Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b83f7a5
EW-1341: Implement backend for producer. (#6006)
mkreuzkam-cap Jan 12, 2026
5ad2eb6
Merge branch 'main' into EW-1355
mkreuzkam-cap Jan 12, 2026
4b9c1bd
EW-1340 (#6014): Implement consumer.
mkreuzkam-cap Jan 27, 2026
074ba4c
Merge branch 'main' into EW-1355
mkreuzkam-cap Jan 27, 2026
7cca7b0
Merge branch 'main' into EW-1355
mkreuzkam-cap Jan 27, 2026
6e7bc86
Merge branch 'main' into EW-1355
mkreuzkam-cap Jan 28, 2026
9aaceac
replace LoggerModule with CoreModule
alweber-cap Jan 29, 2026
1cd4d44
Wrap entry method into try-catch.
mkreuzkam-cap Jan 29, 2026
a8f610b
Another try with a different errorHandler.
mkreuzkam-cap Jan 29, 2026
84aa51b
Test other logging methods.
mkreuzkam-cap Jan 29, 2026
da7ed1c
Use errorLogger
mkreuzkam-cap Jan 29, 2026
8621c4c
Revert error handling tests.
mkreuzkam-cap Jan 29, 2026
413170f
EW-1355: Add debug logs to import consumer.
mkreuzkam-cap Jan 30, 2026
e664703
Merge branch 'main' into EW-1355
mkreuzkam-cap Jan 30, 2026
7df21a8
EW-1355: Optimize import consumer.
mkreuzkam-cap Jan 30, 2026
248ff92
Merge branch 'main' into EW-1355
mkreuzkam-cap Feb 2, 2026
84775bb
Add interceptors for axios.
mkreuzkam-cap Feb 3, 2026
93ea509
Merge branch 'main' into EW-1355
mkreuzkam-cap Feb 3, 2026
ba2aede
Only throw error in interceptor.
mkreuzkam-cap Feb 4, 2026
67d5c3e
Use errorhandler in axios interceptor.
mkreuzkam-cap Feb 4, 2026
b04e88a
Fix coverage in import consumer.
mkreuzkam-cap Feb 4, 2026
5f0f592
Merge branch 'main' into EW-1355
SimoneRadtke-Cap Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 34 additions & 13 deletions apps/server/src/infra/boards-client/boards-client.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { faker } from '@faker-js/faker';
import { createMock } from '@golevelup/ts-jest';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { axiosResponseFactory } from '@testing/factory/axios-response.factory';
import { BoardsClientAdapter } from './boards-client.adapter';
Expand All @@ -8,20 +8,20 @@ import { BoardApi, BoardResponse, CreateBoardBodyParams, CreateBoardResponse } f
describe(BoardsClientAdapter.name, () => {
let module: TestingModule;
let sut: BoardsClientAdapter;

const boardApiMock = createMock<BoardApi>();
let boardApiMock: DeepMocked<BoardApi>;

beforeAll(async () => {
module = await Test.createTestingModule({
providers: [
BoardsClientAdapter,
{
provide: BoardApi,
useValue: boardApiMock,
useValue: createMock<BoardApi>(),
},
],
}).compile();
sut = module.get(BoardsClientAdapter);
boardApiMock = module.get(BoardApi);
});

afterAll(async () => {
Expand Down Expand Up @@ -51,19 +51,26 @@ describe(BoardsClientAdapter.name, () => {

boardApiMock.boardControllerCreateBoard.mockResolvedValue(axiosResponseFactory.build({ data: responseData }));

const jwt = faker.internet.jwt();

return {
params,
responseData,
jwt,
};
};

it('should call boardApi.boardControllerCreateBoard', async () => {
const { params, responseData } = setup();
const { params, responseData, jwt } = setup();

const response = await sut.createBoard(params);
const response = await sut.createBoard(jwt, params);

expect(response).toEqual(responseData);
expect(boardApiMock.boardControllerCreateBoard).toHaveBeenCalledWith(params);
expect(boardApiMock.boardControllerCreateBoard).toHaveBeenCalledWith(params, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
});
});
});
Expand All @@ -89,19 +96,26 @@ describe(BoardsClientAdapter.name, () => {
axiosResponseFactory.build({ data: responseData })
);

const jwt = faker.internet.jwt();

return {
boardId,
responseData,
jwt,
};
};

it('should call boardApi.boardControllerGetBoardSkeleton', async () => {
const { boardId, responseData } = setup();
const { boardId, responseData, jwt } = setup();

const response = await sut.getBoardSkeletonById(boardId);
const response = await sut.getBoardSkeletonById(jwt, boardId);

expect(response).toEqual(responseData);
expect(boardApiMock.boardControllerGetBoardSkeleton).toHaveBeenCalledWith(boardId);
expect(boardApiMock.boardControllerGetBoardSkeleton).toHaveBeenCalledWith(boardId, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
});
});
});
Expand All @@ -116,19 +130,26 @@ describe(BoardsClientAdapter.name, () => {

boardApiMock.boardControllerCreateColumn.mockResolvedValue(axiosResponseFactory.build({ data: responseData }));

const jwt = faker.internet.jwt();

return {
boardId,
responseData,
jwt,
};
};

it('should call boardApi.boardControllerCreateColumn', async () => {
const { boardId, responseData } = setup();
const { boardId, responseData, jwt } = setup();

const response = await sut.createBoardColumn(boardId);
const response = await sut.createBoardColumn(jwt, boardId);

expect(response).toEqual(responseData);
expect(boardApiMock.boardControllerCreateColumn).toHaveBeenCalledWith(boardId);
expect(boardApiMock.boardControllerCreateColumn).toHaveBeenCalledWith(boardId, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
});
});
});
Expand Down
21 changes: 15 additions & 6 deletions apps/server/src/infra/boards-client/boards-client.adapter.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
import { Injectable } from '@nestjs/common';
import { RawAxiosRequestConfig } from 'axios';
import { BoardApi, BoardResponse, ColumnResponse, CreateBoardBodyParams, CreateBoardResponse } from './generated';

