creevey 0.10.0-beta.8 → 0.10.0-rc.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/AUTHORS +2 -0
- package/CHANGELOG.md +281 -0
- package/README.md +19 -41
- package/dist/client/addon/components/Addon.js +18 -8
- package/dist/client/addon/components/Addon.js.map +1 -1
- package/dist/client/addon/components/Panel.js +4 -4
- package/dist/client/addon/components/Panel.js.map +1 -1
- package/dist/client/addon/components/TestSelect.js +2 -2
- package/dist/client/addon/components/TestSelect.js.map +1 -1
- package/dist/client/addon/components/Tools.js +19 -9
- package/dist/client/addon/components/Tools.js.map +1 -1
- package/dist/client/addon/controller.d.ts +1 -1
- package/dist/client/addon/controller.js +3 -3
- package/dist/client/addon/controller.js.map +1 -1
- package/dist/client/addon/decorator.d.ts +1 -1
- package/dist/client/addon/makeDecorator.d.ts +9 -0
- package/dist/client/addon/makeDecorator.js +48 -0
- package/dist/client/addon/makeDecorator.js.map +1 -0
- package/dist/client/addon/manager.js +38 -39
- package/dist/client/addon/manager.js.map +1 -1
- package/dist/client/addon/preset.d.ts +0 -1
- package/dist/client/addon/preset.js +3 -2
- package/dist/client/addon/preset.js.map +1 -1
- package/dist/client/addon/preview.d.ts +1 -1
- package/dist/client/addon/withCreevey.d.ts +5 -3
- package/dist/client/addon/withCreevey.js +14 -21
- package/dist/client/addon/withCreevey.js.map +1 -1
- package/dist/client/shared/components/ImagesView/BlendView.d.ts +2 -2
- package/dist/client/shared/components/ImagesView/BlendView.js +18 -8
- package/dist/client/shared/components/ImagesView/BlendView.js.map +1 -1
- package/dist/client/shared/components/ImagesView/ImagesView.js +1 -1
- package/dist/client/shared/components/ImagesView/ImagesView.js.map +1 -1
- package/dist/client/shared/components/ImagesView/SideBySideView.d.ts +2 -2
- package/dist/client/shared/components/ImagesView/SideBySideView.js +19 -9
- package/dist/client/shared/components/ImagesView/SideBySideView.js.map +1 -1
- package/dist/client/shared/components/ImagesView/SlideView.d.ts +2 -2
- package/dist/client/shared/components/ImagesView/SlideView.js +19 -9
- package/dist/client/shared/components/ImagesView/SlideView.js.map +1 -1
- package/dist/client/shared/components/ImagesView/SwapView.d.ts +2 -2
- package/dist/client/shared/components/ImagesView/SwapView.js +31 -9
- package/dist/client/shared/components/ImagesView/SwapView.js.map +1 -1
- package/dist/client/shared/components/ImagesView/common.d.ts +1 -1
- package/dist/client/shared/components/PageFooter/PageFooter.js +1 -1
- package/dist/client/shared/components/PageFooter/PageFooter.js.map +1 -1
- package/dist/client/shared/components/PageFooter/Paging.js +1 -1
- package/dist/client/shared/components/PageFooter/Paging.js.map +1 -1
- package/dist/client/shared/components/PageHeader/ImagePreview.d.ts +2 -2
- package/dist/client/shared/components/PageHeader/ImagePreview.js +2 -1
- package/dist/client/shared/components/PageHeader/ImagePreview.js.map +1 -1
- package/dist/client/shared/components/PageHeader/PageHeader.js +34 -13
- package/dist/client/shared/components/PageHeader/PageHeader.js.map +1 -1
- package/dist/client/shared/components/ResultsPage.d.ts +2 -2
- package/dist/client/shared/components/ResultsPage.js +45 -15
- package/dist/client/shared/components/ResultsPage.js.map +1 -1
- package/dist/client/shared/creeveyClientApi.js +18 -1
- package/dist/client/shared/creeveyClientApi.js.map +1 -1
- package/dist/client/shared/helpers.d.ts +1 -3
- package/dist/client/shared/helpers.js +4 -19
- package/dist/client/shared/helpers.js.map +1 -1
- package/dist/client/web/CreeveyApp.d.ts +1 -0
- package/dist/client/web/CreeveyApp.js +44 -15
- package/dist/client/web/CreeveyApp.js.map +1 -1
- package/dist/client/web/CreeveyContext.d.ts +6 -0
- package/dist/client/web/CreeveyContext.js +21 -7
- package/dist/client/web/CreeveyContext.js.map +1 -1
- package/dist/client/web/CreeveyLoader.d.ts +1 -1
- package/dist/client/web/CreeveyLoader.js +3 -3
- package/dist/client/web/CreeveyLoader.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/Checkbox.d.ts +4 -4
- package/dist/client/web/CreeveyView/SideBar/Checkbox.js +36 -6
- package/dist/client/web/CreeveyView/SideBar/Checkbox.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/Search.js +20 -10
- package/dist/client/web/CreeveyView/SideBar/Search.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SideBar.js +26 -12
- package/dist/client/web/CreeveyView/SideBar/SideBar.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js +67 -13
- package/dist/client/web/CreeveyView/SideBar/SideBarFooter.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js +32 -12
- package/dist/client/web/CreeveyView/SideBar/SideBarHeader.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/SuiteLink.d.ts +6 -6
- package/dist/client/web/CreeveyView/SideBar/SuiteLink.js +20 -13
- package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/TestLink.js +20 -13
- package/dist/client/web/CreeveyView/SideBar/TestLink.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +2 -2
- package/dist/client/web/CreeveyView/SideBar/TestStatusIcon.js +2 -2
- package/dist/client/web/CreeveyView/SideBar/TestStatusIcon.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/TestsStatus.d.ts +2 -2
- package/dist/client/web/CreeveyView/SideBar/TestsStatus.js +3 -2
- package/dist/client/web/CreeveyView/SideBar/TestsStatus.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/Toggle.js +1 -1
- package/dist/client/web/CreeveyView/SideBar/Toggle.js.map +1 -1
- package/dist/client/web/KeyboardEventsContext.d.ts +1 -8
- package/dist/client/web/KeyboardEventsContext.js +79 -64
- package/dist/client/web/KeyboardEventsContext.js.map +1 -1
- package/dist/client/web/assets/index-CtSq3IhG.js +518 -0
- package/dist/client/web/index.html +1 -1
- package/dist/client/web/index.js +26 -11
- package/dist/client/web/index.js.map +1 -1
- package/dist/client/web/themes.d.ts +2 -0
- package/dist/client/web/themes.js +22 -0
- package/dist/client/web/themes.js.map +1 -0
- package/dist/creevey.d.ts +1 -1
- package/dist/creevey.js +122 -41
- package/dist/creevey.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/playwright/generator.d.ts +25 -0
- package/dist/playwright/generator.js +243 -0
- package/dist/playwright/generator.js.map +1 -0
- package/dist/playwright/helpers.d.ts +2 -0
- package/dist/playwright/helpers.js +29 -0
- package/dist/playwright/helpers.js.map +1 -0
- package/dist/playwright/reporter.d.ts +83 -0
- package/dist/playwright/reporter.js +334 -0
- package/dist/playwright/reporter.js.map +1 -0
- package/dist/playwright/setup.d.ts +3 -0
- package/dist/playwright/setup.js +72 -0
- package/dist/playwright/setup.js.map +1 -0
- package/dist/playwright.d.ts +1 -0
- package/dist/playwright.js +3 -1
- package/dist/playwright.js.map +1 -1
- package/dist/server/compare.d.ts +18 -0
- package/dist/server/compare.js +182 -0
- package/dist/server/compare.js.map +1 -0
- package/dist/server/config.d.ts +3 -3
- package/dist/server/config.js +75 -8
- package/dist/server/config.js.map +1 -1
- package/dist/server/connection.d.ts +3 -0
- package/dist/server/connection.js +28 -0
- package/dist/server/connection.js.map +1 -0
- package/dist/server/docker.d.ts +1 -1
- package/dist/server/docker.js +54 -32
- package/dist/server/docker.js.map +1 -1
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +165 -64
- package/dist/server/index.js.map +1 -1
- package/dist/server/master/api.d.ts +11 -6
- package/dist/server/master/api.js +88 -25
- package/dist/server/master/api.js.map +1 -1
- package/dist/server/master/handlers/capture-handler.d.ts +5 -0
- package/dist/server/master/handlers/capture-handler.js +25 -0
- package/dist/server/master/handlers/capture-handler.js.map +1 -0
- package/dist/server/master/handlers/index.d.ts +4 -0
- package/dist/server/master/handlers/index.js +21 -0
- package/dist/server/master/handlers/index.js.map +1 -0
- package/dist/server/master/handlers/ping-handler.d.ts +2 -0
- package/dist/server/master/handlers/ping-handler.js +8 -0
- package/dist/server/master/handlers/ping-handler.js.map +1 -0
- package/dist/server/master/handlers/static-handler.d.ts +1 -0
- package/dist/server/master/handlers/static-handler.js +20 -0
- package/dist/server/master/handlers/static-handler.js.map +1 -0
- package/dist/server/master/handlers/stories-handler.d.ts +4 -0
- package/dist/server/master/handlers/stories-handler.js +24 -0
- package/dist/server/master/handlers/stories-handler.js.map +1 -0
- package/dist/server/master/master.js +7 -24
- package/dist/server/master/master.js.map +1 -1
- package/dist/server/master/pool.d.ts +1 -0
- package/dist/server/master/pool.js +5 -3
- package/dist/server/master/pool.js.map +1 -1
- package/dist/server/master/queue.d.ts +1 -1
- package/dist/server/master/queue.js +14 -6
- package/dist/server/master/queue.js.map +1 -1
- package/dist/server/master/runner.d.ts +6 -6
- package/dist/server/master/runner.js +98 -130
- package/dist/server/master/runner.js.map +1 -1
- package/dist/server/master/server.d.ts +1 -1
- package/dist/server/master/server.js +193 -88
- package/dist/server/master/server.js.map +1 -1
- package/dist/server/master/start.d.ts +1 -2
- package/dist/server/master/start.js +13 -29
- package/dist/server/master/start.js.map +1 -1
- package/dist/server/master/testsManager.d.ts +81 -0
- package/dist/server/master/testsManager.js +282 -0
- package/dist/server/master/testsManager.js.map +1 -0
- package/dist/server/playwright/docker-file.d.ts +1 -1
- package/dist/server/playwright/docker-file.js +17 -8
- package/dist/server/playwright/docker-file.js.map +1 -1
- package/dist/server/playwright/docker.d.ts +2 -1
- package/dist/server/playwright/docker.js +10 -2
- package/dist/server/playwright/docker.js.map +1 -1
- package/dist/server/playwright/index-source.mjs +16 -0
- package/dist/server/playwright/internal.d.ts +7 -7
- package/dist/server/playwright/internal.js +144 -84
- package/dist/server/playwright/internal.js.map +1 -1
- package/dist/server/playwright/webdriver.d.ts +3 -3
- package/dist/server/playwright/webdriver.js +0 -6
- package/dist/server/playwright/webdriver.js.map +1 -1
- package/dist/server/providers/browser.js +4 -3
- package/dist/server/providers/browser.js.map +1 -1
- package/dist/server/providers/hybrid.js +2 -2
- package/dist/server/providers/hybrid.js.map +1 -1
- package/dist/server/report.d.ts +10 -0
- package/dist/server/report.js +45 -0
- package/dist/server/report.js.map +1 -0
- package/dist/server/reporters/creevey.d.ts +7 -0
- package/dist/server/reporters/creevey.js +63 -0
- package/dist/server/reporters/creevey.js.map +1 -0
- package/dist/server/reporters/index.d.ts +2 -0
- package/dist/server/reporters/index.js +16 -0
- package/dist/server/reporters/index.js.map +1 -0
- package/dist/server/reporters/junit.d.ts +16 -0
- package/dist/server/reporters/junit.js +167 -0
- package/dist/server/reporters/junit.js.map +1 -0
- package/dist/server/reporters/teamcity.d.ts +7 -0
- package/dist/server/reporters/teamcity.js +60 -0
- package/dist/server/reporters/teamcity.js.map +1 -0
- package/dist/server/selenium/internal.d.ts +4 -4
- package/dist/server/selenium/internal.js +56 -40
- package/dist/server/selenium/internal.js.map +1 -1
- package/dist/server/selenium/selenoid.js +12 -6
- package/dist/server/selenium/selenoid.js.map +1 -1
- package/dist/server/selenium/webdriver.d.ts +3 -3
- package/dist/server/selenium/webdriver.js +4 -8
- package/dist/server/selenium/webdriver.js.map +1 -1
- package/dist/server/shutdown.d.ts +1 -0
- package/dist/server/shutdown.js +23 -0
- package/dist/server/shutdown.js.map +1 -0
- package/dist/server/stories.d.ts +0 -1
- package/dist/server/stories.js +0 -12
- package/dist/server/stories.js.map +1 -1
- package/dist/server/telemetry.js +3 -3
- package/dist/server/telemetry.js.map +1 -1
- package/dist/server/testsFiles/parser.js +45 -5
- package/dist/server/testsFiles/parser.js.map +1 -1
- package/dist/server/utils.d.ts +23 -0
- package/dist/server/utils.js +114 -15
- package/dist/server/utils.js.map +1 -1
- package/dist/server/webdriver.d.ts +1 -1
- package/dist/server/worker/context.d.ts +3 -0
- package/dist/server/worker/context.js +15 -0
- package/dist/server/worker/context.js.map +1 -0
- package/dist/server/worker/match-image.d.ts +8 -12
- package/dist/server/worker/match-image.js +11 -178
- package/dist/server/worker/match-image.js.map +1 -1
- package/dist/server/worker/start.d.ts +2 -2
- package/dist/server/worker/start.js +41 -64
- package/dist/server/worker/start.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.js +9 -7
- package/dist/shared/index.js.map +1 -1
- package/dist/types.d.ts +84 -43
- package/dist/types.js +65 -1
- package/dist/types.js.map +1 -1
- package/docs/cli.md +80 -0
- package/docs/config.md +179 -165
- package/docs/examples/playwright-reporer/playwright.config.ts +37 -0
- package/docs/migration-0.9-to-0.10.md +144 -0
- package/docs/playwright-reporter.md +357 -0
- package/docs/storybook.md +60 -0
- package/docs/tests.md +50 -45
- package/package.json +78 -83
- package/playwright.config.mts +46 -0
- package/src/client/addon/components/Addon.tsx +1 -1
- package/src/client/addon/components/Panel.tsx +4 -4
- package/src/client/addon/components/TestSelect.tsx +2 -2
- package/src/client/addon/components/Tools.tsx +2 -2
- package/src/client/addon/controller.ts +4 -4
- package/src/client/addon/makeDecorator.ts +69 -0
- package/src/client/addon/manager.ts +38 -37
- package/src/client/addon/preset.ts +2 -1
- package/src/client/addon/withCreevey.ts +16 -19
- package/src/client/shared/components/ImagesView/BlendView.tsx +1 -1
- package/src/client/shared/components/ImagesView/ImagesView.tsx +1 -1
- package/src/client/shared/components/ImagesView/SideBySideView.tsx +2 -2
- package/src/client/shared/components/ImagesView/SlideView.tsx +2 -2
- package/src/client/shared/components/ImagesView/SwapView.tsx +20 -2
- package/src/client/shared/components/ImagesView/common.ts +1 -1
- package/src/client/shared/components/PageFooter/PageFooter.tsx +1 -1
- package/src/client/shared/components/PageFooter/Paging.tsx +1 -1
- package/src/client/shared/components/PageHeader/ImagePreview.tsx +2 -1
- package/src/client/shared/components/PageHeader/PageHeader.tsx +23 -7
- package/src/client/shared/components/ResultsPage.tsx +33 -10
- package/src/client/shared/creeveyClientApi.ts +19 -1
- package/src/client/shared/helpers.ts +4 -24
- package/src/client/web/CreeveyApp.tsx +30 -9
- package/src/client/web/CreeveyContext.tsx +11 -0
- package/src/client/web/CreeveyLoader.tsx +2 -2
- package/src/client/web/CreeveyView/SideBar/Checkbox.tsx +3 -3
- package/src/client/web/CreeveyView/SideBar/Search.tsx +4 -4
- package/src/client/web/CreeveyView/SideBar/SideBar.tsx +11 -6
- package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +48 -15
- package/src/client/web/CreeveyView/SideBar/SideBarHeader.tsx +20 -5
- package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +12 -12
- package/src/client/web/CreeveyView/SideBar/TestLink.tsx +10 -10
- package/src/client/web/CreeveyView/SideBar/TestStatusIcon.tsx +2 -2
- package/src/client/web/CreeveyView/SideBar/TestsStatus.tsx +3 -2
- package/src/client/web/CreeveyView/SideBar/Toggle.tsx +1 -1
- package/src/client/web/KeyboardEventsContext.tsx +61 -73
- package/src/client/web/index.tsx +10 -5
- package/src/client/web/themes.ts +24 -0
- package/src/creevey.ts +92 -38
- package/src/playwright/generator.ts +322 -0
- package/src/playwright/helpers.ts +31 -0
- package/src/playwright/reporter.ts +381 -0
- package/src/playwright/setup.ts +84 -0
- package/src/playwright.ts +1 -0
- package/src/server/compare.ts +260 -0
- package/src/server/config.ts +52 -9
- package/src/server/connection.ts +26 -0
- package/src/server/docker.ts +62 -34
- package/src/server/index.ts +166 -79
- package/src/server/master/api.ts +94 -28
- package/src/server/master/handlers/capture-handler.ts +20 -0
- package/src/server/master/handlers/index.ts +4 -0
- package/src/server/master/handlers/ping-handler.ts +6 -0
- package/src/server/master/handlers/static-handler.ts +16 -0
- package/src/server/master/handlers/stories-handler.ts +20 -0
- package/src/server/master/master.ts +10 -27
- package/src/server/master/pool.ts +7 -3
- package/src/server/master/queue.ts +21 -7
- package/src/server/master/runner.ts +123 -134
- package/src/server/master/server.ts +214 -101
- package/src/server/master/start.ts +19 -41
- package/src/server/master/testsManager.ts +316 -0
- package/src/server/playwright/docker-file.ts +20 -8
- package/src/server/playwright/docker.ts +16 -3
- package/src/server/playwright/index-source.mjs +16 -0
- package/src/server/playwright/internal.ts +176 -103
- package/src/server/playwright/webdriver.ts +4 -10
- package/src/server/providers/browser.ts +4 -3
- package/src/server/providers/hybrid.ts +2 -3
- package/src/server/report.ts +51 -0
- package/src/server/reporters/creevey.ts +71 -0
- package/src/server/reporters/index.ts +11 -0
- package/src/server/reporters/junit.ts +207 -0
- package/src/server/reporters/teamcity.ts +74 -0
- package/src/server/selenium/internal.ts +70 -53
- package/src/server/selenium/selenoid.ts +13 -6
- package/src/server/selenium/webdriver.ts +8 -12
- package/src/server/shutdown.ts +19 -0
- package/src/server/stories.ts +1 -12
- package/src/server/telemetry.ts +3 -3
- package/src/server/testsFiles/parser.ts +52 -4
- package/src/server/utils.ts +124 -16
- package/src/server/webdriver.ts +1 -1
- package/src/server/worker/context.ts +14 -0
- package/src/server/worker/match-image.ts +16 -248
- package/src/server/worker/start.ts +49 -79
- package/src/shared/index.ts +10 -8
- package/src/types.ts +91 -58
- package/types/global.d.ts +1 -0
- package/dist/client/web/assets/index-DB8lHlJw.js +0 -591
- package/dist/server/reporter.d.ts +0 -26
- package/dist/server/reporter.js +0 -108
- package/dist/server/reporter.js.map +0 -1
- package/dist/server/update.d.ts +0 -2
- package/dist/server/update.js +0 -53
- package/dist/server/update.js.map +0 -1
- package/src/server/reporter.ts +0 -139
- package/src/server/update.ts +0 -74
@@ -1,22 +1,39 @@
|
|
1
|
-
import
|
1
|
+
import path from 'path';
|
2
|
+
import assert from 'assert';
|
3
|
+
import {
|
4
|
+
Browser,
|
5
|
+
BrowserContext,
|
6
|
+
BrowserContextOptions,
|
7
|
+
BrowserType,
|
8
|
+
Page,
|
9
|
+
chromium,
|
10
|
+
firefox,
|
11
|
+
webkit,
|
12
|
+
} from 'playwright-core';
|
2
13
|
import chalk from 'chalk';
|
3
14
|
import { v4 } from 'uuid';
|
15
|
+
import Logger from 'loglevel';
|
4
16
|
import prefix from 'loglevel-plugin-prefix';
|
17
|
+
import type { Args } from 'storybook/internal/types';
|
5
18
|
import {
|
6
19
|
BrowserConfigObject,
|
7
20
|
Config,
|
8
|
-
Options,
|
9
21
|
StoriesRaw,
|
10
22
|
StoryInput,
|
11
23
|
StorybookEvents,
|
12
24
|
StorybookGlobals,
|
13
|
-
|
25
|
+
WorkerOptions,
|
14
26
|
} from '../../types';
|
15
|
-
import { subscribeOn } from '../messages';
|
16
27
|
import { appendIframePath, getAddresses, LOCALHOST_REGEXP, resolveStorybookUrl, storybookRootID } from '../webdriver';
|
17
|
-
import { isShuttingDown, runSequence } from '../utils';
|
28
|
+
import { getCreeveyCache, isShuttingDown, resolvePlaywrightBrowserType, runSequence } from '../utils';
|
18
29
|
import { colors, logger } from '../logger';
|
19
|
-
import {
|
30
|
+
import { removeWorkerContainer } from '../worker/context';
|
31
|
+
|
32
|
+
const browsers = {
|
33
|
+
chromium,
|
34
|
+
firefox,
|
35
|
+
webkit,
|
36
|
+
};
|
20
37
|
|
21
38
|
async function tryConnect(type: BrowserType, gridUrl: string): Promise<Browser | null> {
|
22
39
|
let timeout: NodeJS.Timeout | null = null;
|
@@ -49,23 +66,59 @@ async function tryConnect(type: BrowserType, gridUrl: string): Promise<Browser |
|
|
49
66
|
]);
|
50
67
|
}
|
51
68
|
|
69
|
+
async function tryCreateBrowserContext(
|
70
|
+
browser: Browser,
|
71
|
+
options: BrowserContextOptions,
|
72
|
+
): Promise<{ context: BrowserContext; page: Page }> {
|
73
|
+
try {
|
74
|
+
const context = await browser.newContext(options);
|
75
|
+
const page = await context.newPage();
|
76
|
+
return { context, page };
|
77
|
+
} catch (error) {
|
78
|
+
if (error instanceof Error && error.message.includes('ffmpeg')) {
|
79
|
+
logger().warn('Failed to create browser context with video recording. Video recording will be disabled.');
|
80
|
+
logger().warn(error);
|
81
|
+
const context = await browser.newContext({
|
82
|
+
...options,
|
83
|
+
recordVideo: undefined,
|
84
|
+
});
|
85
|
+
const page = await context.newPage();
|
86
|
+
return { context, page };
|
87
|
+
}
|
88
|
+
throw error;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
52
92
|
export class InternalBrowser {
|
53
93
|
#isShuttingDown = false;
|
54
94
|
#browser: Browser;
|
95
|
+
#context: BrowserContext;
|
55
96
|
#page: Page;
|
97
|
+
#traceDir: string;
|
56
98
|
#sessionId: string = v4();
|
57
99
|
#serverHost: string | null = null;
|
58
100
|
#serverPort: number;
|
59
|
-
#
|
60
|
-
|
101
|
+
#debug: boolean;
|
102
|
+
#storybookGlobals?: StorybookGlobals;
|
103
|
+
constructor(
|
104
|
+
browser: Browser,
|
105
|
+
context: BrowserContext,
|
106
|
+
page: Page,
|
107
|
+
traceDir: string,
|
108
|
+
port: number,
|
109
|
+
debug = false,
|
110
|
+
storybookGlobals?: StorybookGlobals,
|
111
|
+
) {
|
61
112
|
this.#browser = browser;
|
113
|
+
this.#context = context;
|
62
114
|
this.#page = page;
|
115
|
+
this.#traceDir = traceDir;
|
63
116
|
this.#serverPort = port;
|
64
|
-
this.#
|
65
|
-
|
66
|
-
});
|
117
|
+
this.#debug = debug;
|
118
|
+
this.#storybookGlobals = storybookGlobals;
|
67
119
|
}
|
68
120
|
|
121
|
+
// TODO Expose #browser and #context in tests
|
69
122
|
get browser() {
|
70
123
|
return this.#page;
|
71
124
|
}
|
@@ -78,32 +131,41 @@ export class InternalBrowser {
|
|
78
131
|
if (this.#isShuttingDown) return;
|
79
132
|
|
80
133
|
this.#isShuttingDown = true;
|
81
|
-
this.#unsubscribe();
|
82
134
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
135
|
+
const teardown = [
|
136
|
+
this.#debug ? () => this.#context.tracing.stop({ path: path.join(this.#traceDir, 'trace.zip') }) : null,
|
137
|
+
() => this.#page.close(),
|
138
|
+
this.#debug ? () => this.#page.video()?.saveAs(path.join(this.#traceDir, 'video.webm')) : null,
|
139
|
+
() => this.#context.close(),
|
140
|
+
() => this.#browser.close(),
|
141
|
+
() => removeWorkerContainer(),
|
142
|
+
];
|
143
|
+
|
144
|
+
for (const fn of teardown) {
|
145
|
+
try {
|
146
|
+
if (fn) await fn();
|
147
|
+
} catch {
|
148
|
+
/* noop */
|
149
|
+
}
|
88
150
|
}
|
89
151
|
}
|
90
152
|
|
91
153
|
async takeScreenshot(captureElement?: string | null, ignoreElements?: string | string[] | null): Promise<Buffer> {
|
92
|
-
// TODO Implement features from selenium `takeScreenshot`
|
93
|
-
// TODO Do we need scroll bar hack from selenium?
|
94
154
|
const ignore = Array.isArray(ignoreElements) ? ignoreElements : ignoreElements ? [ignoreElements] : [];
|
95
155
|
const mask = ignore.map((el) => this.#page.locator(el));
|
96
156
|
if (captureElement) {
|
97
157
|
const element = await this.#page.$(captureElement);
|
98
158
|
if (!element) throw new Error(`Element with selector ${captureElement} not found`);
|
99
159
|
|
160
|
+
logger().debug(`Capturing ${chalk.cyan(captureElement)} element`);
|
100
161
|
return element.screenshot({
|
162
|
+
style: ':root { overflow: hidden !important; }',
|
101
163
|
animations: 'disabled',
|
102
164
|
mask,
|
103
|
-
style: ':root { overflow: hidden !important; }',
|
104
165
|
});
|
105
166
|
}
|
106
|
-
|
167
|
+
logger().debug('Capturing viewport screenshot');
|
168
|
+
return this.#page.screenshot({ animations: 'disabled', mask });
|
107
169
|
}
|
108
170
|
|
109
171
|
waitForComplete(callback: (isCompleted: boolean) => void): void {
|
@@ -112,6 +174,7 @@ export class InternalBrowser {
|
|
112
174
|
|
113
175
|
async selectStory(id: string, waitForReady = false): Promise<boolean> {
|
114
176
|
// NOTE: Global variables might be reset after hot reload. I think it's workaround, maybe we need better solution
|
177
|
+
await this.updateStorybookGlobals();
|
115
178
|
await this.updateBrowserGlobalVariables();
|
116
179
|
await this.resetMousePosition();
|
117
180
|
|
@@ -122,6 +185,7 @@ export class InternalBrowser {
|
|
122
185
|
[id: string, shouldWaitForReady: boolean]
|
123
186
|
>(
|
124
187
|
([id, shouldWaitForReady]) => {
|
188
|
+
// TODO: Don't use creevey related global variables, inline this function to simplify support
|
125
189
|
if (typeof window.__CREEVEY_SELECT_STORY__ == 'undefined') {
|
126
190
|
return [
|
127
191
|
"Creevey can't switch story. This may happened if forget to add `creevey` addon to your storybook config, or storybook not loaded in browser due syntax error.",
|
@@ -154,58 +218,50 @@ export class InternalBrowser {
|
|
154
218
|
);
|
155
219
|
}
|
156
220
|
|
157
|
-
async loadStoriesFromBrowser(
|
158
|
-
|
159
|
-
const stories = await this.#page.evaluate<StoriesRaw | undefined>(() => window.__CREEVEY_GET_STORIES__());
|
221
|
+
async loadStoriesFromBrowser(): Promise<StoriesRaw> {
|
222
|
+
const stories = await this.#page.evaluate<StoriesRaw | undefined>(() => window.__CREEVEY_GET_STORIES__());
|
160
223
|
|
161
|
-
|
224
|
+
if (!stories) throw new Error("Can't get stories, it seems creevey or storybook API isn't available");
|
162
225
|
|
163
|
-
|
164
|
-
} catch (error) {
|
165
|
-
// TODO Check how other solutions with playwright get stories from storybook
|
166
|
-
if (retry) throw error;
|
167
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
168
|
-
// NOTE: Try one more time because of dynamic nature of vite and storybook
|
169
|
-
return this.loadStoriesFromBrowser(true);
|
170
|
-
}
|
226
|
+
return stories;
|
171
227
|
}
|
172
228
|
|
173
229
|
static async getBrowser(
|
174
230
|
browserName: string,
|
175
231
|
gridUrl: string,
|
176
232
|
config: Config,
|
177
|
-
options:
|
233
|
+
options: WorkerOptions,
|
178
234
|
): Promise<InternalBrowser | null> {
|
179
235
|
const browserConfig = config.browsers[browserName] as BrowserConfigObject;
|
180
236
|
const {
|
181
237
|
storybookUrl: address = config.storybookUrl,
|
182
238
|
viewport,
|
239
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
183
240
|
_storybookGlobals,
|
241
|
+
storybookGlobals = _storybookGlobals,
|
184
242
|
seleniumCapabilities,
|
185
243
|
playwrightOptions,
|
186
244
|
} = browserConfig;
|
245
|
+
const parsedUrl = new URL(gridUrl);
|
246
|
+
const tracesDir = path.join(
|
247
|
+
playwrightOptions?.tracesDir ?? path.join(config.reportDir, 'traces'),
|
248
|
+
process.pid.toString(),
|
249
|
+
);
|
250
|
+
const cacheDir = await getCreeveyCache();
|
187
251
|
|
188
|
-
|
252
|
+
assert(cacheDir, "Couldn't get cache directory");
|
189
253
|
|
190
|
-
|
191
|
-
switch (browserConfig.browserName) {
|
192
|
-
case 'chromium':
|
193
|
-
browser = await tryConnect(chromium, gridUrl);
|
194
|
-
break;
|
195
|
-
case 'firefox':
|
196
|
-
browser = await tryConnect(firefox, gridUrl);
|
197
|
-
break;
|
198
|
-
case 'webkit':
|
199
|
-
browser = await tryConnect(webkit, gridUrl);
|
200
|
-
break;
|
254
|
+
let browser: Browser | null = null;
|
201
255
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
256
|
+
if (parsedUrl.protocol === 'ws:') {
|
257
|
+
browser = await tryConnect(browsers[resolvePlaywrightBrowserType(browserConfig.browserName)], gridUrl);
|
258
|
+
} else if (parsedUrl.protocol === 'creevey:') {
|
259
|
+
browser = await browsers[resolvePlaywrightBrowserType(browserConfig.browserName)].launch({
|
260
|
+
...playwrightOptions,
|
261
|
+
tracesDir: path.join(cacheDir, `${process.pid}`),
|
262
|
+
});
|
207
263
|
} else {
|
208
|
-
if (browserConfig.browserName
|
264
|
+
if (browserConfig.browserName !== 'chrome') {
|
209
265
|
logger().error("Playwright's Selenium Grid feature supports only chrome browser");
|
210
266
|
return null;
|
211
267
|
}
|
@@ -213,27 +269,50 @@ export class InternalBrowser {
|
|
213
269
|
process.env.SELENIUM_REMOTE_URL = gridUrl;
|
214
270
|
process.env.SELENIUM_REMOTE_CAPABILITIES = JSON.stringify(seleniumCapabilities);
|
215
271
|
|
216
|
-
browser = await chromium.launch(playwrightOptions);
|
272
|
+
browser = await chromium.launch({ ...playwrightOptions, tracesDir: path.join(cacheDir, `${process.pid}`) });
|
217
273
|
}
|
218
274
|
|
219
275
|
if (!browser) {
|
220
276
|
return null;
|
221
277
|
}
|
222
278
|
|
223
|
-
const page = await browser
|
279
|
+
const { context, page } = await tryCreateBrowserContext(browser, {
|
280
|
+
recordVideo: options.debug
|
281
|
+
? {
|
282
|
+
dir: path.join(cacheDir, `${process.pid}`),
|
283
|
+
size: viewport,
|
284
|
+
}
|
285
|
+
: undefined,
|
286
|
+
screen: viewport,
|
287
|
+
viewport,
|
288
|
+
});
|
289
|
+
if (options.debug) {
|
290
|
+
await context.tracing.start(
|
291
|
+
Object.assign({ screenshots: true, snapshots: true, sources: true }, playwrightOptions?.trace),
|
292
|
+
);
|
293
|
+
}
|
224
294
|
|
225
|
-
|
295
|
+
if (logger().getLevel() <= Logger.levels.DEBUG) {
|
296
|
+
page.on('console', (msg) => {
|
297
|
+
logger().debug(`Console message: ${msg.text()}`);
|
298
|
+
});
|
299
|
+
}
|
226
300
|
|
227
|
-
const internalBrowser = new InternalBrowser(
|
301
|
+
const internalBrowser = new InternalBrowser(
|
302
|
+
browser,
|
303
|
+
context,
|
304
|
+
page,
|
305
|
+
tracesDir,
|
306
|
+
options.port,
|
307
|
+
options.debug,
|
308
|
+
storybookGlobals,
|
309
|
+
);
|
228
310
|
|
229
311
|
try {
|
230
312
|
if (isShuttingDown.current) return null;
|
231
313
|
const done = await internalBrowser.init({
|
232
314
|
browserName,
|
233
|
-
viewport,
|
234
315
|
storybookUrl: address,
|
235
|
-
storybookGlobals: _storybookGlobals,
|
236
|
-
resolveStorybookUrl: config.resolveStorybookUrl,
|
237
316
|
});
|
238
317
|
|
239
318
|
return done ? internalBrowser : null;
|
@@ -250,19 +329,7 @@ export class InternalBrowser {
|
|
250
329
|
}
|
251
330
|
}
|
252
331
|
|
253
|
-
private async init({
|
254
|
-
browserName,
|
255
|
-
viewport,
|
256
|
-
storybookUrl,
|
257
|
-
storybookGlobals,
|
258
|
-
resolveStorybookUrl,
|
259
|
-
}: {
|
260
|
-
browserName: string;
|
261
|
-
viewport?: { width: number; height: number };
|
262
|
-
storybookUrl: string;
|
263
|
-
storybookGlobals?: StorybookGlobals;
|
264
|
-
resolveStorybookUrl?: () => Promise<string>;
|
265
|
-
}) {
|
332
|
+
private async init({ browserName, storybookUrl }: { browserName: string; storybookUrl: string }) {
|
266
333
|
const sessionId = this.#sessionId;
|
267
334
|
|
268
335
|
prefix.apply(logger(), {
|
@@ -276,36 +343,26 @@ export class InternalBrowser {
|
|
276
343
|
|
277
344
|
return await runSequence(
|
278
345
|
[
|
279
|
-
() => this.openStorybookPage(storybookUrl
|
346
|
+
() => this.openStorybookPage(storybookUrl),
|
280
347
|
() => this.waitForStorybook(),
|
281
|
-
() => this.
|
348
|
+
() => this.triggerViteReload(),
|
349
|
+
() => this.updateStorybookGlobals(),
|
282
350
|
() => this.resolveCreeveyHost(),
|
283
351
|
() => this.updateBrowserGlobalVariables(),
|
284
|
-
() => this.resizeViewport(viewport),
|
285
352
|
],
|
286
353
|
() => !this.#isShuttingDown,
|
287
354
|
);
|
288
355
|
}
|
289
356
|
|
290
|
-
private async openStorybookPage(storybookUrl: string
|
357
|
+
private async openStorybookPage(storybookUrl: string): Promise<void> {
|
291
358
|
if (!LOCALHOST_REGEXP.test(storybookUrl)) {
|
292
359
|
await this.#page.goto(appendIframePath(storybookUrl));
|
293
360
|
return;
|
294
361
|
}
|
295
362
|
|
296
363
|
try {
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
const resolvedUrl = await resolver();
|
301
|
-
|
302
|
-
logger().debug(`Resolver storybook url ${resolvedUrl}`);
|
303
|
-
|
304
|
-
await this.#page.goto(appendIframePath(resolvedUrl));
|
305
|
-
} else {
|
306
|
-
// TODO this.#page.setDefaultNavigationTimeout(10000);
|
307
|
-
await resolveStorybookUrl(appendIframePath(storybookUrl), (url) => this.checkUrl(url));
|
308
|
-
}
|
364
|
+
const resolvedUrl = await resolveStorybookUrl(appendIframePath(storybookUrl), (url) => this.checkUrl(url));
|
365
|
+
await this.#page.goto(resolvedUrl);
|
309
366
|
} catch (error) {
|
310
367
|
logger().error('Failed to resolve storybook URL', error instanceof Error ? error.message : '');
|
311
368
|
throw error;
|
@@ -313,21 +370,23 @@ export class InternalBrowser {
|
|
313
370
|
}
|
314
371
|
|
315
372
|
private async checkUrl(url: string): Promise<boolean> {
|
373
|
+
const page = await this.#browser.newPage();
|
316
374
|
try {
|
317
375
|
logger().debug(`Opening ${chalk.magenta(url)} and checking the page source`);
|
318
|
-
const response = await
|
376
|
+
const response = await page.goto(url, { waitUntil: 'commit' });
|
319
377
|
const source = await response?.text();
|
320
378
|
|
321
379
|
logger().debug(`Checking ${chalk.cyan(`#${storybookRootID}`)} existence on ${chalk.magenta(url)}`);
|
322
380
|
return source?.includes(`id="${storybookRootID}"`) ?? false;
|
323
381
|
} catch {
|
324
382
|
return false;
|
383
|
+
} finally {
|
384
|
+
await page.close();
|
325
385
|
}
|
326
386
|
}
|
327
387
|
|
328
388
|
private async waitForStorybook(): Promise<void> {
|
329
|
-
|
330
|
-
logger().debug('Waiting for `setStories` event to make sure that storybook is initiated');
|
389
|
+
logger().debug('Waiting for Storybook to initiate');
|
331
390
|
|
332
391
|
const isTimeout = await Promise.race([
|
333
392
|
new Promise<boolean>((resolve) => {
|
@@ -338,6 +397,7 @@ export class InternalBrowser {
|
|
338
397
|
(async () => {
|
339
398
|
let wait = true;
|
340
399
|
do {
|
400
|
+
if (this.#page.isClosed()) return false;
|
341
401
|
try {
|
342
402
|
// TODO Research a different way to ensure storybook is initiated
|
343
403
|
wait = await this.#page.evaluate((SET_GLOBALS: string) => {
|
@@ -347,27 +407,43 @@ export class InternalBrowser {
|
|
347
407
|
}, StorybookEvents.SET_GLOBALS);
|
348
408
|
} catch (e: unknown) {
|
349
409
|
logger().debug('An error has been caught during the script:', e);
|
410
|
+
if (this.#page.isClosed()) throw e;
|
350
411
|
}
|
412
|
+
if (wait) await new Promise((resolve) => setTimeout(resolve, 1000));
|
351
413
|
} while (wait);
|
352
414
|
return false;
|
353
415
|
})(),
|
354
416
|
]);
|
355
417
|
|
356
|
-
|
357
|
-
|
418
|
+
if (isTimeout) throw new Error('Failed to wait Storybook init');
|
419
|
+
}
|
420
|
+
|
421
|
+
// TODO Doesn't work for some reason, maybe because of race-condition
|
422
|
+
private async triggerViteReload(): Promise<void> {
|
423
|
+
// NOTE: On the first load, Vite might try to optimize some dependencies and reload the page
|
424
|
+
// We need to trigger reload earlier to avoid unnecessary reloads further
|
425
|
+
try {
|
426
|
+
await this.#page.evaluate(async () => {
|
427
|
+
await window.__STORYBOOK_PREVIEW__.extract();
|
428
|
+
});
|
429
|
+
} catch {
|
430
|
+
await this.waitForStorybook();
|
431
|
+
}
|
358
432
|
}
|
359
433
|
|
360
|
-
private async updateStorybookGlobals(
|
361
|
-
if (!
|
434
|
+
private async updateStorybookGlobals(): Promise<void> {
|
435
|
+
if (!this.#storybookGlobals) return;
|
362
436
|
|
363
437
|
logger().debug('Applying storybook globals');
|
364
438
|
await this.#page.evaluate((globals: StorybookGlobals) => {
|
365
439
|
window.__CREEVEY_UPDATE_GLOBALS__(globals);
|
366
|
-
},
|
440
|
+
}, this.#storybookGlobals);
|
367
441
|
}
|
368
442
|
|
369
443
|
private async resolveCreeveyHost(): Promise<void> {
|
370
|
-
const
|
444
|
+
const storybookUrl = this.#page.url();
|
445
|
+
const storybookHost = new URL(storybookUrl).hostname;
|
446
|
+
const addresses = [storybookHost, ...getAddresses()];
|
371
447
|
|
372
448
|
this.#serverHost = await this.#page.evaluate(
|
373
449
|
([hosts, port]) => {
|
@@ -392,8 +468,10 @@ export class InternalBrowser {
|
|
392
468
|
}
|
393
469
|
|
394
470
|
private async updateBrowserGlobalVariables() {
|
471
|
+
logger().debug('Updating browser global variables');
|
395
472
|
await this.#page.evaluate(
|
396
473
|
([workerId, creeveyHost, creeveyPort]) => {
|
474
|
+
window.__CREEVEY_ENV__ = true;
|
397
475
|
window.__CREEVEY_WORKER_ID__ = workerId;
|
398
476
|
window.__CREEVEY_SERVER_HOST__ = creeveyHost ?? 'localhost';
|
399
477
|
window.__CREEVEY_SERVER_PORT__ = creeveyPort;
|
@@ -402,13 +480,8 @@ export class InternalBrowser {
|
|
402
480
|
);
|
403
481
|
}
|
404
482
|
|
405
|
-
private async resizeViewport(viewport?: { width: number; height: number }): Promise<void> {
|
406
|
-
if (!viewport) return;
|
407
|
-
|
408
|
-
await this.#page.setViewportSize(viewport);
|
409
|
-
}
|
410
|
-
|
411
483
|
private async resetMousePosition(): Promise<void> {
|
484
|
+
logger().debug('Resetting mouse position to (0, 0)');
|
412
485
|
await this.#page.mouse.move(0, 0);
|
413
486
|
}
|
414
487
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
/// <reference types="../../../types/playwright-context" />
|
2
|
-
import { Args } from '
|
3
|
-
import { Config,
|
2
|
+
import type { Args } from 'storybook/internal/types';
|
3
|
+
import { Config, ServerTest, StoriesRaw, StoryInput, WorkerOptions } from '../../types';
|
4
4
|
import { logger } from '../logger';
|
5
5
|
import { subscribeOn } from '../messages';
|
6
6
|
import { CreeveyWebdriverBase } from '../webdriver';
|
@@ -11,8 +11,8 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
11
11
|
#browserName: string;
|
12
12
|
#gridUrl: string;
|
13
13
|
#config: Config;
|
14
|
-
#options:
|
15
|
-
constructor(browser: string, gridUrl: string, config: Config, options:
|
14
|
+
#options: WorkerOptions;
|
15
|
+
constructor(browser: string, gridUrl: string, config: Config, options: WorkerOptions) {
|
16
16
|
super();
|
17
17
|
|
18
18
|
this.#browserName = browser;
|
@@ -32,7 +32,6 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
32
32
|
|
33
33
|
getSessionId(): Promise<string> {
|
34
34
|
if (!this.#browser) {
|
35
|
-
// TODO Describe the error
|
36
35
|
throw new Error('Browser is not initialized');
|
37
36
|
}
|
38
37
|
|
@@ -79,7 +78,6 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
79
78
|
|
80
79
|
async loadStoriesFromBrowser(): Promise<StoriesRaw> {
|
81
80
|
if (!this.#browser) {
|
82
|
-
// TODO Describe the error
|
83
81
|
throw new Error('Browser is not initialized');
|
84
82
|
}
|
85
83
|
|
@@ -95,7 +93,6 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
95
93
|
ignoreElements?: string | string[] | null,
|
96
94
|
): Promise<Buffer> {
|
97
95
|
if (!this.#browser) {
|
98
|
-
// TODO Describe the error
|
99
96
|
throw new Error('Browser is not initialized');
|
100
97
|
}
|
101
98
|
|
@@ -104,7 +101,6 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
104
101
|
|
105
102
|
protected waitForComplete(callback: (isCompleted: boolean) => void): void {
|
106
103
|
if (!this.#browser) {
|
107
|
-
// TODO Describe the error
|
108
104
|
throw new Error('Browser is not initialized');
|
109
105
|
}
|
110
106
|
|
@@ -113,7 +109,6 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
113
109
|
|
114
110
|
protected async selectStory(id: string, waitForReady?: boolean): Promise<boolean> {
|
115
111
|
if (!this.#browser) {
|
116
|
-
// TODO Describe the error
|
117
112
|
throw new Error('Browser is not initialized');
|
118
113
|
}
|
119
114
|
|
@@ -122,7 +117,6 @@ export class PlaywrightWebdriver extends CreeveyWebdriverBase {
|
|
122
117
|
|
123
118
|
protected async updateStoryArgs(story: StoryInput, updatedArgs: Args): Promise<void> {
|
124
119
|
if (!this.#browser) {
|
125
|
-
// TODO Describe the error
|
126
120
|
throw new Error('Browser is not initialized');
|
127
121
|
}
|
128
122
|
|
@@ -24,7 +24,7 @@ export const loadStories: StoriesProvider = async (_config, storiesListener, web
|
|
24
24
|
oldTests.join('\n'),
|
25
25
|
);
|
26
26
|
unsubscribe();
|
27
|
-
resolve(stories);
|
27
|
+
resolve(deserializeRawStories(stories));
|
28
28
|
}
|
29
29
|
});
|
30
30
|
sendStoriesMessage(worker, { type: 'get' });
|
@@ -37,10 +37,11 @@ export const loadStories: StoriesProvider = async (_config, storiesListener, web
|
|
37
37
|
} else {
|
38
38
|
subscribeOn('stories', (message) => {
|
39
39
|
if (message.type == 'get')
|
40
|
-
emitStoriesMessage({ type: 'set', payload: { stories, oldTests: storiesWithOldTests } });
|
40
|
+
emitStoriesMessage({ type: 'set', payload: { stories: rawStories, oldTests: storiesWithOldTests } });
|
41
41
|
if (message.type == 'update') storiesListener(new Map(message.payload));
|
42
42
|
});
|
43
|
-
const
|
43
|
+
const rawStories = (await webdriver?.loadStoriesFromBrowser()) ?? {};
|
44
|
+
const stories = deserializeRawStories(rawStories);
|
44
45
|
|
45
46
|
const storiesWithOldTests: string[] = [];
|
46
47
|
|
@@ -1,5 +1,4 @@
|
|
1
|
-
import
|
2
|
-
|
1
|
+
import { watch } from 'chokidar';
|
3
2
|
import { loadStories as browserProvider } from './browser.js';
|
4
3
|
import type { Config, CreeveyStoryParams, CreeveyStory, StoriesProvider } from '../../types.js';
|
5
4
|
import { logger } from '../logger.js';
|
@@ -53,7 +52,7 @@ async function parseParams(
|
|
53
52
|
const testFiles = readDirRecursive(config.testsDir).filter((file) => config.testsRegex?.test(file));
|
54
53
|
|
55
54
|
if (listener) {
|
56
|
-
|
55
|
+
watch(testFiles).on('change', (filePath) => {
|
57
56
|
logger().debug(`changed: ${filePath}`);
|
58
57
|
|
59
58
|
// doesn't work, always returns {} due modules caching
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import open from 'open';
|
2
|
+
import { Config } from '../types.js';
|
3
|
+
import { logger } from './logger.js';
|
4
|
+
import { TestsManager } from './master/testsManager.js';
|
5
|
+
import { start as startServer } from './master/server.js';
|
6
|
+
import { CreeveyApi } from './master/api.js';
|
7
|
+
import { shutdownWorkers } from './utils.js';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* UI Update Mode implementation.
|
11
|
+
* This mode allows users to review and approve screenshots from the browser interface.
|
12
|
+
* It combines the functionality of both --ui and --update flags.
|
13
|
+
*
|
14
|
+
* @param config Creevey configuration
|
15
|
+
* @param port Port to run the server on
|
16
|
+
*/
|
17
|
+
export function report(config: Config, reportDir: string, port: number): void {
|
18
|
+
logger().info('Starting UI Update Mode');
|
19
|
+
|
20
|
+
process.on('SIGINT', () => void shutdownWorkers());
|
21
|
+
|
22
|
+
const url = `http://localhost:${port}`;
|
23
|
+
|
24
|
+
// Initialize TestsManager with the configured directories
|
25
|
+
const testsManager = new TestsManager(config.screenDir, reportDir);
|
26
|
+
|
27
|
+
// Load tests from the report
|
28
|
+
const testsFromReport = testsManager.loadTestsFromReport();
|
29
|
+
|
30
|
+
if (Object.keys(testsFromReport).length === 0) {
|
31
|
+
logger().warn('No tests found in report. Run tests first to generate report data.');
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
|
35
|
+
// Set tests in the manager
|
36
|
+
testsManager.updateTests(testsFromReport);
|
37
|
+
|
38
|
+
// Start API server with UI enabled
|
39
|
+
const resolveApi = startServer(reportDir, port, true);
|
40
|
+
|
41
|
+
// Initialize API
|
42
|
+
const api = new CreeveyApi(testsManager);
|
43
|
+
|
44
|
+
// Resolve the API for the server
|
45
|
+
resolveApi(api);
|
46
|
+
|
47
|
+
logger().info(`UI Update Mode started on ${url}`);
|
48
|
+
logger().info('You can now review and approve screenshots from the browser.');
|
49
|
+
|
50
|
+
void open(url);
|
51
|
+
}
|