fix(app): display study not found message for all modes (#5752)

* fix(app): move study validation to ModeRoute component

- Moved validation from defaultRouteInit.ts to Mode.tsx
- Added dedicated useEffect hook for study validation

* test: add Playwright test for study not found error page across multiple modes
This commit is contained in:
Ghadeer Albattarni authored and GitHub committed 2026-02-09 21:51:44 -05:00
1 parent 3c0dd39054
commit 7f9e59ee30
7 files changed
+159 -8

No files matched your search

+83
View File
@@ -0,0 +1,83 @@
import { expect, test } from './utils';
test.describe('Study Validation', () => {
const invalidStudyUID = '9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9.9';
const validStudyUID = '1.3.6.1.4.1.25403.345050719074.3824.20170125095438.5';
const modes = ['viewer', 'segmentation', 'microscopy', 'tmtv'];
// Test 1: Single invalid study
modes.forEach(mode => {
test(`should display error page when study UID is not found in ${mode} mode`, async ({
page,
notFoundStudyPageObject,
}) => {
await page.goto(`/${mode}/ohif?StudyInstanceUIDs=${invalidStudyUID}`);
await page.waitForURL('**/notfoundstudy', { timeout: 15000 });
await expect(notFoundStudyPageObject.errorMessage).toBeVisible();
await expect(notFoundStudyPageObject.errorMessage).toHaveText(
'One or more of the requested studies are not available at this time.'
);
await expect(notFoundStudyPageObject.returnMessage).toBeVisible();
await expect(notFoundStudyPageObject.returnMessage).toContainText(
'Return to the study list to select a different study to view.'
);
await expect(notFoundStudyPageObject.studyListLink).toBeVisible();
await expect(notFoundStudyPageObject.studyListLink).toHaveAttribute('href', '/');
});
});
// Test 2: Multiple studies - valid first, then invalid
modes.forEach(mode => {
test(`should display error page when second study UID is invalid in ${mode} mode`, async ({
page,
notFoundStudyPageObject,
}) => {
await page.goto(`/${mode}/ohif?StudyInstanceUIDs=${validStudyUID},${invalidStudyUID}`);
await page.waitForURL('**/notfoundstudy', { timeout: 15000 });
await expect(notFoundStudyPageObject.errorMessage).toBeVisible();
await expect(notFoundStudyPageObject.errorMessage).toHaveText(
'One or more of the requested studies are not available at this time.'
);
await expect(notFoundStudyPageObject.returnMessage).toBeVisible();
await expect(notFoundStudyPageObject.returnMessage).toContainText(
'Return to the study list to select a different study to view.'
);
await expect(notFoundStudyPageObject.studyListLink).toBeVisible();
await expect(notFoundStudyPageObject.studyListLink).toHaveAttribute('href', '/');
});
});
// Test 3: Multiple studies - invalid first, then valid
modes.forEach(mode => {
test(`should display error page when first study UID is invalid in ${mode} mode`, async ({
page,
notFoundStudyPageObject,
}) => {
await page.goto(`/${mode}/ohif?StudyInstanceUIDs=${invalidStudyUID},${validStudyUID}`);
await page.waitForURL('**/notfoundstudy', { timeout: 15000 });
await expect(notFoundStudyPageObject.errorMessage).toBeVisible();
await expect(notFoundStudyPageObject.errorMessage).toHaveText(
'One or more of the requested studies are not available at this time.'
);
await expect(notFoundStudyPageObject.returnMessage).toBeVisible();
await expect(notFoundStudyPageObject.returnMessage).toContainText(
'Return to the study list to select a different study to view.'
);
await expect(notFoundStudyPageObject.studyListLink).toBeVisible();
await expect(notFoundStudyPageObject.studyListLink).toHaveAttribute('href', '/');
});
});
});
+21
View File
@@ -0,0 +1,21 @@
import { Locator, Page } from '@playwright/test';
export class NotFoundStudyPageObject {
readonly page: Page;
constructor(page: Page) {
this.page = page;
}
get errorMessage(): Locator {
return this.page.locator('[data-cy="study-not-found-message"]');
}
get returnMessage(): Locator {
return this.page.locator('[data-cy="return-to-study-list-message"]');
}
get studyListLink(): Locator {
return this.page.getByRole('link', { name: 'study list' });
}
}
+2
View File
@@ -3,6 +3,7 @@ import { MainToolbarPageObject } from './MainToolbarPageObject';
import { LeftPanelPageObject } from './LeftPanelPageObject';
import { RightPanelPageObject } from './RightPanelPageObject';
import { ViewportPageObject } from './ViewportPageObject';
import { NotFoundStudyPageObject } from './NotFoundStudyPageObject';
export {
DOMOverlayPageObject,
@@ -10,4 +11,5 @@ export {
LeftPanelPageObject,
RightPanelPageObject,
ViewportPageObject,
NotFoundStudyPageObject,
};
+5
View File
@@ -5,6 +5,7 @@ import {
LeftPanelPageObject,
RightPanelPageObject,
ViewportPageObject,
NotFoundStudyPageObject,
} from '../pages';
type PageObjects = {
@@ -13,6 +14,7 @@ type PageObjects = {
leftPanelPageObject: LeftPanelPageObject;
rightPanelPageObject: RightPanelPageObject;
viewportPageObject: ViewportPageObject;
notFoundStudyPageObject: NotFoundStudyPageObject;
};
export const test = base.extend<PageObjects>({
@@ -31,6 +33,9 @@ export const test = base.extend<PageObjects>({
viewportPageObject: async ({ page }, use) => {
await use(new ViewportPageObject(page));
},
notFoundStudyPageObject: async ({ page }, use) => {
await use(new NotFoundStudyPageObject(page));
},
});
export { expect } from 'playwright-test-coverage';