Skip to content

Commit

Permalink
Add failing test for approving draft project
Browse files Browse the repository at this point in the history
  • Loading branch information
myieye committed Nov 27, 2024
1 parent e5bd400 commit 1025515
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 15 deletions.
56 changes: 56 additions & 0 deletions frontend/tests/draftProject.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as testEnv from './envVars';

import {AdminDashboardPage} from './pages/adminDashboardPage';
import {ProjectPage} from './pages/projectPage';
import {loginAs} from './utils/authHelpers';
import {test, type CreateProjectResponse} from './fixtures';
import {waitForGqlResponse} from './utils/gqlHelpers';
import {expect} from '@playwright/test';
import {UserDashboardPage} from './pages/userDashboardPage';
import {EmailSubjects} from './email/email-page';
import {UserAccountSettingsPage} from './pages/userAccountSettingsPage';

test('Request and approve draft project', async ({page, tempUser, uniqueTestId}) => {
const userDashboardPage = await test.step('Login as user without project create permission', async () => {
await loginAs(page.request, tempUser.email, tempUser.password);
return await new UserDashboardPage(page).goto();
});

await test.step('Verify email so we can request a project', async () => {
const emailPage = await tempUser.mailbox.openEmail(page, EmailSubjects.VerifyEmail);
const pagePromise = emailPage.page.context().waitForEvent('page');
await emailPage.clickVerifyEmail();
const newPage = await pagePromise;
await new UserAccountSettingsPage(newPage).waitFor();
await newPage.close();
});

let project = await test.step('Request a new project', async () => {
await userDashboardPage.page.reload();
await userDashboardPage.waitFor();
const requestProjectPage = await userDashboardPage.clickCreateProject();
const projectCode = `draft-project-test-${uniqueTestId}`;
const project = await requestProjectPage.fillForm({code: projectCode, purpose: 'Testing'}); // Software Developer is only available for admins
await requestProjectPage.submit();
await userDashboardPage.waitFor();
return project;
});

const createProjectResponse = await test.step('Approve the project as admin', async () => {
await loginAs(page.request, 'admin');
const adminDashboard = await new AdminDashboardPage(page).goto();
const approveProjectPage = await adminDashboard.openDraftProject(project.name);
project = await approveProjectPage.fillForm({...project, purpose: 'Software Developer'}); // Software Developer, so that it can be hard deleted
const createProjectResponse = await waitForGqlResponse<CreateProjectResponse>(page, async () => {
await approveProjectPage.submit();
});
await new ProjectPage(page, project.name, project.code).waitFor();
return createProjectResponse;
});

await test.step('Delete the project', async () => {
const projectId = createProjectResponse.data.createProject.createProjectResponse.id;
const deleteResponse = await page.request.delete(`${testEnv.serverBaseUrl}/api/project/${projectId}`);
expect(deleteResponse.ok()).toBeTruthy();
});
});
13 changes: 9 additions & 4 deletions frontend/tests/pages/adminDashboardPage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Locator, Page } from '@playwright/test';
import type {Locator, Page} from '@playwright/test';

import { AuthenticatedBasePage } from './authenticatedBasePage';
import { CreateProjectPage } from './createProjectPage';
import { ProjectPage } from './projectPage';
import {AuthenticatedBasePage} from './authenticatedBasePage';
import {CreateProjectPage} from './createProjectPage';
import {ProjectPage} from './projectPage';

export class AdminDashboardPage extends AuthenticatedBasePage {
get projectFilterBarInput(): Locator { return this.page.locator('.filter-bar').nth(0).getByRole('textbox'); }
Expand All @@ -16,6 +16,11 @@ export class AdminDashboardPage extends AuthenticatedBasePage {
return await new ProjectPage(this.page, projectName, projectCode).waitFor();
}

async openDraftProject(projectName: string): Promise<CreateProjectPage> {
await this.clickProject(projectName);
return await new CreateProjectPage(this.page).waitFor();
}

async clickProject(projectName: string): Promise<void> {
await this.projectFilterBarInput.fill(projectName); // make sure project is visible
const table = this.page.locator('table').nth(0);
Expand Down
29 changes: 21 additions & 8 deletions frontend/tests/pages/createProjectPage.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import { BasePage } from './basePage';
import type { Page } from '@playwright/test';
import {BasePage} from './basePage';
import type {Page} from '@playwright/test';

type ProjectConfig = {
code: string;
customCode: boolean;
name: string;
type: string;
purpose: 'Software Developer' | 'Testing' | 'Training' | 'Language Project';
description: string;
};

export class CreateProjectPage extends BasePage {
constructor(page: Page) {
super(page, page.getByRole('heading', { name: 'Create Project' }), `/project/create`);
super(page, page.getByRole('heading', { name: /(Create|Request) Project/ }), `/project/create`);
}

async fillForm(values: { code: string, customCode?: boolean, name?: string, type?: string, purpose?: string, description?: string }): Promise<void> {
const { code, customCode = false, name = code, type, purpose = 'Software Developer', description = name } = values;
async fillForm(values: Pick<ProjectConfig, 'code'> & Partial<ProjectConfig>): Promise<ProjectConfig> {
let code = values.code;
const { customCode = false, name = code, type = 'FLEx', purpose = 'Software Developer', description = name } = values;
await this.page.getByLabel('Name').fill(name);
await this.page.getByLabel('Description').fill(description ?? name);
if (type) await this.page.getByLabel('Project type').selectOption({ label: type });
if (purpose) await this.page.getByLabel('Purpose').selectOption({ label: purpose });
await this.page.getByLabel('Project type').selectOption({ label: type });
await this.page.getByLabel('Purpose').selectOption({ label: purpose });
await this.page.getByLabel('Language Code').fill(code);
if (customCode) {
await this.page.getByLabel('Custom Code').check();
await this.page.getByLabel('Code', { exact: true }).fill(code);
} else {
code = await this.page.getByLabel('Code', {exact: true}).inputValue();
}
return { code, name, type, purpose, description, customCode };
}

async submit(): Promise<void> {
await this.page.getByRole('button', {name: 'Create Project'}).click();
await this.page.getByRole('button', {name: /(Create|Request) Project/}).click();
}
}
12 changes: 9 additions & 3 deletions frontend/tests/pages/userDashboardPage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Page } from '@playwright/test';
import { AuthenticatedBasePage } from './authenticatedBasePage';
import { ProjectPage } from './projectPage';
import {AuthenticatedBasePage} from './authenticatedBasePage';
import {CreateProjectPage} from './createProjectPage';
import type {Page} from '@playwright/test';
import {ProjectPage} from './projectPage';

export class UserDashboardPage extends AuthenticatedBasePage {
constructor(page: Page) {
Expand All @@ -13,4 +14,9 @@ export class UserDashboardPage extends AuthenticatedBasePage {
await projectCard.click();
return new ProjectPage(this.page, projectName, projectCode).waitFor();
}

async clickCreateProject(): Promise<CreateProjectPage> {
await this.page.getByRole('link', {name: /(Create|Request) Project/, exact: true}).click();
return new CreateProjectPage(this.page).waitFor();
}
}

0 comments on commit 1025515

Please sign in to comment.