Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persisting created new campaignApplication to db #657

Merged
merged 10 commits into from
Jul 17, 2024
49 changes: 49 additions & 0 deletions apps/api/src/auth/__mocks__.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { KeycloakTokenParsed } from './keycloak'

export const mockUser = {
exp: 1719866987,
iat: 1719866687,
jti: '607c488f-6e18-4455-8384-161cec4f1940',
iss: 'http://localhost:8180/auth/realms/webapp',
aud: 'account',
sub: '5795ea9e-ac11-436b-b97d-7b03dbd863f2',
typ: 'Bearer',
azp: 'jwt-headless',
session_state: 'def317ff-0043-4509-ade3-926dd155085e',
'allowed-origins': ['*'],
realm_access: { roles: ['default-roles-webapp', 'offline_access', 'uma_authorization'] },
resource_access: {
account: { roles: ['manage-account', 'manage-account-links', 'view-profile'] },
},
scope: 'openid profile email',
sid: 'def317ff-0043-4509-ade3-926dd155085e',
email_verified: 'true',
name: 'asdasd sdfsdfsdfs',
preferred_username: 'martbul01@gmail.com',
given_name: 'asdasd',
family_name: 'sdfsdfsdfs',
email: 'martbul01@gmail.com',
} as KeycloakTokenParsed

export const mockUserAdmin = {
exp: 1719866987,
iat: 1719866687,
jti: '607c488f-6e18-4455-8384-161cec4f1940',
iss: 'http://localhost:8180/auth/realms/webapp',
aud: 'account',
sub: '5795ea9e-ac11-436b-b97d-7b03dbd863f2',
typ: 'Bearer',
azp: 'jwt-headless',
session_state: 'def317ff-0043-4509-ade3-926dd155085e',
'allowed-origins': ['*'],
realm_access: { roles: ['default-roles-webapp', 'offline_access', 'uma_authorization'] },
resource_access: { account: { roles: ['manage-account', 'account-view-supporters'] } },
scope: 'openid profile email',
sid: 'def317ff-0043-4509-ade3-926dd155085e',
email_verified: 'true',
name: 'asdasd sdfsdfsdfs',
preferred_username: 'martbul01@gmail.com',
given_name: 'asdasd',
family_name: 'sdfsdfsdfs',
email: 'martbul01@gmail.com',
} as KeycloakTokenParsed
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { CampaignApplicationState, CampaignTypeCategory } from '@prisma/client'
import { CreateCampaignApplicationDto } from '../dto/create-campaign-application.dto'

export const mockNewCampaignApplication = {
campaignName: 'Test Campaign',
organizerName: 'Test Organizer',
organizerEmail: 'testemail@gmail.com',
organizerPhone: '123456789',
beneficiary: 'Test beneficary',
organizerBeneficiaryRel: 'Test organizerBeneficiaryRel',
goal: 'Test goal',
history: 'Test history',
amount: '1000',
description: 'Test description',
campaignGuarantee: 'Test guarantee',
otherFinanceSources: 'Test otherFinanceSources',
otherNotes: 'Test otherNotes',
category: CampaignTypeCategory.medical,
}

const dto: CreateCampaignApplicationDto = {

Check warning on line 21 in apps/api/src/campaign-application/__mocks__/campaign-application-mocks.ts

View workflow job for this annotation

GitHub Actions / Run API tests

'dto' is assigned a value but never used
...mockNewCampaignApplication,
acceptTermsAndConditions: true,
transparencyTermsAccepted: true,
personalInformationProcessingAccepted: true,
toEntity: new CreateCampaignApplicationDto().toEntity,
}

export const mockCampaigns = [
{
id: '1',
createdAt: new Date('2022-04-08T06:36:33.661Z'),
updatedAt: new Date('2022-04-08T06:36:33.662Z'),
description: 'Test description1',
organizerId: 'testOrganizerId1',
organizerName: 'Test Organizer1',
organizerEmail: 'organizer1@example.com',
beneficiary: 'test beneficary1',
organizerPhone: '123456789',
organizerBeneficiaryRel: 'Test Relation1',
campaignName: 'Test Campaign1',
goal: 'Test Goal1',
history: 'test history1',
amount: '1000',
campaignGuarantee: 'test campaignGuarantee1',
otherFinanceSources: 'test otherFinanceSources1',
otherNotes: 'test otherNotes1',
state: CampaignApplicationState.review,
category: CampaignTypeCategory.medical,
ticketURL: 'testsodifhso1',
archived: false,
},
{
id: '2',
createdAt: new Date('2022-04-08T06:36:33.661Z'),
updatedAt: new Date('2022-04-08T06:36:33.662Z'),
description: 'Test description2',
organizerId: 'testOrganizerId2',
organizerName: 'Test Organizer2',
organizerEmail: 'organizer2@example.com',
beneficiary: 'test beneficary2',
organizerPhone: '123456789',
organizerBeneficiaryRel: 'Test Relation2',
campaignName: 'Test Campaign2',
goal: 'Test Goal2',
history: 'test history2',
amount: '1000',
campaignGuarantee: 'test campaignGuarantee2',
otherFinanceSources: 'test otherFinanceSources2',
otherNotes: 'test otherNotes2',
state: CampaignApplicationState.review,
category: CampaignTypeCategory.medical,
ticketURL: 'testsodifhso2',
archived: false,
},
]

