AFFiNE/tests/affine-local/e2e/page-properties.spec.ts
pengx17 4b6c4ed546
feat(core): doc database properties (#8520)
fix AF-1454

1. move inline tags editor to components
2. add progress component
3. adjust doc properties styles for desktop
4. subscribe bs database links and display in doc info
5. move update/create dates to doc info
6. a trivial e2e test

<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/T2klNLEk0wxLh4NRDzhk/eed266c1-fdac-4f0e-baa9-4aa00d14a2e8.mp4">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/T2klNLEk0wxLh4NRDzhk/eed266c1-fdac-4f0e-baa9-4aa00d14a2e8.mp4">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/eed266c1-fdac-4f0e-baa9-4aa00d14a2e8.mp4">10月23日.mp4</video>
2024-10-24 07:38:45 +00:00

357 lines
11 KiB
TypeScript

/* eslint-disable unicorn/prefer-dom-node-dataset */
import { test } from '@affine-test/kit/playwright';
import {
openHomePage,
openJournalsPage,
} from '@affine-test/kit/utils/load-page';
import {
addDatabase,
addDatabaseRow,
clickNewPageButton,
createLinkedPage,
dragTo,
waitForEditorLoad,
waitForEmptyEditor,
} from '@affine-test/kit/utils/page-logic';
import {
addCustomProperty,
changePropertyVisibility,
clickPropertyValue,
closeTagsEditor,
ensurePagePropertiesVisible,
expectTagsVisible,
getPropertyValueLocator,
openTagsEditor,
openWorkspaceProperties,
removeSelectedTag,
searchAndCreateTag,
togglePropertyListVisibility,
} from '@affine-test/kit/utils/properties';
import { expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await openHomePage(page);
await clickNewPageButton(page);
await waitForEmptyEditor(page);
await ensurePagePropertiesVisible(page);
});
test('allow create tag', async ({ page }) => {
await openTagsEditor(page);
await searchAndCreateTag(page, 'Test1');
await searchAndCreateTag(page, 'Test2');
await closeTagsEditor(page);
await expectTagsVisible(page, ['Test1', 'Test2']);
await openTagsEditor(page);
await removeSelectedTag(page, 'Test1');
await closeTagsEditor(page);
await expectTagsVisible(page, ['Test2']);
});
test('allow using keyboard to navigate tags', async ({ page }) => {
await openTagsEditor(page);
await searchAndCreateTag(page, 'Test1');
await searchAndCreateTag(page, 'Test2');
await page.keyboard.press('ArrowLeft');
await page.keyboard.press('Backspace');
await closeTagsEditor(page);
await expectTagsVisible(page, ['Test1']);
await openTagsEditor(page);
await page.keyboard.press('ArrowDown');
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
await closeTagsEditor(page);
await expectTagsVisible(page, ['Test1', 'Test2']);
});
test('allow create tag on journals page', async ({ page }) => {
await openJournalsPage(page);
await waitForEditorLoad(page);
await ensurePagePropertiesVisible(page);
await openTagsEditor(page);
await searchAndCreateTag(page, 'Test1');
await searchAndCreateTag(page, 'Test2');
await closeTagsEditor(page);
await expectTagsVisible(page, ['Test1', 'Test2']);
await openTagsEditor(page);
await removeSelectedTag(page, 'Test1');
await closeTagsEditor(page);
await expectTagsVisible(page, ['Test2']);
});
test('add custom property', async ({ page }) => {
await addCustomProperty(page, page, 'text');
await addCustomProperty(page, page, 'number');
await addCustomProperty(page, page, 'date');
await addCustomProperty(page, page, 'checkbox');
await addCustomProperty(page, page, 'createdBy');
await addCustomProperty(page, page, 'updatedBy');
});
test('add custom property & edit', async ({ page }) => {
await addCustomProperty(page, page, 'checkbox');
await expect(
getPropertyValueLocator(page, 'checkbox').locator('input')
).not.toBeChecked();
await clickPropertyValue(page, 'checkbox');
await expect(
getPropertyValueLocator(page, 'checkbox').locator('input')
).toBeChecked();
});
test('property table reordering', async ({ page }) => {
await addCustomProperty(page, page, 'text');
await addCustomProperty(page, page, 'number');
await addCustomProperty(page, page, 'date');
await addCustomProperty(page, page, 'checkbox');
await addCustomProperty(page, page, 'createdBy');
await addCustomProperty(page, page, 'updatedBy');
await dragTo(
page,
page.locator('[data-testid="doc-property-name"]:has-text("Text")'),
page.locator(
'[data-testid="doc-property-name"]:has-text("Checkbox") + div'
),
'bottom'
);
// new order should be Doc mode, (Tags), Created at, Updated at, Number, Date, Checkbox, Text
for (const [index, property] of [
'Tags',
'Doc mode',
'Journal',
'Created at',
'Updated at',
'Number',
'Date',
'Checkbox',
'Text',
'Created by',
'Last edited by',
].entries()) {
await expect(
page
.getByTestId('doc-property-row')
.nth(index)
.getByTestId('doc-property-name')
).toHaveText(property);
}
});
test('page info show more will not should by default when there is no properties', async ({
page,
}) => {
// by default page info show more should not show
await expect(page.getByTestId('page-info-show-more')).not.toBeVisible();
});
test('page info show more will show all properties', async ({ page }) => {
await addCustomProperty(page, page, 'text');
await addCustomProperty(page, page, 'number');
await addCustomProperty(page, page, 'date');
await addCustomProperty(page, page, 'checkbox');
await addCustomProperty(page, page, 'createdBy');
await addCustomProperty(page, page, 'updatedBy');
await changePropertyVisibility(page, 'Text', 'always-hide');
await expect(page.getByTestId('property-collapsible-button')).toBeVisible();
await page.click('[data-testid="property-collapsible-button"]');
for (const [index, property] of [
'Tags',
'Doc mode',
'Journal',
'Created at',
'Updated at',
'Text',
'Number',
'Date',
'Checkbox',
'Created by',
'Last edited by',
].entries()) {
await expect(
page
.getByTestId('doc-property-row')
.nth(index)
.getByTestId('doc-property-name')
).toHaveText(property);
}
});
test('change page properties visibility', async ({ page }) => {
await addCustomProperty(page, page, 'text');
await addCustomProperty(page, page, 'number');
await addCustomProperty(page, page, 'date');
await addCustomProperty(page, page, 'checkbox');
await togglePropertyListVisibility(page);
// add some number to number property
await clickPropertyValue(page, 'Number');
await page.locator('input[type=number]').fill('123');
await changePropertyVisibility(page, 'Text', 'always-hide');
await changePropertyVisibility(page, 'Number', 'hide-when-empty');
// text property should not be visible
await expect(
page.locator('[data-testid="doc-property-name"]:has-text("Text")')
).not.toBeVisible();
// number property should be visible
await expect(
page.locator('[data-testid="doc-property-name"]:has-text("Number")')
).toBeVisible();
});
test('check if added property is also in workspace settings', async ({
page,
}) => {
await addCustomProperty(page, page, 'text');
await openWorkspaceProperties(page);
await expect(
page.locator('[data-testid=doc-property-manager-item]:has-text("Text")')
).toBeVisible();
});
test('edit property name', async ({ page }) => {
await addCustomProperty(page, page, 'text');
await page
.locator('[data-testid="doc-property-name"]:has-text("Text")')
.click();
await expect(page.locator('[data-radix-menu-content]')).toBeVisible();
await expect(page.locator('[data-radix-menu-content] input')).toHaveValue(
'Text'
);
await page.locator('[data-radix-menu-content] input').fill('New Text');
await page.keyboard.press('Enter');
await expect(page.locator('[data-radix-menu-content] input')).toHaveValue(
'New Text'
);
await page.keyboard.press('Escape');
// check if the property name is also updated in workspace settings
await openWorkspaceProperties(page);
await expect(
page.locator('[data-testid=doc-property-manager-item]:has-text("New Text")')
).toBeVisible();
});
test('delete property via property popup', async ({ page }) => {
await addCustomProperty(page, page, 'text');
await page
.locator('[data-testid="doc-property-name"]:has-text("Text")')
.click();
await expect(page.locator('[data-radix-menu-content]')).toBeVisible();
await page
.locator('[data-radix-menu-content]')
.getByRole('menuitem', {
name: 'Delete property',
})
.click();
// confirm delete dialog should show
await expect(page.getByRole('dialog')).toBeVisible();
await page
.getByRole('button', {
name: 'Confirm',
})
.click();
// check if the property is removed
await expect(
page.locator('[data-testid="http://localhost:8080/"]:has-text("Text")')
).not.toBeVisible();
});
test('workspace properties can be collapsed', async ({ page }) => {
await expect(page.getByTestId('doc-property-row').first()).toBeVisible();
await page.getByRole('button', { name: 'Workspace properties' }).click();
await expect(page.getByTestId('doc-property-row').first()).not.toBeVisible();
await page.getByRole('button', { name: 'Workspace properties' }).click();
await expect(page.getByTestId('doc-property-row').first()).toBeVisible();
});
// todo: add more tests for database backlink info for different cell types
test('can show database backlink info', async ({ page }) => {
const pageTitle = 'some page title';
await clickNewPageButton(page, pageTitle);
await page.keyboard.press('Enter');
const databaseTitle = 'some database title';
await addDatabase(page, databaseTitle);
await expect(page.locator('affine-database-title')).toContainText(
databaseTitle
);
await expect(
page.locator(`affine-database-title:has-text("${databaseTitle}")`)
).toBeVisible();
await addDatabaseRow(page, databaseTitle);
// the new row's title cell should have been focused at the point of adding the row
await createLinkedPage(page, 'linked page');
// change status label
await page.keyboard.press('Escape');
await page.keyboard.press('ArrowRight');
await page.keyboard.press('Enter');
await page.keyboard.type('Done');
await page
.locator('affine-multi-tag-select .select-option:has-text("Done")')
.click();
// go back to title cell
await page.keyboard.press('ArrowLeft');
await page.keyboard.press('Enter');
// goto the linked page
await page.locator('.affine-reference-title:has-text("linked page")').click();
// ensure the page properties are visible
await ensurePagePropertiesVisible(page);
// database backlink property should be rendered, but collapsed
const linkedDatabaseSection = page
.getByTestId('property-collapsible-section')
.filter({
hasText: 'some database title',
});
await expect(linkedDatabaseSection).toBeVisible();
await expect(
linkedDatabaseSection.getByTestId('property-collapsible-section-content')
).not.toBeVisible();
await expect(
linkedDatabaseSection.locator(
`.affine-reference-title:has-text("${pageTitle}")`
)
).toBeVisible();
// expand the linked database section
await linkedDatabaseSection
.getByTestId('property-collapsible-section-trigger')
.click();
await expect(
linkedDatabaseSection.getByTestId('property-collapsible-section-content')
).toBeVisible();
await expect(
linkedDatabaseSection
.getByTestId('database-backlink-cell')
.getByTestId('inline-tags-list')
.filter({
hasText: 'Done',
})
).toBeVisible();
});