mirror of
https://github.com/nasa/openmct.git
synced 2025-04-25 13:29:51 +00:00
fix: Navigating from Recent Objects breadcrumb correctly updates the URL hash (#6234)
* fix: provide hashUrl for ObjectPath breadcrumbs * a11y: add `navigation` role and aria-label to breadcrumb * test(e2e): add regression test for breadcrumb nav --------- Co-authored-by: Scott Bell <scott@traclabs.com>
This commit is contained in:
parent
66d7c626e1
commit
6d63339b23
@ -24,15 +24,22 @@ const { test, expect } = require('../../pluginFixtures.js');
|
|||||||
const { createDomainObjectWithDefaults } = require('../../appActions.js');
|
const { createDomainObjectWithDefaults } = require('../../appActions.js');
|
||||||
|
|
||||||
test.describe('Recent Objects', () => {
|
test.describe('Recent Objects', () => {
|
||||||
test('Recent Objects CRUD operations', async ({ page }) => {
|
let recentObjectsList;
|
||||||
|
let clock;
|
||||||
|
let folderA;
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
await page.goto('./', { waitUntil: 'networkidle' });
|
await page.goto('./', { waitUntil: 'networkidle' });
|
||||||
|
|
||||||
|
// Set Recent Objects List locator for subsequent tests
|
||||||
|
recentObjectsList = page.getByRole('list', {
|
||||||
|
name: 'Recent Objects'
|
||||||
|
});
|
||||||
|
|
||||||
// Create a folder and nest a Clock within it
|
// Create a folder and nest a Clock within it
|
||||||
const recentObjectsList = page.locator('[aria-label="Recent Objects"]');
|
folderA = await createDomainObjectWithDefaults(page, {
|
||||||
const folderA = await createDomainObjectWithDefaults(page, {
|
|
||||||
type: 'Folder'
|
type: 'Folder'
|
||||||
});
|
});
|
||||||
const clock = await createDomainObjectWithDefaults(page, {
|
clock = await createDomainObjectWithDefaults(page, {
|
||||||
type: 'Clock',
|
type: 'Clock',
|
||||||
parent: folderA.uuid
|
parent: folderA.uuid
|
||||||
});
|
});
|
||||||
@ -42,7 +49,8 @@ test.describe('Recent Objects', () => {
|
|||||||
await page.mouse.down();
|
await page.mouse.down();
|
||||||
await page.mouse.move(0, 100);
|
await page.mouse.move(0, 100);
|
||||||
await page.mouse.up();
|
await page.mouse.up();
|
||||||
|
});
|
||||||
|
test('Recent Objects CRUD operations', async ({ page }) => {
|
||||||
// Verify that both created objects appear in the list and are in the correct order
|
// Verify that both created objects appear in the list and are in the correct order
|
||||||
expect(recentObjectsList.getByRole('listitem', { name: clock.name })).toBeTruthy();
|
expect(recentObjectsList.getByRole('listitem', { name: clock.name })).toBeTruthy();
|
||||||
expect(recentObjectsList.getByRole('listitem', { name: folderA.name })).toBeTruthy();
|
expect(recentObjectsList.getByRole('listitem', { name: folderA.name })).toBeTruthy();
|
||||||
@ -52,7 +60,7 @@ test.describe('Recent Objects', () => {
|
|||||||
expect(recentObjectsList.getByRole('listitem').nth(1).getByText(folderA.name)).toBeTruthy();
|
expect(recentObjectsList.getByRole('listitem').nth(1).getByText(folderA.name)).toBeTruthy();
|
||||||
|
|
||||||
// Navigate to the folder by clicking on the main object name in the recent objects list item
|
// Navigate to the folder by clicking on the main object name in the recent objects list item
|
||||||
await recentObjectsList.getByRole('listitem', { name: folderA.name }).getByText(folderA.name).click();
|
await page.getByRole('listitem', { name: folderA.name }).getByText(folderA.name).click();
|
||||||
await page.waitForURL(`**/${folderA.uuid}?*`);
|
await page.waitForURL(`**/${folderA.uuid}?*`);
|
||||||
expect(recentObjectsList.getByRole('listitem').nth(0).getByText(folderA.name)).toBeTruthy();
|
expect(recentObjectsList.getByRole('listitem').nth(0).getByText(folderA.name)).toBeTruthy();
|
||||||
|
|
||||||
@ -63,7 +71,11 @@ test.describe('Recent Objects', () => {
|
|||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
|
|
||||||
// Verify rename has been applied in recent objects list item and objects paths
|
// Verify rename has been applied in recent objects list item and objects paths
|
||||||
expect(page.getByRole('listitem', { name: clock.name }).locator('a').getByText(folderA.name)).toBeTruthy();
|
expect(await page.getByRole('navigation', {
|
||||||
|
name: `${clock.name} Breadcrumb`
|
||||||
|
}).locator('a').filter({
|
||||||
|
hasText: folderA.name
|
||||||
|
}).count()).toBeGreaterThan(0);
|
||||||
expect(recentObjectsList.getByRole('listitem', { name: folderA.name })).toBeTruthy();
|
expect(recentObjectsList.getByRole('listitem', { name: folderA.name })).toBeTruthy();
|
||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
@ -79,7 +91,42 @@ test.describe('Recent Objects', () => {
|
|||||||
await expect(recentObjectsList.getByRole('listitem', { name: folderA.name })).toBeHidden();
|
await expect(recentObjectsList.getByRole('listitem', { name: folderA.name })).toBeHidden();
|
||||||
await expect(recentObjectsList.getByRole('listitem', { name: clock.name })).toBeHidden();
|
await expect(recentObjectsList.getByRole('listitem', { name: clock.name })).toBeHidden();
|
||||||
});
|
});
|
||||||
test.fixme("Clicking on the 'target button' scrolls the object into view in the tree and highlights it");
|
test("Clicking on an object in the path of a recent object navigates to the object", async ({ page, openmctConfig }) => {
|
||||||
test.fixme("Clicking on an object in the path of a recent object navigates to the object");
|
const { myItemsFolderName } = openmctConfig;
|
||||||
test.fixme("Tests for context menu actions from recent objects");
|
test.info().annotations.push({
|
||||||
|
type: 'issue',
|
||||||
|
description: 'https://github.com/nasa/openmct/issues/6151'
|
||||||
|
});
|
||||||
|
await page.goto('./#/browse/mine');
|
||||||
|
|
||||||
|
// Navigate to the folder by clicking on its entry in the Clock's breadcrumb
|
||||||
|
const waitForFolderNavigation = page.waitForURL(`**/${folderA.uuid}?*`);
|
||||||
|
await page.getByRole('navigation', {
|
||||||
|
name: `${clock.name} Breadcrumb`
|
||||||
|
}).locator('a').filter({
|
||||||
|
hasText: folderA.name
|
||||||
|
}).click();
|
||||||
|
|
||||||
|
// Verify that the hash URL updates correctly
|
||||||
|
await waitForFolderNavigation;
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
expect(page.url()).toMatch(new RegExp(`.*${folderA.uuid}\?.*`));
|
||||||
|
|
||||||
|
// Navigate to My Items by clicking on its entry in the Clock's breadcrumb
|
||||||
|
const waitForMyItemsNavigation = page.waitForURL(`**/mine?*`);
|
||||||
|
await page.getByRole('navigation', {
|
||||||
|
name: `${clock.name} Breadcrumb`
|
||||||
|
}).locator('a').filter({
|
||||||
|
hasText: myItemsFolderName
|
||||||
|
}).click();
|
||||||
|
|
||||||
|
// Verify that the hash URL updates correctly
|
||||||
|
await waitForMyItemsNavigation;
|
||||||
|
// eslint-disable-next-line no-useless-escape
|
||||||
|
expect(page.url()).toMatch(new RegExp(`.*mine\?.*`));
|
||||||
|
});
|
||||||
|
test.fixme("Clicking on the 'target button' scrolls the object into view in the tree and highlights it", async ({ page }) => {
|
||||||
|
});
|
||||||
|
test.fixme("Tests for context menu actions from recent objects", async ({ page }) => {
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
<ul
|
<ul
|
||||||
v-if="orderedPath.length"
|
v-if="orderedPath.length"
|
||||||
class="c-location"
|
class="c-location"
|
||||||
|
:aria-label="`${domainObject.name} Breadcrumb`"
|
||||||
|
role="navigation"
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
v-for="pathObject in orderedPath"
|
v-for="pathObject in orderedPath"
|
||||||
@ -34,6 +36,7 @@
|
|||||||
:domain-object="pathObject.domainObject"
|
:domain-object="pathObject.domainObject"
|
||||||
:object-path="pathObject.objectPath"
|
:object-path="pathObject.objectPath"
|
||||||
:read-only="readOnly"
|
:read-only="readOnly"
|
||||||
|
:navigate-to-path="navigateToPath(pathObject.objectPath)"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -110,6 +113,18 @@ export default {
|
|||||||
this.orderedPath = pathWithDomainObject.slice(1, pathWithDomainObject.length - 1).reverse();
|
this.orderedPath = pathWithDomainObject.slice(1, pathWithDomainObject.length - 1).reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* Generate the hash url for the given object path, removing the '/ROOT' prefix if present.
|
||||||
|
* @param {import('../../api/objects/ObjectAPI').DomainObject[]} objectPath
|
||||||
|
*/
|
||||||
|
navigateToPath(objectPath) {
|
||||||
|
/** @type {String} */
|
||||||
|
const path = `/browse/${this.openmct.objects.getRelativePath(objectPath)}`;
|
||||||
|
|
||||||
|
return path.replace('ROOT/', '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user