Storybook Helpers (#35158)
This commit is contained in:
parent
0a7418e6d8
commit
c52848b444
11 changed files with 288 additions and 25 deletions
53
app/javascript/testing/api.ts
Normal file
53
app/javascript/testing/api.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { http, HttpResponse } from 'msw';
|
||||
import { action } from 'storybook/actions';
|
||||
|
||||
import { relationshipsFactory } from './factories';
|
||||
|
||||
export const mockHandlers = {
|
||||
mute: http.post<{ id: string }>('/api/v1/accounts/:id/mute', ({ params }) => {
|
||||
action('muting account')(params);
|
||||
return HttpResponse.json(
|
||||
relationshipsFactory({ id: params.id, muting: true }),
|
||||
);
|
||||
}),
|
||||
unmute: http.post<{ id: string }>(
|
||||
'/api/v1/accounts/:id/unmute',
|
||||
({ params }) => {
|
||||
action('unmuting account')(params);
|
||||
return HttpResponse.json(
|
||||
relationshipsFactory({ id: params.id, muting: false }),
|
||||
);
|
||||
},
|
||||
),
|
||||
block: http.post<{ id: string }>(
|
||||
'/api/v1/accounts/:id/block',
|
||||
({ params }) => {
|
||||
action('blocking account')(params);
|
||||
return HttpResponse.json(
|
||||
relationshipsFactory({ id: params.id, blocking: true }),
|
||||
);
|
||||
},
|
||||
),
|
||||
unblock: http.post<{ id: string }>(
|
||||
'/api/v1/accounts/:id/unblock',
|
||||
({ params }) => {
|
||||
action('unblocking account')(params);
|
||||
return HttpResponse.json(
|
||||
relationshipsFactory({
|
||||
id: params.id,
|
||||
blocking: false,
|
||||
}),
|
||||
);
|
||||
},
|
||||
),
|
||||
};
|
||||
|
||||
export const unhandledRequestHandler = ({ url }: Request) => {
|
||||
const { pathname } = new URL(url);
|
||||
if (pathname.startsWith('/api/v1/')) {
|
||||
action(`unhandled request to ${pathname}`)(url);
|
||||
console.warn(
|
||||
`Unhandled request to ${pathname}. Please add a handler for this request in your storybook configuration.`,
|
||||
);
|
||||
}
|
||||
};
|
70
app/javascript/testing/factories.ts
Normal file
70
app/javascript/testing/factories.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import type { ApiRelationshipJSON } from '@/mastodon/api_types/relationships';
|
||||
import { createAccountFromServerJSON } from '@/mastodon/models/account';
|
||||
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
|
||||
|
||||
type FactoryOptions<T> = {
|
||||
id?: string;
|
||||
} & Partial<T>;
|
||||
|
||||
type FactoryFunction<T> = (options?: FactoryOptions<T>) => T;
|
||||
|
||||
export const accountFactory: FactoryFunction<ApiAccountJSON> = ({
|
||||
id,
|
||||
...data
|
||||
} = {}) => ({
|
||||
id: id ?? '1',
|
||||
acct: 'testuser',
|
||||
avatar: '/avatars/original/missing.png',
|
||||
avatar_static: '/avatars/original/missing.png',
|
||||
username: 'testuser',
|
||||
display_name: 'Test User',
|
||||
bot: false,
|
||||
created_at: '2023-01-01T00:00:00.000Z',
|
||||
discoverable: true,
|
||||
emojis: [],
|
||||
fields: [],
|
||||
followers_count: 0,
|
||||
following_count: 0,
|
||||
group: false,
|
||||
header: '/header.png',
|
||||
header_static: '/header_static.png',
|
||||
indexable: true,
|
||||
last_status_at: '2023-01-01',
|
||||
locked: false,
|
||||
mute_expires_at: null,
|
||||
note: 'This is a test user account.',
|
||||
statuses_count: 0,
|
||||
suspended: false,
|
||||
url: '/@testuser',
|
||||
uri: '/users/testuser',
|
||||
noindex: false,
|
||||
roles: [],
|
||||
hide_collections: false,
|
||||
...data,
|
||||
});
|
||||
|
||||
export const accountFactoryState = (
|
||||
options: FactoryOptions<ApiAccountJSON> = {},
|
||||
) => createAccountFromServerJSON(accountFactory(options));
|
||||
|
||||
export const relationshipsFactory: FactoryFunction<ApiRelationshipJSON> = ({
|
||||
id,
|
||||
...data
|
||||
} = {}) => ({
|
||||
id: id ?? '1',
|
||||
following: false,
|
||||
followed_by: false,
|
||||
blocking: false,
|
||||
blocked_by: false,
|
||||
languages: null,
|
||||
muting_notifications: false,
|
||||
note: '',
|
||||
requested_by: false,
|
||||
muting: false,
|
||||
requested: false,
|
||||
domain_blocking: false,
|
||||
endorsed: false,
|
||||
notifying: false,
|
||||
showing_reblogs: true,
|
||||
...data,
|
||||
});
|
52
app/javascript/testing/rendering.tsx
Normal file
52
app/javascript/testing/rendering.tsx
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { IntlProvider } from 'react-intl';
|
||||
|
||||
import { MemoryRouter } from 'react-router';
|
||||
|
||||
import type { RenderOptions } from '@testing-library/react';
|
||||
import { render as rtlRender } from '@testing-library/react';
|
||||
|
||||
import { IdentityContext } from '@/mastodon/identity_context';
|
||||
|
||||
beforeAll(() => {
|
||||
global.requestIdleCallback = vi.fn((cb: IdleRequestCallback) => {
|
||||
// @ts-expect-error IdleRequestCallback expects an argument of type IdleDeadline,
|
||||
// but that doesn't exist in this environment.
|
||||
cb();
|
||||
return 0;
|
||||
});
|
||||
});
|
||||
|
||||
function render(
|
||||
ui: React.ReactElement,
|
||||
{
|
||||
locale = 'en',
|
||||
signedIn = true,
|
||||
...renderOptions
|
||||
}: RenderOptions & { locale?: string; signedIn?: boolean } = {},
|
||||
) {
|
||||
const fakeIdentity = {
|
||||
signedIn: signedIn,
|
||||
accountId: '123',
|
||||
disabledAccountId: undefined,
|
||||
permissions: 0,
|
||||
};
|
||||
|
||||
const Wrapper = (props: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<IntlProvider locale={locale}>
|
||||
<IdentityContext.Provider value={fakeIdentity}>
|
||||
{props.children}
|
||||
</IdentityContext.Provider>
|
||||
</IntlProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
};
|
||||
return rtlRender(ui, { wrapper: Wrapper, ...renderOptions });
|
||||
}
|
||||
|
||||
// re-export everything
|
||||
export * from '@testing-library/react';
|
||||
|
||||
// override render method
|
||||
export { render };
|
Loading…
Add table
Add a link
Reference in a new issue