Skip to content

Commit

Permalink
Added e2e tests for extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
cohansen committed Dec 20, 2024
1 parent 51202f4 commit 644e50a
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 1 deletion.
67 changes: 67 additions & 0 deletions e2e-tests/fixtures/Extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { APIRequestContext, Page } from '@playwright/test';
import { getUserCookieValue } from '../utilities/helpers';

export class Extension {
async createExtension(page: Page, request: APIRequestContext, extensionName: string): Promise<number | undefined> {
const cookie = getUserCookieValue(await page.context().cookies());

if (cookie !== undefined) {
const response = await request.post('http://localhost:8080/v1/graphql/', {
data: JSON.stringify({
query: `
mutation InsertExtension {
insert_extensions(objects: {
label: "${extensionName}",
description: "Description for ${extensionName}",
url: "http://localhost:8080",
extension_roles: {
data: {
role: aerie_admin
}
}
}) {
returning {
id
}
}
}`,
}),
headers: {
Authorization: `Bearer ${cookie}`,
'Content-Type': 'application/json',
},
});

const data = (await response.json()).data.insert_extensions.returning;

return data[0].id as number;
}
}

async deleteExtension(page: Page, request: APIRequestContext, id: number): Promise<void> {
const cookie = getUserCookieValue(await page.context().cookies());

if (cookie !== undefined) {
await request.post('http://localhost:8080/v1/graphql/', {
data: JSON.stringify({
query: `
mutation DeleteExtension {
delete_extensions(where: {
id: {
_eq: ${id}
}
}) {
returning {
id
}
}
}`,
}),
headers: {
Authorization: `Bearer ${cookie}`,
'Content-Type': 'application/json',
},
});
}
}
}
4 changes: 4 additions & 0 deletions e2e-tests/fixtures/Plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class Plan {
navButtonConstraintsMenu: Locator;
navButtonExpansion: Locator;
navButtonExpansionMenu: Locator;
navButtonExtension: Locator;
navButtonExtensionMenu: Locator;
navButtonScheduling: Locator;
navButtonSchedulingMenu: Locator;
navButtonSimulation: Locator;
Expand Down Expand Up @@ -513,6 +515,8 @@ export class Plan {
this.navButtonActivityCheckingMenu = this.navButtonActivityChecking.getByRole('menu');
this.navButtonExpansion = page.locator(`.nav-button:has-text("Expansion")`);
this.navButtonExpansionMenu = this.navButtonExpansion.getByRole('menu');
this.navButtonExtension = page.locator(`.nav-button:has-text("Extensions")`);
this.navButtonExtensionMenu = this.navButtonExtension.getByRole('menu');
this.navButtonConstraints = page.locator(`.nav-button:has-text("Constraints")`);
this.navButtonConstraintsMenu = this.navButtonConstraints.getByRole('menu');
this.navButtonScheduling = page.locator(`.nav-button:has-text("Scheduling")`);
Expand Down
84 changes: 84 additions & 0 deletions e2e-tests/tests/extension.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import test, { BrowserContext, expect, Page } from '@playwright/test';
import { adjectives, animals, colors, uniqueNamesGenerator } from 'unique-names-generator';
import { Constraints } from '../fixtures/Constraints';
import { Extension } from '../fixtures/Extension';
import { Models } from '../fixtures/Models';
import { Plan } from '../fixtures/Plan';
import { Plans } from '../fixtures/Plans';
import { SchedulingConditions } from '../fixtures/SchedulingConditions';
import { SchedulingGoals } from '../fixtures/SchedulingGoals';

let extension: Extension;
let extensionName: string;
let extensionId: number | undefined;
let constraints: Constraints;
let context: BrowserContext;
let models: Models;
let page: Page;
let plan: Plan;
let plans: Plans;
let schedulingConditions: SchedulingConditions;
let schedulingGoals: SchedulingGoals;

test.beforeAll(async ({ baseURL, browser, request }) => {
context = await browser.newContext();
page = await context.newPage();

extension = new Extension();
extensionName = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals] });
extensionId = await extension.createExtension(page, request, extensionName);

models = new Models(page);
plans = new Plans(page, models);
constraints = new Constraints(page);
schedulingConditions = new SchedulingConditions(page);
schedulingGoals = new SchedulingGoals(page);
plan = new Plan(page, plans, constraints, schedulingGoals, schedulingConditions);

await models.goto();
await models.createModel(baseURL);
await plans.goto();
await plans.createPlan();
await plan.goto();
});

test.afterAll(async () => {
await plan.deleteAllActivities();
await plans.goto();
await plans.deletePlan();
await models.goto();
await models.deleteModel();
await page.close();
await context.close();
});

test.describe.serial('Extensions', () => {
test(`Hovering on 'Extensions' in the top navigation bar should show the extension menu`, async () => {
await expect(plan.navButtonExtensionMenu).not.toBeVisible();
plan.navButtonExtension.hover();
await expect(plan.navButtonExtensionMenu).toBeVisible();
plan.planTitle.hover();
await expect(plan.navButtonExtensionMenu).not.toBeVisible();
});

test(`The extension that we created before the tests should be in the extension menu`, async () => {
plan.navButtonExtension.hover();
await expect(plan.navButtonExtensionMenu).toBeVisible();
await expect(plan.navButtonExtensionMenu.getByRole('menuitem', { name: extensionName })).toBeVisible();
});

test(`Clicking the extension should invoke the http call`, async () => {
plan.navButtonExtension.hover();
const extensionRequest = page.waitForRequest('http://localhost:3000/extensions');
plan.navButtonExtensionMenu.getByRole('menuitem', { name: extensionName }).click();
expect((await (await extensionRequest).response())?.ok).toBeTruthy();
});

test(`Delete an extension`, async ({ page, request }) => {
if (extensionId !== undefined) {
await extension.deleteExtension(page, request, extensionId);
await expect(plan.navButtonExtensionMenu).not.toBeVisible();
await expect(plan.navButtonExtension).not.toBeVisible();
}
});
});
5 changes: 5 additions & 0 deletions e2e-tests/tests/plan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ test.describe.serial('Plan', () => {
await expect(plan.navButtonSchedulingMenu).not.toBeVisible();
});

test(`By default the extension menu should not show because there are no extensions`, async () => {
await expect(plan.navButtonExtension).not.toBeVisible();
await expect(plan.navButtonExtensionMenu).not.toBeVisible();
});

test(`Changing to a new plan should clear the selected activity`, async ({ baseURL }) => {
await plan.showPanel(PanelNames.TIMELINE_ITEMS);

Expand Down
11 changes: 11 additions & 0 deletions e2e-tests/utilities/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Cookie } from '@playwright/test';

export function getUserCookieValue(cookies: Cookie[]): string | undefined {
for (const cookie of cookies) {
if (cookie.name === 'user') {
return JSON.parse(atob(cookie.value)).token;
}
}

return undefined;
}
3 changes: 2 additions & 1 deletion src/routes/plans/[id]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
simulationDatasetErrors,
} from '../../../stores/errors';
import { planExpansionStatus, resetExpansionStores, selectedExpansionSetId } from '../../../stores/expansion';
import { extensions } from '../../../stores/extensions';
import {
activityTypes,
initialPlan,
Expand Down Expand Up @@ -791,7 +792,7 @@
</svelte:fragment>
</PlanNavButton>
<ExtensionMenu
extensions={data.extensions}
extensions={$extensions}
title={!compactNavMode ? 'Extensions' : ''}
user={data.user}
on:callExtension={onCallExtension}
Expand Down

0 comments on commit 644e50a

Please sign in to comment.