@pobammer-ts/small-rules 1.1.0 → 2.0.0

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.ts CHANGED
@@ -680,13 +680,20 @@ declare const smallRules: import("oxlint-plugin-utilities").Plugin<{
680
680
  readonly type: "object";
681
681
  }]>;
682
682
  "prefer-expect-assertions": import("oxlint-plugin-utilities").CreateRule<readonly [{
683
+ readonly additionalAssertionFunctions?: readonly string[];
683
684
  readonly additionalExpectCallNames?: readonly string[];
684
685
  readonly onlyFunctionsWithAsyncKeyword?: boolean;
685
686
  readonly onlyFunctionsWithExpectInCallback?: boolean;
686
687
  readonly onlyFunctionsWithExpectInLoop?: boolean;
687
- }], "assertionsRequiresNumberArgument" | "assertionsRequiresOneArgument" | "hasAssertionsTakesNoArguments" | "haveExpectAssertions" | "suggestAddingAssertions" | "suggestAddingHasAssertions" | "wrongAssertionCount", readonly [{
688
+ }], "assertionsRequiresNumberArgument" | "assertionsRequiresOneArgument" | "hasAssertionsTakesNoArguments" | "haveExpectAssertions" | "preferAssertionsCount" | "suggestAddingAssertions" | "suggestAddingHasAssertions" | "wrongAssertionCount", readonly [{
688
689
  readonly additionalProperties: false;
689
690
  readonly properties: {
691
+ readonly additionalAssertionFunctions: {
692
+ readonly items: {
693
+ readonly type: "string";
694
+ };
695
+ readonly type: "array";
696
+ };
690
697
  readonly additionalExpectCallNames: {
691
698
  readonly items: {
692
699
  readonly type: "string";
@@ -705,20 +712,6 @@ declare const smallRules: import("oxlint-plugin-utilities").Plugin<{
705
712
  };
706
713
  readonly type: "object";
707
714
  }]>;
708
- "prefer-expect-assertions-count": import("oxlint-plugin-utilities").CreateRule<readonly [{
709
- readonly additionalAssertionFunctions?: readonly string[];
710
- }], "preferAssertionsCount", readonly [{
711
- readonly additionalProperties: false;
712
- readonly properties: {
713
- readonly additionalAssertionFunctions: {
714
- readonly items: {
715
- readonly type: "string";
716
- };
717
- readonly type: "array";
718
- };
719
- };
720
- readonly type: "object";
721
- }]>;
722
715
  "prefer-hoisted-jsx-elements": import("oxlint-plugin-utilities").CreateRule<readonly [{
723
716
  readonly additionalHoistableComponents?: readonly string[];
724
717
  readonly additionalStaticFactories?: readonly string[];
package/dist/index.js CHANGED
@@ -20280,7 +20280,7 @@ function getExpectContext(currentParent, root) {
20280
20280
  };
20281
20281
  const ownContext = {
20282
20282
  hasCallback: isFunction(currentParent),
20283
- hasIndeterminate: isFunction(currentParent) || isIndeterminateLoopNode(currentParent) || currentParent.type === "ConditionalExpression" || currentParent.type === "IfStatement" || currentParent.type === "SwitchCase" || currentParent.type === "TryStatement",
20283
+ hasIndeterminate: isFunction(currentParent) || isIndeterminateLoopNode(currentParent) || currentParent.type === "ConditionalExpression" || currentParent.type === "IfStatement" || currentParent.type === "SwitchCase" || currentParent.type === "TryStatement" && currentParent.handler !== null,
20284
20284
  hasLoop: isIndeterminateLoopNode(currentParent)
20285
20285
  };
20286
20286
  if (currentParent.parent === null) return ownContext;
@@ -20334,20 +20334,29 @@ function countExpectCalls(body, additionalAssertionFunctions = []) {
20334
20334
  }
20335
20335
  //#endregion
20336
20336
  //#region src/rules/prefer-expect-assertions.ts
20337
+ function parseStringArray(value) {
20338
+ if (!Array.isArray(value)) return [];
20339
+ return value.filter((item) => typeof item === "string");
20340
+ }
20337
20341
  function parseOptions$1(rawOptions) {
20338
20342
  if (!isRecord$2(rawOptions)) return {
20343
+ additionalAssertionFunctions: [],
20339
20344
  additionalExpectCallNames: [],
20340
20345
  onlyFunctionsWithAsyncKeyword: false,
20341
20346
  onlyFunctionsWithExpectInCallback: false,
20342
20347
  onlyFunctionsWithExpectInLoop: false
20343
20348
  };
20344
20349
  return {
20345
- additionalExpectCallNames: Array.isArray(rawOptions.additionalExpectCallNames) ? rawOptions.additionalExpectCallNames.filter((name) => typeof name === "string") : [],
20350
+ additionalAssertionFunctions: parseStringArray(rawOptions.additionalAssertionFunctions),
20351
+ additionalExpectCallNames: parseStringArray(rawOptions.additionalExpectCallNames),
20346
20352
  onlyFunctionsWithAsyncKeyword: rawOptions.onlyFunctionsWithAsyncKeyword === true,
20347
20353
  onlyFunctionsWithExpectInCallback: rawOptions.onlyFunctionsWithExpectInCallback === true,
20348
20354
  onlyFunctionsWithExpectInLoop: rawOptions.onlyFunctionsWithExpectInLoop === true
20349
20355
  };
20350
20356
  }
20357
+ function getAdditionalExpectCallNames(options) {
20358
+ return [...new Set([...options.additionalExpectCallNames, ...options.additionalAssertionFunctions])];
20359
+ }
20351
20360
  function hasEnabledFilter(options) {
20352
20361
  return options.onlyFunctionsWithAsyncKeyword || options.onlyFunctionsWithExpectInCallback || options.onlyFunctionsWithExpectInLoop;
20353
20362
  }
@@ -20448,11 +20457,22 @@ const preferExpectAssertions = defineRule({
20448
20457
  if (callback === void 0) return;
20449
20458
  const body = getCallbackBody(callback);
20450
20459
  if (body === void 0) return;
20451
- const { deterministic, indeterminate, hasIndeterminate, hasExpectInCallback, hasExpectInLoop } = countExpectCalls(body, options.additionalExpectCallNames);
20460
+ const { deterministic, indeterminate, hasIndeterminate, hasExpectInCallback, hasExpectInLoop } = countExpectCalls(body, getAdditionalExpectCallNames(options));
20452
20461
  if (!shouldCheckTest(callback, options, deterministic, indeterminate, hasExpectInCallback, hasExpectInLoop)) return;
20453
20462
  const assertionCall = getFirstStatementCall(callback);
20454
20463
  if (assertionCall !== void 0 && (isExpectAssertionsCall(assertionCall) || isExpectHasAssertionsCall(assertionCall))) {
20455
20464
  validateAssertionCall(context, assertionCall, deterministic, hasIndeterminate);
20465
+ if (isExpectHasAssertionsCall(assertionCall) && assertionCall.arguments.length === 0 && deterministic > 0 && !hasIndeterminate) {
20466
+ const [firstStatement] = getCallbackBlockBody(callback)?.body ?? [];
20467
+ if (firstStatement !== void 0) context.report({
20468
+ data: { count: String(deterministic) },
20469
+ fix(fixer) {
20470
+ return fixer.replaceText(firstStatement, `expect.assertions(${deterministic});`);
20471
+ },
20472
+ messageId: "preferAssertionsCount",
20473
+ node: assertionCall
20474
+ });
20475
+ }
20456
20476
  return;
20457
20477
  }
20458
20478
  reportMissingAssertions(context, callback, node, deterministic, hasIndeterminate);
@@ -20460,15 +20480,17 @@ const preferExpectAssertions = defineRule({
20460
20480
  },
20461
20481
  meta: {
20462
20482
  docs: {
20463
- description: "Enforce expect assertion guards in Jest tests.",
20483
+ description: "Enforce expect assertion guards in Jest tests and prefer expect.assertions(n) over expect.hasAssertions() when the count is known.",
20464
20484
  recommended: true
20465
20485
  },
20486
+ fixable: "code",
20466
20487
  hasSuggestions: true,
20467
20488
  messages: {
20468
20489
  assertionsRequiresNumberArgument: "This argument should be a number",
20469
20490
  assertionsRequiresOneArgument: "`expect.assertions` expects a single argument of type number",
20470
20491
  hasAssertionsTakesNoArguments: "`expect.hasAssertions` expects no arguments",
20471
20492
  haveExpectAssertions: "Every test should have either `expect.assertions(<number of assertions>)` or `expect.hasAssertions()` as its first expression",
20493
+ preferAssertionsCount: "Use `expect.assertions({{count}})` instead of `expect.hasAssertions()` when the count is known",
20472
20494
  suggestAddingAssertions: "Add `expect.assertions({{count}})`",
20473
20495
  suggestAddingHasAssertions: "Add `expect.hasAssertions()`",
20474
20496
  wrongAssertionCount: "Expected {{expected}} assertions, but test has {{actual}} expect calls"
@@ -20476,6 +20498,10 @@ const preferExpectAssertions = defineRule({
20476
20498
  schema: [{
20477
20499
  additionalProperties: false,
20478
20500
  properties: {
20501
+ additionalAssertionFunctions: {
20502
+ items: { type: "string" },
20503
+ type: "array"
20504
+ },
20479
20505
  additionalExpectCallNames: {
20480
20506
  items: { type: "string" },
20481
20507
  type: "array"
@@ -20490,46 +20516,6 @@ const preferExpectAssertions = defineRule({
20490
20516
  }
20491
20517
  });
20492
20518
  //#endregion
20493
- //#region src/rules/prefer-expect-assertions-count.ts
20494
- const preferExpectAssertionsCount = defineRule({
20495
- create(context) {
20496
- const additionalAssertionFunctions = context.options[0]?.additionalAssertionFunctions ?? [];
20497
- return { CallExpression(node) {
20498
- if (!isTestCaseCall(node)) return;
20499
- const callback = getTestCallback(node);
20500
- if (callback?.body?.type !== "BlockStatement") return;
20501
- const [firstStatement] = callback.body.body;
20502
- if (firstStatement?.type !== "ExpressionStatement" || firstStatement.expression.type !== "CallExpression" || !isExpectHasAssertionsCall(firstStatement.expression)) return;
20503
- const { deterministic, indeterminate, hasIndeterminate } = countExpectCalls(callback.body, additionalAssertionFunctions);
20504
- if (hasIndeterminate || indeterminate > 0 || deterministic === 0) return;
20505
- context.report({
20506
- data: { count: String(deterministic) },
20507
- fix(fixer) {
20508
- return fixer.replaceText(firstStatement, `expect.assertions(${deterministic});`);
20509
- },
20510
- messageId: "preferAssertionsCount",
20511
- node: firstStatement.expression
20512
- });
20513
- } };
20514
- },
20515
- meta: {
20516
- docs: {
20517
- description: "Prefer expect.assertions(n) over expect.hasAssertions() when the assertion count is known.",
20518
- recommended: true
20519
- },
20520
- fixable: "code",
20521
- messages: { preferAssertionsCount: "Use `expect.assertions({{count}})` instead of `expect.hasAssertions()` when the count is known" },
20522
- schema: [{
20523
- additionalProperties: false,
20524
- properties: { additionalAssertionFunctions: {
20525
- items: { type: "string" },
20526
- type: "array"
20527
- } },
20528
- type: "object"
20529
- }]
20530
- }
20531
- });
20532
- //#endregion
20533
20519
  //#region src/rules/prefer-hoisted-jsx-elements.ts
20534
20520
  function normalizeAdditionalHoistableComponents(rawOptions) {
20535
20521
  if (!(isRecord$2(rawOptions) && "additionalHoistableComponents" in rawOptions)) return /* @__PURE__ */ new Set();
@@ -26042,7 +26028,6 @@ const smallRules = definePlugin({
26042
26028
  "prefer-context-stack": preferContextStack,
26043
26029
  "prefer-early-return": preferEarlyReturn,
26044
26030
  "prefer-expect-assertions": preferExpectAssertions,
26045
- "prefer-expect-assertions-count": preferExpectAssertionsCount,
26046
26031
  "prefer-hoisted-jsx-elements": preferHoistedJsxElements,
26047
26032
  "prefer-hoisted-jsx-object-properties": preferHoistedJsxObjectProperties,
26048
26033
  "prefer-idiv": preferIdiv,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pobammer-ts/small-rules",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Various Oxlint-native rules for linting roblox-ts projects.",
5
5
  "keywords": [
6
6
  "lint",
@@ -118,7 +118,7 @@
118
118
  "vitiate": "0.3.0"
119
119
  },
120
120
  "peerDependencies": {
121
- "typescript": "6"
121
+ "typescript": ">=5 <8"
122
122
  },
123
123
  "engines": {
124
124
  "node": "^20.19.0 || >=22.12.0"