Skip to content

Commit 9b167e9

Browse files
committed
test: add test cases to prevent regression, some exposing exisiting issues
1 parent 28a36da commit 9b167e9

File tree

7 files changed

+144
-31
lines changed

7 files changed

+144
-31
lines changed

src/parser-styles.js

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import postcss from "postcss";
1+
import postcss, { CssSyntaxError } from "postcss";
22

33
/**
44
* Represents a parser that adjusts the positions of nodes within the source code.
@@ -18,16 +18,25 @@ export class StyleParser {
1818
/**
1919
* Modifies a position object to be relative to the input file instead of the parsed CSS.
2020
*
21-
* @param {postcss.Position} position - The position object that requires adjustment.
21+
* @param {postcss.Position | postcss.FilePosition | postcss.CssSyntaxError} object - The position object that requires adjustment.
2222
*/
23-
_adjustPosition(position) {
23+
_adjustPosition(object) {
2424
const { col, line } = this.input.fromOffset(this.styleLiteral.getStart());
25-
26-
if (position.line === 1) {
27-
position.column += col;
25+
if (object) {
26+
if (object.line === 1) {
27+
object.column += col;
28+
}
29+
object.line += line - 1;
30+
if (typeof object.offset === "number") {
31+
object.offset += this.styleLiteral.getStart() + 1;
32+
}
33+
if (typeof object.endLine === "number") {
34+
if (object.endLine === 1) {
35+
object.endColumn += col;
36+
}
37+
object.endLine += line;
38+
}
2839
}
29-
position.line += line - 1;
30-
position.offset += this.styleLiteral.getStart() + 1;
3140
}
3241

3342
/**
@@ -38,6 +47,8 @@ export class StyleParser {
3847
_adjustNode(node) {
3948
this._adjustPosition(node.source.start);
4049
this._adjustPosition(node.source.end);
50+
51+
// End position on source is inclusive but the function is generic for both position and ranges
4152
node.source.end.column -= 1;
4253
node.source.end.offset -= 1;
4354
}
@@ -57,8 +68,8 @@ export class StyleParser {
5768
/**
5869
* Modifies error positions to reflect the context of the input file accurately.
5970
*
60-
* @param {any} error - The error object that needs positional adjustment.
61-
* @returns {any} The error object with updated position information.
71+
* @param {CssSyntaxError} error - The error object that needs positional adjustment.
72+
* @returns {CssSyntaxError} The error object with updated position information.
6273
*/
6374
_adjustError(error) {
6475
if (error && error.name === "CssSyntaxError") {
@@ -68,6 +79,8 @@ export class StyleParser {
6879
/:\d+:\d+:/,
6980
`:${error.line}:${error.column}:`,
7081
);
82+
error.source = this.input.css;
83+
error.input.source = this.input.css;
7184
}
7285
return error;
7386
}

test/e2e/stylelint.js

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import stylelint from "stylelint";
33
import stylelintConfig from "stylelint-config-standard";
44
import customSyntax from "../../src/index.js";
55
import { getAllFixtureFilenames, getFixtureCode } from "../utils.js";
6-
import * as assert from "uvu/assert";
6+
import { equal, is, not, ok, snapshot } from "uvu/assert";
77

88
const stylelintRun = (content, path, opts) => {
99
return stylelint.lint({
@@ -36,14 +36,18 @@ autofixFiles.forEach(({ fixable, fixed }) => {
3636
const result = await stylelintRun(fixture.code, fixture.path, {
3737
fix: true,
3838
});
39-
assert.is(result.code, getFixtureCode(fixed).code);
39+
snapshot(result.code, getFixtureCode(fixed).code);
4040
});
4141
});
4242

4343
const noSourceFixture = getFixtureCode("no-style.component.ts");
4444
test(`Test if stylelint considers this empty source: ${noSourceFixture.filename}`, async () => {
4545
const result = await stylelintRun(noSourceFixture.code, noSourceFixture.path);
46-
assert.equal(result.results[0].warnings, []);
46+
equal(
47+
result.results[0].warnings.length,
48+
0,
49+
`Expected no warnings but the following warnings were raised: ${result.results[0].warnings}`,
50+
);
4751
});
4852

4953
const emptySourceFixture = getFixtureCode("empty-style.component.ts");
@@ -52,17 +56,32 @@ test(`Test if stylelint considers this empty source: ${emptySourceFixture.filena
5256
emptySourceFixture.code,
5357
emptySourceFixture.path,
5458
);
59+
ok(result);
60+
ok(result.results[0]);
5561

56-
assert.equal(result.results[0].warnings[0], {
57-
line: 6,
58-
column: 11,
59-
endLine: 6,
60-
endColumn: 12,
61-
rule: "no-empty-source",
62-
severity: "error",
63-
text: "Unexpected empty source (no-empty-source)",
64-
url: undefined,
65-
});
62+
const warnings = result.results[0].warnings;
63+
not.equal(warnings, [], "Expected warnings not to be empty");
64+
ok(
65+
warnings.map((w) => w.rule).includes("no-empty-source"),
66+
`Expected a warning about empty source. Warnings: ${warnings}`,
67+
);
68+
});
69+
70+
const whitespaceFixture = getFixtureCode("whitespace.component.ts");
71+
test(`Test if stylelint considers this empty source: ${whitespaceFixture.filename}`, async () => {
72+
const result = await stylelintRun(
73+
whitespaceFixture.code,
74+
whitespaceFixture.path,
75+
);
76+
ok(result);
77+
ok(result.results[0]);
78+
79+
const warnings = result.results[0].warnings;
80+
not.equal(warnings, [], "Expected warnings not to be empty");
81+
ok(
82+
warnings.map((w) => w.rule).includes("no-empty-source"),
83+
`Expected a warning about empty source. Warnings: ${warnings.toString()}`,
84+
);
6685
});
6786

6887
test.run();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Component } from "@angular/core";
2+
3+
@Component({
4+
selector: "app-example",
5+
template: "<div></div>",
6+
styles: ".example color: red; }",
7+
})
8+
export class ExampleComponent {}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Component } from "@angular/core";
2+
3+
@Component({
4+
selector: "app-example",
5+
template: "<div></div>",
6+
styles: [" ", " ", "\n", "\r\n"],
7+
})
8+
export class ExampleComponent {}

test/integration/byte-to-byte.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@ import { test } from "uvu";
22
import * as assert from "uvu/assert";
33
import postcss from "postcss";
44
import customSyntax from "../../src/index.js";
5-
import { getAllFixtureFilenames, getFixtureCode } from "../utils.js";
5+
import { getFixtureCode } from "../utils.js";
66

7-
getAllFixtureFilenames().forEach((filename) => {
7+
const testCases = [
8+
"empty-style.component.ts",
9+
"fixable.component.ts",
10+
"fixed.component.ts",
11+
"multi-style.component.ts",
12+
"no-style.component.ts",
13+
"one-style.component.ts",
14+
"real.component.ts",
15+
"whitespace.component.ts",
16+
];
17+
18+
testCases.forEach((filename) => {
819
const fixture = getFixtureCode(filename);
920

1021
test(`CustomSyntax byte-to-byte transformation on: ${fixture.filename}`, async () => {

test/unit/parse.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@ import { test } from "uvu";
22
import * as assert from "uvu/assert";
33
import { parse } from "../../src/index.js";
44
import postcss from "postcss";
5-
import { getAllFixtureFilenames, getFixtureCode } from "../utils.js";
5+
import { getFixtureCode } from "../utils.js";
66

7-
getAllFixtureFilenames().forEach((filename) => {
7+
const testCases = [
8+
"empty-style.component.ts",
9+
"fixable.component.ts",
10+
"fixed.component.ts",
11+
"multi-style.component.ts",
12+
"no-style.component.ts",
13+
"one-style.component.ts",
14+
"real.component.ts",
15+
"whitespace.component.ts",
16+
];
17+
18+
testCases.forEach((filename) => {
819
const fixture = getFixtureCode(filename);
920

1021
test(`Parse runs error free for: ${fixture.filename}`, () => {

test/unit/parser-styles.js

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { test } from "uvu";
22
import { getFixtureCode } from "../utils.js";
33
import { TypescriptParser } from "../../src/parser-typescript.js";
4-
import { Input } from "postcss";
4+
import { CssSyntaxError, Input } from "postcss";
55
import { StyleParser } from "../../src/parser-styles.js";
6-
import { equal } from "uvu/assert";
6+
import { equal, throws } from "uvu/assert";
77

8-
const testCases = [
8+
const positionTestCases = [
99
{
1010
filename: "empty-style.component.ts",
1111
sources: [
@@ -71,7 +71,7 @@ const testCases = [
7171
},
7272
];
7373

74-
testCases.forEach(({ filename, sources }) => {
74+
positionTestCases.forEach(({ filename, sources }) => {
7575
const fixture = getFixtureCode(filename);
7676

7777
test(`Ensure strings have correct position: ${fixture.filename}`, () => {
@@ -89,4 +89,47 @@ testCases.forEach(({ filename, sources }) => {
8989
});
9090
});
9191

92+
const syntaxErrFixture = getFixtureCode("syntax-error.component.ts");
93+
94+
test(`Ensure syntax error has correct position: ${syntaxErrFixture.filename}`, () => {
95+
const opts = { from: syntaxErrFixture.path };
96+
const input = new Input(syntaxErrFixture.code, opts);
97+
98+
const tsParser = new TypescriptParser(input);
99+
const styleLiterals = tsParser.parse();
100+
101+
const styleParser = new StyleParser(input, styleLiterals[0]);
102+
103+
throws(
104+
() => styleParser.parse(opts),
105+
(/** @type {Error} */ err) => {
106+
if (!(err instanceof CssSyntaxError)) return false;
107+
108+
const expectedPos = {
109+
file: syntaxErrFixture.path,
110+
line: 6,
111+
column: 22,
112+
endLine: 7,
113+
endColumn: 27,
114+
source: syntaxErrFixture.code,
115+
};
116+
117+
const expectedInput = {
118+
url: "file:///home/blyedev/Projects/postcss-angular-inline/test/fixtures/syntax-error.component.ts",
119+
...expectedPos,
120+
};
121+
const expectedErrorProperties = {
122+
name: "CssSyntaxError",
123+
reason: "Unknown word",
124+
...expectedPos,
125+
input: expectedInput,
126+
};
127+
128+
equal({ ...err }, { ...expectedErrorProperties });
129+
130+
return true;
131+
},
132+
);
133+
});
134+
92135
test.run();

0 commit comments

Comments
 (0)