Testing and types updates (#39657)

This commit is contained in:
Echo authored and GitHub committed 2026-06-29 14:26:22 +00:00
1 parent b2ebfa13a9
commit 00a8fbc43e
29 files changed
+263 -191

No files matched your search

@@ -2,7 +2,10 @@ import type { ComponentProps } from 'react';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { accountFactoryState, relationshipsFactory } from '@/testing/factories';
import {
accountFactoryImmutable,
relationshipsFactoryAPI,
} from '@/testing/factories';
import { Account } from './index';
@@ -69,7 +72,7 @@ const meta = {
parameters: {
state: {
accounts: {
'1': accountFactoryState(),
'1': accountFactoryImmutable(),
},
},
},
@@ -121,7 +124,7 @@ export const Blocked: Story = {
parameters: {
state: {
relationships: {
'1': relationshipsFactory({
'1': relationshipsFactoryAPI({
blocking: true,
}),
},
@@ -134,7 +137,7 @@ export const Muted: Story = {
parameters: {
state: {
relationships: {
'1': relationshipsFactory({
'1': relationshipsFactoryAPI({
muting: true,
}),
},
@@ -1,6 +1,9 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import { accountFactoryState, relationshipsFactory } from '@/testing/factories';
import {
accountFactoryImmutable,
relationshipsFactoryAPI,
} from '@/testing/factories';
import { PendingBadge } from '../badge';
@@ -16,7 +19,7 @@ const meta = {
parameters: {
state: {
accounts: {
'1': accountFactoryState(),
'1': accountFactoryImmutable(),
},
},
},
@@ -32,7 +35,7 @@ export const FollowsYou: Story = {
parameters: {
state: {
relationships: {
'1': relationshipsFactory({
'1': relationshipsFactoryAPI({
followed_by: true,
}),
},
@@ -2,7 +2,7 @@ import type { ComponentProps } from 'react';
import type { Meta, StoryObj } from '@storybook/react-vite';
import { accountFactoryState } from '@/testing/factories';
import { accountFactoryImmutable } from '@/testing/factories';
import { DisplayName, LinkedDisplayName } from './index';
@@ -23,7 +23,7 @@ const meta = {
tags: [],
render({ name, username, loading, ...args }) {
const account = !loading
? accountFactoryState({
? accountFactoryImmutable({
display_name: name,
acct: username,
})
@@ -69,7 +69,7 @@ export const LocalUser: Story = {
export const Linked: Story = {
render({ name, username, loading, ...args }) {
const account = !loading
? accountFactoryState({
? accountFactoryImmutable({
display_name: name,
acct: username,
})
@@ -8,8 +8,9 @@ import type {
} from 'react';
import { useCallback, useId, useRef } from 'react';
import type { Merge } from 'type-fest';
import { insertEmojiAtPosition } from '@/mastodon/features/emoji/utils';
import type { OmitUnion } from '@/mastodon/utils/types';
import { CharacterCounter } from '../character_counter';
import { EmojiPickerButton } from '../emoji/picker_button';
@@ -29,7 +30,7 @@ export type EmojiInputProps = {
} & Omit<CommonFieldWrapperProps, 'wrapperClassName'>;
export const EmojiTextInputField: FC<
OmitUnion<ComponentPropsWithoutRef<'input'>, EmojiInputProps>
Merge<ComponentPropsWithoutRef<'input'>, EmojiInputProps>
> = ({
onChange,
value,
@@ -72,7 +73,7 @@ export const EmojiTextInputField: FC<
};
export const EmojiTextAreaField: FC<
OmitUnion<Omit<TextAreaProps, 'style'>, EmojiInputProps>
Merge<Omit<TextAreaProps, 'style'>, EmojiInputProps>
> = ({
onChange,
value,
@@ -3,14 +3,14 @@ import type { ComponentPropsWithoutRef, ReactNode } from 'react';
import classNames from 'classnames';
import type { OmitUnion } from '@/mastodon/utils/types';
import type { Merge } from 'type-fest';
import { Icon } from '../icon';
import type { IconProp } from '../icon';
import classes from './styles.module.css';
export type MiniCardProps = OmitUnion<
export type MiniCardProps = Merge<
ComponentPropsWithoutRef<'div'>,
{
label: ReactNode;
@@ -3,7 +3,7 @@ import type { ComponentPropsWithoutRef, Key } from 'react';
import classNames from 'classnames';
import type { OmitUnion } from '@/mastodon/utils/types';
import type { Merge } from 'type-fest';
import { MiniCard } from '.';
import type { MiniCardProps as BaseCardProps } from '.';
@@ -19,7 +19,7 @@ interface MiniCardListProps {
export const MiniCardList = forwardRef<
HTMLDListElement,
OmitUnion<ComponentPropsWithoutRef<'dl'>, MiniCardListProps>
Merge<ComponentPropsWithoutRef<'dl'>, MiniCardListProps>
>(({ cards = [], className, children, ...props }, ref) => {
if (!cards.length) {
return null;
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
import { statusFactoryState } from '@/testing/factories';
import { statusFactoryImmutable } from '@/testing/factories';
import { BoostButton } from './boost_button';
@@ -50,7 +50,7 @@ function argsToStatus({
quoteAllowed,
alreadyBoosted,
}: StoryProps) {
return statusFactoryState({
return statusFactoryImmutable({
reblogs_count: reblogCount,
visibility,
reblogged: alreadyBoosted,
@@ -5,6 +5,8 @@ import { useIntl } from 'react-intl';
import classNames from 'classnames';
import type { SetRequired } from 'type-fest';
import { quoteComposeById } from '@/mastodon/actions/compose_typed';
import { toggleReblog } from '@/mastodon/actions/interactions';
import { openModal } from '@/mastodon/actions/modal';
@@ -13,7 +15,6 @@ import { quickBoosting } from '@/mastodon/initial_state';
import type { ActionMenuItem } from '@/mastodon/models/dropdown_menu';
import type { Status } from '@/mastodon/models/status';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
import type { SomeRequired } from '@/mastodon/utils/types';
import type { RenderItemFn } from '../dropdown_menu';
import { Dropdown, DropdownMenuItemContent } from '../dropdown_menu';
@@ -91,7 +92,7 @@ interface ReblogButtonProps {
counters?: boolean;
}
type ActionMenuItemWithIcon = SomeRequired<ActionMenuItem, 'icon'>;
type ActionMenuItemWithIcon = SetRequired<ActionMenuItem, 'icon'>;
const BoostOrQuoteMenu: FC<ReblogButtonProps> = ({ status, counters }) => {
const intl = useIntl();
@@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite';
import { fn } from 'storybook/test';
import type { StatusTranslation } from '@/mastodon/models/status';
import { statusFactoryState } from '@/testing/factories';
import { statusFactoryImmutable } from '@/testing/factories';
import { StatusContent } from './content';
@@ -57,7 +57,7 @@ const meta = {
},
},
stateFn(args: StatusContentProps) {
let status = statusFactoryState();
let status = statusFactoryImmutable();
if (args.translatedTo) {
status = status.set('translation', {
contentHtml: `${args.text}<p><em>(in ${args.translatedTo})</em></p>`,
@@ -1,7 +1,7 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import { HashtagMenuController } from '@/mastodon/features/ui/components/hashtag_menu_controller';
import { accountFactoryState } from '@/testing/factories';
import { accountFactoryImmutable } from '@/testing/factories';
import { HoverCardController } from '../hover_card_controller';
@@ -55,7 +55,7 @@ const meta = {
parameters: {
state: {
accounts: {
'1': accountFactoryState({ id: '1', acct: 'hashtaguser' }),
'1': accountFactoryImmutable({ id: '1', acct: 'hashtaguser' }),
},
},
},
@@ -9,11 +9,11 @@ import { fn } from 'storybook/test';
import type { ApiMediaAttachmentJSON } from '@/mastodon/api_types/media_attachments';
import type { StatusVisibility } from '@/mastodon/api_types/statuses';
import {
accountFactoryState,
mediaAttachmentFactory,
pollFactory,
statusFactory,
statusFactoryState,
accountFactoryImmutable,
mediaAttachmentFactoryAPI,
pollFactoryImmutable,
statusFactoryAPI,
statusFactoryImmutable,
} from '@/testing/factories';
import { TypedStatus } from './types';
@@ -71,7 +71,7 @@ interface StatusStoryProps {
showPrepend?: boolean;
}
const otherAccount = accountFactoryState({
const otherAccount = accountFactoryImmutable({
id: '2',
display_name: 'Another user',
});
@@ -106,14 +106,14 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
showPrepend = true,
} = props;
const { account, status } = useMemo(() => {
const account = accountFactoryState();
const account = accountFactoryImmutable();
const media_attachments: ApiMediaAttachmentJSON[] = [];
switch (attachments) {
// Use fall through add attachments depending on count.
case 'image-3':
media_attachments.push(
mediaAttachmentFactory({
mediaAttachmentFactoryAPI({
id: '2',
url: 'https://cataas.com/cat/EbVq9zMc4Xxv7s73',
meta: {
@@ -129,7 +129,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
// eslint-disable-next-line no-fallthrough
case 'image-2':
media_attachments.push(
mediaAttachmentFactory({
mediaAttachmentFactoryAPI({
id: '3',
url: 'https://cataas.com/cat/YFaQ4xWYoWURSz37',
meta: {
@@ -145,7 +145,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
// eslint-disable-next-line no-fallthrough
case 'image-1':
media_attachments.push(
mediaAttachmentFactory({
mediaAttachmentFactoryAPI({
id: '4',
url: 'https://cataas.com/cat/bYBTjiFUqjUPIBUD',
meta: {
@@ -161,7 +161,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
break;
case 'video':
media_attachments.push(
mediaAttachmentFactory({
mediaAttachmentFactoryAPI({
type: 'video',
url: 'https://www.pexels.com/download/video/11760787/',
meta: {
@@ -175,7 +175,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
break;
case 'audio':
media_attachments.push(
mediaAttachmentFactory({
mediaAttachmentFactoryAPI({
type: 'audio',
url: 'https://upload.wikimedia.org/wikipedia/commons/4/40/Elephant_voice_-_trumpeting.ogg',
}),
@@ -183,7 +183,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
break;
case 'gifv':
media_attachments.push(
mediaAttachmentFactory({
mediaAttachmentFactoryAPI({
type: 'gifv',
url: 'https://www.pexels.com/download/video/11760787/',
meta: {
@@ -196,13 +196,15 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
);
break;
case 'unknown':
media_attachments.push(mediaAttachmentFactory({ type: attachments }));
media_attachments.push(
mediaAttachmentFactoryAPI({ type: attachments }),
);
break;
}
return {
account,
status: statusFactoryState({
status: statusFactoryImmutable({
text,
spoiler_text: contentWarning,
visibility,
@@ -215,7 +217,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
quote: isQuote
? {
state: 'accepted',
quoted_status: { ...statusFactory(), quote: undefined },
quoted_status: { ...statusFactoryAPI(), quote: undefined },
}
: undefined,
favourites_count: favouriteCount,
@@ -236,7 +238,7 @@ const StatusStoryComponent: FC<StatusStoryProps> = (props) => {
if (isReblog) {
status.set(
'reblog',
statusFactoryState({ id: '2' }).set('account', otherAccount),
statusFactoryImmutable({ id: '2' }).set('account', otherAccount),
);
}
if (isPoll) {
@@ -469,8 +471,8 @@ const meta = {
'2': otherAccount,
},
polls: {
'1': pollFactory(),
'2': pollFactory({
'1': pollFactoryImmutable(),
'2': pollFactoryImmutable({
voted: true,
voters_count: 1,
votes_count: 1,
@@ -3,7 +3,10 @@ import { Map as ImmutableMap } from 'immutable';
import type { Meta, StoryObj } from '@storybook/react-vite';
import type { ApiQuoteJSON } from '@/mastodon/api_types/quotes';
import { accountFactoryState, statusFactoryState } from '@/testing/factories';
import {
accountFactoryImmutable,
statusFactoryImmutable,
} from '@/testing/factories';
import type { StatusQuoteManagerProps } from './status_quoted';
import { StatusQuoteManager } from './status_quoted';
@@ -16,15 +19,15 @@ const meta = {
parameters: {
state: {
accounts: {
'1': accountFactoryState({ id: '1', acct: 'hashtaguser' }),
'1': accountFactoryImmutable({ id: '1', acct: 'hashtaguser' }),
},
statuses: {
'1': statusFactoryState({
'1': statusFactoryImmutable({
id: '1',
language: 'en',
text: 'Hello world!',
}),
'2': statusFactoryState({
'2': statusFactoryImmutable({
id: '2',
language: 'en',
text: 'Quote!',
@@ -33,19 +36,19 @@ const meta = {
quoted_status: '1',
}) as unknown as ApiQuoteJSON,
}),
'1001': statusFactoryState({
'1001': statusFactoryImmutable({
id: '1001',
language: 'mn-Mong',
// meaning: Mongolia
text: 'ᠮᠤᠩᠭᠤᠯ',
}),
'1002': statusFactoryState({
'1002': statusFactoryImmutable({
id: '1002',
language: 'mn-Mong',
// meaning: All human beings are born free and equal in dignity and rights.
text: 'ᠬᠦᠮᠦᠨ ᠪᠦᠷ ᠲᠥᠷᠥᠵᠦ ᠮᠡᠨᠳᠡᠯᠡᠬᠦ ᠡᠷᠬᠡ ᠴᠢᠯᠥᠭᠡ ᠲᠡᠢ᠂ ᠠᠳᠠᠯᠢᠬᠠᠨ ᠨᠡᠷ᠎ᠡ ᠲᠥᠷᠥ ᠲᠡᠢ᠂ ᠢᠵᠢᠯ ᠡᠷᠬᠡ ᠲᠡᠢ ᠪᠠᠢᠠᠭ᠃',
}),
'1003': statusFactoryState({
'1003': statusFactoryImmutable({
id: '1003',
language: 'mn-Mong',
// meaning: Mongolia
@@ -5,7 +5,8 @@ import { useIntl } from 'react-intl';
import classNames from 'classnames';
import type { OmitUnion } from '@/mastodon/utils/types';
import type { Merge } from 'type-fest';
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
import type { IconProp } from '../icon';
@@ -24,7 +25,7 @@ export interface TagProps {
export const Tag = forwardRef<
HTMLButtonElement,
OmitUnion<ComponentPropsWithoutRef<'button'>, TagProps>
Merge<ComponentPropsWithoutRef<'button'>, TagProps>
>(({ name, active, icon, className, children, ...props }, ref) => {
if (!name) {
return null;
@@ -47,7 +48,7 @@ Tag.displayName = 'Tag';
export const EditableTag = forwardRef<
HTMLSpanElement,
OmitUnion<
Merge<
ComponentPropsWithoutRef<'span'>,
TagProps & {
onRemove: () => void;