Fix 12844 notification external link (#12845)

* Fix external notification links

* Add notification link regression test

* Preserve fallback for empty notification links

* Satisfy Biome optional-chain check

* Apply Biome formatting

* Retrigger CI

---------

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
Leonid Zaliubovskyi
2026-09-13 11:37:55 +00:00
committed by GitHub
co-authored by Oliver
parent b14a4e7812
commit 13cc62567c
2 changed files with 98 additions and 2 deletions
@@ -62,6 +62,10 @@ function NotificationEntry({
}
}
const base = `/${getBaseUrl()}`;
const href =
link?.startsWith('/') && !link.startsWith(base) ? `${base}${link}` : link;
return (
<Paper p='xs' shadow='xs'>
<Group justify='space-between' wrap='nowrap'>
@@ -72,7 +76,7 @@ function NotificationEntry({
>
<Stack gap={2}>
<Anchor
href={link ? `/${getBaseUrl()}${link}` : '#'}
href={href || '#'}
underline='hover'
target='_blank'
onClick={(event: any) => {
@@ -81,7 +85,7 @@ function NotificationEntry({
onRead();
}
if (link.startsWith('/')) {
if (link?.startsWith('/')) {
navigateToLink(link, navigate, event);
}
}}
@@ -0,0 +1,92 @@
import { expect, test } from './baseFixtures.js';
import { doLogin } from './login.js';
const notifications = [
{
pk: 1,
target: {
model_type: 'pluginconfig',
model_id: 1,
link: 'https://example.com/path'
},
source: null,
user: 1,
category: 'test_external',
name: 'External Notification',
message: 'External notification link',
creation: '2026-09-12 12:00',
age: 1,
age_human: 'a moment ago',
read: false
},
{
pk: 2,
target: {
model_type: 'pluginconfig',
model_id: 1,
link: '/settings/admin/'
},
source: null,
user: 1,
category: 'test_internal',
name: 'Internal Notification',
message: 'Internal notification link',
creation: '2026-09-12 12:00',
age: 1,
age_human: 'a moment ago',
read: false
},
{
pk: 3,
target: {
model_type: 'pluginconfig',
model_id: 1,
link: '/web/settings/admin/'
},
source: null,
user: 1,
category: 'test_base',
name: 'Base Notification',
message: 'Notification link with base path',
creation: '2026-09-12 12:00',
age: 1,
age_human: 'a moment ago',
read: false
}
];
test('Notifications - link targets', async ({ page }) => {
await page.route('**/api/notifications/**', async (route) => {
if (route.request().method() !== 'GET') {
await route.continue();
return;
}
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
count: notifications.length,
next: null,
previous: null,
results: notifications
})
});
});
await doLogin(page);
await page.getByRole('button', { name: 'open-notifications' }).click();
await expect(
page.getByRole('link', { name: 'External Notification' })
).toHaveAttribute('href', 'https://example.com/path');
await expect(
page.getByRole('link', { name: 'Internal Notification' })
).toHaveAttribute('href', '/web/settings/admin/');
await expect(
page.getByRole('link', { name: 'Base Notification' })
).toHaveAttribute('href', '/web/settings/admin/');
});