5361 Tags not persisting when several notebook entries are created at once ()

* add end to end test to catch multiple entry errors

* click expansion triangle instead

* fix race condition between annotation creation and mutation

* make sure notebook tags run in e2e

* address PR comments
This commit is contained in:
Scott Bell 2022-07-05 17:45:39 +02:00 committed by GitHub
parent 2766452b38
commit 2999a5135e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 94 additions and 32 deletions
e2e/tests/plugins/notebook
package.json
src
api/annotation
plugins/notebook/components

@ -29,46 +29,57 @@ const { test } = require('../../../fixtures');
/**
* Creates a notebook object and adds an entry.
* @param {import('@playwright/test').Page} page
* @param {import('@playwright/test').Page} - page to load
* @param {number} [iterations = 1] - the number of entries to create
*/
async function createNotebookAndEntry(page) {
async function createNotebookAndEntry(page, iterations = 1) {
//Go to baseURL
await page.goto('/', { waitUntil: 'networkidle' });
// Click button:has-text("Create")
await page.locator('button:has-text("Create")').click();
// Click li:has-text("Notebook")
await page.locator('li:has-text("Notebook")').click();
await page.locator('[title="Create and save timestamped notes with embedded object snapshots."]').click();
// Click button:has-text("OK")
await Promise.all([
page.waitForNavigation(),
page.locator('[name="mctForm"] >> text=My Items').click(),
page.locator('button:has-text("OK")').click()
]);
// Click text=To start a new entry, click here or drag and drop any object
await page.locator('text=To start a new entry, click here or drag and drop any object').click();
for (let iteration = 0; iteration < iterations; iteration++) {
// Click text=To start a new entry, click here or drag and drop any object
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 = ${iteration}`;
await page.locator(entryLocator).click();
await page.locator(entryLocator).fill(`Entry ${iteration}`);
}
}
/**
* 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) {
await createNotebookAndEntry(page);
// Click text=To start a new entry, click here or drag and drop any object
await page.locator('button:has-text("Add Tag")').click();
async function createNotebookEntryAndTags(page, iterations = 1) {
await createNotebookAndEntry(page, iterations);
// Click [placeholder="Type to select tag"]
await page.locator('[placeholder="Type to select tag"]').click();
// Click text=Driving
await page.locator('text=Driving').click();
for (let iteration = 0; iteration < iterations; iteration++) {
// Click text=To start a new entry, click here or drag and drop any object
await page.locator(`button:has-text("Add Tag") >> nth = ${iteration}`).click();
// Click button:has-text("Add Tag")
await page.locator('button:has-text("Add Tag")').click();
// Click [placeholder="Type to select tag"]
await page.locator('[placeholder="Type to select tag"]').click();
// Click text=Science
await page.locator('text=Science').click();
// Click [placeholder="Type to select tag"]
await page.locator('[placeholder="Type to select tag"]').click();
// Click text=Driving
await page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click();
// Click button:has-text("Add Tag")
await page.locator(`button:has-text("Add Tag") >> nth = ${iteration}`).click();
// Click [placeholder="Type to select tag"]
await page.locator('[placeholder="Type to select tag"]').click();
// Click text=Science
await page.locator('[aria-label="Autocomplete Options"] >> text=Science').click();
}
}
test.describe('Tagging in Notebooks', () => {
@ -137,10 +148,58 @@ test.describe('Tagging in Notebooks', () => {
await expect(page.locator('[aria-label="Search Result"]')).not.toContainText("Driving");
});
test('Tags persist across reload', async ({ page }) => {
await createNotebookEntryAndTags(page);
//Go to baseURL
await page.reload();
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText("Science");
await expect(page.locator('[aria-label="Notebook Entry"]')).toContainText("Driving");
await page.goto('/', { waitUntil: 'networkidle' });
// Create a clock object we can navigate to
await page.click('button:has-text("Create")');
// Click Clock
await page.click('text=Clock');
// Click button:has-text("OK")
await Promise.all([
page.waitForNavigation(),
page.locator('[name="mctForm"] >> text=My Items').click(),
page.locator('button:has-text("OK")').click()
]);
await page.click('.c-disclosure-triangle');
const ITERATIONS = 4;
await createNotebookEntryAndTags(page, ITERATIONS);
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");
}
// Click Unnamed Clock
await page.click('text="Unnamed Clock"');
// Click Unnamed Notebook
await page.click('text="Unnamed Notebook"');
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 Promise.all([
page.reload(),
page.waitForLoadState('networkidle')
]);
// Click Unnamed Notebook
await page.click('text="Unnamed Notebook"');
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");
}
});
});

@ -89,7 +89,7 @@
"test": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run",
"test:firefox": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run --browsers=FirefoxHeadless",
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
"test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome smoke branding default condition timeConductor clock exampleImagery persistence performance grandsearch notebook/tags",
"test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome smoke branding default condition timeConductor clock exampleImagery persistence performance grandsearch tags",
"test:e2e:local": "npx playwright test --config=e2e/playwright-local.config.js --project=chrome",
"test:e2e:updatesnapshots": "npx playwright test --config=e2e/playwright-local.config.js --project=chrome --grep @snapshot --update-snapshots",
"test:e2e:visual": "percy exec --config ./e2e/.percy.yml -- npx playwright test --config=e2e/playwright-visual.config.js",

@ -172,17 +172,19 @@ export default class AnnotationAPI extends EventEmitter {
name: contentText,
domainObject: targetDomainObject,
annotationType,
tags: [],
tags: [tag],
contentText,
targets
};
existingAnnotation = await this.create(annotationCreationArguments);
const newAnnotation = await this.create(annotationCreationArguments);
return newAnnotation;
} else {
const tagArray = [tag, ...existingAnnotation.tags];
this.openmct.objects.mutate(existingAnnotation, 'tags', tagArray);
return existingAnnotation;
}
const tagArray = [tag, ...existingAnnotation.tags];
this.openmct.objects.mutate(existingAnnotation, 'tags', tagArray);
return existingAnnotation;
}
removeAnnotationTag(existingAnnotation, tagToRemove) {

@ -59,6 +59,7 @@
<div
:id="entry.id"
class="c-ne__text c-ne__input"
aria-label="Notebook Entry Input"
tabindex="0"
contenteditable="true"
@focus="editingEntry()"