2019-03-19 00:50:23 +01:00
|
|
|
|
// Copyright 2019 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.
|
|
|
|
|
|
|
|
|
|
// Almost all CSS output tests should go in sass-spec rather than here. This
|
|
|
|
|
// just covers tests that explicitly validate out that's considered too
|
|
|
|
|
// implementation-specific to verify in sass-spec.
|
|
|
|
|
|
2023-05-19 22:22:44 +02:00
|
|
|
|
@TestOn('vm')
|
|
|
|
|
|
2019-03-19 00:50:23 +01:00
|
|
|
|
import 'package:test/test.dart';
|
|
|
|
|
|
|
|
|
|
import 'package:sass/sass.dart';
|
|
|
|
|
|
|
|
|
|
void main() {
|
2021-08-16 23:52:35 +02:00
|
|
|
|
group("emits private-use area characters as escapes in expanded mode", () {
|
2021-10-05 05:53:31 +02:00
|
|
|
|
testCharacter(String escape) {
|
|
|
|
|
test(escape, () {
|
2021-08-16 23:52:35 +02:00
|
|
|
|
expect(compileString("a {b: $escape}"),
|
|
|
|
|
equalsIgnoringWhitespace("a { b: $escape; }"));
|
|
|
|
|
});
|
2021-10-05 05:53:31 +02:00
|
|
|
|
}
|
2021-08-16 23:52:35 +02:00
|
|
|
|
|
|
|
|
|
group("in the basic multilingual plane", () {
|
|
|
|
|
testCharacter(r"\e000");
|
|
|
|
|
testCharacter(r"\f000");
|
|
|
|
|
testCharacter(r"\f8ff");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
group("in the supplementary planes", () {
|
|
|
|
|
testCharacter(r"\f0000");
|
|
|
|
|
testCharacter(r"\fabcd");
|
|
|
|
|
testCharacter(r"\ffffd");
|
|
|
|
|
testCharacter(r"\100000");
|
|
|
|
|
testCharacter(r"\10abcd");
|
|
|
|
|
testCharacter(r"\10fffd");
|
|
|
|
|
|
2021-10-04 20:16:19 +02:00
|
|
|
|
// Although these aren't technically in private-use area, they're in
|
2021-08-16 23:52:35 +02:00
|
|
|
|
// private-use planes and they have no visual representation to we
|
|
|
|
|
// escape them as well.
|
|
|
|
|
group("that aren't technically in PUAs", () {
|
|
|
|
|
testCharacter(r"\ffffe");
|
|
|
|
|
testCharacter(r"\fffff");
|
|
|
|
|
testCharacter(r"\10fffe");
|
|
|
|
|
testCharacter(r"\10ffff");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
group("adds a space", () {
|
|
|
|
|
test("if followed by a hex character", () {
|
|
|
|
|
expect(compileString(r"a {b: '\e000 a'}"),
|
|
|
|
|
equalsIgnoringWhitespace(r'a { b: "\e000 a"; }'));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("if followed by a space", () {
|
|
|
|
|
expect(compileString(r"a {b: '\e000 '}"),
|
|
|
|
|
equalsIgnoringWhitespace(r'a { b: "\e000 "; }'));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2019-03-19 00:50:23 +01:00
|
|
|
|
// Regression test for sass/dart-sass#623. This needs to be tested here
|
|
|
|
|
// because sass-spec normalizes CR LF newlines.
|
|
|
|
|
group("normalizes newlines in a loud comment", () {
|
|
|
|
|
test("in SCSS", () {
|
|
|
|
|
expect(compileString("/* foo\r\n * bar */"), equals("/* foo\n * bar */"));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("in Sass", () {
|
|
|
|
|
expect(compileString("/*\r\n foo\r\n bar", syntax: Syntax.sass),
|
|
|
|
|
equals("/* foo\n * bar */"));
|
|
|
|
|
});
|
|
|
|
|
});
|
2019-05-21 00:49:40 +02:00
|
|
|
|
|
|
|
|
|
// Regression test for sass/dart-sass#688. This needs to be tested here
|
|
|
|
|
// because it varies between Dart and Node.
|
|
|
|
|
group("removes exponential notation", () {
|
|
|
|
|
group("for integers", () {
|
|
|
|
|
test(">= 1e21", () {
|
|
|
|
|
expect(compileString("a {b: 1e21}"),
|
|
|
|
|
equalsIgnoringWhitespace("a { b: 1${'0' * 21}; }"));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// At time of writing, numbers that are 20 digits or fewer are not printed
|
|
|
|
|
// in exponential notation by either Dart or Node, and we rely on that to
|
|
|
|
|
// determine when to get rid of the exponent. This test ensures that if that
|
|
|
|
|
// ever changes, we know about it.
|
|
|
|
|
test("< 1e21", () {
|
|
|
|
|
expect(compileString("a {b: 1e20}"),
|
|
|
|
|
equalsIgnoringWhitespace("a { b: 1${'0' * 20}; }"));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
group("for floating-point numbers", () {
|
2020-09-04 21:25:42 +02:00
|
|
|
|
test("Infinity", () {
|
|
|
|
|
expect(compileString("a {b: 1e999}"),
|
2023-03-23 23:59:27 +01:00
|
|
|
|
equalsIgnoringWhitespace("a { b: calc(infinity); }"));
|
2020-09-04 21:25:42 +02:00
|
|
|
|
});
|
|
|
|
|
|
2019-05-21 00:49:40 +02:00
|
|
|
|
test(">= 1e21", () {
|
|
|
|
|
expect(compileString("a {b: 1.01e21}"),
|
|
|
|
|
equalsIgnoringWhitespace("a { b: 101${'0' * 19}; }"));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// At time of writing, numbers that are 20 digits or fewer are not printed
|
|
|
|
|
// in exponential notation by either Dart or Node, and we rely on that to
|
|
|
|
|
// determine when to get rid of the exponent. This test ensures that if that
|
|
|
|
|
// ever changes, we know about it.
|
|
|
|
|
test("< 1e21", () {
|
|
|
|
|
expect(compileString("a {b: 1.01e20}"),
|
|
|
|
|
equalsIgnoringWhitespace("a { b: 101${'0' * 18}; }"));
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2022-06-03 03:46:12 +02:00
|
|
|
|
|
|
|
|
|
// Tests for sass/dart-sass#417.
|
|
|
|
|
//
|
|
|
|
|
// Note there's no need for "in Sass" cases as it's not possible to have
|
|
|
|
|
// trailing loud comments in the Sass syntax.
|
|
|
|
|
group("preserve trailing loud comments in SCSS", () {
|
|
|
|
|
test("after open block", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector { /* please don't move me */
|
|
|
|
|
name: value;
|
|
|
|
|
}"""), equals("""
|
|
|
|
|
selector { /* please don't move me */
|
|
|
|
|
name: value;
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("after open block (multi-line selector)", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector1,
|
|
|
|
|
selector2 { /* please don't move me */
|
|
|
|
|
name: value;
|
|
|
|
|
}"""), equals("""
|
|
|
|
|
selector1,
|
|
|
|
|
selector2 { /* please don't move me */
|
|
|
|
|
name: value;
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("after close block", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector {
|
|
|
|
|
name: value;
|
|
|
|
|
} /* please don't move me */"""), equals("""
|
|
|
|
|
selector {
|
|
|
|
|
name: value;
|
|
|
|
|
} /* please don't move me */"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("only content in block", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector {
|
|
|
|
|
/* please don't move me */
|
|
|
|
|
}"""), equals("""
|
|
|
|
|
selector {
|
|
|
|
|
/* please don't move me */
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("only content in block (no newlines)", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector { /* please don't move me */ }"""), equals("""
|
|
|
|
|
selector { /* please don't move me */ }"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("double trailing empty block", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector { /* please don't move me */ /* please don't move me */ }"""),
|
|
|
|
|
equals("""
|
|
|
|
|
selector { /* please don't move me */ /* please don't move me */
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("double trailing style rule", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector {
|
|
|
|
|
margin: 1px; /* please don't move me */ /* please don't move me */
|
|
|
|
|
}"""), equals("""
|
|
|
|
|
selector {
|
|
|
|
|
margin: 1px; /* please don't move me */ /* please don't move me */
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("after property in block", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector {
|
|
|
|
|
name1: value1; /* please don't move me 1 */
|
|
|
|
|
name2: value2; /* please don't move me 2 */
|
|
|
|
|
name3: value3; /* please don't move me 3 */
|
|
|
|
|
}"""), equals("""
|
|
|
|
|
selector {
|
|
|
|
|
name1: value1; /* please don't move me 1 */
|
|
|
|
|
name2: value2; /* please don't move me 2 */
|
|
|
|
|
name3: value3; /* please don't move me 3 */
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("after rule in block", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
selector {
|
|
|
|
|
@rule1; /* please don't move me 1 */
|
|
|
|
|
@rule2; /* please don't move me 2 */
|
|
|
|
|
@rule3; /* please don't move me 3 */
|
|
|
|
|
}"""), equals("""
|
|
|
|
|
selector {
|
|
|
|
|
@rule1; /* please don't move me 1 */
|
|
|
|
|
@rule2; /* please don't move me 2 */
|
|
|
|
|
@rule3; /* please don't move me 3 */
|
|
|
|
|
}"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("after top-level statement", () {
|
|
|
|
|
expect(compileString("@rule; /* please don't move me */"),
|
|
|
|
|
equals("@rule; /* please don't move me */"));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// The trailing comment detection logic looks for left braces to detect
|
|
|
|
|
// whether a comment is on the same line as its parent node. This test
|
|
|
|
|
// checks to make sure it isn't confused by syntax that uses braces for
|
|
|
|
|
// things other than starting child blocks.
|
|
|
|
|
test("selector contains left brace", () {
|
|
|
|
|
expect(compileString("""@rule1;
|
|
|
|
|
@rule2;
|
|
|
|
|
selector[href*="{"]
|
|
|
|
|
{ /* please don't move me */ }
|
|
|
|
|
|
|
|
|
|
@rule3;"""), equals("""@rule1;
|
|
|
|
|
@rule2;
|
|
|
|
|
selector[href*="{"] { /* please don't move me */ }
|
|
|
|
|
|
|
|
|
|
@rule3;"""));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
group("loud comments in mixin", () {
|
|
|
|
|
test("empty with spacing", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
@mixin loudComment {
|
|
|
|
|
/* ... */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selector {
|
|
|
|
|
@include loudComment;
|
|
|
|
|
}"""), """
|
|
|
|
|
selector {
|
|
|
|
|
/* ... */
|
|
|
|
|
}""");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("empty no spacing", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
@mixin loudComment{/* ... */}
|
|
|
|
|
selector {@include loudComment;}"""), """
|
|
|
|
|
selector {
|
|
|
|
|
/* ... */
|
|
|
|
|
}""");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("with style rule", () {
|
|
|
|
|
expect(compileString("""
|
|
|
|
|
@mixin loudComment {
|
|
|
|
|
margin: 1px; /* mixin */
|
|
|
|
|
} /* mixin-out */
|
|
|
|
|
|
|
|
|
|
selector {
|
|
|
|
|
@include loudComment; /* selector */
|
|
|
|
|
}"""), """
|
|
|
|
|
/* mixin-out */
|
|
|
|
|
selector {
|
|
|
|
|
margin: 1px; /* mixin */
|
|
|
|
|
/* selector */
|
|
|
|
|
}""");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
group("loud comments in nested blocks", () {
|
|
|
|
|
test("with styles", () {
|
|
|
|
|
expect(
|
|
|
|
|
compileString("""
|
|
|
|
|
foo { /* foo */
|
|
|
|
|
padding: 1px; /* foo padding */
|
|
|
|
|
bar { /* bar */
|
|
|
|
|
padding: 2px; /* bar padding */
|
|
|
|
|
baz { /* baz */
|
|
|
|
|
padding: 3px; /* baz padding */
|
|
|
|
|
margin: 3px; /* baz margin */
|
|
|
|
|
} /* baz end */
|
|
|
|
|
biz { /* biz */
|
|
|
|
|
padding: 3px; /* biz padding */
|
|
|
|
|
margin: 3px; /* biz margin */
|
|
|
|
|
} /* biz end */
|
|
|
|
|
margin: 2px; /* bar margin */
|
|
|
|
|
} /* bar end */
|
|
|
|
|
margin: 1px; /* foo margin */
|
|
|
|
|
} /* foo end */
|
|
|
|
|
"""),
|
|
|
|
|
"""
|
|
|
|
|
foo { /* foo */
|
|
|
|
|
padding: 1px; /* foo padding */
|
|
|
|
|
/* bar end */
|
|
|
|
|
margin: 1px; /* foo margin */
|
|
|
|
|
}
|
|
|
|
|
foo bar { /* bar */
|
|
|
|
|
padding: 2px; /* bar padding */
|
|
|
|
|
/* baz end */
|
|
|
|
|
/* biz end */
|
|
|
|
|
margin: 2px; /* bar margin */
|
|
|
|
|
}
|
|
|
|
|
foo bar baz { /* baz */
|
|
|
|
|
padding: 3px; /* baz padding */
|
|
|
|
|
margin: 3px; /* baz margin */
|
|
|
|
|
}
|
|
|
|
|
foo bar biz { /* biz */
|
|
|
|
|
padding: 3px; /* biz padding */
|
|
|
|
|
margin: 3px; /* biz margin */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* foo end */""",
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("empty", () {
|
|
|
|
|
expect(
|
|
|
|
|
compileString("""
|
|
|
|
|
foo { /* foo */
|
|
|
|
|
bar { /* bar */
|
|
|
|
|
baz { /* baz */
|
|
|
|
|
} /* baz end */
|
|
|
|
|
biz { /* biz */
|
|
|
|
|
} /* biz end */
|
|
|
|
|
} /* bar end */
|
|
|
|
|
} /* foo end */
|
|
|
|
|
"""),
|
|
|
|
|
"""
|
|
|
|
|
foo { /* foo */
|
|
|
|
|
/* bar end */
|
|
|
|
|
}
|
|
|
|
|
foo bar { /* bar */
|
|
|
|
|
/* baz end */
|
|
|
|
|
/* biz end */
|
|
|
|
|
}
|
|
|
|
|
foo bar baz { /* baz */ }
|
|
|
|
|
foo bar biz { /* biz */ }
|
|
|
|
|
|
|
|
|
|
/* foo end */""",
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
});
|
2019-03-19 00:50:23 +01:00
|
|
|
|
}
|