@Injectable()
export class BoardsClientAdapter {
constructor(private readonly boardApi: BoardApi) {}

public async createBoard(params: CreateBoardBodyParams): Promise<CreateBoardResponse> {
const response = await this.boardApi.boardControllerCreateBoard(params);
public async createBoard(jwt: string, params: CreateBoardBodyParams): Promise<CreateBoardResponse> {
const response = await this.boardApi.boardControllerCreateBoard(params, this.getAxiosConfig(jwt));

return response.data;
}

public async createBoardColumn(boardId: string): Promise<ColumnResponse> {
const response = await this.boardApi.boardControllerCreateColumn(boardId);
public async createBoardColumn(jwt: string, boardId: string): Promise<ColumnResponse> {
const response = await this.boardApi.boardControllerCreateColumn(boardId, this.getAxiosConfig(jwt));

return response.data;
}

public async getBoardSkeletonById(boardId: string): Promise<BoardResponse> {
const response = await this.boardApi.boardControllerGetBoardSkeleton(boardId);
public async getBoardSkeletonById(jwt: string, boardId: string): Promise<BoardResponse> {
const response = await this.boardApi.boardControllerGetBoardSkeleton(boardId, this.getAxiosConfig(jwt));

return response.data;
}

private getAxiosConfig(jwt: string): RawAxiosRequestConfig {
return {
headers: {
Authorization: `Bearer ${jwt}`,
},
};
}
}
14 changes: 1 addition & 13 deletions apps/server/src/infra/boards-client/boards-client.module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import { Test, TestingModule } from '@nestjs/testing';
import { ConfigModule } from '@nestjs/config';
import { faker } from '@faker-js/faker';
import { Request } from 'express';
import { createMock } from '@golevelup/ts-jest';
import { REQUEST } from '@nestjs/core';
import { BoardsClientAdapter } from './boards-client.adapter';
import { BoardsClientConfig } from './boards-client.config';
import { BoardsClientModule } from './boards-client.module';

describe(BoardsClientModule.name, () => {
let module: TestingModule;

const requestMock = createMock<Request>({
headers: {
authorization: `Bearer ${faker.string.alphanumeric(42)}`,
},
});

beforeEach(async () => {
module = await Test.createTestingModule({
imports: [
Expand All @@ -32,10 +23,7 @@ describe(BoardsClientModule.name, () => {
],
}),
],
})
.overrideProvider(REQUEST)
.useValue(requestMock)
.compile();
}).compile();
});

afterAll(async () => {
Expand Down
14 changes: 4 additions & 10 deletions apps/server/src/infra/boards-client/boards-client.module.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,23 @@
import { Module, Scope } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
import { JwtExtractor } from '@shared/common/utils';
import { BoardsClientAdapter } from './boards-client.adapter';
import { BoardsClientConfig } from './boards-client.config';
import { Configuration, BoardApi } from './generated';
import { BoardApi, Configuration } from './generated';

@Module({
providers: [
BoardsClientAdapter,
{
provide: BoardApi,
scope: Scope.REQUEST,
useFactory: (configService: ConfigService<BoardsClientConfig, true>, request: Request): BoardApi => {
useFactory: (configService: ConfigService<BoardsClientConfig, true>): BoardApi => {
const basePath = configService.getOrThrow<string>('API_HOST');
const accessToken = JwtExtractor.extractJwtFromRequestOrFail(request);
const configuration = new Configuration({
basePath: `${basePath}/v3`,
accessToken,
});

return new BoardApi(configuration);
},
inject: [ConfigService, REQUEST],
inject: [ConfigService],
},
],
exports: [BoardsClientAdapter],
Expand Down
56 changes: 39 additions & 17 deletions apps/server/src/infra/cards-client/card-client.adapter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createMock } from '@golevelup/ts-jest';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { Test, TestingModule } from '@nestjs/testing';
import { BoardCardApi, BoardElementApi, ContentElementType } from './generated';
import { CardClientAdapter } from '.';
Expand All @@ -8,25 +8,26 @@ import { axiosResponseFactory } from '@testing/factory/axios-response.factory';
describe(CardClientAdapter.name, () => {
let module: TestingModule;
let sut: CardClientAdapter;

const cardApiMock = createMock<BoardCardApi>();
const boardElementApiMock = createMock<BoardElementApi>();
let cardApiMock: DeepMocked<BoardCardApi>;
let boardElementApiMock: DeepMocked<BoardElementApi>;

beforeAll(async () => {
module = await Test.createTestingModule({
providers: [
CardClientAdapter,
{
provide: BoardElementApi,
useValue: boardElementApiMock,
provide: BoardCardApi,
useValue: createMock<BoardCardApi>(),
},
{
provide: BoardCardApi,
useValue: cardApiMock,
provide: BoardElementApi,
useValue: createMock<BoardElementApi>(),
},
],
}).compile();
sut = module.get(CardClientAdapter);
cardApiMock = module.get(BoardCardApi);
boardElementApiMock = module.get(BoardElementApi);
});

afterAll(async () => {
Expand Down Expand Up @@ -54,20 +55,27 @@ describe(CardClientAdapter.name, () => {
axiosResponseFactory.build({ data: { id: cardId, type: ContentElementType.RICH_TEXT } })
);

const jwt = faker.internet.jwt();

return {
cardId,
createContentElementBodyParams,
jwt,
};
};

it('should call cardApi.cardControllerCreateElement', async () => {
const { cardId, createContentElementBodyParams } = setup();
const { cardId, createContentElementBodyParams, jwt } = setup();

const response = await sut.createCardElement(cardId, createContentElementBodyParams);
const response = await sut.createCardElement(jwt, cardId, createContentElementBodyParams);

expect(response.id).toEqual(cardId);
expect(response.type).toEqual(ContentElementType.RICH_TEXT);
expect(cardApiMock.cardControllerCreateElement).toHaveBeenCalledWith(cardId, createContentElementBodyParams);
expect(cardApiMock.cardControllerCreateElement).toHaveBeenCalledWith(cardId, createContentElementBodyParams, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
});
});
});
Expand All @@ -79,19 +87,25 @@ describe(CardClientAdapter.name, () => {
const renameBodyParams = {
title: faker.lorem.words(),
};
const jwt = faker.internet.jwt();

return {
cardId,
renameBodyParams,
jwt,
};
};

it('should call cardApi.cardControllerUpdateCardTitle', async () => {
const { cardId, renameBodyParams } = setup();
const { cardId, renameBodyParams, jwt } = setup();

await sut.updateCardTitle(cardId, renameBodyParams);
await sut.updateCardTitle(jwt, cardId, renameBodyParams);

expect(cardApiMock.cardControllerUpdateCardTitle).toHaveBeenCalledWith(cardId, renameBodyParams);
expect(cardApiMock.cardControllerUpdateCardTitle).toHaveBeenCalledWith(cardId, renameBodyParams, {
headers: {
Authorization: `Bearer ${jwt}`,
},
});
});
});
});
Expand All @@ -114,21 +128,29 @@ describe(CardClientAdapter.name, () => {
axiosResponseFactory.build({ data: updateElementContentBodyParams })
);

const jwt = faker.internet.jwt();

return {
elementId,
updateElementContentBodyParams,
jwt,
};
};

it('should call elementAPI.elementControllerUpdateElement', async () => {
const { elementId, updateElementContentBodyParams } = setup();
const { elementId, updateElementContentBodyParams, jwt } = setup();

const response = await sut.updateCardElement(elementId, updateElementContentBodyParams);
const response = await sut.updateCardElement(jwt, elementId, updateElementContentBodyParams);

expect(response).toEqual(updateElementContentBodyParams);
expect(boardElementApiMock.elementControllerUpdateElement).toHaveBeenCalledWith(
elementId,
updateElementContentBodyParams
updateElementContentBodyParams,
{
headers: {
Authorization: `Bearer ${jwt}`,
},
}
);
});
});
Expand Down
Loading
Loading