2017-07-07 02:36:15 +02:00
|
|
|
// Copyright 2017 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.
|
|
|
|
|
|
|
|
@TestOn('node')
|
2018-11-16 00:16:24 +01:00
|
|
|
@Tags(['node'])
|
2017-07-07 02:36:15 +02:00
|
|
|
|
2018-04-26 02:47:29 +02:00
|
|
|
import 'dart:convert';
|
2018-07-24 01:20:06 +02:00
|
|
|
import 'dart:js';
|
2018-04-26 02:47:29 +02:00
|
|
|
|
2018-06-14 01:57:28 +02:00
|
|
|
import 'package:path/path.dart' as p;
|
2017-07-07 02:36:15 +02:00
|
|
|
import 'package:test/test.dart';
|
|
|
|
|
2018-03-23 22:58:57 +01:00
|
|
|
import 'package:sass/src/node/utils.dart';
|
2017-07-07 04:29:39 +02:00
|
|
|
|
2017-07-07 02:36:15 +02:00
|
|
|
import 'ensure_npm_package.dart';
|
|
|
|
import 'hybrid.dart';
|
2017-10-21 01:56:54 +02:00
|
|
|
import 'node_api/api.dart';
|
2018-04-26 02:47:29 +02:00
|
|
|
import 'node_api/intercept_stdout.dart';
|
2017-10-21 01:56:54 +02:00
|
|
|
import 'node_api/utils.dart';
|
2017-07-07 02:36:15 +02:00
|
|
|
|
|
|
|
String sassPath;
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
setUpAll(ensureNpmPackage);
|
2017-10-21 01:56:54 +02:00
|
|
|
useSandbox();
|
2017-07-07 02:36:15 +02:00
|
|
|
|
|
|
|
setUp(() async {
|
|
|
|
sassPath = p.join(sandbox, 'test.scss');
|
|
|
|
await writeTextFile(sassPath, 'a {b: c}');
|
|
|
|
});
|
|
|
|
|
|
|
|
group("renderSync()", () {
|
|
|
|
test("renders a file", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath)),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 02:36:15 +02:00
|
|
|
});
|
|
|
|
|
2018-04-21 02:55:13 +02:00
|
|
|
test("renders a file from a relative path", () {
|
|
|
|
runTestInSandbox();
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: 'test.scss')),
|
2018-04-21 02:55:13 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
|
|
|
});
|
|
|
|
|
2017-07-07 10:40:15 +02:00
|
|
|
test("renders a file with the indented syntax", () async {
|
|
|
|
var indentedPath = p.join(sandbox, 'test.sass');
|
|
|
|
await writeTextFile(indentedPath, 'a\n b: c');
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: indentedPath)),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 10:40:15 +02:00
|
|
|
});
|
|
|
|
|
2017-07-07 09:57:10 +02:00
|
|
|
test("supports relative imports for a file", () async {
|
|
|
|
var importerPath = p.join(sandbox, 'importer.scss');
|
|
|
|
await writeTextFile(importerPath, '@import "test"');
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: importerPath)),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 09:57:10 +02:00
|
|
|
});
|
|
|
|
|
2018-04-21 02:55:13 +02:00
|
|
|
// Regression test for #284
|
|
|
|
test("supports relative imports for a file from a relative path", () async {
|
|
|
|
await createDirectory(p.join(sandbox, 'subdir'));
|
|
|
|
|
|
|
|
var importerPath = p.join(sandbox, 'subdir/importer.scss');
|
|
|
|
await writeTextFile(importerPath, '@import "../test"');
|
|
|
|
|
|
|
|
runTestInSandbox();
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: 'subdir/importer.scss')),
|
2018-04-21 02:55:13 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
|
|
|
});
|
|
|
|
|
2017-10-21 02:00:53 +02:00
|
|
|
test("supports absolute path imports", () async {
|
|
|
|
expect(
|
2018-11-16 00:16:24 +01:00
|
|
|
renderSync(RenderOptions(
|
2017-10-21 02:00:53 +02:00
|
|
|
// Node Sass parses imports as paths, not as URLs, so the absolute
|
|
|
|
// path should work here.
|
|
|
|
data: '@import "${sassPath.replaceAll('\\', '\\\\')}"')),
|
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
|
|
|
});
|
|
|
|
|
2020-01-04 00:41:12 +01:00
|
|
|
test("supports import-only files", () async {
|
|
|
|
await writeTextFile(p.join(sandbox, 'foo.scss'), 'a {b: regular}');
|
|
|
|
await writeTextFile(
|
|
|
|
p.join(sandbox, 'foo.import.scss'), 'a {b: import-only}');
|
|
|
|
|
|
|
|
runTestInSandbox();
|
|
|
|
expect(renderSync(RenderOptions(data: "@import 'foo'")),
|
|
|
|
equalsIgnoringWhitespace('a { b: import-only; }'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("supports mixed `@use` and `@import`", () async {
|
|
|
|
await writeTextFile(p.join(sandbox, 'foo.scss'), 'a {b: regular}');
|
|
|
|
await writeTextFile(
|
|
|
|
p.join(sandbox, 'foo.import.scss'), 'a {b: import-only}');
|
|
|
|
|
|
|
|
runTestInSandbox();
|
|
|
|
expect(renderSync(RenderOptions(data: "@use 'foo'; @import 'foo';")),
|
|
|
|
equalsIgnoringWhitespace('a { b: regular; } a { b: import-only; }'));
|
|
|
|
});
|
|
|
|
|
2017-07-07 09:57:10 +02:00
|
|
|
test("renders a string", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(data: "a {b: c}")),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 09:57:10 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("one of data and file must be set", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var error = renderSyncError(RenderOptions());
|
2017-07-07 09:57:10 +02:00
|
|
|
expect(error.toString(),
|
|
|
|
contains('Either options.data or options.file must be set.'));
|
|
|
|
});
|
|
|
|
|
2017-07-07 23:50:12 +02:00
|
|
|
test("supports load paths", () {
|
|
|
|
expect(
|
2018-11-16 00:16:24 +01:00
|
|
|
renderSync(
|
|
|
|
RenderOptions(data: "@import 'test'", includePaths: [sandbox])),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 23:50:12 +02:00
|
|
|
});
|
|
|
|
|
2018-11-06 00:24:14 +01:00
|
|
|
test("supports SASS_PATH", () async {
|
|
|
|
await createDirectory(p.join(sandbox, 'dir1'));
|
|
|
|
await createDirectory(p.join(sandbox, 'dir2'));
|
|
|
|
await writeTextFile(p.join(sandbox, 'dir1', 'test1.scss'), 'a {b: c}');
|
|
|
|
await writeTextFile(p.join(sandbox, 'dir2', 'test2.scss'), 'x {y: z}');
|
|
|
|
|
2019-05-21 00:34:57 +02:00
|
|
|
withSassPath([p.join(sandbox, 'dir1'), p.join(sandbox, 'dir2')], () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(data: """
|
2018-11-06 00:24:14 +01:00
|
|
|
@import 'test1';
|
|
|
|
@import 'test2';
|
|
|
|
""")), equalsIgnoringWhitespace('a { b: c; } x { y: z; }'));
|
2019-05-21 00:34:57 +02:00
|
|
|
});
|
2018-11-06 00:24:14 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
test("load path takes precedence over SASS_PATH", () async {
|
|
|
|
await createDirectory(p.join(sandbox, 'dir1'));
|
|
|
|
await createDirectory(p.join(sandbox, 'dir2'));
|
|
|
|
await writeTextFile(p.join(sandbox, 'dir1', 'test.scss'), 'a {b: c}');
|
|
|
|
await writeTextFile(p.join(sandbox, 'dir2', 'test.scss'), 'x {y: z}');
|
|
|
|
|
|
|
|
setEnvironmentVariable("SASS_PATH", p.join(sandbox, 'dir1'));
|
|
|
|
|
|
|
|
try {
|
|
|
|
expect(
|
2018-11-16 00:16:24 +01:00
|
|
|
renderSync(RenderOptions(
|
2018-11-06 00:24:14 +01:00
|
|
|
data: "@import 'test'",
|
|
|
|
includePaths: [p.join(sandbox, 'dir2')])),
|
|
|
|
equalsIgnoringWhitespace('x { y: z; }'));
|
|
|
|
} finally {
|
|
|
|
setEnvironmentVariable("SASS_PATH", null);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-05-03 02:04:36 +02:00
|
|
|
// Regression test for #314
|
|
|
|
test(
|
|
|
|
"a file imported through a relative load path supports relative "
|
|
|
|
"imports", () async {
|
|
|
|
var subDir = p.join(sandbox, 'sub');
|
|
|
|
await createDirectory(subDir);
|
|
|
|
await writeTextFile(p.join(subDir, '_test.scss'), '@import "other"');
|
|
|
|
|
|
|
|
await writeTextFile(p.join(subDir, '_other.scss'), 'x {y: z}');
|
|
|
|
|
|
|
|
expect(
|
2018-11-16 00:16:24 +01:00
|
|
|
renderSync(RenderOptions(
|
2018-05-03 02:04:36 +02:00
|
|
|
data: "@import 'sub/test'", includePaths: [p.relative(sandbox)])),
|
|
|
|
equalsIgnoringWhitespace('x { y: z; }'));
|
|
|
|
});
|
|
|
|
|
2017-07-07 10:40:15 +02:00
|
|
|
test("can render the indented syntax", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(data: "a\n b: c", indentedSyntax: true)),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 10:40:15 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("the indented syntax flag takes precedence over the file extension",
|
|
|
|
() async {
|
|
|
|
var scssPath = p.join(sandbox, 'test.scss');
|
|
|
|
await writeTextFile(scssPath, 'a\n b: c');
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: scssPath, indentedSyntax: true)),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 09:57:10 +02:00
|
|
|
});
|
|
|
|
|
2017-07-08 01:39:58 +02:00
|
|
|
test("supports the expanded output style", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, outputStyle: 'expanded')),
|
2018-04-21 02:35:34 +02:00
|
|
|
equals('a {\n b: c;\n}'));
|
2017-07-08 01:39:58 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("doesn't support other output styles", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var error =
|
|
|
|
renderSyncError(RenderOptions(file: sassPath, outputStyle: 'nested'));
|
2017-07-08 01:39:58 +02:00
|
|
|
expect(error.toString(), contains('Unsupported output style "nested".'));
|
|
|
|
});
|
|
|
|
|
2017-07-07 02:36:15 +02:00
|
|
|
test("allows tab indentation", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, indentType: 'tab')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('''
|
|
|
|
a {
|
|
|
|
\t\tb: c;
|
|
|
|
}'''));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("allows unknown indentation names", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, indentType: 'asdf')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('''
|
|
|
|
a {
|
|
|
|
b: c;
|
|
|
|
}'''));
|
|
|
|
});
|
|
|
|
|
|
|
|
group("linefeed allows", () {
|
|
|
|
test("cr", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, linefeed: 'cr')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('a {\r b: c;\r}'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("crlf", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, linefeed: 'crlf')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('a {\r\n b: c;\r\n}'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("lfcr", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, linefeed: 'lfcr')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('a {\n\r b: c;\n\r}'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("unknown names", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, linefeed: 'asdf')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('a {\n b: c;\n}'));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
group("indentWidth allows", () {
|
|
|
|
test("a number", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, indentWidth: 10)),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('''
|
|
|
|
a {
|
|
|
|
b: c;
|
|
|
|
}'''));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("a string", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(file: sassPath, indentWidth: '1')),
|
2017-07-07 02:36:15 +02:00
|
|
|
equals('''
|
|
|
|
a {
|
|
|
|
b: c;
|
|
|
|
}'''));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2018-04-26 02:47:29 +02:00
|
|
|
test("emits warnings on stderr", () {
|
|
|
|
expect(
|
|
|
|
const LineSplitter().bind(interceptStderr()),
|
|
|
|
emitsInOrder([
|
|
|
|
"WARNING: aw beans",
|
|
|
|
" stdin 1:1 root stylesheet",
|
|
|
|
]));
|
|
|
|
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(data: "@warn 'aw beans'")), isEmpty);
|
2018-04-26 02:47:29 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("emits debug messages on stderr", () {
|
|
|
|
expect(const LineSplitter().bind(interceptStderr()),
|
|
|
|
emits("stdin:1 DEBUG: what the heck"));
|
|
|
|
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(
|
|
|
|
renderSync(RenderOptions(data: "@debug 'what the heck'")), isEmpty);
|
2018-04-26 02:47:29 +02:00
|
|
|
});
|
|
|
|
|
2018-03-23 22:22:49 +01:00
|
|
|
group("with both data and file", () {
|
|
|
|
test("uses the data parameter as the source", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(renderSync(RenderOptions(data: "x {y: z}", file: sassPath)),
|
2018-03-23 22:22:49 +01:00
|
|
|
equalsIgnoringWhitespace('x { y: z; }'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("doesn't require the file path to exist", () {
|
|
|
|
expect(
|
2018-11-16 00:16:24 +01:00
|
|
|
renderSync(RenderOptions(
|
2018-03-23 22:22:49 +01:00
|
|
|
data: "x {y: z}", file: p.join(sandbox, 'non-existent.scss'))),
|
|
|
|
equalsIgnoringWhitespace('x { y: z; }'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("imports relative to the file path", () async {
|
|
|
|
await writeTextFile(p.join(sandbox, 'importee.scss'), 'x {y: z}');
|
|
|
|
expect(
|
|
|
|
renderSync(
|
2018-11-16 00:16:24 +01:00
|
|
|
RenderOptions(data: "@import 'importee'", file: sassPath)),
|
2018-03-23 22:22:49 +01:00
|
|
|
equalsIgnoringWhitespace('x { y: z; }'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("reports errors from the file path", () {
|
|
|
|
var error =
|
2018-11-16 00:16:24 +01:00
|
|
|
renderSyncError(RenderOptions(data: "x {y: }", file: sassPath));
|
2018-03-23 22:22:49 +01:00
|
|
|
expect(
|
|
|
|
error.toString(),
|
|
|
|
equals("Error: Expected expression.\n"
|
2019-01-29 02:42:32 +01:00
|
|
|
" ╷\n"
|
|
|
|
"1 │ x {y: }\n"
|
|
|
|
" │ ^\n"
|
|
|
|
" ╵\n"
|
2018-03-23 22:22:49 +01:00
|
|
|
" $sassPath 1:7 root stylesheet"));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-07-09 23:52:14 +02:00
|
|
|
group("the result object", () {
|
|
|
|
test("includes the filename", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(file: sassPath));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.entry, equals(sassPath));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("includes data without a filename", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(data: 'a {b: c}'));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.entry, equals('data'));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("includes timing information", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(file: sassPath));
|
2018-06-15 22:58:13 +02:00
|
|
|
expect(result.stats.start, const TypeMatcher<int>());
|
|
|
|
expect(result.stats.end, const TypeMatcher<int>());
|
2017-12-08 02:32:40 +01:00
|
|
|
expect(result.stats.start, lessThanOrEqualTo(result.stats.end));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.duration,
|
|
|
|
equals(result.stats.end - result.stats.start));
|
|
|
|
});
|
|
|
|
|
|
|
|
group("has includedFiles which", () {
|
|
|
|
test("contains the root path if available", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(file: sassPath));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.includedFiles, equals([sassPath]));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("doesn't contain the root path if it's not available", () {
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(data: 'a {b: c}'));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.includedFiles, isEmpty);
|
|
|
|
});
|
|
|
|
|
|
|
|
test("contains imported paths", () async {
|
|
|
|
var importerPath = p.join(sandbox, 'importer.scss');
|
|
|
|
await writeTextFile(importerPath, '@import "test"');
|
|
|
|
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(file: importerPath));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.includedFiles,
|
|
|
|
unorderedEquals([importerPath, sassPath]));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("only contains each path once", () async {
|
|
|
|
var importerPath = p.join(sandbox, 'importer.scss');
|
|
|
|
await writeTextFile(importerPath, '@import "test"; @import "test";');
|
|
|
|
|
2018-11-16 00:16:24 +01:00
|
|
|
var result = sass.renderSync(RenderOptions(file: importerPath));
|
2017-07-09 23:52:14 +02:00
|
|
|
expect(result.stats.includedFiles,
|
|
|
|
unorderedEquals([importerPath, sassPath]));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2017-07-10 02:59:53 +02:00
|
|
|
group("the error object", () {
|
|
|
|
RenderError error;
|
|
|
|
group("for a parse error in a file", () {
|
|
|
|
setUp(() async {
|
|
|
|
await writeTextFile(sassPath, "a {b: }");
|
2018-11-16 00:16:24 +01:00
|
|
|
error = renderSyncError(RenderOptions(file: sassPath));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
2018-03-23 22:58:57 +01:00
|
|
|
test("is a JS Error", () async {
|
|
|
|
expect(isJSError(error), isTrue);
|
|
|
|
});
|
|
|
|
|
2017-07-10 02:59:53 +02:00
|
|
|
test("has a useful toString() and message", () async {
|
|
|
|
expect(
|
|
|
|
error,
|
|
|
|
toStringAndMessageEqual("Expected expression.\n"
|
2019-01-29 02:42:32 +01:00
|
|
|
" ╷\n"
|
|
|
|
"1 │ a {b: }\n"
|
|
|
|
" │ ^\n"
|
|
|
|
" ╵\n"
|
2017-07-10 02:59:53 +02:00
|
|
|
" $sassPath 1:7 root stylesheet"));
|
|
|
|
});
|
|
|
|
|
|
|
|
test("sets the line, column, and filename", () {
|
|
|
|
expect(error.line, equals(1));
|
|
|
|
expect(error.column, equals(7));
|
|
|
|
expect(error.file, equals(sassPath));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
group("for a parse error in a string", () {
|
|
|
|
setUp(() {
|
2018-11-16 00:16:24 +01:00
|
|
|
error = renderSyncError(RenderOptions(data: "a {b: }"));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
2018-03-23 22:58:57 +01:00
|
|
|
test("is a JS Error", () async {
|
|
|
|
expect(isJSError(error), isTrue);
|
|
|
|
});
|
|
|
|
|
2017-07-10 02:59:53 +02:00
|
|
|
test("has a useful toString() and message", () {
|
|
|
|
expect(
|
|
|
|
error,
|
|
|
|
toStringAndMessageEqual("Expected expression.\n"
|
2019-01-29 02:42:32 +01:00
|
|
|
" ╷\n"
|
|
|
|
"1 │ a {b: }\n"
|
|
|
|
" │ ^\n"
|
|
|
|
" ╵\n"
|
2017-11-03 02:13:05 +01:00
|
|
|
" stdin 1:7 root stylesheet"));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("sets the line, column, and filename", () {
|
|
|
|
expect(error.line, equals(1));
|
|
|
|
expect(error.column, equals(7));
|
|
|
|
expect(error.file, equals("stdin"));
|
|
|
|
});
|
|
|
|
});
|
2017-07-07 02:36:15 +02:00
|
|
|
|
2017-07-10 02:59:53 +02:00
|
|
|
group("for a runtime error in a file", () {
|
|
|
|
setUp(() async {
|
|
|
|
await writeTextFile(sassPath, "a {b: 1 % a}");
|
2018-11-16 00:16:24 +01:00
|
|
|
error = renderSyncError(RenderOptions(file: sassPath));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("has a useful toString() and message", () {
|
|
|
|
expect(
|
|
|
|
error,
|
|
|
|
toStringAndMessageEqual('Undefined operation "1 % a".\n'
|
2019-01-29 02:42:32 +01:00
|
|
|
' ╷\n'
|
|
|
|
'1 │ a {b: 1 % a}\n'
|
|
|
|
' │ ^^^^^\n'
|
|
|
|
' ╵\n'
|
2018-06-14 01:57:28 +02:00
|
|
|
' $sassPath 1:7 root stylesheet'));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("sets the line, column, and filename", () {
|
|
|
|
expect(error.line, equals(1));
|
|
|
|
expect(error.column, equals(7));
|
|
|
|
expect(error.file, equals(sassPath));
|
|
|
|
});
|
2017-07-07 02:36:15 +02:00
|
|
|
});
|
|
|
|
|
2017-07-10 02:59:53 +02:00
|
|
|
group("for a runtime error in a string", () {
|
|
|
|
setUp(() {
|
2018-11-16 00:16:24 +01:00
|
|
|
error = renderSyncError(RenderOptions(data: "a {b: 1 % a}"));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("has a useful toString() and message", () {
|
|
|
|
expect(
|
|
|
|
error,
|
|
|
|
toStringAndMessageEqual('Undefined operation "1 % a".\n'
|
2019-01-29 02:42:32 +01:00
|
|
|
' ╷\n'
|
|
|
|
'1 │ a {b: 1 % a}\n'
|
|
|
|
' │ ^^^^^\n'
|
|
|
|
' ╵\n'
|
2017-11-03 02:13:05 +01:00
|
|
|
' stdin 1:7 root stylesheet'));
|
2017-07-10 02:59:53 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("sets the line, column, and filename", () {
|
|
|
|
expect(error.line, equals(1));
|
|
|
|
expect(error.column, equals(7));
|
|
|
|
expect(error.file, equals("stdin"));
|
|
|
|
});
|
2017-07-07 02:36:15 +02:00
|
|
|
});
|
|
|
|
});
|
2018-07-24 01:20:06 +02:00
|
|
|
|
|
|
|
group("when called with a raw JS collection", () {
|
|
|
|
test("for includePaths", () {
|
|
|
|
expect(
|
|
|
|
renderSyncJS({
|
2018-07-24 01:57:21 +02:00
|
|
|
"data": "@import 'test'",
|
|
|
|
"includePaths": [sandbox]
|
2018-07-24 01:20:06 +02:00
|
|
|
}),
|
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
|
|
|
});
|
|
|
|
|
|
|
|
// Regression test for #412
|
|
|
|
test("for includePaths with an importer", () {
|
|
|
|
expect(
|
|
|
|
renderSyncJS({
|
2018-07-24 01:57:21 +02:00
|
|
|
"data": "@import 'test'",
|
|
|
|
"includePaths": [sandbox],
|
2019-11-06 01:28:26 +01:00
|
|
|
"importer": allowInterop((void _, void __) => null)
|
2018-07-24 01:20:06 +02:00
|
|
|
}),
|
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
|
|
|
});
|
|
|
|
});
|
2017-07-07 02:36:15 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
group("render()", () {
|
|
|
|
test("renders a file", () async {
|
2018-11-16 00:16:24 +01:00
|
|
|
expect(await render(RenderOptions(file: sassPath)),
|
2018-04-21 02:35:34 +02:00
|
|
|
equalsIgnoringWhitespace('a { b: c; }'));
|
2017-07-07 02:36:15 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
test("throws an error that has a useful toString", () async {
|
|
|
|
await writeTextFile(sassPath, 'a {b: }');
|
|
|
|
|
2018-11-16 00:16:24 +01:00
|
|
|
var error = await renderError(RenderOptions(file: sassPath));
|
2017-07-10 02:59:53 +02:00
|
|
|
expect(
|
|
|
|
error.toString(),
|
|
|
|
equals("Error: Expected expression.\n"
|
2019-01-29 02:42:32 +01:00
|
|
|
" ╷\n"
|
|
|
|
"1 │ a {b: }\n"
|
|
|
|
" │ ^\n"
|
|
|
|
" ╵\n"
|
2017-07-10 02:59:53 +02:00
|
|
|
" $sassPath 1:7 root stylesheet"));
|
2017-07-07 02:36:15 +02:00
|
|
|
});
|
2018-09-19 21:28:47 +02:00
|
|
|
});
|
2017-07-07 02:36:15 +02:00
|
|
|
}
|