diff --git a/global-setup.ts b/global-setup.ts index 251f093..61fc035 100644 --- a/global-setup.ts +++ b/global-setup.ts @@ -1,5 +1,5 @@ import { chromium, FullConfig } from '@playwright/test'; -import { LoginPage } from './page-objects/login/loginPage'; +import { LoginPage } from '@/page-objects/views/login/loginPage'; import userData from './fixtures/userData.json'; async function globalSetup(config: FullConfig) { @@ -7,8 +7,8 @@ async function globalSetup(config: FullConfig) { const browser = await chromium.launch(); const page = await browser.newPage(); const loginPage = new LoginPage(page); - - await page.goto(baseURL + '/#/login'); + + await page.goto(baseURL + '/#/login', { waitUntil: 'domcontentloaded' }); await loginPage.login(userData.adminUser.username, userData.adminUser.password); await page.context().storageState({ path: storageState as string }); diff --git a/page-objects/layout/listLayoutPage.ts b/page-objects/layout/listLayoutPage.ts index 896b9e4..f173e6d 100644 --- a/page-objects/layout/listLayoutPage.ts +++ b/page-objects/layout/listLayoutPage.ts @@ -5,10 +5,12 @@ export default abstract class ListLayoutPage extends NormalLayoutPage { protected listContainer = '.list-layout'; protected createButton = '#add-btn'; + protected confirmButton = '#confirm-btn'; protected searchInput = '#filter-search .el-input input'; protected tableRows = '.list-layout table tbody tr'; protected viewButton = '.view-btn'; protected deleteButton = '.delete-btn'; + protected deleteConfirmButton = '.delete-confirm-btn'; async navigate() { await super.navigate(); @@ -33,9 +35,14 @@ export default abstract class ListLayoutPage extends NormalLayoutPage { await this.page.click(this.createButton); } + async confirm() { + await this.page.click(this.confirmButton); + } + async deleteRow(rowIndex: number) { const row = this.page.locator(this.tableRows).nth(rowIndex); await row.locator(this.deleteButton).click(); + await this.page.click(this.deleteConfirmButton); } async getTableRowCount(): Promise { diff --git a/page-objects/layout/normalLayoutPage.ts b/page-objects/layout/normalLayoutPage.ts index 08882df..068d7f6 100644 --- a/page-objects/layout/normalLayoutPage.ts +++ b/page-objects/layout/normalLayoutPage.ts @@ -1,5 +1,5 @@ import { Page } from '@playwright/test'; -import { LoginPage } from '@/page-objects/login/loginPage'; +import { LoginPage } from '@/page-objects/views/login/loginPage'; import userData from '@/fixtures/userData.json'; export default abstract class NormalLayoutPage { diff --git a/page-objects/project/projectFormPage.ts b/page-objects/project/projectFormPage.ts deleted file mode 100644 index e69de29..0000000 diff --git a/page-objects/home/homePage.ts b/page-objects/views/home/homePage.ts similarity index 100% rename from page-objects/home/homePage.ts rename to page-objects/views/home/homePage.ts diff --git a/page-objects/login/loginPage.ts b/page-objects/views/login/loginPage.ts similarity index 100% rename from page-objects/login/loginPage.ts rename to page-objects/views/login/loginPage.ts diff --git a/page-objects/node/nodeDetailPage.ts b/page-objects/views/node/nodeDetailPage.ts similarity index 96% rename from page-objects/node/nodeDetailPage.ts rename to page-objects/views/node/nodeDetailPage.ts index 64f20db..b02f511 100644 --- a/page-objects/node/nodeDetailPage.ts +++ b/page-objects/views/node/nodeDetailPage.ts @@ -1,4 +1,4 @@ -import { NodeListPage } from '@/page-objects/node/nodeListPage'; +import { NodeListPage } from '@/page-objects/views/node/nodeListPage'; import DetailLayoutPage from '@/page-objects/layout/detailLayoutPage'; export class NodeDetailPage extends DetailLayoutPage { diff --git a/page-objects/node/nodeListPage.ts b/page-objects/views/node/nodeListPage.ts similarity index 100% rename from page-objects/node/nodeListPage.ts rename to page-objects/views/node/nodeListPage.ts diff --git a/page-objects/views/project/projectFormPage.ts b/page-objects/views/project/projectFormPage.ts new file mode 100644 index 0000000..6d3d1f9 --- /dev/null +++ b/page-objects/views/project/projectFormPage.ts @@ -0,0 +1,55 @@ +import { Page } from '@playwright/test'; + +export class ProjectFormPage { + private page: Page; + + constructor(page: Page) { + this.page = page; + } + + // Locators + private nameInput = '[data-test="name"] input'; + private descriptionTextarea = '[data-test="description"] textarea'; + + async fillProjectForm(name: string, description: string) { + await this.setName(name); + await this.setDescription(description); + } + + async setName(name: string) { + await this.page.fill(this.nameInput, name); + } + + async setDescription(description: string) { + await this.page.fill(this.descriptionTextarea, description); + } + + async getName(): Promise { + return await this.page.inputValue(this.nameInput); + } + + async getDescription(): Promise { + return await this.page.inputValue(this.descriptionTextarea); + } + + async isNameInputDisabled(): Promise { + const nameInput = this.page.locator(this.nameInput); + return await nameInput.isDisabled(); + } + + async isDescriptionInputDisabled(): Promise { + const descriptionTextarea = this.page.locator(this.descriptionTextarea); + return await descriptionTextarea.isDisabled(); + } + + async getNamePlaceholder(): Promise { + const nameInput = this.page.locator(this.nameInput); + return await nameInput.getAttribute('placeholder'); + } + + async getDescriptionPlaceholder(): Promise { + const descriptionTextarea = this.page.locator(this.descriptionTextarea); + return await descriptionTextarea.getAttribute('placeholder'); + } +} + diff --git a/page-objects/project/projectListPage.ts b/page-objects/views/project/projectListPage.ts similarity index 100% rename from page-objects/project/projectListPage.ts rename to page-objects/views/project/projectListPage.ts diff --git a/page-objects/spider/spiderListPage.ts b/page-objects/views/spider/spiderListPage.ts similarity index 100% rename from page-objects/spider/spiderListPage.ts rename to page-objects/views/spider/spiderListPage.ts diff --git a/tests/login/login.spec.ts b/tests/login/login.spec.ts index a0a2018..93889f1 100644 --- a/tests/login/login.spec.ts +++ b/tests/login/login.spec.ts @@ -1,5 +1,5 @@ import { test as base, expect } from '@playwright/test'; -import { LoginPage } from '@/page-objects/login/loginPage'; +import { LoginPage } from '@/page-objects/views/login/loginPage'; import userData from '@/fixtures/userData.json'; // Define a new test fixture with a blank storage state diff --git a/tests/node/nodeDetail.spec.ts b/tests/node/nodeDetail.spec.ts index 9054b30..615e758 100644 --- a/tests/node/nodeDetail.spec.ts +++ b/tests/node/nodeDetail.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from '@playwright/test'; -import { NodeDetailPage } from '@/page-objects/node/nodeDetailPage'; +import { NodeDetailPage } from '@/page-objects/views/node/nodeDetailPage'; test.describe('Node Detail Page', () => { let nodeDetailPage: NodeDetailPage; diff --git a/tests/node/nodeList.spec.ts b/tests/node/nodeList.spec.ts index f88fec5..fd86025 100644 --- a/tests/node/nodeList.spec.ts +++ b/tests/node/nodeList.spec.ts @@ -1,5 +1,5 @@ import { test, expect } from '@playwright/test'; -import { NodeListPage } from '@/page-objects/node/nodeListPage'; +import { NodeListPage } from '@/page-objects/views/node/nodeListPage'; test.describe('Node List Tests', () => { let nodeListPage: NodeListPage; diff --git a/tests/project/projectList.spec.ts b/tests/project/projectList.spec.ts index b17bbc2..1f68da1 100644 --- a/tests/project/projectList.spec.ts +++ b/tests/project/projectList.spec.ts @@ -1,11 +1,14 @@ import { test, expect } from '@playwright/test'; -import { ProjectListPage } from '@/page-objects/project/projectListPage'; +import { ProjectListPage } from '@/page-objects/views/project/projectListPage'; +import { ProjectFormPage } from '@/page-objects/views/project/projectFormPage'; -test.describe.skip('Project List Tests', () => { +test.describe('Project List Tests', () => { let projectListPage: ProjectListPage; + let projectFormPage: ProjectFormPage; test.beforeEach(async ({ page }) => { projectListPage = new ProjectListPage(page); + projectFormPage = new ProjectFormPage(page); await projectListPage.navigate(); }); @@ -14,27 +17,6 @@ test.describe.skip('Project List Tests', () => { expect(projectCount).toBeGreaterThanOrEqual(0); }); - test('should create a new project', async ({ page }) => { - const initialCount = await projectListPage.getTableRowCount(); - await projectListPage.clickCreate(); - - // Here you would interact with the create project dialog - // For this example, we'll assume the dialog is handled elsewhere - // and just check that the button click worked - - await page.waitForSelector('.el-dialog'); - const dialogVisible = await page.isVisible('.el-dialog'); - expect(dialogVisible).toBe(true); - - // Close the dialog - await page.click('.el-dialog__close'); - - // In a real scenario, you'd fill out the form and submit it - // Then you'd verify the new project appears in the list - // const newCount = await projectListPage.getProjectCount(); - // expect(newCount).toBe(initialCount + 1); - }); - test('should search for a project', async ({ page }) => { const searchTerm = 'Test Project'; await projectListPage.searchRows(searchTerm); @@ -54,7 +36,7 @@ test.describe.skip('Project List Tests', () => { const projectCount = await projectListPage.getTableRowCount(); if (projectCount > 0) { await projectListPage.navigateToDetail(0); - await page.waitForNavigation(); + await page.waitForSelector('.detail-layout'); expect(page.url()).toContain('/projects/'); } else { // If no projects, skip this test @@ -62,22 +44,65 @@ test.describe.skip('Project List Tests', () => { } }); - test('should delete a project', async ({ page }) => { - const projectCount = await projectListPage.getTableRowCount(); - if (projectCount > 0) { - const initialCount = projectCount; - await projectListPage.deleteRow(0); + test('should verify project form placeholders', async () => { + await projectListPage.clickCreate(); + + const namePlaceholder = await projectFormPage.getNamePlaceholder(); + const descriptionPlaceholder = await projectFormPage.getDescriptionPlaceholder(); + + expect(namePlaceholder).toBe('Name' || '名称'); + expect(descriptionPlaceholder).toBe('Description' || '描述'); + }); + + test('should verify project form field states', async () => { + await projectListPage.clickCreate(); - // Assume there's a confirmation dialog - await page.click('.el-message-box__btns .el-button--primary'); + const isNameDisabled = await projectFormPage.isNameInputDisabled(); + const isDescriptionDisabled = await projectFormPage.isDescriptionInputDisabled(); + + expect(isNameDisabled).toBe(false); + expect(isDescriptionDisabled).toBe(false); + }); + + // Sequential tests for create and delete + test.describe.serial('Create and Delete Tests', () => { + test('should create a new project', async ({ page }) => { + const initialCount = await projectListPage.getTableRowCount(); + await projectListPage.clickCreate(); + + // Fill out the project form + const projectName = 'Test Project'; + const projectDescription = 'This is a test project'; + await projectFormPage.fillProjectForm(projectName, projectDescription); + + // Submit the form (you might need to implement this method in ProjectListPage) + await projectListPage.confirm(); + + // Wait for the new project to appear in the list + await page.waitForTimeout(1000); - await page.waitForTimeout(1000); // Wait for deletion to process const newCount = await projectListPage.getTableRowCount(); - expect(newCount).toBe(initialCount - 1); - } else { - // If no projects, skip this test - test.skip(); - } + expect(newCount).toBe(initialCount + 1); + + // Verify the new project appears in the list + const lastProjectData = await projectListPage.getTableRow(newCount - 1); + expect(lastProjectData.name).toBe(projectName); + expect(lastProjectData.description).toBe(projectDescription); + }); + + test('should delete a project', async ({ page }) => { + const projectCount = await projectListPage.getTableRowCount(); + if (projectCount > 0) { + const initialCount = projectCount; + await projectListPage.deleteRow(0); + + await page.waitForTimeout(1000); // Wait for deletion to process + const newCount = await projectListPage.getTableRowCount(); + expect(newCount).toBe(initialCount - 1); + } else { + // If no projects, skip this test + test.skip(); + } + }); }); }); -