mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-01 06:10:16 +08:00
feat(core): enable new all docs by default (#12404)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Simplified the user interface by always displaying the new All Pages view, removing the feature flag and old page version. - Updated selection interactions to use shift+click on document items instead of checkboxes. - Centralized drag-and-drop functionality in document list items and simplified drag handle behavior. - Generalized new page button component to accept standard HTML attributes. - Changed test ID attributes on new page buttons and list headers to use standard `data-testid`. - **Bug Fixes** - Added stable test identifiers to new page buttons, document list items, menu items, and operation buttons for improved test reliability. - Enabled external drag-and-drop support on the trash button. - **Tests** - Streamlined and updated end-to-end tests to match the new selection flow and UI changes, removing outdated or redundant test cases. - Simplified utility functions and wait conditions in test helpers for better accuracy and maintainability. - Updated selectors in tests to reflect new document item identifiers and centralized page element retrieval using utility functions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -15,6 +15,8 @@ const DefaultDisplayPreference: ExplorerDisplayPreference = {
|
||||
showDocIcon: true,
|
||||
showDocPreview: true,
|
||||
quickFavorite: true,
|
||||
showDragHandle: true,
|
||||
showMoreOperation: true,
|
||||
};
|
||||
|
||||
export type DocExplorerContextType = {
|
||||
@@ -85,5 +87,11 @@ export const createDocExplorerContext = (
|
||||
quickTab$: displayPreference$.selector(
|
||||
displayPreference => displayPreference.quickTab
|
||||
),
|
||||
showMoreOperation$: displayPreference$.selector(
|
||||
displayPreference => displayPreference.showMoreOperation
|
||||
),
|
||||
showDragHandle$: displayPreference$.selector(
|
||||
displayPreference => displayPreference.showDragHandle
|
||||
),
|
||||
} satisfies DocExplorerContextType;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,6 @@ import { DocsService } from '@affine/core/modules/doc';
|
||||
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
|
||||
import { WorkbenchLink } from '@affine/core/modules/workbench';
|
||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
AutoTidyUpIcon,
|
||||
PropertyIcon,
|
||||
@@ -146,20 +145,45 @@ export const DocListItem = ({ ...props }: DocListItemProps) => {
|
||||
[contextValue, handleMultiSelect, prevCheckAnchorId, props, selectMode]
|
||||
);
|
||||
|
||||
const { dragRef, CustomDragPreview } = useDraggable<AffineDNDData>(
|
||||
() => ({
|
||||
canDrag: true,
|
||||
data: {
|
||||
entity: {
|
||||
type: 'doc',
|
||||
id: props.docId as string,
|
||||
},
|
||||
from: {
|
||||
at: 'all-docs:list',
|
||||
},
|
||||
},
|
||||
}),
|
||||
[props.docId]
|
||||
);
|
||||
|
||||
return (
|
||||
<WorkbenchLink
|
||||
draggable={false}
|
||||
to={`/${props.docId}`}
|
||||
onClick={handleClick}
|
||||
data-selected={selectedDocIds.includes(props.docId)}
|
||||
className={styles.root}
|
||||
>
|
||||
{view === 'list' ? (
|
||||
<ListViewDoc {...props} />
|
||||
) : (
|
||||
<CardViewDoc {...props} />
|
||||
)}
|
||||
</WorkbenchLink>
|
||||
<>
|
||||
<WorkbenchLink
|
||||
ref={dragRef}
|
||||
draggable={false}
|
||||
to={`/${props.docId}`}
|
||||
onClick={handleClick}
|
||||
data-selected={selectedDocIds.includes(props.docId)}
|
||||
className={styles.root}
|
||||
data-testid={`doc-list-item`}
|
||||
data-doc-id={props.docId}
|
||||
>
|
||||
{view === 'list' ? (
|
||||
<ListViewDoc {...props} />
|
||||
) : (
|
||||
<CardViewDoc {...props} />
|
||||
)}
|
||||
</WorkbenchLink>
|
||||
<CustomDragPreview>
|
||||
<RawDocIcon id={props.docId} />
|
||||
<RawDocTitle id={props.docId} />
|
||||
</CustomDragPreview>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -172,10 +196,9 @@ const RawDocIcon = memo(function RawDocIcon({
|
||||
return <Icon {...props} />;
|
||||
});
|
||||
const RawDocTitle = memo(function RawDocTitle({ id }: { id: string }) {
|
||||
const i18n = useI18n();
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const title = useLiveData(docDisplayMetaService.title$(id));
|
||||
return i18n.t(title);
|
||||
return title;
|
||||
});
|
||||
const RawDocPreview = memo(function RawDocPreview({
|
||||
id,
|
||||
@@ -188,47 +211,20 @@ const RawDocPreview = memo(function RawDocPreview({
|
||||
});
|
||||
const DragHandle = memo(function DragHandle({
|
||||
id,
|
||||
preview,
|
||||
...props
|
||||
}: HTMLProps<HTMLDivElement> & { preview?: ReactNode }) {
|
||||
}: HTMLProps<HTMLDivElement>) {
|
||||
const contextValue = useContext(DocExplorerContext);
|
||||
const selectMode = useLiveData(contextValue.selectMode$);
|
||||
const showDragHandle = useLiveData(contextValue.showDragHandle$);
|
||||
|
||||
const { dragRef, CustomDragPreview } = useDraggable<AffineDNDData>(
|
||||
() => ({
|
||||
canDrag: true,
|
||||
data: {
|
||||
entity: {
|
||||
type: 'doc',
|
||||
id: id as string,
|
||||
},
|
||||
from: {
|
||||
at: 'all-docs:list',
|
||||
},
|
||||
},
|
||||
}),
|
||||
[id]
|
||||
);
|
||||
|
||||
if (selectMode || !id || !showDragHandle) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div ref={dragRef} {...props}>
|
||||
<DragHandleIcon />
|
||||
</div>
|
||||
<CustomDragPreview>
|
||||
{preview ?? (
|
||||
<>
|
||||
<RawDocIcon id={id} />
|
||||
<RawDocTitle id={id} />
|
||||
</>
|
||||
)}
|
||||
</CustomDragPreview>
|
||||
</>
|
||||
<div {...props}>
|
||||
<DragHandleIcon />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
const Select = memo(function Select({
|
||||
@@ -248,7 +244,11 @@ const Select = memo(function Select({
|
||||
}
|
||||
|
||||
return (
|
||||
<div data-select-mode={selectMode} {...props}>
|
||||
<div
|
||||
data-select-mode={selectMode}
|
||||
data-testid={`doc-list-item-select`}
|
||||
{...props}
|
||||
>
|
||||
<Checkbox
|
||||
checked={selectedDocIds.includes(id)}
|
||||
onChange={handleSelectChange}
|
||||
@@ -323,7 +323,11 @@ export const ListViewDoc = ({ docId }: DocListItemProps) => {
|
||||
<Select id={docId} className={styles.listSelect} />
|
||||
<DocIcon id={docId} className={styles.listIcon} />
|
||||
<div className={styles.listBrief}>
|
||||
<DocTitle id={docId} className={styles.listTitle} />
|
||||
<DocTitle
|
||||
id={docId}
|
||||
className={styles.listTitle}
|
||||
data-testid="doc-list-item-title"
|
||||
/>
|
||||
<DocPreview
|
||||
id={docId}
|
||||
className={styles.listPreview}
|
||||
@@ -370,7 +374,11 @@ export const CardViewDoc = ({ docId }: DocListItemProps) => {
|
||||
<li className={styles.cardViewRoot}>
|
||||
<header className={styles.cardViewHeader}>
|
||||
<DocIcon id={docId} className={styles.cardViewIcon} />
|
||||
<DocTitle id={docId} className={styles.cardViewTitle} />
|
||||
<DocTitle
|
||||
id={docId}
|
||||
className={styles.cardViewTitle}
|
||||
data-testid="doc-list-item-title"
|
||||
/>
|
||||
{quickActions.map(action => {
|
||||
return <action.Component size="16" key={action.key} doc={doc} />;
|
||||
})}
|
||||
|
||||
@@ -47,6 +47,7 @@ const ToggleFavorite = ({ docId }: DocOperationProps) => {
|
||||
<MenuItem
|
||||
prefixIcon={<IsFavoriteIcon favorite={favourite} />}
|
||||
onClick={toggleFavorite}
|
||||
data-testid="doc-list-operation-favorite"
|
||||
>
|
||||
{favourite
|
||||
? t['com.affine.favoritePageOperation.remove']()
|
||||
@@ -107,7 +108,7 @@ const SplitView = ({ docId }: DocOperationProps) => {
|
||||
|
||||
return (
|
||||
<MenuItem onClick={onOpenInSplitView} prefixIcon={<SplitViewIcon />}>
|
||||
{t['com.affine.workbench.tab.page-menu-open']()}
|
||||
{t['com.affine.workbench.split-view.page-menu-open']()}
|
||||
</MenuItem>
|
||||
);
|
||||
};
|
||||
@@ -165,7 +166,11 @@ const MoveToTrash = ({ docId }: DocOperationProps) => {
|
||||
}, [doc, openConfirmModal, t]);
|
||||
|
||||
return (
|
||||
<MenuItem prefixIcon={<DeleteIcon />} onClick={onMoveToTrash}>
|
||||
<MenuItem
|
||||
prefixIcon={<DeleteIcon />}
|
||||
data-testid="doc-list-operation-trash"
|
||||
onClick={onMoveToTrash}
|
||||
>
|
||||
{t['com.affine.moveToTrash.title']()}
|
||||
</MenuItem>
|
||||
);
|
||||
@@ -187,10 +192,22 @@ export const MoreMenuContent = (props: DocOperationProps) => {
|
||||
export const MoreMenu = ({
|
||||
docId,
|
||||
children,
|
||||
contentOptions,
|
||||
...menuProps
|
||||
}: Omit<MenuProps, 'items'> & { docId: string }) => {
|
||||
return (
|
||||
<Menu items={<MoreMenuContent docId={docId} />} {...menuProps}>
|
||||
<Menu
|
||||
items={<MoreMenuContent docId={docId} />}
|
||||
contentOptions={{
|
||||
...contentOptions,
|
||||
onClick: e => {
|
||||
// prevent external click events from being triggered
|
||||
e.stopPropagation();
|
||||
contentOptions?.onClick?.(e);
|
||||
},
|
||||
}}
|
||||
{...menuProps}
|
||||
>
|
||||
{children}
|
||||
</Menu>
|
||||
);
|
||||
@@ -213,7 +230,11 @@ export const MoreMenuButton = ({
|
||||
|
||||
return (
|
||||
<MoreMenu docId={docId} {...menuProps}>
|
||||
<IconButton icon={<MoreVerticalIcon />} {...iconProps} />
|
||||
<IconButton
|
||||
data-testid="doc-list-operation-button"
|
||||
icon={<MoreVerticalIcon />}
|
||||
{...iconProps}
|
||||
/>
|
||||
</MoreMenu>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -47,6 +47,7 @@ export const QuickFavorite = memo(function QuickFavorite({
|
||||
<IconButton
|
||||
icon={<IsFavoriteIcon favorite={favourite} />}
|
||||
onClick={toggleFavorite}
|
||||
data-testid="doc-list-operation-favorite"
|
||||
{...iconButtonProps}
|
||||
/>
|
||||
);
|
||||
@@ -157,6 +158,7 @@ export const QuickDelete = memo(function QuickDelete({
|
||||
onClick={onMoveToTrash}
|
||||
icon={<DeleteIcon />}
|
||||
variant="danger"
|
||||
data-testid="doc-list-operation-trash"
|
||||
{...iconButtonProps}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -92,7 +92,7 @@ export const PageListHeader = () => {
|
||||
<div className={styles.docListHeaderTitle}>{title}</div>
|
||||
<PageListNewPageButton
|
||||
size="small"
|
||||
testId="new-page-button-trigger"
|
||||
data-testid="new-page-button-trigger"
|
||||
onCreateEdgeless={e => createEdgeless({ at: inferOpenMode(e) })}
|
||||
onCreatePage={e =>
|
||||
createPage('page' as DocMode, { at: inferOpenMode(e) })
|
||||
@@ -194,7 +194,7 @@ export const CollectionPageListHeader = ({
|
||||
<Button onClick={handleEdit}>{t['Edit']()}</Button>
|
||||
<PageListNewPageButton
|
||||
size="small"
|
||||
testId="new-page-button-trigger"
|
||||
data-testid="new-page-button-trigger"
|
||||
onCreateDoc={onCreateDoc}
|
||||
onCreateEdgeless={onCreateEdgeless}
|
||||
onCreatePage={onCreatePage}
|
||||
|
||||
@@ -7,22 +7,22 @@ export const PageListNewPageButton = ({
|
||||
className,
|
||||
children,
|
||||
size,
|
||||
testId,
|
||||
onCreateDoc,
|
||||
onCreatePage,
|
||||
onCreateEdgeless,
|
||||
onImportFile,
|
||||
...props
|
||||
}: PropsWithChildren<{
|
||||
className?: string;
|
||||
size?: 'small' | 'default';
|
||||
testId?: string;
|
||||
onCreateDoc: (e?: MouseEvent) => void;
|
||||
onCreatePage: (e?: MouseEvent) => void;
|
||||
onCreateEdgeless: (e?: MouseEvent) => void;
|
||||
onImportFile?: (e?: MouseEvent) => void;
|
||||
}>) => {
|
||||
}> &
|
||||
React.HTMLAttributes<HTMLDivElement>) => {
|
||||
return (
|
||||
<div className={className} data-testid={testId}>
|
||||
<div className={className} {...props}>
|
||||
<NewPageButton
|
||||
size={size}
|
||||
importFile={onImportFile}
|
||||
|
||||
@@ -68,6 +68,7 @@ export const TrashButton = () => {
|
||||
}
|
||||
}
|
||||
},
|
||||
allowExternal: true,
|
||||
}),
|
||||
[docsService.list, guardService, openConfirmModal, t]
|
||||
);
|
||||
|
||||
@@ -104,6 +104,7 @@ export const AllDocsHeader = ({
|
||||
onCreatePage={e => createPage('page', { at: inferOpenMode(e) })}
|
||||
onCreateDoc={e => createPage(undefined, { at: inferOpenMode(e) })}
|
||||
onImportFile={onImportFile}
|
||||
data-testid="new-page-button-trigger"
|
||||
>
|
||||
<span className={styles.newPageButtonLabel}>{t['New Page']()}</span>
|
||||
</PageListNewPageButton>
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
} from '@affine/core/modules/collection';
|
||||
import { CollectionRulesService } from '@affine/core/modules/collection-rules';
|
||||
import type { FilterParams } from '@affine/core/modules/collection-rules/types';
|
||||
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
|
||||
import { WorkspaceLocalState } from '@affine/core/modules/workspace';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
@@ -24,7 +23,6 @@ import {
|
||||
ViewIcon,
|
||||
ViewTitle,
|
||||
} from '../../../../modules/workbench';
|
||||
import { AllPage as AllPageOld } from '../all-page-old/all-page';
|
||||
import { AllDocSidebarTabs } from '../layouts/all-doc-sidebar-tabs';
|
||||
import * as styles from './all-page.css';
|
||||
import { AllDocsHeader } from './all-page-header';
|
||||
@@ -350,10 +348,5 @@ export const AllPage = () => {
|
||||
};
|
||||
|
||||
export const Component = () => {
|
||||
const featureFlagService = useService(FeatureFlagService);
|
||||
const enableNewAllDocsPage = useLiveData(
|
||||
featureFlagService.flags.enable_new_all_docs_page.$
|
||||
);
|
||||
|
||||
return enableNewAllDocsPage ? <AllPage /> : <AllPageOld />;
|
||||
return <AllPage />;
|
||||
};
|
||||
|
||||
@@ -100,7 +100,7 @@ export const CollectionListHeader = ({
|
||||
<Button onClick={handleEdit}>{t['Edit']()}</Button>
|
||||
<PageListNewPageButton
|
||||
size="small"
|
||||
testId="new-page-button-trigger"
|
||||
data-testid="new-page-button-trigger"
|
||||
onCreateDoc={onCreateDoc}
|
||||
onCreateEdgeless={onCreateEdgeless}
|
||||
onCreatePage={onCreatePage}
|
||||
|
||||
@@ -311,13 +311,6 @@ export const AFFINE_FLAGS = {
|
||||
configurable: false,
|
||||
defaultState: isCanaryBuild,
|
||||
},
|
||||
enable_new_all_docs_page: {
|
||||
category: 'affine',
|
||||
displayName: 'Enable New All Docs Page',
|
||||
description: 'Use new all docs page',
|
||||
configurable: isCanaryBuild,
|
||||
defaultState: false,
|
||||
},
|
||||
enable_cloud_indexer: {
|
||||
category: 'affine',
|
||||
displayName: 'Enable Cloud Indexer',
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
enableCloudWorkspace,
|
||||
loginUser,
|
||||
} from '@affine-test/kit/utils/cloud';
|
||||
import { getPageByTitle } from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
import { expect } from '@playwright/test';
|
||||
|
||||
@@ -32,14 +33,10 @@ test('should show blob management dialog', async ({ page }) => {
|
||||
await clickSideBarAllPageButton(page);
|
||||
|
||||
// delete the welcome page ('Getting Started')
|
||||
await page
|
||||
.getByTestId('page-list-item')
|
||||
.filter({
|
||||
has: page.getByText('Getting Started'),
|
||||
})
|
||||
.getByTestId('page-list-operation-button')
|
||||
await getPageByTitle(page, 'Getting Started')
|
||||
.getByTestId('doc-list-operation-button')
|
||||
.click();
|
||||
const deleteBtn = page.getByTestId('move-to-trash');
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
await expect(page.getByText('Delete doc?')).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
clickNewPageButton,
|
||||
createLinkedPage,
|
||||
dragTo,
|
||||
getPageByTitle,
|
||||
waitForAllPagesLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
@@ -60,14 +61,10 @@ test('open split view in all docs (operations button)', async ({ page }) => {
|
||||
await clickNewPageButton(page, testTitle);
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
await page
|
||||
.getByTestId('page-list-item')
|
||||
.filter({
|
||||
hasText: testTitle,
|
||||
})
|
||||
.getByTestId('page-list-operation-button')
|
||||
await getPageByTitle(page, testTitle)
|
||||
.getByTestId('doc-list-operation-button')
|
||||
.click();
|
||||
await page.getByRole('menuitem', { name: 'Open in Split View' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Open in split view' }).click();
|
||||
await expect(page.getByTestId('split-view-panel')).toHaveCount(2);
|
||||
const targetPage = page.getByTestId('split-view-panel').last();
|
||||
await expect(targetPage).toHaveAttribute('data-is-active', 'true');
|
||||
@@ -85,12 +82,7 @@ test('open split view in all docs (drag to resize handle)', async ({
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
|
||||
// case for AF-2061. toggle selection checkbox
|
||||
await page.getByTestId('page-list-header-selection-checkbox').click();
|
||||
|
||||
const pageItem = page.getByTestId('page-list-item').filter({
|
||||
hasText: testTitle,
|
||||
});
|
||||
const pageItem = getPageByTitle(page, testTitle);
|
||||
|
||||
const leftResizeHandle = page.getByTestId('resize-handle').first();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
clickNewPageButton,
|
||||
createLinkedPage,
|
||||
dragTo,
|
||||
getPageByTitle,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { clickSideBarAllPageButton } from '@affine-test/kit/utils/sidebar';
|
||||
import { expect } from '@playwright/test';
|
||||
@@ -21,11 +22,6 @@ test('create new tab', async ({ views }) => {
|
||||
// new tab title should be All docs
|
||||
await expectTabTitle(page, 1, 'All docs');
|
||||
await expectActiveTab(page, 1);
|
||||
page = await views.getActive();
|
||||
// page content should be at all docs page
|
||||
await expect(page.getByTestId('virtualized-page-list')).toContainText(
|
||||
'All docs'
|
||||
);
|
||||
});
|
||||
|
||||
test('can switch & close tab by clicking', async ({ page }) => {
|
||||
@@ -115,7 +111,7 @@ test('drag a page from "All pages" list to tabs header', async ({ page }) => {
|
||||
|
||||
await dragTo(
|
||||
page,
|
||||
page.locator(`[data-testid="page-list-item"]:has-text("${title}")`),
|
||||
getPageByTitle(page, title),
|
||||
page.getByTestId('add-tab-view-button')
|
||||
);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { apis } from '@affine/electron-api';
|
||||
import { test } from '@affine-test/kit/electron';
|
||||
import {
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import {
|
||||
@@ -102,7 +103,7 @@ test('export then add', async ({ page, appInfo, workspace }) => {
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// find button which has the title "test1"
|
||||
await page.getByTestId('page-list-item').getByText('test1').click();
|
||||
await getPageByTitle(page, 'test1').click();
|
||||
await waitForEditorLoad(page);
|
||||
const title = page.locator('[data-block-is-title] >> text="test1"');
|
||||
await expect(title).toBeVisible();
|
||||
|
||||
@@ -4,7 +4,6 @@ import { getPagesCount } from '@affine-test/kit/utils/filter';
|
||||
import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
clickPageMoreActions,
|
||||
getAllPage,
|
||||
getBlockSuiteEditorTitle,
|
||||
waitForAllPagesLoad,
|
||||
@@ -50,40 +49,37 @@ test('enable selection and use ESC to disable selection', async ({ page }) => {
|
||||
// there should be no checkbox in the page list by default
|
||||
expect(
|
||||
await page
|
||||
.locator('[data-testid="page-list-item"] [data-testid="affine-checkbox"]')
|
||||
.locator('[data-testid="doc-list-item-select"][data-select-mode="true"]')
|
||||
.count()
|
||||
).toBe(0);
|
||||
|
||||
// by clicking [data-testid="page-list-header-selection-checkbox"], checkboxes should appear
|
||||
// by shift + clicking [data-testid="doc-list-item"], checkboxes should appear
|
||||
await page
|
||||
.locator('[data-testid="page-list-header-selection-checkbox"]')
|
||||
.click();
|
||||
|
||||
// there should be checkboxes in the page list now
|
||||
expect(
|
||||
await page
|
||||
.locator('[data-testid="page-list-item"] [data-testid="affine-checkbox"]')
|
||||
.count()
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
// by ESC, checkboxes should NOT disappear (because it is too early)
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
expect(
|
||||
await page
|
||||
.locator('[data-testid="page-list-item"] [data-testid="affine-checkbox"]')
|
||||
.count()
|
||||
).toBeGreaterThan(0);
|
||||
.locator('[data-testid="doc-list-item"]')
|
||||
.first()
|
||||
.click({
|
||||
modifiers: ['Shift'],
|
||||
});
|
||||
|
||||
// wait for 500ms
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// there should be checkboxes in the page list now
|
||||
expect(
|
||||
await page
|
||||
.locator('[data-testid="doc-list-item-select"][data-select-mode="true"]')
|
||||
.count()
|
||||
).toBeGreaterThan(0);
|
||||
|
||||
// esc again, checkboxes should disappear
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
// wait for 500ms
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
expect(
|
||||
await page
|
||||
.locator('[data-testid="page-list-item"] [data-testid="affine-checkbox"]')
|
||||
.locator('[data-testid="doc-list-item-select"][data-select-mode="true"]')
|
||||
.count()
|
||||
).toBe(0);
|
||||
});
|
||||
@@ -97,21 +93,16 @@ test('select two pages and delete', async ({ page }) => {
|
||||
|
||||
const pageCount = await getPagesCount(page);
|
||||
|
||||
// by clicking [data-testid="page-list-header-selection-checkbox"], checkboxes should appear
|
||||
// by shift + clicking [data-testid="doc-list-item"], checkboxes should appear, and first doc be selected
|
||||
await page
|
||||
.locator('[data-testid="page-list-header-selection-checkbox"]')
|
||||
.click();
|
||||
.locator('[data-testid="doc-list-item"]')
|
||||
.first()
|
||||
.click({
|
||||
modifiers: ['Shift'],
|
||||
});
|
||||
|
||||
// select the first two pages
|
||||
await page
|
||||
.locator('[data-testid="page-list-item"] [data-testid="affine-checkbox"]')
|
||||
.nth(0)
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('[data-testid="page-list-item"] [data-testid="affine-checkbox"]')
|
||||
.nth(1)
|
||||
.click();
|
||||
await page.locator('[data-testid="doc-list-item"]').nth(1).click();
|
||||
|
||||
// the floating popover should appear
|
||||
await expect(page.locator('[data-testid="floating-toolbar"]')).toBeVisible();
|
||||
@@ -132,153 +123,6 @@ test('select two pages and delete', async ({ page }) => {
|
||||
|
||||
expect(await getPagesCount(page)).toBe(pageCount - 2);
|
||||
});
|
||||
test('select two pages and permanently delete', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
|
||||
const pageCount = await getPagesCount(page);
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.locator('[data-testid="page-list-item"]').nth(0).click();
|
||||
|
||||
await page.locator('[data-testid="page-list-item"]').nth(1).click();
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
// the floating popover should appear
|
||||
await expect(page.locator('[data-testid="floating-toolbar"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="floating-toolbar"]')).toHaveText(
|
||||
'2 doc(s) selected'
|
||||
);
|
||||
|
||||
// click delete button
|
||||
await page.locator('[data-testid="list-toolbar-delete"]').click();
|
||||
|
||||
// the confirm dialog should appear
|
||||
await expect(page.getByText('Delete 2 docs?')).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
||||
// check the page count again
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
expect(await getPagesCount(page)).toBe(pageCount - 2);
|
||||
|
||||
await page.getByTestId('trash-page').click();
|
||||
await page.waitForTimeout(300);
|
||||
const trashPageCount = await getPagesCount(page);
|
||||
|
||||
expect(trashPageCount).toBe(2);
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.locator('[data-testid="page-list-item"]').nth(0).click();
|
||||
|
||||
await page.locator('[data-testid="page-list-item"]').nth(1).click();
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
await expect(page.locator('[data-testid="floating-toolbar"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="floating-toolbar"]')).toHaveText(
|
||||
'2 doc(s) selected'
|
||||
);
|
||||
|
||||
await page.locator('[data-testid="list-toolbar-delete"]').click();
|
||||
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
expect(await getPagesCount(page)).toBe(trashPageCount - 2);
|
||||
});
|
||||
|
||||
test('select a group of items by clicking "Select All" in group header', async ({
|
||||
page,
|
||||
}) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
|
||||
// Select All will appear when hovering the header
|
||||
await page.hover('[data-testid="page-list-group-header"]');
|
||||
|
||||
// click Select All
|
||||
await page.getByRole('button', { name: 'Select All' }).click();
|
||||
|
||||
const selectedItemCount = await page
|
||||
.locator('[data-testid="page-list-group-header"]')
|
||||
.getAttribute('data-group-selected-items-count');
|
||||
|
||||
const selectedGroupItemTotalCount = await page
|
||||
.locator('[data-testid="page-list-group-header"]')
|
||||
.getAttribute('data-group-items-count');
|
||||
expect(selectedItemCount).toBe(selectedGroupItemTotalCount);
|
||||
|
||||
// check the selected count is equal to the one displayed in the floating toolbar
|
||||
await expect(page.locator('[data-testid="floating-toolbar"]')).toHaveText(
|
||||
`${selectedItemCount} doc(s) selected`
|
||||
);
|
||||
});
|
||||
|
||||
test('click display button to group pages', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
|
||||
|
||||
await clickPageMoreActions(page);
|
||||
const favoriteBtn = page.getByTestId('editor-option-menu-favorite');
|
||||
await favoriteBtn.click();
|
||||
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
// click the display button
|
||||
await page.locator('[data-testid="page-display-menu-button"]').click();
|
||||
|
||||
// click grouping menu item and wait for submenu
|
||||
|
||||
await page.locator('[data-testid="page-display-grouping-menuItem"]').click();
|
||||
|
||||
// don't know why the `page.getByTestId('group-by-favourites').click()` will make the submenu disappear and failed
|
||||
await page.getByTestId('group-by-favourites').evaluate((el: HTMLElement) => {
|
||||
el.click();
|
||||
});
|
||||
|
||||
// the group header should appear
|
||||
await expect(
|
||||
page.locator('[data-testid="group-label-favourited"]')
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="group-label-notFavourited"]')
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test('select display properties to hide bodyNotes', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill(
|
||||
'this is a new page to test display properties'
|
||||
);
|
||||
await page.keyboard.press('Enter', { delay: 10 });
|
||||
await page.keyboard.insertText('DRAGON BALL: Sparking! ZERO');
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
const cell = page
|
||||
.getByTestId('page-list-item')
|
||||
.getByText('DRAGON BALL: Sparking! ZERO');
|
||||
await expect(cell).toBeVisible();
|
||||
await page.locator('[data-testid="page-display-menu-button"]').click();
|
||||
await page.locator('[data-testid="property-bodyNotes"]').click();
|
||||
await expect(cell).not.toBeVisible();
|
||||
await page.locator('[data-testid="property-bodyNotes"]').click();
|
||||
await expect(cell).toBeVisible();
|
||||
});
|
||||
|
||||
test('select three pages with shiftKey and delete', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
@@ -291,9 +135,9 @@ test('select three pages with shiftKey and delete', async ({ page }) => {
|
||||
|
||||
const pageCount = await getPagesCount(page);
|
||||
await page.keyboard.down('Shift');
|
||||
await page.locator('[data-testid="page-list-item"]').nth(0).click();
|
||||
await page.locator('[data-testid="doc-list-item"]').nth(0).click();
|
||||
|
||||
await page.locator('[data-testid="page-list-item"]').nth(2).click();
|
||||
await page.locator('[data-testid="doc-list-item"]').nth(2).click();
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
// the floating popover should appear
|
||||
@@ -316,40 +160,6 @@ test('select three pages with shiftKey and delete', async ({ page }) => {
|
||||
expect(await getPagesCount(page)).toBe(pageCount - 3);
|
||||
});
|
||||
|
||||
test('create a collection and delete it', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
await clickNewPageButton(page);
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
await page.getByTestId('workspace-collections-button').click();
|
||||
|
||||
// create a collection
|
||||
await page.getByTestId('all-collection-new-button').click();
|
||||
await expect(page.getByTestId('prompt-modal-input')).toBeVisible();
|
||||
await page.getByTestId('prompt-modal-input').fill('test collection');
|
||||
await page.getByTestId('prompt-modal-confirm').click();
|
||||
|
||||
// check the collection is created
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
await page.getByTestId('workspace-collections-button').click();
|
||||
const cell = page
|
||||
.getByTestId('collection-list-item')
|
||||
.getByText('test collection');
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
// delete the collection
|
||||
await page.getByTestId('collection-item-operation-button').click();
|
||||
await page.getByTestId('delete-collection').click();
|
||||
await page.waitForURL(url => url.pathname.endsWith('collection'));
|
||||
|
||||
const newCell = page
|
||||
.getByTestId('collection-list-item')
|
||||
.getByText('test collection');
|
||||
await expect(newCell).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('create a tag and delete it', async ({ page }) => {
|
||||
await openHomePage(page);
|
||||
await waitForEditorLoad(page);
|
||||
|
||||
@@ -72,7 +72,7 @@ test('default to edgeless by editor header items', async ({ page }) => {
|
||||
await clickSideBarAllPageButton(page);
|
||||
await waitForAllPagesLoad(page);
|
||||
const docItem = page.locator(
|
||||
`[data-testid="page-list-item"]:has-text("this is a new page")`
|
||||
`[data-testid="doc-list-item"]:has-text("this is a new page")`
|
||||
);
|
||||
expect(docItem).not.toBeUndefined();
|
||||
await docItem.click();
|
||||
|
||||
@@ -106,7 +106,7 @@ test('drag a page from "All pages" list to favourites, then drag to trash', asyn
|
||||
|
||||
const favouritePage = await dragToFavourites(
|
||||
page,
|
||||
page.locator(`[data-testid="page-list-item"]:has-text("${title}")`),
|
||||
page.locator(`[data-testid="doc-list-item"]:has-text("${title}")`),
|
||||
pageId
|
||||
);
|
||||
|
||||
@@ -124,7 +124,7 @@ test('drag a page from "All pages" list to collections, then drag to trash', asy
|
||||
|
||||
const collectionPage = await dragToCollection(
|
||||
page,
|
||||
page.locator(`[data-testid="page-list-item"]:has-text("${title}")`)
|
||||
page.locator(`[data-testid="doc-list-item"]:has-text("${title}")`)
|
||||
);
|
||||
|
||||
await dragToTrash(page, title, collectionPage);
|
||||
@@ -140,7 +140,7 @@ test('drag a page from "All pages" list to trash', async ({ page }) => {
|
||||
await dragToTrash(
|
||||
page,
|
||||
title,
|
||||
page.locator(`[data-testid="page-list-item"]:has-text("${title}")`)
|
||||
page.locator(`[data-testid="doc-list-item"]:has-text("${title}")`)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -155,7 +155,7 @@ test('drag a page from favourites to collection', async ({ page }) => {
|
||||
// drag to favourites
|
||||
const favouritePage = await dragToFavourites(
|
||||
page,
|
||||
page.locator(`[data-testid="page-list-item"]:has-text("${title}")`),
|
||||
page.locator(`[data-testid="doc-list-item"]:has-text("${title}")`),
|
||||
pageId
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import {
|
||||
@@ -15,9 +16,18 @@ import { expect } from '@playwright/test';
|
||||
|
||||
const removeOnboardingPages = async (page: Page) => {
|
||||
await page.getByTestId('all-pages').click();
|
||||
await page.getByTestId('page-list-header-selection-checkbox').click();
|
||||
// click again to select all
|
||||
await page.getByTestId('page-list-header-selection-checkbox').click();
|
||||
await page
|
||||
.getByTestId('doc-list-item')
|
||||
.first()
|
||||
.click({
|
||||
modifiers: ['Shift'],
|
||||
});
|
||||
await page
|
||||
.getByTestId('doc-list-item')
|
||||
.last()
|
||||
.click({
|
||||
modifiers: ['Shift'],
|
||||
});
|
||||
await page.getByTestId('list-toolbar-delete').click();
|
||||
// confirm delete
|
||||
await page.getByTestId('confirm-modal-confirm').click();
|
||||
@@ -57,7 +67,7 @@ const createAndPinCollection = async (
|
||||
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
const cell = page.getByTestId('page-list-item-title').getByText('test page');
|
||||
const cell = page.getByTestId('doc-list-item-title').getByText('test page');
|
||||
await expect(cell).toBeVisible();
|
||||
};
|
||||
|
||||
@@ -137,7 +147,7 @@ test('add collection from sidebar', async ({ page }) => {
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('test page');
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page.getByTestId('page-list-item-title').getByText('test page');
|
||||
const cell = await getPageByTitle(page, 'test page');
|
||||
await expect(cell).toBeVisible();
|
||||
await page
|
||||
.getByTestId('navigation-panel-collections')
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
getPageItem,
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
@@ -21,17 +22,16 @@ test('page delete -> refresh page -> it should be disappear', async ({
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page delete');
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const cell = allPages.getByText('this is a new page delete');
|
||||
const cell = await getPageByTitle(page, 'this is a new page delete');
|
||||
await expect(cell).toBeVisible();
|
||||
await getPageOperationButton(page, newPageId).click();
|
||||
const deleteBtn = page.getByTestId('move-to-trash');
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
const confirmTip = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('trash-page').click();
|
||||
await getPageItem(page, newPageId).getByTestId('delete-page-button').click();
|
||||
await page.getByTestId('delete-page-button').click();
|
||||
await page.getByText('Delete permanently?').dblclick();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await expect(page.getByText('Deleted docs will appear here.')).toBeVisible();
|
||||
@@ -54,19 +54,16 @@ test('page delete -> create new page -> refresh page -> new page should be appea
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page delete');
|
||||
const newPageDeleteId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const cellDelete = allPages.getByText('this is a new page delete');
|
||||
const cellDelete = await getPageByTitle(page, 'this is a new page delete');
|
||||
await expect(cellDelete).toBeVisible();
|
||||
await getPageOperationButton(page, newPageDeleteId).click();
|
||||
const deleteBtn = page.getByTestId('move-to-trash');
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
const confirmTip = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('trash-page').click();
|
||||
await getPageItem(page, newPageDeleteId)
|
||||
.getByTestId('delete-page-button')
|
||||
.click();
|
||||
await page.getByTestId('delete-page-button').click();
|
||||
await page.getByText('Delete permanently?').dblclick();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await expect(page.getByText('Deleted docs will appear here')).toBeVisible();
|
||||
@@ -114,32 +111,31 @@ test('delete multiple pages -> create multiple pages -> refresh', async ({
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
// 1st cell to be deleted
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const cellDelete1 = allPages.getByText('this is a new page1');
|
||||
const cellDelete1 = await getPageByTitle(page, 'this is a new page1');
|
||||
await expect(cellDelete1).toBeVisible();
|
||||
await getPageOperationButton(page, newPageId1).click();
|
||||
const deleteBtn1 = page.getByTestId('move-to-trash');
|
||||
const deleteBtn1 = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn1.click();
|
||||
const confirmTip1 = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip1).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('trash-page').click();
|
||||
await getPageItem(page, newPageId1).getByTestId('delete-page-button').click();
|
||||
await page.getByTestId('delete-page-button').click();
|
||||
await page.getByText('Delete permanently?').dblclick();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
// 2nd cell to be deleted
|
||||
const cellDelete2 = allPages.getByText('this is a new page2');
|
||||
const cellDelete2 = await getPageByTitle(page, 'this is a new page2');
|
||||
await expect(cellDelete2).toBeVisible();
|
||||
await getPageOperationButton(page, newPageId2).click();
|
||||
const deleteBtn2 = page.getByTestId('move-to-trash');
|
||||
const deleteBtn2 = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn2.click();
|
||||
const confirmTip2 = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip2).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('trash-page').click();
|
||||
await getPageItem(page, newPageId2).getByTestId('delete-page-button').click();
|
||||
await page.getByTestId('delete-page-button').click();
|
||||
await page.getByText('Delete permanently?').dblclick();
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
@@ -20,7 +20,7 @@ test('New a page and open it, then favorite it', async ({
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to favorite');
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page
|
||||
.getByTestId('page-list-item')
|
||||
.getByTestId('doc-list-item-title')
|
||||
.getByText('this is a new page to favorite');
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
@@ -88,14 +88,8 @@ test('Cancel favorite', async ({ page, workspace }) => {
|
||||
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
const box = await getPageByTitle(
|
||||
page,
|
||||
'this is a new page to favorite'
|
||||
).boundingBox();
|
||||
//hover table record
|
||||
await page.mouse.move((box?.x ?? 0) + 10, (box?.y ?? 0) + 10);
|
||||
|
||||
await page.getByTestId('favorited-icon').nth(0).click();
|
||||
const doc = await getPageByTitle(page, 'this is a new page to favorite');
|
||||
await doc.getByTestId('doc-list-operation-favorite').click();
|
||||
|
||||
// expect it not in favorite list
|
||||
await expect(
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
import { getCurrentDocIdFromUrl } from '@affine-test/kit/utils/url';
|
||||
@@ -30,8 +31,7 @@ test('click btn bew page and find it in all pages', async ({
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page');
|
||||
await page.getByTestId('all-pages').click();
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const cell = allPages.getByText('this is a new page');
|
||||
const cell = getPageByTitle(page, 'this is a new page');
|
||||
await expect(cell).toBeVisible();
|
||||
const currentWorkspace = await workspace.current();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
@@ -42,7 +43,7 @@ test('switch between new page and all page', async ({ page }) => {
|
||||
await clickNewPageButton(page, title);
|
||||
await page.getByTestId('all-pages').click();
|
||||
|
||||
const cell = page.getByTestId('page-list-item').getByText(title);
|
||||
const cell = await getPageByTitle(page, title);
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
await cell.click();
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
@@ -20,13 +21,11 @@ test('New a page , then delete it in all pages, restore it', async ({
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to restore');
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page
|
||||
.getByTestId('virtualized-page-list')
|
||||
.getByText('this is a new page to restore');
|
||||
const cell = await getPageByTitle(page, 'this is a new page to restore');
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
await getPageOperationButton(page, newPageId).click();
|
||||
const deleteBtn = page.getByTestId('move-to-trash');
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
const confirmTip = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip).toBeVisible();
|
||||
@@ -42,8 +41,11 @@ test('New a page , then delete it in all pages, restore it', async ({
|
||||
// stay in trash page
|
||||
expect(page.url()).toBe(trashPage);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const restoreCell = allPages.getByText('this is a new page to restore');
|
||||
|
||||
const restoreCell = await getPageByTitle(
|
||||
page,
|
||||
'this is a new page to restore'
|
||||
);
|
||||
await expect(restoreCell).toBeVisible();
|
||||
const currentWorkspace = await workspace.current();
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
clickNewPageButton,
|
||||
clickPageMoreActions,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
@@ -20,9 +21,7 @@ test('New a page ,then open it and show delete modal', async ({
|
||||
await getBlockSuiteEditorTitle(page).click();
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
|
||||
await page.getByTestId('all-pages').click();
|
||||
const cell = page
|
||||
.getByTestId('page-list-item')
|
||||
.getByText('this is a new page to delete');
|
||||
const cell = await getPageByTitle(page, 'this is a new page to delete');
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
await cell.click();
|
||||
@@ -47,12 +46,11 @@ test('New a page ,then go to all pages and show delete modal', async ({
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const cell = allPages.getByText('this is a new page to delete');
|
||||
const cell = await getPageByTitle(page, 'this is a new page to delete');
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
await getPageOperationButton(page, newPageId).click();
|
||||
const deleteBtn = page.getByTestId('move-to-trash');
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
const confirmTip = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip).toBeVisible();
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openHomePage } from '@affine-test/kit/utils/load-page';
|
||||
import {
|
||||
clickNewPageButton,
|
||||
getBlockSuiteEditorTitle,
|
||||
getPageByTitle,
|
||||
getPageOperationButton,
|
||||
waitForEditorLoad,
|
||||
} from '@affine-test/kit/utils/page-logic';
|
||||
@@ -20,12 +21,11 @@ test('New a page , then delete it in all pages, finally find it in trash', async
|
||||
await getBlockSuiteEditorTitle(page).fill('this is a new page to delete');
|
||||
const newPageId = getCurrentDocIdFromUrl(page);
|
||||
await page.getByTestId('all-pages').click();
|
||||
const allPages = page.getByTestId('virtualized-page-list');
|
||||
const cell = allPages.getByText('this is a new page to delete');
|
||||
const cell = await getPageByTitle(page, 'this is a new page to delete');
|
||||
await expect(cell).toBeVisible();
|
||||
|
||||
await getPageOperationButton(page, newPageId).click();
|
||||
const deleteBtn = page.getByTestId('move-to-trash');
|
||||
const deleteBtn = page.getByTestId('doc-list-operation-trash');
|
||||
await deleteBtn.click();
|
||||
const confirmTip = page.getByRole('dialog', { name: 'Delete doc?' });
|
||||
await expect(confirmTip).toBeVisible();
|
||||
@@ -33,9 +33,7 @@ test('New a page , then delete it in all pages, finally find it in trash', async
|
||||
await page.getByRole('button', { name: 'Delete' }).click();
|
||||
|
||||
await page.getByTestId('trash-page').click();
|
||||
await expect(
|
||||
allPages.getByText('this is a new page to delete')
|
||||
).toBeVisible();
|
||||
await expect(page.getByText('this is a new page to delete')).toBeVisible();
|
||||
const currentWorkspace = await workspace.current();
|
||||
|
||||
expect(currentWorkspace.meta.flavour).toContain('local');
|
||||
|
||||
@@ -2,17 +2,8 @@ import type { Page } from '@playwright/test';
|
||||
|
||||
// fixme: there could be multiple page lists in the Page
|
||||
export const getPagesCount = async (page: Page) => {
|
||||
const locator = page.locator('[data-testid="virtualized-page-list"]');
|
||||
const pageListCount = await locator.count();
|
||||
|
||||
if (pageListCount === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// locator is not a HTMLElement, so we can't use dataset
|
||||
// oxlint-disable-next-line unicorn/prefer-dom-node-dataset
|
||||
const count = await locator.getAttribute('data-total-count');
|
||||
return count ? parseInt(count) : 0;
|
||||
const locator = page.locator('[data-testid="doc-list-item"]');
|
||||
return await locator.count();
|
||||
};
|
||||
|
||||
export async function selectTag(page: Page, name: string | RegExp) {
|
||||
|
||||
@@ -30,13 +30,10 @@ export async function waitForEditorLoad(page: Page) {
|
||||
}
|
||||
|
||||
export async function waitForAllPagesLoad(page: Page) {
|
||||
// if page-list-header-selection-checkbox is rendered, we believe all_pages is ready
|
||||
await page.waitForSelector(
|
||||
'[data-testid="page-list-header-selection-checkbox"]',
|
||||
{
|
||||
timeout: 20000,
|
||||
}
|
||||
);
|
||||
// if doc-list-item is rendered, we believe all_pages is ready
|
||||
await page.waitForSelector('[data-testid="doc-list-item"]', {
|
||||
timeout: 20000,
|
||||
});
|
||||
}
|
||||
|
||||
export async function clickNewPageButton(page: Page, title?: string) {
|
||||
@@ -112,15 +109,19 @@ export async function clickPageMoreActions(page: Page) {
|
||||
}
|
||||
|
||||
export const getPageOperationButton = (page: Page, id: string) => {
|
||||
return getPageItem(page, id).getByTestId('page-list-operation-button');
|
||||
return getPageItem(page, id).getByTestId('doc-list-operation-button');
|
||||
};
|
||||
|
||||
export const getPageItem = (page: Page, id: string) => {
|
||||
return page.locator(`[data-page-id="${id}"][data-testid="page-list-item"]`);
|
||||
return page.locator(`[data-doc-id="${id}"][data-testid="doc-list-item"]`);
|
||||
};
|
||||
|
||||
export const getPageByTitle = (page: Page, title: string) => {
|
||||
return page.getByTestId('page-list-item').getByText(title);
|
||||
return page.getByTestId('doc-list-item').filter({
|
||||
has: page.locator(
|
||||
`[data-testid="doc-list-item-title"]:has-text("${title}")`
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
export type DragLocation =
|
||||
|
||||
Reference in New Issue
Block a user