Skip to content

Commit c7a073c

Browse files
committed
test(selector-parsing): added tests
1 parent fb8ce7d commit c7a073c

9 files changed

+141
-1
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@
5959
"eslint-visitor-keys": "^4.0.0",
6060
"espree": "^10.0.0",
6161
"postcss": "^8.4.49",
62-
"postcss-scss": "^4.0.9"
62+
"postcss-scss": "^4.0.9",
63+
"postcss-selector-parser": "^7.0.0"
6364
},
6465
"devDependencies": {
6566
"@changesets/changelog-github": "^0.5.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<script>
2+
let a = 10
3+
</script>
4+
5+
<span class="myClass">Hello!</span>
6+
7+
<b>{a}</b>
8+
9+
<style>
10+
.myClass {
11+
color: red;
12+
}
13+
14+
b {
15+
font-size: xx-large;
16+
}
17+
18+
a:active,
19+
a::before,
20+
b + a,
21+
b + .myClass,
22+
a[data-key="value"] {
23+
color: blue;
24+
}
25+
</style>

tests/fixtures/parser/selector-parsing/simple-css-output.json

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<div class="container">
2+
<div class="div-class">Hello</div>
3+
4+
<span class="span-class">World!</span>
5+
</div>
6+
7+
<style lang="postcss">
8+
body {
9+
colour: white;
10+
background-colour: grey;
11+
}
12+
13+
a:active,
14+
a::before,
15+
b + a,
16+
b + .myClass,
17+
a[data-key="value"] {
18+
color: blue;
19+
}
20+
</style>

tests/fixtures/parser/selector-parsing/simple-postcss-output.json

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<div class="container">
2+
<div class="div-class">Hello</div>
3+
4+
<span class="span-class">World!</span>
5+
</div>
6+
7+
<style lang="scss">
8+
.container {
9+
.div-class {
10+
// This is an inline comment
11+
color: red;
12+
}
13+
14+
.span-class {
15+
font-weight: bold;
16+
}
17+
18+
a:active,
19+
a::before,
20+
b + a,
21+
b + .myClass,
22+
a[data-key="value"] {
23+
color: blue;
24+
}
25+
}
26+
</style>

tests/fixtures/parser/selector-parsing/simple-scss-output.json

Whitespace-only changes.

tests/src/parser/selector-parsing.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import assert from "assert";
2+
import fs from "fs";
3+
import path from "path";
4+
import type { Node } from "postcss";
5+
import type { Root as SelectorRoot } from "postcss-selector-parser";
6+
7+
import { parseForESLint } from "../../../src/index.js";
8+
import {
9+
generateParserOptions,
10+
listupFixtures,
11+
selectorNodeToJson,
12+
} from "./test-utils.js";
13+
14+
const dirname = path.dirname(new URL(import.meta.url).pathname);
15+
const SELECTOR_PARSING_FIXTURE_ROOT = path.resolve(
16+
dirname,
17+
"../../fixtures/parser/selector-parsing",
18+
);
19+
20+
function parse(code: string, filePath: string, config: any) {
21+
return parseForESLint(code, generateParserOptions({ filePath }, config));
22+
}
23+
24+
describe("Check for AST.", () => {
25+
for (const {
26+
input,
27+
inputFileName,
28+
outputFileName,
29+
config,
30+
meetRequirements,
31+
} of listupFixtures(SELECTOR_PARSING_FIXTURE_ROOT)) {
32+
if (!meetRequirements("parse")) {
33+
continue;
34+
}
35+
describe(inputFileName, () => {
36+
let services: any;
37+
38+
it("most to generate the expected selector AST.", () => {
39+
services = parse(input, inputFileName, config).services;
40+
if (!meetRequirements("test")) {
41+
return;
42+
}
43+
const styleContext = services.getStyleContext();
44+
assert.strictEqual(styleContext.status, "success");
45+
const selectorASTs: SelectorRoot[] = [];
46+
styleContext.sourceAst.walk((node: Node) => {
47+
if (node.type === "rule") {
48+
selectorASTs.push(services.getStyleSelectorAST(node));
49+
}
50+
});
51+
const output = fs.readFileSync(outputFileName, "utf8");
52+
assert.strictEqual(`${selectorASTs.map(selectorNodeToJson)}\n`, output);
53+
});
54+
});
55+
}
56+
});

tests/src/parser/test-utils.ts

+12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { Linter, Scope as ESLintScope } from "eslint";
55
import { LinesAndColumns } from "../../../src/context/index.js";
66
import type { Reference, Scope, ScopeManager, Variable } from "eslint-scope";
77
import type * as TSESScopes from "@typescript-eslint/scope-manager";
8+
import type { Node as SelectorNode } from "postcss-selector-parser";
89
import type { SvelteNode } from "../../../src/ast/index.js";
910
import type { StyleContext } from "../../../src/index.js";
1011
import { TS_GLOBALS } from "./ts-vars.js";
@@ -480,6 +481,17 @@ export function styleContextToJson(styleContext: StyleContext): string {
480481
}
481482
}
482483

484+
export function selectorNodeToJson(node: SelectorNode): string {
485+
return JSON.stringify(node, nodeReplacer, 2);
486+
487+
function nodeReplacer(key: string, value: any): any {
488+
if (key === "parent" || key.startsWith("_")) {
489+
return undefined;
490+
}
491+
return value;
492+
}
493+
}
494+
483495
function normalizeScope(scope: Scope | TSESScopes.Scope): any {
484496
let variables = scope.variables as TSESScopes.Variable[];
485497
if (scope.type === "global") {

0 commit comments

Comments
 (0)