mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
fix(frontend): browser tab notification respects user-renamed titles; add unit test (#10406)
This commit is contained in:
parent
794381c22b
commit
0ec6ed20cb
51
frontend/__tests__/utils/browser-tab.test.ts
Normal file
51
frontend/__tests__/utils/browser-tab.test.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
|
||||
import { browserTab } from "#/utils/browser-tab";
|
||||
|
||||
// These tests exercise the browser-tab notification flasher behavior.
|
||||
// Specifically we verify that when the document title changes externally
|
||||
// while a notification is active, the flasher updates its internal
|
||||
// baseline so it restores/toggles to the new title instead of an old one.
|
||||
|
||||
describe("browserTab notifications", () => {
|
||||
const MESSAGE = "Agent ready";
|
||||
const INITIAL = "Conversation 123 | OpenHands";
|
||||
const RENAMED = "My renamed title | OpenHands";
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
// reset title for each test
|
||||
document.title = INITIAL;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
browserTab.stopNotification();
|
||||
vi.runOnlyPendingTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("updates baseline when title changes during an active notification and restores to the new title", () => {
|
||||
// Start flashing
|
||||
browserTab.startNotification(MESSAGE);
|
||||
|
||||
// Tick once: should switch to the message
|
||||
vi.advanceTimersByTime(1000);
|
||||
expect(document.title).toBe(MESSAGE);
|
||||
|
||||
// Simulate an external rename while flashing (e.g., user edits title)
|
||||
document.title = RENAMED;
|
||||
|
||||
// Next tick: flasher observes the external change and updates baseline
|
||||
vi.advanceTimersByTime(1000);
|
||||
// On this tick, we toggle back to the message
|
||||
expect(document.title).toBe(MESSAGE);
|
||||
|
||||
// Next tick should toggle to the updated baseline (renamed title)
|
||||
vi.advanceTimersByTime(1000);
|
||||
expect(document.title).toBe(RENAMED);
|
||||
|
||||
// Stop flashing: title should remain the updated baseline
|
||||
browserTab.stopNotification();
|
||||
expect(document.title).toBe(RENAMED);
|
||||
});
|
||||
});
|
||||
@ -11,20 +11,23 @@ export const browserTab = {
|
||||
startNotification(message: string) {
|
||||
if (!isBrowser) return;
|
||||
|
||||
// Store original title if not already stored
|
||||
if (!originalTitle) {
|
||||
originalTitle = document.title;
|
||||
}
|
||||
// Always capture the current title as the baseline to restore to
|
||||
originalTitle = document.title;
|
||||
|
||||
// Clear any existing interval
|
||||
if (titleInterval) {
|
||||
this.stopNotification();
|
||||
}
|
||||
|
||||
// Alternate between original title and notification message
|
||||
// Alternate between the latest baseline title and the notification message.
|
||||
// If the title changes externally (e.g., user renames conversation),
|
||||
// update the baseline so we restore to the new value when stopping.
|
||||
titleInterval = window.setInterval(() => {
|
||||
document.title =
|
||||
document.title === originalTitle ? message : originalTitle;
|
||||
const current = document.title;
|
||||
if (current !== originalTitle && current !== message) {
|
||||
originalTitle = current;
|
||||
}
|
||||
document.title = current === message ? originalTitle : message;
|
||||
}, 1000);
|
||||
|
||||
// Set favicon to indicate notification
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user