mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 21:27:52 +00:00
test: add timelist countdown/up test
This commit is contained in:
parent
cc8f726bd5
commit
ad30a8fb2c
@ -1,37 +1,37 @@
|
||||
{
|
||||
"Group 1": [
|
||||
{
|
||||
"name": "Group 1 event 1",
|
||||
"start": 1650320408000,
|
||||
"name": "Time until birthday",
|
||||
"start": 1650320402000,
|
||||
"end": 1660343797000,
|
||||
"type": "Group 1",
|
||||
"color": "orange",
|
||||
"textColor": "white"
|
||||
},
|
||||
{
|
||||
"name": "Group 1 event 2",
|
||||
"start": 1650320508000,
|
||||
"end": 1660343897000,
|
||||
"type": "Group 1",
|
||||
"color": "yellow",
|
||||
"name": "Time until supper",
|
||||
"start": 1650320402000,
|
||||
"end": 1650420410000,
|
||||
"type": "Group 2",
|
||||
"color": "blue",
|
||||
"textColor": "white"
|
||||
}
|
||||
],
|
||||
"Group 2": [
|
||||
{
|
||||
"name": "Group 2 event 1",
|
||||
"start": 1650320608000,
|
||||
"end": 1660343997000,
|
||||
"name": "Time since the last time I ate",
|
||||
"start": 1650320102001,
|
||||
"end": 1650320102001,
|
||||
"type": "Group 2",
|
||||
"color": "green",
|
||||
"textColor": "white"
|
||||
},
|
||||
{
|
||||
"name": "Group 2 event 2",
|
||||
"start": 1650320808000,
|
||||
"end": 1660344097000,
|
||||
"type": "Group 2",
|
||||
"color": "blue",
|
||||
"name": "Time since last accident",
|
||||
"start": 1650320102002,
|
||||
"end": 1650320102002,
|
||||
"type": "Group 1",
|
||||
"color": "yellow",
|
||||
"textColor": "white"
|
||||
}
|
||||
]
|
||||
|
@ -22,6 +22,15 @@
|
||||
|
||||
const { test, expect } = require('../../../pluginFixtures');
|
||||
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 = {
|
||||
TEST_GROUP: [
|
||||
@ -69,7 +78,6 @@ const testPlan = {
|
||||
};
|
||||
|
||||
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 ({
|
||||
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