diff --git a/assets/auto-imports.d.ts b/assets/auto-imports.d.ts index 9784eb32..c6b6db12 100644 --- a/assets/auto-imports.d.ts +++ b/assets/auto-imports.d.ts @@ -420,7 +420,7 @@ declare global { export type { DrawerWidth } from './composable/drawer' import('./composable/drawer') // @ts-ignore - export type { LogStreamSource } from './composable/eventStreams' + export type { SearchStatus, LogStreamSource } from './composable/eventStreams' import('./composable/eventStreams') // @ts-ignore export type { ExprEditorOptions } from './composable/exprEditor' diff --git a/assets/components.d.ts b/assets/components.d.ts index 6f570ce2..8e54aceb 100644 --- a/assets/components.d.ts +++ b/assets/components.d.ts @@ -182,6 +182,7 @@ declare module 'vue' { ScrollableView: typeof import('./components/ScrollableView.vue')['default'] ScrollProgress: typeof import('./components/ScrollProgress.vue')['default'] Search: typeof import('./components/Search.vue')['default'] + SearchStatus: typeof import('./components/LogViewer/SearchStatus.vue')['default'] ServiceLog: typeof import('./components/ServiceViewer/ServiceLog.vue')['default'] SideDrawer: typeof import('./components/common/SideDrawer.vue')['default'] SideMenu: typeof import('./components/SideMenu.vue')['default'] diff --git a/assets/components/LogViewer/EventSource.spec.ts b/assets/components/LogViewer/EventSource.spec.ts index ccb67d2c..2a855a10 100644 --- a/assets/components/LogViewer/EventSource.spec.ts +++ b/assets/components/LogViewer/EventSource.spec.ts @@ -9,6 +9,7 @@ import { computed, nextTick } from "vue"; import { createI18n } from "vue-i18n"; import { createRouter, createWebHistory } from "vue-router"; import { default as Component } from "./EventSource.vue"; +import SearchStatus from "./SearchStatus.vue"; import LogViewer from "@/components/LogViewer/LogViewer.vue"; import { Container } from "@/models/Container"; import { Level } from "@/models/LogEntry"; @@ -172,6 +173,32 @@ describe("", () => { expect(message).toMatchSnapshot(); }); + describe("search status", () => { + test("shows no-logs when not searching and the stream is empty", async () => { + const wrapper = createLogEventSource(); + sources[sourceUrl].emitOpen(); + + await vi.advanceTimersByTimeAsync(3500); + await nextTick(); + + expect(wrapper.find('[data-testid="no-logs"]').exists()).toBe(true); + }); + + test("suppresses no-logs while a search is still running", async () => { + const wrapper = createLogEventSource(); + sources[sourceUrl].emitOpen(); + sources[sourceUrl].emit("search-status", { + data: JSON.stringify({ scannedTo: "2026-06-01T14:31:00Z", matches: 0, done: false }), + }); + + vi.advanceTimersByTime(3000); + await nextTick(); + + expect(wrapper.find('[data-testid="no-logs"]').exists()).toBe(false); + expect(wrapper.findComponent(SearchStatus).exists()).toBe(true); + }); + }); + describe("render html correctly", () => { test("should render messages", async () => { const wrapper = createLogEventSource(); diff --git a/assets/components/LogViewer/EventSource.vue b/assets/components/LogViewer/EventSource.vue index 9161c1c2..f7783215 100644 --- a/assets/components/LogViewer/EventSource.vue +++ b/assets/components/LogViewer/EventSource.vue @@ -1,12 +1,13 @@