mirror of
https://github.com/danog/dart-sass.git
synced 2024-12-03 10:08:01 +01:00
2430ac6d20
Instead, we create a single zone-scoped object that's visible for the entire lifespan of the visitor, and which exposes evaluation internals which can be updated as direct field modifications.
252 lines
8.0 KiB
Dart
252 lines
8.0 KiB
Dart
// Copyright 2018 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('vm')
|
|
|
|
import 'package:test/test.dart';
|
|
import 'package:source_span/source_span.dart';
|
|
import 'package:stack_trace/stack_trace.dart';
|
|
|
|
import 'package:sass/sass.dart';
|
|
|
|
import 'test_importer.dart';
|
|
|
|
void main() {
|
|
group("with @warn", () {
|
|
test("passes the message and stack trace to the logger", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString('''
|
|
@mixin foo {@warn heck}
|
|
@include foo;
|
|
''', logger: _TestLogger.withWarn((message,
|
|
{span, trace, deprecation = false}) {
|
|
expect(message, equals("heck"));
|
|
expect(span, isNull);
|
|
expect(trace!.frames.first.member, equals('foo()'));
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("stringifies the argument", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString('@warn #abc', logger:
|
|
_TestLogger.withWarn((message, {span, trace, deprecation = false}) {
|
|
expect(message, equals("#abc"));
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("doesn't inspect the argument", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString('@warn null', logger:
|
|
_TestLogger.withWarn((message, {span, trace, deprecation = false}) {
|
|
expect(message, isEmpty);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
});
|
|
|
|
group("with @debug", () {
|
|
test("passes the message and span to the logger", () {
|
|
compileString('@debug heck',
|
|
logger: _TestLogger.withDebug(expectAsync2((message, span) {
|
|
expect(message, equals("heck"));
|
|
expect(span.start.line, equals(0));
|
|
expect(span.start.column, equals(0));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(11));
|
|
})));
|
|
});
|
|
|
|
test("stringifies the argument", () {
|
|
compileString('@debug #abc',
|
|
logger: _TestLogger.withDebug(expectAsync2((message, span) {
|
|
expect(message, equals("#abc"));
|
|
})));
|
|
});
|
|
|
|
test("inspects the argument", () {
|
|
compileString('@debug null',
|
|
logger: _TestLogger.withDebug(expectAsync2((message, span) {
|
|
expect(message, equals("null"));
|
|
})));
|
|
});
|
|
});
|
|
|
|
test("with a parser warning passes the message and span", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString('a {b: c && d}', logger:
|
|
_TestLogger.withWarn((message, {span, trace, deprecation = false}) {
|
|
expect(message, contains('"&&" means two copies'));
|
|
|
|
expect(span!.start.line, equals(0));
|
|
expect(span.start.column, equals(8));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(10));
|
|
|
|
expect(trace, isNull);
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("with a runner warning passes the message, span, and trace", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString('''
|
|
@mixin foo {#{blue} {x: y}}
|
|
@include foo;
|
|
''', logger:
|
|
_TestLogger.withWarn((message, {span, trace, deprecation = false}) {
|
|
expect(message, contains("color value blue"));
|
|
|
|
expect(span!.start.line, equals(0));
|
|
expect(span.start.column, equals(22));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(26));
|
|
|
|
expect(trace!.frames.first.member, equals('foo()'));
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
group("with warn()", () {
|
|
group("from a function", () {
|
|
test("synchronously", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString("""
|
|
@function bar() {@return foo()}
|
|
a {b: bar()}
|
|
""", functions: [
|
|
Callable("foo", "", expectAsync1((_) {
|
|
warn("heck");
|
|
return sassNull;
|
|
}))
|
|
], logger: _TestLogger.withWarn((message,
|
|
{span, trace, deprecation = false}) {
|
|
expect(message, equals("heck"));
|
|
|
|
expect(span!.start.line, equals(0));
|
|
expect(span.start.column, equals(33));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(38));
|
|
|
|
expect(trace!.frames.first.member, equals('bar()'));
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("asynchronously", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileStringAsync("""
|
|
@function bar() {@return foo()}
|
|
a {b: bar()}
|
|
""", functions: [
|
|
AsyncCallable("foo", "", expectAsync1((_) async {
|
|
warn("heck");
|
|
return sassNull;
|
|
}))
|
|
], logger: _TestLogger.withWarn((message,
|
|
{span, trace, deprecation = false}) {
|
|
expect(message, equals("heck"));
|
|
|
|
expect(span!.start.line, equals(0));
|
|
expect(span.start.column, equals(33));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(38));
|
|
|
|
expect(trace!.frames.first.member, equals('bar()'));
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("asynchronously after a gap", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileStringAsync("""
|
|
@function bar() {@return foo()}
|
|
a {b: bar()}
|
|
""", functions: [
|
|
AsyncCallable("foo", "", expectAsync1((_) async {
|
|
await Future<void>.delayed(Duration.zero);
|
|
warn("heck");
|
|
return sassNull;
|
|
}))
|
|
], logger: _TestLogger.withWarn((message,
|
|
{span, trace, deprecation = false}) {
|
|
expect(message, equals("heck"));
|
|
|
|
expect(span!.start.line, equals(0));
|
|
expect(span.start.column, equals(33));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(38));
|
|
|
|
expect(trace!.frames.first.member, equals('bar()'));
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
});
|
|
|
|
test("from an importer", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString("@import 'foo';", importers: [
|
|
TestImporter((url) => Uri.parse("u:$url"), (url) {
|
|
warn("heck");
|
|
return ImporterResult("", indented: false);
|
|
})
|
|
], logger:
|
|
_TestLogger.withWarn((message, {span, trace, deprecation = false}) {
|
|
expect(message, equals("heck"));
|
|
|
|
expect(span!.start.line, equals(0));
|
|
expect(span.start.column, equals(8));
|
|
expect(span.end.line, equals(0));
|
|
expect(span.end.column, equals(13));
|
|
|
|
expect(trace!.frames.first.member, equals('@import'));
|
|
expect(deprecation, isFalse);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("with deprecation", () {
|
|
var mustBeCalled = expectAsync0(() {});
|
|
compileString("a {b: foo()}", functions: [
|
|
Callable("foo", "", expectAsync1((_) {
|
|
warn("heck", deprecation: true);
|
|
return sassNull;
|
|
}))
|
|
], logger:
|
|
_TestLogger.withWarn((message, {span, trace, deprecation = false}) {
|
|
expect(message, equals("heck"));
|
|
expect(deprecation, isTrue);
|
|
mustBeCalled();
|
|
}));
|
|
});
|
|
|
|
test("throws an error outside a callback", () {
|
|
expect(() => warn("heck"), throwsStateError);
|
|
});
|
|
});
|
|
}
|
|
|
|
/// A [Logger] whose [warn] and [debug] methods are provided by callbacks.
|
|
class _TestLogger implements Logger {
|
|
final void Function(String, {FileSpan? span, Trace? trace, bool deprecation})
|
|
_warn;
|
|
final void Function(String, SourceSpan) _debug;
|
|
|
|
_TestLogger.withWarn(this._warn) : _debug = const Logger.stderr().debug;
|
|
|
|
_TestLogger.withDebug(this._debug) : _warn = const Logger.stderr().warn;
|
|
|
|
void warn(String message,
|
|
{FileSpan? span, Trace? trace, bool deprecation = false}) =>
|
|
_warn(message, span: span, trace: trace, deprecation: deprecation);
|
|
void debug(String message, SourceSpan span) => _debug(message, span);
|
|
}
|