Skip to content

Commit

Permalink
Merge pull request #123 from codegouvfr/test-backend-routes
Browse files Browse the repository at this point in the history
test backend routes
  • Loading branch information
JeromeBu authored Jun 7, 2024
2 parents 8528edf + a521225 commit c635ac2
Show file tree
Hide file tree
Showing 12 changed files with 391 additions and 21 deletions.
60 changes: 60 additions & 0 deletions api/src/core/adapters/dbApi/InMemoryDbApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { CompiledData } from "../../ports/CompileData";
import type { Db, DbApi } from "../../ports/DbApi";

export class InMemoryDbApi implements DbApi {
#softwareRows: Db.SoftwareRow[] = [];
#agentRows: Db.AgentRow[] = [];
#softwareReferentRows: Db.SoftwareReferentRow[] = [];
#softwareUserRows: Db.SoftwareUserRow[] = [];
#instanceRows: Db.InstanceRow[] = [];

#compiledData: CompiledData<"private"> = [];

async fetchDb() {
return {
softwareRows: this.#softwareRows,
agentRows: this.#agentRows,
softwareReferentRows: this.#softwareReferentRows,
softwareUserRows: this.#softwareUserRows,
instanceRows: this.#instanceRows
};
}

async updateDb({ newDb }: { newDb: Db }) {
this.#softwareRows = newDb.softwareRows;
this.#agentRows = newDb.agentRows;
this.#softwareReferentRows = newDb.softwareReferentRows;
this.#softwareUserRows = newDb.softwareUserRows;
this.#instanceRows = newDb.instanceRows;
}

async fetchCompiledData() {
return this.#compiledData;
}

async updateCompiledData({ newCompiledData }: { newCompiledData: CompiledData<"private"> }) {
this.#compiledData = newCompiledData;
}

// test helpers

get softwareRows() {
return this.#softwareRows;
}

get agentRows() {
return this.#agentRows;
}

get softwareReferentRows() {
return this.#softwareReferentRows;
}

get softwareUserRows() {
return this.#softwareUserRows;
}

get instanceRows() {
return this.#instanceRows;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { DbApi, Db } from "../ports/DbApi";
import { gitSsh } from "../../tools/gitSsh";
import type { DbApi, Db } from "../../ports/DbApi";
import { gitSsh } from "../../../tools/gitSsh";
import { Deferred } from "evt/tools/Deferred";
import { type CompiledData, compiledDataPrivateToPublic } from "../ports/CompileData";
import { type CompiledData, compiledDataPrivateToPublic } from "../../ports/CompileData";
import * as fs from "fs";
import { join as pathJoin } from "path";
import type { ReturnType } from "tsafe";
Expand All @@ -24,7 +24,7 @@ export type GitDbApiParams = {
sshPrivateKey: string;
};

export function createGitDbApi(params: GitDbApiParams): { dbApi: DbApi; initializeDbApiCache: () => Promise<void> } {
export function createGitDbApi(params: GitDbApiParams): Db.DbApiAndInitializeCache {
const { dataRepoSshUrl, sshPrivateKeyName, sshPrivateKey } = params;

const dbApi: DbApi = {
Expand Down
7 changes: 2 additions & 5 deletions api/src/core/adapters/hal/getHalSoftware.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { describe, expect, it } from "vitest";
import { describe, it } from "vitest";
import { expectToEqual } from "../../../tools/test.helpers";
import { getHalSoftware } from "./getHalSoftware";
import { getHalSoftwareOptions } from "./getHalSoftwareOptions";

const expectToEqual = <T>(actual: T, expected: T) => {
expect(actual).toEqual(expected);
};

describe("HAL", () => {
describe("getHalSoftware", () => {
it("gets data from Hal and converts it to ExternalSoftware", async () => {
Expand Down
27 changes: 22 additions & 5 deletions api/src/core/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { createCore, createObjectThatThrowsIfAccessed, type GenericCore } from "redux-clean-architecture";
import { createCompileData } from "./adapters/compileData";
import { comptoirDuLibreApi } from "./adapters/comptoirDuLibreApi";
import { createGitDbApi, type GitDbApiParams } from "./adapters/dbApi";
import { createGitDbApi, type GitDbApiParams } from "./adapters/dbApi/createGitDbApi";
import { InMemoryDbApi } from "./adapters/dbApi/InMemoryDbApi";
import { getCnllPrestatairesSill } from "./adapters/getCnllPrestatairesSill";
import { getServiceProviders } from "./adapters/getServiceProviders";
import { createGetSoftwareLatestVersion } from "./adapters/getSoftwareLatestVersion";
Expand All @@ -12,15 +13,20 @@ import { getHalSoftwareOptions } from "./adapters/hal/getHalSoftwareOptions";
import { createKeycloakUserApi, type KeycloakUserApiParams } from "./adapters/userApi";
import type { CompileData } from "./ports/CompileData";
import type { ComptoirDuLibreApi } from "./ports/ComptoirDuLibreApi";
import type { DbApi } from "./ports/DbApi";
import { DbApi, Db } from "./ports/DbApi";
import type { ExternalDataOrigin, GetSoftwareExternalData } from "./ports/GetSoftwareExternalData";
import type { GetSoftwareExternalDataOptions } from "./ports/GetSoftwareExternalDataOptions";
import type { GetSoftwareLatestVersion } from "./ports/GetSoftwareLatestVersion";
import type { UserApi } from "./ports/UserApi";
import { usecases } from "./usecases";

type GitDbConfig = { dbKind: "git" } & GitDbApiParams;
type InMemoryDbConfig = { dbKind: "inMemory" };

type DbConfig = GitDbConfig | InMemoryDbConfig;

type ParamsOfBootstrapCore = {
gitDbApiParams: GitDbApiParams;
dbConfig: DbConfig;
keycloakUserApiParams: KeycloakUserApiParams | undefined;
githubPersonalAccessTokenForApiRateLimit: string;
doPerPerformPeriodicalCompilation: boolean;
Expand All @@ -45,9 +51,20 @@ export type State = Core["types"]["State"];
export type Thunks = Core["types"]["Thunks"];
export type CreateEvt = Core["types"]["CreateEvt"];

const getDbApiAndInitializeCache = (dbConfig: DbConfig): Db.DbApiAndInitializeCache => {
if (dbConfig.dbKind === "git") return createGitDbApi(dbConfig);
if (dbConfig.dbKind === "inMemory")
return {
dbApi: new InMemoryDbApi(),
initializeDbApiCache: async () => {}
};
const shouldNotBeReached: never = dbConfig;
throw new Error(`Unsupported case: ${shouldNotBeReached}`);
};

export async function bootstrapCore(params: ParamsOfBootstrapCore): Promise<{ core: Core; context: Context }> {
const {
gitDbApiParams,
dbConfig,
keycloakUserApiParams,
githubPersonalAccessTokenForApiRateLimit,
doPerPerformPeriodicalCompilation,
Expand All @@ -70,7 +87,7 @@ export async function bootstrapCore(params: ParamsOfBootstrapCore): Promise<{ co
getServiceProviders
});

const { dbApi, initializeDbApiCache } = createGitDbApi(gitDbApiParams);
const { dbApi, initializeDbApiCache } = getDbApiAndInitializeCache(dbConfig);

const { userApi, initializeUserApiCache } =
keycloakUserApiParams === undefined
Expand Down
2 changes: 2 additions & 0 deletions api/src/core/ports/DbApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ export namespace Db {
referencedSinceTime: number;
updateTime: number;
};

export type DbApiAndInitializeCache = { dbApi: DbApi; initializeDbApiCache: () => Promise<void> };
}

export type Os = "windows" | "linux" | "mac" | "android" | "ios";
Expand Down
49 changes: 49 additions & 0 deletions api/src/rpc/createTestCaller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { bootstrapCore } from "../core";
import { InMemoryDbApi } from "../core/adapters/dbApi/InMemoryDbApi";
import { ExternalDataOrigin } from "../core/ports/GetSoftwareExternalData";
import { createRouter } from "./router";
import { User } from "./user";

type TestCallerConfig = {
user: User | undefined;
};

export const defaultUser: User = {
id: "1",
email: "[email protected]",
organization: "Default Organization"
};

export type ApiCaller = Awaited<ReturnType<typeof createTestCaller>>["apiCaller"];

export const createTestCaller = async ({ user }: TestCallerConfig = { user: defaultUser }) => {
const externalSoftwareDataOrigin: ExternalDataOrigin = "wikidata";

const { core, context } = await bootstrapCore({
"dbConfig": { dbKind: "inMemory" },
"keycloakUserApiParams": undefined,
"githubPersonalAccessTokenForApiRateLimit": "fake-token",
"doPerPerformPeriodicalCompilation": false,
"doPerformCacheInitialization": false,
"externalSoftwareDataOrigin": externalSoftwareDataOrigin
});

const jwtClaimByUserKey = {
"id": "sub",
"email": "email",
"organization": "organization"
};

const { router } = createRouter({
core,
coreContext: context,
keycloakParams: undefined,
redirectUrl: undefined,
externalSoftwareDataOrigin,
readmeUrl: "http://readme.url",
termsOfServiceUrl: "http://terms.url",
jwtClaimByUserKey
});

return { apiCaller: router.createCaller({ user }), inMemoryDb: context.dbApi as InMemoryDbApi };
};
6 changes: 3 additions & 3 deletions api/src/rpc/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { assert } from "tsafe/assert";
import { z } from "zod";
import type { Context as CoreContext, Core } from "../core";
import { ExternalDataOrigin, Language, languages, type LocalizedString } from "../core/ports/GetSoftwareExternalData";
import type {
import {
DeclarationFormData,
InstanceFormData,
Os,
Expand Down Expand Up @@ -373,8 +373,8 @@ export function createRouter(params: {

return { agent };
}),
"getAllowedEmailRegexp": loggedProcedure.query(coreContext.userApi.getAllowedEmailRegexp),
"getAllOrganizations": loggedProcedure.query(coreContext.userApi.getAllOrganizations),
"getAllowedEmailRegexp": loggedProcedure.query(() => coreContext.userApi.getAllowedEmailRegexp()),
"getAllOrganizations": loggedProcedure.query(() => coreContext.userApi.getAllOrganizations()),
"changeAgentOrganization": loggedProcedure
.input(
z.object({
Expand Down
Loading

0 comments on commit c635ac2

Please sign in to comment.