Skip to content

Commit

Permalink
more tests and some refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
virgilchiriac committed Oct 24, 2023
1 parent ace6d5c commit 7878a95
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import {
columnBoardNodeFactory,
columnNodeFactory,
courseFactory,
submissionContainerElementFactory,
submissionContainerElementNodeFactory,
submissionItemFactory,
submissionItemNodeFactory,
TestApiClient,
UserAndAccountTestFactory,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { EntityManager } from '@mikro-orm/mongodb';
import { INestApplication } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { BoardExternalReferenceType } from '@shared/domain';
import { BoardExternalReferenceType, ContentElementType } from '@shared/domain';
import {
TestApiClient,
UserAndAccountTestFactory,
cardNodeFactory,
cleanupCollections,
columnBoardNodeFactory,
columnNodeFactory,
courseFactory,
fileElementNodeFactory,
richTextElementNodeFactory,
submissionContainerElementNodeFactory,
submissionItemNodeFactory,
TestApiClient,
UserAndAccountTestFactory,
userFactory,
} from '@shared/testing';
import { ServerTestModule } from '@modules/server';
Expand Down Expand Up @@ -257,4 +259,117 @@ describe('submission item lookup (api)', () => {
expect(response.status).toEqual(403);
});
});

describe('when submission item has child elements', () => {
describe('when submission item has a RICH_TEXT child element', () => {
const setup = async () => {
await cleanupCollections(em);

const { teacherAccount, teacherUser } = UserAndAccountTestFactory.buildTeacher();
const { studentAccount, studentUser } = UserAndAccountTestFactory.buildStudent();
const course = courseFactory.build({ teachers: [teacherUser], students: [studentUser] });
await em.persistAndFlush([studentAccount, studentUser, teacherAccount, teacherUser, course]);

const columnBoardNode = columnBoardNodeFactory.buildWithId({
context: { id: course.id, type: BoardExternalReferenceType.Course },
});

const columnNode = columnNodeFactory.buildWithId({ parent: columnBoardNode });

const cardNode = cardNodeFactory.buildWithId({ parent: columnNode });

const submissionContainer = submissionContainerElementNodeFactory.buildWithId({ parent: cardNode });
const submissionItem = submissionItemNodeFactory.buildWithId({
parent: submissionContainer,
userId: studentUser.id,
});
const richTextElement = richTextElementNodeFactory.buildWithId({ parent: submissionItem });

await em.persistAndFlush([
columnBoardNode,
columnNode,
cardNode,
submissionContainer,
submissionItem,
richTextElement,
]);

const loggedInClient = await testApiClient.login(studentAccount);

return {
loggedInClient,
submissionContainer,
submissionItem,
richTextElement,
};
};

it('should return all RICH_TEXT child elements', async () => {
const { loggedInClient, submissionContainer, richTextElement } = await setup();

const response = await loggedInClient.get(`${submissionContainer.id}`);
const submissionItemResponse = (response.body as SubmissionsResponse).submissionItemsResponse[0];
const richTextElementResponse = submissionItemResponse.elements.filter(
(element) => element.type === ContentElementType.RICH_TEXT
);

expect(richTextElementResponse[0].id).toEqual(richTextElement.id);
});
});

describe('when submission item has a FILE child element', () => {
const setup = async () => {
await cleanupCollections(em);

const { teacherAccount, teacherUser } = UserAndAccountTestFactory.buildTeacher();
const { studentAccount, studentUser } = UserAndAccountTestFactory.buildStudent();
const course = courseFactory.build({ teachers: [teacherUser], students: [studentUser] });
await em.persistAndFlush([studentAccount, studentUser, teacherAccount, teacherUser, course]);

const columnBoardNode = columnBoardNodeFactory.buildWithId({
context: { id: course.id, type: BoardExternalReferenceType.Course },
});

const columnNode = columnNodeFactory.buildWithId({ parent: columnBoardNode });

const cardNode = cardNodeFactory.buildWithId({ parent: columnNode });

const submissionContainer = submissionContainerElementNodeFactory.buildWithId({ parent: cardNode });
const submissionItem = submissionItemNodeFactory.buildWithId({
parent: submissionContainer,
userId: studentUser.id,
});
const fileElement = fileElementNodeFactory.buildWithId({ parent: submissionItem });

await em.persistAndFlush([
columnBoardNode,
columnNode,
cardNode,
submissionContainer,
submissionItem,
fileElement,
]);

const loggedInClient = await testApiClient.login(studentAccount);

return {
loggedInClient,
submissionContainer,
submissionItem,
fileElement,
};
};
it('should return all FILE child elements', async () => {
const { loggedInClient, submissionContainer, fileElement } = await setup();

const response = await loggedInClient.get(`${submissionContainer.id}`);
const submissionItemResponse = (response.body as SubmissionsResponse).submissionItemsResponse[0];
const fileElementResponse = submissionItemResponse.elements.filter(
(element) => element.type === ContentElementType.FILE
);

expect(fileElementResponse[0].id).toEqual(fileElement.id);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,7 @@ export class BoardSubmissionController {
): Promise<FileElementResponse | RichTextElementResponse> {
const { type } = bodyParams;
const element = await this.submissionItemUc.createElement(currentUser.userId, urlParams.submissionItemId, type);
const response = ContentElementResponseFactory.mapToResponse(element);
if (!isFileElementResponse(response) && !isRichTextElementResponse(response)) {
throw new UnprocessableEntityException();
}
const response = ContentElementResponseFactory.mapSubmissionContentToResponse(element);

return response;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { NotImplementedException } from '@nestjs/common';
import { AnyBoardDo } from '@shared/domain';
import { AnyContentElementResponse } from '../dto';
import { NotImplementedException, UnprocessableEntityException } from '@nestjs/common';
import { AnyBoardDo, FileElement, isSubmissionItemContent, RichTextElement } from '@shared/domain';

Check failure on line 2 in apps/server/src/modules/board/controller/mapper/content-element-response.factory.ts

View workflow job for this annotation

GitHub Actions / nest_lint

'isSubmissionItemContent' is defined but never used
import {
AnyContentElementResponse,
FileElementResponse,
RichTextElementResponse,
isFileElementResponse,
isRichTextElementResponse,
} from '../dto';
import { BaseResponseMapper } from './base-mapper.interface';
import { ExternalToolElementResponseMapper } from './external-tool-element-response.mapper';
import { FileElementResponseMapper } from './file-element-response.mapper';
Expand Down Expand Up @@ -28,4 +34,14 @@ export class ContentElementResponseFactory {

return result;
}

static mapSubmissionContentToResponse(
element: RichTextElement | FileElement
): FileElementResponse | RichTextElementResponse {
const result = this.mapToResponse(element);
if (!isFileElementResponse(result) && !isRichTextElementResponse(result)) {
throw new UnprocessableEntityException();
}
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { UnprocessableEntityException } from '@nestjs/common';
import { FileElementResponseMapper } from './file-element-response.mapper';

Check failure on line 11 in apps/server/src/modules/board/controller/mapper/submission-item-response.mapper.ts

View workflow job for this annotation

GitHub Actions / nest_lint

'FileElementResponseMapper' is defined but never used
import { RichTextElementResponseMapper } from './rich-text-element-response.mapper';

Check failure on line 12 in apps/server/src/modules/board/controller/mapper/submission-item-response.mapper.ts

View workflow job for this annotation

GitHub Actions / nest_lint

'RichTextElementResponseMapper' is defined but never used
import { SubmissionItemResponse, SubmissionsResponse, TimestampsResponse, UserDataResponse } from '../dto';
import { ContentElementResponseFactory } from './content-element-response.factory';

export class SubmissionItemResponseMapper {
private static instance: SubmissionItemResponseMapper;
Expand Down Expand Up @@ -44,17 +45,7 @@ export class SubmissionItemResponseMapper {
createdAt: submissionItem.createdAt,
}),
userId: submissionItem.userId,
elements: children.map((element) => {
if (isFileElement(element)) {
const mapper = FileElementResponseMapper.getInstance();
return mapper.mapToResponse(element);
}
if (isRichTextElement(element)) {
const mapper = RichTextElementResponseMapper.getInstance();
return mapper.mapToResponse(element);
}
throw new UnprocessableEntityException();
}),
elements: children.map((element) => ContentElementResponseFactory.mapSubmissionContentToResponse(element)),
});

return result;
Expand Down
3 changes: 1 addition & 2 deletions apps/server/src/modules/board/uc/base.uc.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { AnyBoardDo, EntityId, SubmissionItem, UserRoleEnum } from '@shared/domain';
import { ForbiddenException, forwardRef, Inject } from '@nestjs/common';
import { ForbiddenException } from '@nestjs/common';
import { AuthorizationService, Action } from '@modules/authorization';
import { BoardDoAuthorizableService } from '../service';

export abstract class BaseUc {
constructor(
@Inject(forwardRef(() => AuthorizationService))
protected readonly authorizationService: AuthorizationService,
protected readonly boardDoAuthorizableService: BoardDoAuthorizableService
) {}
Expand Down

0 comments on commit 7878a95

Please sign in to comment.