From a763ac1ae2cad8f233afd13f0ae7f52a4e1f07c5 Mon Sep 17 00:00:00 2001 From: Kevin Lamping Date: Sat, 14 Feb 2026 14:47:25 -0600 Subject: [PATCH 1/3] test: add failing test for default graph export filename --- .../src/utils/exportGraphData.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts diff --git a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts new file mode 100644 index 00000000000..27b94fdec45 --- /dev/null +++ b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, it, vi } from 'vitest'; +import * as exportUtils from './exportGraphData'; + +describe('exportGraphData', () => { + it('generates a human-friendly default filename for graph exports', () => { + vi.useFakeTimers(); + // 2026-02-14T20:27:20.000Z + vi.setSystemTime(new Date('2026-02-14T20:27:20.000Z')); + + // This function will be added in the next task + // @ts-expect-error - intentional until implemented + const name = exportUtils.getDefaultGraphExportFileName(); + + expect(name).toBe('bh-graph-2026-02-14_20-27-20.json'); + + vi.useRealTimers(); + }); +}); From 33bf9ae595190709f5847f417ae1e2d0ee19d582 Mon Sep 17 00:00:00 2001 From: Kevin Lamping Date: Sat, 14 Feb 2026 14:47:40 -0600 Subject: [PATCH 2/3] feat: generate timestamped default filename for graph exports --- .../javascript/bh-shared-ui/src/utils/exportGraphData.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts index 56217bf9dd9..65c702a6b0d 100644 --- a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts +++ b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts @@ -29,6 +29,14 @@ export const downloadFile = ({ data, fileName, fileType }: { data: any; fileName a.remove(); }; +export const getDefaultGraphExportFileName = () => { + const iso = new Date().toISOString(); + // iso: YYYY-MM-DDTHH:mm:ss.sssZ + const withoutMs = iso.replace(/\.\d{3}Z$/, ''); + const safe = withoutMs.replace('T', '_').replace(/:/g, '-'); + return `bh-graph-${safe}.json`; +}; + export const exportToJson = (data: any) => { downloadFile({ data: JSON.stringify(data), From 2c5b676c58f751089dada70425eb5f156648c7c7 Mon Sep 17 00:00:00 2001 From: Kevin Lamping Date: Sat, 14 Feb 2026 14:49:28 -0600 Subject: [PATCH 3/3] feat: use timestamped default filename for JSON graph exports --- .../src/utils/exportGraphData.test.ts | 49 ++++++++++++++++++- .../bh-shared-ui/src/utils/exportGraphData.ts | 2 +- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts index 27b94fdec45..cee23e7c168 100644 --- a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts +++ b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.test.ts @@ -7,12 +7,57 @@ describe('exportGraphData', () => { // 2026-02-14T20:27:20.000Z vi.setSystemTime(new Date('2026-02-14T20:27:20.000Z')); - // This function will be added in the next task - // @ts-expect-error - intentional until implemented const name = exportUtils.getDefaultGraphExportFileName(); expect(name).toBe('bh-graph-2026-02-14_20-27-20.json'); vi.useRealTimers(); }); + + it('uses the default filename generator when exporting JSON', () => { + vi.useFakeTimers(); + vi.setSystemTime(new Date('2026-02-14T20:27:20.000Z')); + + const originalCreateObjectURL = (window.URL as any).createObjectURL; + const createObjectUrlSpy = vi.fn(() => 'blob:mock'); + Object.defineProperty(window.URL, 'createObjectURL', { + value: createObjectUrlSpy, + writable: true, + }); + + let createdAnchor: HTMLAnchorElement | undefined; + const originalCreateElement = document.createElement.bind(document); + const createElementSpy = vi.spyOn(document, 'createElement').mockImplementation((tagName: any, options?: any) => { + const el = originalCreateElement(tagName, options) as any; + if (tagName === 'a') createdAnchor = el as HTMLAnchorElement; + return el; + }); + + const originalMouseEvent = globalThis.MouseEvent; + class MockMouseEvent extends Event { + constructor(type: string, _init?: any) { + super(type); + } + } + Object.defineProperty(globalThis, 'MouseEvent', { + value: MockMouseEvent, + writable: true, + }); + + exportUtils.exportToJson({ a: 1 }); + + expect(createdAnchor?.download).toBe('bh-graph-2026-02-14_20-27-20.json'); + expect(createObjectUrlSpy).toHaveBeenCalled(); + + createElementSpy.mockRestore(); + Object.defineProperty(window.URL, 'createObjectURL', { + value: originalCreateObjectURL, + writable: true, + }); + Object.defineProperty(globalThis, 'MouseEvent', { + value: originalMouseEvent, + writable: true, + }); + vi.useRealTimers(); + }); }); diff --git a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts index 65c702a6b0d..7c8de1c295f 100644 --- a/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts +++ b/packages/javascript/bh-shared-ui/src/utils/exportGraphData.ts @@ -40,7 +40,7 @@ export const getDefaultGraphExportFileName = () => { export const exportToJson = (data: any) => { downloadFile({ data: JSON.stringify(data), - fileName: 'bh-graph.json', + fileName: getDefaultGraphExportFileName(), fileType: 'text/json', }); };