test: add more case

This commit is contained in:
Curry Yang
2026-02-12 15:56:49 +08:00
committed by Curry Yang
parent 8162fc598b
commit ee80a8dc98
3 changed files with 248 additions and 3 deletions

View File

@@ -359,4 +359,77 @@ export class ProjectPage {
async readFixtureContent(fixturePath: string): Promise<string> {
return loadFixture(fixturePath);
}
// ==================== Workspace Export Operations ====================
/**
* Opens the workspace card dropdown menu
* @param workspaceName - The name of the workspace
*/
async openWorkspaceCardDropdown(workspaceName: string) {
const workspaceCard = this.getWorkspaceCard(workspaceName);
await workspaceCard.getByLabel('Workspace actions menu button').click();
}
/**
* Clicks the Export option in the workspace card dropdown
*/
async clickExportInDropdown() {
await this.page.getByRole('menuitem', { name: 'Export' }).click();
}
/**
* Clicks the Export button in the Export Requests modal
*/
async clickExportButtonInExportRequestsModal() {
await this.page.getByRole('dialog').getByRole('button', { name: 'Export' }).click();
}
/**
* Selects the export format in the format selection modal
* @param format - The format to select ('yaml' for Insomnia v5, 'har' for HAR)
*/
async selectExportFormat(format: 'yaml' | 'har') {
await this.page.getByText('Which format would you like to export as?').waitFor({ state: 'visible' });
await this.page.getByLabel('Select Modal').locator('select').selectOption(format);
await this.page.getByRole('button', { name: 'Done' }).click();
}
/**
* Mocks the save dialog to return a specific file path
* Used for single file exports from workspace card
* @param filePath - The file path to return
*/
async mockSaveDialogForFile(filePath: string) {
await this.app.evaluate(async ({ ipcMain }, filePath) => {
ipcMain.removeHandler('showSaveDialog');
ipcMain.handle('showSaveDialog', async () => {
return { filePath, canceled: false };
});
}, filePath);
}
/**
* Exports a workspace from the workspace card dropdown
* Note: After calling this method, use DataPage.waitForExportFiles() to ensure the file is written
* @param workspaceName - The name of the workspace to export
* @param exportPath - The absolute path where the file should be exported
* @param format - The export format ('yaml' or 'har')
*/
async exportWorkspaceFromCard(workspaceName: string, exportPath: string, format: 'yaml' | 'har' = 'yaml') {
// Mock the save dialog first
await this.mockSaveDialogForFile(exportPath);
// Open workspace card dropdown
await this.openWorkspaceCardDropdown(workspaceName);
// Click Export option
await this.clickExportInDropdown();
// Click Export button in the export requests modal (all requests selected by default)
await this.clickExportButtonInExportRequestsModal();
// Select export format
await this.selectExportFormat(format);
}
}

View File

