creevey 0.10.0-beta.9 → 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 +2 -2
- 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 +5 -20
- 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 +19 -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 +1 -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 +22 -10
- 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 +22 -9
- package/dist/client/web/CreeveyApp.js.map +1 -1
- package/dist/client/web/CreeveyContext.d.ts +1 -0
- package/dist/client/web/CreeveyContext.js +18 -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 +18 -8
- 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 +28 -17
- 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 -11
- package/dist/client/web/CreeveyView/SideBar/SuiteLink.js.map +1 -1
- package/dist/client/web/CreeveyView/SideBar/TestLink.js +20 -11
- 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.js +17 -7
- 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 +161 -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 +137 -79
- 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 +3 -3
- package/dist/server/selenium/internal.js +48 -34
- 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 +113 -13
- 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 +27 -63
- 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 +2 -2
- 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 +10 -18
- 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 +2 -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 +1 -1
- package/src/client/shared/components/PageHeader/PageHeader.tsx +23 -7
- package/src/client/shared/components/ResultsPage.tsx +6 -4
- package/src/client/shared/creeveyClientApi.ts +19 -1
- package/src/client/shared/helpers.ts +4 -24
- package/src/client/web/CreeveyApp.tsx +5 -2
- package/src/client/web/CreeveyContext.tsx +2 -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 +1 -1
- package/src/client/web/CreeveyView/SideBar/SideBar.tsx +11 -6
- package/src/client/web/CreeveyView/SideBar/SideBarFooter.tsx +21 -19
- package/src/client/web/CreeveyView/SideBar/SideBarHeader.tsx +20 -5
- package/src/client/web/CreeveyView/SideBar/SuiteLink.tsx +10 -8
- package/src/client/web/CreeveyView/SideBar/TestLink.tsx +9 -7
- 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/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 +161 -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 +169 -96
- 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 +62 -45
- 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 +123 -14
- 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 +32 -75
- 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-BE9CL5_G.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,25 +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;
|
101
|
+
#debug: boolean;
|
59
102
|
#storybookGlobals?: StorybookGlobals;
|
60
|
-
|
61
|
-
|
103
|
+
constructor(
|
104
|
+
browser: Browser,
|
105
|
+
context: BrowserContext,
|
106
|
+
page: Page,
|
107
|
+
traceDir: string,
|
108
|
+
port: number,
|
109
|
+
debug = false,
|
110
|
+
storybookGlobals?: StorybookGlobals,
|
111
|
+
) {
|
62
112
|
this.#browser = browser;
|
113
|
+
this.#context = context;
|
63
114
|
this.#page = page;
|
115
|
+
this.#traceDir = traceDir;
|
64
116
|
this.#serverPort = port;
|
117
|
+
this.#debug = debug;
|
65
118
|
this.#storybookGlobals = storybookGlobals;
|
66
|
-
this.#unsubscribe = subscribeOn('shutdown', () => {
|
67
|
-
void this.closeBrowser();
|
68
|
-
});
|
69
119
|
}
|
70
120
|
|
121
|
+
// TODO Expose #browser and #context in tests
|
71
122
|
get browser() {
|
72
123
|
return this.#page;
|
73
124
|
}
|
@@ -80,32 +131,41 @@ export class InternalBrowser {
|
|
80
131
|
if (this.#isShuttingDown) return;
|
81
132
|
|
82
133
|
this.#isShuttingDown = true;
|
83
|
-
this.#unsubscribe();
|
84
134
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
+
}
|
90
150
|
}
|
91
151
|
}
|
92
152
|
|
93
153
|
async takeScreenshot(captureElement?: string | null, ignoreElements?: string | string[] | null): Promise<Buffer> {
|
94
|
-
// TODO Implement features from selenium `takeScreenshot`
|
95
|
-
// TODO Do we need scroll bar hack from selenium?
|
96
154
|
const ignore = Array.isArray(ignoreElements) ? ignoreElements : ignoreElements ? [ignoreElements] : [];
|
97
155
|
const mask = ignore.map((el) => this.#page.locator(el));
|
98
156
|
if (captureElement) {
|
99
157
|
const element = await this.#page.$(captureElement);
|
100
158
|
if (!element) throw new Error(`Element with selector ${captureElement} not found`);
|
101
159
|
|
160
|
+
logger().debug(`Capturing ${chalk.cyan(captureElement)} element`);
|
102
161
|
return element.screenshot({
|
162
|
+
style: ':root { overflow: hidden !important; }',
|
103
163
|
animations: 'disabled',
|
104
164
|
mask,
|
105
|
-
style: ':root { overflow: hidden !important; }',
|
106
165
|
});
|
107
166
|
}
|
108
|
-
|
167
|
+
logger().debug('Capturing viewport screenshot');
|
168
|
+
return this.#page.screenshot({ animations: 'disabled', mask });
|
109
169
|
}
|
110
170
|
|
111
171
|
waitForComplete(callback: (isCompleted: boolean) => void): void {
|
@@ -125,6 +185,7 @@ export class InternalBrowser {
|
|
125
185
|
[id: string, shouldWaitForReady: boolean]
|
126
186
|
>(
|
127
187
|
([id, shouldWaitForReady]) => {
|
188
|
+
// TODO: Don't use creevey related global variables, inline this function to simplify support
|
128
189
|
if (typeof window.__CREEVEY_SELECT_STORY__ == 'undefined') {
|
129
190
|
return [
|
130
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.",
|
@@ -157,58 +218,50 @@ export class InternalBrowser {
|
|
157
218
|
);
|
158
219
|
}
|
159
220
|
|
160
|
-
async loadStoriesFromBrowser(
|
161
|
-
|
162
|
-
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__());
|
163
223
|
|
164
|
-
|
224
|
+
if (!stories) throw new Error("Can't get stories, it seems creevey or storybook API isn't available");
|
165
225
|
|
166
|
-
|
167
|
-
} catch (error) {
|
168
|
-
// TODO Check how other solutions with playwright get stories from storybook
|
169
|
-
if (retry) throw error;
|
170
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
171
|
-
// NOTE: Try one more time because of dynamic nature of vite and storybook
|
172
|
-
return this.loadStoriesFromBrowser(true);
|
173
|
-
}
|
226
|
+
return stories;
|
174
227
|
}
|
175
228
|
|
176
229
|
static async getBrowser(
|
177
230
|
browserName: string,
|
178
231
|
gridUrl: string,
|
179
232
|
config: Config,
|
180
|
-
options:
|
233
|
+
options: WorkerOptions,
|
181
234
|
): Promise<InternalBrowser | null> {
|
182
235
|
const browserConfig = config.browsers[browserName] as BrowserConfigObject;
|
183
236
|
const {
|
184
237
|
storybookUrl: address = config.storybookUrl,
|
185
238
|
viewport,
|
239
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
186
240
|
_storybookGlobals,
|
241
|
+
storybookGlobals = _storybookGlobals,
|
187
242
|
seleniumCapabilities,
|
188
243
|
playwrightOptions,
|
189
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();
|
190
251
|
|
191
|
-
|
252
|
+
assert(cacheDir, "Couldn't get cache directory");
|
192
253
|
|
193
|
-
|
194
|
-
switch (browserConfig.browserName) {
|
195
|
-
case 'chromium':
|
196
|
-
browser = await tryConnect(chromium, gridUrl);
|
197
|
-
break;
|
198
|
-
case 'firefox':
|
199
|
-
browser = await tryConnect(firefox, gridUrl);
|
200
|
-
break;
|
201
|
-
case 'webkit':
|
202
|
-
browser = await tryConnect(webkit, gridUrl);
|
203
|
-
break;
|
254
|
+
let browser: Browser | null = null;
|
204
255
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
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
|
+
});
|
210
263
|
} else {
|
211
|
-
if (browserConfig.browserName
|
264
|
+
if (browserConfig.browserName !== 'chrome') {
|
212
265
|
logger().error("Playwright's Selenium Grid feature supports only chrome browser");
|
213
266
|
return null;
|
214
267
|
}
|
@@ -216,26 +269,50 @@ export class InternalBrowser {
|
|
216
269
|
process.env.SELENIUM_REMOTE_URL = gridUrl;
|
217
270
|
process.env.SELENIUM_REMOTE_CAPABILITIES = JSON.stringify(seleniumCapabilities);
|
218
271
|
|
219
|
-
browser = await chromium.launch(playwrightOptions);
|
272
|
+
browser = await chromium.launch({ ...playwrightOptions, tracesDir: path.join(cacheDir, `${process.pid}`) });
|
220
273
|
}
|
221
274
|
|
222
275
|
if (!browser) {
|
223
276
|
return null;
|
224
277
|
}
|
225
278
|
|
226
|
-
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
|
+
}
|
227
294
|
|
228
|
-
|
295
|
+
if (logger().getLevel() <= Logger.levels.DEBUG) {
|
296
|
+
page.on('console', (msg) => {
|
297
|
+
logger().debug(`Console message: ${msg.text()}`);
|
298
|
+
});
|
299
|
+
}
|
229
300
|
|
230
|
-
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
|
+
);
|
231
310
|
|
232
311
|
try {
|
233
312
|
if (isShuttingDown.current) return null;
|
234
313
|
const done = await internalBrowser.init({
|
235
314
|
browserName,
|
236
|
-
viewport,
|
237
315
|
storybookUrl: address,
|
238
|
-
resolveStorybookUrl: config.resolveStorybookUrl,
|
239
316
|
});
|
240
317
|
|
241
318
|
return done ? internalBrowser : null;
|
@@ -252,17 +329,7 @@ export class InternalBrowser {
|
|
252
329
|
}
|
253
330
|
}
|
254
331
|
|
255
|
-
private async init({
|
256
|
-
browserName,
|
257
|
-
viewport,
|
258
|
-
storybookUrl,
|
259
|
-
resolveStorybookUrl,
|
260
|
-
}: {
|
261
|
-
browserName: string;
|
262
|
-
viewport?: { width: number; height: number };
|
263
|
-
storybookUrl: string;
|
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(),
|
348
|
+
() => this.triggerViteReload(),
|
281
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,14 +407,28 @@ 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
434
|
private async updateStorybookGlobals(): Promise<void> {
|
@@ -367,7 +441,9 @@ export class InternalBrowser {
|
|
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
|
+
}
|