Skip to content

Commit 69e4b94

Browse files
authored
Merge branch 'master' into feature-imagery-disparty-map
2 parents 50d9b64 + ebaadfa commit 69e4b94

13 files changed

Lines changed: 400 additions & 438 deletions

File tree

.eslintrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const config = {
4444
'vue/no-deprecated-events-api': 'warn',
4545
'vue/no-v-for-template-key': 'off',
4646
'vue/no-v-for-template-key-on-child': 'error',
47+
'vue/require-default-prop': 'off',
4748
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
4849
'prettier/prettier': 'error',
4950
'you-dont-need-lodash-underscore/omit': 'off',
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*****************************************************************************
2+
* Open MCT, Copyright (c) 2014-2024, United States Government
3+
* as represented by the Administrator of the National Aeronautics and Space
4+
* Administration. All rights reserved.
5+
*
6+
* Open MCT is licensed under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
* http://www.apache.org/licenses/LICENSE-2.0.
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
* License for the specific language governing permissions and limitations
15+
* under the License.
16+
*
17+
* Open MCT includes source code licensed under additional open source
18+
* licenses. See the Open Source Licenses file (LICENSES.md) included with
19+
* this source code distribution or the Licensing information page available
20+
* at runtime from the About dialog for additional information.
21+
*****************************************************************************/
22+
import fs from 'fs';
23+
24+
import { createDomainObjectWithDefaults, createPlanFromJSON } from '../../../appActions.js';
25+
import { setBoundsToSpanAllActivities } from '../../../helper/planningUtils.js';
26+
import { expect, test } from '../../../pluginFixtures.js';
27+
28+
const testPlan = JSON.parse(
29+
fs.readFileSync(
30+
new URL('../../../test-data/examplePlans/ExamplePlan_Small1.json', import.meta.url)
31+
)
32+
);
33+
34+
test.describe('Resizing the window', () => {
35+
let activities;
36+
let activitiesCount;
37+
let timeAxisScale;
38+
let resizeHandle;
39+
40+
test.beforeEach(async ({ page }) => {
41+
await page.goto('./', { waitUntil: 'domcontentloaded' });
42+
43+
activities = page.locator('.c-plan__activity.activity-bounds');
44+
activitiesCount = Object.values(testPlan).flat().length;
45+
timeAxisScale = page.locator('.c-swimlane__time-axis').locator('.c-swimlane__lane-object');
46+
resizeHandle = page.getByLabel('Resize Inspect Pane');
47+
});
48+
49+
test('will scale activities properly in the Plan View', async ({ page }) => {
50+
const plan = await createPlanFromJSON(page, {
51+
json: testPlan
52+
});
53+
await setBoundsToSpanAllActivities(page, testPlan, plan.url);
54+
55+
await test.step('all activities are in viewport', async () => {
56+
await expect(activities).toHaveCount(activitiesCount);
57+
for (const activity of await activities.all()) {
58+
await expect(activity).toBeInViewport();
59+
}
60+
});
61+
62+
await test.step('shrink viewport and all activities should still fit in timespan', async () => {
63+
const { width } = await timeAxisScale.boundingBox();
64+
const { x, y } = await resizeHandle.boundingBox();
65+
66+
await resizeHandle.hover();
67+
await page.mouse.down();
68+
await page.mouse.move(x - width + 15, y);
69+
await page.mouse.up();
70+
71+
await expect(activities).toHaveCount(activitiesCount);
72+
for (const activity of await activities.all()) {
73+
await expect(activity).toBeInViewport();
74+
}
75+
});
76+
});
77+
78+
test('will scale activities properly in the Gantt View', async ({ page }) => {
79+
const ganttChart = await createDomainObjectWithDefaults(page, {
80+
type: 'Gantt Chart'
81+
});
82+
const plan = await createPlanFromJSON(page, {
83+
json: testPlan,
84+
parent: ganttChart.uuid
85+
});
86+
await setBoundsToSpanAllActivities(page, testPlan, plan.url);
87+
88+
await test.step('all activities are in viewport', async () => {
89+
await expect(activities).toHaveCount(activitiesCount);
90+
for (const activity of await activities.all()) {
91+
await expect(activity).toBeInViewport();
92+
}
93+
});
94+
95+
await test.step('shrink viewport and all activities should still fit in timespan', async () => {
96+
const { width } = await timeAxisScale.boundingBox();
97+
const { x, y } = await resizeHandle.boundingBox();
98+
99+
await resizeHandle.hover();
100+
await page.mouse.down();
101+
await page.mouse.move(x - width + 15, y);
102+
await page.mouse.up();
103+
104+
await expect(activities).toHaveCount(activitiesCount);
105+
for (const activity of await activities.all()) {
106+
await expect(activity).toBeInViewport();
107+
}
108+
});
109+
});
110+
111+
test('will scale activities properly in the Time Strip View', async ({ page }) => {
112+
const timeStrip = await createDomainObjectWithDefaults(page, { type: 'Time Strip' });
113+
const plan = await createPlanFromJSON(page, {
114+
json: testPlan,
115+
parent: timeStrip.uuid
116+
});
117+
await setBoundsToSpanAllActivities(page, testPlan, plan.url);
118+
119+
await test.step('all activities are in viewport', async () => {
120+
await expect(activities).toHaveCount(activitiesCount);
121+
for (const activity of await activities.all()) {
122+
await expect(activity).toBeInViewport();
123+
}
124+
});
125+
126+
await test.step('shrink viewport and all activities should still fit in timespan', async () => {
127+
const { width } = await timeAxisScale.boundingBox();
128+
const { x, y } = await resizeHandle.boundingBox();
129+
130+
await resizeHandle.hover();
131+
await page.mouse.down();
132+
await page.mouse.move(x - width + 15, y);
133+
await page.mouse.up();
134+
135+
await expect(activities).toHaveCount(activitiesCount);
136+
for (const activity of await activities.all()) {
137+
await expect(activity).toBeInViewport();
138+
}
139+
});
140+
});
141+
});

e2e/tests/functional/planning/timestrip.e2e.spec.js

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import {
2424
createDomainObjectWithDefaults,
2525
createPlanFromJSON,
2626
navigateToObjectWithFixedTimeBounds,
27+
navigateToObjectWithRealTime,
28+
setEndOffset,
2729
setFixedIndependentTimeConductorBounds,
2830
setFixedTimeMode,
2931
setTimeConductorBounds
@@ -76,39 +78,19 @@ const testPlan = {
7678
};
7779

7880
test.describe('Time Strip', () => {
79-
let timestrip;
80-
let plan;
81+
let timeStrip;
8182

8283
test.beforeEach(async ({ page }) => {
8384
// Goto baseURL
8485
await page.goto('./', { waitUntil: 'domcontentloaded' });
8586

86-
timestrip = await test.step('Create a Time Strip', async () => {
87-
const createdTimeStrip = await createDomainObjectWithDefaults(page, { type: 'Time Strip' });
88-
const objectName = await page.locator('.l-browse-bar__object-name').innerText();
89-
expect(objectName).toBe(createdTimeStrip.name);
90-
91-
return createdTimeStrip;
92-
});
93-
94-
plan = await test.step('Create a Plan and add it to the timestrip', async () => {
95-
const createdPlan = await createPlanFromJSON(page, {
96-
name: 'Test Plan',
97-
json: testPlan
98-
});
99-
100-
await page.goto(timestrip.url);
101-
// Expand the tree to show the plan
102-
await page.getByLabel('Show selected item in tree').click();
103-
await page
104-
.getByLabel(`Navigate to ${createdPlan.name}`)
105-
.dragTo(page.getByLabel('Object View'));
106-
await page.getByLabel('Save').click();
107-
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
108-
109-
return createdPlan;
87+
timeStrip = await createDomainObjectWithDefaults(page, { type: 'Time Strip' });
88+
await createPlanFromJSON(page, {
89+
json: testPlan,
90+
parent: timeStrip.uuid
11091
});
11192
});
93+
11294
test('Create two Time Strips, add a single Plan to both, and verify they can have separate Independent Time Contexts', async ({
11395
page
11496
}) => {
@@ -125,7 +107,7 @@ test.describe('Time Strip', () => {
125107
const endBound = testPlan.TEST_GROUP[testPlan.TEST_GROUP.length - 1].end;
126108

127109
// Switch to fixed time mode with all plan events within the bounds
128-
await navigateToObjectWithFixedTimeBounds(page, timestrip.url, startBound, endBound);
110+
await navigateToObjectWithFixedTimeBounds(page, timeStrip.url, startBound, endBound);
129111

130112
// Verify all events are displayed
131113
const eventCount = await page.locator('.activity-bounds').count();
@@ -150,19 +132,17 @@ test.describe('Time Strip', () => {
150132

151133
await test.step('Can have multiple TimeStrips with the same plan linked and different Independent Time Contexts', async () => {
152134
// Create another Time Strip and verify that it has been created
153-
const createdTimeStrip = await createDomainObjectWithDefaults(page, {
135+
const secondTimeStrip = await createDomainObjectWithDefaults(page, {
154136
type: 'Time Strip',
155137
name: 'Another Time Strip'
156138
});
157139

158-
const objectName = await page.locator('.l-browse-bar__object-name').innerText();
159-
expect(objectName).toBe(createdTimeStrip.name);
160-
161-
// Drag the existing Plan onto the newly created Time Strip, and save.
162-
await page.getByLabel(`Navigate to ${plan.name}`).dragTo(page.getByLabel('Object View'));
163-
await page.getByLabel('Save').click();
164-
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
140+
await createPlanFromJSON(page, {
141+
json: testPlan,
142+
parent: secondTimeStrip.uuid
143+
});
165144

145+
await navigateToObjectWithFixedTimeBounds(page, secondTimeStrip.url);
166146
// All events should be displayed at this point because the
167147
// initial independent context bounds will match the global bounds
168148
expect(await activityBounds.count()).toEqual(5);
@@ -182,7 +162,7 @@ test.describe('Time Strip', () => {
182162
expect(await activityBounds.count()).toEqual(2);
183163

184164
// Switch to the previous Time Strip and verify that only one event is displayed
185-
await page.goto(timestrip.url);
165+
await page.goto(timeStrip.url);
186166
expect(await activityBounds.count()).toEqual(1);
187167
});
188168
});
@@ -230,4 +210,47 @@ test.describe('Time Strip', () => {
230210
await expect(page.getByLabel('Now Marker')).toBeHidden();
231211
});
232212
});
213+
214+
test('Time strip ahead/behind line', async ({ page }) => {
215+
const aheadBehindMarker = page.getByLabel('Ahead Behind Marker');
216+
await navigateToObjectWithRealTime(page, timeStrip.url);
217+
await setEndOffset(page, {
218+
endMins: '15',
219+
endSecs: '00'
220+
});
221+
222+
await test.step('set the ahead line', async () => {
223+
// select the first plan in the timeStrip
224+
await page.locator('.c-swimlane__lane-label.c-object-label').nth(1).click();
225+
await page.getByRole('button', { name: 'Edit Object' }).click();
226+
await page
227+
.locator('select[aria-label="Plan Execution Monitoring Status"]')
228+
.selectOption({ label: 'Ahead by' });
229+
page.getByLabel('Plan Execution Monitoring Duration').fill('5');
230+
231+
await page.getByLabel('Save').click();
232+
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
233+
234+
await expect(aheadBehindMarker).toBeVisible();
235+
await expect(aheadBehindMarker).toContainClass('--ahead');
236+
await expect(aheadBehindMarker).not.toContainClass('--behind');
237+
});
238+
239+
await test.step('set the behind line', async () => {
240+
// select the first plan in the timeStrip
241+
await page.locator('.c-swimlane__lane-label.c-object-label').nth(1).click();
242+
await page.getByRole('button', { name: 'Edit Object' }).click();
243+
await page
244+
.locator('select[aria-label="Plan Execution Monitoring Status"]')
245+
.selectOption({ label: 'Behind by' });
246+
page.getByLabel('Plan Execution Monitoring Duration').fill('5');
247+
248+
await page.getByLabel('Save').click();
249+
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
250+
251+
await expect(aheadBehindMarker).toBeVisible();
252+
await expect(aheadBehindMarker).not.toContainClass('--ahead');
253+
await expect(aheadBehindMarker).toContainClass('--behind');
254+
});
255+
});
233256
});

0 commit comments

Comments
 (0)