@@ -1,14 +1,16 @@
import type { Page } from '@playwright/test';
import type { ElectronApplication, Page } from '@playwright/test';
/**
* Page Object for the Workspace page (debug view)
* Handles workspace-level operations including navigation
* Handles workspace-level operations including navigation and export
*/
export class WorkspacePage {
readonly page: Page;
readonly app?: ElectronApplication;
constructor(page: Page) {
constructor(page: Page, app?: ElectronApplication) {
this.page = page;
this.app = app;
}
/**
@@ -25,4 +27,79 @@ export class WorkspacePage {
// Wait for the breadcrumb to be visible, indicating workspace is loaded
await this.page.getByTestId('project').waitFor({ state: 'visible' });
}
// ==================== Export Operations ====================
/**
* Opens the workspace dropdown menu
*/
async openWorkspaceDropdown() {
await this.page.getByTestId('workspace-context-dropdown').click();
}
/**
* Clicks the Export option in the workspace dropdown
*/
async clickExportInWorkspaceDropdown() {
// Wait for the Export menu item to be visible, then click it
const exportMenuItem = this.page.getByRole('menuitemradio', { name: 'Export' });
await exportMenuItem.click();
}
/**
* Clicks the Export button in the Export Requests modal
*/
async clickExportButtonInExportRequestsModal() {
await this.page.getByRole('dialog').getByRole('button', { name: 'Export' }).click();
}
/**
* Selects the export format in the format selection modal
* @param format - The format to select ('yaml' for Insomnia v5, 'har' for HAR)
*/
async selectExportFormat(format: 'yaml' | 'har') {
await this.page.getByText('Which format would you like to export as?').waitFor({ state: 'visible' });
await this.page.getByLabel('Select Modal').locator('select').selectOption(format);
await this.page.getByRole('button', { name: 'Done' }).click();
}
/**
* Mocks the save dialog to return a specific file path
* Used for single file exports from workspace dropdown
* @param filePath - The file path to return
*/
async mockSaveDialogForFile(filePath: string) {
if (!this.app) {
throw new Error('ElectronApplication instance is required for mocking save dialog');
}
await this.app.evaluate(async ({ ipcMain }, filePath) => {
ipcMain.removeHandler('showSaveDialog');
ipcMain.handle('showSaveDialog', async () => {
return { filePath, canceled: false };
});
}, filePath);
}
/**
* Exports the workspace from the workspace dropdown
* Note: After calling this method, use DataPage.waitForExportFiles() to ensure the file is written
* @param exportPath - The absolute path where the file should be exported
* @param format - The export format ('yaml' or 'har')
*/
async exportWorkspaceFromDropdown(exportPath: string, format: 'yaml' | 'har' = 'yaml') {
// Mock the save dialog first
await this.mockSaveDialogForFile(exportPath);
// Open workspace dropdown
await this.openWorkspaceDropdown();
// Click Export option
await this.clickExportInWorkspaceDropdown();
// Click Export button in the export requests modal (all requests selected by default)
await this.clickExportButtonInExportRequestsModal();
// Select export format
await this.selectExportFormat(format);
}
}

View File

@@ -4,6 +4,7 @@ import { expect } from '@playwright/test';
import { DataPage } from '../../pages/preferences/data';
import { ProjectPage } from '../../pages/project';
import { WorkspacePage } from '../../pages/workspace';
import { test } from '../../playwright/test';
test.describe('Export', () => {
@@ -166,4 +167,98 @@ test.describe('Export', () => {
dataPage.cleanupExportDir(tempDir);
}
});
test('Can export single workspace from workspace card dropdown', async ({ app, page }) => {
const projectPage = new ProjectPage(page, app);
const workspacePage = new WorkspacePage(page);
const dataPage = new DataPage(page, app);
const projectName = 'Export Single Workspace Test';
const fixtureFile = FIXTURE_FILES[0]; // Collection A
// Step 1: Create a new project
await projectPage.createProject(projectName, 'local');
// Wait for empty project view
await projectPage.waitForEmptyProjectView();
// Step 2: Import a single fixture file
await projectPage.importFixtureFromEmptyProject(fixtureFile);
// After import, app redirects to workspace page, navigate back to project
await workspacePage.waitForWorkspaceLoaded();
await workspacePage.goBackToProject();
// Verify collection was imported
const filesGrid = page.getByLabel('Files');
await expect.soft(filesGrid.getByLabel('Collection A')).toBeVisible();
// Step 3: Export workspace from workspace card dropdown
const tempDir = dataPage.createTempExportDir();
const exportFilePath = path.join(tempDir, 'Collection-A-export.yaml');
try {
// Export the workspace using the workspace card dropdown
await projectPage.exportWorkspaceFromCard('Collection A', exportFilePath, 'yaml');
// Wait for the export file to be created
await dataPage.waitForExportFiles(tempDir, 1);
// Step 4: Verify the exported file matches the fixture
const exportedContent = dataPage.readExportedFile(exportFilePath);
// Compare with fixture
const comparison = dataPage.compareWithFixture(exportedContent, fixtureFile);
expect.soft(comparison.matches, `Exported file should match fixture ${fixtureFile}`).toBe(true);
} finally {
// Cleanup temp directory
dataPage.cleanupExportDir(tempDir);
}
});
test('Can export single workspace from workspace dropdown', async ({ app, page }) => {
const projectPage = new ProjectPage(page, app);
const workspacePage = new WorkspacePage(page, app);
const dataPage = new DataPage(page, app);
const projectName = 'Export Workspace Dropdown Test';
const fixtureFile = FIXTURE_FILES[0]; // Collection A
// Step 1: Create a new project
await projectPage.createProject(projectName, 'local');
// Wait for empty project view
await projectPage.waitForEmptyProjectView();
// Step 2: Import a single fixture file
await projectPage.importFixtureFromEmptyProject(fixtureFile);
// After import, app redirects to workspace page
// This time we stay on the workspace page (don't navigate back to project)
await workspacePage.waitForWorkspaceLoaded();
// Step 3: Export workspace from workspace dropdown
const tempDir = dataPage.createTempExportDir();
const exportFilePath = path.join(tempDir, 'Collection-A-workspace-dropdown-export.yaml');
try {
// Export the workspace using the workspace dropdown
await workspacePage.exportWorkspaceFromDropdown(exportFilePath, 'yaml');
// Wait for the export file to be created
await dataPage.waitForExportFiles(tempDir, 1);
// Step 4: Verify the exported file matches the fixture
const exportedContent = dataPage.readExportedFile(exportFilePath);
// Compare with fixture
const comparison = dataPage.compareWithFixture(exportedContent, fixtureFile);
expect.soft(comparison.matches, `Exported file should match fixture ${fixtureFile}`).toBe(true);
} finally {
// Cleanup temp directory
dataPage.cleanupExportDir(tempDir);
}
});
});