feat(mobile): explorer create/rename operation (#8628)

close AF-1560
This commit is contained in:
CatsJuice
2024-11-04 05:28:05 +00:00
parent 12e3cf1d07
commit 4cbf4b74d6
44 changed files with 1139 additions and 252 deletions

View File

@@ -0,0 +1,76 @@
import { test } from '@affine-test/kit/mobile';
import { expect, type Locator, type Page } from '@playwright/test';
import {
expandCollapsibleSection,
getAttrOfActiveElement,
openExplorerNodeMenu,
} from './utils';
const locateFolder = async (scope: Page | Locator, name: string) => {
return scope.locator(`[data-role="explorer-folder"][aria-label="${name}"]`);
};
/**
* Check rename input is focused
*/
const isRenameInputFocused = async (page: Page) => {
const focusElTestid = await getAttrOfActiveElement(page);
expect(focusElTestid).toEqual('rename-input');
};
const createRootFolder = async (page: Page, name: string) => {
const section = await expandCollapsibleSection(page, 'organize');
await section.getByTestId('explorer-bar-add-organize-button').tap();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await isRenameInputFocused(page);
await page.keyboard.type(name);
await dialog.getByTestId('rename-confirm').tap();
await expect(dialog).not.toBeVisible();
const node = await locateFolder(section, name);
return node;
};
const createSubFolder = async (page: Page, parent: Locator, name: string) => {
const menu = await openExplorerNodeMenu(page, parent);
await menu.getByTestId('create-subfolder').tap();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await isRenameInputFocused(page);
await page.keyboard.type(name);
await dialog.getByTestId('rename-confirm').tap();
await expect(dialog).not.toBeVisible();
const node = await locateFolder(parent, name);
return node;
};
test('create a folder', async ({ page }) => {
const node = await createRootFolder(page, 'Test Folder');
await expect(node).toBeVisible();
});
test('create a sub folder', async ({ page }) => {
const parent = await createRootFolder(page, 'Parent Folder');
await expect(parent).toBeVisible();
await parent.tap();
const child = await createSubFolder(page, parent, 'Child Folder');
await expect(child).toBeVisible();
});
test('create a folder and rename it', async ({ page }) => {
const originalName = 'Test Folder';
const appendedName = ' Renamed';
const folder = await createRootFolder(page, originalName);
const menu = await openExplorerNodeMenu(page, folder);
await menu.getByTestId('rename-folder').tap();
await isRenameInputFocused(page);
await page.keyboard.type(appendedName);
await menu.getByTestId('rename-confirm').tap();
const renamedFolder = await locateFolder(page, originalName + appendedName);
await expect(folder).not.toBeVisible();
await expect(renamedFolder).toBeVisible();
});

View File

@@ -0,0 +1,87 @@
import { test } from '@affine-test/kit/mobile';
import { expect, type Locator, type Page } from '@playwright/test';
import {
expandCollapsibleSection,
getAttrOfActiveElement,
openExplorerNodeMenu,
} from './utils';
async function locateTag(scope: Page | Locator, name: string) {
return scope.locator(`[data-role="explorer-tag"][aria-label="${name}"]`);
}
async function getExplorerTagColor(tagNode: Locator) {
const icon = tagNode.getByTestId('explorer-tag-icon-dot');
await expect(icon).toBeVisible();
const color = await icon.evaluate(el => el.style.backgroundColor);
return color;
}
async function changeTagColor(scope: Locator, color: string) {
const trigger = scope.getByTestId('tag-color-picker-trigger');
const select = scope.getByTestId('tag-color-picker-select');
await trigger.tap();
await expect(select).toBeVisible();
const colorDot = select.locator(`[data-color="${color}"]`);
await colorDot.tap();
}
async function createRootTag(
page: Page,
name: string,
color = 'var(--affine-palette-line-red)'
) {
const section = await expandCollapsibleSection(page, 'tags');
await section.getByTestId('explorer-add-tag-button').tap();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
// input name
const focusedTestid = await getAttrOfActiveElement(page);
expect(focusedTestid).toEqual('rename-input');
await page.keyboard.type(name);
// set color
await changeTagColor(dialog, color);
// confirm
await dialog.getByTestId('rename-confirm').tap();
const tag = await locateTag(section, name);
await expect(tag).toBeVisible();
// check tag color
const fill = await getExplorerTagColor(tag);
expect(fill).toEqual(color);
return tag;
}
test('create a tag from explorer', async ({ page }) => {
await createRootTag(page, 'Test Tag');
});
test('rename a tag from explorer', async ({ page }) => {
const originalName = 'Test Tag';
const appendedName = ' Renamed';
const tag = await createRootTag(page, originalName);
const menu = await openExplorerNodeMenu(page, tag);
await menu.getByTestId('rename-tag').tap();
const focusedTestid = await getAttrOfActiveElement(page);
expect(focusedTestid).toEqual('rename-input');
await page.keyboard.type(appendedName);
await menu.getByTestId('rename-confirm').tap();
await expect(tag).not.toBeVisible();
const renamedTag = await locateTag(page, originalName + appendedName);
await expect(renamedTag).toBeVisible();
});
test('change tag color from explorer', async ({ page }) => {
const newColor = 'var(--affine-palette-line-green)';
const tagName = 'Test Tag';
const tag = await createRootTag(page, tagName);
const menu = await openExplorerNodeMenu(page, tag);
await menu.getByTestId('rename-tag').tap();
await changeTagColor(menu, newColor);
await menu.getByTestId('rename-confirm').tap();
const updatedTag = await locateTag(page, tagName);
const fill = await getExplorerTagColor(updatedTag);
expect(fill).toEqual(newColor);
});

View File

@@ -1,5 +1,5 @@
/* eslint-disable unicorn/prefer-dom-node-dataset */
import { expect, type Page } from '@playwright/test';
import { expect, type Locator, type Page } from '@playwright/test';
export async function expandCollapsibleSection(page: Page, name: string) {
const divider = page.locator(`[data-collapsible]:has-text("${name}")`);
@@ -20,3 +20,24 @@ export async function expandCollapsibleSection(page: Page, name: string) {
export async function pageBack(page: Page) {
await page.getByTestId('page-header-back').tap();
}
export async function getAttrOfActiveElement(
page: Page,
attrName = 'data-testid'
) {
return await page.evaluate(name => {
const el = document.activeElement;
return el ? el.getAttribute(name) : '';
}, attrName);
}
/**
* Open the context menu of an explorer node
* @returns Menu Locator
*/
export async function openExplorerNodeMenu(page: Page, node: Locator) {
await node.getByTestId('menu-trigger').tap();
const menu = page.getByRole('dialog');
await expect(menu).toBeVisible();
return menu;
}