diff --git a/.vscode/launch.json b/.vscode/launch.json index afb9e5b34..edac37cca 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -183,7 +183,7 @@ "name": "jest testing", "program": "${workspaceFolder}/node_modules/.bin/jest", "cwd": "${workspaceFolder}/core/jest-testing", - "args": ["react-story"], + "args": ["react-link"], "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", "disableOptimisticBPs": true, diff --git a/core/jest-testing/README.md b/core/jest-testing/README.md index abe63bd63..5e7068e58 100644 --- a/core/jest-testing/README.md +++ b/core/jest-testing/README.md @@ -9,5 +9,5 @@ Given a file name, retrives the jest tests and associated results. This package is usually installed as part of the @component-controls package, but you can also install it standalone: ```bash -$ npm install @component-controls/jest-collector --save-dev +$ npm install @component-controls/jest-testing --save-dev ``` diff --git a/core/jest-testing/test/fixtures/story/__jest-tmp-1/jest.config.js b/core/jest-testing/test/fixtures/simple/__jest-tmp-2/jest.config.js similarity index 100% rename from core/jest-testing/test/fixtures/story/__jest-tmp-1/jest.config.js rename to core/jest-testing/test/fixtures/simple/__jest-tmp-2/jest.config.js diff --git a/core/test-renderers/.babelrc b/core/test-renderers/.babelrc new file mode 100644 index 000000000..2d6197779 --- /dev/null +++ b/core/test-renderers/.babelrc @@ -0,0 +1,14 @@ +{ + "presets": [ + "@babel/preset-typescript", + [ + "@babel/preset-env", + { + "targets": { + "node": "current" + } + } + ], + "@babel/preset-react" + ] +} diff --git a/core/test-renderers/.eslintignore b/core/test-renderers/.eslintignore new file mode 100644 index 000000000..d44b137bb --- /dev/null +++ b/core/test-renderers/.eslintignore @@ -0,0 +1,2 @@ +dist +test/fixtures/ \ No newline at end of file diff --git a/core/test-renderers/LICENSE.md b/core/test-renderers/LICENSE.md new file mode 100644 index 000000000..a64cf9401 --- /dev/null +++ b/core/test-renderers/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Atanas Stoyanov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/core/test-renderers/README.md b/core/test-renderers/README.md new file mode 100644 index 000000000..819e0b06f --- /dev/null +++ b/core/test-renderers/README.md @@ -0,0 +1,13 @@ +# Table of contents + +# Overview + +A collection of test renderers for react + +# Installation + +This package is usually installed as part of the @component-controls package, but you can also install it standalone: + +```bash +$ npm install @component-controls/test-renderers --save-dev +``` diff --git a/core/test-renderers/package.json b/core/test-renderers/package.json new file mode 100644 index 000000000..4e454ccaa --- /dev/null +++ b/core/test-renderers/package.json @@ -0,0 +1,72 @@ +{ + "name": "@component-controls/test-renderers", + "version": "3.4.5", + "description": "React test renderers: rtl, rtr and enzyme", + "keywords": [ + "react", + "react-testing-library", + "react-test-renderer", + "enzyme", + "testing" + ], + "main": "dist/index.js", + "module": "dist/index.esm.js", + "typings": "dist/index.d.ts", + "files": [ + "dist/", + "package.json", + "README.md" + ], + "scripts": { + "build": "yarn cross-env NODE_ENV=production rollup -c", + "dev": "yarn cross-env NODE_ENV=development rollup -cw", + "docs": "ts-md", + "fix": "yarn lint --fix", + "lint": "yarn eslint . --ext mdx,ts,tsx", + "prepare": "yarn build", + "test": "yarn jest --passWithNoTests" + }, + "homepage": "https://github.com/ccontrols/component-controls", + "bugs": { + "url": "https://github.com/ccontrols/component-controls/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/ccontrols/component-controls.git", + "directory": "core/test-renderers" + }, + "license": "MIT", + "dependencies": { + "@component-controls/core": "^3.4.2", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^10.4.9", + "@wojtekmaj/enzyme-adapter-react-17": "^0.3.1", + "enzyme": "^3.11.0", + "enzyme-to-json": "^3.5.0", + "rc-util": "^5.0.7", + "react-test-renderer": "^16.13.1" + }, + "devDependencies": { + "@types/enzyme": "^3.10.5", + "@types/react-dom": "^16.9.8", + "@types/react-test-renderer": "^16.9.3", + "@types/testing-library__jest-dom": "^5.9.2", + "jest": "^26.4.2", + "react-dom": "^16.13.1", + "typescript": "^4.0.5" + }, + "publishConfig": { + "access": "public" + }, + "authors": [ + "Atanas Stoyanov" + ], + "jest": { + "testEnvironment": "node", + "preset": "ts-jest", + "roots": [ + "./test" + ] + }, + "gitHead": "e30d62f101e104711a16261fce04785d58cac1eb" +} diff --git a/core/test-renderers/rollup.config.js b/core/test-renderers/rollup.config.js new file mode 100644 index 000000000..ba1c61c86 --- /dev/null +++ b/core/test-renderers/rollup.config.js @@ -0,0 +1,5 @@ +import { config } from '../../rollup-config'; + +export default config({ + input: ['./src/index.ts'], +}); diff --git a/plugins/jest-snapshots/src/renderers.ts b/core/test-renderers/src/index.ts similarity index 77% rename from plugins/jest-snapshots/src/renderers.ts rename to core/test-renderers/src/index.ts index f6cbe92ac..3bba870eb 100644 --- a/plugins/jest-snapshots/src/renderers.ts +++ b/core/test-renderers/src/index.ts @@ -1,7 +1,9 @@ import { render as reactTestRenderer } from './renderers/react-test-renderer'; import { render as enzymeReact16Renderer } from './renderers/enzyme-react-16'; import { render as rtlRenderer } from './renderers/react-testing-library'; -import { RendererFn } from './index'; +import { RendererFn, RendererFnResult, Json } from './types'; + +export { RendererFn, RendererFnResult, Json }; export const renderers: Record = { react: rtlRenderer, diff --git a/core/test-renderers/src/renderers/enzyme-react-16.ts b/core/test-renderers/src/renderers/enzyme-react-16.ts new file mode 100644 index 000000000..e1dfab469 --- /dev/null +++ b/core/test-renderers/src/renderers/enzyme-react-16.ts @@ -0,0 +1,22 @@ +import { mount, configure, ReactWrapper } from 'enzyme'; +import toJson from 'enzyme-to-json'; +import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import { RendererFn, RendererFnResult } from '../types'; + +configure({ adapter: new Adapter() }); + +export const render: RendererFn = async ( + { story, doc, config }, + options?: any, +): Promise<(RendererFnResult & Partial) | undefined> => { + const renderFn = config.renderFn; + if (renderFn) { + const rendered = renderFn(story, doc, config); + const component = mount(rendered, options); + return { + toJson: () => toJson(component, { mode: 'deep' }), + ...component, + }; + } + return undefined; +}; diff --git a/core/test-renderers/src/renderers/react-test-renderer.ts b/core/test-renderers/src/renderers/react-test-renderer.ts new file mode 100644 index 000000000..1748e2a4d --- /dev/null +++ b/core/test-renderers/src/renderers/react-test-renderer.ts @@ -0,0 +1,15 @@ +import renderer from 'react-test-renderer'; +import { RendererFn, RendererFnResult, Json } from '../types'; + +export const render: RendererFn = async ( + { story, doc, config }, + options, +): Promise<(RendererFnResult & renderer.ReactTestRenderer) | undefined> => { + const renderFn = config.renderFn; + if (renderFn) { + const rendered = renderFn(story, doc, config); + const component = renderer.create(rendered, options); + return { toJson: () => component.toJSON() as Json, ...component }; + } + return undefined; +}; diff --git a/core/test-renderers/src/renderers/react-testing-library.ts b/core/test-renderers/src/renderers/react-testing-library.ts new file mode 100644 index 000000000..034c99bab --- /dev/null +++ b/core/test-renderers/src/renderers/react-testing-library.ts @@ -0,0 +1,18 @@ +import { render as rtlRender, RenderResult } from '@testing-library/react'; +import { RendererFn, RendererFnResult } from '../types'; + +export const render: RendererFn = async ( + { story, doc, config }, + options?: any, +): Promise<(RendererFnResult & RenderResult) | undefined> => { + const renderFn = config.renderFn; + if (renderFn) { + const rendered = renderFn(story, doc, config); + const results = rtlRender(rendered, options); + return { + toJson: () => results.asFragment(), + ...results, + }; + } + return undefined; +}; diff --git a/core/test-renderers/src/types.ts b/core/test-renderers/src/types.ts new file mode 100644 index 000000000..46e479ab6 --- /dev/null +++ b/core/test-renderers/src/types.ts @@ -0,0 +1,18 @@ +import { Story, Document, RunConfiguration } from '@component-controls/core'; + +export type Json = + | { + type: string; + props?: { [key: string]: any }; + children: Array | null; + } + | DocumentFragment; + +export type RendererFnResult = { + toJson: () => Json | null; +}; + +export type RendererFn = ( + props: { story: Story; doc: Document; config: RunConfiguration }, + options?: any, +) => Promise; diff --git a/core/test-renderers/tsconfig.json b/core/test-renderers/tsconfig.json new file mode 100644 index 000000000..e946e49ee --- /dev/null +++ b/core/test-renderers/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "esnext", + "outDir": "dist", + "rootDir": "src", + "declaration": true, + "types": ["node", "jest"], + "typeRoots": ["../../node_modules/@types", "node_modules/@types"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules/**", "test/**"] +} diff --git a/examples/stories/src/tutorial/testing/jest-snapshots.mdx b/examples/stories/src/tutorial/testing/jest-snapshots.mdx index de034a4eb..84e8c855a 100644 --- a/examples/stories/src/tutorial/testing/jest-snapshots.mdx +++ b/examples/stories/src/tutorial/testing/jest-snapshots.mdx @@ -82,7 +82,7 @@ Using this approach, you will create a custom test file and use directly jest to ```js:title=stories.test.js const path = require('path'); -const { renderers } = require('@component-controls/jest-snapshots/renderers'); +const { renderers } = require('@component-controls/test-renderers'); const { runJestSnapshots } = require('@component-controls/jest-snapshots'); runJestSnapshots( @@ -105,7 +105,7 @@ A full list of the [compiler cli parameters](/tutorial/reference/cli#parameters) If the output folder is not specified, the bundle is located in the `public` folder ```js:title=stories.test.js -const { renderers } = require('@component-controls/jest-snapshots/renderers'); +const { renderers } = require('@component-controls/test-renderers'); const { runJestSnapshots } = require('@component-controls/jest-snapshots'); runJestSnapshots(renderers.enzyme); diff --git a/plugins/jest-snapshots/package.json b/plugins/jest-snapshots/package.json index ab474b638..2225623a7 100644 --- a/plugins/jest-snapshots/package.json +++ b/plugins/jest-snapshots/package.json @@ -17,8 +17,6 @@ "package.json", "args.js", "args.d.ts", - "renderers.js", - "renderers.d.ts", "README.md", "stories.test.js" ], @@ -45,25 +43,16 @@ "cc-jest": "./bin/index.js" }, "dependencies": { + "@component-controls/test-renderers": "^3.4.5", "@component-controls/store": "^3.4.5", "@component-controls/webpack-compile": "^3.4.5", "@component-controls/webpack-configs": "^3.4.5", - "@testing-library/jest-dom": "^5.11.4", - "@testing-library/react": "^10.4.9", - "@wojtekmaj/enzyme-adapter-react-17": "^0.3.1", - "enzyme": "^3.11.0", - "enzyme-to-json": "^3.5.0", "jest-cli": "^26.4.2", - "rc-util": "^5.0.7", - "react-test-renderer": "^16.13.1", "ts-jest": "^26.4.4" }, "devDependencies": { - "@types/enzyme": "^3.10.5", "@types/jest": "^26.0.10", "@types/react-dom": "^16.9.8", - "@types/react-test-renderer": "^16.9.3", - "@types/testing-library__jest-dom": "^5.9.2", "jest": "^26.4.2", "react-dom": "^16.13.1", "typescript": "^4.0.5" diff --git a/plugins/jest-snapshots/renderers.d.ts b/plugins/jest-snapshots/renderers.d.ts deleted file mode 100644 index d4d53c4f1..000000000 --- a/plugins/jest-snapshots/renderers.d.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './dist/renderers'; diff --git a/plugins/jest-snapshots/renderers.js b/plugins/jest-snapshots/renderers.js deleted file mode 100644 index ae2cd7cd9..000000000 --- a/plugins/jest-snapshots/renderers.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./dist/renderers'); diff --git a/plugins/jest-snapshots/rollup.config.js b/plugins/jest-snapshots/rollup.config.js index c3f4e421b..ae1d759b7 100644 --- a/plugins/jest-snapshots/rollup.config.js +++ b/plugins/jest-snapshots/rollup.config.js @@ -1,10 +1,5 @@ import { config } from '../../rollup-config'; export default config({ - input: [ - './src/index.ts', - './src/cli.ts', - './src/args.ts', - './src/renderers.ts', - ], + input: ['./src/index.ts', './src/cli.ts', './src/args.ts'], }); diff --git a/plugins/jest-snapshots/src/args.ts b/plugins/jest-snapshots/src/args.ts index 569b8f682..082a69f8c 100644 --- a/plugins/jest-snapshots/src/args.ts +++ b/plugins/jest-snapshots/src/args.ts @@ -1,5 +1,5 @@ import { ArgOptions } from '@component-controls/webpack-compile/cli'; -import { renderers } from './renderers'; +import { renderers } from '@component-controls/test-renderers'; export const jestCliArgs: ArgOptions = [ { diff --git a/plugins/jest-snapshots/src/index.ts b/plugins/jest-snapshots/src/index.ts index e8ce4f008..0de7ed5d8 100644 --- a/plugins/jest-snapshots/src/index.ts +++ b/plugins/jest-snapshots/src/index.ts @@ -1,21 +1,16 @@ import { loadStore } from '@component-controls/store'; +import { RendererFn } from '@component-controls/test-renderers'; import { getBundleName } from '@component-controls/webpack-compile'; -import { Store } from '@component-controls/core'; export type RendererFnResult = Promise | any; -export type RendererFn = ( - storyId: string, - store: Store, - options?: any, -) => Promise; - export const runJestSnapshots = ( renderer: RendererFn, bundleName?: string, ): void => { const bundle = bundleName || getBundleName(); const store = loadStore(require(bundle)); + const config = store.config; Object.keys(store.docs).forEach(docId => { const doc = store.docs[docId]; @@ -25,8 +20,8 @@ export const runJestSnapshots = ( stories.forEach(storyId => { const story = store.stories[storyId]; it(story.name, async () => { - const tree = await renderer(storyId, store); - expect(tree).toMatchSnapshot(); + const { toJson } = (await renderer({ story, doc, config })) || {}; + expect(toJson ? toJson() : undefined).toMatchSnapshot(); }); }); }); diff --git a/plugins/jest-snapshots/src/renderers/enzyme-react-16.ts b/plugins/jest-snapshots/src/renderers/enzyme-react-16.ts deleted file mode 100644 index b73afda2f..000000000 --- a/plugins/jest-snapshots/src/renderers/enzyme-react-16.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { mount, configure } from 'enzyme'; -import toJson from 'enzyme-to-json'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; - -import { Store } from '@component-controls/core'; -import { RendererFn } from '../index'; - -configure({ adapter: new Adapter() }); - -export const render: RendererFn = async ( - storyId: string, - store: Store, - options?: any, -) => { - const renderFn = store.config.renderFn; - if (renderFn) { - const story = store.stories[storyId]; - const doc = story?.doc ? store.docs[story?.doc] : undefined; - const rendered = renderFn(story, doc, options); - const component = mount(rendered); - return toJson(component, { mode: 'deep' }); - } - return undefined; -}; diff --git a/plugins/jest-snapshots/src/renderers/react-test-renderer.ts b/plugins/jest-snapshots/src/renderers/react-test-renderer.ts deleted file mode 100644 index faa1c75e6..000000000 --- a/plugins/jest-snapshots/src/renderers/react-test-renderer.ts +++ /dev/null @@ -1,19 +0,0 @@ -import renderer from 'react-test-renderer'; -import { Store } from '@component-controls/core'; -import { RendererFn } from '../index'; - -export const render: RendererFn = async ( - storyId: string, - store: Store, - options?: any, -) => { - const renderFn = store.config.renderFn; - if (renderFn) { - const story = store.stories[storyId]; - const doc = story?.doc ? store.docs[story?.doc] : undefined; - const rendered = renderFn(story, doc, options); - const component = renderer.create(rendered); - return component.toJSON(); - } - return undefined; -}; diff --git a/plugins/jest-snapshots/src/renderers/react-testing-library.ts b/plugins/jest-snapshots/src/renderers/react-testing-library.ts deleted file mode 100644 index ae04677d2..000000000 --- a/plugins/jest-snapshots/src/renderers/react-testing-library.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { render as rtlRender } from '@testing-library/react'; - -import { Store } from '@component-controls/core'; -import { RendererFn } from '../index'; - -export const render: RendererFn = async ( - storyId: string, - store: Store, - options?: any, -) => { - const renderFn = store.config.renderFn; - if (renderFn) { - const story = store.stories[storyId]; - const doc = story?.doc ? store.docs[story?.doc] : undefined; - - const rendered = renderFn(story, doc, options); - const { asFragment } = rtlRender(rendered); - return asFragment(); - } - return undefined; -}; diff --git a/plugins/jest-snapshots/stories.test.js b/plugins/jest-snapshots/stories.test.js index 9757dadc3..79dea672a 100644 --- a/plugins/jest-snapshots/stories.test.js +++ b/plugins/jest-snapshots/stories.test.js @@ -5,7 +5,7 @@ const { getBundleName } = require('@component-controls/webpack-compile'); const { cliArgs } = require('@component-controls/webpack-compile/cli'); const { jestCliArgs } = require('@component-controls/jest-snapshots/args'); -const { renderers } = require('@component-controls/jest-snapshots/renderers'); +const { renderers } = require('@component-controls/test-renderers'); const bundle = getBundleName(); const store = loadStore(require(bundle)); @@ -14,7 +14,7 @@ const args = cliArgs(jestCliArgs); const rendererName = args.parse().renderer; const renderer = renderers[rendererName]; - +const config = store.config; Object.keys(store.docs).forEach(docId => { const doc = store.docs[docId]; @@ -46,8 +46,8 @@ Object.keys(store.docs).forEach(docId => { const story = store.stories[storyId]; act(() => { it(story.name, async () => { - const tree = await renderer(storyId, store); - expect(tree).toMatchSnapshot(); + const { toJson } = (await renderer({ story, doc, config })) || {}; + expect(toJson ? toJson() : undefined).toMatchSnapshot(); }); }); }); diff --git a/plugins/jest-snapshots/test/stories.test.ts b/plugins/jest-snapshots/test/stories.test.ts index 40551e414..16b85d21f 100644 --- a/plugins/jest-snapshots/test/stories.test.ts +++ b/plugins/jest-snapshots/test/stories.test.ts @@ -1,4 +1,4 @@ -import { renderers } from '../src/renderers'; +import { renderers } from '@component-controls/test-renderers'; import { runJestSnapshots } from '../dist/index'; runJestSnapshots(renderers.enzyme);