-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: ability to generate multiple sets of autotests #28
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,10 +11,19 @@ interface HTMLElement { | |
innerText: string; | ||
} | ||
|
||
type StorybookWindow = Window & | ||
export type StorybookWindow = Window & | ||
typeof globalThis & { | ||
__HERMIONE_OPEN_STORY__: (storyId: string, remountOnly: boolean, done: (result: string) => void) => void; | ||
__STORYBOOK_ADDONS_CHANNEL__: EventEmitter; | ||
__HERMIONE_OPEN_STORY__: ( | ||
storyId: string, | ||
storybookGlobals: Record<string, unknown>, | ||
remountOnly: boolean, | ||
done: (result: string) => void, | ||
) => void; | ||
__TESTPLANE_STORYBOOK_INITIAL_GLOBALS__?: Record<string, unknown>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. storybook does not save initial (default) globals, so we have to do it ourselves |
||
__STORYBOOK_PREVIEW__?: { storeInitializationPromise?: Promise<void> }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storybook preview. Here is |
||
__STORYBOOK_ADDONS_CHANNEL__: EventEmitter & { | ||
data?: { setGlobals?: Array<{ globals: Record<string, unknown> }> }; | ||
}; | ||
__STORYBOOK_ADDON_INTERACTIONS_INSTRUMENTER_STATE__: Record< | ||
string, | ||
{ | ||
|
@@ -34,10 +43,11 @@ export async function inject(browser: WebdriverIO.Browser): Promise<void> { | |
export async function execute( | ||
browser: WebdriverIO.Browser, | ||
storyId: string, | ||
storybookGlobals: Record<string, unknown>, | ||
shouldRemount: boolean, | ||
): Promise<StoryLoadResult> { | ||
const getResult = (): Promise<StoryLoadResult> => | ||
browser.executeAsync(executeOpenStoryScript, storyId, shouldRemount).then(JSON.parse); | ||
browser.executeAsync(executeOpenStoryScript, storyId, storybookGlobals, shouldRemount).then(JSON.parse); | ||
|
||
const result: StoryLoadResult = await getResult(); | ||
|
||
|
@@ -58,7 +68,12 @@ export async function execute( | |
|
||
export default { inject, execute }; | ||
|
||
function openStoryScript(storyId: string, shouldRemount: boolean, done: (result: string) => void): void { | ||
function openStoryScript( | ||
storyId: string, | ||
storybookGlobals: Record<string, unknown>, | ||
shouldRemount: boolean, | ||
done: (result: string) => void, | ||
): void { | ||
function onPageLoad(fn: () => void): void { | ||
if (document.readyState === "complete") { | ||
fn(); | ||
|
@@ -81,6 +96,7 @@ function openStoryScript(storyId: string, shouldRemount: boolean, done: (result: | |
channel.off("storyMissing", onStoryMissing); | ||
channel.off("storyThrewException", onStoryThrewException); | ||
channel.off("storyErrored", onStoryErrored); | ||
channel.off("globalsUpdated", onGlobalsUpdated); | ||
|
||
done(JSON.stringify(value)); | ||
} | ||
|
@@ -140,23 +156,59 @@ function openStoryScript(storyId: string, shouldRemount: boolean, done: (result: | |
doneJson(result); | ||
} | ||
|
||
channel.once("playFunctionThrewException", onPlayFunctionThrewException); | ||
channel.once("storyRendered", onStoryRendered); | ||
channel.once("storyMissing", onStoryMissing); | ||
channel.once("storyThrewException", onStoryThrewException); | ||
channel.once("storyErrored", onStoryErrored); | ||
function onGlobalsUpdated(): void { | ||
channel.once("playFunctionThrewException", onPlayFunctionThrewException); | ||
channel.once("storyRendered", onStoryRendered); | ||
channel.once("storyMissing", onStoryMissing); | ||
channel.once("storyThrewException", onStoryThrewException); | ||
channel.once("storyErrored", onStoryErrored); | ||
|
||
if (shouldRemount) { | ||
channel.emit("setCurrentStory", { storyId: "" }); | ||
if (shouldRemount) { | ||
channel.emit("setCurrentStory", { storyId: "" }); | ||
} | ||
|
||
channel.emit("setCurrentStory", { storyId }); | ||
} | ||
|
||
channel.emit("setCurrentStory", { storyId }); | ||
if (!channel) { | ||
result.loadError = "Couldn't find storybook channel. Looks like the opened page is not storybook preview"; | ||
|
||
doneJson(result); | ||
} | ||
|
||
const storybookPreview = (window as StorybookWindow).__STORYBOOK_PREVIEW__; | ||
const isStorybookPreviewAvailable = storybookPreview && storybookPreview.storeInitializationPromise; | ||
const shouldUpdateStorybookGlobals = storybookGlobals && isStorybookPreviewAvailable; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if |
||
|
||
if (shouldUpdateStorybookGlobals) { | ||
(storybookPreview.storeInitializationPromise as Promise<void>).then(function () { | ||
let defaultGlobals = (window as StorybookWindow).__TESTPLANE_STORYBOOK_INITIAL_GLOBALS__; | ||
|
||
if (!defaultGlobals) { | ||
const setGlobalCalls = (window as StorybookWindow).__STORYBOOK_ADDONS_CHANNEL__.data?.setGlobals; | ||
const initValue = (setGlobalCalls && setGlobalCalls[0].globals) || {}; | ||
|
||
defaultGlobals = (window as StorybookWindow).__TESTPLANE_STORYBOOK_INITIAL_GLOBALS__ = initValue; | ||
} | ||
Comment on lines
+179
to
+192
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Saving first
In this scenario, test2 has globals {a:"b"} already set and he only updates {c:"d"}. So, in order to make tests independent from order, we are merging default globals with user-called globals In other tests in this session we can reuse these default globals from "TESTPLANE_STORYBOOK_INITIAL_GLOBALS" as long as we don't reload the page. And in case if we do, we could pull initial globals from |
||
|
||
channel.once("globalsUpdated", onGlobalsUpdated); | ||
|
||
channel.emit("updateGlobals", { globals: Object.assign({}, defaultGlobals, storybookGlobals) }); | ||
}); | ||
} else { | ||
onGlobalsUpdated(); | ||
} | ||
}); | ||
} | ||
|
||
function executeOpenStoryScript(storyId: string, remountOnly: boolean, done: (result: string) => void): void { | ||
function executeOpenStoryScript( | ||
storyId: string, | ||
storybookGlobals: Record<string, unknown>, | ||
remountOnly: boolean, | ||
done: (result: string) => void, | ||
): void { | ||
if ((window as StorybookWindow).__HERMIONE_OPEN_STORY__) { | ||
(window as StorybookWindow).__HERMIONE_OPEN_STORY__(storyId, remountOnly, done); | ||
(window as StorybookWindow).__HERMIONE_OPEN_STORY__(storyId, storybookGlobals, remountOnly, done); | ||
} else { | ||
done(JSON.stringify({ notInjected: true })); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont want to separate "update globals" to different step because it is extra http request and we would need to re-render the story itself. Because of this, globals are updated right before story setting, so we would have to do this only once.