creevey 0.8.0-beta.0 → 0.9.0-beta.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/CHANGELOG.md +5 -9
- package/lib/cjs/client/addon/Manager.js +0 -1
- package/lib/cjs/client/addon/preset.js +1 -0
- package/lib/cjs/client/addon/readyForCapture.js +12 -0
- package/lib/cjs/client/addon/withCreevey.js +313 -41
- package/lib/cjs/client/shared/components/ImagesView/BlendView.js +3 -3
- package/lib/cjs/client/shared/components/ImagesView/SideBySideView.js +3 -3
- package/lib/cjs/client/shared/components/ImagesView/SlideView.js +4 -3
- package/lib/cjs/client/shared/components/ImagesView/SwapView.js +3 -3
- package/lib/cjs/client/shared/helpers.js +1 -1
- package/lib/cjs/client/web/main.js +6 -6
- package/lib/cjs/index.js +27 -9
- package/lib/cjs/server/config.js +7 -3
- package/lib/cjs/server/extract.js +11 -4
- package/lib/cjs/server/index.js +2 -4
- package/lib/cjs/server/master/index.js +3 -9
- package/lib/cjs/server/master/master.js +1 -0
- package/lib/cjs/server/master/pool.js +29 -29
- package/lib/cjs/server/master/server.js +75 -3
- package/lib/cjs/server/messages.js +124 -12
- package/lib/cjs/server/parser.js +85 -0
- package/lib/cjs/server/selenium/browser.js +119 -21
- package/lib/cjs/server/stories.js +49 -46
- package/lib/cjs/server/storybook/providers/browser.js +78 -0
- package/lib/cjs/server/storybook/providers/hybrid.js +79 -0
- package/lib/cjs/server/storybook/{nodejs-provider.js → providers/nodejs.js} +32 -13
- package/lib/cjs/server/utils.js +7 -0
- package/lib/cjs/server/worker/helpers.js +2 -6
- package/lib/cjs/server/worker/worker.js +15 -3
- package/lib/cjs/shared.js +78 -6
- package/lib/cjs/types.js +5 -0
- package/lib/esm/client/addon/Manager.js +0 -1
- package/lib/esm/client/addon/preset.js +1 -0
- package/lib/esm/client/addon/readyForCapture.js +5 -0
- package/lib/esm/client/addon/withCreevey.js +303 -41
- package/lib/esm/client/shared/components/ImagesView/BlendView.js +2 -3
- package/lib/esm/client/shared/components/ImagesView/SideBySideView.js +2 -3
- package/lib/esm/client/shared/components/ImagesView/SlideView.js +3 -3
- package/lib/esm/client/shared/components/ImagesView/SwapView.js +2 -3
- package/lib/esm/client/shared/helpers.js +1 -1
- package/lib/esm/index.js +6 -3
- package/lib/esm/server/config.js +7 -5
- package/lib/esm/server/extract.js +8 -4
- package/lib/esm/server/index.js +2 -3
- package/lib/esm/server/master/index.js +4 -10
- package/lib/esm/server/master/master.js +1 -0
- package/lib/esm/server/master/pool.js +31 -31
- package/lib/esm/server/master/server.js +73 -5
- package/lib/esm/server/messages.js +118 -12
- package/lib/esm/server/parser.js +63 -0
- package/lib/esm/server/selenium/browser.js +116 -23
- package/lib/esm/server/stories.js +50 -46
- package/lib/esm/server/storybook/providers/browser.js +61 -0
- package/lib/esm/server/storybook/providers/hybrid.js +63 -0
- package/lib/esm/server/storybook/{nodejs-provider.js → providers/nodejs.js} +30 -13
- package/lib/esm/server/utils.js +6 -1
- package/lib/esm/server/worker/helpers.js +2 -6
- package/lib/esm/server/worker/worker.js +16 -4
- package/lib/esm/shared.js +59 -5
- package/lib/esm/types.js +3 -0
- package/lib/types/cli.d.ts +1 -1
- package/lib/types/client/addon/Manager.d.ts +37 -37
- package/lib/types/client/addon/components/Addon.d.ts +8 -8
- package/lib/types/client/addon/components/Icons.d.ts +7 -7
- package/lib/types/client/addon/components/Panel.d.ts +9 -9
- package/lib/types/client/addon/components/TestSelect.d.ts +9 -9
- package/lib/types/client/addon/components/Tools.d.ts +6 -6
- package/lib/types/client/addon/decorator.d.ts +1 -1
- package/lib/types/client/addon/preset.d.ts +24 -22
- package/lib/types/client/addon/readyForCapture.d.ts +6 -0
- package/lib/types/client/addon/register.d.ts +3 -3
- package/lib/types/client/addon/utils.d.ts +2 -2
- package/lib/types/client/addon/withCreevey.d.ts +24 -13
- package/lib/types/client/shared/components/ImagesView/BlendView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/ImagesView.d.ts +25 -25
- package/lib/types/client/shared/components/ImagesView/SideBySideView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/SlideView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/SwapView.d.ts +3 -3
- package/lib/types/client/shared/components/ImagesView/index.d.ts +5 -5
- package/lib/types/client/shared/components/PageFooter/PageFooter.d.ts +9 -9
- package/lib/types/client/shared/components/PageFooter/Paging.d.ts +8 -8
- package/lib/types/client/shared/components/PageHeader/ImagePreview.d.ts +12 -12
- package/lib/types/client/shared/components/PageHeader/PageHeader.d.ts +17 -17
- package/lib/types/client/shared/components/ResultsPage.d.ts +18 -18
- package/lib/types/client/shared/creeveyClientApi.d.ts +9 -9
- package/lib/types/client/shared/helpers.d.ts +46 -46
- package/lib/types/client/shared/viewMode.d.ts +4 -4
- package/lib/types/client/web/CreeveyApp.d.ts +12 -12
- package/lib/types/client/web/CreeveyContext.d.ts +11 -11
- package/lib/types/client/web/CreeveyLoader.d.ts +3 -3
- package/lib/types/client/web/CreeveyView/SideBar/Checkbox.d.ts +19 -19
- package/lib/types/client/web/CreeveyView/SideBar/Search.d.ts +6 -6
- package/lib/types/client/web/CreeveyView/SideBar/SideBar.d.ts +14 -14
- package/lib/types/client/web/CreeveyView/SideBar/SideBarHeader.d.ts +13 -13
- package/lib/types/client/web/CreeveyView/SideBar/SuiteLink.d.ts +33 -33
- package/lib/types/client/web/CreeveyView/SideBar/TestLink.d.ts +8 -8
- package/lib/types/client/web/CreeveyView/SideBar/TestStatusIcon.d.ts +10 -10
- package/lib/types/client/web/CreeveyView/SideBar/TestsStatus.d.ts +9 -9
- package/lib/types/client/web/CreeveyView/SideBar/Toggle.d.ts +6 -6
- package/lib/types/client/web/CreeveyView/SideBar/index.d.ts +1 -1
- package/lib/types/client/web/KeyboardEventsContext.d.ts +13 -13
- package/lib/types/client/web/index.d.ts +4 -4
- package/lib/types/creevey.d.ts +1 -1
- package/lib/types/index.d.ts +2 -1
- package/lib/types/server/config.d.ts +4 -4
- package/lib/types/server/docker.d.ts +7 -7
- package/lib/types/server/extract.d.ts +2 -2
- package/lib/types/server/index.d.ts +2 -2
- package/lib/types/server/loaders/babel/creevey-plugin.d.ts +1 -1
- package/lib/types/server/loaders/babel/helpers.d.ts +19 -19
- package/lib/types/server/loaders/babel/register.d.ts +5 -5
- package/lib/types/server/loaders/hooks/mdx.d.ts +1 -1
- package/lib/types/server/loaders/hooks/svelte.d.ts +1 -1
- package/lib/types/server/loaders/webpack/compile.d.ts +2 -2
- package/lib/types/server/loaders/webpack/creevey-loader.d.ts +2 -2
- package/lib/types/server/loaders/webpack/dummy-hmr.d.ts +10 -10
- package/lib/types/server/loaders/webpack/mdx-loader.d.ts +6 -6
- package/lib/types/server/loaders/webpack/start.d.ts +1 -1
- package/lib/types/server/logger.d.ts +6 -6
- package/lib/types/server/master/api.d.ts +7 -7
- package/lib/types/server/master/index.d.ts +3 -3
- package/lib/types/server/master/master.d.ts +7 -6
- package/lib/types/server/master/pool.d.ts +31 -30
- package/lib/types/server/master/runner.d.ts +26 -26
- package/lib/types/server/master/server.d.ts +2 -2
- package/lib/types/server/messages.d.ts +28 -18
- package/lib/types/server/parser.d.ts +12 -0
- package/lib/types/server/selenium/browser.d.ts +17 -14
- package/lib/types/server/selenium/index.d.ts +2 -2
- package/lib/types/server/selenium/selenoid.d.ts +3 -3
- package/lib/types/server/stories.d.ts +8 -8
- package/lib/types/server/storybook/entry.d.ts +18 -18
- package/lib/types/server/storybook/helpers.d.ts +24 -24
- package/lib/types/server/storybook/providers/browser.d.ts +4 -0
- package/lib/types/server/storybook/providers/hybrid.d.ts +4 -0
- package/lib/types/server/storybook/providers/nodejs.d.ts +9 -0
- package/lib/types/server/update.d.ts +2 -2
- package/lib/types/server/utils.d.ts +20 -19
- package/lib/types/server/worker/chai-image.d.ts +6 -6
- package/lib/types/server/worker/helpers.d.ts +8 -7
- package/lib/types/server/worker/index.d.ts +1 -1
- package/lib/types/server/worker/reporter.d.ts +8 -8
- package/lib/types/server/worker/worker.d.ts +4 -4
- package/lib/types/shared.d.ts +16 -4
- package/lib/types/types.d.ts +488 -459
- package/package.json +12 -6
- package/storybook-static/stories.json +21 -0
- package/types/mocha.d.ts +1 -0
- package/lib/types/server/storybook/nodejs-provider.d.ts +0 -5
@@ -3,8 +3,11 @@
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
4
4
|
value: true
|
5
5
|
});
|
6
|
+
exports.takeScreenshot = takeScreenshot;
|
6
7
|
exports.updateStorybookGlobals = updateStorybookGlobals;
|
8
|
+
exports.loadStoriesFromBrowser = loadStoriesFromBrowser;
|
7
9
|
exports.getBrowser = getBrowser;
|
10
|
+
exports.closeBrowser = closeBrowser;
|
8
11
|
exports.switchStory = switchStory;
|
9
12
|
|
10
13
|
var _chalk = _interopRequireDefault(require("chalk"));
|
@@ -39,6 +42,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
39
42
|
|
40
43
|
const DOCKER_INTERNAL = 'host.docker.internal';
|
41
44
|
let browserLogger = _logger.logger;
|
45
|
+
let browserName = '';
|
46
|
+
let browser = null;
|
47
|
+
let creeveyServerHost = null;
|
42
48
|
|
43
49
|
function getSessionData(grid, sessionId = '') {
|
44
50
|
const gridUrl = new URL(grid);
|
@@ -65,9 +71,13 @@ function getSessionData(grid, sessionId = '') {
|
|
65
71
|
}));
|
66
72
|
}
|
67
73
|
|
74
|
+
function getAddresses() {
|
75
|
+
return [DOCKER_INTERNAL].concat(...Object.values((0, _os.networkInterfaces)()).filter(_types.isDefined).map(network => network.filter(info => info.family == 'IPv4').map(info => info.address)));
|
76
|
+
}
|
77
|
+
|
68
78
|
async function resolveStorybookUrl(storybookUrl, checkUrl) {
|
69
79
|
browserLogger.debug('Resolving storybook url');
|
70
|
-
const addresses =
|
80
|
+
const addresses = getAddresses();
|
71
81
|
|
72
82
|
for (const ip of addresses) {
|
73
83
|
const resolvedUrl = storybookUrl.replace(_utils.LOCALHOST_REGEXP, ip);
|
@@ -366,14 +376,16 @@ async function selectStory(browser, {
|
|
366
376
|
name
|
367
377
|
}, waitForReady = false) {
|
368
378
|
browserLogger.debug(`Triggering 'SetCurrentStory' event with storyId ${_chalk.default.magenta(id)}`);
|
369
|
-
const
|
379
|
+
const result = await browser.executeAsyncScript(function (id, kind, name, shouldWaitForReady, callback) {
|
370
380
|
if (typeof window.__CREEVEY_SELECT_STORY__ == 'undefined') {
|
371
|
-
return callback("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.");
|
381
|
+
return callback(["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."]);
|
372
382
|
}
|
373
383
|
|
374
384
|
window.__CREEVEY_SELECT_STORY__(id, kind, name, shouldWaitForReady, callback);
|
375
385
|
}, id, kind, name, waitForReady);
|
386
|
+
const [errorMessage, isCaptureCalled = false] = result || [];
|
376
387
|
if (errorMessage) throw new Error(errorMessage);
|
388
|
+
return isCaptureCalled;
|
377
389
|
}
|
378
390
|
|
379
391
|
async function updateStorybookGlobals(browser, globals) {
|
@@ -413,7 +425,48 @@ async function openStorybookPage(browser, storybookUrl, resolver) {
|
|
413
425
|
}
|
414
426
|
}
|
415
427
|
|
416
|
-
async function
|
428
|
+
async function resolveCreeveyHost(browser, port) {
|
429
|
+
if (creeveyServerHost != null) return creeveyServerHost;
|
430
|
+
const addresses = getAddresses();
|
431
|
+
creeveyServerHost = await browser.executeAsyncScript(function (hosts, port, callback) {
|
432
|
+
void Promise.all(hosts.map(function (host) {
|
433
|
+
return new Promise(function (resolve, reject) {
|
434
|
+
setTimeout(reject, 10000); // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
435
|
+
|
436
|
+
fetch('http://' + host + ':' + port + '/ping').then(resolve).catch(reject);
|
437
|
+
}).then(function (response) {
|
438
|
+
return response.text();
|
439
|
+
}).then(function (pong) {
|
440
|
+
return pong == 'pong' ? host : null;
|
441
|
+
}).catch(function () {
|
442
|
+
return null;
|
443
|
+
});
|
444
|
+
})).then(function (hosts) {
|
445
|
+
callback(hosts.find(function (host) {
|
446
|
+
return host != null;
|
447
|
+
}));
|
448
|
+
});
|
449
|
+
}, addresses, port);
|
450
|
+
if (creeveyServerHost == null) throw new Error("Can't reach creevey server from a browser");
|
451
|
+
return creeveyServerHost;
|
452
|
+
}
|
453
|
+
|
454
|
+
async function loadStoriesFromBrowser(port) {
|
455
|
+
if (!browser) throw new Error("Can't get stories from browser if webdriver isn't connected");
|
456
|
+
const host = await resolveCreeveyHost(browser, port);
|
457
|
+
const stories = await browser.executeAsyncScript(function (creeveyHost, creeveyPort, callback) {
|
458
|
+
window.__CREEVEY_SERVER_HOST__ = creeveyHost;
|
459
|
+
window.__CREEVEY_SERVER_PORT__ = creeveyPort;
|
460
|
+
void window.__CREEVEY_GET_STORIES__().then(callback);
|
461
|
+
}, host, port);
|
462
|
+
if (!stories) throw new Error("Can't get stories, it seems creevey or storybook API isn't available");
|
463
|
+
return stories;
|
464
|
+
}
|
465
|
+
|
466
|
+
async function getBrowser(config, name) {
|
467
|
+
if (browser) return browser;
|
468
|
+
browserName = name;
|
469
|
+
const browserConfig = config.browsers[browserName];
|
417
470
|
const {
|
418
471
|
gridUrl = config.gridUrl,
|
419
472
|
storybookUrl: address = config.storybookUrl,
|
@@ -423,14 +476,11 @@ async function getBrowser(config, browserConfig) {
|
|
423
476
|
...userCapabilities
|
424
477
|
} = browserConfig;
|
425
478
|
void limit;
|
426
|
-
const
|
427
|
-
browserName
|
428
|
-
} = userCapabilities;
|
429
|
-
const realAddress = address;
|
430
|
-
let browser = null; // TODO Define some capabilities explicitly and define typings
|
479
|
+
const realAddress = address; // TODO Define some capabilities explicitly and define typings
|
431
480
|
|
432
|
-
const capabilities = new _seleniumWebdriver.Capabilities(userCapabilities
|
433
|
-
|
481
|
+
const capabilities = new _seleniumWebdriver.Capabilities({ ...userCapabilities,
|
482
|
+
pageLoadStrategy: _capabilities.PageLoadStrategy.NONE
|
483
|
+
});
|
434
484
|
(0, _messages.subscribeOn)('shutdown', () => {
|
435
485
|
var _browser;
|
436
486
|
|
@@ -445,7 +495,7 @@ async function getBrowser(config, browserConfig) {
|
|
445
495
|
const url = new URL(gridUrl);
|
446
496
|
url.username = url.username ? '********' : '';
|
447
497
|
url.password = url.password ? '********' : '';
|
448
|
-
browserLogger.debug(`(${
|
498
|
+
browserLogger.debug(`(${name}) Connecting to Selenium ${_chalk.default.magenta(url.toString())}`);
|
449
499
|
browser = await new _seleniumWebdriver.Builder().usingServer(gridUrl).withCapabilities(capabilities).build();
|
450
500
|
const sessionId = (_await$browser$getSes = await browser.getSession()) === null || _await$browser$getSes === void 0 ? void 0 : _await$browser$getSes.getId();
|
451
501
|
let browserHost = '';
|
@@ -459,14 +509,14 @@ async function getBrowser(config, browserConfig) {
|
|
459
509
|
/* noop */
|
460
510
|
}
|
461
511
|
|
462
|
-
browserLogger.debug(`(${
|
512
|
+
browserLogger.debug(`(${name}) Connected successful with ${[_chalk.default.green(browserHost), _chalk.default.magenta(sessionId)].filter(Boolean).join(':')}`);
|
463
513
|
browserLogger = (0, _loglevel.getLogger)(sessionId);
|
464
514
|
|
465
515
|
_loglevelPluginPrefix.default.apply(browserLogger, {
|
466
516
|
format(level) {
|
467
517
|
const levelColor = _logger.colors[level.toUpperCase()];
|
468
518
|
|
469
|
-
return `[${
|
519
|
+
return `[${name}:${_chalk.default.gray(sessionId)}] ${levelColor(level)} =>`;
|
470
520
|
}
|
471
521
|
|
472
522
|
});
|
@@ -486,6 +536,7 @@ async function getBrowser(config, browserConfig) {
|
|
486
536
|
var _browser3;
|
487
537
|
|
488
538
|
(_browser3 = browser) === null || _browser3 === void 0 ? void 0 : _browser3.quit().catch(_types.noop);
|
539
|
+
browser = null;
|
489
540
|
return null;
|
490
541
|
}
|
491
542
|
|
@@ -499,6 +550,9 @@ async function getBrowser(config, browserConfig) {
|
|
499
550
|
await updateStorybookGlobals(browser, _storybookGlobals);
|
500
551
|
}
|
501
552
|
|
553
|
+
await browser.executeScript(function (workerId) {
|
554
|
+
window.__CREEVEY_WORKER_ID__ = workerId;
|
555
|
+
}, process.pid);
|
502
556
|
return browser;
|
503
557
|
}
|
504
558
|
|
@@ -514,12 +568,23 @@ async function updateStoryArgs(browser, story, updatedArgs) {
|
|
514
568
|
}, story.id, updatedArgs, Events.UPDATE_STORY_ARGS, Events.STORY_RENDERED);
|
515
569
|
}
|
516
570
|
|
571
|
+
async function closeBrowser() {
|
572
|
+
if (!browser) return;
|
573
|
+
|
574
|
+
try {
|
575
|
+
await browser.quit();
|
576
|
+
} finally {
|
577
|
+
browser = null;
|
578
|
+
}
|
579
|
+
}
|
580
|
+
|
517
581
|
async function switchStory() {
|
518
582
|
var _this$currentTest, _this$currentTest$ctx, _parameters$creevey;
|
519
583
|
|
520
584
|
let testOrSuite = this.currentTest;
|
521
585
|
if (!testOrSuite) throw new Error("Can't switch story, because test context doesn't have 'currentTest' field");
|
522
586
|
this.testScope.length = 0;
|
587
|
+
this.screenshots.length = 0;
|
523
588
|
this.testScope.push(this.browserName);
|
524
589
|
|
525
590
|
while ((_testOrSuite = testOrSuite) !== null && _testOrSuite !== void 0 && _testOrSuite.title) {
|
@@ -543,13 +608,6 @@ async function switchStory() {
|
|
543
608
|
ignoreElements
|
544
609
|
} = (_parameters$creevey = parameters.creevey) !== null && _parameters$creevey !== void 0 ? _parameters$creevey : {};
|
545
610
|
browserLogger.debug(`Switching to story ${_chalk.default.cyan(kind)}/${_chalk.default.cyan(name)} by id ${_chalk.default.magenta(id)}`);
|
546
|
-
await resetMousePosition(this.browser);
|
547
|
-
await selectStory(this.browser, {
|
548
|
-
id,
|
549
|
-
kind,
|
550
|
-
name
|
551
|
-
}, waitForReady);
|
552
|
-
browserLogger.debug(`Story ${_chalk.default.magenta(id)} ready for capturing`);
|
553
611
|
if (captureElement) Object.defineProperty(this, 'captureElement', {
|
554
612
|
enumerable: true,
|
555
613
|
configurable: true,
|
@@ -561,6 +619,46 @@ async function switchStory() {
|
|
561
619
|
this.updateStoryArgs = updatedArgs => updateStoryArgs(this.browser, story, updatedArgs);
|
562
620
|
|
563
621
|
this.testScope.reverse();
|
622
|
+
let storyPlayResolver;
|
623
|
+
let waitForComplete = new Promise(resolve => storyPlayResolver = resolve);
|
624
|
+
const unsubscribe = (0, _messages.subscribeOn)('stories', message => {
|
625
|
+
var _payload$captureEleme, _payload$ignoreElemen;
|
626
|
+
|
627
|
+
if (message.type != 'capture') return;
|
628
|
+
const {
|
629
|
+
payload = {},
|
630
|
+
payload: {
|
631
|
+
imageName
|
632
|
+
} = {}
|
633
|
+
} = message;
|
634
|
+
void takeScreenshot(this.browser, (_payload$captureEleme = payload.captureElement) !== null && _payload$captureEleme !== void 0 ? _payload$captureEleme : captureElement, (_payload$ignoreElemen = payload.ignoreElements) !== null && _payload$ignoreElemen !== void 0 ? _payload$ignoreElemen : ignoreElements).then(screenshot => {
|
635
|
+
this.screenshots.push({
|
636
|
+
imageName,
|
637
|
+
screenshot
|
638
|
+
});
|
639
|
+
void this.browser.executeAsyncScript(function (callback) {
|
640
|
+
window.__CREEVEY_HAS_PLAY_COMPLETED_YET__(callback);
|
641
|
+
}).then(isCompleted => storyPlayResolver(isCompleted));
|
642
|
+
(0, _messages.emitStoriesMessage)({
|
643
|
+
type: 'capture'
|
644
|
+
});
|
645
|
+
});
|
646
|
+
});
|
647
|
+
await resetMousePosition(this.browser);
|
648
|
+
const isCaptureCalled = await selectStory(this.browser, {
|
649
|
+
id,
|
650
|
+
kind,
|
651
|
+
name
|
652
|
+
}, waitForReady);
|
653
|
+
|
654
|
+
if (isCaptureCalled) {
|
655
|
+
while (!(await waitForComplete)) {
|
656
|
+
waitForComplete = new Promise(resolve => storyPlayResolver = resolve);
|
657
|
+
}
|
658
|
+
}
|
659
|
+
|
660
|
+
unsubscribe();
|
661
|
+
browserLogger.debug(`Story ${_chalk.default.magenta(id)} ready for capturing`);
|
564
662
|
}
|
565
663
|
|
566
664
|
async function insertIgnoreStyles(browser, ignoreElements) {
|
@@ -21,8 +21,6 @@ var _utils = require("./utils");
|
|
21
21
|
|
22
22
|
var _helpers = require("./storybook/helpers");
|
23
23
|
|
24
|
-
var _shared = require("../shared");
|
25
|
-
|
26
24
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
27
25
|
|
28
26
|
function storyTestFabric(delay, testFn) {
|
@@ -30,7 +28,12 @@ function storyTestFabric(delay, testFn) {
|
|
30
28
|
var _testFn$call;
|
31
29
|
|
32
30
|
delay ? await new Promise(resolve => setTimeout(resolve, delay)) : void 0;
|
33
|
-
await ((_testFn$call = testFn === null || testFn === void 0 ? void 0 : testFn.call(this)) !== null && _testFn$call !== void 0 ? _testFn$call : this.
|
31
|
+
await ((_testFn$call = testFn === null || testFn === void 0 ? void 0 : testFn.call(this)) !== null && _testFn$call !== void 0 ? _testFn$call : this.screenshots.length > 0 ? this.expect(this.screenshots.reduce((screenshots, {
|
32
|
+
imageName,
|
33
|
+
screenshot
|
34
|
+
}, index) => ({ ...screenshots,
|
35
|
+
[imageName !== null && imageName !== void 0 ? imageName : `screenshot_${index}`]: screenshot
|
36
|
+
}), {})).to.matchImages() : this.expect(await this.takeScreenshot()).to.matchImage());
|
34
37
|
};
|
35
38
|
}
|
36
39
|
|
@@ -56,42 +59,40 @@ function createCreeveyTest(browser, storyMeta, skipOptions, testName) {
|
|
56
59
|
};
|
57
60
|
}
|
58
61
|
|
59
|
-
function convertStories(
|
62
|
+
function convertStories(browserName, stories) {
|
60
63
|
const tests = {};
|
61
64
|
(Array.isArray(stories) ? stories : Object.values(stories)).forEach(storyMeta => {
|
65
|
+
var _storyMeta$parameters;
|
66
|
+
|
62
67
|
// TODO Skip docsOnly stories for now
|
63
68
|
if (storyMeta.parameters.docsOnly) return;
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
};
|
84
|
-
return;
|
85
|
-
}
|
69
|
+
const {
|
70
|
+
delay: delayParam,
|
71
|
+
tests: storyTests,
|
72
|
+
skip
|
73
|
+
} = (_storyMeta$parameters = storyMeta.parameters.creevey) !== null && _storyMeta$parameters !== void 0 ? _storyMeta$parameters : {};
|
74
|
+
const delay = typeof delayParam == 'number' ? delayParam : delayParam !== null && delayParam !== void 0 && delayParam.for.includes(browserName) ? delayParam.ms : 0; // typeof tests === "undefined" => rootSuite -> kindSuite -> storyTest -> [browsers.png]
|
75
|
+
// typeof tests === "function" => rootSuite -> kindSuite -> storyTest -> browser -> [images.png]
|
76
|
+
// typeof tests === "object" => rootSuite -> kindSuite -> storySuite -> test -> [browsers.png]
|
77
|
+
// typeof tests === "object" => rootSuite -> kindSuite -> storySuite -> test -> browser -> [images.png]
|
78
|
+
|
79
|
+
if (!storyTests) {
|
80
|
+
const test = createCreeveyTest(browserName, storyMeta, skip);
|
81
|
+
tests[test.id] = { ...test,
|
82
|
+
storyId: storyMeta.id,
|
83
|
+
story: storyMeta,
|
84
|
+
fn: storyTestFabric(delay)
|
85
|
+
};
|
86
|
+
return;
|
87
|
+
}
|
86
88
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
});
|
89
|
+
Object.entries(storyTests).forEach(([testName, testFn]) => {
|
90
|
+
const test = createCreeveyTest(browserName, storyMeta, skip, testName);
|
91
|
+
tests[test.id] = { ...test,
|
92
|
+
storyId: storyMeta.id,
|
93
|
+
story: storyMeta,
|
94
|
+
fn: storyTestFabric(delay, testFn)
|
95
|
+
};
|
95
96
|
});
|
96
97
|
});
|
97
98
|
return tests;
|
@@ -99,22 +100,24 @@ function convertStories(browsers, stories) {
|
|
99
100
|
|
100
101
|
async function loadTestsFromStories(browsers, provider, update) {
|
101
102
|
const testIdsByFiles = new Map();
|
102
|
-
const
|
103
|
+
const stories = await provider(storiesByFiles => {
|
103
104
|
const testsDiff = {};
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
105
|
+
const tests = {};
|
106
|
+
browsers.forEach(browser => {
|
107
|
+
Array.from(storiesByFiles.entries()).forEach(([filename, stories]) => {
|
108
|
+
var _testIdsByFiles$get$f, _testIdsByFiles$get;
|
109
|
+
|
110
|
+
Object.assign(tests, convertStories(browser, stories));
|
111
|
+
const changed = Object.keys(tests);
|
112
|
+
const removed = (_testIdsByFiles$get$f = (_testIdsByFiles$get = testIdsByFiles.get(filename)) === null || _testIdsByFiles$get === void 0 ? void 0 : _testIdsByFiles$get.filter(testId => !tests[testId])) !== null && _testIdsByFiles$get$f !== void 0 ? _testIdsByFiles$get$f : [];
|
113
|
+
if (changed.length == 0) testIdsByFiles.delete(filename);else testIdsByFiles.set(filename, changed);
|
114
|
+
Object.assign(testsDiff, tests);
|
115
|
+
removed.forEach(testId => testsDiff[testId] = undefined);
|
116
|
+
});
|
113
117
|
});
|
114
118
|
update === null || update === void 0 ? void 0 : update(testsDiff);
|
115
119
|
});
|
116
|
-
const
|
117
|
-
const tests = convertStories(browsers, stories);
|
120
|
+
const tests = browsers.reduce((tests, browser) => Object.assign(tests, convertStories(browser, stories)), {});
|
118
121
|
Object.values(tests).filter(_types.isDefined).forEach(({
|
119
122
|
id,
|
120
123
|
story: {
|
@@ -0,0 +1,78 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
exports.loadStories = loadStories;
|
7
|
+
|
8
|
+
var _cluster = _interopRequireWildcard(require("cluster"));
|
9
|
+
|
10
|
+
var _selenium = require("../../selenium");
|
11
|
+
|
12
|
+
var _messages = require("../../messages");
|
13
|
+
|
14
|
+
var _shared = require("../../../shared");
|
15
|
+
|
16
|
+
var _types = require("../../../types");
|
17
|
+
|
18
|
+
var _logger = require("../../logger");
|
19
|
+
|
20
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
21
|
+
|
22
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
23
|
+
|
24
|
+
async function loadStories(_config, {
|
25
|
+
port
|
26
|
+
}, storiesListener) {
|
27
|
+
if (_cluster.isMaster) {
|
28
|
+
return new Promise(resolve => {
|
29
|
+
const worker = Object.values(_cluster.default.workers).filter(_types.isDefined).find(worker => worker.isConnected());
|
30
|
+
|
31
|
+
if (worker) {
|
32
|
+
const unsubscribe = (0, _messages.subscribeOnWorker)(worker, 'stories', message => {
|
33
|
+
if (message.type == 'set') {
|
34
|
+
const {
|
35
|
+
stories,
|
36
|
+
oldTests
|
37
|
+
} = message.payload;
|
38
|
+
if (oldTests.length > 0) _logger.logger.warn(`If you use browser stories provider of CSFv3 Storybook feature\n` + `Creevey will not load tests defined in story parameters from following stories:\n` + oldTests.join('\n'));
|
39
|
+
unsubscribe();
|
40
|
+
resolve(stories);
|
41
|
+
}
|
42
|
+
});
|
43
|
+
(0, _messages.sendStoriesMessage)(worker, {
|
44
|
+
type: 'get'
|
45
|
+
});
|
46
|
+
}
|
47
|
+
|
48
|
+
(0, _messages.subscribeOn)('stories', message => {
|
49
|
+
// TODO updates only one browser :(
|
50
|
+
if (message.type == 'update') storiesListener(new Map(message.payload));
|
51
|
+
});
|
52
|
+
});
|
53
|
+
} else {
|
54
|
+
(0, _messages.subscribeOn)('stories', message => {
|
55
|
+
if (message.type == 'get') (0, _messages.emitStoriesMessage)({
|
56
|
+
type: 'set',
|
57
|
+
payload: {
|
58
|
+
stories,
|
59
|
+
oldTests: storiesWithOldTests
|
60
|
+
}
|
61
|
+
});
|
62
|
+
if (message.type == 'update') storiesListener(new Map(message.payload));
|
63
|
+
});
|
64
|
+
const stories = (0, _shared.deserializeRawStories)(await (0, _selenium.loadStoriesFromBrowser)(port));
|
65
|
+
const storiesWithOldTests = [];
|
66
|
+
Object.values(stories).forEach(story => {
|
67
|
+
var _parameters, _parameters$creevey;
|
68
|
+
|
69
|
+
if ((_parameters = story.parameters) !== null && _parameters !== void 0 && (_parameters$creevey = _parameters.creevey) !== null && _parameters$creevey !== void 0 && _parameters$creevey.tests) {
|
70
|
+
var _parameters2, _parameters2$creevey;
|
71
|
+
|
72
|
+
(_parameters2 = story.parameters) === null || _parameters2 === void 0 ? true : (_parameters2$creevey = _parameters2.creevey) === null || _parameters2$creevey === void 0 ? true : delete _parameters2$creevey.tests;
|
73
|
+
storiesWithOldTests.push(`${story.kind}/${story.name}`);
|
74
|
+
}
|
75
|
+
});
|
76
|
+
return stories;
|
77
|
+
}
|
78
|
+
}
|
@@ -0,0 +1,79 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
4
|
+
value: true
|
5
|
+
});
|
6
|
+
exports.loadStories = loadStories;
|
7
|
+
|
8
|
+
var _chokidar = _interopRequireDefault(require("chokidar"));
|
9
|
+
|
10
|
+
var _browser = require("./browser");
|
11
|
+
|
12
|
+
var _logger = require("../../logger");
|
13
|
+
|
14
|
+
var _parser = _interopRequireDefault(require("../../parser"));
|
15
|
+
|
16
|
+
var _utils = require("../../../server/utils");
|
17
|
+
|
18
|
+
var _shared = require("../../../shared");
|
19
|
+
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
21
|
+
|
22
|
+
async function loadStories(_config, {
|
23
|
+
port
|
24
|
+
}, storiesListener) {
|
25
|
+
let creeveyParamsByStoryId = {};
|
26
|
+
|
27
|
+
const mergeParamsFromTestsToStory = (story, creeveyParams) => {
|
28
|
+
if (story.parameters) {
|
29
|
+
story.parameters.creevey = (0, _shared.combineParameters)(story.parameters.creevey || {}, creeveyParams);
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
const stories = await (0, _browser.loadStories)(_config, {
|
34
|
+
port
|
35
|
+
}, updatedStoriesByFiles => {
|
36
|
+
Array.from(updatedStoriesByFiles.entries()).forEach(([, storiesArray]) => {
|
37
|
+
storiesArray.forEach(story => {
|
38
|
+
const creeveyParams = creeveyParamsByStoryId[story.id];
|
39
|
+
|
40
|
+
if (creeveyParams) {
|
41
|
+
mergeParamsFromTestsToStory(story, creeveyParams);
|
42
|
+
}
|
43
|
+
});
|
44
|
+
});
|
45
|
+
storiesListener(updatedStoriesByFiles);
|
46
|
+
}); // TODO fix test files hot reloading
|
47
|
+
|
48
|
+
creeveyParamsByStoryId = await parseParams(_config
|
49
|
+
/*, (data) => console.log(data) */
|
50
|
+
);
|
51
|
+
Object.entries(stories).forEach(([storyId, story]) => {
|
52
|
+
mergeParamsFromTestsToStory(story, creeveyParamsByStoryId[storyId]);
|
53
|
+
});
|
54
|
+
return stories;
|
55
|
+
}
|
56
|
+
|
57
|
+
function parseParams(config, listener) {
|
58
|
+
if (!config.testDir) {
|
59
|
+
return Promise.resolve({});
|
60
|
+
}
|
61
|
+
|
62
|
+
const testFiles = (0, _utils.readDirRecursive)(config.testDir).filter(file => {
|
63
|
+
var _config$testRegex;
|
64
|
+
|
65
|
+
return (_config$testRegex = config.testRegex) === null || _config$testRegex === void 0 ? void 0 : _config$testRegex.test(file);
|
66
|
+
});
|
67
|
+
|
68
|
+
if (listener) {
|
69
|
+
_chokidar.default.watch(testFiles).on('change', filePath => {
|
70
|
+
_logger.logger.debug(`changed: ${filePath}`); // doesn't work, always returns {} due modules caching
|
71
|
+
// see https://github.com/nodejs/modules/issues/307
|
72
|
+
|
73
|
+
|
74
|
+
void (0, _parser.default)(testFiles).then(data => listener(data));
|
75
|
+
});
|
76
|
+
}
|
77
|
+
|
78
|
+
return (0, _parser.default)(testFiles);
|
79
|
+
}
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
5
5
|
});
|
6
6
|
exports.loadStories = loadStories;
|
7
|
+
exports.extractStoriesData = extractStoriesData;
|
7
8
|
|
8
9
|
var _path = _interopRequireDefault(require("path"));
|
9
10
|
|
@@ -11,17 +12,17 @@ var _cluster = require("cluster");
|
|
11
12
|
|
12
13
|
var _chokidar = _interopRequireDefault(require("chokidar"));
|
13
14
|
|
14
|
-
var _types = require("
|
15
|
+
var _types = require("../../../types");
|
15
16
|
|
16
|
-
var _utils = require("
|
17
|
+
var _utils = require("../../utils");
|
17
18
|
|
18
|
-
var _messages = require("
|
19
|
+
var _messages = require("../../messages");
|
19
20
|
|
20
|
-
var _helpers = require("
|
21
|
+
var _helpers = require("../helpers");
|
21
22
|
|
22
|
-
var _logger = require("
|
23
|
+
var _logger = require("../../logger");
|
23
24
|
|
24
|
-
var _shared = require("
|
25
|
+
var _shared = require("../../../shared");
|
25
26
|
|
26
27
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
27
28
|
|
@@ -30,7 +31,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
|
|
30
31
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
31
32
|
|
32
33
|
async function initStorybookEnvironment() {
|
33
|
-
// @ts-
|
34
|
+
// @ts-expect-error There is no @types/global-jsdom package
|
34
35
|
(await Promise.resolve().then(() => _interopRequireWildcard(require('global-jsdom')))).default(undefined, {
|
35
36
|
url: 'http://localhost'
|
36
37
|
}); // NOTE Cutoff `jsdom` part from userAgent, because storybook check enviroment and create events channel if runs in browser
|
@@ -48,7 +49,7 @@ async function initStorybookEnvironment() {
|
|
48
49
|
if (_cluster.isWorker) logger.warn = _types.noop; // NOTE: disable logger for 5.x storybook
|
49
50
|
|
50
51
|
logger.debug = _types.noop;
|
51
|
-
return Promise.resolve().then(() => _interopRequireWildcard(require('
|
52
|
+
return Promise.resolve().then(() => _interopRequireWildcard(require('../entry')));
|
52
53
|
}
|
53
54
|
|
54
55
|
function watchStories(channel, watcher, initialFiles) {
|
@@ -110,8 +111,8 @@ async function loadStoriesDirectly(config, {
|
|
110
111
|
const {
|
111
112
|
addParameters,
|
112
113
|
configure
|
113
|
-
} = await Promise.resolve().then(() => _interopRequireWildcard(require('
|
114
|
-
const requireContext = await (await Promise.resolve().then(() => _interopRequireWildcard(require('
|
114
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('../entry')));
|
115
|
+
const requireContext = await (await Promise.resolve().then(() => _interopRequireWildcard(require('../../loaders/babel/register')))).default(config, debug);
|
115
116
|
|
116
117
|
const preview = (() => {
|
117
118
|
try {
|
@@ -187,7 +188,8 @@ async function loadStoriesDirectly(config, {
|
|
187
188
|
void startStorybook();
|
188
189
|
});
|
189
190
|
void startStorybook();
|
190
|
-
}
|
191
|
+
} // TODO Do we need to support multiple storybooks here?
|
192
|
+
|
191
193
|
|
192
194
|
async function loadStories(config, {
|
193
195
|
watch,
|
@@ -200,7 +202,7 @@ async function loadStories(config, {
|
|
200
202
|
} = storybookApi;
|
201
203
|
channel.removeAllListeners(Events.CURRENT_STORY_WAS_SET);
|
202
204
|
channel.on('storiesUpdated', storiesListener);
|
203
|
-
let watcher
|
205
|
+
let watcher;
|
204
206
|
if (watch) watcher = _chokidar.default.watch([], {
|
205
207
|
ignoreInitial: true
|
206
208
|
});
|
@@ -209,7 +211,7 @@ async function loadStories(config, {
|
|
209
211
|
const stories = (0, _helpers.isStorybookVersionLessThan)(6) || (0, _helpers.isStorybookVersionGreaterThan)(6, 3) ? data.stories : (0, _shared.denormalizeStoryParameters)(data);
|
210
212
|
const files = new Set(Object.values(stories).map(story => story.parameters.fileName));
|
211
213
|
if (watcher) channel.on(Events.SET_STORIES, watchStories(channel, watcher, files));
|
212
|
-
resolve(
|
214
|
+
resolve(stories);
|
213
215
|
});
|
214
216
|
});
|
215
217
|
if (config.useWebpackToExtractTests) loadStoriesFromBundle(watch);else void loadStoriesDirectly(config, {
|
@@ -217,4 +219,21 @@ async function loadStories(config, {
|
|
217
219
|
debug
|
218
220
|
});
|
219
221
|
return loadPromise;
|
222
|
+
}
|
223
|
+
|
224
|
+
async function extractStoriesData(config, {
|
225
|
+
watch,
|
226
|
+
debug
|
227
|
+
}) {
|
228
|
+
const storybookApi = await initStorybookEnvironment();
|
229
|
+
const Events = await (0, _helpers.importStorybookCoreEvents)();
|
230
|
+
const {
|
231
|
+
channel
|
232
|
+
} = storybookApi;
|
233
|
+
channel.removeAllListeners(Events.CURRENT_STORY_WAS_SET);
|
234
|
+
const loadPromise = new Promise(resolve => channel.once(Events.SET_STORIES, resolve));
|
235
|
+
if (config.useWebpackToExtractTests) loadStoriesFromBundle(watch);else void loadStoriesDirectly(config, {
|
236
|
+
debug
|
237
|
+
});
|
238
|
+
return loadPromise;
|
220
239
|
}
|
package/lib/cjs/server/utils.js
CHANGED
@@ -10,6 +10,7 @@ exports.getCreeveyCache = getCreeveyCache;
|
|
10
10
|
exports.runSequence = runSequence;
|
11
11
|
exports.testsToImages = testsToImages;
|
12
12
|
exports.removeProps = removeProps;
|
13
|
+
exports.readDirRecursive = readDirRecursive;
|
13
14
|
exports.downloadBinary = exports.isInsideDocker = exports.skipOptionKeys = exports.extensions = exports.LOCALHOST_REGEXP = exports.isShuttingDown = void 0;
|
14
15
|
|
15
16
|
var _fs = require("fs");
|
@@ -175,4 +176,10 @@ function removeProps(obj, propPath) {
|
|
175
176
|
if (typeof prop == 'string') delete obj[prop];
|
176
177
|
if ((0, _types.isFunction)(prop)) Object.keys(obj).filter(prop).forEach(key => delete obj[key]);
|
177
178
|
}
|
179
|
+
}
|
180
|
+
|
181
|
+
function readDirRecursive(dirPath) {
|
182
|
+
return [].concat(...(0, _fs.readdirSync)(dirPath, {
|
183
|
+
withFileTypes: true
|
184
|
+
}).map(dirent => dirent.isDirectory() ? readDirRecursive(`${dirPath}/${dirent.name}`) : [`${dirPath}/${dirent.name}`]));
|
178
185
|
}
|