creevey 0.7.37 → 0.8.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 +30 -5
- package/README.md +1 -1
- package/docs/config.md +37 -5
- package/docs/grid.md +2 -1
- package/lib/cjs/client/addon/Manager.js +3 -1
- package/lib/cjs/client/addon/utils.js +1 -41
- package/lib/cjs/client/addon/withCreevey.js +11 -13
- package/lib/cjs/client/web/1.js +2 -2
- package/lib/cjs/client/web/2.js +1 -1
- package/lib/cjs/client/web/main.js +6 -6
- package/lib/cjs/index.js +14 -1
- package/lib/cjs/server/config.js +3 -0
- package/lib/cjs/server/extract.js +7 -3
- package/lib/cjs/server/loaders/babel/register.js +2 -1
- package/lib/cjs/server/loaders/webpack/compile.js +3 -19
- package/lib/cjs/server/loaders/webpack/creevey-loader.js +1 -1
- package/lib/cjs/server/master/master.js +3 -5
- package/lib/cjs/server/selenium/browser.js +25 -11
- package/lib/cjs/server/selenium/selenoid.js +1 -1
- package/lib/cjs/server/stories.js +20 -226
- package/lib/cjs/server/storybook/entry.js +5 -4
- package/lib/cjs/server/storybook/helpers.js +40 -4
- package/lib/cjs/server/storybook/nodejs-provider.js +220 -0
- package/lib/cjs/server/utils.js +25 -2
- package/lib/cjs/server/worker/helpers.js +8 -9
- package/lib/cjs/server/worker/worker.js +1 -2
- package/lib/cjs/shared.js +35 -0
- package/lib/esm/client/addon/Manager.js +3 -2
- package/lib/esm/client/addon/utils.js +1 -33
- package/lib/esm/client/addon/withCreevey.js +1 -1
- package/lib/esm/index.js +3 -1
- package/lib/esm/server/config.js +4 -1
- package/lib/esm/server/extract.js +7 -3
- package/lib/esm/server/loaders/babel/register.js +3 -2
- package/lib/esm/server/loaders/webpack/compile.js +4 -20
- package/lib/esm/server/loaders/webpack/creevey-loader.js +1 -1
- package/lib/esm/server/master/master.js +3 -5
- package/lib/esm/server/selenium/browser.js +22 -7
- package/lib/esm/server/selenium/selenoid.js +1 -1
- package/lib/esm/server/stories.js +23 -219
- package/lib/esm/server/storybook/entry.js +4 -4
- package/lib/esm/server/storybook/helpers.js +36 -4
- package/lib/esm/server/storybook/nodejs-provider.js +200 -0
- package/lib/esm/server/utils.js +23 -1
- package/lib/esm/server/worker/helpers.js +8 -9
- package/lib/esm/server/worker/worker.js +1 -2
- package/lib/esm/shared.js +22 -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 +22 -22
- package/lib/types/client/addon/register.d.ts +3 -3
- package/lib/types/client/addon/utils.d.ts +2 -6
- package/lib/types/client/addon/withCreevey.d.ts +13 -46
- 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/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 +6 -6
- package/lib/types/server/master/pool.d.ts +30 -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 +18 -18
- package/lib/types/server/selenium/browser.d.ts +14 -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 -13
- package/lib/types/server/storybook/entry.d.ts +18 -14
- package/lib/types/server/storybook/helpers.d.ts +24 -22
- package/lib/types/server/storybook/nodejs-provider.d.ts +5 -0
- package/lib/types/server/update.d.ts +2 -2
- package/lib/types/server/utils.d.ts +19 -18
- package/lib/types/server/worker/chai-image.d.ts +6 -6
- package/lib/types/server/worker/helpers.d.ts +7 -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 +4 -0
- package/lib/types/types.d.ts +459 -431
- package/package.json +53 -48
- package/types/mocha.d.ts +1 -0
- package/storybook-static/stories.json +0 -530
@@ -1,15 +1,11 @@
|
|
1
1
|
import path from 'path';
|
2
2
|
import { mkdirSync, writeFileSync } from 'fs';
|
3
|
-
import { isWorker, isMaster } from 'cluster';
|
4
3
|
import { createHash } from 'crypto';
|
5
|
-
import
|
6
|
-
import { isDefined, isFunction, isObject
|
7
|
-
import { shouldSkip,
|
8
|
-
import {
|
9
|
-
import {
|
10
|
-
import { importStorybookClientLogger, importStorybookConfig, importStorybookCoreCommon, importStorybookCoreEvents, isStorybookVersionLessThan } from './storybook/helpers';
|
11
|
-
import { logger } from './logger';
|
12
|
-
export let storybookApi = null;
|
4
|
+
import { mapValues, pick } from 'lodash';
|
5
|
+
import { isDefined, isFunction, isObject } from '../types';
|
6
|
+
import { shouldSkip, removeProps } from './utils';
|
7
|
+
import { isStorybookVersionGreaterThan, isStorybookVersionLessThan } from './storybook/helpers';
|
8
|
+
import { denormalizeStoryParameters } from '../shared';
|
13
9
|
|
14
10
|
function storyTestFabric(delay, testFn) {
|
15
11
|
return async function storyTest() {
|
@@ -83,214 +79,9 @@ function convertStories(browsers, stories) {
|
|
83
79
|
return tests;
|
84
80
|
}
|
85
81
|
|
86
|
-
async function
|
87
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
88
|
-
(await import('jsdom-global')).default(undefined, {
|
89
|
-
url: 'http://localhost'
|
90
|
-
}); // NOTE Cutoff `jsdom` part from userAgent, because storybook check enviroment and create events channel if runs in browser
|
91
|
-
// https://github.com/storybookjs/storybook/blob/v5.2.8/lib/core/src/client/preview/start.js#L98
|
92
|
-
// Example: "Mozilla/5.0 (linux) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/15.2.1"
|
93
|
-
|
94
|
-
Object.defineProperty(window.navigator, 'userAgent', {
|
95
|
-
value: window.navigator.userAgent.split(' ').filter(token => !token.startsWith('jsdom')).join(' ')
|
96
|
-
}); // TODO Look at creevey debug flag
|
97
|
-
|
98
|
-
const {
|
99
|
-
logger
|
100
|
-
} = await importStorybookClientLogger(); // NOTE: Disable duplication warnings for >=6.2 storybook
|
101
|
-
|
102
|
-
if (isWorker) logger.warn = noop; // NOTE: disable logger for 5.x storybook
|
103
|
-
|
104
|
-
logger.debug = noop;
|
105
|
-
return import('./storybook/entry');
|
106
|
-
}
|
107
|
-
|
108
|
-
function watchStories(channel, watcher, initialFiles) {
|
109
|
-
const watchingFiles = initialFiles;
|
110
|
-
let storiesByFiles = new Map();
|
111
|
-
subscribeOn('shutdown', () => void watcher.close());
|
112
|
-
watcher.add(Array.from(watchingFiles));
|
113
|
-
watcher.on('change', filePath => storiesByFiles.set(path.isAbsolute(filePath) ? filePath : `./${filePath.replace(/\\/g, '/')}`, []));
|
114
|
-
watcher.on('unlink', filePath => storiesByFiles.set(path.isAbsolute(filePath) ? filePath : `./${filePath.replace(/\\/g, '/')}`, []));
|
115
|
-
return data => {
|
116
|
-
const stories = isStorybookVersionLessThan(6) ? data.stories : flatStories(data);
|
117
|
-
const files = new Set(Object.values(stories).map(story => story.parameters.fileName));
|
118
|
-
const addedFiles = Array.from(files).filter(filePath => !watchingFiles.has(filePath));
|
119
|
-
const removedFiles = Array.from(watchingFiles).filter(filePath => !files.has(filePath));
|
120
|
-
watcher.add(addedFiles);
|
121
|
-
addedFiles.forEach(filePath => {
|
122
|
-
watchingFiles.add(filePath);
|
123
|
-
storiesByFiles.set(filePath, []);
|
124
|
-
});
|
125
|
-
removedFiles.forEach(filePath => watchingFiles.delete(filePath));
|
126
|
-
Object.values(stories).forEach(story => {
|
127
|
-
var _storiesByFiles$get;
|
128
|
-
|
129
|
-
return (_storiesByFiles$get = storiesByFiles.get(story.parameters.fileName)) === null || _storiesByFiles$get === void 0 ? void 0 : _storiesByFiles$get.push(story);
|
130
|
-
});
|
131
|
-
channel.emit('storiesUpdated', storiesByFiles);
|
132
|
-
storiesByFiles = new Map();
|
133
|
-
};
|
134
|
-
} // TODO use the storybook version, after the fix of skip option API
|
135
|
-
|
136
|
-
|
137
|
-
function flatStories({
|
138
|
-
globalParameters,
|
139
|
-
kindParameters,
|
140
|
-
stories
|
141
|
-
}) {
|
142
|
-
Object.values(stories).forEach(story => {
|
143
|
-
// NOTE: Copy-paste merge parameters from storybook
|
144
|
-
story.parameters = mergeWith({}, globalParameters, kindParameters[story.kind], story.parameters, (objValue, srcValue) => Array.isArray(objValue) ? objValue.concat(srcValue) : undefined);
|
145
|
-
});
|
146
|
-
return stories;
|
147
|
-
}
|
148
|
-
|
149
|
-
function loadStoriesFromBundle(watch) {
|
150
|
-
const bundlePath = path.join(getCreeveyCache(), 'storybook/main.js');
|
151
|
-
|
152
|
-
if (watch) {
|
153
|
-
subscribeOn('webpack', message => {
|
154
|
-
if (message.type != 'rebuild succeeded') return;
|
155
|
-
Object.values(global.__CREEVEY_HMR_DATA__).filter(({
|
156
|
-
callback
|
157
|
-
}) => callback).forEach(({
|
158
|
-
data,
|
159
|
-
callback
|
160
|
-
}) => callback(data));
|
161
|
-
delete require.cache[bundlePath];
|
162
|
-
import(bundlePath);
|
163
|
-
});
|
164
|
-
}
|
165
|
-
|
166
|
-
import(bundlePath);
|
167
|
-
}
|
168
|
-
|
169
|
-
async function loadStoriesDirectly(config, {
|
170
|
-
watcher,
|
171
|
-
debug
|
172
|
-
}) {
|
173
|
-
const {
|
174
|
-
toRequireContext
|
175
|
-
} = await importStorybookCoreCommon();
|
176
|
-
const {
|
177
|
-
addParameters,
|
178
|
-
configure
|
179
|
-
} = await import('./storybook/entry');
|
180
|
-
const requireContext = await (await import('./loaders/babel/register')).default(config, debug);
|
181
|
-
|
182
|
-
const preview = (() => {
|
183
|
-
try {
|
184
|
-
return require.resolve(`${config.storybookDir}/preview`);
|
185
|
-
} catch (_) {
|
186
|
-
/* noop */
|
187
|
-
}
|
188
|
-
})();
|
189
|
-
|
190
|
-
const {
|
191
|
-
stories
|
192
|
-
} = await importStorybookConfig();
|
193
|
-
const contexts = stories.map(input => {
|
194
|
-
const {
|
195
|
-
path: storiesPath,
|
196
|
-
recursive,
|
197
|
-
match
|
198
|
-
} = toRequireContext(input);
|
199
|
-
watcher === null || watcher === void 0 ? void 0 : watcher.add(path.resolve(config.storybookDir, storiesPath));
|
200
|
-
return () => requireContext(storiesPath, recursive, new RegExp(match));
|
201
|
-
});
|
202
|
-
|
203
|
-
let disposeCallback = data => void data;
|
204
|
-
|
205
|
-
Object.assign(module, {
|
206
|
-
hot: {
|
207
|
-
data: {},
|
208
|
-
|
209
|
-
accept() {
|
210
|
-
/* noop */
|
211
|
-
},
|
212
|
-
|
213
|
-
dispose(callback) {
|
214
|
-
disposeCallback = callback;
|
215
|
-
}
|
216
|
-
|
217
|
-
}
|
218
|
-
});
|
219
|
-
|
220
|
-
async function startStorybook() {
|
221
|
-
if (preview) {
|
222
|
-
const {
|
223
|
-
parameters,
|
224
|
-
globals,
|
225
|
-
globalTypes
|
226
|
-
} = await import(preview);
|
227
|
-
if (parameters) addParameters(parameters);
|
228
|
-
if (globals) addParameters({
|
229
|
-
globals
|
230
|
-
});
|
231
|
-
if (globalTypes) addParameters({
|
232
|
-
globalTypes
|
233
|
-
});
|
234
|
-
}
|
235
|
-
|
236
|
-
try {
|
237
|
-
configure(contexts.map(ctx => ctx()), module, false);
|
238
|
-
} catch (error) {
|
239
|
-
if (isMaster) logger.error(error);
|
240
|
-
}
|
241
|
-
}
|
242
|
-
|
243
|
-
watcher === null || watcher === void 0 ? void 0 : watcher.add(config.storybookDir);
|
244
|
-
watcher === null || watcher === void 0 ? void 0 : watcher.on('all', (_event, filename) => {
|
245
|
-
var _module$hot;
|
246
|
-
|
247
|
-
disposeCallback((_module$hot = module.hot) === null || _module$hot === void 0 ? void 0 : _module$hot.data);
|
248
|
-
delete require.cache[filename];
|
249
|
-
void startStorybook();
|
250
|
-
});
|
251
|
-
void startStorybook();
|
252
|
-
}
|
253
|
-
|
254
|
-
async function loadStorybook(config, {
|
255
|
-
watch,
|
256
|
-
debug
|
257
|
-
}, storiesListener) {
|
258
|
-
storybookApi = await initStorybookEnvironment();
|
259
|
-
const Events = await importStorybookCoreEvents();
|
260
|
-
const {
|
261
|
-
channel
|
262
|
-
} = storybookApi;
|
263
|
-
channel.removeAllListeners(Events.CURRENT_STORY_WAS_SET);
|
264
|
-
channel.on('storiesUpdated', storiesListener);
|
265
|
-
let watcher = null;
|
266
|
-
if (watch) watcher = chokidar.watch([], {
|
267
|
-
ignoreInitial: true
|
268
|
-
});
|
269
|
-
const loadPromise = new Promise(resolve => {
|
270
|
-
channel.once(Events.SET_STORIES, data => {
|
271
|
-
const stories = isStorybookVersionLessThan(6) ? data.stories : flatStories(data);
|
272
|
-
const files = new Set(Object.values(stories).map(story => story.parameters.fileName));
|
273
|
-
if (watcher) channel.on(Events.SET_STORIES, watchStories(channel, watcher, files));
|
274
|
-
resolve(stories);
|
275
|
-
});
|
276
|
-
});
|
277
|
-
if (config.useWebpackToExtractTests) loadStoriesFromBundle(watch);else void loadStoriesDirectly(config, {
|
278
|
-
watcher,
|
279
|
-
debug
|
280
|
-
});
|
281
|
-
return loadPromise;
|
282
|
-
}
|
283
|
-
|
284
|
-
export async function loadTestsFromStories(config, browsers, {
|
285
|
-
watch = false,
|
286
|
-
debug = false,
|
287
|
-
update
|
288
|
-
}) {
|
82
|
+
export async function loadTestsFromStories(browsers, provider, update) {
|
289
83
|
const testIdsByFiles = new Map();
|
290
|
-
const
|
291
|
-
debug,
|
292
|
-
watch
|
293
|
-
}, storiesByFiles => {
|
84
|
+
const data = await provider(storiesByFiles => {
|
294
85
|
const testsDiff = {};
|
295
86
|
Array.from(storiesByFiles.entries()).forEach(([filename, stories]) => {
|
296
87
|
var _testIdsByFiles$get$f, _testIdsByFiles$get;
|
@@ -304,6 +95,7 @@ export async function loadTestsFromStories(config, browsers, {
|
|
304
95
|
});
|
305
96
|
update === null || update === void 0 ? void 0 : update(testsDiff);
|
306
97
|
});
|
98
|
+
const stories = isStorybookVersionLessThan(6) || isStorybookVersionGreaterThan(6, 3) ? data.stories : denormalizeStoryParameters(data);
|
307
99
|
const tests = convertStories(browsers, stories);
|
308
100
|
Object.values(tests).filter(isDefined).forEach(({
|
309
101
|
id,
|
@@ -321,11 +113,23 @@ export async function loadTestsFromStories(config, browsers, {
|
|
321
113
|
});
|
322
114
|
return tests;
|
323
115
|
}
|
324
|
-
export function saveStoriesJson(extract) {
|
325
|
-
var
|
116
|
+
export function saveStoriesJson(storiesData, extract) {
|
117
|
+
var _storiesData$stories;
|
326
118
|
|
327
119
|
const outputDir = typeof extract == 'boolean' ? 'storybook-static' : extract;
|
328
|
-
|
120
|
+
|
121
|
+
if (!isStorybookVersionLessThan(6)) {
|
122
|
+
// NOTE Copy-pasted from Storybook's `getStoriesJsonData` method
|
123
|
+
const allowed = ['fileName', 'docsOnly', 'framework', '__id', '__isArgsStory'];
|
124
|
+
storiesData.globalParameters = pick(storiesData.globalParameters, allowed); // @ts-expect-error ignore error
|
125
|
+
|
126
|
+
storiesData.kindParameters = mapValues(storiesData.kindParameters, v => pick(v, allowed)); // @ts-expect-error ignore error
|
127
|
+
|
128
|
+
storiesData.stories = mapValues(storiesData.stories, v => ({ ...pick(v, ['id', 'name', 'kind', 'story']),
|
129
|
+
parameters: pick(v.parameters, allowed)
|
130
|
+
}));
|
131
|
+
} // TODO Fix args stories
|
132
|
+
|
329
133
|
|
330
134
|
removeProps(storiesData !== null && storiesData !== void 0 ? storiesData : {}, ['stories', () => true, 'parameters', '__isArgsStory']);
|
331
135
|
Object.values((_storiesData$stories = storiesData === null || storiesData === void 0 ? void 0 : storiesData.stories) !== null && _storiesData$stories !== void 0 ? _storiesData$stories : {}).forEach(story => isObject(story) && 'parameters' in story && isObject(story.parameters) && delete story.parameters.__isArgsStory);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
var _api$channel, _api$context;
|
2
2
|
|
3
|
+
import { addons } from '@storybook/addons';
|
3
4
|
import { getStorybookFramework, isStorybookVersionLessThan, resolveFromStorybook } from './helpers';
|
4
5
|
const framework = getStorybookFramework(); // eslint-disable-next-line @typescript-eslint/no-var-requires
|
5
6
|
|
@@ -8,10 +9,8 @@ const core = require(resolveFromStorybook('@storybook/core')); //@ts-expect-erro
|
|
8
9
|
|
9
10
|
|
10
11
|
const start = isStorybookVersionLessThan(6, 2) ? core.default.start : core.start;
|
11
|
-
const api = start(() => void 0);
|
12
|
-
|
13
|
-
|
14
|
-
export const channel = (_api$channel = api.channel) !== null && _api$channel !== void 0 ? _api$channel : (_api$context = api.context) === null || _api$context === void 0 ? void 0 : _api$context.channel;
|
12
|
+
const api = start(() => void 0);
|
13
|
+
export const channel = isStorybookVersionLessThan(6, 4) ? (_api$channel = api.channel) !== null && _api$channel !== void 0 ? _api$channel : (_api$context = api.context) === null || _api$context === void 0 ? void 0 : _api$context.channel : addons.getChannel();
|
15
14
|
export const clientApi = api.clientApi;
|
16
15
|
export const forceReRender = api.forceReRender;
|
17
16
|
export const storiesOf = (kind, m) => {
|
@@ -23,6 +22,7 @@ export const configure = (...args) => {
|
|
23
22
|
if (isStorybookVersionLessThan(5, 2)) {
|
24
23
|
//NOTE: Storybook <= 5.1 pass args as is
|
25
24
|
//@ts-expect-error: ignore it
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
|
26
26
|
return api.configApi.configure(...args);
|
27
27
|
}
|
28
28
|
|
@@ -45,16 +45,22 @@ export function isStorybookVersionLessThan(major, minor) {
|
|
45
45
|
const [sbMajor, sbMinor] = ((_process$env$__CREEVE = process.env.__CREEVEY_STORYBOOK_VERSION__) !== null && _process$env$__CREEVE !== void 0 ? _process$env$__CREEVE : getStorybookVersion()).split('.');
|
46
46
|
return Number(sbMajor) < major || minor != undefined && Number(sbMajor) == major && Number(sbMinor) < minor;
|
47
47
|
}
|
48
|
-
export function
|
48
|
+
export function isStorybookVersionGreaterThan(major, minor) {
|
49
49
|
var _process$env$__CREEVE2;
|
50
50
|
|
51
51
|
const [sbMajor, sbMinor] = ((_process$env$__CREEVE2 = process.env.__CREEVEY_STORYBOOK_VERSION__) !== null && _process$env$__CREEVE2 !== void 0 ? _process$env$__CREEVE2 : getStorybookVersion()).split('.');
|
52
|
+
return Number(sbMajor) > major || minor != undefined && Number(sbMajor) == major && Number(sbMinor) > minor;
|
53
|
+
}
|
54
|
+
export function isStorybookVersion(major, minor) {
|
55
|
+
var _process$env$__CREEVE3;
|
56
|
+
|
57
|
+
const [sbMajor, sbMinor] = ((_process$env$__CREEVE3 = process.env.__CREEVEY_STORYBOOK_VERSION__) !== null && _process$env$__CREEVE3 !== void 0 ? _process$env$__CREEVE3 : getStorybookVersion()).split('.');
|
52
58
|
return Number(sbMajor) == major || minor != undefined && Number(sbMajor) == major && Number(sbMinor) == minor;
|
53
59
|
}
|
54
60
|
export function getStorybookFramework() {
|
55
|
-
var _process$env$
|
61
|
+
var _process$env$__CREEVE4;
|
56
62
|
|
57
|
-
const framework = (_process$env$
|
63
|
+
const framework = (_process$env$__CREEVE4 = process.env.__CREEVEY_STORYBOOK_FRAMEWORK__) !== null && _process$env$__CREEVE4 !== void 0 ? _process$env$__CREEVE4 : supportedFrameworks.find(framework => {
|
58
64
|
try {
|
59
65
|
return require.resolve(resolveFromStorybook(`@storybook/${framework}`));
|
60
66
|
} catch (_) {
|
@@ -70,5 +76,31 @@ export const storybookConfigRef = {
|
|
70
76
|
}
|
71
77
|
};
|
72
78
|
export async function importStorybookConfig() {
|
73
|
-
|
79
|
+
const configPath = `${storybookDirRef.current}/main`;
|
80
|
+
|
81
|
+
try {
|
82
|
+
return storybookConfigRef.current = (await import(require.resolve(configPath))).default;
|
83
|
+
} catch (_) {
|
84
|
+
const storybookUtilsPath = isStorybookVersionLessThan(6, 2) ? '@storybook/core/dist/server/utils' : '@storybook/core-common/dist/cjs/utils';
|
85
|
+
const serverRequireModule = isStorybookVersionLessThan(6, 2) ? 'server-require' : 'interpret-require'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
86
|
+
|
87
|
+
const {
|
88
|
+
getInterpretedFile
|
89
|
+
} = await import(resolveFromStorybook(`${storybookUtilsPath}/interpret-files`)); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
90
|
+
|
91
|
+
const {
|
92
|
+
default: serverRequireFallback,
|
93
|
+
serverRequire = serverRequireFallback
|
94
|
+
} = await import(resolveFromStorybook(`${storybookUtilsPath}/${serverRequireModule}`)); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
95
|
+
|
96
|
+
const mainConfigFile = isStorybookVersionLessThan(6, 1) ? configPath : // eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
97
|
+
getInterpretedFile(configPath); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
|
98
|
+
|
99
|
+
return storybookConfigRef.current = serverRequire(mainConfigFile);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
export async function isCSFv3Enabled() {
|
103
|
+
var _await$importStoryboo, _await$importStoryboo2, _await$importStoryboo3;
|
104
|
+
|
105
|
+
return (_await$importStoryboo = (_await$importStoryboo2 = await importStorybookConfig()) === null || _await$importStoryboo2 === void 0 ? void 0 : (_await$importStoryboo3 = _await$importStoryboo2.features) === null || _await$importStoryboo3 === void 0 ? void 0 : _await$importStoryboo3.previewCsfV3) !== null && _await$importStoryboo !== void 0 ? _await$importStoryboo : false;
|
74
106
|
}
|
@@ -0,0 +1,200 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/ban-ts-comment */
|
2
|
+
import path from 'path';
|
3
|
+
import { isWorker, isMaster } from 'cluster';
|
4
|
+
import chokidar from 'chokidar';
|
5
|
+
import { noop } from '../../types';
|
6
|
+
import { getCreeveyCache } from '../utils';
|
7
|
+
import { subscribeOn } from '../messages';
|
8
|
+
import { importStorybookClientLogger, importStorybookConfig, importStorybookCoreCommon, importStorybookCoreEvents, isStorybookVersionGreaterThan, isStorybookVersionLessThan } from './helpers';
|
9
|
+
import { logger } from '../logger';
|
10
|
+
import { denormalizeStoryParameters } from '../../shared';
|
11
|
+
|
12
|
+
async function initStorybookEnvironment() {
|
13
|
+
// @ts-ignore
|
14
|
+
(await import('global-jsdom')).default(undefined, {
|
15
|
+
url: 'http://localhost'
|
16
|
+
}); // NOTE Cutoff `jsdom` part from userAgent, because storybook check enviroment and create events channel if runs in browser
|
17
|
+
// https://github.com/storybookjs/storybook/blob/v5.2.8/lib/core/src/client/preview/start.js#L98
|
18
|
+
// Example: "Mozilla/5.0 (linux) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/15.2.1"
|
19
|
+
|
20
|
+
Object.defineProperty(window.navigator, 'userAgent', {
|
21
|
+
value: window.navigator.userAgent.split(' ').filter(token => !token.startsWith('jsdom')).join(' ')
|
22
|
+
}); // TODO Look at creevey debug flag
|
23
|
+
|
24
|
+
const {
|
25
|
+
logger
|
26
|
+
} = await importStorybookClientLogger(); // NOTE: Disable duplication warnings for >=6.2 storybook
|
27
|
+
|
28
|
+
if (isWorker) logger.warn = noop; // NOTE: disable logger for 5.x storybook
|
29
|
+
|
30
|
+
logger.debug = noop;
|
31
|
+
return import('./entry');
|
32
|
+
}
|
33
|
+
|
34
|
+
function watchStories(channel, watcher, initialFiles) {
|
35
|
+
const watchingFiles = initialFiles;
|
36
|
+
let storiesByFiles = new Map();
|
37
|
+
subscribeOn('shutdown', () => void watcher.close());
|
38
|
+
watcher.add(Array.from(watchingFiles));
|
39
|
+
watcher.on('change', filePath => storiesByFiles.set(path.isAbsolute(filePath) ? filePath : `./${filePath.replace(/\\/g, '/')}`, []));
|
40
|
+
watcher.on('unlink', filePath => storiesByFiles.set(path.isAbsolute(filePath) ? filePath : `./${filePath.replace(/\\/g, '/')}`, []));
|
41
|
+
return data => {
|
42
|
+
const stories = isStorybookVersionLessThan(6) || isStorybookVersionGreaterThan(6, 3) ? data.stories : denormalizeStoryParameters(data);
|
43
|
+
const files = new Set(Object.values(stories).map(story => story.parameters.fileName));
|
44
|
+
const addedFiles = Array.from(files).filter(filePath => !watchingFiles.has(filePath));
|
45
|
+
const removedFiles = Array.from(watchingFiles).filter(filePath => !files.has(filePath));
|
46
|
+
watcher.add(addedFiles);
|
47
|
+
addedFiles.forEach(filePath => {
|
48
|
+
watchingFiles.add(filePath);
|
49
|
+
storiesByFiles.set(filePath, []);
|
50
|
+
});
|
51
|
+
removedFiles.forEach(filePath => watchingFiles.delete(filePath));
|
52
|
+
Object.values(stories).forEach(story => {
|
53
|
+
var _storiesByFiles$get;
|
54
|
+
|
55
|
+
return (_storiesByFiles$get = storiesByFiles.get(story.parameters.fileName)) === null || _storiesByFiles$get === void 0 ? void 0 : _storiesByFiles$get.push(story);
|
56
|
+
});
|
57
|
+
channel.emit('storiesUpdated', storiesByFiles);
|
58
|
+
storiesByFiles = new Map();
|
59
|
+
};
|
60
|
+
}
|
61
|
+
|
62
|
+
function loadStoriesFromBundle(watch) {
|
63
|
+
const bundlePath = path.join(getCreeveyCache(), 'storybook/main.js');
|
64
|
+
|
65
|
+
if (watch) {
|
66
|
+
subscribeOn('webpack', message => {
|
67
|
+
if (message.type != 'rebuild succeeded') return;
|
68
|
+
Object.values(global.__CREEVEY_HMR_DATA__).filter(({
|
69
|
+
callback
|
70
|
+
}) => callback).forEach(({
|
71
|
+
data,
|
72
|
+
callback
|
73
|
+
}) => callback(data));
|
74
|
+
delete require.cache[bundlePath];
|
75
|
+
import(bundlePath);
|
76
|
+
});
|
77
|
+
}
|
78
|
+
|
79
|
+
import(bundlePath);
|
80
|
+
}
|
81
|
+
|
82
|
+
async function loadStoriesDirectly(config, {
|
83
|
+
watcher,
|
84
|
+
debug
|
85
|
+
}) {
|
86
|
+
const {
|
87
|
+
toRequireContext,
|
88
|
+
normalizeStoriesEntry
|
89
|
+
} = await importStorybookCoreCommon();
|
90
|
+
const {
|
91
|
+
addParameters,
|
92
|
+
configure
|
93
|
+
} = await import('./entry');
|
94
|
+
const requireContext = await (await import('../loaders/babel/register')).default(config, debug);
|
95
|
+
|
96
|
+
const preview = (() => {
|
97
|
+
try {
|
98
|
+
return require.resolve(`${config.storybookDir}/preview`);
|
99
|
+
} catch (_) {
|
100
|
+
/* noop */
|
101
|
+
}
|
102
|
+
})();
|
103
|
+
|
104
|
+
const {
|
105
|
+
stories
|
106
|
+
} = await importStorybookConfig();
|
107
|
+
const contexts = stories.map(entry => {
|
108
|
+
const normalizedEntry = isStorybookVersionLessThan(6, 4) ? entry : normalizeStoriesEntry(entry, {
|
109
|
+
configDir: config.storybookDir,
|
110
|
+
workingDir: process.cwd()
|
111
|
+
});
|
112
|
+
const {
|
113
|
+
path: storiesPath,
|
114
|
+
recursive,
|
115
|
+
match
|
116
|
+
} = toRequireContext(normalizedEntry);
|
117
|
+
watcher === null || watcher === void 0 ? void 0 : watcher.add(path.resolve(config.storybookDir, storiesPath));
|
118
|
+
return () => requireContext(storiesPath, recursive, new RegExp(match));
|
119
|
+
});
|
120
|
+
|
121
|
+
let disposeCallback = data => void data;
|
122
|
+
|
123
|
+
Object.assign(module, {
|
124
|
+
hot: {
|
125
|
+
data: {},
|
126
|
+
|
127
|
+
accept() {
|
128
|
+
/* noop */
|
129
|
+
},
|
130
|
+
|
131
|
+
dispose(callback) {
|
132
|
+
disposeCallback = callback;
|
133
|
+
}
|
134
|
+
|
135
|
+
}
|
136
|
+
});
|
137
|
+
|
138
|
+
async function startStorybook() {
|
139
|
+
if (preview) {
|
140
|
+
const {
|
141
|
+
parameters,
|
142
|
+
globals,
|
143
|
+
globalTypes
|
144
|
+
} = await import(preview);
|
145
|
+
if (parameters) addParameters(parameters);
|
146
|
+
if (globals) addParameters({
|
147
|
+
globals
|
148
|
+
});
|
149
|
+
if (globalTypes) addParameters({
|
150
|
+
globalTypes
|
151
|
+
});
|
152
|
+
}
|
153
|
+
|
154
|
+
try {
|
155
|
+
configure(contexts.map(ctx => ctx()), module, false);
|
156
|
+
} catch (error) {
|
157
|
+
if (isMaster) logger.error(error);
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
watcher === null || watcher === void 0 ? void 0 : watcher.add(config.storybookDir);
|
162
|
+
watcher === null || watcher === void 0 ? void 0 : watcher.on('all', (_event, filename) => {
|
163
|
+
var _module$hot;
|
164
|
+
|
165
|
+
disposeCallback((_module$hot = module.hot) === null || _module$hot === void 0 ? void 0 : _module$hot.data);
|
166
|
+
delete require.cache[filename];
|
167
|
+
void startStorybook();
|
168
|
+
});
|
169
|
+
void startStorybook();
|
170
|
+
}
|
171
|
+
|
172
|
+
export async function loadStories(config, {
|
173
|
+
watch,
|
174
|
+
debug
|
175
|
+
}, storiesListener) {
|
176
|
+
const storybookApi = await initStorybookEnvironment();
|
177
|
+
const Events = await importStorybookCoreEvents();
|
178
|
+
const {
|
179
|
+
channel
|
180
|
+
} = storybookApi;
|
181
|
+
channel.removeAllListeners(Events.CURRENT_STORY_WAS_SET);
|
182
|
+
channel.on('storiesUpdated', storiesListener);
|
183
|
+
let watcher = null;
|
184
|
+
if (watch) watcher = chokidar.watch([], {
|
185
|
+
ignoreInitial: true
|
186
|
+
});
|
187
|
+
const loadPromise = new Promise(resolve => {
|
188
|
+
channel.once(Events.SET_STORIES, data => {
|
189
|
+
const stories = isStorybookVersionLessThan(6) || isStorybookVersionGreaterThan(6, 3) ? data.stories : denormalizeStoryParameters(data);
|
190
|
+
const files = new Set(Object.values(stories).map(story => story.parameters.fileName));
|
191
|
+
if (watcher) channel.on(Events.SET_STORIES, watchStories(channel, watcher, files));
|
192
|
+
resolve(data);
|
193
|
+
});
|
194
|
+
});
|
195
|
+
if (config.useWebpackToExtractTests) loadStoriesFromBundle(watch);else void loadStoriesDirectly(config, {
|
196
|
+
watcher,
|
197
|
+
debug
|
198
|
+
});
|
199
|
+
return loadPromise;
|
200
|
+
}
|
package/lib/esm/server/utils.js
CHANGED
@@ -9,6 +9,7 @@ export const isShuttingDown = {
|
|
9
9
|
};
|
10
10
|
export const LOCALHOST_REGEXP = /(localhost|127\.0\.0\.1)/i;
|
11
11
|
export const extensions = ['.js', '.jsx', '.ts', '.tsx'];
|
12
|
+
export const skipOptionKeys = ['in', 'kinds', 'stories', 'tests', 'reason'];
|
12
13
|
|
13
14
|
function matchBy(pattern, value) {
|
14
15
|
return typeof pattern == 'string' && pattern == value || Array.isArray(pattern) && pattern.includes(value) || pattern instanceof RegExp && pattern.test(value) || !isDefined(pattern);
|
@@ -20,9 +21,30 @@ export function shouldSkip(browser, meta, skipOptions, test) {
|
|
20
21
|
}
|
21
22
|
|
22
23
|
if (Array.isArray(skipOptions)) {
|
23
|
-
|
24
|
+
for (const skip of skipOptions) {
|
25
|
+
const reason = shouldSkip(browser, meta, skip, test);
|
26
|
+
if (reason) return reason;
|
27
|
+
}
|
28
|
+
|
29
|
+
return false;
|
30
|
+
}
|
31
|
+
|
32
|
+
let hasSkipOptionKeys = false;
|
33
|
+
|
34
|
+
for (const skipKey in skipOptions) {
|
35
|
+
if (skipOptionKeys.includes(skipKey)) {
|
36
|
+
hasSkipOptionKeys = true;
|
37
|
+
continue;
|
38
|
+
}
|
39
|
+
|
40
|
+
const reason = shouldSkip(browser, meta, {
|
41
|
+
reason: skipKey,
|
42
|
+
...skipOptions[skipKey]
|
43
|
+
}, test);
|
44
|
+
if (reason) return reason;
|
24
45
|
}
|
25
46
|
|
47
|
+
if (!hasSkipOptionKeys) return false;
|
26
48
|
const {
|
27
49
|
in: browsers,
|
28
50
|
kinds,
|
@@ -51,15 +51,14 @@ export async function addTestsFromStories(rootSuite, config, {
|
|
51
51
|
debug
|
52
52
|
}) {
|
53
53
|
const mochaTestsById = new Map();
|
54
|
-
const tests = await loadTestsFromStories(
|
54
|
+
const tests = await loadTestsFromStories([browser], listener => config.storiesProvider(config, {
|
55
55
|
watch,
|
56
|
-
debug
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
});
|
56
|
+
debug
|
57
|
+
}, listener), testsDiff => Object.entries(testsDiff).forEach(([id, newTest]) => {
|
58
|
+
const oldTest = mochaTestsById.get(id);
|
59
|
+
mochaTestsById.delete(id);
|
60
|
+
if (oldTest) removeTestOrSuite(oldTest);
|
61
|
+
if (newTest) mochaTestsById.set(id, addTest(rootSuite, newTest));
|
62
|
+
}));
|
64
63
|
Object.values(tests).filter(isDefined).forEach(test => mochaTestsById.set(test.id, addTest(rootSuite, test)));
|
65
64
|
}
|
@@ -22,8 +22,7 @@ async function getStat(filePath) {
|
|
22
22
|
try {
|
23
23
|
return await statAsync(filePath);
|
24
24
|
} catch (error) {
|
25
|
-
|
26
|
-
if (error.code === 'ENOENT') {
|
25
|
+
if (typeof error == 'object' && error && error.code === 'ENOENT') {
|
27
26
|
return null;
|
28
27
|
}
|
29
28
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { mapValues, mergeWith } from 'lodash';
|
2
|
+
// NOTE: Copy-paste from storybook/api
|
3
|
+
export const combineParameters = (...parameterSets) => // eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
4
|
+
mergeWith({}, ...parameterSets, (_, srcValue) => {
|
5
|
+
// Treat arrays as scalars:
|
6
|
+
if (Array.isArray(srcValue)) return srcValue;
|
7
|
+
return undefined;
|
8
|
+
}); // NOTE: Copy-paste from storybook/api
|
9
|
+
|
10
|
+
export const denormalizeStoryParameters = ({
|
11
|
+
globalParameters,
|
12
|
+
kindParameters,
|
13
|
+
stories
|
14
|
+
}) => {
|
15
|
+
return mapValues(stories, storyData => {
|
16
|
+
var _kindParameters$story;
|
17
|
+
|
18
|
+
return { ...storyData,
|
19
|
+
parameters: combineParameters(globalParameters, (_kindParameters$story = kindParameters[storyData.kind]) !== null && _kindParameters$story !== void 0 ? _kindParameters$story : {}, storyData.parameters)
|
20
|
+
};
|
21
|
+
});
|
22
|
+
};
|
package/lib/types/cli.d.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
#!/usr/bin/env node
|
1
|
+
#!/usr/bin/env node
|