import { generateRandomHash } from "@/server/utils/docker/compose"; import { addPrefixToServiceNetworks } from "@/server/utils/docker/compose/network"; import type { ComposeSpecification } from "@/server/utils/docker/types"; import { load } from "js-yaml"; import { expect, test } from "vitest"; const composeFile = ` version: "3.8" services: web: image: nginx:latest networks: - frontend - backend api: image: myapi:latest networks: - backend `; test("Add prefix to networks in services", () => { const composeData = load(composeFile) as ComposeSpecification; const prefix = generateRandomHash(); if (!composeData?.services) { return; } const services = addPrefixToServiceNetworks(composeData.services, prefix); const actualComposeData = { ...composeData, services }; expect(actualComposeData?.services?.web?.networks).toContain( `frontend-${prefix}`, ); expect(actualComposeData?.services?.api?.networks).toContain( `backend-${prefix}`, ); const apiNetworks = actualComposeData?.services?.api?.networks; expect(apiNetworks).toBeDefined(); expect(actualComposeData?.services?.api?.networks).toContain( `backend-${prefix}`, ); }); // Caso 2: Objeto con aliases const composeFile2 = ` version: "3.8" services: api: image: myapi:latest networks: frontend: aliases: - api networks: frontend: driver: bridge `; test("Add prefix to networks in services with aliases", () => { const composeData = load(composeFile2) as ComposeSpecification; const prefix = generateRandomHash(); if (!composeData?.services) { return; } const services = addPrefixToServiceNetworks(composeData.services, prefix); const actualComposeData = { ...composeData, services }; expect(actualComposeData.services?.api?.networks).toHaveProperty( `frontend-${prefix}`, ); const networkConfig = actualComposeData?.services?.api?.networks as { [key: string]: { aliases?: string[] }; }; expect(networkConfig[`frontend-${prefix}`]).toBeDefined(); expect(networkConfig[`frontend-${prefix}`]?.aliases).toContain("api"); expect(actualComposeData.services?.api?.networks).not.toHaveProperty( "frontend-ash", ); }); const composeFile3 = ` version: "3.8" services: redis: image: redis:alpine networks: backend: networks: backend: driver: bridge `; test("Add prefix to networks in services (Object with simple networks)", () => { const composeData = load(composeFile3) as ComposeSpecification; const prefix = generateRandomHash(); if (!composeData?.services) { return; } const services = addPrefixToServiceNetworks(composeData.services, prefix); const actualComposeData = { ...composeData, services }; expect(actualComposeData.services?.redis?.networks).toHaveProperty( `backend-${prefix}`, ); }); const composeFileCombined = ` version: "3.8" services: web: image: nginx:latest networks: - frontend - backend api: image: myapi:latest networks: frontend: aliases: - api redis: image: redis:alpine networks: backend: networks: frontend: driver: bridge backend: driver: bridge `; test("Add prefix to networks in services (combined case)", () => { const composeData = load(composeFileCombined) as ComposeSpecification; const prefix = generateRandomHash(); if (!composeData?.services) { return; } const services = addPrefixToServiceNetworks(composeData.services, prefix); const actualComposeData = { ...composeData, services }; // Caso 1: ListOfStrings expect(actualComposeData.services?.web?.networks).toContain( `frontend-${prefix}`, ); expect(actualComposeData.services?.web?.networks).toContain( `backend-${prefix}`, ); // Caso 2: Objeto con aliases const apiNetworks = actualComposeData.services?.api?.networks as { [key: string]: unknown; }; expect(apiNetworks).toHaveProperty(`frontend-${prefix}`); expect(apiNetworks[`frontend-${prefix}`]).toBeDefined(); expect(apiNetworks).not.toHaveProperty("frontend"); // Caso 3: Objeto con redes simples const redisNetworks = actualComposeData.services?.redis?.networks; expect(redisNetworks).toHaveProperty(`backend-${prefix}`); expect(redisNetworks).not.toHaveProperty("backend"); });