export const mockCreatedCampaignApplication = {
id: 'mockCampaignApplicationId',
createdAt: new Date('2022-04-08T06:36:33.661Z'),
updatedAt: new Date('2022-04-08T06:36:33.662Z'),
...mockNewCampaignApplication,
organizerId: 'mockOrganizerId',
state: CampaignApplicationState.review,
ticketURL: null,
archived: false,
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import { Test, TestingModule } from '@nestjs/testing'
import { CampaignApplicationController } from './campaign-application.controller'
import { CampaignApplicationService } from './campaign-application.service'
import { SpyOf, autoSpy } from '@podkrepi-bg/testing'
import { ForbiddenException } from '@nestjs/common'
import { KeycloakTokenParsed, isAdmin } from '../auth/keycloak'

jest.mock('../auth/keycloak')
import { autoSpy } from '@podkrepi-bg/testing'
import { CreateCampaignApplicationDto } from './dto/create-campaign-application.dto'
import { KeycloakTokenParsed } from '../auth/keycloak'
import { ForbiddenException, NotFoundException } from '@nestjs/common'
import { PersonService } from '../person/person.service'
import { mockUser, mockUserAdmin } from './../auth/__mocks__'
import { mockNewCampaignApplication } from './__mocks__/campaign-application-mocks'

describe('CampaignApplicationController', () => {
let controller: CampaignApplicationController
let service: SpyOf<CampaignApplicationService>
let service: CampaignApplicationService
let personService: PersonService

const mockCreateNewCampaignApplication = {
...mockNewCampaignApplication,
acceptTermsAndConditions: true,
transparencyTermsAccepted: true,
personalInformationProcessingAccepted: true,
toEntity: new CreateCampaignApplicationDto().toEntity,
} as CreateCampaignApplicationDto

beforeEach(async () => {
service = autoSpy(CampaignApplicationService)
personService = autoSpy(PersonService)

const module: TestingModule = await Test.createTestingModule({
controllers: [CampaignApplicationController],
providers: [{ provide: CampaignApplicationService, useValue: service }],
providers: [
{ provide: CampaignApplicationService, useValue: service },
{ provide: PersonService, useValue: personService },
],
}).compile()

controller = module.get<CampaignApplicationController>(CampaignApplicationController)
Expand All @@ -26,63 +41,63 @@ describe('CampaignApplicationController', () => {
expect(controller).toBeDefined()
})

it('when create called it should delegate to the service create', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is deleted but the logic is still in use. Was this by design?

// arrange
// act
controller.create({
acceptTermsAndConditions: true,
personalInformationProcessingAccepted: true,
transparencyTermsAccepted: true,
title: 'new ',
toEntity: jest.fn(),
})

// assert
expect(service.create).toHaveBeenCalledWith({
acceptTermsAndConditions: true,
personalInformationProcessingAccepted: true,
transparencyTermsAccepted: true,
title: 'new ',
toEntity: expect.any(Function),
})
it('when create called it should delegate to the service create', async () => {
// Arrange
jest.spyOn(personService, 'findOneByKeycloakId').mockResolvedValue(mockUser)

// Act
await controller.create(mockCreateNewCampaignApplication, mockUser)

// Assert
expect(service.create).toHaveBeenCalledWith(mockCreateNewCampaignApplication, mockUser)
})

it('when create called with wrong user it should throw NotFoundException', async () => {
jest.spyOn(personService, 'findOneByKeycloakId').mockResolvedValue(null)

// Act & Assert
await expect(controller.create(mockCreateNewCampaignApplication, mockUser)).rejects.toThrow(
NotFoundException,
)
})

it('when findAll called by a non-admin user it should throw a ForbiddenException', () => {
// arrange
jest.mock('../auth/keycloak', () => ({
isAdmin: jest.fn().mockReturnValue(false),
}))

// Arrange
const user = { sub: 'non-admin', 'allowed-origins': ['test'] } as KeycloakTokenParsed
;(isAdmin as jest.Mock).mockReturnValue(false)

// act & assert
// Act & Assert
expect(() => controller.findAll(user)).toThrow(ForbiddenException)
})

it('when findAll called by an admin user it should delegate to the service findAll', () => {
// arrange
const user = { sub: 'admin', 'allowed-origins': ['test'] } as KeycloakTokenParsed
;(isAdmin as jest.Mock).mockReturnValue(true)

// act
controller.findAll(user)

// assert
expect(service.findAll).toHaveBeenCalledWith()
jest.mock('../auth/keycloak', () => ({
isAdmin: jest.fn().mockImplementation((user: KeycloakTokenParsed) => {
return user.resource_access?.account?.roles.includes('account-view-supporters')
}),
}))

// Act & Assert
expect(() => controller.findAll(mockUserAdmin)).not.toThrow(ForbiddenException)
controller.findAll(mockUserAdmin)
expect(service.findAll).toHaveBeenCalled()
})

it('when findOne called it should delegate to the service findOne', () => {
// arrange
// act
// Act
controller.findOne('id')

// assert
// Assert
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid such unnecessary changes - they make the code review that much harder

expect(service.findOne).toHaveBeenCalledWith('id')
})

it('when update called it should delegate to the service update', () => {
// arrange
// act
// Act
controller.update('1', {}, { sub: 'test', 'allowed-origins': ['test'] })

// assert
// Assert
expect(service.update).toHaveBeenCalledWith('1', {})
})
})
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
import { Controller, Get, Post, Body, Patch, Param, ForbiddenException } from '@nestjs/common'
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
ForbiddenException,
NotFoundException,
Logger,
} from '@nestjs/common'
import { CampaignApplicationService } from './campaign-application.service'
import { CreateCampaignApplicationDto } from './dto/create-campaign-application.dto'
import { UpdateCampaignApplicationDto } from './dto/update-campaign-application.dto'
import { ApiTags } from '@nestjs/swagger'
import { AuthenticatedUser, Public, RoleMatchingMode, Roles } from 'nest-keycloak-connect'
import { AuthenticatedUser, RoleMatchingMode, Roles } from 'nest-keycloak-connect'
import { RealmViewSupporters, ViewSupporters } from '@podkrepi-bg/podkrepi-types'
import { KeycloakTokenParsed, isAdmin } from '../auth/keycloak'
import { PersonService } from '../person/person.service'

@ApiTags('campaign-application')
@Controller('campaign-application')
export class CampaignApplicationController {
constructor(private readonly campaignApplicationService: CampaignApplicationService) {}
constructor(
private readonly campaignApplicationService: CampaignApplicationService,
private readonly personService: PersonService,
) {}

@Post('create')
@Public()
create(@Body() createCampaignApplicationDto: CreateCampaignApplicationDto) {
return this.campaignApplicationService.create(createCampaignApplicationDto)
async create(
@Body() createCampaignApplicationDto: CreateCampaignApplicationDto,
@AuthenticatedUser() user: KeycloakTokenParsed,
) {
const person = await this.personService.findOneByKeycloakId(user.sub)

if (!person) {
Logger.error('No person found in database')
throw new NotFoundException('No person found in database')
}

return this.campaignApplicationService.create(createCampaignApplicationDto, person)
}

@Get('list')
Expand All @@ -39,7 +62,7 @@
async update(
@Param('id') id: string,
@Body() updateCampaignApplicationDto: UpdateCampaignApplicationDto,
@AuthenticatedUser() user: KeycloakTokenParsed,

Check warning on line 65 in apps/api/src/campaign-application/campaign-application.controller.ts

View workflow job for this annotation

GitHub Actions / Run API tests

'user' is defined but never used
) {
return this.campaignApplicationService.update(id, updateCampaignApplicationDto)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { Module } from '@nestjs/common'
import { CampaignApplicationService } from './campaign-application.service'
import { CampaignApplicationController } from './campaign-application.controller'
import { PrismaModule } from '../prisma/prisma.module'
import { PersonModule } from '../person/person.module'
import { OrganizerModule } from '../organizer/organizer.module'
@Module({
imports: [PrismaModule],
imports: [PrismaModule, PersonModule, OrganizerModule],
controllers: [CampaignApplicationController],
providers: [CampaignApplicationService],
})
Expand Down
Loading
Loading