diff --git a/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js b/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js index 10f5bcb14f..24d323a96e 100644 --- a/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/notebook.e2e.spec.js @@ -198,6 +198,36 @@ test.describe('Notebook page tests', () => { }); }); +test.describe('Notebook export tests', () => { + test.beforeEach(async ({ page }) => { + //Navigate to baseURL + await page.goto('./', { waitUntil: 'networkidle' }); + + // 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'); + + 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 }) => {}); +}); + test.describe('Notebook search tests', () => { test.fixme('Can search for a single result', async ({ page }) => {}); test.fixme('Can search for many results', async ({ page }) => {}); @@ -219,7 +249,15 @@ test.describe('Notebook entry tests', () => { type: NOTEBOOK_NAME }); }); - test.fixme('When a new entry is created, it should be focused', async ({ page }) => {}); + 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); + + // 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 await createDomainObjectWithDefaults(page, { @@ -263,7 +301,25 @@ test.describe('Notebook entry tests', () => { expect(embedName).toBe('Dropped Overlay Plot'); }); test.fixme('new entries persist through navigation events without save', async ({ page }) => {}); - test.fixme('previous and new entries can be deleted', 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(); + }); 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'; @@ -377,22 +433,4 @@ test.describe('Notebook entry tests', () => { expect.soft(await sanitizedLink.count()).toBe(1); expect(await unsanitizedLink.count()).toBe(0); }); - 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('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 }) => {}); }); diff --git a/e2e/tests/functional/plugins/notebook/tags.e2e.spec.js b/e2e/tests/functional/plugins/notebook/tags.e2e.spec.js index 5098acfab1..d0cf8ca707 100644 --- a/e2e/tests/functional/plugins/notebook/tags.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/tags.e2e.spec.js @@ -34,9 +34,6 @@ const nbUtils = require('../../../../helper/notebookUtils'); * @param {number} [iterations = 1] - the number of entries to create */ async function createNotebookAndEntry(page, iterations = 1) { - //Go to baseURL - await page.goto('./', { waitUntil: 'networkidle' }); - const notebook = createDomainObjectWithDefaults(page, { type: 'Notebook' }); for (let iteration = 0; iteration < iterations; iteration++) { @@ -81,12 +78,13 @@ async function createNotebookEntryAndTags(page, iterations = 1) { } test.describe('Tagging in Notebooks @addInit', () => { + test.beforeEach(async ({ page }) => { + //Go to baseURL + await page.goto('./', { waitUntil: 'networkidle' }); + }); test('Can load tags', async ({ page }) => { await createNotebookAndEntry(page); - // TODO can be removed with fix for https://github.com/nasa/openmct/issues/6411 - await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').click(); - await selectInspectorTab(page, 'Annotations'); await page.locator('button:has-text("Add Tag")').click(); @@ -110,12 +108,24 @@ test.describe('Tagging in Notebooks @addInit', () => { 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 }) => { + 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(); + + // 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); - // TODO can be removed with fix for https://github.com/nasa/openmct/issues/6411 - await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').click(); - await selectInspectorTab(page, 'Annotations'); // Test canceling adding a tag after we click "Type to select tag" @@ -270,9 +280,6 @@ test.describe('Tagging in Notebooks @addInit', () => { test('Can cancel adding a tag', async ({ page }) => { await createNotebookAndEntry(page); - // TODO can be removed with fix for https://github.com/nasa/openmct/issues/6411 - await page.locator('[aria-label="Notebook Entry"].is-selected div.c-ne__text').click(); - await selectInspectorTab(page, 'Annotations'); // Click on the "Add Tag" button diff --git a/src/plugins/notebook/components/Notebook.vue b/src/plugins/notebook/components/Notebook.vue index cc6f2d6418..b6893d03fa 100644 --- a/src/plugins/notebook/components/Notebook.vue +++ b/src/plugins/notebook/components/Notebook.vue @@ -125,7 +125,7 @@ v-if="selectedPage && !selectedPage.isLocked" :class="{ 'disabled': activeTransaction }" class="c-notebook__drag-area icon-plus" - @click="newEntry()" + @click="newEntry(null, $event)" @dragover="dragOver" @drop.capture="dropCapture" @drop="dropOnEntry($event)" @@ -193,7 +193,7 @@ import SearchResults from './SearchResults.vue'; import Sidebar from './Sidebar.vue'; import ProgressBar from '../../../ui/components/ProgressBar.vue'; import { clearDefaultNotebook, getDefaultNotebook, setDefaultNotebook, setDefaultNotebookSectionId, setDefaultNotebookPageId } from '../utils/notebook-storage'; -import { addNotebookEntry, createNewEmbed, getEntryPosById, getNotebookEntries, mutateObject } from '../utils/notebook-entries'; +import { addNotebookEntry, createNewEmbed, getEntryPosById, getNotebookEntries, mutateObject, selectEntry } from '../utils/notebook-entries'; import { saveNotebookImageDomainObject, updateNamespaceOfDomainObject } from '../utils/notebook-image'; import { isNotebookViewType, RESTRICTED_NOTEBOOK_TYPE } from '../notebook-constants'; @@ -793,15 +793,29 @@ export default { return section.id; }, - async newEntry(embed = null) { + async newEntry(embed, event) { this.startTransaction(); this.resetSearch(); const notebookStorage = this.createNotebookStorageObject(); this.updateDefaultNotebook(notebookStorage); const id = await addNotebookEntry(this.openmct, this.domainObject, notebookStorage, embed); + + const element = this.$refs.notebookEntries.querySelector(`#${id}`); + const entryAnnotations = this.notebookAnnotations[id] ?? {}; + selectEntry({ + element, + entryId: id, + domainObject: this.domainObject, + openmct: this.openmct, + notebookAnnotations: entryAnnotations + }); + if (event) { + event.stopPropagation(); + } + + this.filterAndSortEntries(); this.focusEntryId = id; this.selectedEntryId = id; - this.filterAndSortEntries(); }, orientationChange() { this.formatSidebar(); diff --git a/src/plugins/notebook/components/NotebookEntry.vue b/src/plugins/notebook/components/NotebookEntry.vue index 54c971821e..dfa822fdc2 100644 --- a/src/plugins/notebook/components/NotebookEntry.vue +++ b/src/plugins/notebook/components/NotebookEntry.vue @@ -32,7 +32,7 @@ @dragover="changeCursor" @drop.capture="cancelEditMode" @drop.prevent="dropOnEntry" - @click="selectEntry($event, entry)" + @click="selectAndEmitEntry($event, entry)" >
@@ -164,7 +164,7 @@