From d1bba7232f33b7e1dbad72a162038a400beaccea Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 6 Oct 2022 18:11:17 +0200 Subject: [PATCH 1/9] add isTestRunner utility --- README.md | 31 ++++++++++++++++++++++++++++--- bin/test-storybook.js | 2 +- package.json | 1 + src/is-test-runner.ts | 13 +++++++++++++ src/setup-page.ts | 18 ++++++++++++++++-- 5 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 src/is-test-runner.ts diff --git a/README.md b/README.md index 52902649..8476f15a 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,9 @@ Storybook test runner turns all of your stories into executable tests. - [DOM snapshot recipe](#dom-snapshot-recipe) - [Image snapshot recipe](#image-snapshot-recipe) - [Render lifecycle](#render-lifecycle) - - [Global utility functions](#global-utility-functions) + - [Utility functions](#utility-functions) + - [getStoryContext](#getstorycontext) + - [isTestRunner](#istestrunner) - [Troubleshooting](#troubleshooting) - [The error output in the CLI is too short](#the-error-output-in-the-cli-is-too-short) - [The test runner seems flaky and keeps timing out](#the-test-runner-seems-flaky-and-keeps-timing-out) @@ -475,7 +477,11 @@ it('button--basic', async () => { }); ``` -### Global utility functions +### Utility functions + +For more specific use cases, the test runner provides utility functions that could be useful to you. + +#### getStoryContext While running tests using the hooks, you might want to get information from a story, such as the parameters passed to it, or its args. The test runner now provides a `getStoryContext` utility function that fetches the story context for the current story: @@ -506,7 +512,7 @@ module.exports = { // Apply story-level a11y rules await configureAxe(page, { rules: storyContext.parameters?.a11y?.config?.rules, - }) + }); // from Storybook 7.0 onwards, the selector should be #storybook-root await checkA11y(page, '#root', { @@ -521,6 +527,25 @@ module.exports = { }; ``` +#### isTestRunner + +The `isTestRunner` function can be used to determine if a story is rendering in the context of the test runner. + +```js +import { isTestRunner } from '@storybook/test-runner/is-test-runner'; +export const MyStory = () => ( +
+

Is this story running in the test runner?

+

{isTestRunner() ? 'Yes' : 'No'}

+
+); +``` + +The result of `isTestRunner()` will be true in the following scenarios: + +1. In the browser, when the story is rendered while running the test runner +2. In node, if you prepend your Storybook script with `STORYBOOK_TEST_RUNNER=true` + ## Troubleshooting #### The error output in the CLI is too short diff --git a/bin/test-storybook.js b/bin/test-storybook.js index c3b28c9e..63a0c93e 100755 --- a/bin/test-storybook.js +++ b/bin/test-storybook.js @@ -9,13 +9,13 @@ const fs = require('fs'); const dedent = require('ts-dedent').default; const path = require('path'); const tempy = require('tempy'); -const semver = require('semver'); const { getCliOptions, getStorybookMetadata } = require('../dist/cjs/util'); const { transformPlaywrightJson } = require('../dist/cjs/playwright/transformPlaywrightJson'); // Do this as the first thing so that any code reading it knows the right env. process.env.BABEL_ENV = 'test'; process.env.NODE_ENV = 'test'; +process.env.STORYBOOK_TEST_RUNNER = 'true'; process.env.PUBLIC_URL = ''; // Makes the script crash on unhandled rejections instead of silently diff --git a/package.json b/package.json index 8f89297a..85fa378a 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,7 @@ "jest-watch-typeahead": "^2.0.0", "node-fetch": "^2", "playwright": "^1.14.0", + "read-pkg-up": "^7.0.1", "regenerator-runtime": "^0.13.9", "semver": "^7.3.7", "tempy": "^1.0.1", diff --git a/src/is-test-runner.ts b/src/is-test-runner.ts new file mode 100644 index 00000000..eb546e12 --- /dev/null +++ b/src/is-test-runner.ts @@ -0,0 +1,13 @@ +/** + * Returns whether the story is rendering inside of the Storybook test runner. + */ +export function isTestRunner() { + const isTestRunnerInNode = process?.env?.STORYBOOK_TEST_RUNNER === 'true'; + const isTestRunnerInBrowser = !!( + typeof window !== 'undefined' && + window && + window.navigator.userAgent.match(/StorybookTestRunner/) + ); + + return isTestRunnerInNode || isTestRunnerInBrowser; +} diff --git a/src/setup-page.ts b/src/setup-page.ts index 5b73b688..520551ee 100644 --- a/src/setup-page.ts +++ b/src/setup-page.ts @@ -1,5 +1,5 @@ import type { Page } from 'playwright'; -import dedent from 'ts-dedent'; +import readPackageUp from 'read-pkg-up'; const sanitizeURL = (url: string) => { let finalURL = url; @@ -25,8 +25,9 @@ const sanitizeURL = (url: string) => { export const setupPage = async (page: Page) => { const targetURL = new URL('iframe.html', process.env.TARGET_URL).toString(); const viewMode = process.env.VIEW_MODE || 'story'; - const isCoverageMode = process.env.STORYBOOK_COLLECT_COVERAGE === 'true'; const renderedEvent = viewMode === 'docs' ? 'docsRendered' : 'storyRendered'; + const { packageJson } = await readPackageUp(); + const { version: testRunnerVersion } = packageJson; const referenceURL = process.env.REFERENCE_URL && sanitizeURL(process.env.REFERENCE_URL); const debugPrintLimit = process.env.DEBUG_PRINT_LIMIT @@ -102,6 +103,17 @@ export const setupPage = async (page: Page) => { return input; } + function addToUserAgent(extra) { + const originalUserAgent = globalThis.navigator.userAgent; + if (!originalUserAgent.includes(extra)) { + Object.defineProperty(globalThis.navigator, 'userAgent', { + get: function () { + return [originalUserAgent, extra].join(' '); + }, + }); + } + }; + class StorybookTestRunnerError extends Error { constructor(storyId, errorMessage, logs) { super(errorMessage); @@ -166,6 +178,8 @@ export const setupPage = async (page: Page) => { ); } + addToUserAgent(\`(StorybookTestRunner@${testRunnerVersion})\`); + // collect logs to show upon test error let logs = []; From b9238169081693d0cf4d2aada1936701ff42d615 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 6 Oct 2022 18:12:09 +0200 Subject: [PATCH 2/9] use isTestRunner in internal example --- .storybook/preview.js | 11 +++++++++++ stories/atoms/Button.stories.js | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 .storybook/preview.js diff --git a/.storybook/preview.js b/.storybook/preview.js new file mode 100644 index 00000000..ec14191d --- /dev/null +++ b/.storybook/preview.js @@ -0,0 +1,11 @@ +import { isTestRunner } from '../dist/esm/is-test-runner'; + +const withSkippableTests = (StoryFn, { parameters }) => { + if (parameters.test?.skip && isTestRunner()) { + return () => {}; + } + + return StoryFn(); +}; + +export const decorators = [withSkippableTests]; diff --git a/stories/atoms/Button.stories.js b/stories/atoms/Button.stories.js index f4295cbb..6ed5f608 100644 --- a/stories/atoms/Button.stories.js +++ b/stories/atoms/Button.stories.js @@ -1,5 +1,6 @@ import React from 'react'; import { expect } from '@storybook/jest'; +import { isTestRunner } from '../../dist/esm/is-test-runner'; import { within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/testing-library'; import { Button } from './Button'; @@ -109,3 +110,25 @@ WithLoaders.play = async ({ args, canvasElement }) => { await userEvent.click(todoItem); await expect(args.onSubmit).toHaveBeenCalledWith('delectus aut autem'); }; + +export const UserAgent = () => ( +
+

+ isTestRunner: {isTestRunner().toString()} +

+

+ User agent: {window.navigator.userAgent} +

+
+); +UserAgent.play = async () => { + if (isTestRunner()) { + await expect(window.navigator.userAgent).toContain('StorybookTestRunner'); + } +}; +UserAgent.parameters = { + tests: { + skip: true, + disableSnapshots: true, + }, +}; From 53a57494d8b0330f367c42a39c3bc9975dcd7a85 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Thu, 6 Oct 2022 22:17:49 +0200 Subject: [PATCH 3/9] update entry point for isTestRunner --- package.json | 23 ++++++++++++++----- src/is-test-runner/is-test-runner.cjs | 8 +++++++ .../is-test-runner.mjs} | 5 +--- 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 src/is-test-runner/is-test-runner.cjs rename src/{is-test-runner.ts => is-test-runner/is-test-runner.mjs} (58%) diff --git a/package.json b/package.json index 85fa378a..4832b66d 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,21 @@ "license": "MIT", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", - "types": "dist/ts/index.d.ts", + "exports": { + ".": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js", + "types": "./dist/ts/index.d.ts" + }, + "./is-test-runner": { + "import": "./dist/esm/is-test-runner.mjs", + "require": "./dist/cjs/is-test-runner.cjs" + }, + "./package.json": "./package.json" + }, + "bin": { + "test-storybook": "./bin/test-storybook.js" + }, "files": [ "bin", "dist/**/*", @@ -30,8 +44,8 @@ "scripts": { "clean": "rimraf ./dist", "buildBabel": "concurrently \"yarn buildBabel:cjs\" \"yarn buildBabel:esm\"", - "buildBabel:cjs": "babel ./src -d ./dist/cjs --extensions \".js,.jsx,.ts,.tsx\"", - "buildBabel:esm": "babel ./src -d ./dist/esm --env-name esm --extensions \".js,.jsx,.ts,.tsx\"", + "buildBabel:cjs": "babel ./src -d ./dist/cjs --extensions \".js,.jsx,.ts,.tsx,.cjs,.mjs\"", + "buildBabel:esm": "babel ./src -d ./dist/esm --env-name esm --extensions \".js,.jsx,.ts,.tsx,.cjs,.mjs\"", "buildTsc": "tsc --declaration --emitDeclarationOnly --outDir ./dist/ts", "prebuild": "yarn clean", "build": "concurrently \"yarn buildBabel\" \"yarn buildTsc\"", @@ -52,9 +66,6 @@ "generate-dynamic-stories": "node scripts/generate-dynamic-stories.js", "prepare": "husky install" }, - "bin": { - "test-storybook": "./bin/test-storybook.js" - }, "devDependencies": { "@auto-it/released": "^10.37.1", "@babel/cli": "^7.12.1", diff --git a/src/is-test-runner/is-test-runner.cjs b/src/is-test-runner/is-test-runner.cjs new file mode 100644 index 00000000..2bbabd78 --- /dev/null +++ b/src/is-test-runner/is-test-runner.cjs @@ -0,0 +1,8 @@ +/** + * Returns whether the story is rendering inside of the Storybook test runner. + */ +module.exports = { + isTestRunner: function () { + return process?.env?.STORYBOOK_TEST_RUNNER === 'true'; + } +} diff --git a/src/is-test-runner.ts b/src/is-test-runner/is-test-runner.mjs similarity index 58% rename from src/is-test-runner.ts rename to src/is-test-runner/is-test-runner.mjs index eb546e12..1907dec4 100644 --- a/src/is-test-runner.ts +++ b/src/is-test-runner/is-test-runner.mjs @@ -2,12 +2,9 @@ * Returns whether the story is rendering inside of the Storybook test runner. */ export function isTestRunner() { - const isTestRunnerInNode = process?.env?.STORYBOOK_TEST_RUNNER === 'true'; - const isTestRunnerInBrowser = !!( + return!!( typeof window !== 'undefined' && window && window.navigator.userAgent.match(/StorybookTestRunner/) ); - - return isTestRunnerInNode || isTestRunnerInBrowser; } From 4010e3ec381704fc6b5d3ae1e8626021c3a0d82f Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Thu, 6 Oct 2022 20:09:33 -0400 Subject: [PATCH 4/9] Fix paths to `isTestRunner` --- .storybook/preview.js | 2 +- package.json | 4 ++-- stories/atoms/Button.stories.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.storybook/preview.js b/.storybook/preview.js index ec14191d..eae7d2d5 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,4 +1,4 @@ -import { isTestRunner } from '../dist/esm/is-test-runner'; +import { isTestRunner } from '../dist/esm/is-test-runner/is-test-runner'; const withSkippableTests = (StoryFn, { parameters }) => { if (parameters.test?.skip && isTestRunner()) { diff --git a/package.json b/package.json index 4832b66d..474d21d3 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "types": "./dist/ts/index.d.ts" }, "./is-test-runner": { - "import": "./dist/esm/is-test-runner.mjs", - "require": "./dist/cjs/is-test-runner.cjs" + "import": "./dist/esm/is-test-runner/is-test-runner.js", + "require": "./dist/cjs/is-test-runner/is-test-runner.js" }, "./package.json": "./package.json" }, diff --git a/stories/atoms/Button.stories.js b/stories/atoms/Button.stories.js index 6ed5f608..b80c87f5 100644 --- a/stories/atoms/Button.stories.js +++ b/stories/atoms/Button.stories.js @@ -1,6 +1,6 @@ import React from 'react'; import { expect } from '@storybook/jest'; -import { isTestRunner } from '../../dist/esm/is-test-runner'; +import { isTestRunner } from '../../dist/esm/is-test-runner/is-test-runner'; import { within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/testing-library'; import { Button } from './Button'; From ffbab9c9db674f90d88a63140cf82283bcc25a57 Mon Sep 17 00:00:00 2001 From: Ian VanSchooten Date: Thu, 6 Oct 2022 20:39:38 -0400 Subject: [PATCH 5/9] Move to root for types/eslint --- .storybook/preview.js | 2 +- src/is-test-runner/is-test-runner.cjs => is-test-runner.cjs | 0 is-test-runner.d.ts | 1 + src/is-test-runner/is-test-runner.mjs => is-test-runner.mjs | 0 package.json | 5 +++-- stories/atoms/Button.stories.js | 2 +- 6 files changed, 6 insertions(+), 4 deletions(-) rename src/is-test-runner/is-test-runner.cjs => is-test-runner.cjs (100%) create mode 100644 is-test-runner.d.ts rename src/is-test-runner/is-test-runner.mjs => is-test-runner.mjs (100%) diff --git a/.storybook/preview.js b/.storybook/preview.js index eae7d2d5..7d9921dd 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,4 +1,4 @@ -import { isTestRunner } from '../dist/esm/is-test-runner/is-test-runner'; +import { isTestRunner } from '../is-test-runner'; const withSkippableTests = (StoryFn, { parameters }) => { if (parameters.test?.skip && isTestRunner()) { diff --git a/src/is-test-runner/is-test-runner.cjs b/is-test-runner.cjs similarity index 100% rename from src/is-test-runner/is-test-runner.cjs rename to is-test-runner.cjs diff --git a/is-test-runner.d.ts b/is-test-runner.d.ts new file mode 100644 index 00000000..e48091ab --- /dev/null +++ b/is-test-runner.d.ts @@ -0,0 +1 @@ +export declare const isTestRunner: () => boolean; diff --git a/src/is-test-runner/is-test-runner.mjs b/is-test-runner.mjs similarity index 100% rename from src/is-test-runner/is-test-runner.mjs rename to is-test-runner.mjs diff --git a/package.json b/package.json index 474d21d3..65bc55af 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,9 @@ "types": "./dist/ts/index.d.ts" }, "./is-test-runner": { - "import": "./dist/esm/is-test-runner/is-test-runner.js", - "require": "./dist/cjs/is-test-runner/is-test-runner.js" + "import": "./is-test-runner.mjs", + "require": "./is-test-runner.cjs", + "types": "./is-test-runner.d.ts" }, "./package.json": "./package.json" }, diff --git a/stories/atoms/Button.stories.js b/stories/atoms/Button.stories.js index b80c87f5..e2ac6151 100644 --- a/stories/atoms/Button.stories.js +++ b/stories/atoms/Button.stories.js @@ -1,6 +1,6 @@ import React from 'react'; import { expect } from '@storybook/jest'; -import { isTestRunner } from '../../dist/esm/is-test-runner/is-test-runner'; +import { isTestRunner } from '../../is-test-runner'; import { within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/testing-library'; import { Button } from './Button'; From 2a0c55589dae8db707e96890805a2665d53d318b Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 7 Oct 2022 11:25:07 +0200 Subject: [PATCH 6/9] undo exports map and simplify is-test-runner --- is-test-runner.cjs | 8 -------- is-test-runner.d.ts | 1 - is-test-runner.js | 19 +++++++++++++++++++ is-test-runner.mjs | 10 ---------- package.json | 18 +++--------------- 5 files changed, 22 insertions(+), 34 deletions(-) delete mode 100644 is-test-runner.cjs delete mode 100644 is-test-runner.d.ts create mode 100644 is-test-runner.js delete mode 100644 is-test-runner.mjs diff --git a/is-test-runner.cjs b/is-test-runner.cjs deleted file mode 100644 index 2bbabd78..00000000 --- a/is-test-runner.cjs +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Returns whether the story is rendering inside of the Storybook test runner. - */ -module.exports = { - isTestRunner: function () { - return process?.env?.STORYBOOK_TEST_RUNNER === 'true'; - } -} diff --git a/is-test-runner.d.ts b/is-test-runner.d.ts deleted file mode 100644 index e48091ab..00000000 --- a/is-test-runner.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const isTestRunner: () => boolean; diff --git a/is-test-runner.js b/is-test-runner.js new file mode 100644 index 00000000..c176480a --- /dev/null +++ b/is-test-runner.js @@ -0,0 +1,19 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { + value: true, +}); +exports.isTestRunner = isTestRunner; + +/** + * Returns whether the story is rendering inside of the Storybook test runner. + */ +function isTestRunner() { + const isTestRunnerInNode = process?.env?.STORYBOOK_TEST_RUNNER === 'true'; + const isTestRunnerInBrowser = !!( + typeof window !== 'undefined' && + window && + window.navigator.userAgent.match(/StorybookTestRunner/) + ); + return isTestRunnerInBrowser || isTestRunnerInNode; +} diff --git a/is-test-runner.mjs b/is-test-runner.mjs deleted file mode 100644 index 1907dec4..00000000 --- a/is-test-runner.mjs +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Returns whether the story is rendering inside of the Storybook test runner. - */ -export function isTestRunner() { - return!!( - typeof window !== 'undefined' && - window && - window.navigator.userAgent.match(/StorybookTestRunner/) - ); -} diff --git a/package.json b/package.json index 65bc55af..b017e276 100644 --- a/package.json +++ b/package.json @@ -18,19 +18,7 @@ "license": "MIT", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", - "exports": { - ".": { - "import": "./dist/esm/index.js", - "require": "./dist/cjs/index.js", - "types": "./dist/ts/index.d.ts" - }, - "./is-test-runner": { - "import": "./is-test-runner.mjs", - "require": "./is-test-runner.cjs", - "types": "./is-test-runner.d.ts" - }, - "./package.json": "./package.json" - }, + "types": "dist/ts/index.d.ts", "bin": { "test-storybook": "./bin/test-storybook.js" }, @@ -45,8 +33,8 @@ "scripts": { "clean": "rimraf ./dist", "buildBabel": "concurrently \"yarn buildBabel:cjs\" \"yarn buildBabel:esm\"", - "buildBabel:cjs": "babel ./src -d ./dist/cjs --extensions \".js,.jsx,.ts,.tsx,.cjs,.mjs\"", - "buildBabel:esm": "babel ./src -d ./dist/esm --env-name esm --extensions \".js,.jsx,.ts,.tsx,.cjs,.mjs\"", + "buildBabel:cjs": "babel ./src -d ./dist/cjs --extensions \".js,.jsx,.ts,.tsx\" --copy-files is-test-runner.js", + "buildBabel:esm": "babel ./src -d ./dist/esm --env-name esm --extensions \".js,.jsx,.ts,.tsx\" --copy-files is-test-runner.js", "buildTsc": "tsc --declaration --emitDeclarationOnly --outDir ./dist/ts", "prebuild": "yarn clean", "build": "concurrently \"yarn buildBabel\" \"yarn buildTsc\"", From 3a5249152adcb7d9f7d08f81644ce1e5d59ed12c Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 7 Oct 2022 11:31:39 +0200 Subject: [PATCH 7/9] update docs --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8476f15a..c8d13672 100644 --- a/README.md +++ b/README.md @@ -529,7 +529,7 @@ module.exports = { #### isTestRunner -The `isTestRunner` function can be used to determine if a story is rendering in the context of the test runner. +The `isTestRunner` function can be used to determine if a story is rendering in the context of the test runner. This might be useful if you want to disable certain features in your stories when running in the test runner, though it's likely an edge case. ```js import { isTestRunner } from '@storybook/test-runner/is-test-runner'; @@ -543,8 +543,19 @@ export const MyStory = () => ( The result of `isTestRunner()` will be true in the following scenarios: -1. In the browser, when the story is rendered while running the test runner -2. In node, if you prepend your Storybook script with `STORYBOOK_TEST_RUNNER=true` +1. In the browser, when the story is rendered while running the test runner. This is only applicable in the following scenarios: + + - inside of a render/template function + - inside of a play function + - inside of preview.js + - inside any other code that is executed in the browser + +2. In node, if you prepend your Storybook script with `STORYBOOK_TEST_RUNNER=true`.\* + +> **Warning** +> +> - Currently, given that you have to run Storybook before the test-runner, the `isTestRunner` function will return `false` when running in node even if you are running the test-runner, unless you set the STORYBOOK_TEST_RUNNER environment variable. An example of execution in node is if you're using that function to set parameters or args, or inside of main.js. +> In the future, once the test-runner can spawn Storybook, this will no longer be the case. ## Troubleshooting @@ -595,3 +606,4 @@ For more context, [here's some explanation](https://github.com/facebook/jest/iss Future plans involve adding support for the following features: - 📄 Run addon reports +- ⚙️ Spawning Storybook via the test runner in a single command From 719a112a11faa23e18013ecb738b6408b4dbe99d Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 7 Oct 2022 12:29:19 +0200 Subject: [PATCH 8/9] update check function --- is-test-runner.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/is-test-runner.js b/is-test-runner.js index c176480a..736c63cf 100644 --- a/is-test-runner.js +++ b/is-test-runner.js @@ -1,14 +1,7 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true, -}); -exports.isTestRunner = isTestRunner; - /** * Returns whether the story is rendering inside of the Storybook test runner. */ -function isTestRunner() { +export function isTestRunner() { const isTestRunnerInNode = process?.env?.STORYBOOK_TEST_RUNNER === 'true'; const isTestRunnerInBrowser = !!( typeof window !== 'undefined' && From d45feb99e7d28e48c727df8bf45c81dd0b3b0fe2 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Fri, 7 Oct 2022 13:39:07 +0200 Subject: [PATCH 9/9] undo is-test-runner function for now --- .../is-test-runner.js | 4 +- .storybook/preview.js | 2 +- README.md | 41 ++++++++----------- package.json | 4 +- stories/atoms/Button.stories.js | 2 +- 5 files changed, 22 insertions(+), 31 deletions(-) rename is-test-runner.js => .storybook/is-test-runner.js (58%) diff --git a/is-test-runner.js b/.storybook/is-test-runner.js similarity index 58% rename from is-test-runner.js rename to .storybook/is-test-runner.js index 736c63cf..58b532bf 100644 --- a/is-test-runner.js +++ b/.storybook/is-test-runner.js @@ -2,11 +2,9 @@ * Returns whether the story is rendering inside of the Storybook test runner. */ export function isTestRunner() { - const isTestRunnerInNode = process?.env?.STORYBOOK_TEST_RUNNER === 'true'; - const isTestRunnerInBrowser = !!( + return !!( typeof window !== 'undefined' && window && window.navigator.userAgent.match(/StorybookTestRunner/) ); - return isTestRunnerInBrowser || isTestRunnerInNode; } diff --git a/.storybook/preview.js b/.storybook/preview.js index 7d9921dd..9cfd9258 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,4 +1,4 @@ -import { isTestRunner } from '../is-test-runner'; +import { isTestRunner } from './is-test-runner'; const withSkippableTests = (StoryFn, { parameters }) => { if (parameters.test?.skip && isTestRunner()) { diff --git a/README.md b/README.md index c8d13672..5d2b7346 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Storybook test runner turns all of your stories into executable tests. - [Render lifecycle](#render-lifecycle) - [Utility functions](#utility-functions) - [getStoryContext](#getstorycontext) - - [isTestRunner](#istestrunner) + - [StorybookTestRunner user agent](#storybooktestrunner-user-agent) - [Troubleshooting](#troubleshooting) - [The error output in the CLI is too short](#the-error-output-in-the-cli-is-too-short) - [The test runner seems flaky and keeps timing out](#the-test-runner-seems-flaky-and-keeps-timing-out) @@ -527,35 +527,28 @@ module.exports = { }; ``` -#### isTestRunner +#### StorybookTestRunner user agent -The `isTestRunner` function can be used to determine if a story is rendering in the context of the test runner. This might be useful if you want to disable certain features in your stories when running in the test runner, though it's likely an edge case. +The test-runner adds a `StorybookTestRunner` entry to the browser's user agent. You can use it to determine if a story is rendering in the context of the test runner. This might be useful if you want to disable certain features in your stories when running in the test runner, though it's likely an edge case. ```js -import { isTestRunner } from '@storybook/test-runner/is-test-runner'; -export const MyStory = () => ( -
-

Is this story running in the test runner?

-

{isTestRunner() ? 'Yes' : 'No'}

-
-); +export const MyStory = () => { + const isTestRunner = window.navigator.userAgent.match(/StorybookTestRunner/); + return ( +
+

Is this story running in the test runner?

+

{isTestRunner ? 'Yes' : 'No'}

+
+ ); +}; ``` -The result of `isTestRunner()` will be true in the following scenarios: - -1. In the browser, when the story is rendered while running the test runner. This is only applicable in the following scenarios: - - - inside of a render/template function - - inside of a play function - - inside of preview.js - - inside any other code that is executed in the browser +Given that this check is happening in the browser, it is only applicable in the following scenarios: -2. In node, if you prepend your Storybook script with `STORYBOOK_TEST_RUNNER=true`.\* - -> **Warning** -> -> - Currently, given that you have to run Storybook before the test-runner, the `isTestRunner` function will return `false` when running in node even if you are running the test-runner, unless you set the STORYBOOK_TEST_RUNNER environment variable. An example of execution in node is if you're using that function to set parameters or args, or inside of main.js. -> In the future, once the test-runner can spawn Storybook, this will no longer be the case. +- inside of a render/template function of a story +- inside of a play function +- inside of preview.js +- inside any other code that is executed in the browser ## Troubleshooting diff --git a/package.json b/package.json index b017e276..619b8e7c 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "scripts": { "clean": "rimraf ./dist", "buildBabel": "concurrently \"yarn buildBabel:cjs\" \"yarn buildBabel:esm\"", - "buildBabel:cjs": "babel ./src -d ./dist/cjs --extensions \".js,.jsx,.ts,.tsx\" --copy-files is-test-runner.js", - "buildBabel:esm": "babel ./src -d ./dist/esm --env-name esm --extensions \".js,.jsx,.ts,.tsx\" --copy-files is-test-runner.js", + "buildBabel:cjs": "babel ./src -d ./dist/cjs --extensions \".js,.jsx,.ts,.tsx\"", + "buildBabel:esm": "babel ./src -d ./dist/esm --env-name esm --extensions \".js,.jsx,.ts,.tsx\"", "buildTsc": "tsc --declaration --emitDeclarationOnly --outDir ./dist/ts", "prebuild": "yarn clean", "build": "concurrently \"yarn buildBabel\" \"yarn buildTsc\"", diff --git a/stories/atoms/Button.stories.js b/stories/atoms/Button.stories.js index e2ac6151..2291dc2a 100644 --- a/stories/atoms/Button.stories.js +++ b/stories/atoms/Button.stories.js @@ -1,6 +1,6 @@ import React from 'react'; import { expect } from '@storybook/jest'; -import { isTestRunner } from '../../is-test-runner'; +import { isTestRunner } from '../../.storybook/is-test-runner'; import { within, waitFor, userEvent, waitForElementToBeRemoved } from '@storybook/testing-library'; import { Button } from './Button';