mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-24 04:32:11 +03:00
feat: add and modify test case for new settings modal (#2925)
This commit is contained in:
parent
b1d2d77263
commit
d7fcad2d0d
@ -31,6 +31,7 @@ export const DeleteLeaveWorkspace: FC<{
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowDelete(true);
|
setShowDelete(true);
|
||||||
}}
|
}}
|
||||||
|
testId="delete-workspace-button"
|
||||||
>
|
>
|
||||||
<ArrowRightSmallIcon />
|
<ArrowRightSmallIcon />
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
|
@ -21,7 +21,11 @@ export const AboutAffine = () => {
|
|||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SettingHeader title={t['About AFFiNE']()} subtitle={t['None yet']()} />
|
<SettingHeader
|
||||||
|
title={t['About AFFiNE']()}
|
||||||
|
subtitle={t['None yet']()}
|
||||||
|
data-testid="about-title"
|
||||||
|
/>
|
||||||
{runtimeConfig.enableNewSettingUnstableApi && environment.isDesktop ? (
|
{runtimeConfig.enableNewSettingUnstableApi && environment.isDesktop ? (
|
||||||
<SettingWrapper title={t['Version']()}>
|
<SettingWrapper title={t['Version']()}>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
|
@ -30,9 +30,15 @@ export const ThemeSettings = () => {
|
|||||||
[setTheme]
|
[setTheme]
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<RadioButton value="system">{t['system']()}</RadioButton>
|
<RadioButton value="system" data-testid="system-theme-trigger">
|
||||||
<RadioButton value="light">{t['light']()}</RadioButton>
|
{t['system']()}
|
||||||
<RadioButton value="dark">{t['dark']()}</RadioButton>
|
</RadioButton>
|
||||||
|
<RadioButton value="light" data-testid="light-theme-trigger">
|
||||||
|
{t['light']()}
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton value="dark" data-testid="dark-theme-trigger">
|
||||||
|
{t['dark']()}
|
||||||
|
</RadioButton>
|
||||||
</RadioButtonGroup>
|
</RadioButtonGroup>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -86,6 +92,7 @@ export const AppearanceSettings = () => {
|
|||||||
desc={t['Maximum display of content within a page.']()}
|
desc={t['Maximum display of content within a page.']()}
|
||||||
>
|
>
|
||||||
<Switch
|
<Switch
|
||||||
|
data-testid="full-width-layout-trigger"
|
||||||
checked={appSettings.fullWidthLayout}
|
checked={appSettings.fullWidthLayout}
|
||||||
onChange={checked => changeSwitch('fullWidthLayout', checked)}
|
onChange={checked => changeSwitch('fullWidthLayout', checked)}
|
||||||
/>
|
/>
|
||||||
|
@ -16,6 +16,7 @@ export type GeneralSettingList = {
|
|||||||
key: GeneralSettingKeys;
|
key: GeneralSettingKeys;
|
||||||
title: string;
|
title: string;
|
||||||
icon: FC<SVGProps<SVGSVGElement>>;
|
icon: FC<SVGProps<SVGSVGElement>>;
|
||||||
|
testId: string;
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
export const useGeneralSettingList = (): GeneralSettingList => {
|
export const useGeneralSettingList = (): GeneralSettingList => {
|
||||||
@ -25,16 +26,19 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
|||||||
key: 'appearance',
|
key: 'appearance',
|
||||||
title: t['com.affine.settings.appearance'](),
|
title: t['com.affine.settings.appearance'](),
|
||||||
icon: AppearanceIcon,
|
icon: AppearanceIcon,
|
||||||
|
testId: 'appearance-panel-trigger',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'shortcuts',
|
key: 'shortcuts',
|
||||||
title: t['Keyboard Shortcuts'](),
|
title: t['Keyboard Shortcuts'](),
|
||||||
icon: KeyboardIcon,
|
icon: KeyboardIcon,
|
||||||
|
testId: 'shortcuts-panel-trigger',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'about',
|
key: 'about',
|
||||||
title: t['About AFFiNE'](),
|
title: t['About AFFiNE'](),
|
||||||
icon: InformationIcon,
|
icon: InformationIcon,
|
||||||
|
testId: 'about-panel-trigger',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
@ -23,6 +23,7 @@ export const Shortcuts = () => {
|
|||||||
<SettingHeader
|
<SettingHeader
|
||||||
title={t['Keyboard Shortcuts']()}
|
title={t['Keyboard Shortcuts']()}
|
||||||
subtitle={t['Check Keyboard Shortcuts quickly']()}
|
subtitle={t['Check Keyboard Shortcuts quickly']()}
|
||||||
|
data-testid="keyboard-shortcuts-title"
|
||||||
/>
|
/>
|
||||||
<SettingWrapper title={t['General']()}>
|
<SettingWrapper title={t['General']()}>
|
||||||
{Object.entries(generalShortcuts).map(([title, shortcuts]) => {
|
{Object.entries(generalShortcuts).map(([title, shortcuts]) => {
|
||||||
|
@ -46,11 +46,11 @@ export const SettingSidebar = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
return (
|
return (
|
||||||
<div className={settingSlideBar}>
|
<div className={settingSlideBar} data-testid="settings-sidebar">
|
||||||
<div className={sidebarTitle}>{t['Settings']()}</div>
|
<div className={sidebarTitle}>{t['Settings']()}</div>
|
||||||
<div className={sidebarSubtitle}>{t['General']()}</div>
|
<div className={sidebarSubtitle}>{t['General']()}</div>
|
||||||
<div className={sidebarItemsWrapper}>
|
<div className={sidebarItemsWrapper}>
|
||||||
{generalSettingList.map(({ title, icon, key }) => {
|
{generalSettingList.map(({ title, icon, key, testId }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(sidebarSelectItem, {
|
className={clsx(sidebarSelectItem, {
|
||||||
@ -61,6 +61,7 @@ export const SettingSidebar = ({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
onGeneralSettingClick(key);
|
onGeneralSettingClick(key);
|
||||||
}}
|
}}
|
||||||
|
data-testid={testId}
|
||||||
>
|
>
|
||||||
{icon({ className: 'icon' })}
|
{icon({ className: 'icon' })}
|
||||||
<span className="setting-name">{title}</span>
|
<span className="setting-name">{title}</span>
|
||||||
|
@ -182,7 +182,7 @@ export const RootAppSidebar = ({
|
|||||||
</RouteMenuLinkItem>
|
</RouteMenuLinkItem>
|
||||||
{runtimeConfig.enableNewSettingModal ? (
|
{runtimeConfig.enableNewSettingModal ? (
|
||||||
<MenuItem icon={<SettingsIcon />} onClick={onOpenSettingModal}>
|
<MenuItem icon={<SettingsIcon />} onClick={onOpenSettingModal}>
|
||||||
<span data-testid="new-settings">
|
<span data-testid="settings-modal-trigger">
|
||||||
{t['Settings']()}
|
{t['Settings']()}
|
||||||
<i
|
<i
|
||||||
style={{
|
style={{
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import type { FC } from 'react';
|
import type { FC, HTMLAttributes } from 'react';
|
||||||
|
|
||||||
import { settingHeader } from './share.css';
|
import { settingHeader } from './share.css';
|
||||||
export const SettingHeader: FC<{ title: string; subtitle?: string }> = ({
|
|
||||||
title,
|
export const SettingHeader: FC<
|
||||||
subtitle,
|
{ title: string; subtitle?: string } & Omit<
|
||||||
}) => {
|
HTMLAttributes<HTMLDivElement>,
|
||||||
|
'title'
|
||||||
|
>
|
||||||
|
> = ({ title, subtitle, ...otherProps }) => {
|
||||||
return (
|
return (
|
||||||
<div className={settingHeader}>
|
<div className={settingHeader} {...otherProps}>
|
||||||
<div className="title">{title}</div>
|
<div className="title">{title}</div>
|
||||||
<div className="subtitle">{subtitle}</div>
|
<div className="subtitle">{subtitle}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,8 +10,17 @@ export const SettingRow: FC<
|
|||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
spreadCol?: boolean;
|
spreadCol?: boolean;
|
||||||
|
testId?: string;
|
||||||
}>
|
}>
|
||||||
> = ({ name, desc, children, onClick, style, spreadCol = true }) => {
|
> = ({
|
||||||
|
name,
|
||||||
|
desc,
|
||||||
|
children,
|
||||||
|
onClick,
|
||||||
|
style,
|
||||||
|
spreadCol = true,
|
||||||
|
testId = '',
|
||||||
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(settingRow, {
|
className={clsx(settingRow, {
|
||||||
@ -19,6 +28,7 @@ export const SettingRow: FC<
|
|||||||
})}
|
})}
|
||||||
style={style}
|
style={style}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
data-testid={testId}
|
||||||
>
|
>
|
||||||
<div className="left-col">
|
<div className="left-col">
|
||||||
<div className="name">{name}</div>
|
<div className="name">{name}</div>
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
// components/switch.tsx
|
// components/switch.tsx
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useState } from 'react';
|
import { type HTMLAttributes, type ReactNode, useState } from 'react';
|
||||||
|
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
type SwitchProps = {
|
type SwitchProps = Omit<HTMLAttributes<HTMLLabelElement>, 'onChange'> & {
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
onChange?: (checked: boolean) => void;
|
onChange?: (checked: boolean) => void;
|
||||||
children?: React.ReactNode;
|
children?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Switch = (props: SwitchProps) => {
|
export const Switch = (props: SwitchProps) => {
|
||||||
const { checked, onChange, children } = props;
|
const { checked, onChange, children, ...otherProps } = props;
|
||||||
const [isChecked, setIsChecked] = useState(checked);
|
const [isChecked, setIsChecked] = useState(checked);
|
||||||
|
|
||||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@ -21,7 +21,7 @@ export const Switch = (props: SwitchProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label className={clsx(styles.labelStyle)}>
|
<label className={clsx(styles.labelStyle)} {...otherProps}>
|
||||||
{children}
|
{children}
|
||||||
<input
|
<input
|
||||||
className={clsx(styles.inputStyle)}
|
className={clsx(styles.inputStyle)}
|
||||||
|
@ -7,3 +7,26 @@ export async function clickCollaborationPanel(page: Page) {
|
|||||||
export async function clickPublishPanel(page: Page) {
|
export async function clickPublishPanel(page: Page) {
|
||||||
await page.click('[data-tab-key="publish"]');
|
await page.click('[data-tab-key="publish"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function openSettingModal(page: Page) {
|
||||||
|
await page.getByTestId('settings-modal-trigger').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function openAppearancePanel(page: Page) {
|
||||||
|
await page.getByTestId('appearance-panel-trigger').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function openShortcutsPanel(page: Page) {
|
||||||
|
await page.getByTestId('shortcuts-panel-trigger').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function openAboutPanel(page: Page) {
|
||||||
|
await page.getByTestId('about-panel-trigger').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function openWorkspaceSettingPanel(
|
||||||
|
page: Page,
|
||||||
|
workspaceName: string
|
||||||
|
) {
|
||||||
|
await page.getByTestId('settings-sidebar').getByText(workspaceName).click();
|
||||||
|
}
|
||||||
|
@ -3,10 +3,9 @@ import { expect } from '@playwright/test';
|
|||||||
|
|
||||||
import { openHomePage } from '../libs/load-page';
|
import { openHomePage } from '../libs/load-page';
|
||||||
import { waitEditorLoad } from '../libs/page-logic';
|
import { waitEditorLoad } from '../libs/page-logic';
|
||||||
import {
|
import { openWorkspaceSettingPanel } from '../libs/setting';
|
||||||
clickSideBarCurrentWorkspaceBanner,
|
import { openSettingModal } from '../libs/setting';
|
||||||
clickSideBarSettingButton,
|
import { clickSideBarCurrentWorkspaceBanner } from '../libs/sidebar';
|
||||||
} from '../libs/sidebar';
|
|
||||||
import { assertCurrentWorkspaceFlavour } from '../libs/workspace';
|
import { assertCurrentWorkspaceFlavour } from '../libs/workspace';
|
||||||
|
|
||||||
test('Create new workspace, then delete it', async ({ page }) => {
|
test('Create new workspace, then delete it', async ({ page }) => {
|
||||||
@ -24,7 +23,8 @@ test('Create new workspace, then delete it', async ({ page }) => {
|
|||||||
expect(await page.getByTestId('workspace-name').textContent()).toBe(
|
expect(await page.getByTestId('workspace-name').textContent()).toBe(
|
||||||
'Test Workspace'
|
'Test Workspace'
|
||||||
);
|
);
|
||||||
await clickSideBarSettingButton(page);
|
await openSettingModal(page);
|
||||||
|
await openWorkspaceSettingPanel(page, 'Test Workspace');
|
||||||
await page.getByTestId('delete-workspace-button').click();
|
await page.getByTestId('delete-workspace-button').click();
|
||||||
const workspaceNameDom = await page.getByTestId('workspace-name');
|
const workspaceNameDom = await page.getByTestId('workspace-name');
|
||||||
const currentWorkspaceName = await workspaceNameDom.evaluate(
|
const currentWorkspaceName = await workspaceNameDom.evaluate(
|
||||||
@ -50,12 +50,13 @@ test('Create new workspace, then delete it', async ({ page }) => {
|
|||||||
test('Delete last workspace', async ({ page }) => {
|
test('Delete last workspace', async ({ page }) => {
|
||||||
await openHomePage(page);
|
await openHomePage(page);
|
||||||
await waitEditorLoad(page);
|
await waitEditorLoad(page);
|
||||||
await clickSideBarSettingButton(page);
|
|
||||||
await page.getByTestId('delete-workspace-button').click();
|
|
||||||
const workspaceNameDom = await page.getByTestId('workspace-name');
|
const workspaceNameDom = await page.getByTestId('workspace-name');
|
||||||
const currentWorkspaceName = await workspaceNameDom.evaluate(
|
const currentWorkspaceName = await workspaceNameDom.evaluate(
|
||||||
node => node.textContent
|
node => node.textContent
|
||||||
);
|
);
|
||||||
|
await openSettingModal(page);
|
||||||
|
await openWorkspaceSettingPanel(page, currentWorkspaceName as string);
|
||||||
|
await page.getByTestId('delete-workspace-button').click();
|
||||||
await page
|
await page
|
||||||
.getByTestId('delete-workspace-input')
|
.getByTestId('delete-workspace-input')
|
||||||
.type(currentWorkspaceName as string);
|
.type(currentWorkspaceName as string);
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
import { resolve } from 'node:path';
|
|
||||||
|
|
||||||
import { test, testResultDir } from '@affine-test/kit/playwright';
|
|
||||||
import { expect } from '@playwright/test';
|
|
||||||
|
|
||||||
import { openHomePage } from '../libs/load-page';
|
|
||||||
import { waitEditorLoad } from '../libs/page-logic';
|
|
||||||
import { clickSideBarSettingButton } from '../libs/sidebar';
|
|
||||||
|
|
||||||
test('Should highlight the setting page menu when selected', async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await openHomePage(page);
|
|
||||||
await waitEditorLoad(page);
|
|
||||||
const element = await page.getByTestId('slider-bar-workspace-setting-button');
|
|
||||||
const prev = await element.screenshot({
|
|
||||||
path: resolve(
|
|
||||||
testResultDir,
|
|
||||||
'slider-bar-workspace-setting-button-prev.png'
|
|
||||||
),
|
|
||||||
});
|
|
||||||
await clickSideBarSettingButton(page);
|
|
||||||
await page.waitForTimeout(50);
|
|
||||||
const after = await element.screenshot({
|
|
||||||
path: resolve(
|
|
||||||
testResultDir,
|
|
||||||
'slider-bar-workspace-setting-button-after.png'
|
|
||||||
),
|
|
||||||
});
|
|
||||||
expect(prev).not.toEqual(after);
|
|
||||||
});
|
|
71
tests/parallels/settings.spec.ts
Normal file
71
tests/parallels/settings.spec.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { test } from '@affine-test/kit/playwright';
|
||||||
|
import { expect } from '@playwright/test';
|
||||||
|
|
||||||
|
import { openHomePage } from '../libs/load-page';
|
||||||
|
import { waitEditorLoad } from '../libs/page-logic';
|
||||||
|
import {
|
||||||
|
openAboutPanel,
|
||||||
|
openAppearancePanel,
|
||||||
|
openSettingModal,
|
||||||
|
openShortcutsPanel,
|
||||||
|
} from '../libs/setting';
|
||||||
|
|
||||||
|
test('Open settings modal', async ({ page }) => {
|
||||||
|
await openHomePage(page);
|
||||||
|
await waitEditorLoad(page);
|
||||||
|
await openSettingModal(page);
|
||||||
|
|
||||||
|
const modal = await page.getByTestId('setting-modal');
|
||||||
|
await expect(modal).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Change theme', async ({ page }) => {
|
||||||
|
await openHomePage(page);
|
||||||
|
await waitEditorLoad(page);
|
||||||
|
await openSettingModal(page);
|
||||||
|
await openAppearancePanel(page);
|
||||||
|
const root = page.locator('html');
|
||||||
|
|
||||||
|
await page.getByTestId('light-theme-trigger').click();
|
||||||
|
const lightMode = await root.evaluate(element =>
|
||||||
|
element.getAttribute('data-theme')
|
||||||
|
);
|
||||||
|
expect(lightMode).toBe('light');
|
||||||
|
|
||||||
|
await page.getByTestId('dark-theme-trigger').click();
|
||||||
|
const darkMode = await root.evaluate(element =>
|
||||||
|
element.getAttribute('data-theme')
|
||||||
|
);
|
||||||
|
expect(darkMode).toBe('dark');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Change layout width', async ({ page }) => {
|
||||||
|
await openHomePage(page);
|
||||||
|
await waitEditorLoad(page);
|
||||||
|
await openSettingModal(page);
|
||||||
|
await openAppearancePanel(page);
|
||||||
|
|
||||||
|
await page.getByTestId('full-width-layout-trigger').click();
|
||||||
|
|
||||||
|
const editorWrapper = await page.locator('.editor-wrapper');
|
||||||
|
const className = await editorWrapper.getAttribute('class');
|
||||||
|
expect(className).toContain('full-screen');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Open shortcuts panel', async ({ page }) => {
|
||||||
|
await openHomePage(page);
|
||||||
|
await waitEditorLoad(page);
|
||||||
|
await openSettingModal(page);
|
||||||
|
await openShortcutsPanel(page);
|
||||||
|
const title = await page.getByTestId('keyboard-shortcuts-title');
|
||||||
|
await expect(title).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Open about panel', async ({ page }) => {
|
||||||
|
await openHomePage(page);
|
||||||
|
await waitEditorLoad(page);
|
||||||
|
await openSettingModal(page);
|
||||||
|
await openAboutPanel(page);
|
||||||
|
const title = await page.getByTestId('about-title');
|
||||||
|
await expect(title).toBeVisible();
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user