Skip to content
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

SvelteKit: Default to log an action for goto, invalidate and invalidateAll #24955

Merged
merged 5 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions code/e2e-tests/framework-svelte.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,36 @@ test.describe('SvelteKit', () => {
});
await expect(complexLogItem).toBeVisible();
});

test('goto are logged in Actions panel', async ({ page }) => {
const sbPage = new SbPage(page);

await sbPage.navigateToStory('stories/sveltekit/modules/navigation', 'default-actions');
const root = sbPage.previewRoot();
await sbPage.viewAddonPanel('Actions');

const goto = root.locator('button', { hasText: 'goto' });
await goto.click();

const gotoLogItem = page.locator('#storybook-panel-root #panel-tab-content', {
hasText: `/storybook-goto`,
});
await expect(gotoLogItem).toBeVisible();

const invalidate = root.getByRole('button', { name: 'invalidate', exact: true });
await invalidate.click();

const invalidateLogItem = page.locator('#storybook-panel-root #panel-tab-content', {
hasText: `/storybook-invalidate`,
});
await expect(invalidateLogItem).toBeVisible();

const invalidateAll = root.getByRole('button', { name: 'invalidateAll' });
await invalidateAll.click();

const invalidateAllLogItem = page.locator('#storybook-panel-root #panel-tab-content', {
hasText: `"invalidateAll"`,
});
await expect(invalidateAllLogItem).toBeVisible();
});
});
20 changes: 10 additions & 10 deletions code/frameworks/sveltekit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,16 @@ export const MyStory = {

You can add the name of the module you want to mock to `parameters.sveltekit_experimental` (in the example above we are mocking the `stores` module which correspond to `$app/stores`) and then pass the following kind of objects:

| Module | Path in parameters | Kind of objects |
| ------------------------------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| `import { page } from "$app/stores"` | `parameters.sveltekit_experimental.stores.page` | A Partial of the page store |
| `import { navigating } from "$app/stores"` | `parameters.sveltekit_experimental.stores.navigating` | A Partial of the navigating store |
| `import { updated } from "$app/stores"` | `parameters.sveltekit_experimental.stores.updated` | A boolean representing the value of updated (you can also access `check()` which will be a noop) |
| `import { goto } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.goto` | A callback that will be called whenever goto is called |
| `import { invalidate } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.invalidate` | A callback that will be called whenever invalidate is called |
| `import { invalidateAll } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.invalidateAll` | A callback that will be called whenever invalidateAll is called |
| `import { afterNavigate } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.afterNavigate` | An object that will be passed to the afterNavigate function (which will be invoked onMount) called |
| `import { enhance } from "$app/forms"` | `parameters.sveltekit_experimental.forms.enhance` | A callback that will called when a form with `use:enhance` is submitted |
| Module | Path in parameters | Kind of objects |
| ------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `import { page } from "$app/stores"` | `parameters.sveltekit_experimental.stores.page` | A Partial of the page store |
| `import { navigating } from "$app/stores"` | `parameters.sveltekit_experimental.stores.navigating` | A Partial of the navigating store |
| `import { updated } from "$app/stores"` | `parameters.sveltekit_experimental.stores.updated` | A boolean representing the value of updated (you can also access `check()` which will be a noop) |
| `import { goto } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.goto` | A callback that will be called whenever goto is called, in no function is provided an action will be logged to the Actions panel |
| `import { invalidate } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.invalidate` | A callback that will be called whenever invalidate is called, in no function is provided an action will be logged to the Actions panel |
| `import { invalidateAll } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.invalidateAll` | A callback that will be called whenever invalidateAll is called, in no function is provided an action will be logged to the Actions panel |
| `import { afterNavigate } from "$app/navigation"` | `parameters.sveltekit_experimental.navigation.afterNavigate` | An object that will be passed to the afterNavigate function (which will be invoked onMount) called |
| `import { enhance } from "$app/forms"` | `parameters.sveltekit_experimental.forms.enhance` | A callback that will called when a form with `use:enhance` is submitted |

All the other functions are still exported as `noop` from the mocked modules so that your application will still work.

Expand Down
31 changes: 21 additions & 10 deletions code/frameworks/sveltekit/src/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,14 @@ export const decorators: Decorator[] = [
* eg. storybook:goto, storybook:invalidateAll
* @param baseModule the base module where the function lives (navigation|forms)
* @param functions the list of functions in that module that emit events
* @param {boolean} [defaultToAction] the list of functions in that module that emit events
* @returns a function to remove all the listener added
*/
function createListeners(baseModule: keyof SvelteKitParameters, functions: string[]) {
function createListeners(
baseModule: keyof SvelteKitParameters,
functions: string[],
defaultToAction?: boolean
) {
// the array of every added listener, we can use this in the return function
// to clean them
const toRemove: Array<{
Expand All @@ -75,10 +80,11 @@ export const decorators: Decorator[] = [
functions.forEach((func) => {
// we loop over every function and check if the user actually passed
// a function in sveltekit_experimental[baseModule][func] eg. sveltekit_experimental.navigation.goto
if (
const hasFunction =
(svelteKitParameters as any)[baseModule]?.[func] &&
(svelteKitParameters as any)[baseModule][func] instanceof Function
) {
(svelteKitParameters as any)[baseModule][func] instanceof Function;
// if we default to an action we still add the listener (this will be the case for goto, invalidate, invalidateAll)
if (hasFunction || defaultToAction) {
// we create the listener that will just get the detail array from the custom element
// and call the user provided function spreading this args in...this will basically call
// the function that the user provide with the same arguments the function is invoked to
Expand All @@ -87,7 +93,12 @@ export const decorators: Decorator[] = [
// it provided to storybook will be called with "/my-route"
const listener = ({ detail = [] as any[] }) => {
const args = Array.isArray(detail) ? detail : [];
(svelteKitParameters as any)[baseModule][func](...args);
// if it has a function in the parameters we call that function
// otherwise we invoke the action
const fnToCall = hasFunction
? (svelteKitParameters as any)[baseModule][func]
: action(func);
fnToCall(...args);
};
const eventType = `storybook:${func}`;
toRemove.push({ eventType, listener });
Expand All @@ -104,11 +115,11 @@ export const decorators: Decorator[] = [
};
}

const removeNavigationListeners = createListeners('navigation', [
'goto',
'invalidate',
'invalidateAll',
]);
const removeNavigationListeners = createListeners(
'navigation',
['goto', 'invalidate', 'invalidateAll'],
true
);
const removeFormsListeners = createListeners('forms', ['enhance']);
window.addEventListener('click', globalClickListener);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@

<button
on:click={() => {
goto('/storybook');
goto('/storybook-goto');
}}>goto</button
>

<button
on:click={() => {
invalidate('/storybook');
invalidate('/storybook-invalidate');
}}>invalidate</button
>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const Goto = {
const canvas = within(canvasElement);
const button = canvas.getByText('goto');
button.click();
expect(goto).toHaveBeenCalledWith('/storybook');
expect(goto).toHaveBeenCalledWith('/storybook-goto');
},
parameters: {
sveltekit_experimental: {
Expand All @@ -25,14 +25,16 @@ export const Goto = {
},
};

export const DefaultActions = {};

const invalidate = fn();

export const Invalidate = {
async play({ canvasElement }) {
const canvas = within(canvasElement);
const button = canvas.getByText('invalidate', { exact: true });
button.click();
expect(invalidate).toHaveBeenCalledWith('/storybook');
expect(invalidate).toHaveBeenCalledWith('/storybook-invalidate');
},
parameters: {
sveltekit_experimental: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

<button
on:click={() => {
goto('/storybook');
goto('/storybook-goto');
}}>goto</button
>

<button
on:click={() => {
invalidate('/storybook');
invalidate('/storybook-invalidate');
}}>invalidate</button
>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const Goto = {
const canvas = within(canvasElement);
const button = canvas.getByText('goto');
button.click();
expect(goto).toHaveBeenCalledWith('/storybook');
expect(goto).toHaveBeenCalledWith('/storybook-goto');
},
parameters: {
sveltekit_experimental: {
Expand All @@ -25,14 +25,16 @@ export const Goto = {
},
};

export const DefaultActions = {};

const invalidate = fn();

export const Invalidate = {
async play({ canvasElement }) {
const canvas = within(canvasElement);
const button = canvas.getByText('invalidate', { exact: true });
button.click();
expect(invalidate).toHaveBeenCalledWith('/storybook');
expect(invalidate).toHaveBeenCalledWith('/storybook-invalidate');
},
parameters: {
sveltekit_experimental: {
Expand Down