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

Merged
merged 108 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
059e43c
WIP
AaronPlave Oct 21, 2024
2f2aae2
Fixes for spans
AaronPlave Oct 30, 2024
3b160fb
Componentize editor section headers. Remove unused styles.
AaronPlave Oct 31, 2024
cb35339
Refactoring, fixing, improving timeline editor
AaronPlave Oct 31, 2024
2d5670e
Add icon
AaronPlave Nov 5, 2024
9fa3a7e
Add svelte dragging library
AaronPlave Nov 5, 2024
93bbb42
Style refactor
AaronPlave Nov 5, 2024
70ec0fd
Make menu items tab focusable
AaronPlave Nov 5, 2024
1eb7d32
Style tweak
AaronPlave Nov 5, 2024
003ee3f
WIP activity layer filtering
AaronPlave Nov 5, 2024
54181b1
style refactor
AaronPlave Nov 5, 2024
159a85d
Get default activity arguments during plan load
AaronPlave Nov 12, 2024
77c6880
Potentially remove unused input workaround
AaronPlave Nov 12, 2024
dcd2b01
WIP filtering
AaronPlave Nov 12, 2024
eadd04b
Basic manual type selection list filtering
AaronPlave Nov 12, 2024
77c826f
add cssgrid to activity filter builder
AaronPlave Nov 12, 2024
171af59
Bring back resource editing in old form for now
AaronPlave Nov 12, 2024
2445ac7
Remove all layer fixes
AaronPlave Nov 12, 2024
57bb8ae
Style fix
AaronPlave Nov 12, 2024
f2fff0f
Refactor
AaronPlave Nov 12, 2024
2687eb9
Show an indication dot when an activity layer has active filters
AaronPlave Nov 12, 2024
011b4c9
Show resulting type and instance counts
AaronPlave Nov 12, 2024
0f44251
Greater/less than support
AaronPlave Nov 12, 2024
7d1c57b
Remove log
AaronPlave Nov 12, 2024
1daa49f
use > and <
AaronPlave Nov 12, 2024
05476c7
Reactivity fix
AaronPlave Nov 12, 2024
524def4
Support boolean comparison
AaronPlave Nov 12, 2024
db7e950
Input filtering
AaronPlave Nov 21, 2024
673d006
Bug fix
AaronPlave Nov 21, 2024
f433e7a
Support for min col and row css grid sizing
AaronPlave Nov 21, 2024
f1de8c7
Add derived subsystem tags store. Fix subsystem tags filtering.
AaronPlave Nov 21, 2024
9cb4527
Tooltip tweaks
AaronPlave Nov 21, 2024
4da995d
Fixes
AaronPlave Nov 21, 2024
e3017f3
Scheduling goal id filtering WIP support
AaronPlave Nov 21, 2024
f0aa1f8
Manual type selection menu positioning fix
AaronPlave Nov 21, 2024
37ff973
Filter parameter possibilities by resulting types if any. List all re…
AaronPlave Nov 22, 2024
38a0d26
Tweak SearchableDropdown to be more like a dropdown
AaronPlave Nov 22, 2024
5f4930f
Popper positioning workaround when inside css transformed parent. Use…
AaronPlave Nov 22, 2024
aa2cdc7
Fixes and refactoring
AaronPlave Nov 25, 2024
69f50fb
Fixes
AaronPlave Nov 26, 2024
9d53c0c
Support within and not within
AaronPlave Nov 26, 2024
4e37234
Apply subfilters to resulting types
AaronPlave Nov 30, 2024
f746c1d
Type fixes
AaronPlave Nov 30, 2024
c7f8cbb
Type fixes
AaronPlave Nov 30, 2024
f14c8c5
Fixes and refactoring
AaronPlave Dec 2, 2024
05661a8
Bug fix for confirm modal when adding activities to timeline
AaronPlave Dec 3, 2024
98fd3e3
Type fix
AaronPlave Dec 5, 2024
155cf02
Swap x-range icon
AaronPlave Dec 17, 2024
c0351cc
Add left slot to MenuHeader
AaronPlave Dec 17, 2024
c7dc812
Refactor SearchableDropdown to allow for multiple options if requested
AaronPlave Dec 17, 2024
53531ae
Style and functionality updates for all layers
AaronPlave Dec 17, 2024
466cd8a
Bug fixes
AaronPlave Dec 17, 2024
b84a6d7
Bug fixes
AaronPlave Dec 17, 2024
d800fc4
Use resource layer name as override on SearchableDropdown selected op…
AaronPlave Dec 17, 2024
2d50346
Show units for duration, int, and real parameters. Filter window drag…
AaronPlave Dec 17, 2024
6d24704
Show all activities when no filters exist on layer. Bug fix.
AaronPlave Dec 17, 2024
b6128a1
Virtualization of SearchableDropdown. Fixes.
AaronPlave Dec 18, 2024
18fdadf
View migration to v2
AaronPlave Dec 19, 2024
67355d0
Prevent highlight on drag
AaronPlave Dec 19, 2024
f737b96
Improve auto width sizing of SearchableDropdown
AaronPlave Dec 19, 2024
d93631c
Fixes
AaronPlave Dec 20, 2024
ec17da0
Type fix
AaronPlave Dec 20, 2024
033e250
Type fixes
AaronPlave Dec 20, 2024
6dbc718
Type fix
AaronPlave Dec 20, 2024
0f5f5ac
Tests
AaronPlave Dec 20, 2024
ad54b7d
Remove unused code
AaronPlave Dec 20, 2024
b29da98
Type fixes
AaronPlave Dec 20, 2024
13b1d1c
Tests. Rename field Tag -> Tags. Remove unused is_one_of and is_not_o…
AaronPlave Dec 20, 2024
7b242fe
Fix
AaronPlave Dec 20, 2024
9e3acea
Test fix
AaronPlave Dec 20, 2024
8c631b9
Unit test fixes
AaronPlave Dec 23, 2024
e80a7e9
Tweak
AaronPlave Dec 23, 2024
50e488c
Aria labels
AaronPlave Dec 23, 2024
e1d9d1b
Dispatch show event
AaronPlave Dec 23, 2024
1f17984
Aria fixes
AaronPlave Dec 23, 2024
f5e15bf
Basic test for DynamicFilter
AaronPlave Dec 23, 2024
9719540
Remove log
AaronPlave Dec 23, 2024
5b0d1a7
Remove .only
AaronPlave Dec 23, 2024
9ed421e
Fixes
AaronPlave Dec 30, 2024
3c9de36
e2e tests and fixes
AaronPlave Dec 30, 2024
a618a31
Remove pause in e2e test
AaronPlave Dec 30, 2024
689df1e
Test fix
AaronPlave Dec 31, 2024
32b5f84
Test fixes
AaronPlave Dec 31, 2024
cff40ec
Fixes
AaronPlave Dec 31, 2024
67d870e
Remove logs
AaronPlave Dec 31, 2024
98b5155
Add tooltip
AaronPlave Jan 2, 2025
538657c
Use Activity Layer instead of All Activities as default activity laye…
AaronPlave Jan 6, 2025
d10852f
Change global filters to other filters
AaronPlave Jan 6, 2025
d3161f4
Turn off native autosuggest in various inputs. Add string input for t…
AaronPlave Jan 6, 2025
2312e97
Fix within input values
AaronPlave Jan 6, 2025
f0bb09b
Filtering bug fixes and refactoring
AaronPlave Jan 6, 2025
2378295
Resource layer tests
AaronPlave Jan 6, 2025
f221972
Remove unused async
AaronPlave Jan 15, 2025
7b8578f
Remove comment
AaronPlave Jan 15, 2025
6e0f669
Remove comment
AaronPlave Jan 15, 2025
3edebf8
Tweaks
AaronPlave Jan 15, 2025
79ae261
Rename aria-label
AaronPlave Jan 15, 2025
33a3878
Fix test
AaronPlave Jan 15, 2025
629935f
Move enums to separate file
AaronPlave Jan 15, 2025
c10db80
Remove unused export
AaronPlave Jan 15, 2025
6ab6bc4
Remove unused exports
AaronPlave Jan 15, 2025
c813093
More tests
AaronPlave Jan 15, 2025
30357de
Fix
AaronPlave Jan 15, 2025
0260d96
Test fix
AaronPlave Jan 15, 2025
061f641
Filtering fixes
AaronPlave Jan 15, 2025
9b66060
Remove comment
AaronPlave Jan 17, 2025
50a15e0
Remove comment
AaronPlave Jan 17, 2025
04bf0d6
Refactor
AaronPlave Jan 17, 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 @@ -249,7 +249,7 @@ export class Plan {
}

