chore: add prettier (2/3): apply formatting, re-enable lint ci step (#6682)
* style: apply prettier formatting * fix: re-enable lint ci check
This commit is contained in:
@@ -32,417 +32,454 @@ const path = require('path');
|
||||
const NOTEBOOK_NAME = 'Notebook';
|
||||
|
||||
test.describe('Notebook CRUD Operations', () => {
|
||||
test.fixme('Can create a Notebook Object', async ({ page }) => {
|
||||
//Create domain object
|
||||
//Newly created notebook should have one Section and one page, 'Unnamed Section'/'Unnamed Page'
|
||||
});
|
||||
test.fixme('Can update a Notebook Object', async ({ page }) => {});
|
||||
test.fixme('Can view a perviously created Notebook Object', async ({ page }) => {});
|
||||
test.fixme('Can Delete a Notebook Object', async ({ page }) => {
|
||||
// Other than non-persistible objects
|
||||
});
|
||||
test.fixme('Can create a Notebook Object', async ({ page }) => {
|
||||
//Create domain object
|
||||
//Newly created notebook should have one Section and one page, 'Unnamed Section'/'Unnamed Page'
|
||||
});
|
||||
test.fixme('Can update a Notebook Object', async ({ page }) => {});
|
||||
test.fixme('Can view a perviously created Notebook Object', async ({ page }) => {});
|
||||
test.fixme('Can Delete a Notebook Object', async ({ page }) => {
|
||||
// Other than non-persistible objects
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Default Notebook', () => {
|
||||
// General Default Notebook statements
|
||||
// ## Useful commands:
|
||||
// 1. - To check default notebook:
|
||||
// `JSON.parse(localStorage.getItem('notebook-storage'));`
|
||||
// 1. - Clear default notebook:
|
||||
// `localStorage.setItem('notebook-storage', null);`
|
||||
test.fixme('A newly created Notebook is automatically set as the default notebook if no other notebooks exist', async ({ page }) => {
|
||||
//Create new notebook
|
||||
//Verify Default Notebook Characteristics
|
||||
});
|
||||
test.fixme('A newly created Notebook is automatically set as the default notebook if at least one other notebook exists', async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Create second notebook B
|
||||
//Verify Non-Default Notebook A Characteristics
|
||||
//Verify Default Notebook B Characteristics
|
||||
});
|
||||
test.fixme('If a default notebook is deleted, the second most recent notebook becomes the default', async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Create second notebook B
|
||||
//Delete Notebook B
|
||||
//Verify Default Notebook A Characteristics
|
||||
});
|
||||
// General Default Notebook statements
|
||||
// ## Useful commands:
|
||||
// 1. - To check default notebook:
|
||||
// `JSON.parse(localStorage.getItem('notebook-storage'));`
|
||||
// 1. - Clear default notebook:
|
||||
// `localStorage.setItem('notebook-storage', null);`
|
||||
test.fixme(
|
||||
'A newly created Notebook is automatically set as the default notebook if no other notebooks exist',
|
||||
async ({ page }) => {
|
||||
//Create new notebook
|
||||
//Verify Default Notebook Characteristics
|
||||
}
|
||||
);
|
||||
test.fixme(
|
||||
'A newly created Notebook is automatically set as the default notebook if at least one other notebook exists',
|
||||
async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Create second notebook B
|
||||
//Verify Non-Default Notebook A Characteristics
|
||||
//Verify Default Notebook B Characteristics
|
||||
}
|
||||
);
|
||||
test.fixme(
|
||||
'If a default notebook is deleted, the second most recent notebook becomes the default',
|
||||
async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Create second notebook B
|
||||
//Delete Notebook B
|
||||
//Verify Default Notebook A Characteristics
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test.describe('Notebook section tests', () => {
|
||||
//The following test cases are associated with Notebook Sections
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
//The following test cases are associated with Notebook Sections
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
test('Default and new sections are automatically named Unnamed Section with Unnamed Page', async ({ page }) => {
|
||||
const notebookSectionNames = page.locator('.c-notebook__sections .c-list__item__name');
|
||||
const notebookPageNames = page.locator('.c-notebook__pages .c-list__item__name');
|
||||
await expect(notebookSectionNames).toBeHidden();
|
||||
await expect(notebookPageNames).toBeHidden();
|
||||
// Expand sidebar
|
||||
await page.locator('.c-notebook__toggle-nav-button').click();
|
||||
// Check that the default section and page are created and the name matches the defaults
|
||||
const defaultSectionName = await notebookSectionNames.innerText();
|
||||
await expect(notebookSectionNames).toBeVisible();
|
||||
expect(defaultSectionName).toBe('Unnamed Section');
|
||||
const defaultPageName = await notebookPageNames.innerText();
|
||||
await expect(notebookPageNames).toBeVisible();
|
||||
expect(defaultPageName).toBe('Unnamed Page');
|
||||
|
||||
// Add a section
|
||||
await page.locator('.js-sidebar-sections .c-icon-button.icon-plus').click();
|
||||
|
||||
// Check that new section and page within the new section match the defaults
|
||||
const newSectionName = await notebookSectionNames.nth(1).innerText();
|
||||
await expect(notebookSectionNames.nth(1)).toBeVisible();
|
||||
expect(newSectionName).toBe('Unnamed Section');
|
||||
const newPageName = await notebookPageNames.innerText();
|
||||
await expect(notebookPageNames).toBeVisible();
|
||||
expect(newPageName).toBe('Unnamed Page');
|
||||
|
||||
});
|
||||
test.fixme('Section selection operations and associated behavior', async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Add Sections until 6 total with no default section/page
|
||||
//Select 3rd section
|
||||
//Delete 4th section
|
||||
//3rd section is still selected
|
||||
//Delete 3rd section
|
||||
//1st section is selected
|
||||
//Set 3rd section as default
|
||||
//Delete 2nd section
|
||||
//3rd section is still default
|
||||
//Delete 3rd section
|
||||
//1st is selected and there is no default notebook
|
||||
});
|
||||
test.fixme('Section rename operations', async ({ page }) => {
|
||||
// Create a new notebook
|
||||
// Add a section
|
||||
// Rename the section but do not confirm
|
||||
// Keyboard press 'Escape'
|
||||
// Verify that the section name reverts to the default name
|
||||
// Rename the section but do not confirm
|
||||
// Keyboard press 'Enter'
|
||||
// Verify that the section name is updated
|
||||
// Rename the section to "" (empty string)
|
||||
// Keyboard press 'Enter' to confirm
|
||||
// Verify that the section name reverts to the default name
|
||||
// Rename the section to something long that overflows the text box
|
||||
// Verify that the section name is not truncated while input is active
|
||||
// Confirm the section name edit
|
||||
// Verify that the section name is truncated now that input is not active
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
});
|
||||
test('Default and new sections are automatically named Unnamed Section with Unnamed Page', async ({
|
||||
page
|
||||
}) => {
|
||||
const notebookSectionNames = page.locator('.c-notebook__sections .c-list__item__name');
|
||||
const notebookPageNames = page.locator('.c-notebook__pages .c-list__item__name');
|
||||
await expect(notebookSectionNames).toBeHidden();
|
||||
await expect(notebookPageNames).toBeHidden();
|
||||
// Expand sidebar
|
||||
await page.locator('.c-notebook__toggle-nav-button').click();
|
||||
// Check that the default section and page are created and the name matches the defaults
|
||||
const defaultSectionName = await notebookSectionNames.innerText();
|
||||
await expect(notebookSectionNames).toBeVisible();
|
||||
expect(defaultSectionName).toBe('Unnamed Section');
|
||||
const defaultPageName = await notebookPageNames.innerText();
|
||||
await expect(notebookPageNames).toBeVisible();
|
||||
expect(defaultPageName).toBe('Unnamed Page');
|
||||
|
||||
// Add a section
|
||||
await page.locator('.js-sidebar-sections .c-icon-button.icon-plus').click();
|
||||
|
||||
// Check that new section and page within the new section match the defaults
|
||||
const newSectionName = await notebookSectionNames.nth(1).innerText();
|
||||
await expect(notebookSectionNames.nth(1)).toBeVisible();
|
||||
expect(newSectionName).toBe('Unnamed Section');
|
||||
const newPageName = await notebookPageNames.innerText();
|
||||
await expect(notebookPageNames).toBeVisible();
|
||||
expect(newPageName).toBe('Unnamed Page');
|
||||
});
|
||||
test.fixme('Section selection operations and associated behavior', async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Add Sections until 6 total with no default section/page
|
||||
//Select 3rd section
|
||||
//Delete 4th section
|
||||
//3rd section is still selected
|
||||
//Delete 3rd section
|
||||
//1st section is selected
|
||||
//Set 3rd section as default
|
||||
//Delete 2nd section
|
||||
//3rd section is still default
|
||||
//Delete 3rd section
|
||||
//1st is selected and there is no default notebook
|
||||
});
|
||||
test.fixme('Section rename operations', async ({ page }) => {
|
||||
// Create a new notebook
|
||||
// Add a section
|
||||
// Rename the section but do not confirm
|
||||
// Keyboard press 'Escape'
|
||||
// Verify that the section name reverts to the default name
|
||||
// Rename the section but do not confirm
|
||||
// Keyboard press 'Enter'
|
||||
// Verify that the section name is updated
|
||||
// Rename the section to "" (empty string)
|
||||
// Keyboard press 'Enter' to confirm
|
||||
// Verify that the section name reverts to the default name
|
||||
// Rename the section to something long that overflows the text box
|
||||
// Verify that the section name is not truncated while input is active
|
||||
// Confirm the section name edit
|
||||
// Verify that the section name is truncated now that input is not active
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Notebook page tests', () => {
|
||||
//The following test cases are associated with Notebook Pages
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
//The following test cases are associated with Notebook Pages
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
//Test will need to be implemented after a refactor in #5713
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip('Delete page popup is removed properly on clicking dropdown again', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/5713'
|
||||
});
|
||||
// Expand sidebar and add a second page
|
||||
await page.locator('.c-notebook__toggle-nav-button').click();
|
||||
await page.locator('text=Page Add >> button').click();
|
||||
});
|
||||
//Test will need to be implemented after a refactor in #5713
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip('Delete page popup is removed properly on clicking dropdown again', async ({
|
||||
page
|
||||
}) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/5713'
|
||||
});
|
||||
// Expand sidebar and add a second page
|
||||
await page.locator('.c-notebook__toggle-nav-button').click();
|
||||
await page.locator('text=Page Add >> button').click();
|
||||
|
||||
// Click on the 2nd page dropdown button and expect the Delete Page option to appear
|
||||
await page.locator('button[title="Open context menu"]').nth(2).click();
|
||||
await expect(page.locator('text=Delete Page')).toBeEnabled();
|
||||
// Clicking on the same page a second time causes the same Delete Page option to recreate
|
||||
await page.locator('button[title="Open context menu"]').nth(2).click();
|
||||
await expect(page.locator('text=Delete Page')).toBeEnabled();
|
||||
// Clicking on the first page causes the first delete button to detach and recreate on the first page
|
||||
await page.locator('button[title="Open context menu"]').nth(1).click();
|
||||
const numOfDeletePagePopups = await page.locator('li[title="Delete Page"]').count();
|
||||
expect(numOfDeletePagePopups).toBe(1);
|
||||
});
|
||||
test.fixme('Page selection operations and associated behavior', async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Delete existing Page
|
||||
//New 'Unnamed Page' automatically created
|
||||
//Create 6 total Pages without a default page
|
||||
//Select 3rd
|
||||
//Delete 3rd
|
||||
//First is now selected
|
||||
//Set 3rd as default
|
||||
//Select 2nd page
|
||||
//Delete 2nd page
|
||||
//3rd (default) is now selected
|
||||
//Set 3rd as default page
|
||||
//Select 3rd (default) page
|
||||
//Delete 3rd page
|
||||
//First is now selected and there is no default notebook
|
||||
});
|
||||
test.fixme('Page rename operations', async ({ page }) => {
|
||||
// Create a new notebook
|
||||
// Add a page
|
||||
// Rename the page but do not confirm
|
||||
// Keyboard press 'Escape'
|
||||
// Verify that the page name reverts to the default name
|
||||
// Rename the page but do not confirm
|
||||
// Keyboard press 'Enter'
|
||||
// Verify that the page name is updated
|
||||
// Rename the page to "" (empty string)
|
||||
// Keyboard press 'Enter' to confirm
|
||||
// Verify that the page name reverts to the default name
|
||||
// Rename the page to something long that overflows the text box
|
||||
// Verify that the page name is not truncated while input is active
|
||||
// Confirm the page name edit
|
||||
// Verify that the page name is truncated now that input is not active
|
||||
});
|
||||
// Click on the 2nd page dropdown button and expect the Delete Page option to appear
|
||||
await page.locator('button[title="Open context menu"]').nth(2).click();
|
||||
await expect(page.locator('text=Delete Page')).toBeEnabled();
|
||||
// Clicking on the same page a second time causes the same Delete Page option to recreate
|
||||
await page.locator('button[title="Open context menu"]').nth(2).click();
|
||||
await expect(page.locator('text=Delete Page')).toBeEnabled();
|
||||
// Clicking on the first page causes the first delete button to detach and recreate on the first page
|
||||
await page.locator('button[title="Open context menu"]').nth(1).click();
|
||||
const numOfDeletePagePopups = await page.locator('li[title="Delete Page"]').count();
|
||||
expect(numOfDeletePagePopups).toBe(1);
|
||||
});
|
||||
test.fixme('Page selection operations and associated behavior', async ({ page }) => {
|
||||
//Create new notebook A
|
||||
//Delete existing Page
|
||||
//New 'Unnamed Page' automatically created
|
||||
//Create 6 total Pages without a default page
|
||||
//Select 3rd
|
||||
//Delete 3rd
|
||||
//First is now selected
|
||||
//Set 3rd as default
|
||||
//Select 2nd page
|
||||
//Delete 2nd page
|
||||
//3rd (default) is now selected
|
||||
//Set 3rd as default page
|
||||
//Select 3rd (default) page
|
||||
//Delete 3rd page
|
||||
//First is now selected and there is no default notebook
|
||||
});
|
||||
test.fixme('Page rename operations', async ({ page }) => {
|
||||
// Create a new notebook
|
||||
// Add a page
|
||||
// Rename the page but do not confirm
|
||||
// Keyboard press 'Escape'
|
||||
// Verify that the page name reverts to the default name
|
||||
// Rename the page but do not confirm
|
||||
// Keyboard press 'Enter'
|
||||
// Verify that the page name is updated
|
||||
// Rename the page to "" (empty string)
|
||||
// Keyboard press 'Enter' to confirm
|
||||
// Verify that the page name reverts to the default name
|
||||
// Rename the page to something long that overflows the text box
|
||||
// Verify that the page name is not truncated while input is active
|
||||
// Confirm the page name edit
|
||||
// Verify that the page name is truncated now that input is not active
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Notebook export tests', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
// Create Notebook
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
test('can export notebook as text', async ({ page }) => {
|
||||
await nbUtils.enterTextEntry(page, `Foo bar entry`);
|
||||
// Click on 3 Dot Menu
|
||||
await page.locator('button[title="More options"]').click();
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
});
|
||||
test('can export notebook as text', async ({ page }) => {
|
||||
await nbUtils.enterTextEntry(page, `Foo bar entry`);
|
||||
// Click on 3 Dot Menu
|
||||
await page.locator('button[title="More options"]').click();
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
|
||||
await page.getByRole('menuitem', { name: /Export Notebook as Text/ }).click();
|
||||
await page.getByRole('menuitem', { name: /Export Notebook as Text/ }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
const download = await downloadPromise;
|
||||
const readStream = await download.createReadStream();
|
||||
const exportedText = await streamToString(readStream);
|
||||
expect(exportedText).toContain('Foo bar entry');
|
||||
});
|
||||
test.fixme('can export multiple notebook entries as text ', async ({ page }) => {});
|
||||
test.fixme('can export all notebook entry metdata', async ({ page }) => {});
|
||||
test.fixme('can export all notebook tags', async ({ page }) => {});
|
||||
test.fixme('can export all notebook snapshots', async ({ page }) => {});
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
const download = await downloadPromise;
|
||||
const readStream = await download.createReadStream();
|
||||
const exportedText = await streamToString(readStream);
|
||||
expect(exportedText).toContain('Foo bar entry');
|
||||
});
|
||||
test.fixme('can export multiple notebook entries as text ', async ({ page }) => {});
|
||||
test.fixme('can export all notebook entry metdata', async ({ page }) => {});
|
||||
test.fixme('can export all notebook tags', async ({ page }) => {});
|
||||
test.fixme('can export all notebook snapshots', async ({ page }) => {});
|
||||
});
|
||||
|
||||
test.describe('Notebook search tests', () => {
|
||||
test.fixme('Can search for a single result', async ({ page }) => {});
|
||||
test.fixme('Can search for many results', async ({ page }) => {});
|
||||
test.fixme('Can search for new and recently modified entries', async ({ page }) => {});
|
||||
test.fixme('Can search for section text', async ({ page }) => {});
|
||||
test.fixme('Can search for page text', async ({ page }) => {});
|
||||
test.fixme('Can search for entry text', async ({ page }) => {});
|
||||
test.fixme('Can search for a single result', async ({ page }) => {});
|
||||
test.fixme('Can search for many results', async ({ page }) => {});
|
||||
test.fixme('Can search for new and recently modified entries', async ({ page }) => {});
|
||||
test.fixme('Can search for section text', async ({ page }) => {});
|
||||
test.fixme('Can search for page text', async ({ page }) => {});
|
||||
test.fixme('Can search for entry text', async ({ page }) => {});
|
||||
});
|
||||
|
||||
test.describe('Notebook entry tests', () => {
|
||||
// Create Notebook with URL Whitelist
|
||||
let notebookObject;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
await page.addInitScript({ path: path.join(__dirname, '../../../../helper/', 'addInitNotebookWithUrls.js') });
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
notebookObject = await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
// Create Notebook with URL Whitelist
|
||||
let notebookObject;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
await page.addInitScript({
|
||||
path: path.join(__dirname, '../../../../helper/', 'addInitNotebookWithUrls.js')
|
||||
});
|
||||
test('When a new entry is created, it should be focused and selected', async ({ page }) => {
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Click .c-notebook__drag-area
|
||||
await page.locator('.c-notebook__drag-area').click();
|
||||
await expect(page.locator('[aria-label="Notebook Entry Input"]')).toBeVisible();
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toHaveClass(/is-selected/);
|
||||
notebookObject = await createDomainObjectWithDefaults(page, {
|
||||
type: NOTEBOOK_NAME
|
||||
});
|
||||
test('When an object is dropped into a notebook, a new entry is created and it should be focused @unstable', async ({ page }) => {
|
||||
// Create Overlay Plot
|
||||
const overlayPlot = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Overlay Plot'
|
||||
});
|
||||
});
|
||||
test('When a new entry is created, it should be focused and selected', async ({ page }) => {
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
await page.getByRole('treeitem', { name: overlayPlot.name }).dragTo(page.locator('.c-notebook__drag-area'));
|
||||
|
||||
const embed = page.locator('.c-ne__embed__link');
|
||||
const embedName = await embed.innerText();
|
||||
|
||||
await expect(embed).toHaveClass(/icon-plot-overlay/);
|
||||
expect(embedName).toBe(overlayPlot.name);
|
||||
// Click .c-notebook__drag-area
|
||||
await page.locator('.c-notebook__drag-area').click();
|
||||
await expect(page.locator('[aria-label="Notebook Entry Input"]')).toBeVisible();
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toHaveClass(/is-selected/);
|
||||
});
|
||||
test('When an object is dropped into a notebook, a new entry is created and it should be focused @unstable', async ({
|
||||
page
|
||||
}) => {
|
||||
// Create Overlay Plot
|
||||
const overlayPlot = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Overlay Plot'
|
||||
});
|
||||
test('When an object is dropped into a notebooks existing entry, it should be focused @unstable', async ({ page }) => {
|
||||
// Create Overlay Plot
|
||||
const overlayPlot = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Overlay Plot'
|
||||
});
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
await nbUtils.enterTextEntry(page, 'Entry to drop into');
|
||||
await page.getByRole('treeitem', { name: overlayPlot.name }).dragTo(page.locator('text=Entry to drop into'));
|
||||
await page
|
||||
.getByRole('treeitem', { name: overlayPlot.name })
|
||||
.dragTo(page.locator('.c-notebook__drag-area'));
|
||||
|
||||
const existingEntry = page.locator('.c-ne__content', {
|
||||
has: page.locator('text="Entry to drop into"')
|
||||
});
|
||||
const embed = existingEntry.locator('.c-ne__embed__link');
|
||||
const embedName = await embed.innerText();
|
||||
const embed = page.locator('.c-ne__embed__link');
|
||||
const embedName = await embed.innerText();
|
||||
|
||||
await expect(embed).toHaveClass(/icon-plot-overlay/);
|
||||
expect(embedName).toBe(overlayPlot.name);
|
||||
await expect(embed).toHaveClass(/icon-plot-overlay/);
|
||||
expect(embedName).toBe(overlayPlot.name);
|
||||
});
|
||||
test('When an object is dropped into a notebooks existing entry, it should be focused @unstable', async ({
|
||||
page
|
||||
}) => {
|
||||
// Create Overlay Plot
|
||||
const overlayPlot = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Overlay Plot'
|
||||
});
|
||||
test.fixme('new entries persist through navigation events without save', async ({ page }) => {});
|
||||
test('previous and new entries can be deleted', async ({ page }) => {
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
await page.hover('text="First Entry"');
|
||||
await page.click('button[title="Delete this entry"]');
|
||||
await page.getByRole('button', { name: 'Ok' }).filter({ hasText: 'Ok' }).click();
|
||||
await expect(page.locator('text="First Entry"')).toBeHidden();
|
||||
await nbUtils.enterTextEntry(page, 'Another First Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Second Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Third Entry');
|
||||
await page.hover('[aria-label="Notebook Entry"] >> nth=2');
|
||||
await page.click('button[title="Delete this entry"] >> nth=2');
|
||||
await page.getByRole('button', { name: 'Ok' }).filter({ hasText: 'Ok' }).click();
|
||||
await expect(page.locator('text="Third Entry"')).toBeHidden();
|
||||
await expect(page.locator('text="Another First Entry"')).toBeVisible();
|
||||
await expect(page.locator('text="Second Entry"')).toBeVisible();
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
await nbUtils.enterTextEntry(page, 'Entry to drop into');
|
||||
await page
|
||||
.getByRole('treeitem', { name: overlayPlot.name })
|
||||
.dragTo(page.locator('text=Entry to drop into'));
|
||||
|
||||
const existingEntry = page.locator('.c-ne__content', {
|
||||
has: page.locator('text="Entry to drop into"')
|
||||
});
|
||||
test('when a valid link is entered into a notebook entry, it becomes clickable when viewing', async ({ page }) => {
|
||||
const TEST_LINK = 'http://www.google.com';
|
||||
const embed = existingEntry.locator('.c-ne__embed__link');
|
||||
const embedName = await embed.innerText();
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
await expect(embed).toHaveClass(/icon-plot-overlay/);
|
||||
expect(embedName).toBe(overlayPlot.name);
|
||||
});
|
||||
test.fixme('new entries persist through navigation events without save', async ({ page }) => {});
|
||||
test('previous and new entries can be deleted', async ({ page }) => {
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
await page.hover('text="First Entry"');
|
||||
await page.click('button[title="Delete this entry"]');
|
||||
await page.getByRole('button', { name: 'Ok' }).filter({ hasText: 'Ok' }).click();
|
||||
await expect(page.locator('text="First Entry"')).toBeHidden();
|
||||
await nbUtils.enterTextEntry(page, 'Another First Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Second Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Third Entry');
|
||||
await page.hover('[aria-label="Notebook Entry"] >> nth=2');
|
||||
await page.click('button[title="Delete this entry"] >> nth=2');
|
||||
await page.getByRole('button', { name: 'Ok' }).filter({ hasText: 'Ok' }).click();
|
||||
await expect(page.locator('text="Third Entry"')).toBeHidden();
|
||||
await expect(page.locator('text="Another First Entry"')).toBeVisible();
|
||||
await expect(page.locator('text="Second Entry"')).toBeVisible();
|
||||
});
|
||||
test('when a valid link is entered into a notebook entry, it becomes clickable when viewing', async ({
|
||||
page
|
||||
}) => {
|
||||
const TEST_LINK = 'http://www.google.com';
|
||||
|
||||
await nbUtils.enterTextEntry(page, `This should be a link: ${TEST_LINK} is it?`);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
const validLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
// Start waiting for popup before clicking. Note no await.
|
||||
const popupPromise = page.waitForEvent('popup');
|
||||
await nbUtils.enterTextEntry(page, `This should be a link: ${TEST_LINK} is it?`);
|
||||
|
||||
await validLink.click();
|
||||
const popup = await popupPromise;
|
||||
const validLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
|
||||
// Wait for the popup to load.
|
||||
await popup.waitForLoadState();
|
||||
expect.soft(popup.url()).toContain('www.google.com');
|
||||
// Start waiting for popup before clicking. Note no await.
|
||||
const popupPromise = page.waitForEvent('popup');
|
||||
|
||||
expect(await validLink.count()).toBe(1);
|
||||
});
|
||||
test('when an invalid link is entered into a notebook entry, it does not become clickable when viewing', async ({ page }) => {
|
||||
const TEST_LINK = 'www.google.com';
|
||||
await validLink.click();
|
||||
const popup = await popupPromise;
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
// Wait for the popup to load.
|
||||
await popup.waitForLoadState();
|
||||
expect.soft(popup.url()).toContain('www.google.com');
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
expect(await validLink.count()).toBe(1);
|
||||
});
|
||||
test('when an invalid link is entered into a notebook entry, it does not become clickable when viewing', async ({
|
||||
page
|
||||
}) => {
|
||||
const TEST_LINK = 'www.google.com';
|
||||
|
||||
await nbUtils.enterTextEntry(page, `This should NOT be a link: ${TEST_LINK} is it?`);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
const invalidLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
expect(await invalidLink.count()).toBe(0);
|
||||
});
|
||||
test('when a link is entered, but it is not in the whitelisted urls, it does not become clickable when viewing', async ({ page }) => {
|
||||
const TEST_LINK = 'http://www.bing.com';
|
||||
await nbUtils.enterTextEntry(page, `This should NOT be a link: ${TEST_LINK} is it?`);
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
const invalidLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
expect(await invalidLink.count()).toBe(0);
|
||||
});
|
||||
test('when a link is entered, but it is not in the whitelisted urls, it does not become clickable when viewing', async ({
|
||||
page
|
||||
}) => {
|
||||
const TEST_LINK = 'http://www.bing.com';
|
||||
|
||||
await nbUtils.enterTextEntry(page, `This should NOT be a link: ${TEST_LINK} is it?`);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
const invalidLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
expect(await invalidLink.count()).toBe(0);
|
||||
});
|
||||
test('when a valid link with a subdomain and a valid domain in the whitelisted urls is entered into a notebook entry, it becomes clickable when viewing', async ({ page }) => {
|
||||
const INVALID_TEST_LINK = 'http://bing.google.com';
|
||||
await nbUtils.enterTextEntry(page, `This should NOT be a link: ${TEST_LINK} is it?`);
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
const invalidLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
expect(await invalidLink.count()).toBe(0);
|
||||
});
|
||||
test('when a valid link with a subdomain and a valid domain in the whitelisted urls is entered into a notebook entry, it becomes clickable when viewing', async ({
|
||||
page
|
||||
}) => {
|
||||
const INVALID_TEST_LINK = 'http://bing.google.com';
|
||||
|
||||
await nbUtils.enterTextEntry(page, `This should be a link: ${INVALID_TEST_LINK} is it?`);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
const validLink = page.locator(`a[href="${INVALID_TEST_LINK}"]`);
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
expect(await validLink.count()).toBe(1);
|
||||
});
|
||||
test('when a valid secure link is entered into a notebook entry, it becomes clickable when viewing', async ({ page }) => {
|
||||
const TEST_LINK = 'https://www.google.com';
|
||||
await nbUtils.enterTextEntry(page, `This should be a link: ${INVALID_TEST_LINK} is it?`);
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
const validLink = page.locator(`a[href="${INVALID_TEST_LINK}"]`);
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
expect(await validLink.count()).toBe(1);
|
||||
});
|
||||
test('when a valid secure link is entered into a notebook entry, it becomes clickable when viewing', async ({
|
||||
page
|
||||
}) => {
|
||||
const TEST_LINK = 'https://www.google.com';
|
||||
|
||||
await nbUtils.enterTextEntry(page, `This should be a link: ${TEST_LINK} is it?`);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
const validLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
// Start waiting for popup before clicking. Note no await.
|
||||
const popupPromise = page.waitForEvent('popup');
|
||||
await nbUtils.enterTextEntry(page, `This should be a link: ${TEST_LINK} is it?`);
|
||||
|
||||
await validLink.click();
|
||||
const popup = await popupPromise;
|
||||
const validLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
|
||||
// Wait for the popup to load.
|
||||
await popup.waitForLoadState();
|
||||
expect.soft(popup.url()).toContain('www.google.com');
|
||||
// Start waiting for popup before clicking. Note no await.
|
||||
const popupPromise = page.waitForEvent('popup');
|
||||
|
||||
expect(await validLink.count()).toBe(1);
|
||||
});
|
||||
test('when a nefarious link is entered into a notebook entry, it is sanitized when viewing', async ({ page }) => {
|
||||
const TEST_LINK = 'http://www.google.com?bad=';
|
||||
const TEST_LINK_BAD = `http://www.google.com?bad=<script>alert('gimme your cookies')</script>`;
|
||||
await validLink.click();
|
||||
const popup = await popupPromise;
|
||||
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
// Wait for the popup to load.
|
||||
await popup.waitForLoadState();
|
||||
expect.soft(popup.url()).toContain('www.google.com');
|
||||
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
expect(await validLink.count()).toBe(1);
|
||||
});
|
||||
test('when a nefarious link is entered into a notebook entry, it is sanitized when viewing', async ({
|
||||
page
|
||||
}) => {
|
||||
const TEST_LINK = 'http://www.google.com?bad=';
|
||||
const TEST_LINK_BAD = `http://www.google.com?bad=<script>alert('gimme your cookies')</script>`;
|
||||
|
||||
await nbUtils.enterTextEntry(page, `This should be a link, BUT not a bad link: ${TEST_LINK_BAD} is it?`);
|
||||
// Navigate to the notebook object
|
||||
await page.goto(notebookObject.url);
|
||||
|
||||
const sanitizedLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
const unsanitizedLink = page.locator(`a[href="${TEST_LINK_BAD}"]`);
|
||||
// Reveal the notebook in the tree
|
||||
await page.getByTitle('Show selected item in tree').click();
|
||||
|
||||
expect.soft(await sanitizedLink.count()).toBe(1);
|
||||
expect(await unsanitizedLink.count()).toBe(0);
|
||||
});
|
||||
await nbUtils.enterTextEntry(
|
||||
page,
|
||||
`This should be a link, BUT not a bad link: ${TEST_LINK_BAD} is it?`
|
||||
);
|
||||
|
||||
const sanitizedLink = page.locator(`a[href="${TEST_LINK}"]`);
|
||||
const unsanitizedLink = page.locator(`a[href="${TEST_LINK_BAD}"]`);
|
||||
|
||||
expect.soft(await sanitizedLink.count()).toBe(1);
|
||||
expect(await unsanitizedLink.count()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,106 +29,135 @@ const { test, expect } = require('../../../../pluginFixtures');
|
||||
// const nbUtils = require('../../../../helper/notebookUtils');
|
||||
|
||||
test.describe('Snapshot Menu tests', () => {
|
||||
test.fixme('When no default notebook is selected, Snapshot Menu dropdown should only have a single option', async ({ page }) => {
|
||||
// There should be no default notebook
|
||||
// Clear default notebook if exists using `localStorage.setItem('notebook-storage', null);`
|
||||
// refresh page
|
||||
// Click on 'Notebook Snaphot Menu'
|
||||
// 'save to Notebook Snapshots' should be only option there
|
||||
});
|
||||
test.fixme('When default notebook is updated selected, Snapshot Menu dropdown should list it as the newest option', async ({ page }) => {
|
||||
// Create 2a notebooks
|
||||
// Set Notebook A as Default
|
||||
// Open Snapshot Menu and note that Notebook A is listed
|
||||
// Close Snapshot Menu
|
||||
// Set Default Notebook to Notebook B
|
||||
// Open Snapshot Notebook and note that Notebook B is listed
|
||||
// Select Default Notebook Option and verify that Snapshot is added to Notebook B
|
||||
});
|
||||
test.fixme('Can add Snapshots via Snapshot Menu and details are correct', async ({ page }) => {
|
||||
//Note this should be a visual test, too
|
||||
// Create Telemetry object
|
||||
// Create A notebook with many pages and sections.
|
||||
// Set page and section defaults to be between first and last of many. i.e. 3 of 5
|
||||
// Navigate to Telemetry object
|
||||
// Select Default Notebook Option and verify that Snapshot is added to Notebook A
|
||||
// Verify Snapshot Details appear correctly
|
||||
});
|
||||
test.fixme('Snapshots adjust time conductor', async ({ page }) => {
|
||||
// Create Telemetry object
|
||||
// Set Telemetry object's timeconductor to Fixed time with Start and Endtimes are recorded
|
||||
// Embed Telemetry object into notebook
|
||||
// Set Time Conductor to Local clock
|
||||
// Click into embedded telemetry object and verify object appears with same fixed time from record
|
||||
});
|
||||
test.fixme(
|
||||
'When no default notebook is selected, Snapshot Menu dropdown should only have a single option',
|
||||
async ({ page }) => {
|
||||
// There should be no default notebook
|
||||
// Clear default notebook if exists using `localStorage.setItem('notebook-storage', null);`
|
||||
// refresh page
|
||||
// Click on 'Notebook Snaphot Menu'
|
||||
// 'save to Notebook Snapshots' should be only option there
|
||||
}
|
||||
);
|
||||
test.fixme(
|
||||
'When default notebook is updated selected, Snapshot Menu dropdown should list it as the newest option',
|
||||
async ({ page }) => {
|
||||
// Create 2a notebooks
|
||||
// Set Notebook A as Default
|
||||
// Open Snapshot Menu and note that Notebook A is listed
|
||||
// Close Snapshot Menu
|
||||
// Set Default Notebook to Notebook B
|
||||
// Open Snapshot Notebook and note that Notebook B is listed
|
||||
// Select Default Notebook Option and verify that Snapshot is added to Notebook B
|
||||
}
|
||||
);
|
||||
test.fixme('Can add Snapshots via Snapshot Menu and details are correct', async ({ page }) => {
|
||||
//Note this should be a visual test, too
|
||||
// Create Telemetry object
|
||||
// Create A notebook with many pages and sections.
|
||||
// Set page and section defaults to be between first and last of many. i.e. 3 of 5
|
||||
// Navigate to Telemetry object
|
||||
// Select Default Notebook Option and verify that Snapshot is added to Notebook A
|
||||
// Verify Snapshot Details appear correctly
|
||||
});
|
||||
test.fixme('Snapshots adjust time conductor', async ({ page }) => {
|
||||
// Create Telemetry object
|
||||
// Set Telemetry object's timeconductor to Fixed time with Start and Endtimes are recorded
|
||||
// Embed Telemetry object into notebook
|
||||
// Set Time Conductor to Local clock
|
||||
// Click into embedded telemetry object and verify object appears with same fixed time from record
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Snapshot Container tests', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
// const notebook = await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Notebook',
|
||||
// name: "Test Notebook"
|
||||
// });
|
||||
// // Create Overlay Plot
|
||||
// const snapShotObject = await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Overlay Plot',
|
||||
// name: "Dropped Overlay Plot"
|
||||
// });
|
||||
// Create Notebook
|
||||
// const notebook = await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Notebook',
|
||||
// name: "Test Notebook"
|
||||
// });
|
||||
// // Create Overlay Plot
|
||||
// const snapShotObject = await createDomainObjectWithDefaults(page, {
|
||||
// type: 'Overlay Plot',
|
||||
// name: "Dropped Overlay Plot"
|
||||
// });
|
||||
|
||||
await page.getByRole('button', { name: ' Snapshot ' }).click();
|
||||
await page.getByRole('menuitem', { name: ' Save to Notebook Snapshots' }).click();
|
||||
await page.getByRole('button', { name: 'Show' }).click();
|
||||
|
||||
});
|
||||
test.fixme('5 Snapshots can be added to a container', async ({ page }) => {});
|
||||
test.fixme('5 Snapshots can be added to a container and Deleted with Delete All action', async ({ page }) => {});
|
||||
test.fixme('A snapshot can be Deleted from Container with 3 dot action menu', async ({ page }) => {});
|
||||
test.fixme('A snapshot can be Viewed, Annotated, display deleted, and saved from Container with 3 dot action menu', async ({ page }) => {
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More options').click();
|
||||
await page.getByRole('menuitem', { name: ' View Snapshot' }).click();
|
||||
await expect(page.locator('.c-overlay__outer')).toBeVisible();
|
||||
await page.getByTitle('Annotate').click();
|
||||
await expect(page.locator('#snap-annotation-canvas')).toBeVisible();
|
||||
await page.getByRole('button', { name: '' }).click();
|
||||
// await expect(page.locator('#snap-annotation-canvas')).not.toBeVisible();
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await page.getByRole('button', { name: 'Done' }).click();
|
||||
//await expect(await page.locator)
|
||||
});
|
||||
test('A snapshot can be Quick Viewed from Container with 3 dot action menu', async ({ page }) => {
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More options').click();
|
||||
await page.getByRole('menuitem', { name: 'Quick View' }).click();
|
||||
await expect(page.locator('.c-overlay__outer')).toBeVisible();
|
||||
});
|
||||
test.fixme('A snapshot can be Navigated To from Container with 3 dot action menu', async ({ page }) => {});
|
||||
test.fixme('A snapshot can be Navigated To Item in Time from Container with 3 dot action menu', async ({ page }) => {});
|
||||
test.fixme('A snapshot Container can be open and closed', async ({ page }) => {});
|
||||
test.fixme('Can add object to Snapshot container and pull into notebook and create a new entry', async ({ page }) => {
|
||||
//Create Notebook
|
||||
//Create Telemetry Object
|
||||
//From Telemetry Object, use 'save to Notebook Snapshots'
|
||||
//Snapshots indicator should blink, click on it to view snapshots
|
||||
//Navigate to Notebook
|
||||
//Drag and Drop onto droppable area for new entry
|
||||
//New Entry created with given snapshot added
|
||||
//Snapshot removed from container?
|
||||
});
|
||||
test.fixme('Can add object to Snapshot container and pull into notebook and existing entry', async ({ page }) => {
|
||||
//Create Notebook
|
||||
//Create Telemetry Object
|
||||
//From Telemetry Object, use 'save to Notebook Snapshots'
|
||||
//Snapshots indicator should blink, click on it to view snapshots
|
||||
//Navigate to Notebook
|
||||
//Drag and Drop into exiting entry
|
||||
//Existing Entry updated with given snapshot
|
||||
//Snapshot removed from container?
|
||||
});
|
||||
test.fixme('Verify Embedded options for PNG, JPG, and Annotate work correctly', async ({ page }) => {
|
||||
//Add snapshot to container
|
||||
//Verify PNG, JPG, and Annotate buttons work correctly
|
||||
});
|
||||
await page.getByRole('button', { name: ' Snapshot ' }).click();
|
||||
await page.getByRole('menuitem', { name: ' Save to Notebook Snapshots' }).click();
|
||||
await page.getByRole('button', { name: 'Show' }).click();
|
||||
});
|
||||
test.fixme('5 Snapshots can be added to a container', async ({ page }) => {});
|
||||
test.fixme(
|
||||
'5 Snapshots can be added to a container and Deleted with Delete All action',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Deleted from Container with 3 dot action menu',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Viewed, Annotated, display deleted, and saved from Container with 3 dot action menu',
|
||||
async ({ page }) => {
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More options').click();
|
||||
await page.getByRole('menuitem', { name: ' View Snapshot' }).click();
|
||||
await expect(page.locator('.c-overlay__outer')).toBeVisible();
|
||||
await page.getByTitle('Annotate').click();
|
||||
await expect(page.locator('#snap-annotation-canvas')).toBeVisible();
|
||||
await page.getByRole('button', { name: '' }).click();
|
||||
// await expect(page.locator('#snap-annotation-canvas')).not.toBeVisible();
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
await page.getByRole('button', { name: 'Done' }).click();
|
||||
//await expect(await page.locator)
|
||||
}
|
||||
);
|
||||
test('A snapshot can be Quick Viewed from Container with 3 dot action menu', async ({ page }) => {
|
||||
await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More options').click();
|
||||
await page.getByRole('menuitem', { name: 'Quick View' }).click();
|
||||
await expect(page.locator('.c-overlay__outer')).toBeVisible();
|
||||
});
|
||||
test.fixme(
|
||||
'A snapshot can be Navigated To from Container with 3 dot action menu',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme(
|
||||
'A snapshot can be Navigated To Item in Time from Container with 3 dot action menu',
|
||||
async ({ page }) => {}
|
||||
);
|
||||
test.fixme('A snapshot Container can be open and closed', async ({ page }) => {});
|
||||
test.fixme(
|
||||
'Can add object to Snapshot container and pull into notebook and create a new entry',
|
||||
async ({ page }) => {
|
||||
//Create Notebook
|
||||
//Create Telemetry Object
|
||||
//From Telemetry Object, use 'save to Notebook Snapshots'
|
||||
//Snapshots indicator should blink, click on it to view snapshots
|
||||
//Navigate to Notebook
|
||||
//Drag and Drop onto droppable area for new entry
|
||||
//New Entry created with given snapshot added
|
||||
//Snapshot removed from container?
|
||||
}
|
||||
);
|
||||
test.fixme(
|
||||
'Can add object to Snapshot container and pull into notebook and existing entry',
|
||||
async ({ page }) => {
|
||||
//Create Notebook
|
||||
//Create Telemetry Object
|
||||
//From Telemetry Object, use 'save to Notebook Snapshots'
|
||||
//Snapshots indicator should blink, click on it to view snapshots
|
||||
//Navigate to Notebook
|
||||
//Drag and Drop into exiting entry
|
||||
//Existing Entry updated with given snapshot
|
||||
//Snapshot removed from container?
|
||||
}
|
||||
);
|
||||
test.fixme(
|
||||
'Verify Embedded options for PNG, JPG, and Annotate work correctly',
|
||||
async ({ page }) => {
|
||||
//Add snapshot to container
|
||||
//Verify PNG, JPG, and Annotate buttons work correctly
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -29,180 +29,184 @@ const { createDomainObjectWithDefaults } = require('../../../../appActions');
|
||||
const nbUtils = require('../../../../helper/notebookUtils');
|
||||
|
||||
test.describe('Notebook Tests with CouchDB @couchdb', () => {
|
||||
let testNotebook;
|
||||
let testNotebook;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
// Create Notebook
|
||||
testNotebook = await createDomainObjectWithDefaults(page, {type: 'Notebook' });
|
||||
await page.goto(testNotebook.url, { waitUntil: 'networkidle'});
|
||||
// Create Notebook
|
||||
testNotebook = await createDomainObjectWithDefaults(page, { type: 'Notebook' });
|
||||
await page.goto(testNotebook.url, { waitUntil: 'networkidle' });
|
||||
});
|
||||
|
||||
test('Inspect Notebook Entry Network Requests', async ({ page }) => {
|
||||
//Ensure we're on the annotations Tab in the inspector
|
||||
await page.getByText('Annotations').click();
|
||||
// Expand sidebar
|
||||
await page.locator('.c-notebook__toggle-nav-button').click();
|
||||
|
||||
// Collect all request events to count and assert after notebook action
|
||||
let notebookElementsRequests = [];
|
||||
page.on('request', (request) => notebookElementsRequests.push(request));
|
||||
|
||||
//Clicking Add Page generates
|
||||
let [notebookUrlRequest, allDocsRequest] = await Promise.all([
|
||||
// Waits for the next request with the specified url
|
||||
page.waitForRequest(`**/openmct/${testNotebook.uuid}`),
|
||||
page.waitForRequest('**/openmct/_all_docs?include_docs=true'),
|
||||
// Triggers the request
|
||||
page.click('[aria-label="Add Page"]')
|
||||
]);
|
||||
// Ensures that there are no other network requests
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Assert that only two requests are made
|
||||
// Network Requests are:
|
||||
// 1) The actual POST to create the page
|
||||
// 2) The shared worker event from 👆 request
|
||||
expect(notebookElementsRequests.length).toBe(2);
|
||||
|
||||
// Assert on request object
|
||||
expect(notebookUrlRequest.postDataJSON().metadata.name).toBe(testNotebook.name);
|
||||
expect(notebookUrlRequest.postDataJSON().model.persisted).toBeGreaterThanOrEqual(
|
||||
notebookUrlRequest.postDataJSON().model.modified
|
||||
);
|
||||
expect(allDocsRequest.postDataJSON().keys).toContain(testNotebook.uuid);
|
||||
|
||||
// Add an entry
|
||||
// Network Requests are:
|
||||
// 1) The actual POST to create the entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
await page.waitForLoadState('networkidle');
|
||||
expect(notebookElementsRequests.length).toBeLessThanOrEqual(2);
|
||||
|
||||
// Add some tags
|
||||
// Network Requests are for each tag creation are:
|
||||
// 1) Getting the original path of the parent object
|
||||
// 2) Getting the original path of the grandparent object (recursive call)
|
||||
// 3) Creating the annotation/tag object
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
// 5) Mutate notebook domain object's annotationModified property
|
||||
// 6) The shared worker event from 👆 POST request
|
||||
// 7) Notebooks fetching new annotations due to annotationModified changed
|
||||
// 8) The update of the notebook domain's object's modified property
|
||||
// 9) The shared worker event from 👆 POST request
|
||||
// 10) Entry is timestamped
|
||||
// 11) The shared worker event from 👆 POST request
|
||||
|
||||
notebookElementsRequests = [];
|
||||
await addTagAndAwaitNetwork(page, 'Driving');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(11);
|
||||
|
||||
notebookElementsRequests = [];
|
||||
await addTagAndAwaitNetwork(page, 'Drilling');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(11);
|
||||
|
||||
notebookElementsRequests = [];
|
||||
await addTagAndAwaitNetwork(page, 'Science');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(11);
|
||||
|
||||
// Delete all the tags
|
||||
// Network requests are:
|
||||
// 1) Send POST to mutate _delete property to true on annotation with tag
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
// This happens for 3 tags so 12 requests
|
||||
notebookElementsRequests = [];
|
||||
await removeTagAndAwaitNetwork(page, 'Driving');
|
||||
await removeTagAndAwaitNetwork(page, 'Drilling');
|
||||
await removeTagAndAwaitNetwork(page, 'Science');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(12);
|
||||
|
||||
// Add two more pages
|
||||
await page.click('[aria-label="Add Page"]');
|
||||
await page.click('[aria-label="Add Page"]');
|
||||
|
||||
// Add three entries
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Second Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Third Entry');
|
||||
|
||||
// Add three tags
|
||||
await addTagAndAwaitNetwork(page, 'Science');
|
||||
await addTagAndAwaitNetwork(page, 'Drilling');
|
||||
await addTagAndAwaitNetwork(page, 'Driving');
|
||||
|
||||
// Add a fourth entry
|
||||
// Network requests are:
|
||||
// 1) Send POST to add new entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'Fourth Entry');
|
||||
page.waitForLoadState('networkidle');
|
||||
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
|
||||
|
||||
// Add a fifth entry
|
||||
// Network requests are:
|
||||
// 1) Send POST to add new entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'Fifth Entry');
|
||||
page.waitForLoadState('networkidle');
|
||||
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
|
||||
|
||||
// Add a sixth entry
|
||||
// 1) Send POST to add new entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'Sixth Entry');
|
||||
page.waitForLoadState('networkidle');
|
||||
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
|
||||
});
|
||||
|
||||
test('Search tests', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/akhenry/openmct-yamcs/issues/69'
|
||||
});
|
||||
await page.getByText('Annotations').click();
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
|
||||
test('Inspect Notebook Entry Network Requests', async ({ page }) => {
|
||||
//Ensure we're on the annotations Tab in the inspector
|
||||
await page.getByText('Annotations').click();
|
||||
// Expand sidebar
|
||||
await page.locator('.c-notebook__toggle-nav-button').click();
|
||||
// Add three tags
|
||||
await addTagAndAwaitNetwork(page, 'Science');
|
||||
await addTagAndAwaitNetwork(page, 'Drilling');
|
||||
await addTagAndAwaitNetwork(page, 'Driving');
|
||||
|
||||
// Collect all request events to count and assert after notebook action
|
||||
let notebookElementsRequests = [];
|
||||
page.on('request', (request) => notebookElementsRequests.push(request));
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
//Partial match for "Science" should only return Science
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]').first()).toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Search Result"]').first()).not.toContainText('Driving');
|
||||
await expect(page.locator('[aria-label="Search Result"]').first()).not.toContainText(
|
||||
'Drilling'
|
||||
);
|
||||
|
||||
//Clicking Add Page generates
|
||||
let [notebookUrlRequest, allDocsRequest] = await Promise.all([
|
||||
// Waits for the next request with the specified url
|
||||
page.waitForRequest(`**/openmct/${testNotebook.uuid}`),
|
||||
page.waitForRequest('**/openmct/_all_docs?include_docs=true'),
|
||||
// Triggers the request
|
||||
page.click('[aria-label="Add Page"]')
|
||||
]);
|
||||
// Ensures that there are no other network requests
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Assert that only two requests are made
|
||||
// Network Requests are:
|
||||
// 1) The actual POST to create the page
|
||||
// 2) The shared worker event from 👆 request
|
||||
expect(notebookElementsRequests.length).toBe(2);
|
||||
|
||||
// Assert on request object
|
||||
expect(notebookUrlRequest.postDataJSON().metadata.name).toBe(testNotebook.name);
|
||||
expect(notebookUrlRequest.postDataJSON().model.persisted).toBeGreaterThanOrEqual(notebookUrlRequest.postDataJSON().model.modified);
|
||||
expect(allDocsRequest.postDataJSON().keys).toContain(testNotebook.uuid);
|
||||
|
||||
// Add an entry
|
||||
// Network Requests are:
|
||||
// 1) The actual POST to create the entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
await page.waitForLoadState('networkidle');
|
||||
expect(notebookElementsRequests.length).toBeLessThanOrEqual(2);
|
||||
|
||||
// Add some tags
|
||||
// Network Requests are for each tag creation are:
|
||||
// 1) Getting the original path of the parent object
|
||||
// 2) Getting the original path of the grandparent object (recursive call)
|
||||
// 3) Creating the annotation/tag object
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
// 5) Mutate notebook domain object's annotationModified property
|
||||
// 6) The shared worker event from 👆 POST request
|
||||
// 7) Notebooks fetching new annotations due to annotationModified changed
|
||||
// 8) The update of the notebook domain's object's modified property
|
||||
// 9) The shared worker event from 👆 POST request
|
||||
// 10) Entry is timestamped
|
||||
// 11) The shared worker event from 👆 POST request
|
||||
|
||||
notebookElementsRequests = [];
|
||||
await addTagAndAwaitNetwork(page, 'Driving');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(11);
|
||||
|
||||
notebookElementsRequests = [];
|
||||
await addTagAndAwaitNetwork(page, 'Drilling');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(11);
|
||||
|
||||
notebookElementsRequests = [];
|
||||
await addTagAndAwaitNetwork(page, 'Science');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(11);
|
||||
|
||||
// Delete all the tags
|
||||
// Network requests are:
|
||||
// 1) Send POST to mutate _delete property to true on annotation with tag
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
// This happens for 3 tags so 12 requests
|
||||
notebookElementsRequests = [];
|
||||
await removeTagAndAwaitNetwork(page, 'Driving');
|
||||
await removeTagAndAwaitNetwork(page, 'Drilling');
|
||||
await removeTagAndAwaitNetwork(page, 'Science');
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(12);
|
||||
|
||||
// Add two more pages
|
||||
await page.click('[aria-label="Add Page"]');
|
||||
await page.click('[aria-label="Add Page"]');
|
||||
|
||||
// Add three entries
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Second Entry');
|
||||
await nbUtils.enterTextEntry(page, 'Third Entry');
|
||||
|
||||
// Add three tags
|
||||
await addTagAndAwaitNetwork(page, 'Science');
|
||||
await addTagAndAwaitNetwork(page, 'Drilling');
|
||||
await addTagAndAwaitNetwork(page, 'Driving');
|
||||
|
||||
// Add a fourth entry
|
||||
// Network requests are:
|
||||
// 1) Send POST to add new entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'Fourth Entry');
|
||||
page.waitForLoadState('networkidle');
|
||||
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
|
||||
|
||||
// Add a fifth entry
|
||||
// Network requests are:
|
||||
// 1) Send POST to add new entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'Fifth Entry');
|
||||
page.waitForLoadState('networkidle');
|
||||
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
|
||||
|
||||
// Add a sixth entry
|
||||
// 1) Send POST to add new entry
|
||||
// 2) The shared worker event from 👆 POST request
|
||||
// 3) Timestamp update on entry
|
||||
// 4) The shared worker event from 👆 POST request
|
||||
notebookElementsRequests = [];
|
||||
await nbUtils.enterTextEntry(page, 'Sixth Entry');
|
||||
page.waitForLoadState('networkidle');
|
||||
|
||||
expect(filterNonFetchRequests(notebookElementsRequests).length).toBeLessThanOrEqual(4);
|
||||
});
|
||||
|
||||
test('Search tests', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/akhenry/openmct-yamcs/issues/69'
|
||||
});
|
||||
await page.getByText('Annotations').click();
|
||||
await nbUtils.enterTextEntry(page, 'First Entry');
|
||||
|
||||
// Add three tags
|
||||
await addTagAndAwaitNetwork(page, 'Science');
|
||||
await addTagAndAwaitNetwork(page, 'Drilling');
|
||||
await addTagAndAwaitNetwork(page, 'Driving');
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
//Partial match for "Science" should only return Science
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]').first()).toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Search Result"]').first()).not.toContainText("Driving");
|
||||
await expect(page.locator('[aria-label="Search Result"]').first()).not.toContainText("Drilling");
|
||||
|
||||
//Searching for a tag which does not exist should return an empty result
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Xq');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
});
|
||||
//Searching for a tag which does not exist should return an empty result
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Xq');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
// Try to reduce indeterminism of browser requests by only returning fetch requests.
|
||||
// Filter out preflight CORS, fetching stylesheets, page icons, etc. that can occur during tests
|
||||
function filterNonFetchRequests(requests) {
|
||||
return requests.filter(request => {
|
||||
return (request.resourceType() === 'fetch');
|
||||
});
|
||||
return requests.filter((request) => {
|
||||
return request.resourceType() === 'fetch';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -212,17 +216,17 @@ function filterNonFetchRequests(requests) {
|
||||
* @param {string} tagName
|
||||
*/
|
||||
async function addTagAndAwaitNetwork(page, tagName) {
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
await Promise.all([
|
||||
// Waits for the next request with the specified url
|
||||
page.waitForRequest('**/openmct/_all_docs?include_docs=true'),
|
||||
// Triggers the request
|
||||
page.locator(`[aria-label="Autocomplete Options"] >> text=${tagName}`).click(),
|
||||
expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeVisible()
|
||||
]);
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
await Promise.all([
|
||||
// Waits for the next request with the specified url
|
||||
page.waitForRequest('**/openmct/_all_docs?include_docs=true'),
|
||||
// Triggers the request
|
||||
page.locator(`[aria-label="Autocomplete Options"] >> text=${tagName}`).click(),
|
||||
expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeVisible()
|
||||
]);
|
||||
await page.waitForLoadState('networkidle');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,12 +236,14 @@ async function addTagAndAwaitNetwork(page, tagName) {
|
||||
* @param {string} tagName
|
||||
*/
|
||||
async function removeTagAndAwaitNetwork(page, tagName) {
|
||||
await page.hover(`[aria-label="Tag"]:has-text("${tagName}")`);
|
||||
await Promise.all([
|
||||
page.locator(`[aria-label="Remove tag ${tagName}"]`).click(),
|
||||
//With this pattern, we're awaiting the response but asserting on the request payload.
|
||||
page.waitForResponse(resp => resp.request().postData().includes(`"_deleted":true`) && resp.status() === 201)
|
||||
]);
|
||||
await expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeHidden();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await page.hover(`[aria-label="Tag"]:has-text("${tagName}")`);
|
||||
await Promise.all([
|
||||
page.locator(`[aria-label="Remove tag ${tagName}"]`).click(),
|
||||
//With this pattern, we're awaiting the response but asserting on the request payload.
|
||||
page.waitForResponse(
|
||||
(resp) => resp.request().postData().includes(`"_deleted":true`) && resp.status() === 201
|
||||
)
|
||||
]);
|
||||
await expect(page.locator(`[aria-label="Tag"]:has-text("${tagName}")`)).toBeHidden();
|
||||
await page.waitForLoadState('networkidle');
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
*****************************************************************************/
|
||||
/* global __dirname */
|
||||
const { test, expect, streamToString } = require('../../../../pluginFixtures');
|
||||
const { openObjectTreeContextMenu, createDomainObjectWithDefaults } = require('../../../../appActions');
|
||||
const {
|
||||
openObjectTreeContextMenu,
|
||||
createDomainObjectWithDefaults
|
||||
} = require('../../../../appActions');
|
||||
const path = require('path');
|
||||
const nbUtils = require('../../../../helper/notebookUtils');
|
||||
|
||||
@@ -30,183 +33,186 @@ const TEST_TEXT_NAME = 'Test Page';
|
||||
const CUSTOM_NAME = 'CUSTOM_NAME';
|
||||
|
||||
test.describe('Restricted Notebook', () => {
|
||||
let notebook;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
notebook = await startAndAddRestrictedNotebookObject(page);
|
||||
});
|
||||
let notebook;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
notebook = await startAndAddRestrictedNotebookObject(page);
|
||||
});
|
||||
|
||||
test('Can be renamed @addInit', async ({ page }) => {
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText(`${notebook.name}`);
|
||||
});
|
||||
test('Can be renamed @addInit', async ({ page }) => {
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText(`${notebook.name}`);
|
||||
});
|
||||
|
||||
test('Can be deleted if there are no locked pages @addInit', async ({ page }) => {
|
||||
await openObjectTreeContextMenu(page, notebook.url);
|
||||
test('Can be deleted if there are no locked pages @addInit', async ({ page }) => {
|
||||
await openObjectTreeContextMenu(page, notebook.url);
|
||||
|
||||
const menuOptions = page.locator('.c-menu ul');
|
||||
await expect.soft(menuOptions).toContainText('Remove');
|
||||
const menuOptions = page.locator('.c-menu ul');
|
||||
await expect.soft(menuOptions).toContainText('Remove');
|
||||
|
||||
const restrictedNotebookTreeObject = page.locator(`a:has-text("${notebook.name}")`);
|
||||
const restrictedNotebookTreeObject = page.locator(`a:has-text("${notebook.name}")`);
|
||||
|
||||
// notebook tree object exists
|
||||
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(1);
|
||||
// notebook tree object exists
|
||||
expect.soft(await restrictedNotebookTreeObject.count()).toEqual(1);
|
||||
|
||||
// Click Remove Text
|
||||
await page.locator('li[role="menuitem"]:has-text("Remove")').click();
|
||||
// Click Remove Text
|
||||
await page.locator('li[role="menuitem"]:has-text("Remove")').click();
|
||||
|
||||
// Click 'OK' on confirmation window and wait for save banner to appear
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.locator('button:has-text("OK")').click(),
|
||||
page.waitForSelector('.c-message-banner__message')
|
||||
]);
|
||||
// Click 'OK' on confirmation window and wait for save banner to appear
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.locator('button:has-text("OK")').click(),
|
||||
page.waitForSelector('.c-message-banner__message')
|
||||
]);
|
||||
|
||||
// has been deleted
|
||||
expect(await restrictedNotebookTreeObject.count()).toEqual(0);
|
||||
});
|
||||
// has been deleted
|
||||
expect(await restrictedNotebookTreeObject.count()).toEqual(0);
|
||||
});
|
||||
|
||||
test('Can be locked if at least one page has one entry @addInit', async ({ page }) => {
|
||||
|
||||
await nbUtils.enterTextEntry(page, TEST_TEXT);
|
||||
|
||||
const commitButton = page.locator('button:has-text("Commit Entries")');
|
||||
expect(await commitButton.count()).toEqual(1);
|
||||
});
|
||||
test('Can be locked if at least one page has one entry @addInit', async ({ page }) => {
|
||||
await nbUtils.enterTextEntry(page, TEST_TEXT);
|
||||
|
||||
const commitButton = page.locator('button:has-text("Commit Entries")');
|
||||
expect(await commitButton.count()).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Restricted Notebook with at least one entry and with the page locked @addInit', () => {
|
||||
let notebook;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
notebook = await startAndAddRestrictedNotebookObject(page);
|
||||
await nbUtils.enterTextEntry(page, TEST_TEXT);
|
||||
await lockPage(page);
|
||||
let notebook;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
notebook = await startAndAddRestrictedNotebookObject(page);
|
||||
await nbUtils.enterTextEntry(page, TEST_TEXT);
|
||||
await lockPage(page);
|
||||
|
||||
// open sidebar
|
||||
await page.locator('button.c-notebook__toggle-nav-button').click();
|
||||
});
|
||||
// open sidebar
|
||||
await page.locator('button.c-notebook__toggle-nav-button').click();
|
||||
});
|
||||
|
||||
test('Locked page should now be in a locked state @addInit @unstable', async ({ page }, testInfo) => {
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip(testInfo.project === 'chrome-beta', "Test is unreliable on chrome-beta");
|
||||
// main lock message on page
|
||||
const lockMessage = page.locator('text=This page has been committed and cannot be modified or removed');
|
||||
expect.soft(await lockMessage.count()).toEqual(1);
|
||||
test('Locked page should now be in a locked state @addInit @unstable', async ({
|
||||
page
|
||||
}, testInfo) => {
|
||||
// eslint-disable-next-line playwright/no-skipped-test
|
||||
test.skip(testInfo.project === 'chrome-beta', 'Test is unreliable on chrome-beta');
|
||||
// main lock message on page
|
||||
const lockMessage = page.locator(
|
||||
'text=This page has been committed and cannot be modified or removed'
|
||||
);
|
||||
expect.soft(await lockMessage.count()).toEqual(1);
|
||||
|
||||
// lock icon on page in sidebar
|
||||
const pageLockIcon = page.locator('ul.c-notebook__pages li div.icon-lock');
|
||||
expect.soft(await pageLockIcon.count()).toEqual(1);
|
||||
// lock icon on page in sidebar
|
||||
const pageLockIcon = page.locator('ul.c-notebook__pages li div.icon-lock');
|
||||
expect.soft(await pageLockIcon.count()).toEqual(1);
|
||||
|
||||
// no way to remove a restricted notebook with a locked page
|
||||
await openObjectTreeContextMenu(page, notebook.url);
|
||||
const menuOptions = page.locator('.c-menu ul');
|
||||
// no way to remove a restricted notebook with a locked page
|
||||
await openObjectTreeContextMenu(page, notebook.url);
|
||||
const menuOptions = page.locator('.c-menu ul');
|
||||
|
||||
await expect(menuOptions).not.toContainText('Remove');
|
||||
});
|
||||
await expect(menuOptions).not.toContainText('Remove');
|
||||
});
|
||||
|
||||
test('Can still: add page, rename, add entry, delete unlocked pages @addInit', async ({ page }) => {
|
||||
// Add a new page to the section
|
||||
await page.getByRole('button', { name: 'Add Page' }).click();
|
||||
// Focus the new page by clicking it
|
||||
await page.getByText('Unnamed Page').nth(1).click();
|
||||
// Rename the new page
|
||||
await page.getByText('Unnamed Page').nth(1).fill(TEST_TEXT_NAME);
|
||||
test('Can still: add page, rename, add entry, delete unlocked pages @addInit', async ({
|
||||
page
|
||||
}) => {
|
||||
// Add a new page to the section
|
||||
await page.getByRole('button', { name: 'Add Page' }).click();
|
||||
// Focus the new page by clicking it
|
||||
await page.getByText('Unnamed Page').nth(1).click();
|
||||
// Rename the new page
|
||||
await page.getByText('Unnamed Page').nth(1).fill(TEST_TEXT_NAME);
|
||||
|
||||
// expect to be able to rename unlocked pages
|
||||
const newPageElement = page.getByText(TEST_TEXT_NAME);
|
||||
const newPageCount = await newPageElement.count();
|
||||
await newPageElement.press('Enter'); // exit contenteditable state
|
||||
expect.soft(newPageCount).toEqual(1);
|
||||
// expect to be able to rename unlocked pages
|
||||
const newPageElement = page.getByText(TEST_TEXT_NAME);
|
||||
const newPageCount = await newPageElement.count();
|
||||
await newPageElement.press('Enter'); // exit contenteditable state
|
||||
expect.soft(newPageCount).toEqual(1);
|
||||
|
||||
// enter test text
|
||||
await nbUtils.enterTextEntry(page, TEST_TEXT);
|
||||
// enter test text
|
||||
await nbUtils.enterTextEntry(page, TEST_TEXT);
|
||||
|
||||
// expect new page to be lockable
|
||||
const commitButton = page.getByRole('button', { name: ' Commit Entries' });
|
||||
expect.soft(await commitButton.count()).toEqual(1);
|
||||
// expect new page to be lockable
|
||||
const commitButton = page.getByRole('button', { name: ' Commit Entries' });
|
||||
expect.soft(await commitButton.count()).toEqual(1);
|
||||
|
||||
// Click the context menu button for the new page
|
||||
await page.getByTitle('Open context menu').click();
|
||||
// Delete the page
|
||||
await page.getByRole('listitem', { name: 'Delete Page' }).click();
|
||||
// Click OK button
|
||||
await page.getByRole('button', { name: 'Ok' }).click();
|
||||
// Click the context menu button for the new page
|
||||
await page.getByTitle('Open context menu').click();
|
||||
// Delete the page
|
||||
await page.getByRole('listitem', { name: 'Delete Page' }).click();
|
||||
// Click OK button
|
||||
await page.getByRole('button', { name: 'Ok' }).click();
|
||||
|
||||
// deleted page, should no longer exist
|
||||
const deletedPageElement = page.getByText(TEST_TEXT_NAME);
|
||||
expect(await deletedPageElement.count()).toEqual(0);
|
||||
});
|
||||
// deleted page, should no longer exist
|
||||
const deletedPageElement = page.getByText(TEST_TEXT_NAME);
|
||||
expect(await deletedPageElement.count()).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Restricted Notebook with a page locked and with an embed @addInit', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const notebook = await startAndAddRestrictedNotebookObject(page);
|
||||
await nbUtils.dragAndDropEmbed(page, notebook);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
const notebook = await startAndAddRestrictedNotebookObject(page);
|
||||
await nbUtils.dragAndDropEmbed(page, notebook);
|
||||
});
|
||||
test('Allows embeds to be deleted if page unlocked @addInit', async ({ page }) => {
|
||||
// Click .c-ne__embed__name .c-popup-menu-button
|
||||
await page.locator('.c-ne__embed__name .c-icon-button').click(); // embed popup menu
|
||||
|
||||
test('Allows embeds to be deleted if page unlocked @addInit', async ({ page }) => {
|
||||
// Click .c-ne__embed__name .c-popup-menu-button
|
||||
await page.locator('.c-ne__embed__name .c-icon-button').click(); // embed popup menu
|
||||
const embedMenu = page.locator('body >> .c-menu');
|
||||
await expect(embedMenu).toContainText('Remove This Embed');
|
||||
});
|
||||
|
||||
const embedMenu = page.locator('body >> .c-menu');
|
||||
await expect(embedMenu).toContainText('Remove This Embed');
|
||||
});
|
||||
|
||||
test('Disallows embeds to be deleted if page locked @addInit', async ({ page }) => {
|
||||
await lockPage(page);
|
||||
// Click .c-ne__embed__name .c-popup-menu-button
|
||||
await page.locator('.c-ne__embed__name .c-icon-button').click(); // embed popup menu
|
||||
|
||||
const embedMenu = page.locator('body >> .c-menu');
|
||||
await expect(embedMenu).not.toContainText('Remove This Embed');
|
||||
});
|
||||
test('Disallows embeds to be deleted if page locked @addInit', async ({ page }) => {
|
||||
await lockPage(page);
|
||||
// Click .c-ne__embed__name .c-popup-menu-button
|
||||
await page.locator('.c-ne__embed__name .c-icon-button').click(); // embed popup menu
|
||||
|
||||
const embedMenu = page.locator('body >> .c-menu');
|
||||
await expect(embedMenu).not.toContainText('Remove This Embed');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('can export restricted notebook as text', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await startAndAddRestrictedNotebookObject(page);
|
||||
});
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await startAndAddRestrictedNotebookObject(page);
|
||||
});
|
||||
|
||||
test('basic functionality ', async ({ page }) => {
|
||||
await nbUtils.enterTextEntry(page, `Foo bar entry`);
|
||||
// Click on 3 Dot Menu
|
||||
await page.locator('button[title="More options"]').click();
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
test('basic functionality ', async ({ page }) => {
|
||||
await nbUtils.enterTextEntry(page, `Foo bar entry`);
|
||||
// Click on 3 Dot Menu
|
||||
await page.locator('button[title="More options"]').click();
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
|
||||
await page.getByRole('menuitem', { name: /Export Notebook as Text/ }).click();
|
||||
await page.getByRole('menuitem', { name: /Export Notebook as Text/ }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
const download = await downloadPromise;
|
||||
const readStream = await download.createReadStream();
|
||||
const exportedText = await streamToString(readStream);
|
||||
expect(exportedText).toContain('Foo bar entry');
|
||||
await page.getByRole('button', { name: 'Save' }).click();
|
||||
const download = await downloadPromise;
|
||||
const readStream = await download.createReadStream();
|
||||
const exportedText = await streamToString(readStream);
|
||||
expect(exportedText).toContain('Foo bar entry');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test.fixme('can export multiple notebook entries as text ', async ({ page }) => {});
|
||||
test.fixme('can export all notebook entry metdata', async ({ page }) => {});
|
||||
test.fixme('can export all notebook tags', async ({ page }) => {});
|
||||
test.fixme('can export all notebook snapshots', async ({ page }) => {});
|
||||
test.fixme('can export multiple notebook entries as text ', async ({ page }) => {});
|
||||
test.fixme('can export all notebook entry metdata', async ({ page }) => {});
|
||||
test.fixme('can export all notebook tags', async ({ page }) => {});
|
||||
test.fixme('can export all notebook snapshots', async ({ page }) => {});
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
async function startAndAddRestrictedNotebookObject(page) {
|
||||
await page.addInitScript({ path: path.join(__dirname, '../../../../helper/', 'addInitRestrictedNotebook.js') });
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
await page.addInitScript({
|
||||
path: path.join(__dirname, '../../../../helper/', 'addInitRestrictedNotebook.js')
|
||||
});
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
return createDomainObjectWithDefaults(page, { type: CUSTOM_NAME });
|
||||
return createDomainObjectWithDefaults(page, { type: CUSTOM_NAME });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
async function lockPage(page) {
|
||||
const commitButton = page.locator('button:has-text("Commit Entries")');
|
||||
await commitButton.click();
|
||||
const commitButton = page.locator('button:has-text("Commit Entries")');
|
||||
await commitButton.click();
|
||||
|
||||
//Wait until Lock Banner is visible
|
||||
await page.locator('text=Lock Page').click();
|
||||
//Wait until Lock Banner is visible
|
||||
await page.locator('text=Lock Page').click();
|
||||
}
|
||||
|
||||
@@ -29,243 +29,247 @@ const { createDomainObjectWithDefaults, selectInspectorTab } = require('../../..
|
||||
const nbUtils = require('../../../../helper/notebookUtils');
|
||||
|
||||
/**
|
||||
* Creates a notebook object and adds an entry.
|
||||
* @param {import('@playwright/test').Page} - page to load
|
||||
* @param {number} [iterations = 1] - the number of entries to create
|
||||
*/
|
||||
* Creates a notebook object and adds an entry.
|
||||
* @param {import('@playwright/test').Page} - page to load
|
||||
* @param {number} [iterations = 1] - the number of entries to create
|
||||
*/
|
||||
async function createNotebookAndEntry(page, iterations = 1) {
|
||||
const notebook = createDomainObjectWithDefaults(page, { type: 'Notebook' });
|
||||
const notebook = createDomainObjectWithDefaults(page, { type: 'Notebook' });
|
||||
|
||||
for (let iteration = 0; iteration < iterations; iteration++) {
|
||||
await nbUtils.enterTextEntry(page, `Entry ${iteration}`);
|
||||
}
|
||||
for (let iteration = 0; iteration < iterations; iteration++) {
|
||||
await nbUtils.enterTextEntry(page, `Entry ${iteration}`);
|
||||
}
|
||||
|
||||
return notebook;
|
||||
return notebook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a notebook object, adds an entry, and adds a tag.
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {number} [iterations = 1] - the number of entries (and tags) to create
|
||||
*/
|
||||
* Creates a notebook object, adds an entry, and adds a tag.
|
||||
* @param {import('@playwright/test').Page} page
|
||||
* @param {number} [iterations = 1] - the number of entries (and tags) to create
|
||||
*/
|
||||
async function createNotebookEntryAndTags(page, iterations = 1) {
|
||||
const notebook = await createNotebookAndEntry(page, iterations);
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
const notebook = await createNotebookAndEntry(page, iterations);
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
|
||||
for (let iteration = 0; iteration < iterations; iteration++) {
|
||||
// Hover and click "Add Tag" button
|
||||
// Hover is needed here to "slow down" the actions while running in headless mode
|
||||
await page.locator(`[aria-label="Notebook Entry"] >> nth = ${iteration}`).click();
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
for (let iteration = 0; iteration < iterations; iteration++) {
|
||||
// Hover and click "Add Tag" button
|
||||
// Hover is needed here to "slow down" the actions while running in headless mode
|
||||
await page.locator(`[aria-label="Notebook Entry"] >> nth = ${iteration}`).click();
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
|
||||
// Click inside the tag search input
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Select the "Driving" tag
|
||||
await page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click();
|
||||
// Click inside the tag search input
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Select the "Driving" tag
|
||||
await page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click();
|
||||
|
||||
// Hover and click "Add Tag" button
|
||||
// Hover is needed here to "slow down" the actions while running in headless mode
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
// Click inside the tag search input
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Select the "Science" tag
|
||||
await page.locator('[aria-label="Autocomplete Options"] >> text=Science').click();
|
||||
}
|
||||
// Hover and click "Add Tag" button
|
||||
// Hover is needed here to "slow down" the actions while running in headless mode
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
// Click inside the tag search input
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Select the "Science" tag
|
||||
await page.locator('[aria-label="Autocomplete Options"] >> text=Science').click();
|
||||
}
|
||||
|
||||
return notebook;
|
||||
return notebook;
|
||||
}
|
||||
|
||||
test.describe('Tagging in Notebooks @addInit', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
test('Can load tags', async ({ page }) => {
|
||||
await createNotebookAndEntry(page);
|
||||
test.beforeEach(async ({ page }) => {
|
||||
//Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
});
|
||||
test('Can load tags', async ({ page }) => {
|
||||
await createNotebookAndEntry(page);
|
||||
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText("Drilling");
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText("Driving");
|
||||
});
|
||||
test('Can add tags', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText('Drilling');
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText('Driving');
|
||||
});
|
||||
test('Can add tags', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText("Driving");
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText('Driving');
|
||||
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).not.toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).not.toContainText("Driving");
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText("Drilling");
|
||||
});
|
||||
test('Can add tags with blank entry', async ({ page }) => {
|
||||
await createDomainObjectWithDefaults(page, { type: 'Notebook' });
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).not.toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).not.toContainText('Driving');
|
||||
await expect(page.locator('[aria-label="Autocomplete Options"]')).toContainText('Drilling');
|
||||
});
|
||||
test('Can add tags with blank entry', async ({ page }) => {
|
||||
await createDomainObjectWithDefaults(page, { type: 'Notebook' });
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
|
||||
await nbUtils.enterTextEntry(page, '');
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
await nbUtils.enterTextEntry(page, '');
|
||||
await page.hover(`button:has-text("Add Tag")`);
|
||||
await page.locator(`button:has-text("Add Tag")`).click();
|
||||
|
||||
// Click inside the tag search input
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Select the "Driving" tag
|
||||
await page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click();
|
||||
// Click inside the tag search input
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Select the "Driving" tag
|
||||
await page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click();
|
||||
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText("Driving");
|
||||
});
|
||||
test('Can cancel adding tags', async ({ page }) => {
|
||||
await createNotebookAndEntry(page);
|
||||
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText('Driving');
|
||||
});
|
||||
test('Can cancel adding tags', async ({ page }) => {
|
||||
await createNotebookAndEntry(page);
|
||||
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
|
||||
// Test canceling adding a tag after we click "Type to select tag"
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
// Test canceling adding a tag after we click "Type to select tag"
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
|
||||
await expect(page.locator('button:has-text("Add Tag")')).toBeVisible();
|
||||
await expect(page.locator('button:has-text("Add Tag")')).toBeVisible();
|
||||
|
||||
// Test canceling adding a tag after we just click "Add Tag"
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
// Test canceling adding a tag after we just click "Add Tag"
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
|
||||
await expect(page.locator('button:has-text("Add Tag")')).toBeVisible();
|
||||
});
|
||||
test('Can search for tags and preview works properly', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText("Driving");
|
||||
await expect(page.locator('button:has-text("Add Tag")')).toBeVisible();
|
||||
});
|
||||
test('Can search for tags and preview works properly', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText('Driving');
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText("Driving");
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText('Driving');
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Xq');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Xq');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout'
|
||||
});
|
||||
|
||||
// Go back into edit mode for the display layout
|
||||
await page.locator('button[title="Edit"]').click();
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).toContainText("Science");
|
||||
await page.getByText('Entry 0').click();
|
||||
await expect(page.locator('.js-preview-window')).toBeVisible();
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout'
|
||||
});
|
||||
|
||||
test('Can delete tags', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
// Delete Driving
|
||||
await page.hover('[aria-label="Tag"]:has-text("Driving")');
|
||||
await page.locator('[aria-label="Remove tag Driving"]').click();
|
||||
// Go back into edit mode for the display layout
|
||||
await page.locator('button[title="Edit"]').click();
|
||||
|
||||
await expect(page.locator('[aria-label="Tags Inspector"]')).toContainText("Science");
|
||||
await expect(page.locator('[aria-label="Tags Inspector"]')).not.toContainText("Driving");
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).toContainText('Science');
|
||||
await page.getByText('Entry 0').click();
|
||||
await expect(page.locator('.js-preview-window')).toBeVisible();
|
||||
});
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText("Driving");
|
||||
test('Can delete tags', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
// Delete Driving
|
||||
await page.hover('[aria-label="Tag"]:has-text("Driving")');
|
||||
await page.locator('[aria-label="Remove tag Driving"]').click();
|
||||
|
||||
await expect(page.locator('[aria-label="Tags Inspector"]')).toContainText('Science');
|
||||
await expect(page.locator('[aria-label="Tags Inspector"]')).not.toContainText('Driving');
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sc');
|
||||
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText('Driving');
|
||||
});
|
||||
|
||||
test('Can delete entries without tags', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/5823'
|
||||
});
|
||||
|
||||
test('Can delete entries without tags', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/5823'
|
||||
});
|
||||
await createNotebookEntryAndTags(page);
|
||||
|
||||
await createNotebookEntryAndTags(page);
|
||||
await page.locator('text=To start a new entry, click here or drag and drop any object').click();
|
||||
const entryLocator = `[aria-label="Notebook Entry Input"] >> nth = 1`;
|
||||
await page.locator(entryLocator).click();
|
||||
await page.locator(entryLocator).fill(`An entry without tags`);
|
||||
await page.locator('[aria-label="Notebook Entry Input"] >> nth=1').press('Enter');
|
||||
|
||||
await page.locator('text=To start a new entry, click here or drag and drop any object').click();
|
||||
const entryLocator = `[aria-label="Notebook Entry Input"] >> nth = 1`;
|
||||
await page.locator(entryLocator).click();
|
||||
await page.locator(entryLocator).fill(`An entry without tags`);
|
||||
await page.locator('[aria-label="Notebook Entry Input"] >> nth=1').press('Enter');
|
||||
await page.hover('[aria-label="Notebook Entry Input"] >> nth=1');
|
||||
await page.locator('button[title="Delete this entry"]').last().click();
|
||||
await expect(
|
||||
page.locator('text=This action will permanently delete this entry. Do you wish to continue?')
|
||||
).toBeVisible();
|
||||
await page.locator('button:has-text("Ok")').click();
|
||||
await expect(
|
||||
page.locator('text=This action will permanently delete this entry. Do you wish to continue?')
|
||||
).toBeHidden();
|
||||
});
|
||||
|
||||
await page.hover('[aria-label="Notebook Entry Input"] >> nth=1');
|
||||
await page.locator('button[title="Delete this entry"]').last().click();
|
||||
await expect(page.locator('text=This action will permanently delete this entry. Do you wish to continue?')).toBeVisible();
|
||||
await page.locator('button:has-text("Ok")').click();
|
||||
await expect(page.locator('text=This action will permanently delete this entry. Do you wish to continue?')).toBeHidden();
|
||||
});
|
||||
test('Can delete objects with tags and neither return in search', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
// Delete Notebook
|
||||
await page.locator('button[title="More options"]').click();
|
||||
await page.locator('li[title="Remove this object from its containing object."]').click();
|
||||
await page.locator('button:has-text("OK")').click();
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
test('Can delete objects with tags and neither return in search', async ({ page }) => {
|
||||
await createNotebookEntryAndTags(page);
|
||||
// Delete Notebook
|
||||
await page.locator('button[title="More options"]').click();
|
||||
await page.locator('li[title="Remove this object from its containing object."]').click();
|
||||
await page.locator('button:has-text("OK")').click();
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Unnamed');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sci');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('dri');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
});
|
||||
test('Tags persist across reload', async ({ page }) => {
|
||||
//Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('Unnamed');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sci');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('dri');
|
||||
await expect(page.locator('text=No results found')).toBeVisible();
|
||||
});
|
||||
test('Tags persist across reload', async ({ page }) => {
|
||||
//Go to baseURL
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
const ITERATIONS = 4;
|
||||
const notebook = await createNotebookEntryAndTags(page, ITERATIONS);
|
||||
await page.goto(notebook.url);
|
||||
|
||||
const ITERATIONS = 4;
|
||||
const notebook = await createNotebookEntryAndTags(page, ITERATIONS);
|
||||
await page.goto(notebook.url);
|
||||
// Verify tags are present
|
||||
for (let iteration = 0; iteration < ITERATIONS; iteration++) {
|
||||
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
|
||||
await expect(page.locator(entryLocator)).toContainText('Science');
|
||||
await expect(page.locator(entryLocator)).toContainText('Driving');
|
||||
}
|
||||
|
||||
// Verify tags are present
|
||||
for (let iteration = 0; iteration < ITERATIONS; iteration++) {
|
||||
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
|
||||
await expect(page.locator(entryLocator)).toContainText("Science");
|
||||
await expect(page.locator(entryLocator)).toContainText("Driving");
|
||||
}
|
||||
//Reload Page
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
|
||||
//Reload Page
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
// Verify tags persist across reload
|
||||
for (let iteration = 0; iteration < ITERATIONS; iteration++) {
|
||||
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
|
||||
await expect(page.locator(entryLocator)).toContainText('Science');
|
||||
await expect(page.locator(entryLocator)).toContainText('Driving');
|
||||
}
|
||||
});
|
||||
test('Can cancel adding a tag', async ({ page }) => {
|
||||
await createNotebookAndEntry(page);
|
||||
|
||||
// Verify tags persist across reload
|
||||
for (let iteration = 0; iteration < ITERATIONS; iteration++) {
|
||||
const entryLocator = `[aria-label="Notebook Entry"] >> nth = ${iteration}`;
|
||||
await expect(page.locator(entryLocator)).toContainText("Science");
|
||||
await expect(page.locator(entryLocator)).toContainText("Driving");
|
||||
}
|
||||
});
|
||||
test('Can cancel adding a tag', async ({ page }) => {
|
||||
await createNotebookAndEntry(page);
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
|
||||
await selectInspectorTab(page, 'Annotations');
|
||||
// Click on the "Add Tag" button
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
|
||||
// Click on the "Add Tag" button
|
||||
await page.locator('button:has-text("Add Tag")').click();
|
||||
// Click inside the AutoComplete field
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
|
||||
// Click inside the AutoComplete field
|
||||
await page.locator('[placeholder="Type to select tag"]').click();
|
||||
// Click on the "Tags" header (simulating a click outside the autocomplete)
|
||||
await page.locator('div.c-inspect-properties__header:has-text("Tags")').click();
|
||||
|
||||
// Click on the "Tags" header (simulating a click outside the autocomplete)
|
||||
await page.locator('div.c-inspect-properties__header:has-text("Tags")').click();
|
||||
// Verify there is a button with text "Add Tag"
|
||||
await expect(page.locator('button:has-text("Add Tag")')).toBeVisible();
|
||||
|
||||
// Verify there is a button with text "Add Tag"
|
||||
await expect(page.locator('button:has-text("Add Tag")')).toBeVisible();
|
||||
|
||||
// Verify the AutoComplete field is hidden
|
||||
await expect(page.locator('[placeholder="Type to select tag"]')).toBeHidden();
|
||||
});
|
||||
// Verify the AutoComplete field is hidden
|
||||
await expect(page.locator('[placeholder="Type to select tag"]')).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user