Skip to content

Commit

Permalink
New Playwright tests for the versions functionality. (#130)
Browse files Browse the repository at this point in the history
Also updated the other Playwright test to not have to clean up their
temporary files in a finally block any more, but rather clean these up
together in a separate 'delete' test that cleans up matching files if
they are older than 2 hours. It does this cleanup through the UI so it
also serves as a test for delete.

Co-authored-by: Chris Millar <cmillar@apache.org>
  • Loading branch information
bosschaert and auniverseaway authored May 17, 2024
1 parent c43bc40 commit 9a30aeb
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 77 deletions.
1 change: 1 addition & 0 deletions test/e2e/tests/browse.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ENV from '../utils/env.js';

test('Get Main Page', async ({ page }) => {
await page.goto(ENV);

const html = await page.content();
expect(html).toContain('Dark Alley');

Expand Down
76 changes: 76 additions & 0 deletions test/e2e/tests/delete.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { test, expect } from '@playwright/test';
import ENV from '../utils/env.js';
import { getTestResourceAge } from '../utils/page.js';

const MIN_HOURS = 2; // Files are deleted after 2 hours

// This test deletes old testing pages that are older than 2 hours
test('Delete multiple old pages', async ({ page }, workerInfo) => {
if (workerInfo.project.name !== 'chromium') {
// only execute this test on chromium
return;
}

test.setTimeout(40000);

// Open the directory listing
await page.goto(`${ENV}/#/da-sites/da-status/tests`);

// Wait for the page to appear
await page.waitForTimeout(1000);

// This page will always be there as its used by a test
await expect(page.getByText('pingtest'), 'Precondition').toBeVisible();

// List the resources and check fot the ones that are to be deleted. These are always pages
// created by the getTestPageURL() function in page.js
const items = page.locator('.da-item-list-item');
let itemsToDelete;
for (let i = 0; i < await items.count(); i += 1) {
const item = items.nth(i);
const fileName = await item.innerText();
console.log('Item', i, fileName, '-', getTestResourceAge(fileName));

// This method checks if the page is a generated test page. If it is, it returns its age in ms.
const age = getTestResourceAge(fileName);
if (!age) {
// eslint-disable-next-line no-continue
continue;
}
const day = 1000 * 60 * 60 * MIN_HOURS;
if (Date.now() - day < age) {
console.log('Too new:', fileName);
// eslint-disable-next-line no-continue
continue;
}

// If we're here the page has to be deleted. We'll tick the checkbox next to it in the page
const checkbox = page.locator('li').filter({ hasText: fileName }).locator('input[type="checkbox"][name="item-selected"]');
console.log('checkboxes:', await checkbox.count());
await checkbox.focus();
await page.keyboard.press(' ');
itemsToDelete = true;
}

if (!itemsToDelete) {
console.log('No items to delete');
return;
}

// Hit the delete button
await page.getByRole('button', { name: 'Delete' }).click();

// Wait for the delete button to disappear which is when we're done
await expect(page.getByRole('button', { name: 'Delete' })).not.toBeVisible({ timeout: 30000 });
});
90 changes: 38 additions & 52 deletions test/e2e/tests/edit.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,74 +11,60 @@
*/
import { test, expect } from '@playwright/test';
import ENV from '../utils/env.js';
import { getTestPageURL } from '../utils/page.js';

test('Update Document', async ({ browser, page }, workerInfo) => {
test.setTimeout(15000);

const dateStamp = Date.now().toString(36);
const pageName = `pw-test1-${dateStamp}-${workerInfo.project.name}`;
const url = `${ENV}/edit#/da-sites/da-status/tests/${pageName}`;
const url = getTestPageURL('edit1', workerInfo);
await page.goto(url);
await expect(page.locator('div.ProseMirror')).toBeVisible();

try {
await page.goto(url);
await expect(page.locator('div.ProseMirror')).toBeVisible();
const enteredText = `[${workerInfo.project.name}] Edited by test ${new Date()}`;
await page.locator('div.ProseMirror').fill(enteredText);

const enteredText = `[${workerInfo.project.name}] Edited by test ${new Date()}`;
await page.locator('div.ProseMirror').fill(enteredText);
// Wait 3 secs
await page.waitForTimeout(3000);
await page.close();

// Wait 3 secs
await page.waitForTimeout(3000);
await page.close();

const newPage = await browser.newPage();
await newPage.goto(url);
await expect(newPage.locator('div.ProseMirror')).toBeVisible();
await expect(newPage.locator('div.ProseMirror')).toContainText(enteredText);
} finally {
// Always delete the document afterwards
const adminURL = `https://admin.da.live/source/da-sites/da-status/tests/${pageName}.html`;
await fetch(adminURL, { method: 'DELETE' });
}
const newPage = await browser.newPage();
await newPage.goto(url);
await expect(newPage.locator('div.ProseMirror')).toBeVisible();
await expect(newPage.locator('div.ProseMirror')).toContainText(enteredText);
});

test('Create Delete Document', async ({ browser, page }, workerInfo) => {
test.setTimeout(15000);

const dateStamp = Date.now().toString(36);
const pageName = `pw-test2-${dateStamp}-${workerInfo.project.name}`;
const url = getTestPageURL('edit2', workerInfo);
const pageName = url.split('/').pop();

try {
await page.goto(`${ENV}/#/da-sites/da-status/tests`);
await page.locator('button.da-actions-new-button').click();
await page.locator('button:text("Document")').click();
await page.locator('input.da-actions-input').fill(pageName);
await page.goto(`${ENV}/#/da-sites/da-status/tests`);
await page.locator('button.da-actions-new-button').click();
await page.locator('button:text("Document")').click();
await page.locator('input.da-actions-input').fill(pageName);

await page.locator('button:text("Create document")').click();
await expect(page.locator('div.ProseMirror')).toBeVisible();
await page.locator('div.ProseMirror').fill('testcontent');
await page.locator('button:text("Create document")').click();
await expect(page.locator('div.ProseMirror')).toBeVisible();
await page.locator('div.ProseMirror').fill('testcontent');

const newPage = await browser.newPage();
await newPage.goto(`${ENV}/#/da-sites/da-status/tests`);
const newPage = await browser.newPage();
await newPage.goto(`${ENV}/#/da-sites/da-status/tests`);

// Wait 1 sec
await newPage.waitForTimeout(4000);
await newPage.reload();
// Wait 1 sec
await newPage.waitForTimeout(4000);
await newPage.reload();

await expect(newPage.locator(`a[href="/edit#/da-sites/da-status/tests/${pageName}"]`)).toBeVisible();
await newPage.locator(`a[href="/edit#/da-sites/da-status/tests/${pageName}"]`).focus();
// Note this currently does not work on webkit as the checkbox isn't keyboard focusable there
await newPage.keyboard.press('Shift+Tab');
await newPage.keyboard.press(' ');
await newPage.waitForTimeout(500);
await expect(newPage.locator('button.delete-button')).toBeVisible();
await newPage.locator('button.delete-button').click();
await expect(newPage.locator(`a[href="/edit#/da-sites/da-status/tests/${pageName}"]`)).toBeVisible();
await newPage.locator(`a[href="/edit#/da-sites/da-status/tests/${pageName}"]`).focus();
// Note this currently does not work on webkit as the checkbox isn't keyboard focusable there
await newPage.keyboard.press('Shift+Tab');
await newPage.keyboard.press(' ');
await newPage.waitForTimeout(500);
await expect(newPage.locator('button.delete-button')).toBeVisible();
await newPage.locator('button.delete-button').click();

// Wait 1 sec
await page.waitForTimeout(1000);
await expect(newPage.locator(`a[href="/edit#/da-sites/da-status/tests/${pageName}"]`)).not.toBeVisible();
} finally {
// Delete the document even if the test fails;
const adminURL = `https://admin.da.live/source/da-sites/da-status/tests/${pageName}.html`;
await fetch(adminURL, { method: 'DELETE' });
}
// Wait 1 sec
await page.waitForTimeout(1000);
await expect(newPage.locator(`a[href="/edit#/da-sites/da-status/tests/${pageName}"]`)).not.toBeVisible();
});
41 changes: 16 additions & 25 deletions test/e2e/tests/sheet.spec.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,27 @@
import { test, expect } from '@playwright/test';
import ENV from '../utils/env.js';
import { getTestSheetURL } from '../utils/page.js';

test('New sheet', async ({ page }, workerInfo) => {
test.setTimeout(15000);

const dateStamp = Date.now().toString(36);
const pageName = `pw-test1-${dateStamp}-${workerInfo.project.name}`;
const url = `${ENV}/sheet#/da-sites/da-status/tests/${pageName}`;
const url = getTestSheetURL('sheet1', workerInfo);
await page.goto(url);

try {
await page.goto(url);
// DA title
await expect(page.locator('h1')).toBeVisible();

// DA title
await expect(page.locator('h1')).toBeVisible();
// Sheet tabs
await expect(page.locator('da-sheet-tabs')).toBeVisible();

// Sheet tabs
await expect(page.locator('da-sheet-tabs')).toBeVisible();
// Enter text into first cell
const enteredText = `[${workerInfo.project.name}] Edited by test ${new Date()}`;
await page.locator('[data-x="0"][data-y="0"]').dblclick();
await page.locator('input').fill('key');

// Enter text into first cell
const enteredText = `[${workerInfo.project.name}] Edited by test ${new Date()}`;
await page.locator('[data-x="0"][data-y="0"]').dblclick();
await page.locator('input').fill('key');
// Enter text into second cell
await page.locator('[data-x="0"][data-y="1"]').dblclick();
await page.locator('td input').fill(enteredText);

// Enter text into second cell
await page.locator('[data-x="0"][data-y="1"]').dblclick();
await page.locator('td input').fill(enteredText);

await page.waitForTimeout(3000);
await page.close();
} finally {
// Always delete the document afterwards
// const adminURL = `https://admin.da.live/source/da-sites/da-status/tests/${pageName}.json`;
// await fetch(adminURL, { method: 'DELETE' });
}
await page.waitForTimeout(3000);
await page.close();
});
68 changes: 68 additions & 0 deletions test/e2e/tests/versions.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { test, expect } from '@playwright/test';
import { getTestPageURL } from '../utils/page.js';

test('Create Version and Restore from it', async ({ page }, workerInfo) => {
// This test has a fairly high timeout because it waits for the document to be saved
// a number of times
test.setTimeout(30000);

await page.goto(getTestPageURL('versions', workerInfo));
await expect(page.locator('div.ProseMirror')).toBeVisible();

// Enter some initial text onto the page
await page.locator('div.ProseMirror').fill('Initial version');

// Wait 3 secs to ensure its saved in da-admin
await page.waitForTimeout(3000);

// Create a new stored version called 'ver 1'
await page.getByRole('button', { name: 'Versions' }).click();
await page.locator('button.da-version-btn').click();
await page.locator('input.da-version-new-input').fill('ver 1');
await page.locator('input.da-version-new-input').press('Enter');

// Close the versions panel and add some more text
await page.locator('button.da-versions-close-btn').click();
await page.locator('div.ProseMirror').fill('Some modifications');

// Wait 3 secs to ensure its saved
await page.waitForTimeout(3000);

// And add some more text
await page.locator('div.ProseMirror').fill('Some more modifications');
// Wait 3 secs to ensure its saved
await page.waitForTimeout(3000);

// Reload the page and check that the latest changes are there
await page.reload();
await expect(page.locator('div.ProseMirror'))
.toContainText('Some more modifications');

// Open the versions panel again
await page.getByRole('button', { name: 'Versions' }).click();

// Check that there is an audit entry for the last edit (which we didn't)
// expliticly create a version for.
const audit = await page.locator('.da-version-entry.is-audit');
await audit.click();
await expect(audit).toContainText('anonymous');

// Select 'ver 1' and restore it
await page.getByText('ver 1', { exact: false }).click();
await page.getByRole('button', { name: 'Restore' }).click();
await page.locator('div.da-version-action-area').getByText('Restore').click();

// Ensure that the original text is still there
await expect(page.locator('div.ProseMirror')).toContainText('Initial version');
});
55 changes: 55 additions & 0 deletions test/e2e/utils/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import ENV from './env.js';

function getTestURL(type, testIdentifier, workerInfo) {
const dateStamp = Date.now().toString(36);
const pageName = `pw-${testIdentifier}-${dateStamp}-${workerInfo.project.name}`;
return `${ENV}/${type}#/da-sites/da-status/tests/${pageName}`;
}

/**
* Returns a URL for a single-use test page.
*
* @param {string} testIdentifier - A identifier for the test
* @param {object} workerInfo - workerInfo as passed in by Playwright
* @returns {string} The URL for the test page.
*/
export function getTestPageURL(testIdentifier, workerInfo) {
return getTestURL('edit', testIdentifier, workerInfo);
}

/**
* Returns a URL for a single-use test sheet.
*
* @param {string} testIdentifier - A identifier for the test
* @param {object} workerInfo - workerInfo as passed in by Playwright
* @returns {string} The URL for the test page.
*/
export function getTestSheetURL(testIdentifier, workerInfo) {
return getTestURL('sheet', testIdentifier, workerInfo);
}

/**
* Return the age of the test file by inspecting the timestamp in the filename.
* It also checks if the filename matches the pattern of generated file names.
* @param {String} fileName The file name, as generated in getTestURL()
* @returns The age in ms or null if the file name does not match the pattern.
*/
export function getTestResourceAge(fileName) {
const re = /pw-\w+(-t1)*-(\w+)-\w+/;
const res = re.exec(fileName);
if (res) {
return parseInt(res[2], 36);
}
return null;
}

0 comments on commit 9a30aeb

Please sign in to comment.