Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advanced Timeline Filtering #1535

Open
wants to merge 92 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
050c46b
WIP
AaronPlave Oct 21, 2024
55e7706
Fixes for spans
AaronPlave Oct 30, 2024
edd0037
Componentize editor section headers. Remove unused styles.
AaronPlave Oct 31, 2024
61b72eb
Refactoring, fixing, improving timeline editor
AaronPlave Oct 31, 2024
e5d558b
Add icon
AaronPlave Nov 5, 2024
6a9fbef
Add svelte dragging library
AaronPlave Nov 5, 2024
2595f71
Style refactor
AaronPlave Nov 5, 2024
fa0b8bf
Make menu items tab focusable
AaronPlave Nov 5, 2024
3e740e5
Style tweak
AaronPlave Nov 5, 2024
1b1f16e
WIP activity layer filtering
AaronPlave Nov 5, 2024
e24e16b
style refactor
AaronPlave Nov 5, 2024
d4cfdb2
Get default activity arguments during plan load
AaronPlave Nov 12, 2024
69c0f4e
Potentially remove unused input workaround
AaronPlave Nov 12, 2024
251e6b5
WIP filtering
AaronPlave Nov 12, 2024
ef8a7b4
Basic manual type selection list filtering
AaronPlave Nov 12, 2024
52cd277
add cssgrid to activity filter builder
AaronPlave Nov 12, 2024
3f0cae1
Bring back resource editing in old form for now
AaronPlave Nov 12, 2024
cab3815
Remove all layer fixes
AaronPlave Nov 12, 2024
23ac089
Style fix
AaronPlave Nov 12, 2024
650525f
Refactor
AaronPlave Nov 12, 2024
a15739c
Show an indication dot when an activity layer has active filters
AaronPlave Nov 12, 2024
3ed8826
Show resulting type and instance counts
AaronPlave Nov 12, 2024
3c0a6a8
Greater/less than support
AaronPlave Nov 12, 2024
b657b24
Remove log
AaronPlave Nov 12, 2024
1f2d615
use > and <
AaronPlave Nov 12, 2024
5896f10
Reactivity fix
AaronPlave Nov 12, 2024
91d5d54
Support boolean comparison
AaronPlave Nov 12, 2024
6ac5399
Input filtering
AaronPlave Nov 21, 2024
6c548ca
Bug fix
AaronPlave Nov 21, 2024
d7a961e
Support for min col and row css grid sizing
AaronPlave Nov 21, 2024
111d808
Add derived subsystem tags store. Fix subsystem tags filtering.
AaronPlave Nov 21, 2024
cd183c0
Tooltip tweaks
AaronPlave Nov 21, 2024
949689a
Fixes
AaronPlave Nov 21, 2024
c5805a3
Scheduling goal id filtering WIP support
AaronPlave Nov 21, 2024
18a4c90
Manual type selection menu positioning fix
AaronPlave Nov 21, 2024
4d24008
Filter parameter possibilities by resulting types if any. List all re…
AaronPlave Nov 22, 2024
839d2cb
Tweak SearchableDropdown to be more like a dropdown
AaronPlave Nov 22, 2024
8738671
Popper positioning workaround when inside css transformed parent. Use…
AaronPlave Nov 22, 2024
933a3a6
Fixes and refactoring
AaronPlave Nov 25, 2024
0a8c461
Fixes
AaronPlave Nov 26, 2024
1e1e5f2
Support within and not within
AaronPlave Nov 26, 2024
bfe0d7b
Apply subfilters to resulting types
AaronPlave Nov 30, 2024
dd3fa2e
Type fixes
AaronPlave Nov 30, 2024
2b5999c
Type fixes
AaronPlave Nov 30, 2024
ce3229c
Fixes and refactoring
AaronPlave Dec 2, 2024
31d4342
Bug fix for confirm modal when adding activities to timeline
AaronPlave Dec 3, 2024
4085ab6
Type fix
AaronPlave Dec 5, 2024
ac87fcd
Swap x-range icon
AaronPlave Dec 17, 2024
eba5450
Add left slot to MenuHeader
AaronPlave Dec 17, 2024
640ef76
Refactor SearchableDropdown to allow for multiple options if requested
AaronPlave Dec 17, 2024
13092c6
Style and functionality updates for all layers
AaronPlave Dec 17, 2024
96581d9
Bug fixes
AaronPlave Dec 17, 2024
7b954e1
Bug fixes
AaronPlave Dec 17, 2024
4d97f7b
Use resource layer name as override on SearchableDropdown selected op…
AaronPlave Dec 17, 2024
1e05be9
Show units for duration, int, and real parameters. Filter window drag…
AaronPlave Dec 17, 2024
ce208e7
Show all activities when no filters exist on layer. Bug fix.
AaronPlave Dec 17, 2024
5bd1530
Virtualization of SearchableDropdown. Fixes.
AaronPlave Dec 18, 2024
eeba7b1
View migration to v2
AaronPlave Dec 19, 2024
4f2ac4f
Prevent highlight on drag
AaronPlave Dec 19, 2024
b939ec3
Improve auto width sizing of SearchableDropdown
AaronPlave Dec 19, 2024
9ed8e65
Fixes
AaronPlave Dec 20, 2024
c46718c
Type fix
AaronPlave Dec 20, 2024
33c39bc
Type fixes
AaronPlave Dec 20, 2024
3ea7ca8
Type fix
AaronPlave Dec 20, 2024
85815f8
Tests
AaronPlave Dec 20, 2024
e3a1e39
Remove unused code
AaronPlave Dec 20, 2024
e196337
Type fixes
AaronPlave Dec 20, 2024
ab5576e
Tests. Rename field Tag -> Tags. Remove unused is_one_of and is_not_o…
AaronPlave Dec 20, 2024
781b78f
Fix
AaronPlave Dec 20, 2024
027b8b3
Test fix
AaronPlave Dec 20, 2024
f9787ed
Unit test fixes
AaronPlave Dec 23, 2024
702b9b6
Tweak
AaronPlave Dec 23, 2024
c7fd1f5
Aria labels
AaronPlave Dec 23, 2024
b0f93ff
Dispatch show event
AaronPlave Dec 23, 2024
10db2c1
Aria fixes
AaronPlave Dec 23, 2024
5fd5f49
Basic test for DynamicFilter
AaronPlave Dec 23, 2024
c609e0e
Remove log
AaronPlave Dec 23, 2024
8a44eb6
Remove .only
AaronPlave Dec 23, 2024
753248c
Fixes
AaronPlave Dec 30, 2024
fac7ae8
e2e tests and fixes
AaronPlave Dec 30, 2024
cb90b1e
Remove pause in e2e test
AaronPlave Dec 30, 2024
48813fd
Test fix
AaronPlave Dec 31, 2024
71af95f
Test fixes
AaronPlave Dec 31, 2024
e46e8bd
Fixes
AaronPlave Dec 31, 2024
5eb918e
Remove logs
AaronPlave Dec 31, 2024
b7fbd44
Add tooltip
AaronPlave Jan 2, 2025
a0fb1d8
Use Activity Layer instead of All Activities as default activity laye…
AaronPlave Jan 6, 2025
11e2d90
Change global filters to other filters
AaronPlave Jan 6, 2025
4658bcf
Turn off native autosuggest in various inputs. Add string input for t…
AaronPlave Jan 6, 2025
f8bea69
Fix within input values
AaronPlave Jan 6, 2025
dd79f3c
Filtering bug fixes and refactoring
AaronPlave Jan 6, 2025
c09c288
Resource layer tests
AaronPlave Jan 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 13 additions & 12 deletions e2e-tests/fixtures/Plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@
}

