Skip to content

Commit 2878e3a

Browse files
committed
Test fixes
1 parent 0f3069b commit 2878e3a

4 files changed

Lines changed: 320 additions & 72 deletions

File tree

e2e-tests/fixtures/Action.ts

Lines changed: 78 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,12 @@ import { adjectives, animals, colors, uniqueNamesGenerator } from 'unique-names-
33
import { setFileInputByFilepath } from '../utilities/helpers';
44

55
export class Action {
6-
actionDefinitionButton: Locator;
76
actionDescription: string = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals] });
8-
actionFormDescription: Locator;
9-
actionFormName: Locator;
10-
actionFormPath: Locator;
117
actionName: string = uniqueNamesGenerator({ dictionaries: [adjectives, colors, animals] });
128
actionPath: string = 'e2e-tests/data/aerie-action-demo.js';
9+
actionsSidebarTab: Locator;
1310
createActionButton: Locator;
1411
createModal: Locator;
15-
createModalDeleteButton: Locator;
16-
runModal: Locator;
1712

1813
constructor(
1914
public page: Page,
@@ -22,14 +17,30 @@ export class Action {
2217
this.updatePage(page);
2318
}
2419

20+
async archiveAction(): Promise<void> {
21+
// Navigate to Configure tab and click Archive Action
22+
await this.page.getByRole('tab', { name: 'Configure' }).click();
23+
await this.page.getByRole('button', { name: 'Archive Action' }).click();
24+
// Confirm the archive modal
25+
const confirmModal = this.page.locator('#modal-container');
26+
await expect(confirmModal).toBeVisible();
27+
await confirmModal.getByRole('button', { name: 'Archive' }).click();
28+
// Verify the Archived badge appears in the detail view header
29+
await expect(this.page.getByText('Archived', { exact: true })).toBeVisible();
30+
// Verify Run Action button is disabled
31+
await expect(this.page.getByRole('button', { name: 'Run Action' })).toBeDisabled();
32+
}
33+
2534
async configureAction(): Promise<void> {
2635
await this.page.getByRole('tab', { name: 'Configure' }).click();
27-
// Provide the github api url to the action found in `actionPath` so that it can
28-
// successfully query the api
29-
await this.page
30-
.locator(".configure .parameter-base-string:has-text('externalUrl') input")
31-
.fill('https://api.github.com/');
32-
await this.page.getByRole('button', { name: 'Save' }).click();
36+
// Fill in the externalUrl setting and blur to trigger change event
37+
const externalUrlInput = this.page.locator(".parameter-base-string:has-text('externalUrl') input");
38+
await externalUrlInput.fill('https://api.github.com/');
39+
await externalUrlInput.dispatchEvent('change');
40+
// Wait for Save button to become enabled (isDirty must be true)
41+
const saveButton = this.page.getByRole('button', { name: 'Save' });
42+
await expect(saveButton).toBeEnabled({ timeout: 5000 });
43+
await saveButton.click();
3344
await this.waitForToast('Action Updated Successfully');
3445
}
3546

@@ -38,46 +49,75 @@ export class Action {
3849
await this.createActionButton.click();
3950
await expect(this.createModal).toBeVisible();
4051
await expect(createButton).toBeDisabled();
41-
await this.actionFormName.fill(this.actionName);
42-
await this.actionFormDescription.fill(this.actionDescription);
43-
await this.actionFormPath.waitFor({ state: 'attached' });
44-
await setFileInputByFilepath(this.page, this.actionFormPath, this.actionPath, createButton);
52+
await this.page.getByLabel('name').fill(this.actionName);
53+
await this.page.getByLabel('description').fill(this.actionDescription);
54+
const fileInput = this.page.locator('input[name="file"]');
55+
await fileInput.waitFor({ state: 'attached' });
56+
await setFileInputByFilepath(this.page, fileInput, this.actionPath, createButton);
4557
await expect(createButton).toBeEnabled();
4658
await createButton.click();
4759
await this.waitForToast('Action Created Successfully');
48-
await this.page.getByRole('button', { name: this.actionName });
49-
await expect(this.actionDefinitionButton).toBeVisible();
60+
// Verify action appears in sidebar
61+
await expect(this.page.getByRole('button', { name: this.actionName })).toBeVisible();
5062
return this.actionName;
5163
}
5264

5365
async inspectAction(): Promise<void> {
54-
await expect(this.actionDefinitionButton).toBeVisible();
55-
await this.actionDefinitionButton.click();
56-
await expect(
57-
this.page.locator(`.action-definition-runs-container:has-text("${this.actionDescription}")`),
58-
).toBeVisible();
66+
// Click action in sidebar to open detail view
67+
await this.page.getByRole('button', { name: this.actionName }).click();
68+
// Verify action detail view shows name and description
69+
await expect(this.page.locator('h2', { hasText: this.actionName })).toBeVisible();
70+
await expect(this.page.locator('p', { hasText: this.actionDescription })).toBeVisible();
71+
// Verify tabs are present
72+
await expect(this.page.getByRole('tab', { name: /Runs/ })).toBeVisible();
73+
await expect(this.page.getByRole('tab', { name: 'Configure' })).toBeVisible();
74+
await expect(this.page.getByRole('tab', { name: 'Code' })).toBeVisible();
5975
}
6076

6177
async runAction(): Promise<void> {
62-
await this.actionDefinitionButton.getByRole('button', { name: 'Run' }).click();
63-
await expect(this.runModal).toBeVisible();
64-
// Provide the aerie repository path to the action found in `actionPath` so that it can
65-
// successfully query the api
66-
await this.runModal.locator(".parameter-base-string:has-text('repository') input").fill('repos/NASA-AMMOS/aerie');
67-
await this.runModal.getByRole('button', { name: 'Run' }).click();
68-
await this.page.waitForURL(`/workspaces/${this.workspaceId}/actions/runs/**`);
69-
await this.page.getByLabel('Complete');
78+
// Click "Run Action" button in the detail view header
79+
await this.page.getByRole('button', { name: 'Run Action' }).click();
80+
// Wait for the run modal to appear
81+
const runModal = this.page.locator('#modal-container');
82+
await expect(runModal).toBeVisible();
83+
// Click the Run button in the modal footer
84+
await runModal.getByRole('button', { exact: true, name: 'Run' }).click();
85+
// Verify we navigated to the run detail view
86+
await expect(this.page.locator('h2', { hasText: /Run #\d+/ })).toBeVisible({ timeout: 15000 });
87+
// Wait for a terminal status (Complete or Failed) in the main content area
88+
const mainContent = this.page.getByRole('main');
89+
await expect(mainContent.getByLabel('Complete').or(mainContent.getByLabel('Failed'))).toBeVisible({
90+
timeout: 30000,
91+
});
92+
}
93+
94+
async selectActionInSidebar(): Promise<void> {
95+
// Click the action in the sidebar list (scoped to complementary to avoid matching other elements)
96+
await this.page.getByRole('complementary').getByRole('button', { name: this.actionName }).click();
97+
await expect(this.page.locator('h2', { hasText: this.actionName })).toBeVisible();
98+
}
99+
100+
async switchToActionsTab(): Promise<void> {
101+
await this.actionsSidebarTab.click();
102+
await expect(this.page.getByText('Workspace Actions')).toBeVisible();
103+
}
104+
105+
async unarchiveAction(): Promise<void> {
106+
// Navigate to Configure tab and click Unarchive Action
107+
await this.page.getByRole('tab', { name: 'Configure' }).click();
108+
await this.page.getByRole('button', { name: 'Unarchive Action' }).click();
109+
// Confirm the unarchive modal
110+
const confirmModal = this.page.locator('#modal-container');
111+
await expect(confirmModal).toBeVisible();
112+
await confirmModal.getByRole('button', { name: 'Unarchive' }).click();
113+
// Verify Run Action button is enabled again
114+
await expect(this.page.getByRole('button', { name: 'Run Action' })).toBeEnabled();
70115
}
71116

72117
updatePage(page: Page) {
73-
this.actionDefinitionButton = page.getByRole('button', { name: this.actionName });
74-
this.actionFormDescription = page.getByLabel('description');
75-
this.actionFormPath = page.locator('input[name="file"]');
76-
this.actionFormName = page.getByLabel('name');
118+
this.actionsSidebarTab = page.getByLabel('Actions', { exact: true });
77119
this.createActionButton = page.getByRole('button', { name: 'New Action' });
78-
this.createModal = page.locator(`.modal:has-text("New Action")`);
79-
this.createModalDeleteButton = this.createModal.getByRole('button', { name: 'Delete' });
80-
this.runModal = page.locator(`.modal:has-text("Run Action")`);
120+
this.createModal = page.locator('.modal:has-text("New Action")');
81121
this.page = page;
82122
}
83123

e2e-tests/tests/actions.test.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,8 @@ test.afterAll(async () => {
4646
});
4747

4848
test.describe.serial('Actions', () => {
49-
test('Navigate to workspace actions from sidebar', async () => {
50-
const newPagePromise = setup.context.waitForEvent('page');
51-
await setup.page.getByRole('complementary').getByRole('button', { name: 'Actions' }).click();
52-
const newTab = await newPagePromise;
53-
await newTab.waitForLoadState();
54-
await newTab.getByText('Loading...').first().waitFor({ state: 'hidden' });
55-
await newTab.waitForURL(`/workspaces/${workspaceId}/actions`);
56-
await action.updatePage(newTab);
49+
test('Navigate to workspace actions tab', async () => {
50+
await action.switchToActionsTab();
5751
});
5852

5953
test('Create an action', async () => {
@@ -71,4 +65,14 @@ test.describe.serial('Actions', () => {
7165
test('Run an action', async () => {
7266
await action.runAction();
7367
});
68+
69+
test('Archive an action prevents running', async () => {
70+
// Go back to the action detail view by clicking action name in sidebar
71+
await action.selectActionInSidebar();
72+
await action.archiveAction();
73+
});
74+
75+
test('Unarchive an action allows running again', async () => {
76+
await action.unarchiveAction();
77+
});
7478
});

0 commit comments

Comments
 (0)