import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { getLookerTriageSignals, writeLookerEvidenceDocuments } from '../../../../../src/context/ingest/adapters/looker/evidence-documents.js'; async function writeJson(root: string, relPath: string, value: unknown): Promise { const target = join(root, relPath); await mkdir(dirname(target), { recursive: true }); await writeFile(target, `${JSON.stringify(value, null, 2)}\n`, 'utf-8'); } async function readJson(root: string, relPath: string): Promise { return JSON.parse(await readFile(join(root, relPath), 'utf-8')) as T; } describe('Looker evidence documents', () => { let stagedDir: string; beforeEach(async () => { stagedDir = await mkdtemp(join(tmpdir(), 'looker-evidence-docs-')); await writeJson(stagedDir, 'explores/b2b/sales_pipeline.json', { modelName: 'b2b', exploreName: 'sales_pipeline', label: 'Sales Pipeline', description: 'Pipeline analysis explore.', fields: { dimensions: [ { name: 'opportunities.stage', label: 'Stage', type: 'string', sql: '${TABLE}.stage', description: null }, ], measures: [ { name: 'opportunities.arr', label: 'ARR', type: 'sum', sql: '${TABLE}.arr', description: 'Annual recurring revenue.', }, ], }, joins: [{ name: 'accounts', type: 'left_outer', relationship: 'many_to_one' }], }); await writeJson(stagedDir, 'dashboards/10.json', { lookerId: '10', title: 'Sales Pipeline Overview', description: 'Executive dashboard for open pipeline ARR.', folderId: '7', ownerId: '3', updatedAt: '2026-04-30T10:00:00.000Z', tiles: [ { id: '100', title: 'Open Pipeline ARR', lookId: null, query: { model: 'b2b', view: 'sales_pipeline', fields: ['opportunities.arr', 'opportunities.stage'], filters: { 'opportunities.stage': 'open' }, sorts: ['opportunities.arr desc'], limit: '500', }, }, ], }); await writeJson(stagedDir, 'looks/20.json', { lookerId: '20', title: 'Active Opportunity Pipeline', description: 'Saved Look for active opportunity pipeline review.', folderId: '7', ownerId: '3', updatedAt: '2026-04-30T11:00:00.000Z', query: { model: 'b2b', view: 'sales_pipeline', fields: ['opportunities.arr'], filters: { 'opportunities.stage': 'open' }, sorts: [], limit: '500', }, }); await writeJson(stagedDir, 'signals/dashboard_usage.json', [ { contentId: '10', queryCount30d: 80, uniqueUsers30d: 12, lastRunAt: '2026-04-30T09:00:00.000Z', topUsers: ['3'], }, ]); await writeJson(stagedDir, 'signals/look_usage.json', [ { contentId: '20', queryCount30d: 2, uniqueUsers30d: 1, lastRunAt: '2026-04-29T09:00:00.000Z', topUsers: ['3'], }, ]); await writeJson(stagedDir, 'signals/scheduled_plans.json', [ { contentId: '10', contentType: 'dashboard', isScheduled: true, scheduleCount: 2, recipientCount: 5 }, ]); await writeJson(stagedDir, 'signals/favorites.json', [ { contentId: '10', contentType: 'dashboard', favoriteCount: 4 }, ]); }); afterEach(async () => { await rm(stagedDir, { recursive: true, force: true }); }); it('writes indexable metadata and markdown for explores, dashboards, and Looks', async () => { await writeLookerEvidenceDocuments(stagedDir); await expect(readJson(stagedDir, 'evidence/explores/b2b/sales_pipeline/metadata.json')).resolves.toMatchObject({ objectType: 'looker_explore', id: 'looker:explore:b2b.sales_pipeline', title: 'Sales Pipeline', path: 'Looker / Explores / b2b.sales_pipeline', properties: { rawPath: 'explores/b2b/sales_pipeline.json', modelName: 'b2b', exploreName: 'sales_pipeline', }, }); await expect(readJson(stagedDir, 'evidence/dashboards/10/metadata.json')).resolves.toMatchObject({ objectType: 'looker_dashboard', id: 'looker:dashboard:10', title: 'Sales Pipeline Overview', path: 'Looker / Dashboards / Sales Pipeline Overview', lastEditedAt: '2026-04-30T10:00:00.000Z', properties: { rawPath: 'dashboards/10.json', lookerId: '10', }, }); await expect(readJson(stagedDir, 'evidence/looks/20/metadata.json')).resolves.toMatchObject({ objectType: 'looker_look', id: 'looker:look:20', title: 'Active Opportunity Pipeline', path: 'Looker / Looks / Active Opportunity Pipeline', properties: { rawPath: 'looks/20.json', lookerId: '20', }, }); const dashboardMarkdown = await readFile(join(stagedDir, 'evidence/dashboards/10/page.md'), 'utf-8'); expect(dashboardMarkdown).toContain('# Sales Pipeline Overview'); expect(dashboardMarkdown).toContain('Executive dashboard for open pipeline ARR.'); expect(dashboardMarkdown).toContain('## Tile: Open Pipeline ARR'); expect(dashboardMarkdown).toContain('- model: b2b'); expect(dashboardMarkdown).toContain('- explore: sales_pipeline'); expect(dashboardMarkdown).toContain('- opportunities.stage = open'); expect(dashboardMarkdown).not.toContain('80'); expect(dashboardMarkdown).not.toContain('queryCount30d'); expect(dashboardMarkdown).not.toContain('recipient'); expect(dashboardMarkdown).not.toContain('favorite'); expect(dashboardMarkdown).not.toContain('owner'); }); it('returns usage-aware triage signals without exposing usage as document prose', async () => { await writeLookerEvidenceDocuments(stagedDir); await expect(getLookerTriageSignals(stagedDir, 'looker:dashboard:10')).resolves.toEqual({ objectType: 'looker_dashboard', propertyHints: { contentType: 'dashboard', queryCount30d: '80', uniqueUsers30d: '12', isScheduled: 'true', favoriteCount: '4', }, lastEditedAt: '2026-04-30T10:00:00.000Z', }); await expect(getLookerTriageSignals(stagedDir, 'looker:look:20')).resolves.toEqual({ objectType: 'looker_look', propertyHints: { contentType: 'look', queryCount30d: '2', uniqueUsers30d: '1', isScheduled: 'false', favoriteCount: '0', }, lastEditedAt: '2026-04-30T11:00:00.000Z', }); }); });