eslint-plugin-executable-stories-jest 1.2.0 → 2.1.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.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -73,7 +73,7 @@ function isStepCall(node) {
|
|
|
73
73
|
return callee.property.type === "Identifier" && STEP_NAMES.has(callee.property.name);
|
|
74
74
|
}
|
|
75
75
|
function insideStoryCallback(node, context) {
|
|
76
|
-
const ancestors = context.
|
|
76
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
77
77
|
const functionAncestors = new Set(ancestors.filter(isFunction));
|
|
78
78
|
for (const ancestor of ancestors) {
|
|
79
79
|
if (ancestor.type !== "CallExpression") continue;
|
|
@@ -104,7 +104,7 @@ var rule = {
|
|
|
104
104
|
const storyCallbackNames = /* @__PURE__ */ new Set();
|
|
105
105
|
const pendingStepCalls = [];
|
|
106
106
|
function getContainingFunctionName(node) {
|
|
107
|
-
const ancestors = context.
|
|
107
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
108
108
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
109
109
|
const ancestor = ancestors[i];
|
|
110
110
|
if (ancestor.type === "FunctionDeclaration" && ancestor.id) {
|
|
@@ -219,7 +219,7 @@ function isTestCallExpression(node) {
|
|
|
219
219
|
return false;
|
|
220
220
|
}
|
|
221
221
|
function insideTestCallback(node, context) {
|
|
222
|
-
const ancestors = context.
|
|
222
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
223
223
|
const functionAncestors = new Set(ancestors.filter(isFunction2));
|
|
224
224
|
for (const ancestor of ancestors) {
|
|
225
225
|
if (ancestor.type !== "CallExpression") continue;
|
|
@@ -251,7 +251,7 @@ var rule2 = {
|
|
|
251
251
|
const testCallbackNames = /* @__PURE__ */ new Set();
|
|
252
252
|
const pendingDocStoryCalls = [];
|
|
253
253
|
function getContainingFunctionName(node) {
|
|
254
|
-
const ancestors = context.
|
|
254
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
255
255
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
256
256
|
const ancestor = ancestors[i];
|
|
257
257
|
if (ancestor.type === "FunctionDeclaration" && ancestor.id) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/rules/require-story-context-for-steps.ts","../src/rules/require-test-context-for-doc-story.ts"],"sourcesContent":["import type { ESLint, Linter } from 'eslint';\nimport requireStoryContextForSteps from './rules/require-story-context-for-steps.js';\nimport requireTestContextForDocStory from './rules/require-test-context-for-doc-story.js';\n\nconst rules = {\n 'require-story-context-for-steps': requireStoryContextForSteps,\n 'require-test-context-for-doc-story': requireTestContextForDocStory,\n};\n\nconst configs: Record<string, Linter.Config[]> = {\n recommended: [\n {\n plugins: {\n 'executable-stories-jest': { rules },\n },\n rules: {\n 'executable-stories-jest/require-story-context-for-steps': 'error',\n 'executable-stories-jest/require-test-context-for-doc-story': 'error',\n },\n },\n ],\n};\n\nconst plugin: ESLint.Plugin = {\n meta: {\n name: 'eslint-plugin-executable-stories-jest',\n version: '0.1.0',\n },\n rules,\n configs,\n};\n\nexport default plugin;\nexport { rules, configs };\n","import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\n/** Current API uses story.given() etc. inside test(); no top-level given/when/then. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nconst STEP_NAMES = new Set([\n 'given',\n 'when',\n 'then',\n 'and',\n 'but',\n 'arrange',\n 'act',\n 'assert',\n 'setup',\n 'context',\n 'execute',\n 'action',\n 'verify',\n]);\n\nconst STORY_MODIFIERS = new Set(['skip', 'only']);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return callee.name === 'story';\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier' || callee.object.name !== 'story')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STORY_MODIFIERS.has(callee.property.name)\n );\n}\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isStepCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return STEP_NAMES.has(callee.name);\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'steps' && callee.object.name !== 'step')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STEP_NAMES.has(callee.property.name)\n );\n}\n\nfunction insideStoryCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.getSourceCode().getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isStoryCall(ancestor) && !isDocStoryCall(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require step functions (given/when/then/and/but and aliases) to be called inside story() or doc.story(..., callback).',\n recommended: true,\n },\n schema: [],\n messages: {\n requireStory:\n 'Step functions must be called inside story(...) (or doc.story(..., callback)).',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const storyCallbackNames = new Set<string>();\n const pendingStepCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.getSourceCode().getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { define() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n const pkg = node.source.value;\n if (typeof pkg === 'string' && pkg === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isStoryCall(node) || isDocStoryCall(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n storyCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.define\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n storyCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isStepCall(node)) return;\n if (insideStoryCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingStepCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingStepCalls) {\n if (\n containingFunctionName &&\n storyCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireStory' });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\nconst TEST_MODIFIERS = new Set([\n 'only',\n 'skip',\n 'todo',\n 'concurrent',\n 'failing',\n]);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\n/** Legacy doc.story() is not used; current API uses story.init() inside it/test. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isTestCallExpression(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') {\n return callee.name === 'test' || callee.name === 'it';\n }\n if (callee.type === 'MemberExpression') {\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'test' && callee.object.name !== 'it')\n return false;\n if (callee.property.type !== 'Identifier') return false;\n return TEST_MODIFIERS.has(callee.property.name);\n }\n if (callee.type === 'CallExpression') {\n const inner = callee.callee;\n if (inner.type !== 'MemberExpression') return false;\n if (inner.object.type !== 'Identifier') return false;\n if (inner.object.name !== 'test' && inner.object.name !== 'it')\n return false;\n return (\n inner.property.type === 'Identifier' && inner.property.name === 'each'\n );\n }\n return false;\n}\n\nfunction insideTestCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.getSourceCode().getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isTestCallExpression(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require doc.story(title) to be called inside a test/it callback in Jest.',\n recommended: true,\n },\n schema: [],\n messages: {\n requireTest:\n \"doc.story(title) must be called inside a test/it callback (e.g. it('...', () => { doc.story('Title'); ... })).\",\n requireTitle: 'doc.story(title) requires a title argument.',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const testCallbackNames = new Set<string>();\n const pendingDocStoryCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.getSourceCode().getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { run() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n if (node.source.value === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isTestCallExpression(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n testCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.run\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n testCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isDocStoryCall(node)) return;\n\n if (node.arguments.length === 0) {\n context.report({ node, messageId: 'requireTitle' });\n return;\n }\n if (node.arguments.length >= 2) return;\n\n if (insideTestCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingDocStoryCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingDocStoryCalls) {\n if (\n containingFunctionName &&\n testCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireTest' });\n }\n },\n };\n },\n};\n\nexport default rule;\n"],"mappings":"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","names":["isFunction","isFunctionNode","V1_PACKAGE","isDocStoryCall","rule"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/rules/require-story-context-for-steps.ts","../src/rules/require-test-context-for-doc-story.ts"],"sourcesContent":["import type { ESLint, Linter } from 'eslint';\nimport requireStoryContextForSteps from './rules/require-story-context-for-steps.js';\nimport requireTestContextForDocStory from './rules/require-test-context-for-doc-story.js';\n\nconst rules = {\n 'require-story-context-for-steps': requireStoryContextForSteps,\n 'require-test-context-for-doc-story': requireTestContextForDocStory,\n};\n\nconst configs: Record<string, Linter.Config[]> = {\n recommended: [\n {\n plugins: {\n 'executable-stories-jest': { rules },\n },\n rules: {\n 'executable-stories-jest/require-story-context-for-steps': 'error',\n 'executable-stories-jest/require-test-context-for-doc-story': 'error',\n },\n },\n ],\n};\n\nconst plugin: ESLint.Plugin = {\n meta: {\n name: 'eslint-plugin-executable-stories-jest',\n version: '0.1.0',\n },\n rules,\n configs,\n};\n\nexport default plugin;\nexport { rules, configs };\n","import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\n/** Current API uses story.given() etc. inside test(); no top-level given/when/then. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nconst STEP_NAMES = new Set([\n 'given',\n 'when',\n 'then',\n 'and',\n 'but',\n 'arrange',\n 'act',\n 'assert',\n 'setup',\n 'context',\n 'execute',\n 'action',\n 'verify',\n]);\n\nconst STORY_MODIFIERS = new Set(['skip', 'only']);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return callee.name === 'story';\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier' || callee.object.name !== 'story')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STORY_MODIFIERS.has(callee.property.name)\n );\n}\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isStepCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return STEP_NAMES.has(callee.name);\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'steps' && callee.object.name !== 'step')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STEP_NAMES.has(callee.property.name)\n );\n}\n\nfunction insideStoryCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.sourceCode.getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isStoryCall(ancestor) && !isDocStoryCall(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require step functions (given/when/then/and/but and aliases) to be called inside story() or doc.story(..., callback).',\n recommended: true,\n },\n schema: [],\n messages: {\n requireStory:\n 'Step functions must be called inside story(...) (or doc.story(..., callback)).',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const storyCallbackNames = new Set<string>();\n const pendingStepCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.sourceCode.getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { define() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n const pkg = node.source.value;\n if (typeof pkg === 'string' && pkg === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isStoryCall(node) || isDocStoryCall(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n storyCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.define\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n storyCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isStepCall(node)) return;\n if (insideStoryCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingStepCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingStepCalls) {\n if (\n containingFunctionName &&\n storyCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireStory' });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\nconst TEST_MODIFIERS = new Set([\n 'only',\n 'skip',\n 'todo',\n 'concurrent',\n 'failing',\n]);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\n/** Legacy doc.story() is not used; current API uses story.init() inside it/test. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isTestCallExpression(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') {\n return callee.name === 'test' || callee.name === 'it';\n }\n if (callee.type === 'MemberExpression') {\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'test' && callee.object.name !== 'it')\n return false;\n if (callee.property.type !== 'Identifier') return false;\n return TEST_MODIFIERS.has(callee.property.name);\n }\n if (callee.type === 'CallExpression') {\n const inner = callee.callee;\n if (inner.type !== 'MemberExpression') return false;\n if (inner.object.type !== 'Identifier') return false;\n if (inner.object.name !== 'test' && inner.object.name !== 'it')\n return false;\n return (\n inner.property.type === 'Identifier' && inner.property.name === 'each'\n );\n }\n return false;\n}\n\nfunction insideTestCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.sourceCode.getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isTestCallExpression(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require doc.story(title) to be called inside a test/it callback in Jest.',\n recommended: true,\n },\n schema: [],\n messages: {\n requireTest:\n \"doc.story(title) must be called inside a test/it callback (e.g. it('...', () => { doc.story('Title'); ... })).\",\n requireTitle: 'doc.story(title) requires a title argument.',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const testCallbackNames = new Set<string>();\n const pendingDocStoryCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.sourceCode.getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { run() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n if (node.source.value === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isTestCallExpression(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n testCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.run\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n testCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isDocStoryCall(node)) return;\n\n if (node.arguments.length === 0) {\n context.report({ node, messageId: 'requireTitle' });\n return;\n }\n if (node.arguments.length >= 2) return;\n\n if (insideTestCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingDocStoryCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingDocStoryCalls) {\n if (\n containingFunctionName &&\n testCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireTest' });\n }\n },\n };\n },\n};\n\nexport default rule;\n"],"mappings":"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","names":["isFunction","isFunctionNode","V1_PACKAGE","isDocStoryCall","rule"]}
|
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ function isStepCall(node) {
|
|
|
45
45
|
return callee.property.type === "Identifier" && STEP_NAMES.has(callee.property.name);
|
|
46
46
|
}
|
|
47
47
|
function insideStoryCallback(node, context) {
|
|
48
|
-
const ancestors = context.
|
|
48
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
49
49
|
const functionAncestors = new Set(ancestors.filter(isFunction));
|
|
50
50
|
for (const ancestor of ancestors) {
|
|
51
51
|
if (ancestor.type !== "CallExpression") continue;
|
|
@@ -76,7 +76,7 @@ var rule = {
|
|
|
76
76
|
const storyCallbackNames = /* @__PURE__ */ new Set();
|
|
77
77
|
const pendingStepCalls = [];
|
|
78
78
|
function getContainingFunctionName(node) {
|
|
79
|
-
const ancestors = context.
|
|
79
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
80
80
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
81
81
|
const ancestor = ancestors[i];
|
|
82
82
|
if (ancestor.type === "FunctionDeclaration" && ancestor.id) {
|
|
@@ -191,7 +191,7 @@ function isTestCallExpression(node) {
|
|
|
191
191
|
return false;
|
|
192
192
|
}
|
|
193
193
|
function insideTestCallback(node, context) {
|
|
194
|
-
const ancestors = context.
|
|
194
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
195
195
|
const functionAncestors = new Set(ancestors.filter(isFunction2));
|
|
196
196
|
for (const ancestor of ancestors) {
|
|
197
197
|
if (ancestor.type !== "CallExpression") continue;
|
|
@@ -223,7 +223,7 @@ var rule2 = {
|
|
|
223
223
|
const testCallbackNames = /* @__PURE__ */ new Set();
|
|
224
224
|
const pendingDocStoryCalls = [];
|
|
225
225
|
function getContainingFunctionName(node) {
|
|
226
|
-
const ancestors = context.
|
|
226
|
+
const ancestors = context.sourceCode.getAncestors(node);
|
|
227
227
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
|
228
228
|
const ancestor = ancestors[i];
|
|
229
229
|
if (ancestor.type === "FunctionDeclaration" && ancestor.id) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/rules/require-story-context-for-steps.ts","../src/rules/require-test-context-for-doc-story.ts","../src/index.ts"],"sourcesContent":["import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\n/** Current API uses story.given() etc. inside test(); no top-level given/when/then. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nconst STEP_NAMES = new Set([\n 'given',\n 'when',\n 'then',\n 'and',\n 'but',\n 'arrange',\n 'act',\n 'assert',\n 'setup',\n 'context',\n 'execute',\n 'action',\n 'verify',\n]);\n\nconst STORY_MODIFIERS = new Set(['skip', 'only']);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return callee.name === 'story';\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier' || callee.object.name !== 'story')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STORY_MODIFIERS.has(callee.property.name)\n );\n}\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isStepCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return STEP_NAMES.has(callee.name);\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'steps' && callee.object.name !== 'step')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STEP_NAMES.has(callee.property.name)\n );\n}\n\nfunction insideStoryCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.getSourceCode().getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isStoryCall(ancestor) && !isDocStoryCall(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require step functions (given/when/then/and/but and aliases) to be called inside story() or doc.story(..., callback).',\n recommended: true,\n },\n schema: [],\n messages: {\n requireStory:\n 'Step functions must be called inside story(...) (or doc.story(..., callback)).',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const storyCallbackNames = new Set<string>();\n const pendingStepCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.getSourceCode().getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { define() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n const pkg = node.source.value;\n if (typeof pkg === 'string' && pkg === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isStoryCall(node) || isDocStoryCall(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n storyCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.define\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n storyCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isStepCall(node)) return;\n if (insideStoryCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingStepCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingStepCalls) {\n if (\n containingFunctionName &&\n storyCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireStory' });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\nconst TEST_MODIFIERS = new Set([\n 'only',\n 'skip',\n 'todo',\n 'concurrent',\n 'failing',\n]);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\n/** Legacy doc.story() is not used; current API uses story.init() inside it/test. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isTestCallExpression(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') {\n return callee.name === 'test' || callee.name === 'it';\n }\n if (callee.type === 'MemberExpression') {\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'test' && callee.object.name !== 'it')\n return false;\n if (callee.property.type !== 'Identifier') return false;\n return TEST_MODIFIERS.has(callee.property.name);\n }\n if (callee.type === 'CallExpression') {\n const inner = callee.callee;\n if (inner.type !== 'MemberExpression') return false;\n if (inner.object.type !== 'Identifier') return false;\n if (inner.object.name !== 'test' && inner.object.name !== 'it')\n return false;\n return (\n inner.property.type === 'Identifier' && inner.property.name === 'each'\n );\n }\n return false;\n}\n\nfunction insideTestCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.getSourceCode().getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isTestCallExpression(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require doc.story(title) to be called inside a test/it callback in Jest.',\n recommended: true,\n },\n schema: [],\n messages: {\n requireTest:\n \"doc.story(title) must be called inside a test/it callback (e.g. it('...', () => { doc.story('Title'); ... })).\",\n requireTitle: 'doc.story(title) requires a title argument.',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const testCallbackNames = new Set<string>();\n const pendingDocStoryCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.getSourceCode().getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { run() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n if (node.source.value === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isTestCallExpression(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n testCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.run\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n testCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isDocStoryCall(node)) return;\n\n if (node.arguments.length === 0) {\n context.report({ node, messageId: 'requireTitle' });\n return;\n }\n if (node.arguments.length >= 2) return;\n\n if (insideTestCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingDocStoryCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingDocStoryCalls) {\n if (\n containingFunctionName &&\n testCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireTest' });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import type { ESLint, Linter } from 'eslint';\nimport requireStoryContextForSteps from './rules/require-story-context-for-steps.js';\nimport requireTestContextForDocStory from './rules/require-test-context-for-doc-story.js';\n\nconst rules = {\n 'require-story-context-for-steps': requireStoryContextForSteps,\n 'require-test-context-for-doc-story': requireTestContextForDocStory,\n};\n\nconst configs: Record<string, Linter.Config[]> = {\n recommended: [\n {\n plugins: {\n 'executable-stories-jest': { rules },\n },\n rules: {\n 'executable-stories-jest/require-story-context-for-steps': 'error',\n 'executable-stories-jest/require-test-context-for-doc-story': 'error',\n },\n },\n ],\n};\n\nconst plugin: ESLint.Plugin = {\n meta: {\n name: 'eslint-plugin-executable-stories-jest',\n version: '0.1.0',\n },\n rules,\n configs,\n};\n\nexport default plugin;\nexport { rules, configs };\n"],"mappings":"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","names":["isFunction","isFunctionNode","V1_PACKAGE","isDocStoryCall","rule"]}
|
|
1
|
+
{"version":3,"sources":["../src/rules/require-story-context-for-steps.ts","../src/rules/require-test-context-for-doc-story.ts","../src/index.ts"],"sourcesContent":["import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\n/** Current API uses story.given() etc. inside test(); no top-level given/when/then. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nconst STEP_NAMES = new Set([\n 'given',\n 'when',\n 'then',\n 'and',\n 'but',\n 'arrange',\n 'act',\n 'assert',\n 'setup',\n 'context',\n 'execute',\n 'action',\n 'verify',\n]);\n\nconst STORY_MODIFIERS = new Set(['skip', 'only']);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return callee.name === 'story';\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier' || callee.object.name !== 'story')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STORY_MODIFIERS.has(callee.property.name)\n );\n}\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isStepCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') return STEP_NAMES.has(callee.name);\n if (callee.type !== 'MemberExpression') return false;\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'steps' && callee.object.name !== 'step')\n return false;\n return (\n callee.property.type === 'Identifier' &&\n STEP_NAMES.has(callee.property.name)\n );\n}\n\nfunction insideStoryCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.sourceCode.getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isStoryCall(ancestor) && !isDocStoryCall(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require step functions (given/when/then/and/but and aliases) to be called inside story() or doc.story(..., callback).',\n recommended: true,\n },\n schema: [],\n messages: {\n requireStory:\n 'Step functions must be called inside story(...) (or doc.story(..., callback)).',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const storyCallbackNames = new Set<string>();\n const pendingStepCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.sourceCode.getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { define() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n const pkg = node.source.value;\n if (typeof pkg === 'string' && pkg === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isStoryCall(node) || isDocStoryCall(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n storyCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.define\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n storyCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isStepCall(node)) return;\n if (insideStoryCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingStepCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingStepCalls) {\n if (\n containingFunctionName &&\n storyCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireStory' });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import type { Rule } from 'eslint';\nimport type {\n ArrowFunctionExpression,\n CallExpression,\n FunctionDeclaration,\n FunctionExpression,\n Node,\n Property,\n VariableDeclarator,\n} from 'estree';\n\nconst TEST_MODIFIERS = new Set([\n 'only',\n 'skip',\n 'todo',\n 'concurrent',\n 'failing',\n]);\n\nfunction isFunction(node: Node): boolean {\n return (\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\nfunction isFunctionNode(\n node: Node,\n): node is FunctionDeclaration | ArrowFunctionExpression | FunctionExpression {\n return (\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression'\n );\n}\n\n/** Legacy doc.story() is not used; current API uses story.init() inside it/test. */\nconst V1_PACKAGE = 'executable-stories-jest';\n\nfunction isDocStoryCall(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type !== 'MemberExpression') return false;\n return (\n callee.object.type === 'Identifier' &&\n callee.object.name === 'doc' &&\n callee.property.type === 'Identifier' &&\n callee.property.name === 'story'\n );\n}\n\nfunction isTestCallExpression(node: CallExpression): boolean {\n const { callee } = node;\n if (callee.type === 'Identifier') {\n return callee.name === 'test' || callee.name === 'it';\n }\n if (callee.type === 'MemberExpression') {\n if (callee.object.type !== 'Identifier') return false;\n if (callee.object.name !== 'test' && callee.object.name !== 'it')\n return false;\n if (callee.property.type !== 'Identifier') return false;\n return TEST_MODIFIERS.has(callee.property.name);\n }\n if (callee.type === 'CallExpression') {\n const inner = callee.callee;\n if (inner.type !== 'MemberExpression') return false;\n if (inner.object.type !== 'Identifier') return false;\n if (inner.object.name !== 'test' && inner.object.name !== 'it')\n return false;\n return (\n inner.property.type === 'Identifier' && inner.property.name === 'each'\n );\n }\n return false;\n}\n\nfunction insideTestCallback(\n node: CallExpression,\n context: Rule.RuleContext,\n): boolean {\n const ancestors = context.sourceCode.getAncestors(node);\n const functionAncestors = new Set(ancestors.filter(isFunction));\n\n for (const ancestor of ancestors) {\n if (ancestor.type !== 'CallExpression') continue;\n if (!isTestCallExpression(ancestor)) continue;\n for (const arg of ancestor.arguments) {\n if (arg && typeof arg === 'object' && functionAncestors.has(arg)) {\n return true;\n }\n }\n }\n return false;\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: {\n description:\n 'Require doc.story(title) to be called inside a test/it callback in Jest.',\n recommended: true,\n },\n schema: [],\n messages: {\n requireTest:\n \"doc.story(title) must be called inside a test/it callback (e.g. it('...', () => { doc.story('Title'); ... })).\",\n requireTitle: 'doc.story(title) requires a title argument.',\n },\n },\n create(context) {\n let hasV1Import = false;\n const namedFunctions = new Map<string, Node>();\n const testCallbackNames = new Set<string>();\n const pendingDocStoryCalls: Array<{\n node: CallExpression;\n containingFunctionName: string | null;\n }> = [];\n\n function getContainingFunctionName(node: CallExpression): string | null {\n const ancestors = context.sourceCode.getAncestors(node);\n for (let i = ancestors.length - 1; i >= 0; i--) {\n const ancestor = ancestors[i];\n if (ancestor.type === 'FunctionDeclaration' && ancestor.id) {\n return ancestor.id.name;\n }\n if (ancestor.type === 'VariableDeclarator') {\n const declarator = ancestor as VariableDeclarator;\n if (\n declarator.id.type === 'Identifier' &&\n declarator.init &&\n isFunctionNode(declarator.init)\n ) {\n return declarator.id.name;\n }\n }\n // Check for object method definitions\n if (ancestor.type === 'Property') {\n const prop = ancestor as Property;\n if (\n prop.key.type === 'Identifier' &&\n prop.value &&\n isFunctionNode(prop.value)\n ) {\n return prop.key.name;\n }\n // Shorthand method syntax: { run() {} }\n if (prop.key.type === 'Identifier' && prop.method) {\n return prop.key.name;\n }\n }\n }\n return null;\n }\n\n return {\n ImportDeclaration(node) {\n if (node.source.value === V1_PACKAGE) {\n hasV1Import = true;\n }\n },\n FunctionDeclaration(node: FunctionDeclaration) {\n if (node.id) {\n namedFunctions.set(node.id.name, node);\n }\n },\n VariableDeclarator(node: VariableDeclarator) {\n if (\n node.id.type === 'Identifier' &&\n node.init &&\n isFunctionNode(node.init)\n ) {\n namedFunctions.set(node.id.name, node.init);\n }\n },\n CallExpression(node: CallExpression) {\n if (!hasV1Import) return;\n\n if (isTestCallExpression(node)) {\n for (const arg of node.arguments) {\n if (arg.type === 'Identifier') {\n testCallbackNames.add(arg.name);\n }\n // Handle member expression callbacks like handlers.run\n if (\n arg.type === 'MemberExpression' &&\n arg.property.type === 'Identifier'\n ) {\n testCallbackNames.add(arg.property.name);\n }\n }\n return;\n }\n\n if (!isDocStoryCall(node)) return;\n\n if (node.arguments.length === 0) {\n context.report({ node, messageId: 'requireTitle' });\n return;\n }\n if (node.arguments.length >= 2) return;\n\n if (insideTestCallback(node, context)) return;\n\n const containingFunctionName = getContainingFunctionName(node);\n pendingDocStoryCalls.push({ node, containingFunctionName });\n },\n 'Program:exit'() {\n for (const { node, containingFunctionName } of pendingDocStoryCalls) {\n if (\n containingFunctionName &&\n testCallbackNames.has(containingFunctionName)\n ) {\n continue;\n }\n context.report({ node, messageId: 'requireTest' });\n }\n },\n };\n },\n};\n\nexport default rule;\n","import type { ESLint, Linter } from 'eslint';\nimport requireStoryContextForSteps from './rules/require-story-context-for-steps.js';\nimport requireTestContextForDocStory from './rules/require-test-context-for-doc-story.js';\n\nconst rules = {\n 'require-story-context-for-steps': requireStoryContextForSteps,\n 'require-test-context-for-doc-story': requireTestContextForDocStory,\n};\n\nconst configs: Record<string, Linter.Config[]> = {\n recommended: [\n {\n plugins: {\n 'executable-stories-jest': { rules },\n },\n rules: {\n 'executable-stories-jest/require-story-context-for-steps': 'error',\n 'executable-stories-jest/require-test-context-for-doc-story': 'error',\n },\n },\n ],\n};\n\nconst plugin: ESLint.Plugin = {\n meta: {\n name: 'eslint-plugin-executable-stories-jest',\n version: '0.1.0',\n },\n rules,\n configs,\n};\n\nexport default plugin;\nexport { rules, configs };\n"],"mappings":"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","names":["isFunction","isFunctionNode","V1_PACKAGE","isDocStoryCall","rule"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-executable-stories-jest",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ESLint rules for executable-stories-jest: step context, doc.story in test/it",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/eslint": "^9.6.1",
|
|
40
40
|
"@types/estree": "^1.0.8",
|
|
41
|
-
"@types/node": "^25.
|
|
42
|
-
"eslint": "^
|
|
41
|
+
"@types/node": "^25.3.0",
|
|
42
|
+
"eslint": "^10.0.1",
|
|
43
43
|
"tsup": "^8.5.1",
|
|
44
44
|
"typescript": "^5.9.3",
|
|
45
45
|
"vitest": "^4.0.18",
|
|
46
|
-
"eslint-config-executable-stories": "0.
|
|
46
|
+
"eslint-config-executable-stories": "0.2.0"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
49
|
"node": ">=22"
|