import { describe, expect, it, vi } from 'vitest'; import { HistoricSqlGrantsMissingError } from '../../../../src/context/ingest/adapters/historic-sql/errors.js'; import { BigQueryJobsByProjectProbeRunner } from '../../../../src/context/ingest/historic-sql-probes/bigquery-runner.js'; describe('BigQueryJobsByProjectProbeRunner', () => { it('creates a region-scoped reader, runs it, and cleans up the connector', async () => { const cleanup = vi.fn(async () => undefined); const reader = { probe: vi.fn(async () => ({ warnings: [], info: ['region: eu'] })), }; const createReader = vi.fn(() => reader); const runner = new BigQueryJobsByProjectProbeRunner({ createReader, createClient: () => ({ client: { executeQuery: vi.fn() }, cleanup }), resolveReference: () => '{"project_id":"project-1"}', }); await expect( runner.run({ projectDir: '/work/project', connectionId: 'bq', connection: { driver: 'bigquery', credentials_json: 'env:BQ_CREDENTIALS_JSON', location: 'EU', }, env: {}, }), ).resolves.toEqual({ warnings: [], info: ['region: eu'] }); expect(createReader).toHaveBeenCalledWith({ projectId: 'project-1', region: 'EU' }); expect(reader.probe).toHaveBeenCalledOnce(); expect(cleanup).toHaveBeenCalledOnce(); }); it('uses us as the default BigQuery region', async () => { const createReader = vi.fn(() => ({ probe: vi.fn(async () => ({ warnings: [], info: [] })), })); const runner = new BigQueryJobsByProjectProbeRunner({ createReader, createClient: () => ({ client: {}, cleanup: vi.fn(async () => undefined) }), resolveReference: () => '{"project_id":"project-1"}', }); await runner.run({ projectDir: '/work/project', connectionId: 'bq', connection: { driver: 'bigquery', credentials_json: '{"project_id":"project-1"}', }, env: {}, }); expect(createReader).toHaveBeenCalledWith({ projectId: 'project-1', region: 'us' }); }); it('rejects missing BigQuery credentials_json.project_id', async () => { const runner = new BigQueryJobsByProjectProbeRunner({ createReader: vi.fn(), createClient: () => ({ client: {}, cleanup: vi.fn() }), resolveReference: () => '{"client_email":"svc@example.test"}', }); await expect( runner.run({ projectDir: '/work/project', connectionId: 'bq', connection: { driver: 'bigquery', credentials_json: 'env:BQ_CREDENTIALS_JSON', }, env: {}, }), ).rejects.toThrow('Query history BigQuery connection bq requires credentials_json.project_id'); }); it('formats successful BigQuery details', () => { const runner = new BigQueryJobsByProjectProbeRunner(); expect( runner.formatSuccessDetail({ warnings: ['JOBS_BY_PROJECT is delayed'], info: ['region: us'], }), ).toEqual({ detail: 'INFORMATION_SCHEMA.JOBS_BY_PROJECT ready; region: us', warnings: ['JOBS_BY_PROJECT is delayed'], }); }); it('maps BigQuery grant errors to runner advice', () => { const runner = new BigQueryJobsByProjectProbeRunner(); expect( runner.fixAdvice( new HistoricSqlGrantsMissingError({ dialect: 'bigquery', message: 'principal cannot query JOBS_BY_PROJECT', remediation: 'Grant roles/bigquery.resourceViewer on the BigQuery project, or grant a custom role containing bigquery.jobs.listAll.', }), ), ).toEqual({ failHeadline: 'BigQuery principal cannot read INFORMATION_SCHEMA.JOBS_BY_PROJECT', remediation: 'Grant roles/bigquery.resourceViewer on the BigQuery project, or grant a custom role containing bigquery.jobs.listAll.', }); }); });