test(core): common setup for ai tests (#11644)

### TL:DR

By sharing initialization logic, accelerate test case execution.

### What Changed

* Global setup for copilot e2e
  * Login
  * Create Workspace
* Enable fully parallel for ci

### Optimization Comparison​

Comparing with PR [fix(core): ask AI input box in the whiteboard is blocked by the menu …](https://github.com/toeverything/AFFiNE/pull/11634):

|           |    Shard 1   |2|3|4|5|6|7|8|
| ------|----|----|----|----|----|---|---|--|
|Before|15min|14min|14min|14min|14min|13min|15min|10min|
|After|8min|11min|8min|8min|8min|8min|8min|7min|

### Trade-Off

Since all copilot use cases currently share a single user and workspace, some test cases need to focus on **isolation** and **independence**.
For example, when testing Embedding-related workflows:
* Different document contents should be used to avoid interference.
* After each test case execution, **cleanup** operations are also required.
* Some tests should be configured to **serial** mode.

```ts
test.describe.configure({ mode: 'serial' });

test.describe('AIChatWith/Collections', () => {
  test.beforeEach(async ({ loggedInPage: page, utils }) => {
    await utils.testUtils.setupTestEnvironment(page);
    await utils.chatPanel.openChatPanel(page);
    await utils.editor.clearAllCollections(page);

    await utils.testUtils.createNewPage(page);
  });

  test.afterEach(async ({ loggedInPage: page, utils }) => {
    // clear all collections
    await utils.editor.clearAllCollections(page);
  });

  test('should support chat with collection', async ({
    loggedInPage: page,
    utils,
  }) => {
    // Create two collections
    await utils.editor.createCollectionAndDoc(
      page,
      'Collection 1',
      'CollectionAAaa is a cute dog'
    );

    await utils.chatPanel.chatWithCollections(page, ['Collection 1']);
    await utils.chatPanel.makeChat(page, 'What is CollectionAAaa(Use English)');
    // ...
  });

  test('should support chat with multiple collections', async ({
    loggedInPage: page,
    utils,
  }) => {
    // Create two collections
    await utils.editor.createCollectionAndDoc(
      page,
      'Collection 2',
      'CollectionEEee is a cute cat'
    );

    await utils.editor.createCollectionAndDoc(
      page,
      'Collection 3',
      'CollectionFFff is a cute dog'
    );

    await utils.chatPanel.chatWithCollections(page, [
      'Collection 2',
      'Collection 3',
    ]);
    await utils.chatPanel.makeChat(
      page,
      'What is CollectionEEee? What is CollectionFFff?(Use English)'
    );
    // ...
  });
});

```

> CLOSE AI-51
This commit is contained in:
yoyoyohamapi
2025-04-14 02:42:06 +00:00
parent 11d1b2fae5
commit d494394c8d
58 changed files with 564 additions and 410 deletions

View File

@@ -238,6 +238,50 @@ export class EditorUtils {
);
}
public static async clearAllCollections(page: Page) {
while (true) {
const collection = await page
.getByTestId('explorer-collections')
.locator('[data-testid^="explorer-collection-"]')
.first();
if (!(await collection.isVisible())) {
break;
}
const collectionContent = await collection.locator('div').first();
await collectionContent.hover();
const more = await collectionContent.getByTestId(
'explorer-tree-node-operation-button'
);
await more.click();
await page.getByTestId('collection-delete-button').click();
}
await page.waitForTimeout(100);
}
public static async clearAllTags(page: Page) {
while (true) {
const tag = await page
.getByTestId('explorer-tags')
.locator('[data-testid^="explorer-tag-"]')
.first();
if (!(await tag.isVisible())) {
break;
}
const tagContent = await tag.locator('div').first();
await tagContent.hover();
const more = await tagContent.getByTestId(
'explorer-tree-node-operation-button'
);
await more.click();
await page.getByTestId('tag-delete-button').click();
}
await page.waitForTimeout(100);
}
public static async createCollectionAndDoc(
page: Page,
collectionName: string,