feat: add and modify test case for new settings modal (#2925)

This commit is contained in:
Qi 2023-06-29 20:54:45 +08:00 committed by GitHub
parent b1d2d77263
commit d7fcad2d0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 152 additions and 57 deletions

View File

@ -31,6 +31,7 @@ export const DeleteLeaveWorkspace: FC<{
onClick={() => { onClick={() => {
setShowDelete(true); setShowDelete(true);
}} }}
testId="delete-workspace-button"
> >
<ArrowRightSmallIcon /> <ArrowRightSmallIcon />
</SettingRow> </SettingRow>

View File

@ -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

View File

@ -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)}
/> />

View File

@ -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',
}, },
]; ];
}; };

View File

@ -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]) => {

View File

@ -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>

View File

@ -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={{

View File

@ -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>

View File

@ -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>

View File

@ -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)}

View File

@ -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();
}

View File

@ -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);

View File

@ -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);
});

View 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();
});