@flint.fyi/rule-tester 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AnyOptionalSchema, AnyRule, InferredInputObject, RuleAbout } from "@flint.fyi/core";
2
-
3
2
  //#region src/types.d.ts
4
3
  interface InvalidTestCase<Options extends object | undefined = object | undefined> extends TestCase<Options> {
5
4
  output?: string;
@@ -47,6 +46,7 @@ interface RuleTesterDefaults {
47
46
  files?: Record<string, string>;
48
47
  }
49
48
  interface RuleTesterOptions {
49
+ assertNoLanguageReports?: boolean;
50
50
  defaults?: RuleTesterDefaults;
51
51
  describe?: TesterSetupDescribe;
52
52
  diskBackedFSRoot?: string;
@@ -63,19 +63,8 @@ type TesterSetupDescribe = (description: string, setup: () => void) => void;
63
63
  type TesterSetupIt = (description: string, setup: () => Promise<void>) => void;
64
64
  declare class RuleTester {
65
65
  #private;
66
- constructor({
67
- defaults,
68
- describe,
69
- diskBackedFSRoot,
70
- it,
71
- only,
72
- scope,
73
- skip
74
- }?: RuleTesterOptions);
75
- describe<OptionsSchema extends AnyOptionalSchema | undefined>(rule: AnyRule<RuleAbout, OptionsSchema>, {
76
- invalid,
77
- valid
78
- }: TestCases<InferredInputObject<OptionsSchema>>): void;
66
+ constructor({ assertNoLanguageReports, defaults, describe, diskBackedFSRoot, it, only, scope, skip }?: RuleTesterOptions);
67
+ describe<OptionsSchema extends AnyOptionalSchema | undefined>(rule: AnyRule<RuleAbout, OptionsSchema>, { invalid, valid }: TestCases<InferredInputObject<OptionsSchema>>): void;
79
68
  }
80
69
  //#endregion
81
70
  export { type InvalidTestCase, RuleTester, type TestCase, type TestSuggestion, type TestSuggestionFileCase, type TestSuggestionForFile, type TestSuggestionForFiles, type ValidTestCase, type ValidTestCaseObject };
package/dist/index.mjs CHANGED
@@ -123,7 +123,7 @@ function resolveReportedSuggestionForFiles(suggestionReported, testCaseNormalize
123
123
  }
124
124
  //#endregion
125
125
  //#region src/runTestCaseRule.ts
126
- async function runTestCaseRule(fileFactories, linterHost, { options, rule }, { code, fileName, files }) {
126
+ async function runTestCaseRule(fileFactories, linterHost, { options, rule }, { code, fileName, files }, { collectLanguageReports = false } = {}) {
127
127
  const filePathAbsolute = normalizePath(path.resolve(linterHost.getCurrentDirectory(), fileName));
128
128
  const caseSensitive = linterHost.isCaseSensitiveFS();
129
129
  const targetKey = pathKey(filePathAbsolute, caseSensitive);
@@ -152,7 +152,10 @@ async function runTestCaseRule(fileFactories, linterHost, { options, rule }, { c
152
152
  rule.language.runFileVisitors(file, options, ruleRuntime);
153
153
  await ruleRuntime.teardown?.();
154
154
  }
155
- return reports.toSorted((a, b) => a.range.begin.raw - b.range.begin.raw || a.range.end.raw - b.range.end.raw);
155
+ return {
156
+ languageReports: collectLanguageReports ? rule.language.getLanguageReports?.(file) ?? [] : [],
157
+ reports: reports.toSorted((a, b) => a.range.begin.raw - b.range.begin.raw || a.range.end.raw - b.range.end.raw)
158
+ };
156
159
  }
157
160
  //#endregion
158
161
  //#region src/RuleTester.ts
@@ -160,7 +163,7 @@ var RuleTester = class {
160
163
  #fileFactories;
161
164
  #linterHost;
162
165
  #testerOptions;
163
- constructor({ defaults = {}, describe, diskBackedFSRoot, it, only, scope = globalThis, skip } = {}) {
166
+ constructor({ assertNoLanguageReports = true, defaults = {}, describe, diskBackedFSRoot, it, only, scope = globalThis, skip } = {}) {
164
167
  let baseHost = diskBackedFSRoot != null ? createEphemeralLinterHost(createDiskBackedLinterHost(path.resolve(process.cwd(), diskBackedFSRoot, "_flint-rule-tester-virtual"))) : void 0;
165
168
  const { files: defaultFiles = {} } = defaults;
166
169
  if (Object.keys(defaultFiles).length) {
@@ -179,6 +182,7 @@ var RuleTester = class {
179
182
  if (!skip) throw new TypeError("RuleTester needs a `skip` function");
180
183
  if (!only) throw new TypeError("RuleTester needs a `only` function");
181
184
  this.#testerOptions = {
185
+ assertNoLanguageReports,
182
186
  defaults,
183
187
  describe: defaultTo(describe, scope, "describe"),
184
188
  it,
@@ -200,10 +204,11 @@ var RuleTester = class {
200
204
  #itInvalidCase(rule, testCase) {
201
205
  const testCaseNormalized = normalizeTestCase(testCase, this.#testerOptions.defaults.fileName);
202
206
  this.#itTestCase(testCaseNormalized, async () => {
203
- const reports = await runTestCaseRule(this.#fileFactories, this.#linterHost, {
207
+ const { languageReports, reports } = await runTestCaseRule(this.#fileFactories, this.#linterHost, {
204
208
  options: parseOptions(rule.options, testCase.options),
205
209
  rule
206
- }, testCaseNormalized);
210
+ }, testCaseNormalized, { collectLanguageReports: this.#testerOptions.assertNoLanguageReports });
211
+ assertNoLanguageReports(languageReports);
207
212
  const actualSnapshot = createReportSnapshot(testCase.code, reports);
208
213
  assert.equal(actualSnapshot, testCase.snapshot);
209
214
  const actualOutput = createOutput(reports, testCaseNormalized);
@@ -214,8 +219,10 @@ var RuleTester = class {
214
219
  }
215
220
  #itTestCase(testCase, setup) {
216
221
  let test = testCase.only ? this.#testerOptions.only : this.#testerOptions.it;
217
- if (testCase.skip) if ("skip" in test && typeof test.skip === "function") test = test.skip;
218
- else test = this.#testerOptions.skip;
222
+ if (testCase.skip) {
223
+ if ("skip" in test && typeof test.skip === "function") test = test.skip;
224
+ else test = this.#testerOptions.skip;
225
+ }
219
226
  test(testCase.name ?? ("files" in testCase ? JSON.stringify({
220
227
  [testCase.fileName]: testCase.code,
221
228
  ...testCase.files
@@ -228,14 +235,18 @@ var RuleTester = class {
228
235
  const testCase = typeof testCaseRaw === "string" ? { code: testCaseRaw } : testCaseRaw;
229
236
  const testCaseNormalized = normalizeTestCase(testCase, this.#testerOptions.defaults.fileName);
230
237
  this.#itTestCase(testCaseNormalized, async () => {
231
- const reports = await runTestCaseRule(this.#fileFactories, this.#linterHost, {
238
+ const { languageReports, reports } = await runTestCaseRule(this.#fileFactories, this.#linterHost, {
232
239
  options: parseOptions(rule.options, testCase.options),
233
240
  rule
234
- }, testCaseNormalized);
241
+ }, testCaseNormalized, { collectLanguageReports: this.#testerOptions.assertNoLanguageReports });
242
+ assertNoLanguageReports(languageReports);
235
243
  if (reports.length) assert.deepStrictEqual(createReportSnapshot(testCaseNormalized.code, reports), testCaseNormalized.code);
236
244
  });
237
245
  }
238
246
  };
247
+ function assertNoLanguageReports(languageReports) {
248
+ if (languageReports.length) assert.fail([`Expected no language reports, but found ${languageReports.length}:`, ...languageReports.map((languageReport) => languageReport.text)].join("\n\n"));
249
+ }
239
250
  function defaultTo(provided, scope, scopeKey) {
240
251
  if (provided) return provided;
241
252
  if (scopeKey in scope && typeof scope[scopeKey] === "function") return scope[scopeKey];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flint.fyi/rule-tester",
3
- "version": "0.18.0",
3
+ "version": "0.19.1",
4
4
  "description": "[Experimental] Rule unit tests for Flint.",
5
5
  "homepage": "https://flint.fyi",
6
6
  "repository": {
@@ -22,14 +22,14 @@
22
22
  "dist/"
23
23
  ],
24
24
  "dependencies": {
25
- "cached-factory": "^0.3.0",
26
- "@flint.fyi/core": "^0.25.0",
27
- "@flint.fyi/utils": "^0.16.0"
25
+ "@flint.fyi/core": "^0.26.0",
26
+ "@flint.fyi/utils": "^0.16.0",
27
+ "cached-factory": "^0.3.0"
28
28
  },
29
29
  "devDependencies": {
30
- "tsdown": "0.22.3",
31
- "vitest": "4.1.0",
32
- "@flint.fyi/build": "^0.1.0"
30
+ "@flint.fyi/build": "^0.1.0",
31
+ "tsdown": "0.22.14",
32
+ "vitest": "4.1.11"
33
33
  },
34
34
  "engines": {
35
35
  "node": ">=26.1.0"