import { afterEach, describe, expect, it } from "vitest"; import { createRequire } from "node:module"; const require = createRequire(import.meta.url); const mock = require("mock-require"); const graphqlRequestModuleId = require.resolve("graphql-request"); const queriesModuleId = require.resolve("../graphql-client/queries"); const rrLoggerModuleId = require.resolve("./rr-logger-event"); const rrExportLogsModuleId = require.resolve("./rr-export-logs"); const loadExportLogs = ({ requests }) => { mock.stopAll(); mock(graphqlRequestModuleId, { GraphQLClient: class MockGraphQLClient { constructor(endpoint) { this.endpoint = endpoint; this.headers = {}; } setHeaders(headers) { this.headers = headers; return this; } async request(query, variables) { requests.push({ endpoint: this.endpoint, headers: this.headers, query, variables }); return {}; } } }); mock(queriesModuleId, { INSERT_EXPORT_LOG: "INSERT_EXPORT_LOG", MARK_JOB_EXPORTED: "MARK_JOB_EXPORTED" }); mock(rrLoggerModuleId, () => {}); delete require.cache[rrExportLogsModuleId]; return require(rrExportLogsModuleId); }; const socket = { data: { authToken: "socket-token" }, user: { email: "tech@example.com" } }; const job = { id: "job-1", bodyshop: { id: "bodyshop-1", md_ro_statuses: { default_exported: "Exported" } } }; describe("server/rr/rr-export-logs", () => { const originalEndpoint = process.env.GRAPHQL_ENDPOINT; afterEach(() => { mock.stopAll(); delete require.cache[rrExportLogsModuleId]; process.env.GRAPHQL_ENDPOINT = originalEndpoint; }); it("marks Reynolds full exports as exported using the shared DMS export mutation", async () => { process.env.GRAPHQL_ENDPOINT = "https://graphql.example.test/v1/graphql"; const requests = []; const { markRRExportSuccess } = loadExportLogs({ requests }); await markRRExportSuccess({ socket, jobId: job.id, job, bodyshop: job.bodyshop, result: { success: true, roStatus: { status: "SUCCESS", statusCode: "0", message: "Finalized" } } }); expect(requests).toHaveLength(1); expect(requests[0]).toMatchObject({ endpoint: "https://graphql.example.test/v1/graphql", headers: { Authorization: "Bearer socket-token" }, query: "MARK_JOB_EXPORTED", variables: { jobId: "job-1", job: { status: "Exported", date_exported: expect.any(Date) }, log: { bodyshopid: "bodyshop-1", jobid: "job-1", successful: true, useremail: "tech@example.com" }, bill: { exported: true, exported_at: expect.any(Date) } } }); }); it("uses the separately loaded bodyshop statuses when job.bodyshop is missing", async () => { process.env.GRAPHQL_ENDPOINT = "https://graphql.example.test/v1/graphql"; const requests = []; const { markRRExportSuccess } = loadExportLogs({ requests }); await markRRExportSuccess({ socket, jobId: job.id, job: { id: job.id }, bodyshop: job.bodyshop, result: { success: true, roStatus: { status: "SUCCESS", statusCode: "0", message: "Finalized" } } }); expect(requests).toHaveLength(1); expect(requests[0]).toMatchObject({ query: "MARK_JOB_EXPORTED", variables: { jobId: "job-1", job: { status: "Exported", date_exported: expect.any(Date) }, log: { bodyshopid: "bodyshop-1", jobid: "job-1", successful: true, useremail: "tech@example.com" } } }); }); it("does not mark Reynolds early RO creation as exported", async () => { process.env.GRAPHQL_ENDPOINT = "https://graphql.example.test/v1/graphql"; const requests = []; const { markRRExportSuccess } = loadExportLogs({ requests }); await markRRExportSuccess({ socket, jobId: job.id, job, bodyshop: job.bodyshop, result: { success: true }, isEarlyRo: true }); expect(requests).toHaveLength(1); expect(requests[0]).toMatchObject({ query: "INSERT_EXPORT_LOG", variables: { logs: [ { bodyshopid: "bodyshop-1", jobid: "job-1", successful: true, useremail: "tech@example.com" } ] } }); }); });