mirror of
https://github.com/AppFlowy-IO/AppFlowy-Web.git
synced 2026-03-13 10:00:26 +08:00
138 lines
5.4 KiB
TypeScript
138 lines
5.4 KiB
TypeScript
/**
|
|
* Embedded Database - Plus Button View Creation Tests
|
|
*
|
|
* Tests plus button view creation, auto-selection, and scroll into view.
|
|
* Migrated from: cypress/e2e/embeded/database/linked-database-plus-button.cy.ts
|
|
*/
|
|
import { test, expect } from '@playwright/test';
|
|
import {
|
|
AddPageSelectors,
|
|
EditorSelectors,
|
|
ModalSelectors,
|
|
SlashCommandSelectors,
|
|
} from '../../../support/selectors';
|
|
import { generateRandomEmail } from '../../../support/test-config';
|
|
import { signInAndWaitForApp } from '../../../support/auth-flow-helpers';
|
|
import { getSlashMenuItemName } from '../../../support/i18n-constants';
|
|
|
|
test.describe('Embedded Database - Plus Button View Creation', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
page.on('pageerror', (err) => {
|
|
if (
|
|
err.message.includes('Minified React error') ||
|
|
err.message.includes('View not found') ||
|
|
err.message.includes('No workspace or service found') ||
|
|
err.message.includes('ResizeObserver loop')
|
|
) {
|
|
return;
|
|
}
|
|
});
|
|
|
|
await page.setViewportSize({ width: 1280, height: 720 });
|
|
});
|
|
|
|
/** Helper to create a document with an embedded linked database */
|
|
async function setupEmbeddedDatabase(
|
|
page: import('@playwright/test').Page,
|
|
request: import('@playwright/test').APIRequestContext
|
|
) {
|
|
const testEmail = generateRandomEmail();
|
|
|
|
await signInAndWaitForApp(page, request, testEmail);
|
|
await expect(page).toHaveURL(/\/app/, { timeout: 30000 });
|
|
await page.waitForTimeout(3000);
|
|
|
|
// Create source database
|
|
await AddPageSelectors.inlineAddButton(page).first().click({ force: true });
|
|
await page.waitForTimeout(1000);
|
|
await AddPageSelectors.addGridButton(page).click({ force: true });
|
|
await page.waitForTimeout(5000);
|
|
|
|
const dbName = 'New Database';
|
|
|
|
// Create document
|
|
await AddPageSelectors.inlineAddButton(page).first().click({ force: true });
|
|
await page.waitForTimeout(1000);
|
|
await page.locator('[role="menuitem"]').first().click({ force: true });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Handle new page modal
|
|
const newPageModal = page.getByTestId('new-page-modal');
|
|
if ((await newPageModal.count()) > 0) {
|
|
await ModalSelectors.spaceItemInModal(page).first().click({ force: true });
|
|
await page.waitForTimeout(500);
|
|
await page.locator('button').filter({ hasText: 'Add' }).click({ force: true });
|
|
await page.waitForTimeout(3000);
|
|
} else {
|
|
await page.waitForTimeout(3000);
|
|
}
|
|
|
|
await expect(EditorSelectors.firstEditor(page)).toBeVisible({ timeout: 15000 });
|
|
|
|
// Insert linked database via slash menu
|
|
await EditorSelectors.firstEditor(page).click({ force: true });
|
|
await page.keyboard.type('/');
|
|
await page.waitForTimeout(500);
|
|
|
|
await expect(SlashCommandSelectors.slashPanel(page)).toBeVisible();
|
|
await SlashCommandSelectors.slashMenuItem(page, getSlashMenuItemName('linkedGrid')).first().click({ force: true });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Select database
|
|
await expect(page.getByText('Link to an existing database')).toBeVisible({ timeout: 10000 });
|
|
const loadingText = page.getByText('Loading...');
|
|
if ((await loadingText.count()) > 0) {
|
|
await expect(loadingText).not.toBeVisible({ timeout: 15000 });
|
|
}
|
|
|
|
const popover = page.locator('.MuiPopover-paper').last();
|
|
await expect(popover).toBeVisible();
|
|
await popover.getByText(dbName, { exact: false }).first().click({ force: true });
|
|
await page.waitForTimeout(3000);
|
|
|
|
return page.locator('[class*="appflowy-database"]').last();
|
|
}
|
|
|
|
test('should create new view using + button and auto-select it', async ({ page, request }) => {
|
|
const embeddedDB = await setupEmbeddedDatabase(page, request);
|
|
await expect(embeddedDB).toBeVisible({ timeout: 15000 });
|
|
|
|
// Find and click the + button to create a new view
|
|
const plusButton = embeddedDB.locator('[data-testid="add-view-button"]');
|
|
await plusButton.scrollIntoViewIfNeeded();
|
|
await plusButton.click({ force: true });
|
|
await page.waitForTimeout(1000);
|
|
|
|
// A new view tab should appear - select Board type if available
|
|
const viewMenu = page.locator('[role="menu"], [data-slot="popover-content"]').last();
|
|
if (await viewMenu.isVisible()) {
|
|
const boardOption = viewMenu.locator('[role="menuitem"]').filter({ hasText: /board/i });
|
|
if ((await boardOption.count()) > 0) {
|
|
await boardOption.first().click({ force: true });
|
|
} else {
|
|
// Just click the first option
|
|
await viewMenu.locator('[role="menuitem"]').first().click({ force: true });
|
|
}
|
|
}
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Verify at least 2 view tabs exist (original + new one)
|
|
const viewTabs = embeddedDB.locator('[data-testid^="view-tab-"]');
|
|
const tabCount = await viewTabs.count();
|
|
expect(tabCount).toBeGreaterThanOrEqual(2);
|
|
|
|
// Verify the new tab is auto-selected (last tab should be active)
|
|
const lastTab = viewTabs.last();
|
|
const isActive = await lastTab.evaluate((el) => {
|
|
return el.classList.contains('active') ||
|
|
el.getAttribute('data-active') === 'true' ||
|
|
el.getAttribute('aria-selected') === 'true' ||
|
|
window.getComputedStyle(el).fontWeight === '700' ||
|
|
parseInt(window.getComputedStyle(el).fontWeight) >= 600;
|
|
});
|
|
|
|
// The new view should either be visually active or at least visible
|
|
await expect(lastTab).toBeVisible();
|
|
});
|
|
});
|