dart-sass/test/cli/shared.dart
Natalie Weizenbaum 594f936c54 Fix an edge-case bug
If a non-partial stylesheet is next to a partial with the same name,
canonicalizing the source URL would fail. We don't really need to
canonicalize that URL anyway, though, since it's only used for import
loops and such a loop will reload and rerun the entrypoint anyway.
2018-06-08 20:28:38 -04:00

269 lines
8.0 KiB
Dart

// Copyright 2016 Google Inc. Use of this source code is governed by an
// MIT-style license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
import 'dart:async';
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;
import 'package:test_process/test_process.dart';
import 'package:sass/src/util/path.dart';
/// Defines test that are shared between the Dart and Node.js CLI test suites.
void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
/// Runs the executable on [arguments] plus an output file, then verifies that
/// the contents of the output file match [expected].
Future expectCompiles(List<String> arguments, expected) async {
var sass = await runSass(
arguments.toList()..add("out.css")..add("--no-source-map"));
await sass.shouldExit(0);
await d.file("out.css", expected).validate();
}
test("--help prints the usage documentation", () async {
// Checking the entire output is brittle, so just do a sanity check to make
// sure it's not totally busted.
var sass = await runSass(["--help"]);
expect(sass.stdout, emits("Compile Sass to CSS."));
expect(
sass.stdout, emitsThrough(contains("Print this usage information.")));
await sass.shouldExit(64);
});
test("compiles a Sass file to CSS", () async {
await d.file("test.scss", "a {b: 1 + 2}").create();
var sass = await runSass(["test.scss"]);
expect(
sass.stdout,
emitsInOrder([
"a {",
" b: 3;",
"}",
]));
await sass.shouldExit(0);
});
// On Windows, this verifies that we don't consider the colon after a drive
// letter to be an `input:output` separator.
test("compiles an absolute Sass file to CSS", () async {
await d.file("test.scss", "a {b: 1 + 2}").create();
var sass = await runSass([p.absolute(p.join(d.sandbox, "test.scss"))]);
expect(
sass.stdout,
emitsInOrder([
"a {",
" b: 3;",
"}",
]));
await sass.shouldExit(0);
});
test("writes a CSS file to disk", () async {
await d.file("test.scss", "a {b: 1 + 2}").create();
var sass = await runSass(["--no-source-map", "test.scss", "out.css"]);
expect(sass.stdout, emitsDone);
await sass.shouldExit(0);
await d.file("out.css", equalsIgnoringWhitespace("a { b: 3; }")).validate();
});
test("creates directories if necessary", () async {
await d.file("test.scss", "a {b: 1 + 2}").create();
var sass =
await runSass(["--no-source-map", "test.scss", "some/new/dir/out.css"]);
expect(sass.stdout, emitsDone);
await sass.shouldExit(0);
await d
.file("some/new/dir/out.css", equalsIgnoringWhitespace("a { b: 3; }"))
.validate();
});
test("compiles from stdin with the magic path -", () async {
var sass = await runSass(["-"]);
sass.stdin.writeln("a {b: 1 + 2}");
sass.stdin.close();
expect(
sass.stdout,
emitsInOrder([
"a {",
" b: 3;",
"}",
]));
await sass.shouldExit(0);
});
group("can import files", () {
test("relative to the entrypoint", () async {
await d.file("test.scss", "@import 'dir/test'").create();
await d.dir("dir", [d.file("test.scss", "a {b: 1 + 2}")]).create();
await expectCompiles(
["test.scss"], equalsIgnoringWhitespace("a { b: 3; }"));
});
test("from the load path", () async {
await d.file("test.scss", "@import 'test2'").create();
await d.dir("dir", [d.file("test2.scss", "a {b: c}")]).create();
await expectCompiles(["--load-path", "dir", "test.scss"],
equalsIgnoringWhitespace("a { b: c; }"));
});
test("relative in preference to from the load path", () async {
await d.file("test.scss", "@import 'test2'").create();
await d.file("test2.scss", "x {y: z}").create();
await d.dir("dir", [d.file("test2.scss", "a {b: c}")]).create();
await expectCompiles(["--load-path", "dir", "test.scss"],
equalsIgnoringWhitespace("x { y: z; }"));
});
test("in load path order", () async {
await d.file("test.scss", "@import 'test2'").create();
await d.dir("dir1", [d.file("test2.scss", "a {b: c}")]).create();
await d.dir("dir2", [d.file("test2.scss", "x {y: z}")]).create();
await expectCompiles(
["--load-path", "dir2", "--load-path", "dir1", "test.scss"],
equalsIgnoringWhitespace("x { y: z; }"));
});
});
group("with --stdin", () {
test("compiles from stdin", () async {
var sass = await runSass(["--stdin"]);
sass.stdin.writeln("a {b: 1 + 2}");
sass.stdin.close();
expect(
sass.stdout,
emitsInOrder([
"a {",
" b: 3;",
"}",
]));
await sass.shouldExit(0);
});
test("writes a CSS file to disk", () async {
var sass = await runSass(["--no-source-map", "--stdin", "out.css"]);
sass.stdin.writeln("a {b: 1 + 2}");
sass.stdin.close();
expect(sass.stdout, emitsDone);
await sass.shouldExit(0);
await d
.file("out.css", equalsIgnoringWhitespace("a { b: 3; }"))
.validate();
});
test("uses the indented syntax with --indented", () async {
var sass = await runSass(["--no-source-map", "--stdin", "--indented"]);
sass.stdin.writeln("a\n b: 1 + 2");
sass.stdin.close();
expect(
sass.stdout,
emitsInOrder([
"a {",
" b: 3;",
"}",
]));
await sass.shouldExit(0);
});
});
test("gracefully reports errors from stdin", () async {
var sass = await runSass(["-"]);
sass.stdin.writeln("a {b: 1 + }");
sass.stdin.close();
expect(
sass.stderr,
emitsInOrder([
"Error: Expected expression.",
"a {b: 1 + }",
" ^",
" - 1:11 root stylesheet",
]));
await sass.shouldExit(65);
});
test("gracefully handles a non-partial next to a partial", () async {
await d.file("test.scss", "a {b: c}").create();
await d.file("_test.scss", "x {y: z}").create();
var sass = await runSass(["test.scss"]);
expect(
sass.stdout,
emitsInOrder([
"a {",
" b: c;",
"}",
]));
await sass.shouldExit(0);
});
test("emits warnings on standard error", () async {
await d.file("test.scss", "@warn 'aw beans'").create();
var sass = await runSass(["test.scss"]);
expect(sass.stdout, emitsDone);
expect(
sass.stderr,
emitsInOrder([
"WARNING: aw beans",
" test.scss 1:1 root stylesheet",
]));
await sass.shouldExit(0);
});
test("emits debug messages on standard error", () async {
await d.file("test.scss", "@debug 'what the heck'").create();
var sass = await runSass(["test.scss"]);
expect(sass.stdout, emitsDone);
expect(sass.stderr, emits("test.scss:1 DEBUG: what the heck"));
await sass.shouldExit(0);
});
group("with --quiet", () {
test("doesn't emit @warn", () async {
await d.file("test.scss", "@warn heck").create();
var sass = await runSass(["--quiet", "test.scss"]);
expect(sass.stderr, emitsDone);
await sass.shouldExit(0);
});
test("doesn't emit @debug", () async {
await d.file("test.scss", "@debug heck").create();
var sass = await runSass(["--quiet", "test.scss"]);
expect(sass.stderr, emitsDone);
await sass.shouldExit(0);
});
test("doesn't emit parser warnings", () async {
await d.file("test.scss", "a {b: c && d}").create();
var sass = await runSass(["--quiet", "test.scss"]);
expect(sass.stderr, emitsDone);
await sass.shouldExit(0);
});
test("doesn't emit runner warnings", () async {
await d.file("test.scss", "#{blue} {x: y}").create();
var sass = await runSass(["--quiet", "test.scss"]);
expect(sass.stderr, emitsDone);
await sass.shouldExit(0);
});
});
}