async fillActivityPresetName(presetName: string) {
await this.panelActivityForm.getByRole('button', { name: 'Set Preset' }).click();
await this.panelActivityForm.getByRole('combobox', { name: 'None' }).click();
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 @@ -271,7 +271,7 @@ export class Plan {
}

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 @@ -374,22 +374,23 @@ export class Plan {
}

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 @@ -415,11 +416,11 @@ export class Plan {
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 @@ -446,7 +447,7 @@ export class Plan {
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 @@ test.describe.serial('Plan Activities', () => {
() => 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();
});

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
Expand Up @@ -57,7 +57,7 @@ test.beforeAll(async ({ baseURL, browser }) => {

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.afterAll(async () => {
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 @@ test.describe.serial('Plan Activity Presets', () => {
() => 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 page.getByRole('combobox', { name: 'Template 1' }).click();

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();
});
});
174 changes: 158 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('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 @@
// 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('Toggle activity filter builder modal')
.click();

// Expect that the modal is present
const modal = activityLayerEditor.getByRole('dialog');
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,55 @@
).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);

// 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);

Check failure on line 277 in e2e-tests/tests/timeline-view-editing.test.ts

View workflow job for this annotation

GitHub Actions / e2e-test

[e2e tests] › tests/timeline-view-editing.test.ts:244:3 › Timeline View Editing › Add a resource layer

2) [e2e tests] › tests/timeline-view-editing.test.ts:244:3 › Timeline View Editing › Add a resource layer Error: expect(received).toBe(expected) // Object.is equality Expected: 1 Received: 0 275 | expect( 276 | await page.locator('.timeline-row-wrapper', { hasText: rowName }).locator('.row-header-y-axis-label').count(), > 277 | ).toBe(1); | ^ 278 | 279 | // Duplicate a resource layer 280 | await resourceLayerEditor at /home/runner/work/***-ui/***-ui/e2e-tests/tests/timeline-view-editing.test.ts:277:7

// 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