mirror of
https://github.com/nasa/openmct.git
synced 2024-12-20 13:43:09 +00:00
test: add timelist countdown/up test
This commit is contained in:
parent
cc8f726bd5
commit
ad30a8fb2c
@ -1,37 +1,37 @@
|
|||||||
{
|
{
|
||||||
"Group 1": [
|
"Group 1": [
|
||||||
{
|
{
|
||||||
"name": "Group 1 event 1",
|
"name": "Time until birthday",
|
||||||
"start": 1650320408000,
|
"start": 1650320402000,
|
||||||
"end": 1660343797000,
|
"end": 1660343797000,
|
||||||
"type": "Group 1",
|
"type": "Group 1",
|
||||||
"color": "orange",
|
"color": "orange",
|
||||||
"textColor": "white"
|
"textColor": "white"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Group 1 event 2",
|
"name": "Time until supper",
|
||||||
"start": 1650320508000,
|
"start": 1650320402000,
|
||||||
"end": 1660343897000,
|
"end": 1650420410000,
|
||||||
"type": "Group 1",
|
"type": "Group 2",
|
||||||
"color": "yellow",
|
"color": "blue",
|
||||||
"textColor": "white"
|
"textColor": "white"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Group 2": [
|
"Group 2": [
|
||||||
{
|
{
|
||||||
"name": "Group 2 event 1",
|
"name": "Time since the last time I ate",
|
||||||
"start": 1650320608000,
|
"start": 1650320102001,
|
||||||
"end": 1660343997000,
|
"end": 1650320102001,
|
||||||
"type": "Group 2",
|
"type": "Group 2",
|
||||||
"color": "green",
|
"color": "green",
|
||||||
"textColor": "white"
|
"textColor": "white"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Group 2 event 2",
|
"name": "Time since last accident",
|
||||||
"start": 1650320808000,
|
"start": 1650320102002,
|
||||||
"end": 1660344097000,
|
"end": 1650320102002,
|
||||||
"type": "Group 2",
|
"type": "Group 1",
|
||||||
"color": "blue",
|
"color": "yellow",
|
||||||
"textColor": "white"
|
"textColor": "white"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -22,6 +22,15 @@
|
|||||||
|
|
||||||
const { test, expect } = require('../../../pluginFixtures');
|
const { test, expect } = require('../../../pluginFixtures');
|
||||||
const { createDomainObjectWithDefaults, createPlanFromJSON } = require('../../../appActions');
|
const { createDomainObjectWithDefaults, createPlanFromJSON } = require('../../../appActions');
|
||||||
|
const { getEarliestStartTime } = require('../../../helper/planningUtils');
|
||||||
|
const examplePlanSmall3 = require('../../../test-data/examplePlans/ExamplePlan_Small3.json');
|
||||||
|
|
||||||
|
const START_TIME_COLUMN = 0;
|
||||||
|
const END_TIME_COLUMN = 1;
|
||||||
|
const TIME_TO_FROM_COLUMN = 2;
|
||||||
|
const ACTIVITY_COLUMN = 3;
|
||||||
|
const HEADER_ROW = 0;
|
||||||
|
const NUM_COLUMNS = 4;
|
||||||
|
|
||||||
const testPlan = {
|
const testPlan = {
|
||||||
TEST_GROUP: [
|
TEST_GROUP: [
|
||||||
@ -69,7 +78,6 @@ const testPlan = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
test.describe('Time List', () => {
|
test.describe('Time List', () => {
|
||||||
// the first time modifying test -- watch Terminator
|
|
||||||
test('Create a Time List, add a single Plan to it and verify all the activities are displayed with no milliseconds', async ({
|
test('Create a Time List, add a single Plan to it and verify all the activities are displayed with no milliseconds', async ({
|
||||||
page
|
page
|
||||||
}) => {
|
}) => {
|
||||||
@ -118,3 +126,162 @@ test.describe('Time List', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The regular expression used to parse the countdown string.
|
||||||
|
* Some examples of valid Countdown strings:
|
||||||
|
* ```
|
||||||
|
* '35D 02:03:04'
|
||||||
|
* '-1D 01:02:03'
|
||||||
|
* '01:02:03'
|
||||||
|
* '-05:06:07'
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
const COUNTDOWN_REGEXP = /(-)?(\d+D\s)?(\d{2}):(\d{2}):(\d{2})/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} CountdownObject
|
||||||
|
* @property {string} sign - The sign of the countdown ('-' if the countdown is negative, otherwise undefined).
|
||||||
|
* @property {string} days - The number of days in the countdown (undefined if there are no days).
|
||||||
|
* @property {string} hours - The number of hours in the countdown.
|
||||||
|
* @property {string} minutes - The number of minutes in the countdown.
|
||||||
|
* @property {string} seconds - The number of seconds in the countdown.
|
||||||
|
* @property {string} toString - The countdown string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object representing the indices of the capture groups in a countdown regex match.
|
||||||
|
*
|
||||||
|
* @typedef {{ SIGN: number, DAYS: number, HOURS: number, MINUTES: number, SECONDS: number, REGEXP: RegExp }}
|
||||||
|
* @property {number} SIGN - The index for the sign capture group (1 if a '-' sign is present, otherwise undefined).
|
||||||
|
* @property {number} DAYS - The index for the days capture group (2 for the number of days, otherwise undefined).
|
||||||
|
* @property {number} HOURS - The index for the hours capture group (3 for the hour part of the time).
|
||||||
|
* @property {number} MINUTES - The index for the minutes capture group (4 for the minute part of the time).
|
||||||
|
* @property {number} SECONDS - The index for the seconds capture group (5 for the second part of the time).
|
||||||
|
*/
|
||||||
|
const COUNTDOWN = Object.freeze({
|
||||||
|
SIGN: 1,
|
||||||
|
DAYS: 2,
|
||||||
|
HOURS: 3,
|
||||||
|
MINUTES: 4,
|
||||||
|
SECONDS: 5
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe('Time List with controlled clock', () => {
|
||||||
|
test.use({
|
||||||
|
clockOptions: {
|
||||||
|
now: getEarliestStartTime(examplePlanSmall3),
|
||||||
|
shouldAdvanceTime: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||||
|
});
|
||||||
|
test('Time List shows current events and counts down correctly in real-time mode', async ({
|
||||||
|
page
|
||||||
|
}) => {
|
||||||
|
await test.step('Create a Time List, add a Plan to it, and switch to real-time mode', async () => {
|
||||||
|
// Create Time List
|
||||||
|
const timelist = await createDomainObjectWithDefaults(page, {
|
||||||
|
type: 'Time List'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a Plan with events that count down and up.
|
||||||
|
// Add it as a child to the Time List.
|
||||||
|
await createPlanFromJSON(page, {
|
||||||
|
json: examplePlanSmall3,
|
||||||
|
parent: timelist.uuid
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navigate to the Time List in real-time mode
|
||||||
|
await page.goto(
|
||||||
|
`${timelist.url}?tc.mode=local&tc.startDelta=900000&tc.endDelta=1800000&tc.timeSystem=utc&view=grid`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const countUpCells = [
|
||||||
|
getCell(page, 1, TIME_TO_FROM_COLUMN),
|
||||||
|
getCell(page, 2, TIME_TO_FROM_COLUMN)
|
||||||
|
];
|
||||||
|
const countdownCells = [
|
||||||
|
getCell(page, 3, TIME_TO_FROM_COLUMN),
|
||||||
|
getCell(page, 4, TIME_TO_FROM_COLUMN)
|
||||||
|
];
|
||||||
|
|
||||||
|
// Verify that the countdown cells are counting down
|
||||||
|
for (let i = 0; i < countdownCells.length; i++) {
|
||||||
|
await test.step(`Countdown cell ${i + 1} counts down`, async () => {
|
||||||
|
const countdownCell = countdownCells[i];
|
||||||
|
// Get the initial countdown timestamp object
|
||||||
|
const beforeCountdown = await getCountdownObject(page, i + 3);
|
||||||
|
// Wait until it changes
|
||||||
|
await expect(countdownCell).not.toHaveText(beforeCountdown.toString());
|
||||||
|
// Get the new countdown timestamp object
|
||||||
|
const afterCountdown = await getCountdownObject(page, i + 3);
|
||||||
|
// Verify that the new countdown timestamp object is less than the old one
|
||||||
|
expect(Number(afterCountdown.seconds)).toBeLessThan(Number(beforeCountdown.seconds));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the countup cells are counting up
|
||||||
|
for (let i = 0; i < countUpCells.length; i++) {
|
||||||
|
await test.step(`Countup cell ${i + 1} counts up`, async () => {
|
||||||
|
const countdownCell = countUpCells[i];
|
||||||
|
// Get the initial countup timestamp object
|
||||||
|
const beforeCountdown = await getCountdownObject(page, i + 1);
|
||||||
|
// Wait until it changes
|
||||||
|
await expect(countdownCell).not.toHaveText(beforeCountdown.toString());
|
||||||
|
// Get the new countup timestamp object
|
||||||
|
const afterCountdown = await getCountdownObject(page, i + 1);
|
||||||
|
// Verify that the new countup timestamp object is greater than the old one
|
||||||
|
expect(Number(afterCountdown.seconds)).toBeGreaterThan(Number(beforeCountdown.seconds));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the cell at the given row and column indices.
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
* @param {number} rowIndex
|
||||||
|
* @param {number} columnIndex
|
||||||
|
* @returns {import('@playwright/test').Locator} cell
|
||||||
|
*/
|
||||||
|
function getCell(page, rowIndex, columnIndex) {
|
||||||
|
return page.getByRole('cell').nth(rowIndex * NUM_COLUMNS + columnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the innerText of the cell at the given row and column indices.
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
* @param {number} rowIndex
|
||||||
|
* @param {number} columnIndex
|
||||||
|
* @returns {Promise<string>} text
|
||||||
|
*/
|
||||||
|
async function getCellText(page, rowIndex, columnIndex) {
|
||||||
|
const text = await getCell(page, rowIndex, columnIndex).innerText();
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text from the countdown cell in the given row, assert that it matches the countdown
|
||||||
|
* regex, and return an object representing the countdown.
|
||||||
|
* @param {import('@playwright/test').Page} page
|
||||||
|
* @param {number} rowIndex the row index
|
||||||
|
* @returns {Promise<CountdownObject>} countdownObject
|
||||||
|
*/
|
||||||
|
async function getCountdownObject(page, rowIndex) {
|
||||||
|
const timeToFrom = await getCellText(page, HEADER_ROW + rowIndex, TIME_TO_FROM_COLUMN);
|
||||||
|
|
||||||
|
expect(timeToFrom).toMatch(COUNTDOWN_REGEXP);
|
||||||
|
const match = timeToFrom.match(COUNTDOWN_REGEXP);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sign: match[COUNTDOWN.SIGN],
|
||||||
|
days: match[COUNTDOWN.DAYS],
|
||||||
|
hours: match[COUNTDOWN.HOURS],
|
||||||
|
minutes: match[COUNTDOWN.MINUTES],
|
||||||
|
seconds: match[COUNTDOWN.SECONDS],
|
||||||
|
toString: () => timeToFrom
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -100,41 +100,3 @@ test.describe('Visual - Planning', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('Timelist with controlled clock', () => {
|
|
||||||
test.use({
|
|
||||||
clockOptions: {
|
|
||||||
now: getEarliestStartTime(examplePlanSmall3),
|
|
||||||
shouldAdvanceTime: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
test.beforeEach(async ({ page }) => {
|
|
||||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
|
||||||
});
|
|
||||||
test('Timelist', async ({ page, theme }) => {
|
|
||||||
const timelist = await createDomainObjectWithDefaults(page, {
|
|
||||||
type: 'Time List',
|
|
||||||
name: 'Time List Visual Test'
|
|
||||||
});
|
|
||||||
await createPlanFromJSON(page, {
|
|
||||||
json: examplePlanSmall3,
|
|
||||||
parent: timelist.uuid
|
|
||||||
});
|
|
||||||
await page.goto(
|
|
||||||
`${timelist.url}?tc.mode=local&tc.startDelta=900000&tc.endDelta=1800000&tc.timeSystem=utc&view=grid`
|
|
||||||
);
|
|
||||||
|
|
||||||
// Dismiss each "Save successful" notification (quicker than waiting)
|
|
||||||
await page.getByLabel('Dismiss').click();
|
|
||||||
await page.getByLabel('Dismiss').click();
|
|
||||||
await page.getByLabel('Dismiss').click();
|
|
||||||
|
|
||||||
await percySnapshot(page, `Timelist Countdown 1 (theme: ${theme})`, {
|
|
||||||
scope: snapshotScope
|
|
||||||
});
|
|
||||||
await page.waitForTimeout(1000);
|
|
||||||
await percySnapshot(page, `Timelist Countdown 2 (theme: ${theme})`, {
|
|
||||||
scope: snapshotScope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
Loading…
Reference in New Issue
Block a user