eslint-plugin-storybook 0.4.2 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # v0.5.0 (Tue Nov 23 2021)
2
+
3
+ #### 🚀 Enhancement
4
+
5
+ - Rule: pass context when invoking play [#53](https://github.com/storybookjs/eslint-plugin-storybook/pull/53) ([@yannbf](https://github.com/yannbf))
6
+
7
+ #### Authors: 1
8
+
9
+ - Yann Braga ([@yannbf](https://github.com/yannbf))
10
+
11
+ ---
12
+
1
13
  # v0.4.2 (Fri Nov 19 2021)
2
14
 
3
15
  #### 🐛 Bug Fix
package/README.md CHANGED
@@ -96,19 +96,20 @@ This plugin does not support MDX files.
96
96
 
97
97
  **Configurations**: csf, csf-strict, addon-interactions, recommended
98
98
 
99
- | Name | Description | 🔧 | Included in configurations |
100
- | ------------------------------------------------------------------------------------------ | --------------------------------------------------- | --- | -------------------------------------------------------- |
101
- | [`storybook/await-interactions`](./docs/rules/await-interactions.md) | Interactions should be awaited | 🔧 | <ul><li>addon-interactions</li><li>recommended</li></ul> |
102
- | [`storybook/csf-component`](./docs/rules/csf-component.md) | The component property should be set | | <ul><li>csf</li></ul> |
103
- | [`storybook/default-exports`](./docs/rules/default-exports.md) | Story files should have a default export | 🔧 | <ul><li>csf</li><li>recommended</li></ul> |
104
- | [`storybook/hierarchy-separator`](./docs/rules/hierarchy-separator.md) | Deprecated hierachy separator in title property | 🔧 | <ul><li>csf</li><li>recommended</li></ul> |
105
- | [`storybook/no-redundant-story-name`](./docs/rules/no-redundant-story-name.md) | A story should not have a redundant name property | 🔧 | <ul><li>csf</li><li>recommended</li></ul> |
106
- | [`storybook/no-stories-of`](./docs/rules/no-stories-of.md) | storiesOf is deprecated and should not be used | | <ul><li>csf-strict</li></ul> |
107
- | [`storybook/no-title-property-in-meta`](./docs/rules/no-title-property-in-meta.md) | Do not define a title in meta | 🔧 | <ul><li>csf-strict</li></ul> |
108
- | [`storybook/prefer-pascal-case`](./docs/rules/prefer-pascal-case.md) | Stories should use PascalCase | 🔧 | <ul><li>recommended</li></ul> |
109
- | [`storybook/story-exports`](./docs/rules/story-exports.md) | A story file must contain at least one story export | 🔧 | <ul><li>recommended</li><li>csf</li></ul> |
110
- | [`storybook/use-storybook-expect`](./docs/rules/use-storybook-expect.md) | Use expect from `@storybook/jest` | 🔧 | <ul><li>addon-interactions</li><li>recommended</li></ul> |
111
- | [`storybook/use-storybook-testing-library`](./docs/rules/use-storybook-testing-library.md) | Do not use testing-library directly on stories | 🔧 | <ul><li>addon-interactions</li><li>recommended</li></ul> |
99
+ | Name | Description | 🔧 | Included in configurations |
100
+ | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------- | --- | -------------------------------------------------------- |
101
+ | [`storybook/await-interactions`](./docs/rules/await-interactions.md) | Interactions should be awaited | 🔧 | <ul><li>addon-interactions</li><li>recommended</li></ul> |
102
+ | [`storybook/context-in-play-function`](./docs/rules/context-in-play-function.md) | Pass a context when invoking play function of another story | | <ul><li>recommended</li><li>addon-interactions</li></ul> |
103
+ | [`storybook/csf-component`](./docs/rules/csf-component.md) | The component property should be set | | <ul><li>csf</li></ul> |
104
+ | [`storybook/default-exports`](./docs/rules/default-exports.md) | Story files should have a default export | 🔧 | <ul><li>csf</li><li>recommended</li></ul> |
105
+ | [`storybook/hierarchy-separator`](./docs/rules/hierarchy-separator.md) | Deprecated hierachy separator in title property | 🔧 | <ul><li>csf</li><li>recommended</li></ul> |
106
+ | [`storybook/no-redundant-story-name`](./docs/rules/no-redundant-story-name.md) | A story should not have a redundant name property | 🔧 | <ul><li>csf</li><li>recommended</li></ul> |
107
+ | [`storybook/no-stories-of`](./docs/rules/no-stories-of.md) | storiesOf is deprecated and should not be used | | <ul><li>csf-strict</li></ul> |
108
+ | [`storybook/no-title-property-in-meta`](./docs/rules/no-title-property-in-meta.md) | Do not define a title in meta | 🔧 | <ul><li>csf-strict</li></ul> |
109
+ | [`storybook/prefer-pascal-case`](./docs/rules/prefer-pascal-case.md) | Stories should use PascalCase | 🔧 | <ul><li>recommended</li></ul> |
110
+ | [`storybook/story-exports`](./docs/rules/story-exports.md) | A story file must contain at least one story export | 🔧 | <ul><li>recommended</li><li>csf</li></ul> |
111
+ | [`storybook/use-storybook-expect`](./docs/rules/use-storybook-expect.md) | Use expect from `@storybook/jest` | 🔧 | <ul><li>addon-interactions</li><li>recommended</li></ul> |
112
+ | [`storybook/use-storybook-testing-library`](./docs/rules/use-storybook-testing-library.md) | Do not use testing-library directly on stories | 🔧 | <ul><li>addon-interactions</li><li>recommended</li></ul> |
112
113
 
113
114
  <!-- RULES-LIST:END -->
114
115
 
@@ -7,6 +7,7 @@ module.exports = {
7
7
  rules: {
8
8
  'import/no-anonymous-default-export': 'off',
9
9
  'storybook/await-interactions': 'error',
10
+ 'storybook/context-in-play-function': 'error',
10
11
  'storybook/use-storybook-expect': 'error',
11
12
  'storybook/use-storybook-testing-library': 'error',
12
13
  },
@@ -7,6 +7,7 @@ module.exports = {
7
7
  rules: {
8
8
  'import/no-anonymous-default-export': 'off',
9
9
  'storybook/await-interactions': 'error',
10
+ 'storybook/context-in-play-function': 'error',
10
11
  'storybook/default-exports': 'error',
11
12
  'storybook/hierarchy-separator': 'warn',
12
13
  'storybook/no-redundant-story-name': 'warn',
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Pass a context object when invoking a play function
4
+ * @author Yann Braga
5
+ */
6
+ const create_storybook_rule_1 = require("../utils/create-storybook-rule");
7
+ const constants_1 = require("../utils/constants");
8
+ const ast_1 = require("../utils/ast");
9
+ module.exports = (0, create_storybook_rule_1.createStorybookRule)({
10
+ name: 'context-in-play-function',
11
+ defaultOptions: [],
12
+ meta: {
13
+ type: 'problem',
14
+ docs: {
15
+ description: 'Pass a context when invoking play function of another story',
16
+ categories: [constants_1.CategoryId.RECOMMENDED, constants_1.CategoryId.ADDON_INTERACTIONS],
17
+ recommended: 'error',
18
+ },
19
+ messages: {
20
+ passContextToPlayFunction: 'Pass a context when invoking play function of another story',
21
+ },
22
+ fixable: null,
23
+ schema: [],
24
+ },
25
+ create(context) {
26
+ // variables should be defined here
27
+ //----------------------------------------------------------------------
28
+ // Helpers
29
+ //----------------------------------------------------------------------
30
+ // any helper functions should go here or else delete this section
31
+ const isPlayFunctionFromAnotherStory = (expr) => {
32
+ if ((0, ast_1.isTSNonNullExpression)(expr.callee) &&
33
+ (0, ast_1.isMemberExpression)(expr.callee.expression) &&
34
+ (0, ast_1.isIdentifier)(expr.callee.expression.property) &&
35
+ expr.callee.expression.property.name === 'play') {
36
+ return true;
37
+ }
38
+ if ((0, ast_1.isMemberExpression)(expr.callee) &&
39
+ (0, ast_1.isIdentifier)(expr.callee.property) &&
40
+ expr.callee.property.name === 'play') {
41
+ return true;
42
+ }
43
+ return false;
44
+ };
45
+ // Expression passing an argument called context OR spreading a variable called context
46
+ const isNotPassingContextCorrectly = (expr) => {
47
+ const firstExpressionArgument = expr.arguments[0];
48
+ if (!firstExpressionArgument) {
49
+ return true;
50
+ }
51
+ if (expr.arguments.length === 1 &&
52
+ (0, ast_1.isIdentifier)(firstExpressionArgument) &&
53
+ firstExpressionArgument.name === 'context') {
54
+ return false;
55
+ }
56
+ if ((0, ast_1.isObjectExpression)(firstExpressionArgument) &&
57
+ firstExpressionArgument.properties.some((prop) => {
58
+ return ((0, ast_1.isSpreadElement)(prop) && (0, ast_1.isIdentifier)(prop.argument) && prop.argument.name === 'context');
59
+ })) {
60
+ return false;
61
+ }
62
+ return true;
63
+ };
64
+ //----------------------------------------------------------------------
65
+ // Public
66
+ //----------------------------------------------------------------------
67
+ let invocationsWithoutProperContext = [];
68
+ return {
69
+ CallExpression(node) {
70
+ if (isPlayFunctionFromAnotherStory(node) && isNotPassingContextCorrectly(node)) {
71
+ invocationsWithoutProperContext.push(node);
72
+ }
73
+ },
74
+ 'Program:exit': function () {
75
+ invocationsWithoutProperContext.forEach((node) => {
76
+ context.report({
77
+ node,
78
+ messageId: 'passContextToPlayFunction',
79
+ });
80
+ });
81
+ },
82
+ };
83
+ },
84
+ });
package/dist/utils/ast.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isTSNonNullExpression = exports.isTSAsExpression = exports.isTSInterfaceDeclaration = exports.isTSTypeAliasDeclaration = exports.isProgram = exports.isFunctionExpression = exports.isReturnStatement = exports.isProperty = exports.isObjectPattern = exports.isObjectExpression = exports.isNewExpression = exports.isMemberExpression = exports.isLiteral = exports.isJSXAttribute = exports.isImportSpecifier = exports.isImportNamespaceSpecifier = exports.isImportDefaultSpecifier = exports.isImportDeclaration = exports.isSequenceExpression = exports.isAssignmentExpression = exports.isVariableDeclaration = exports.isExpressionStatement = exports.isCallExpression = exports.isBlockStatement = exports.isArrowFunctionExpression = exports.isArrayExpression = exports.isVariableDeclarator = exports.isIdentifier = exports.isAwaitExpression = exports.ASTUtils = void 0;
3
+ exports.isTSNonNullExpression = exports.isTSAsExpression = exports.isTSInterfaceDeclaration = exports.isTSTypeAliasDeclaration = exports.isProgram = exports.isFunctionExpression = exports.isReturnStatement = exports.isSpreadElement = exports.isProperty = exports.isObjectPattern = exports.isObjectExpression = exports.isNewExpression = exports.isMemberExpression = exports.isLiteral = exports.isJSXAttribute = exports.isImportSpecifier = exports.isImportNamespaceSpecifier = exports.isImportDefaultSpecifier = exports.isImportDeclaration = exports.isSequenceExpression = exports.isAssignmentExpression = exports.isVariableDeclaration = exports.isExpressionStatement = exports.isCallExpression = exports.isBlockStatement = exports.isArrowFunctionExpression = exports.isArrayExpression = exports.isVariableDeclarator = exports.isIdentifier = exports.isAwaitExpression = exports.ASTUtils = void 0;
4
4
  const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
5
5
  var experimental_utils_2 = require("@typescript-eslint/experimental-utils");
6
6
  Object.defineProperty(exports, "ASTUtils", { enumerable: true, get: function () { return experimental_utils_2.ASTUtils; } });
@@ -27,6 +27,7 @@ exports.isNewExpression = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.NewEx
27
27
  exports.isObjectExpression = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.ObjectExpression);
28
28
  exports.isObjectPattern = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.ObjectPattern);
29
29
  exports.isProperty = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.Property);
30
+ exports.isSpreadElement = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.SpreadElement);
30
31
  exports.isReturnStatement = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.ReturnStatement);
31
32
  exports.isFunctionExpression = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.FunctionExpression);
32
33
  exports.isProgram = isNodeOfType(experimental_utils_1.AST_NODE_TYPES.Program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-storybook",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Best practice rules for Storybook",
5
5
  "keywords": [
6
6
  "eslint",
@@ -71,7 +71,6 @@
71
71
  "ts-jest": "^27.0.7",
72
72
  "ts-migrate": "^0.1.26",
73
73
  "ts-node": "^10.4.0",
74
- "tsc": "^2.0.3",
75
74
  "typescript": "^4.4.4"
76
75
  },
77
76
  "engines": {