diff options
Diffstat (limited to 'e2e/tests/functional/plugins/notebook/notebookWithCouchDB.e2e.spec.js')
-rw-r--r-- | e2e/tests/functional/plugins/notebook/notebookWithCouchDB.e2e.spec.js | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/e2e/tests/functional/plugins/notebook/notebookWithCouchDB.e2e.spec.js b/e2e/tests/functional/plugins/notebook/notebookWithCouchDB.e2e.spec.js new file mode 100644 index 000000000..4edb1ff28 --- /dev/null +++ b/e2e/tests/functional/plugins/notebook/notebookWithCouchDB.e2e.spec.js @@ -0,0 +1,232 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2022, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/* +This test suite is dedicated to tests which verify the basic operations surrounding Notebooks with CouchDB. +*/ + +const { test, expect } = require('../../../../baseFixtures'); +const { createDomainObjectWithDefaults } = require('../../../../appActions'); + +test.describe('Notebook Network Request Inspection @couchdb', () => { + let testNotebook; + test.beforeEach(async ({ page }) => { + //Navigate to baseURL + await page.goto('./', { waitUntil: 'networkidle' }); + + // Create Notebook + testNotebook = await createDomainObjectWithDefaults(page, { + type: 'Notebook', + name: "TestNotebook" + }); + }); + + test('Inspect Notebook Entry Network Requests', async ({ page }) => { + // Expand sidebar + await page.locator('.c-notebook__toggle-nav-button').click(); + + // Collect all request events to count and assert after notebook action + let addingNotebookElementsRequests = []; + page.on('request', (request) => addingNotebookElementsRequests.push(request)); + + 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 + 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(addingNotebookElementsRequests.length).toBe(2); + + // Assert on request object + expect(notebookUrlRequest.postDataJSON().metadata.name).toBe('TestNotebook'); + 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 + addingNotebookElementsRequests = []; + await page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"]').click(); + await page.locator('[aria-label="Notebook Entry Input"]').fill(`First Entry`); + await page.waitForLoadState('networkidle'); + expect(addingNotebookElementsRequests.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 + + addingNotebookElementsRequests = []; + 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 page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Driving")'); + page.waitForLoadState('networkidle'); + expect(filterNonFetchRequests(addingNotebookElementsRequests).length).toBeLessThanOrEqual(11); + + addingNotebookElementsRequests = []; + 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 page.locator('[aria-label="Autocomplete Options"] >> text=Drilling').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Drilling")'); + page.waitForLoadState('networkidle'); + expect(filterNonFetchRequests(addingNotebookElementsRequests).length).toBeLessThanOrEqual(11); + + addingNotebookElementsRequests = []; + 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 page.locator('[aria-label="Autocomplete Options"] >> text=Science').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Science")'); + page.waitForLoadState('networkidle'); + expect(filterNonFetchRequests(addingNotebookElementsRequests).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 + addingNotebookElementsRequests = []; + await page.hover('[aria-label="Tag"]:has-text("Driving")'); + await page.locator('[aria-label="Tag"]:has-text("Driving") ~ .c-completed-tag-deletion').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Driving")', {state: 'hidden'}); + await page.hover('[aria-label="Tag"]:has-text("Drilling")'); + await page.locator('[aria-label="Tag"]:has-text("Drilling") ~ .c-completed-tag-deletion').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Drilling")', {state: 'hidden'}); + page.hover('[aria-label="Tag"]:has-text("Science")'); + await page.locator('[aria-label="Tag"]:has-text("Science") ~ .c-completed-tag-deletion').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Science")', {state: 'hidden'}); + page.waitForLoadState('networkidle'); + expect(filterNonFetchRequests(addingNotebookElementsRequests).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 page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"]').click(); + await page.locator('[aria-label="Notebook Entry Input"]').fill(`First Entry`); + + await page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=1').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=1').fill(`Second Entry`); + + await page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=2').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=2').fill(`Third Entry`); + + // Add three tags + await page.hover(`button:has-text("Add Tag") >> nth=2`); + await page.locator(`button:has-text("Add Tag") >> nth=2`).click(); + await page.locator('[placeholder="Type to select tag"]').click(); + await page.locator('[aria-label="Autocomplete Options"] >> text=Science').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Science")'); + + await page.hover(`button:has-text("Add Tag") >> nth=2`); + await page.locator(`button:has-text("Add Tag") >> nth=2`).click(); + await page.locator('[placeholder="Type to select tag"]').click(); + await page.locator('[aria-label="Autocomplete Options"] >> text=Drilling').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Drilling")'); + + await page.hover(`button:has-text("Add Tag") >> nth=2`); + await page.locator(`button:has-text("Add Tag") >> nth=2`).click(); + await page.locator('[placeholder="Type to select tag"]').click(); + await page.locator('[aria-label="Autocomplete Options"] >> text=Driving').click(); + await page.waitForSelector('[aria-label="Tag"]:has-text("Driving")'); + page.waitForLoadState('networkidle'); + + // 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 + addingNotebookElementsRequests = []; + await page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=3').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=3').fill(`Fourth Entry`); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=3').press('Enter'); + page.waitForLoadState('networkidle'); + + expect(filterNonFetchRequests(addingNotebookElementsRequests).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 + addingNotebookElementsRequests = []; + await page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=4').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=4').fill(`Fifth Entry`); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=4').press('Enter'); + page.waitForLoadState('networkidle'); + + expect(filterNonFetchRequests(addingNotebookElementsRequests).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 + addingNotebookElementsRequests = []; + await page.locator('text=To start a new entry, click here or drag and drop any object').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=5').click(); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=5').fill(`Sixth Entry`); + await page.locator('[aria-label="Notebook Entry Input"] >> nth=5').press('Enter'); + page.waitForLoadState('networkidle'); + + expect(filterNonFetchRequests(addingNotebookElementsRequests).length).toBeLessThanOrEqual(4); + }); +}); + +// 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'); + }); +} |