use-storybook-expect.js 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. "use strict";
  2. /**
  3. * @fileoverview Use expect from '@storybook/jest'
  4. * @author Yann Braga
  5. */
  6. const constants_1 = require("../utils/constants");
  7. const ast_1 = require("../utils/ast");
  8. const create_storybook_rule_1 = require("../utils/create-storybook-rule");
  9. module.exports = (0, create_storybook_rule_1.createStorybookRule)({
  10. name: 'use-storybook-expect',
  11. defaultOptions: [],
  12. meta: {
  13. type: 'suggestion',
  14. fixable: 'code',
  15. hasSuggestions: true,
  16. schema: [],
  17. docs: {
  18. description: 'Use expect from `@storybook/jest`',
  19. categories: [constants_1.CategoryId.ADDON_INTERACTIONS, constants_1.CategoryId.RECOMMENDED],
  20. recommended: 'error',
  21. },
  22. messages: {
  23. updateImports: 'Update imports',
  24. useExpectFromStorybook: 'Do not use expect from jest directly in the story. You should use from `@storybook/jest` instead.',
  25. },
  26. },
  27. create(context) {
  28. // variables should be defined here
  29. //----------------------------------------------------------------------
  30. // Helpers
  31. //----------------------------------------------------------------------
  32. const isExpectFromStorybookImported = (node) => {
  33. const { value: packageName } = node.source;
  34. const usesExpectFromStorybook = packageName === '@storybook/jest' || packageName === '@storybook/test';
  35. return (usesExpectFromStorybook &&
  36. node.specifiers.find((spec) => (0, ast_1.isImportSpecifier)(spec) && spec.imported.name === 'expect'));
  37. };
  38. //----------------------------------------------------------------------
  39. // Public
  40. //----------------------------------------------------------------------
  41. let isImportingFromStorybookExpect = false;
  42. const expectInvocations = [];
  43. return {
  44. ImportDeclaration(node) {
  45. if (isExpectFromStorybookImported(node)) {
  46. isImportingFromStorybookExpect = true;
  47. }
  48. },
  49. CallExpression(node) {
  50. if (!(0, ast_1.isIdentifier)(node.callee)) {
  51. return null;
  52. }
  53. if (node.callee.name === 'expect') {
  54. expectInvocations.push(node.callee);
  55. }
  56. },
  57. 'Program:exit': function () {
  58. if (!isImportingFromStorybookExpect && expectInvocations.length) {
  59. expectInvocations.forEach((node) => {
  60. context.report({
  61. node,
  62. messageId: 'useExpectFromStorybook',
  63. fix: function (fixer) {
  64. return fixer.insertTextAfterRange([0, 0], "import { expect } from '@storybook/jest';\n");
  65. },
  66. suggest: [
  67. {
  68. messageId: 'updateImports',
  69. fix: function (fixer) {
  70. return fixer.insertTextAfterRange([0, 0], "import { expect } from '@storybook/jest';\n");
  71. },
  72. },
  73. ],
  74. });
  75. });
  76. }
  77. },
  78. };
  79. },
  80. });