async fillActivityPresetName(presetName: string) {
await this.panelActivityForm.getByRole('button', { name: 'Set Preset' }).click();
await this.panelActivityForm.getByRole('combobox', { name: 'None' }).click();

Check failure on line 250 in e2e-tests/fixtures/Plan.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Error: locator.click: Test ended. Call log: - waiting for locator('[data-component-name="ActivityFormPanel"]').getByRole('combobox', { name: 'None' }) at fixtures/Plan.ts:250 248 | 249 | async fillActivityPresetName(presetName: string) { > 250 | await this.panelActivityForm.getByRole('combobox', { name: 'None' }).click(); | ^ 251 | await this.panelActivityForm.locator('.dropdown-header').waitFor({ state: 'attached' }); 252 | await this.panelActivityForm.getByPlaceholder('Enter preset name').click(); 253 | await this.panelActivityForm.getByPlaceholder('Enter preset name').fill(presetName); at Plan.fillActivityPresetName (/home/runner/work/***-ui/***-ui/e2e-tests/fixtures/Plan.ts:250:74) at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:49:14

Check failure on line 250 in e2e-tests/fixtures/Plan.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: locator.click: Target page, context or browser has been closed Call log: - waiting for locator('[data-component-name="ActivityFormPanel"]').getByRole('combobox', { name: 'None' }) at fixtures/Plan.ts:250 248 | 249 | async fillActivityPresetName(presetName: string) { > 250 | await this.panelActivityForm.getByRole('combobox', { name: 'None' }).click(); | ^ 251 | await this.panelActivityForm.locator('.dropdown-header').waitFor({ state: 'attached' }); 252 | await this.panelActivityForm.getByPlaceholder('Enter preset name').click(); 253 | await this.panelActivityForm.getByPlaceholder('Enter preset name').fill(presetName); at Plan.fillActivityPresetName (/home/runner/work/***-ui/***-ui/e2e-tests/fixtures/Plan.ts:250:74) at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:49:14
await this.panelActivityForm.locator('.dropdown-header').waitFor({ state: 'attached' });
await this.panelActivityForm.getByPlaceholder('Enter preset name').click();
await this.panelActivityForm.getByPlaceholder('Enter preset name').fill(presetName);
Expand All @@ -269,7 +269,7 @@
}

async fillSimulationTemplateName(templateName: string) {
await this.panelSimulation.getByRole('button', { name: 'Set Template' }).click();
await this.panelSimulation.locator('div[name="Set Template"]').click();
await this.panelSimulation.locator('.dropdown-header').waitFor({ state: 'attached' });
await this.panelSimulation.getByPlaceholder('Enter template name').click();
await this.panelSimulation.getByPlaceholder('Enter template name').fill(templateName);
Expand Down Expand Up @@ -372,22 +372,23 @@
}

async selectActivityAnchorByIndex(index: number) {
await this.panelActivityForm.getByRole('button', { name: 'Set Anchor' }).click();
const anchorCollapse = this.panelActivityForm.getByRole('group', { name: 'Anchor-collapse' });
await anchorCollapse.getByRole('combobox').click();

await this.panelActivityForm.getByRole('menuitem').nth(index).waitFor({ state: 'attached' });
const anchorMenuName = await this.panelActivityForm.getByRole('menuitem').nth(index)?.innerText();
await this.panelActivityForm.getByRole('menuitem').nth(index).click();
await this.panelActivityForm.getByRole('menuitem').nth(index).waitFor({ state: 'detached' });
await anchorCollapse.getByRole('menuitem').nth(index).waitFor({ state: 'attached' });
const anchorMenuName = await anchorCollapse.getByRole('menuitem').nth(index)?.innerText();
await anchorCollapse.getByRole('menuitem').nth(index).click();
await anchorCollapse.getByRole('menuitem').nth(index).waitFor({ state: 'detached' });

await this.page.waitForFunction(
anchorMenuName => document.querySelector('.anchor-form .selected-display-value')?.innerHTML === anchorMenuName,
anchorMenuName,
);
await expect(this.panelActivityForm.getByRole('textbox', { name: anchorMenuName })).toBeVisible();
await expect(anchorCollapse.getByRole('combobox', { name: anchorMenuName })).toBeVisible();
}

async selectActivityPresetByName(presetName: string) {
await this.panelActivityForm.getByRole('button', { name: 'Set Preset' }).click();
await this.panelActivityForm.locator('div[name="Set Preset"]').click();

await this.panelActivityForm.getByRole('menuitem', { name: presetName }).waitFor({ state: 'attached' });
await this.panelActivityForm.getByRole('menuitem', { name: presetName }).click();
Expand All @@ -413,11 +414,11 @@
document.querySelector('.activity-preset-input-container .selected-display-value')?.innerHTML === presetName,
presetName,
);
await expect(this.panelActivityForm.getByRole('textbox', { name: presetName })).toBeVisible();
await expect(this.panelActivityForm.getByRole('combobox', { name: presetName })).toBeVisible();
}

async selectSimulationTemplateByName(templateName: string) {
await this.panelSimulation.getByRole('button', { name: 'Set Template' }).click();
await this.panelSimulation.locator('div[name="Set Template"]').click();

await this.panelSimulation.getByRole('menuitem', { name: templateName }).waitFor({ state: 'attached' });
await this.panelSimulation.getByRole('menuitem', { name: templateName }).click();
Expand All @@ -444,7 +445,7 @@
templateName,
templateName,
);
await expect(this.panelSimulation.getByRole('textbox', { name: templateName })).toBeVisible();
await expect(this.panelSimulation.getByRole('combobox', { name: templateName })).toBeVisible();
}

async showConstraintsLayout() {
Expand Down
2 changes: 1 addition & 1 deletion e2e-tests/tests/plan-activities.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
() => document.querySelector('.anchor-form .selected-display-value')?.innerHTML === 'To Plan',
);

await expect(plan.panelActivityForm.getByRole('textbox', { name: 'To Plan' })).toBeVisible();
await expect(plan.panelActivityForm.getByRole('combobox', { name: 'To Plan' })).toBeVisible();

Check failure on line 72 in e2e-tests/tests/plan-activities.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activities.test.ts:51:3 › Plan Activities › Deleting an activity directive with another directive anchored to it should and selecting re-anchor to plan should re-anchor to plan

2) [e2e tests] › tests/plan-activities.test.ts:51:3 › Plan Activities › Deleting an activity directive with another directive anchored to it should and selecting re-anchor to plan should re-anchor to plan Error: Timed out 5000ms waiting for expect(locator).toBeVisible() Locator: locator('[data-component-name="ActivityFormPanel"]').getByRole('combobox', { name: 'To Plan' }) Expected: visible Received: <element(s) not found> Call log: - expect.toBeVisible with timeout 5000ms - waiting for locator('[data-component-name="ActivityFormPanel"]').getByRole('combobox', { name: 'To Plan' }) 70 | ); 71 | > 72 | await expect(plan.panelActivityForm.getByRole('combobox', { name: 'To Plan' })).toBeVisible(); | ^ 73 | }); 74 | 75 | test('Deleting multiple activity directives but only 1 has a remaining anchored dependent should prompt for just the one with a remaining dependent', async () => { at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activities.test.ts:72:85
});

test('Deleting multiple activity directives but only 1 has a remaining anchored dependent should prompt for just the one with a remaining dependent', async () => {
Expand Down
10 changes: 5 additions & 5 deletions e2e-tests/tests/plan-activity-presets.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import test, { expect, type BrowserContext, type Page } from '@playwright/test';

Check failure on line 1 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Error: tracing.startChunk: Tracing is already stopping

Check failure on line 1 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Error: end of central directory record signature not found
import { Constraints } from '../fixtures/Constraints.js';
import { Models } from '../fixtures/Models.js';
import { Plan } from '../fixtures/Plan.js';
Expand All @@ -15,7 +15,7 @@
let schedulingConditions: SchedulingConditions;
let schedulingGoals: SchedulingGoals;

test.beforeAll(async ({ baseURL, browser }) => {

Check failure on line 18 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values "beforeAll" hook timeout of 30000ms exceeded. 16 | let schedulingGoals: SchedulingGoals; 17 | > 18 | test.beforeAll(async ({ baseURL, browser }) => { | ^ 19 | context = await browser.newContext(); 20 | page = await context.newPage(); 21 | at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:18:6

Check failure on line 18 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values "beforeAll" hook timeout of 30000ms exceeded. 16 | let schedulingGoals: SchedulingGoals; 17 | > 18 | test.beforeAll(async ({ baseURL, browser }) => { | ^ 19 | context = await browser.newContext(); 20 | page = await context.newPage(); 21 | at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:18:6

Check failure on line 18 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── "beforeAll" hook timeout of 30000ms exceeded. 16 | let schedulingGoals: SchedulingGoals; 17 | > 18 | test.beforeAll(async ({ baseURL, browser }) => { | ^ 19 | context = await browser.newContext(); 20 | page = await context.newPage(); 21 | at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:18:6

Check failure on line 18 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── "beforeAll" hook timeout of 30000ms exceeded. 16 | let schedulingGoals: SchedulingGoals; 17 | > 18 | test.beforeAll(async ({ baseURL, browser }) => { | ^ 19 | context = await browser.newContext(); 20 | page = await context.newPage(); 21 | at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:18:6

Check failure on line 18 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── "beforeAll" hook timeout of 30000ms exceeded. 16 | let schedulingGoals: SchedulingGoals; 17 | > 18 | test.beforeAll(async ({ baseURL, browser }) => { | ^ 19 | context = await browser.newContext(); 20 | page = await context.newPage(); 21 | at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:18:6

Check failure on line 18 in e2e-tests/tests/plan-activity-presets.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values

1) [e2e tests] › tests/plan-activity-presets.test.ts:73:3 › Plan Activity Presets › Setting a preset to a directive should update the parameter values Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── "beforeAll" hook timeout of 30000ms exceeded. 16 | let schedulingGoals: SchedulingGoals; 17 | > 18 | test.beforeAll(async ({ baseURL, browser }) => { | ^ 19 | context = await browser.newContext(); 20 | page = await context.newPage(); 21 | at /home/runner/work/***-ui/***-ui/e2e-tests/tests/plan-activity-presets.test.ts:18:6
context = await browser.newContext();
page = await context.newPage();

Expand Down Expand Up @@ -57,7 +57,7 @@

await plan.selectActivityPresetByName('None');

await expect(plan.panelActivityForm.getByRole('textbox', { name: 'None' })).toBeVisible();
await expect(plan.panelActivityForm.getByRole('combobox', { name: 'None' })).toBeVisible();
});

test.afterAll(async () => {
Expand All @@ -72,18 +72,18 @@
test.describe.serial('Plan Activity Presets', () => {
test(`Setting a preset to a directive should update the parameter values`, async () => {
await plan.selectActivityPresetByName('Preset 1');
await expect(page.getByRole('textbox', { name: 'Preset 1' })).toBeVisible();
await expect(page.getByRole('combobox', { name: 'Preset 1' })).toBeVisible();
});

test(`Removing an activity preset from a directive should reflect that it is no longer present`, async () => {
await plan.selectActivityPresetByName('None');
await expect(page.getByRole('textbox', { name: 'None' })).toBeVisible();
await expect(page.getByRole('combobox', { name: 'None' })).toBeVisible();
});

test('Deleting an activity preset should remove it from the list of presets', async () => {
await plan.selectActivityPresetByName('Preset 1');

await page.getByRole('button', { name: 'Set Preset' }).click();
await page.getByRole('combobox', { name: 'Preset 1' }).click();

await page.getByRole('button', { name: 'Delete preset' }).waitFor({ state: 'attached' });
await page.getByRole('button', { name: 'Delete preset' }).click();
Expand All @@ -96,6 +96,6 @@
() => document.querySelector('.activity-preset-input-container .selected-display-value')?.innerHTML === 'None',
);

await expect(page.getByRole('textbox', { name: 'None' })).toBeVisible();
await expect(page.getByRole('combobox', { name: 'None' })).toBeVisible();
});
});
10 changes: 5 additions & 5 deletions e2e-tests/tests/plan-simulation-templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ test.beforeAll(async ({ baseURL, browser }) => {

await plan.selectSimulationTemplateByName('None');

expect(page.getByRole('textbox', { name: 'None' })).toBeVisible();
expect(page.getByRole('combobox', { name: 'None' })).toBeVisible();
});

test.afterAll(async () => {
Expand All @@ -75,19 +75,19 @@ test.describe.serial('Plan Simulation Templates', async () => {
test(`Setting a simulation template to a simulation should update the parameter values`, async () => {
await plan.selectSimulationTemplateByName('Template 1');

expect(plan.panelSimulation.getByRole('textbox', { name: 'Template 1' })).toBeVisible();
expect(plan.panelSimulation.getByRole('combobox', { name: 'Template 1' })).toBeVisible();
});

test(`Removing an simulation template from a simulation should reflect that it is no longer present`, async () => {
await plan.selectSimulationTemplateByName('None');

expect(page.getByRole('textbox', { name: 'None' })).toBeVisible();
expect(page.getByRole('combobox', { name: 'None' })).toBeVisible();
});

test('Deleting an simulation template should remove it from the list of templates', async () => {
await plan.selectSimulationTemplateByName('Template 1');

await page.getByRole('button', { name: 'Set Template' }).click();
await plan.panelSimulation.locator('div[name="Set Template"]').click();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's no longer possible to get this by role?


await page.getByRole('button', { name: 'Delete Template' }).waitFor({ state: 'attached' });
await page.getByRole('button', { name: 'Delete Template' }).click();
Expand All @@ -98,6 +98,6 @@ test.describe.serial('Plan Simulation Templates', async () => {

await page.waitForFunction(() => document.querySelector('.selected-display-value')?.innerHTML === 'None');

expect(page.getByRole('textbox', { name: 'None' })).toBeVisible();
expect(page.getByRole('combobox', { name: 'None' })).toBeVisible();
});
});
176 changes: 160 additions & 16 deletions e2e-tests/tests/timeline-view-editing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ test.describe.serial('Timeline View Editing', () => {
test('Add an activity to the parent plan', async () => {
await plan.showPanel(PanelNames.TIMELINE_ITEMS);
await plan.addActivity('PickBanana');
await plan.addActivity('PeelBanana');
});

test('Change the start time of the activity', async () => {
Expand Down Expand Up @@ -105,26 +106,121 @@ test.describe.serial('Timeline View Editing', () => {
// Look for back button indicating that the row editor is active
expect(page.locator('.section-back-button ').first()).toBeDefined();

const existingLayerCount = await page.locator('.timeline-layer').count();

// Give the row a name
await page.locator('input[name="name"]').first().fill(rowName);
await page.locator('input[name="name"]').first().blur();
});

test('Add an activity layer', async () => {
const activityLayerEditor = page.getByLabel('Activity Layer-editor');
const existingLayerCount = await activityLayerEditor.locator('.timeline-layer-editor').count();

// Add a layer
await page.getByRole('button', { name: 'New Layer' }).click();
const newLayerCount = await page.locator('.timeline-layer').count();
// Add an activity layer
await activityLayerEditor.getByRole('button', { name: 'New Activity Layer' }).click();
const newLayerCount = await activityLayerEditor.locator('.timeline-layer-editor').count();
expect(newLayerCount - existingLayerCount).toEqual(1);

// Expect an activity layer to be created by default
expect(await page.locator('select[name="chartType"]').last().inputValue()).toBe('activity');
// Expect the activity layer to include all activities
expect(await activityLayerEditor.locator('.timeline-layer-editor').first()).toHaveText('Activity Layer');
});

test('Edit an activity layer', async () => {
const activityLayerEditor = page.getByLabel('Activity Layer-editor');

// Open the activity filter builder
await activityLayerEditor
.locator('.timeline-layer-editor')
.first()
.getByLabel('activity-filter-builder-trigger')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little hesitant about using the label as a way to select the button in the test. Anyway this could be getting the button by text or role?

.click();

// Expect that the modal is present
const modal = activityLayerEditor.getByLabel('activity-filter-builder');
expect(modal).toBeDefined();

// Expect that layer name is showing in the name input
expect(modal.locator('input[name="layer-name"]')).toHaveValue('Activity Layer');

// Expect that the resulting types list is not empty
const resultingTypesList = modal.locator('.resulting-types-list');
const allActivityTypesCount = await resultingTypesList.locator('.activity-type-result').count();
expect(allActivityTypesCount).toBeGreaterThan(0);

// Expect that manually selecting types cause the types to appear in the resulting types list
await modal.locator("input[name='manual-types-filter-input']").click();
expect(await modal.locator('.manual-types-menu').first()).toBeDefined();
await modal.getByRole('menuitem', { name: 'ChangeProducer' }).click();
await modal.getByRole('menuitem', { name: 'ControllableDurationActivity' }).click();
await page.keyboard.press('Escape');

expect(await resultingTypesList.getByText('ChangeProducer')).toBeDefined();
expect(await resultingTypesList.getByText('ControllableDurationActivity')).toBeDefined();

// Expect that dynamic types can be added
await modal.getByLabel('dynamic-types').getByRole('button', { name: 'Add Filter' }).click();
expect(await modal.getByLabel('dynamic-types').getByRole('listitem').count()).toBe(1);
await modal.getByLabel('dynamic-types').getByRole('listitem').locator("input[name='filter-value']").fill('banana');
expect(await resultingTypesList.locator('.activity-type-result').count()).toEqual(11);

// Expect that other filters can be added
await modal.getByLabel('other-filters').getByRole('button', { name: 'Add Filter' }).click();
expect(await modal.getByLabel('other-filters').getByRole('listitem').count()).toBe(1);
// Select parameter field
await modal.getByLabel('other-filters').locator("select[aria-label='field']").selectOption('Parameter');
// Select specific parameter
await modal.getByLabel('other-filters').getByText('Select Parameter').click();
await modal.getByLabel('other-filters').getByText('quantity (int)').click();
// Select operator
await modal.getByLabel('other-filters').locator("select[aria-label='operator']").selectOption('equals');
// Fill filter value input
await modal.getByLabel('other-filters').getByRole('listitem').locator("input[name='filter-value']").fill('10');
// Ensure that only one instance (PickBanana) is listed
expect(await modal.getByText('1 instance')).toBeDefined();

// Expect that type subfilters can be added
const activityResult = resultingTypesList.getByRole('listitem', { name: 'activity-type-result-PickBanana' });
await activityResult.getByRole('button', { name: 'Add Filter' }).click();
expect(await activityResult.getByRole('listitem').count()).toBe(1);
// Select name field
await activityResult.locator("select[aria-label='field']").selectOption('Name');
// Select operator
await activityResult.locator("select[aria-label='operator']").selectOption('includes');
// Fill filter value input
await activityResult.getByRole('listitem').locator("input[name='filter-value']").fill('foo');
// Ensure that only one instance (PickBanana) is listed
expect(await modal.getByText('0 instances')).toBeDefined();

// Expect that type subfilters can be removed
await activityResult.getByRole('button', { name: 'Remove filter' }).click();
expect(await modal.getByText('1 instance')).toBeDefined();

// Expect that other filters can be removed
await modal.getByLabel('other-filters').getByRole('button', { name: 'Remove filter' }).click();
expect(await modal.getByText('2 instances')).toBeDefined();

// Expect that dynamic types can be removed
await modal.getByLabel('dynamic-types').getByRole('button', { name: 'Remove filter' }).click();
expect(await resultingTypesList.locator('.activity-type-result').count()).toEqual(2);

// Expect that manual types can be cleared
await modal.locator("input[name='manual-types-filter-input']").click();
await modal.getByRole('menuitem', { name: 'ChangeProducer' }).click();
await page.keyboard.press('Escape');
await modal.getByRole('button', { name: 'Remove Types' }).click();
expect(await resultingTypesList.locator('.activity-type-result').count()).toEqual(allActivityTypesCount);

// Expect the filter list to open
await page.getByPlaceholder('Search').last().click();
await expect(page.locator('.menu-slot > .header')).toBeDefined();
// Give the layer a new name
await modal.locator('input[name="layer-name"]').fill('Foo');

// Add all activities
await page.locator('button', { hasText: /Select [0-9]* activit/ }).click();
// Close the modal
await modal.getByRole('button', { name: 'close' }).click();

// Expect name to match given name
expect(await activityLayerEditor.locator('.timeline-layer-editor').first()).toHaveText('Foo');
});

test('Change activity layer settings', async () => {
const activityLayerEditor = await page.getByLabel('Activity Layer-editor');

// Expect to not see an activity tree group in this row
expect(await page.locator('.timeline-row-wrapper', { hasText: rowName }).locator('.activity-tree').count()).toBe(0);
Expand All @@ -141,9 +237,57 @@ test.describe.serial('Timeline View Editing', () => {
).toBe(1);

// Delete an activity layer
await page.getByRole('button', { name: 'Layer Settings' }).last().click();
await page.getByText('Delete Layer').click();
const finalLayerCount = await page.locator('.timeline-layer').count();
expect(finalLayerCount - newLayerCount).toEqual(-1);
await activityLayerEditor.locator('.timeline-layer-editor').first().getByRole('button', { name: 'Delete' }).click();
expect(await activityLayerEditor.locator('.timeline-layer-editor').count()).toBe(0);
});

test('Add a resource layer', async () => {
const resourceLayerEditor = await page.getByLabel('Resource Layer-editor');
const yAxisEditor = await page.getByLabel('Y Axis-editor');
const existingLayerCount = await resourceLayerEditor.locator('.timeline-layer-editor').count();
const existingYAxesCount = await yAxisEditor.locator('.timeline-y-axis').count();

// Expect no y-axis label to exist for the row in the timeline
expect(
await page.locator('.timeline-row-wrapper', { hasText: rowName }).locator('.row-header-y-axis-label').count(),
).toBe(0);

// Add a resource layer
await resourceLayerEditor.getByRole('button', { name: 'New Resource Layer' }).click();
const newLayerCount = await resourceLayerEditor.locator('.timeline-layer-editor').count();
expect(newLayerCount - existingLayerCount).toEqual(1);

// Expect a y-axis to have been automatically created
const newYAxisCount = await yAxisEditor.locator('.timeline-y-axis').count();
expect(newYAxisCount - existingYAxesCount).toEqual(1);

await page.pause();

// Select a resource
await resourceLayerEditor.getByRole('combobox').click();
await resourceLayerEditor.getByRole('menuitem', { name: '/peel' }).waitFor({ state: 'attached' });
await resourceLayerEditor.getByRole('menuitem', { name: '/peel' }).click();
await resourceLayerEditor.getByRole('menuitem', { name: '/peel' }).waitFor({ state: 'detached' });

// Run simulation
await plan.showPanel(PanelNames.SIMULATION, true);
await plan.runSimulation();

// Expect the resource to have a y-axis label in the timline
expect(
await page.locator('.timeline-row-wrapper', { hasText: rowName }).locator('.row-header-y-axis-label').count(),
).toBe(1);

// Duplicate a resource layer
await resourceLayerEditor
.locator('.timeline-layer-editor')
.first()
.getByRole('button', { name: 'Duplicate' })
.click();
expect(await resourceLayerEditor.locator('.timeline-layer-editor').count()).toBe(2);

// Delete a resource layer
await resourceLayerEditor.locator('.timeline-layer-editor').first().getByRole('button', { name: 'Delete' }).click();
expect(await resourceLayerEditor.locator('.timeline-layer-editor').count()).toBe(1);
});
});
Loading
Loading