Merge pull request 'Alpha Release 0.2.0' (#109) from dev into main
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing

Reviewed-on: #109
Reviewed-by: Philipp Dormann <philipp@philippdormann.de>
This commit is contained in:
Nicolai Ort 2021-01-20 17:05:12 +00:00
commit dd3d93edc7
38 changed files with 2824 additions and 1521 deletions

View File

@ -6,4 +6,4 @@ DB_USER=unused
DB_PASSWORD=bla DB_PASSWORD=bla
DB_NAME=./test.sqlite DB_NAME=./test.sqlite
NODE_ENV=dev NODE_ENV=dev
POSTALCODE_COUNTRYCODE=null POSTALCODE_COUNTRYCODE=DE

View File

@ -6,4 +6,4 @@ DB_USER=bla
DB_PASSWORD=bla DB_PASSWORD=bla
DB_NAME=bla DB_NAME=bla
NODE_ENV=production NODE_ENV=production
POSTALCODE_COUNTRYCODE=null POSTALCODE_COUNTRYCODE=DE

View File

@ -2,8 +2,67 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC. All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [v0.2.0](https://git.odit.services/lfk/backend/compare/v0.1.1...v0.2.0)
- 🧾New changelog file version [CI SKIP] [skip ci] [`8960aa5`](https://git.odit.services/lfk/backend/commit/8960aa5545ddeb57d4ef42c21c0ca6001dfeaea9)
- 🚀Bumped version to v0.2.0 [`ddafd90`](https://git.odit.services/lfk/backend/commit/ddafd90d3e41fb9ee37172a8306c30d8483dfe2c)
- Merge pull request 'Implemented group contacts feature/104-contacts' (#108) from feature/104-contacts into dev [`a0c2b5a`](https://git.odit.services/lfk/backend/commit/a0c2b5ade8d198ec16d33b39e47205e8b03a669f)
- Updated contact update tests [`c3d008e`](https://git.odit.services/lfk/backend/commit/c3d008ec0ff92f80addbdb93ffc1fa2b3278a8a6)
- Added contact delete tests [`dd7e5da`](https://git.odit.services/lfk/backend/commit/dd7e5dae368a8decd79357f658dda2164fa6f1e7)
- Added contact add valid tests [`e165f01`](https://git.odit.services/lfk/backend/commit/e165f019307e7745357493eacf3e2fa31538122b)
- Cleaned up var names [`a3c93f0`](https://git.odit.services/lfk/backend/commit/a3c93f0d394833f1a6f78d862b094ca751c85561)
- Added address update ivalid tests [`427dfaa`](https://git.odit.services/lfk/backend/commit/427dfaafabd243e94aba27c2dec2705fd8ed5d64)
- Added barebones contact controller from donor-controller [`3e7190e`](https://git.odit.services/lfk/backend/commit/3e7190e279181c5f99d890ca141489b24908b904)
- Added first address update tests [`4d40225`](https://git.odit.services/lfk/backend/commit/4d40225a4491e8eb3f41ef0fd558a599f63729be)
- Added a contact update class [`c172aa8`](https://git.odit.services/lfk/backend/commit/c172aa8bf8083500828743ed696955a1fe3caef2)
- Added address update valid tests [`230cdb0`](https://git.odit.services/lfk/backend/commit/230cdb0e37e2b7a21e7feb156f2b91a69ad200fd)
- Implemented deep address validation [`9dc9ce3`](https://git.odit.services/lfk/backend/commit/9dc9ce37d8fbfc92842e4e05bbde68398324a186)
- Added contact add invalid tests [`940d62c`](https://git.odit.services/lfk/backend/commit/940d62cde4cf7be7780904d681a5e4c9efaa2ba5)
- Added a contact response class [`1407fe3`](https://git.odit.services/lfk/backend/commit/1407fe36f3637d6c53024c48788b318d985f8960)
- Removed old create address class [`2a465f8`](https://git.odit.services/lfk/backend/commit/2a465f88c58c0b4be3ecd99d96a04c177a40b312)
- Switched the create classes over to the new address implementation [`2cd15d2`](https://git.odit.services/lfk/backend/commit/2cd15d25e934a5439bfea4de901f136e360e17f6)
- Added contact get tests [`b002cf2`](https://git.odit.services/lfk/backend/commit/b002cf2df1eafc722fbfb51b3bffb02bee002305)
- Test's now accept the new address format [`8dbee32`](https://git.odit.services/lfk/backend/commit/8dbee32eeec8ee3d013e4446e8f53544ee4cb577)
- Implemented the get endpoints [`ab70f7e`](https://git.odit.services/lfk/backend/commit/ab70f7e49893344dde8f5af93f571a5d67818e19)
- Implemented contact deletion [`0379786`](https://git.odit.services/lfk/backend/commit/0379786cbda057ad95d709fa135d34beb0db8de1)
- Removed the IAddressUser Interface entity [`e265172`](https://git.odit.services/lfk/backend/commit/e2651728c5abf2273bf51a7652c51d55d8fa0a2f)
- Implemented contact updateing [`28fb983`](https://git.odit.services/lfk/backend/commit/28fb9834e18bde012c5b51cc49a39585d20f7cc1)
- Fixed key null constraint [`de82437`](https://git.odit.services/lfk/backend/commit/de824375d3a1da6ee4d78ea39b7da66fc05f2a02)
- Implemented contact posting [`11af9c0`](https://git.odit.services/lfk/backend/commit/11af9c02d977dcd6919652256dbdb9fd5438cabd)
- Implemented contact group setting on creation [`3b06d1a`](https://git.odit.services/lfk/backend/commit/3b06d1a6ef3c95eb5bb7d485accddabba0a8e4f7)
- 🧾New changelog file version [CI SKIP] [skip ci] [`32e054e`](https://git.odit.services/lfk/backend/commit/32e054eb84c869210fd483583ae5a6d0e2249cf9)
- Switched Address to embedded entity [`7fbe649`](https://git.odit.services/lfk/backend/commit/7fbe649dc90f4bb9f240c5a80fed447048e5e105)
- Removed the address errors [`58ae9b5`](https://git.odit.services/lfk/backend/commit/58ae9b589aef3580f4b8558c3d5ddbd7171e7915)
- Switched the update classes over to the new address implementation [`d0df5dd`](https://git.odit.services/lfk/backend/commit/d0df5dd641ac17f1fd8ad6bd8b46afa9dd2745c3)
- Updated the contact errors [`a9a5eb6`](https://git.odit.services/lfk/backend/commit/a9a5eb673570bb3c0d1a55bb1292e208493663bd)
- Implemented adress deletion (through reset) [`57b9c2b`](https://git.odit.services/lfk/backend/commit/57b9c2babcd68d69d1cbb240a86c2897717ba758)
- Fixed donor address check [`4824547`](https://git.odit.services/lfk/backend/commit/4824547dde4d7f90e9e2377a26df34cabf082fdb)
- Updated contact delete tests [`8ae53f1`](https://git.odit.services/lfk/backend/commit/8ae53f1c4930e2fd72eb230a5314336f3a45a611)
- Added address to contact response [`09e429f`](https://git.odit.services/lfk/backend/commit/09e429fc676c7dd370bba0495b072f81867bd250)
- Updated comments [`a4e8311`](https://git.odit.services/lfk/backend/commit/a4e8311cbd22588ecb4dc2fdbe05397b07d336f8)
- Updated the responseclasses to use the new address implementation [`dafac06`](https://git.odit.services/lfk/backend/commit/dafac06bc84d1b237096a561b3adcd3ca5cb1dd8)
- Removed (now useless) relations [`673dea2`](https://git.odit.services/lfk/backend/commit/673dea2e5754e99ff77f7556d4fc03d4cca28a94)
- Added missing id property [`6b4b16c`](https://git.odit.services/lfk/backend/commit/6b4b16c13b0c2f55745ded3431cad2f4986be296)
- Added address validity check [`ae7c5ff`](https://git.odit.services/lfk/backend/commit/ae7c5ff0c387e9337d01a9dd819a4dddc208f6dd)
- 🧾New changelog file version [CI SKIP] [skip ci] [`f53894b`](https://git.odit.services/lfk/backend/commit/f53894b16ac1c06ecbeeb0b63a56ac438b2fbe1b)
- Updated comments [`8bc01d3`](https://git.odit.services/lfk/backend/commit/8bc01d3f2406ce8e58c2ab2963c858495c510dcf)
- Fixed contact cascading [`179c2a5`](https://git.odit.services/lfk/backend/commit/179c2a5157fca036acf8d0e6a51821d377860bc1)
- Added openapi description about non-deletion [`56c73c2`](https://git.odit.services/lfk/backend/commit/56c73c2555d4d12ffb088ec5550667022d3a8694)
- Added contact permission target [`d12801e`](https://git.odit.services/lfk/backend/commit/d12801e34d57cec0e867f69123e3be39ed2fe2f5)
- Adjusted env sample [`a1acd35`](https://git.odit.services/lfk/backend/commit/a1acd3519f66965202da0cd15df61a807230619c)
- Renamed controller to better fit the overall nameing scheme [`d743f7e`](https://git.odit.services/lfk/backend/commit/d743f7ee1277256ada8fe39f900349ff2643118a)
- Fixed column not getting resolved [`2b658ac`](https://git.odit.services/lfk/backend/commit/2b658ac381f318cf37fc2051ea3e83976e3c5773)
- Fixed column not getting resolved [`321d291`](https://git.odit.services/lfk/backend/commit/321d291b4bf983ff4930cadecf3a013430a97649)
- Set country code for the ci env to DE [`30b585c`](https://git.odit.services/lfk/backend/commit/30b585c0c12b3b9818778110d33d5b3ab84d4192)
- Implemented postal code validation for the validaton function [`f245840`](https://git.odit.services/lfk/backend/commit/f245840cde5726611197b00730aca72ea133c427)
- Fixed push undefined eror [`2eb26e4`](https://git.odit.services/lfk/backend/commit/2eb26e4e381a97fd829a294501fa42ac7b712b56)
- Merge pull request 'Fully implemented addresses feature/105-addresses' (#107) from feature/105-addresses into dev [`5e36855`](https://git.odit.services/lfk/backend/commit/5e368552ea810ea1d3963b1207ba98f7b46c4abc)
#### [v0.1.1](https://git.odit.services/lfk/backend/compare/v0.1.0...v0.1.1) #### [v0.1.1](https://git.odit.services/lfk/backend/compare/v0.1.0...v0.1.1)
> 16 January 2021
- Merge pull request 'Alpha Release 0.1.1 - Hotfix release' (#106) from dev into main [`7533c34`](https://git.odit.services/lfk/backend/commit/7533c349ef98ed328151259fca68621b3eb5fd98)
- 🚀Bumped version to v0.1.1 [`9445c6f`](https://git.odit.services/lfk/backend/commit/9445c6f21e376329b9200664a44a94ba1f1dd463) - 🚀Bumped version to v0.1.1 [`9445c6f`](https://git.odit.services/lfk/backend/commit/9445c6f21e376329b9200664a44a94ba1f1dd463)
- 🧾New changelog file version [CI SKIP] [skip ci] [`1b9d296`](https://git.odit.services/lfk/backend/commit/1b9d2969ebdca4dca84898b1e8307be7b781b90b) - 🧾New changelog file version [CI SKIP] [skip ci] [`1b9d296`](https://git.odit.services/lfk/backend/commit/1b9d2969ebdca4dca84898b1e8307be7b781b90b)
- Implemented the /me controller that allows a user to get and update themselves [`8ef5f90`](https://git.odit.services/lfk/backend/commit/8ef5f90abda97a73d5c5a7767a144ac3fb5288c1) - Implemented the /me controller that allows a user to get and update themselves [`8ef5f90`](https://git.odit.services/lfk/backend/commit/8ef5f90abda97a73d5c5a7767a144ac3fb5288c1)
@ -14,12 +73,13 @@ All notable changes to this project will be documented in this file. Dates are d
- automaticly merge main into dev after building a latest image [`02efb9a`](https://git.odit.services/lfk/backend/commit/02efb9a8e55831ecce4109e17b2f07a56e491fd5) - automaticly merge main into dev after building a latest image [`02efb9a`](https://git.odit.services/lfk/backend/commit/02efb9a8e55831ecce4109e17b2f07a56e491fd5)
- User deletion now requires confirmation [`6b7ecd3`](https://git.odit.services/lfk/backend/commit/6b7ecd3044c45b2eed46ee5010bed4dab4f02df9) - User deletion now requires confirmation [`6b7ecd3`](https://git.odit.services/lfk/backend/commit/6b7ecd3044c45b2eed46ee5010bed4dab4f02df9)
- 🧾New changelog file version [CI SKIP] [skip ci] [`3766899`](https://git.odit.services/lfk/backend/commit/3766899c8393545a89986a98dafd542edc4a1d39) - 🧾New changelog file version [CI SKIP] [skip ci] [`3766899`](https://git.odit.services/lfk/backend/commit/3766899c8393545a89986a98dafd542edc4a1d39)
- 🧾New changelog file version [CI SKIP] [skip ci] [`6febb99`](https://git.odit.services/lfk/backend/commit/6febb994990b4cab7ee54b0368f74dd95664bfdf)
- 🧾New changelog file version [CI SKIP] [skip ci] [`de36a24`](https://git.odit.services/lfk/backend/commit/de36a24191a8cdc4ff6b23637ea9f91109b59bbb)
- Merge pull request 'User self-management feature/100-me_endpoints' (#103) from feature/100-me_endpoints into dev [`a6c7d54`](https://git.odit.services/lfk/backend/commit/a6c7d54fe72ffe23add926afa0be150a7a370099)
- Created barebones file for the userchecker [`e586a11`](https://git.odit.services/lfk/backend/commit/e586a11e2ad42af9c9bb5d2a47f48e3306fe49b2) - Created barebones file for the userchecker [`e586a11`](https://git.odit.services/lfk/backend/commit/e586a11e2ad42af9c9bb5d2a47f48e3306fe49b2)
- 🧾New changelog file version [CI SKIP] [skip ci] [`6febb99`](https://git.odit.services/lfk/backend/commit/6febb994990b4cab7ee54b0368f74dd95664bfdf)
- Updated descriptions and responses [`fc7b8f4`](https://git.odit.services/lfk/backend/commit/fc7b8f4c16cef0e72b04f096d5a17d4144b5feb7) - Updated descriptions and responses [`fc7b8f4`](https://git.odit.services/lfk/backend/commit/fc7b8f4c16cef0e72b04f096d5a17d4144b5feb7)
- 🧾New changelog file version [CI SKIP] [skip ci] [`50b893f`](https://git.odit.services/lfk/backend/commit/50b893f5370902ccc40f8bb45ed160103400f529) - 🧾New changelog file version [CI SKIP] [skip ci] [`50b893f`](https://git.odit.services/lfk/backend/commit/50b893f5370902ccc40f8bb45ed160103400f529)
- 🧾New changelog file version [CI SKIP] [skip ci] [`de36a24`](https://git.odit.services/lfk/backend/commit/de36a24191a8cdc4ff6b23637ea9f91109b59bbb)
- 🧾New changelog file version [CI SKIP] [skip ci] [`91569ce`](https://git.odit.services/lfk/backend/commit/91569ced40402a63017a90a01efaf48578b5c806)
- Merge pull request 'User self-management feature/100-me_endpoints' (#103) from feature/100-me_endpoints into dev [`a6c7d54`](https://git.odit.services/lfk/backend/commit/a6c7d54fe72ffe23add926afa0be150a7a370099)
- Moved the me endpoints to /users/me [`f9834b5`](https://git.odit.services/lfk/backend/commit/f9834b5f4d80b11ee5f7773b339dd421341c6e7f) - Moved the me endpoints to /users/me [`f9834b5`](https://git.odit.services/lfk/backend/commit/f9834b5f4d80b11ee5f7773b339dd421341c6e7f)
- Moved optional param to being optional [`a334adf`](https://git.odit.services/lfk/backend/commit/a334adffc6d07c8ab340263123e00a96f21acecb) - Moved optional param to being optional [`a334adf`](https://git.odit.services/lfk/backend/commit/a334adffc6d07c8ab340263123e00a96f21acecb)

View File

@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-backend", "name": "@odit/lfk-backend",
"version": "0.1.1", "version": "0.2.0",
"main": "src/app.ts", "main": "src/app.ts",
"repository": "https://git.odit.services/lfk/backend", "repository": "https://git.odit.services/lfk/backend",
"author": { "author": {

View File

@ -0,0 +1,107 @@
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers';
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
import { getConnection, getConnectionManager, Repository } from 'typeorm';
import { GroupContactIdsNotMatchingError, GroupContactNotFoundError } from '../errors/GroupContactErrors';
import { RunnerGroupNotFoundError } from '../errors/RunnerGroupErrors';
import { CreateGroupContact } from '../models/actions/create/CreateGroupContact';
import { UpdateGroupContact } from '../models/actions/update/UpdateGroupContact';
import { GroupContact } from '../models/entities/GroupContact';
import { RunnerGroup } from '../models/entities/RunnerGroup';
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
import { ResponseGroupContact } from '../models/responses/ResponseGroupContact';
@JsonController('/contacts')
@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
export class GroupContactController {
private contactRepository: Repository<GroupContact>;
/**
* Gets the repository of this controller's model/entity.
*/
constructor() {
this.contactRepository = getConnectionManager().get().getRepository(GroupContact);
}
@Get()
@Authorized("CONTACT:GET")
@ResponseSchema(ResponseGroupContact, { isArray: true })
@OpenAPI({ description: 'Lists all contacts. <br> This includes the contact\'s associated groups.' })
async getAll() {
let responseContacts: ResponseGroupContact[] = new Array<ResponseGroupContact>();
const contacts = await this.contactRepository.find({ relations: ['groups'] });
contacts.forEach(contact => {
responseContacts.push(contact.toResponse());
});
return responseContacts;
}
@Get('/:id')
@Authorized("CONTACT:GET")
@ResponseSchema(ResponseGroupContact)
@ResponseSchema(GroupContactNotFoundError, { statusCode: 404 })
@OnUndefined(GroupContactNotFoundError)
@OpenAPI({ description: 'Lists all information about the contact whose id got provided. <br> This includes the contact\'s associated groups.' })
async getOne(@Param('id') id: number) {
let contact = await this.contactRepository.findOne({ id: id }, { relations: ['groups'] })
if (!contact) { throw new GroupContactNotFoundError(); }
return contact.toResponse();
}
@Post()
@Authorized("CONTACT:CREATE")
@ResponseSchema(ResponseGroupContact)
@ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 })
@OpenAPI({ description: 'Create a new contact.' })
async post(@Body({ validate: true }) createContact: CreateGroupContact) {
let contact;
try {
contact = await createContact.toEntity();
} catch (error) {
throw error;
}
contact = await this.contactRepository.save(contact)
return (await this.contactRepository.findOne({ id: contact.id }, { relations: ['groups'] })).toResponse();
}
@Put('/:id')
@Authorized("CONTACT:UPDATE")
@ResponseSchema(ResponseGroupContact)
@ResponseSchema(GroupContactNotFoundError, { statusCode: 404 })
@ResponseSchema(GroupContactIdsNotMatchingError, { statusCode: 406 })
@ResponseSchema(RunnerGroupNotFoundError, { statusCode: 404 })
@OpenAPI({ description: "Update the contact whose id you provided. <br> Please remember that ids can't be changed." })
async put(@Param('id') id: number, @Body({ validate: true }) contact: UpdateGroupContact) {
let oldContact = await this.contactRepository.findOne({ id: id });
if (!oldContact) {
throw new GroupContactNotFoundError();
}
if (oldContact.id != contact.id) {
throw new GroupContactIdsNotMatchingError();
}
await this.contactRepository.save(await contact.update(oldContact));
return (await this.contactRepository.findOne({ id: contact.id }, { relations: ['groups'] })).toResponse();
}
@Delete('/:id')
@Authorized("CONTACT:DELETE")
@ResponseSchema(ResponseGroupContact)
@ResponseSchema(ResponseEmpty, { statusCode: 204 })
@OnUndefined(204)
@OpenAPI({ description: 'Delete the contact whose id you provided. <br> If no contact with this id exists it will just return 204(no content). <br> This won\'t delete any groups associated with the contact.' })
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let contact = await this.contactRepository.findOne({ id: id });
if (!contact) { return null; }
const responseContact = await this.contactRepository.findOne(contact, { relations: ['groups'] });
for (let group of responseContact.groups) {
group.contact = null;
await getConnection().getRepository(RunnerGroup).save(group);
}
await this.contactRepository.delete(contact);
return responseContact.toResponse();
}
}

View File

@ -29,7 +29,7 @@ export class RunnerOrganisationController {
@OpenAPI({ description: 'Lists all organisations. <br> This includes their address, contact and teams (if existing/associated).' }) @OpenAPI({ description: 'Lists all organisations. <br> This includes their address, contact and teams (if existing/associated).' })
async getAll() { async getAll() {
let responseTeams: ResponseRunnerOrganisation[] = new Array<ResponseRunnerOrganisation>(); let responseTeams: ResponseRunnerOrganisation[] = new Array<ResponseRunnerOrganisation>();
const runners = await this.runnerOrganisationRepository.find({ relations: ['address', 'contact', 'teams'] }); const runners = await this.runnerOrganisationRepository.find({ relations: ['contact', 'teams'] });
runners.forEach(runner => { runners.forEach(runner => {
responseTeams.push(new ResponseRunnerOrganisation(runner)); responseTeams.push(new ResponseRunnerOrganisation(runner));
}); });
@ -43,7 +43,7 @@ export class RunnerOrganisationController {
@OnUndefined(RunnerOrganisationNotFoundError) @OnUndefined(RunnerOrganisationNotFoundError)
@OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' }) @OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' })
async getOne(@Param('id') id: number) { async getOne(@Param('id') id: number) {
let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['address', 'contact', 'teams'] }); let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['contact', 'teams'] });
if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); } if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); }
return new ResponseRunnerOrganisation(runnerOrg); return new ResponseRunnerOrganisation(runnerOrg);
} }
@ -62,7 +62,7 @@ export class RunnerOrganisationController {
runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation); runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation);
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['address', 'contact', 'teams'] })); return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['contact', 'teams'] }));
} }
@Put('/:id') @Put('/:id')
@ -84,7 +84,7 @@ export class RunnerOrganisationController {
await this.runnerOrganisationRepository.save(await updateOrganisation.update(oldRunnerOrganisation)); await this.runnerOrganisationRepository.save(await updateOrganisation.update(oldRunnerOrganisation));
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['address', 'contact', 'teams'] })); return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['contact', 'teams'] }));
} }
@Delete('/:id') @Delete('/:id')
@ -94,11 +94,11 @@ export class RunnerOrganisationController {
@ResponseSchema(RunnerOrganisationHasTeamsError, { statusCode: 406 }) @ResponseSchema(RunnerOrganisationHasTeamsError, { statusCode: 406 })
@ResponseSchema(RunnerOrganisationHasRunnersError, { statusCode: 406 }) @ResponseSchema(RunnerOrganisationHasRunnersError, { statusCode: 406 })
@OnUndefined(204) @OnUndefined(204)
@OpenAPI({ description: 'Delete the organsisation whose id you provided. <br> If the organisation still has runners and/or teams associated this will fail. <br> To delete the organisation with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while). <br> If no organisation with this id exists it will just return 204(no content).' }) @OpenAPI({ description: 'Delete the organsisation whose id you provided. <br> If the organisation still has runners and/or teams associated this will fail. <br> To delete the organisation with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while). <br> This won\'t delete the associated contact. <br> If no organisation with this id exists it will just return 204(no content).' })
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let organisation = await this.runnerOrganisationRepository.findOne({ id: id }); let organisation = await this.runnerOrganisationRepository.findOne({ id: id });
if (!organisation) { return null; } if (!organisation) { return null; }
let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['address', 'contact', 'runners', 'teams'] }); let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['contact', 'runners', 'teams'] });
if (!force) { if (!force) {
if (runnerOrganisation.teams.length != 0) { if (runnerOrganisation.teams.length != 0) {

View File

@ -93,7 +93,7 @@ export class RunnerTeamController {
@ResponseSchema(ResponseEmpty, { statusCode: 204 }) @ResponseSchema(ResponseEmpty, { statusCode: 204 })
@ResponseSchema(RunnerTeamHasRunnersError, { statusCode: 406 }) @ResponseSchema(RunnerTeamHasRunnersError, { statusCode: 406 })
@OnUndefined(204) @OnUndefined(204)
@OpenAPI({ description: 'Delete the team whose id you provided. <br> If the team still has runners associated this will fail. <br> To delete the team with all associated runners set the force QueryParam to true (cascading deletion might take a while). <br> If no team with this id exists it will just return 204(no content).' }) @OpenAPI({ description: 'Delete the team whose id you provided. <br> If the team still has runners associated this will fail. <br> To delete the team with all associated runners set the force QueryParam to true (cascading deletion might take a while). <br> This won\'t delete the associated contact.<br> If no team with this id exists it will just return 204(no content).' })
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let team = await this.runnerTeamRepository.findOne({ id: id }); let team = await this.runnerTeamRepository.findOne({ id: id });
if (!team) { return null; } if (!team) { return null; }

View File

@ -1,24 +1,57 @@
import { IsString } from 'class-validator'; import { IsString } from 'class-validator';
import { NotAcceptableError, NotFoundError } from 'routing-controllers'; import { BadRequestError } from 'routing-controllers';
/** /**
* Error to throw, when to provided address doesn't belong to the accepted types. * Error to throw when an address's postal code fails validation.
*/ */
export class AddressWrongTypeError extends NotAcceptableError { export class AddressPostalCodeInvalidError extends BadRequestError {
@IsString() @IsString()
name = "AddressWrongTypeError" name = "AddressPostalCodeInvalidError"
@IsString() @IsString()
message = "The address must be an existing address's id. \n You provided a object of another type." message = "The postal code you provided is invalid. \n Please check if your postal code follows the postal code validation guidelines."
} }
/** /**
* Error to throw, when a non-existent address get's loaded. * Error to throw when an non-empty address's first line isn't set.
*/ */
export class AddressNotFoundError extends NotFoundError { export class AddressFirstLineEmptyError extends BadRequestError {
@IsString() @IsString()
name = "AddressNotFoundError" name = "AddressFirstLineEmptyError"
@IsString() @IsString()
message = "The address you provided couldn't be located in the system. \n Please check your request." message = "You provided a empty first address line. \n If you want an empty address please set all propertys to null. \n For non-empty addresses the following fields have to be set: address1, postalcode, city, country"
}
/**
* Error to throw when an non-empty address's postal code isn't set.
*/
export class AddressPostalCodeEmptyError extends BadRequestError {
@IsString()
name = "AddressPostalCodeEmptyError"
@IsString()
message = "You provided a empty postal code. \n If you want an empty address please set all propertys to null. \n For non-empty addresses the following fields have to be set: address1, postalcode, city, country"
}
/**
* Error to throw when an non-empty address's city isn't set.
*/
export class AddressCityEmptyError extends BadRequestError {
@IsString()
name = "AddressCityEmptyError"
@IsString()
message = "You provided a empty city. \n If you want an empty address please set all propertys to null. \n For non-empty addresses the following fields have to be set: address1, postalcode, city, country"
}
/**
* Error to throw when an non-empty address's country isn't set.
*/
export class AddressCountryEmptyError extends BadRequestError {
@IsString()
name = "AddressCountryEmptyError"
@IsString()
message = "You provided a empty country. \n If you want an empty address please set all propertys to null. \n For non-empty addresses the following fields have to be set: address1, postalcode, city, country"
} }

View File

@ -2,18 +2,7 @@ import { IsString } from 'class-validator';
import { NotAcceptableError, NotFoundError } from 'routing-controllers'; import { NotAcceptableError, NotFoundError } from 'routing-controllers';
/** /**
* Error to throw, when a provided groupContact doesn't belong to the accepted types. * Error to throw, when a non-existent contact get's requested.
*/
export class GroupContactWrongTypeError extends NotAcceptableError {
@IsString()
name = "GroupContactWrongTypeError"
@IsString()
message = "The groupContact must be an existing groupContact's id. \n You provided a object of another type."
}
/**
* Error to throw, when a non-existent groupContact get's loaded.
*/ */
export class GroupContactNotFoundError extends NotFoundError { export class GroupContactNotFoundError extends NotFoundError {
@IsString() @IsString()
@ -21,4 +10,16 @@ export class GroupContactNotFoundError extends NotFoundError {
@IsString() @IsString()
message = "The groupContact you provided couldn't be located in the system. \n Please check your request." message = "The groupContact you provided couldn't be located in the system. \n Please check your request."
} }
/**
* Error to throw when two contacts' ids don't match.
* Usually occurs when a user tries to change a contact's id.
*/
export class GroupContactIdsNotMatchingError extends NotAcceptableError {
@IsString()
name = "GroupContactIdsNotMatchingError"
@IsString()
message = "The ids don't match! \n And if you wanted to change a contact's id: This isn't allowed!"
}

View File

@ -1,69 +0,0 @@
import { IsNotEmpty, IsOptional, IsPostalCode, IsString } from 'class-validator';
import { config } from '../../../config';
import { Address } from '../../entities/Address';
/**
* This classed is used to create a new Address entity from a json body (post request).
*/
export class CreateAddress {
/**
* The newaddress's description.
*/
@IsString()
@IsOptional()
description?: string;
/**
* The new address's first line.
* Containing the street and house number.
*/
@IsString()
@IsNotEmpty()
address1: string;
/**
* The new address's second line.
* Containing optional information.
*/
@IsString()
@IsOptional()
address2?: string;
/**
* The new address's postal code.
* This will get checked against the postal code syntax for the configured country.
*/
@IsString()
@IsNotEmpty()
@IsPostalCode(config.postalcode_validation_countrycode)
postalcode: string;
/**
* The new address's city.
*/
@IsString()
@IsNotEmpty()
city: string;
/**
* The new address's country.
*/
@IsString()
@IsNotEmpty()
country: string;
/**
* Creates a new Address entity from this.
*/
public async toEntity(): Promise<Address> {
let newAddress: Address = new Address();
newAddress.address1 = this.address1;
newAddress.address2 = this.address2;
newAddress.postalcode = this.postalcode;
newAddress.city = this.city;
newAddress.country = this.country;
return newAddress;
}
}

View File

@ -1,38 +1,39 @@
import { IsBoolean, IsOptional } from 'class-validator'; import { IsBoolean, IsOptional } from 'class-validator';
import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors';
import { Donor } from '../../entities/Donor'; import { Address } from '../../entities/Address';
import { CreateParticipant } from './CreateParticipant'; import { Donor } from '../../entities/Donor';
import { CreateParticipant } from './CreateParticipant';
/**
* This classed is used to create a new Donor entity from a json body (post request). /**
*/ * This classed is used to create a new Donor entity from a json body (post request).
export class CreateDonor extends CreateParticipant { */
export class CreateDonor extends CreateParticipant {
/**
* Does this donor need a receipt? /**
*/ * Does this donor need a receipt?
@IsBoolean() */
@IsOptional() @IsBoolean()
receiptNeeded?: boolean = false; @IsOptional()
receiptNeeded?: boolean = false;
/**
* Creates a new Donor entity from this. /**
*/ * Creates a new Donor entity from this.
public async toEntity(): Promise<Donor> { */
let newDonor: Donor = new Donor(); public async toEntity(): Promise<Donor> {
let newDonor: Donor = new Donor();
newDonor.firstname = this.firstname;
newDonor.middlename = this.middlename; newDonor.firstname = this.firstname;
newDonor.lastname = this.lastname; newDonor.middlename = this.middlename;
newDonor.phone = this.phone; newDonor.lastname = this.lastname;
newDonor.email = this.email; newDonor.phone = this.phone;
newDonor.address = await this.getAddress(); newDonor.email = this.email;
newDonor.receiptNeeded = this.receiptNeeded; newDonor.receiptNeeded = this.receiptNeeded;
newDonor.address = this.address;
if (this.receiptNeeded == true && this.address == null) { Address.validate(newDonor.address);
throw new DonorReceiptAddressNeededError() if (this.receiptNeeded == true && Address.isValidAddress(newDonor.address) == false) {
} throw new DonorReceiptAddressNeededError()
}
return newDonor;
} return newDonor;
}
} }

View File

@ -1,78 +1,97 @@
import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; import { IsEmail, IsNotEmpty, IsObject, IsOptional, IsPhoneNumber, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { config } from '../../../config'; import { config } from '../../../config';
import { AddressNotFoundError } from '../../../errors/AddressErrors'; import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors';
import { Address } from '../../entities/Address'; import { Address } from '../../entities/Address';
import { GroupContact } from '../../entities/GroupContact'; import { GroupContact } from '../../entities/GroupContact';
import { RunnerGroup } from '../../entities/RunnerGroup';
/**
* This classed is used to create a new Group entity from a json body (post request). /**
*/ * This classed is used to create a new GroupContact entity from a json body (post request).
export class CreateGroupContact { */
/** export class CreateGroupContact {
* The new contact's first name. /**
*/ * The new contact's first name.
@IsNotEmpty() */
@IsString() @IsNotEmpty()
firstname: string; @IsString()
firstname: string;
/**
* The new contact's middle name. /**
*/ * The new contact's middle name.
@IsOptional() */
@IsString() @IsOptional()
middlename?: string; @IsString()
middlename?: string;
/**
* The new contact's last name. /**
*/ * The new contact's last name.
@IsNotEmpty() */
@IsString() @IsNotEmpty()
lastname: string; @IsString()
lastname: string;
/**
* The new contact's address's id. /**
*/ * The new contact's address.
@IsInt() */
@IsOptional() @IsOptional()
address?: number; @IsObject()
address?: Address;
/**
* The contact's phone number. /**
* This will be validated against the configured country phone numer syntax (default: international). * The contact's phone number.
*/ * This will be validated against the configured country phone numer syntax (default: international).
@IsOptional() */
@IsPhoneNumber(config.phone_validation_countrycode) @IsOptional()
phone?: string; @IsPhoneNumber(config.phone_validation_countrycode)
phone?: string;
/**
* The contact's email address. /**
*/ * The new contact's email address.
@IsOptional() */
@IsEmail() @IsOptional()
email?: string; @IsEmail()
email?: string;
/**
* Gets the new contact's address by it's id. /**
*/ * The new contacts's groups' ids.
public async getAddress(): Promise<Address> { * You can provide either one groupId or an array of groupIDs.
if (!this.address) { return null; } */
let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); @IsOptional()
if (!address) { throw new AddressNotFoundError; } groups?: number[] | number
return address;
}
/**
/** * Get's all groups for this contact by their id's;
* Creates a new Address entity from this. */
*/ public async getGroups(): Promise<RunnerGroup[]> {
public async toEntity(): Promise<GroupContact> { if (!this.groups) { return null; }
let contact: GroupContact = new GroupContact(); let groups = new Array<RunnerGroup>();
contact.firstname = this.firstname; if (!Array.isArray(this.groups)) {
contact.middlename = this.middlename; this.groups = [this.groups]
contact.lastname = this.lastname; }
contact.email = this.email; for (let group of this.groups) {
contact.phone = this.phone; let found = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: group });
contact.address = await this.getAddress(); if (!found) { throw new RunnerGroupNotFoundError(); }
return null; groups.push(found);
} }
return groups;
}
/**
* Creates a new GroupContact entity from this.
*/
public async toEntity(): Promise<GroupContact> {
let newContact: GroupContact = new GroupContact();
newContact.firstname = this.firstname;
newContact.middlename = this.middlename;
newContact.lastname = this.lastname;
newContact.email = this.email;
newContact.phone = this.phone;
newContact.address = this.address;
Address.validate(newContact.address);
newContact.groups = await this.getGroups();
return newContact;
}
} }

View File

@ -1,65 +1,53 @@
import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; import { IsEmail, IsNotEmpty, IsObject, IsOptional, IsPhoneNumber, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { config } from '../../../config';
import { config } from '../../../config'; import { Address } from '../../entities/Address';
import { AddressNotFoundError } from '../../../errors/AddressErrors';
import { Address } from '../../entities/Address'; /**
* This classed is used to create a new Participant entity from a json body (post request).
/** */
* This classed is used to create a new Participant entity from a json body (post request). export abstract class CreateParticipant {
*/ /**
export abstract class CreateParticipant { * The new participant's first name.
/** */
* The new participant's first name. @IsString()
*/ @IsNotEmpty()
@IsString() firstname: string;
@IsNotEmpty()
firstname: string; /**
* The new participant's middle name.
/** */
* The new participant's middle name. @IsString()
*/ @IsOptional()
@IsString() middlename?: string;
@IsOptional()
middlename?: string; /**
* The new participant's last name.
/** */
* The new participant's last name. @IsString()
*/ @IsNotEmpty()
@IsString() lastname: string;
@IsNotEmpty()
lastname: string; /**
* The new participant's phone number.
/** * This will be validated against the configured country phone numer syntax (default: international).
* The new participant's phone number. */
* This will be validated against the configured country phone numer syntax (default: international). @IsString()
*/ @IsOptional()
@IsString() @IsPhoneNumber(config.phone_validation_countrycode)
@IsOptional() phone?: string;
@IsPhoneNumber(config.phone_validation_countrycode)
phone?: string; /**
* The new participant's e-mail address.
/** */
* The new participant's e-mail address. @IsString()
*/ @IsOptional()
@IsString() @IsEmail()
@IsOptional() email?: string;
@IsEmail()
email?: string; /**
* The new participant's address.
/** */
* The new participant's address's id. @IsOptional()
*/ @IsObject()
@IsInt() address?: Address;
@IsOptional()
address?: number;
/**
* Gets the new participant's address by it's id.
*/
public async getAddress(): Promise<Address> {
if (!this.address) { return null; }
let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address });
if (!address) { throw new AddressNotFoundError; }
return address;
}
} }

View File

@ -1,53 +1,55 @@
import { IsInt } from 'class-validator'; import { IsInt } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors';
import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors';
import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors';
import { Runner } from '../../entities/Runner'; import { Address } from '../../entities/Address';
import { RunnerGroup } from '../../entities/RunnerGroup'; import { Runner } from '../../entities/Runner';
import { CreateParticipant } from './CreateParticipant'; import { RunnerGroup } from '../../entities/RunnerGroup';
import { CreateParticipant } from './CreateParticipant';
/**
* This classed is used to create a new Runner entity from a json body (post request). /**
*/ * This classed is used to create a new Runner entity from a json body (post request).
export class CreateRunner extends CreateParticipant { */
export class CreateRunner extends CreateParticipant {
/**
* The new runner's group's id. /**
*/ * The new runner's group's id.
@IsInt() */
group: number; @IsInt()
group: number;
/**
* Creates a new Runner entity from this. /**
*/ * Creates a new Runner entity from this.
public async toEntity(): Promise<Runner> { */
let newRunner: Runner = new Runner(); public async toEntity(): Promise<Runner> {
let newRunner: Runner = new Runner();
newRunner.firstname = this.firstname;
newRunner.middlename = this.middlename; newRunner.firstname = this.firstname;
newRunner.lastname = this.lastname; newRunner.middlename = this.middlename;
newRunner.phone = this.phone; newRunner.lastname = this.lastname;
newRunner.email = this.email; newRunner.phone = this.phone;
newRunner.group = await this.getGroup(); newRunner.email = this.email;
newRunner.address = await this.getAddress(); newRunner.group = await this.getGroup();
newRunner.address = this.address;
return newRunner; Address.validate(newRunner.address);
}
return newRunner;
/** }
* Gets the new runner's group by it's id.
*/ /**
public async getGroup(): Promise<RunnerGroup> { * Gets the new runner's group by it's id.
if (this.group === undefined || this.group === null) { */
throw new RunnerTeamNeedsParentError(); public async getGroup(): Promise<RunnerGroup> {
} if (this.group === undefined || this.group === null) {
if (!isNaN(this.group)) { throw new RunnerTeamNeedsParentError();
let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group }); }
if (!group) { throw new RunnerGroupNotFoundError; } if (!isNaN(this.group)) {
return group; let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group });
} if (!group) { throw new RunnerGroupNotFoundError; }
return group;
throw new RunnerOrganisationWrongTypeError; }
}
throw new RunnerOrganisationWrongTypeError;
}
} }

View File

@ -1,41 +1,30 @@
import { IsInt, IsOptional } from 'class-validator'; import { IsObject, IsOptional } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { Address } from '../../entities/Address';
import { AddressNotFoundError } from '../../../errors/AddressErrors'; import { RunnerOrganisation } from '../../entities/RunnerOrganisation';
import { Address } from '../../entities/Address'; import { CreateRunnerGroup } from './CreateRunnerGroup';
import { RunnerOrganisation } from '../../entities/RunnerOrganisation';
import { CreateRunnerGroup } from './CreateRunnerGroup'; /**
* This classed is used to create a new RunnerOrganisation entity from a json body (post request).
/** */
* This classed is used to create a new RunnerOrganisation entity from a json body (post request). export class CreateRunnerOrganisation extends CreateRunnerGroup {
*/ /**
export class CreateRunnerOrganisation extends CreateRunnerGroup { * The new organisation's address.
/** */
* The new organisation's address's id. @IsOptional()
*/ @IsObject()
@IsInt() address?: Address;
@IsOptional()
address?: number; /**
* Creates a new RunnerOrganisation entity from this.
/** */
* Gets the org's address by it's id. public async toEntity(): Promise<RunnerOrganisation> {
*/ let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation();
public async getAddress(): Promise<Address> {
if (!this.address) { return null; } newRunnerOrganisation.name = this.name;
let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); newRunnerOrganisation.contact = await this.getContact();
if (!address) { throw new AddressNotFoundError; } newRunnerOrganisation.address = this.address;
return address; Address.validate(newRunnerOrganisation.address);
}
return newRunnerOrganisation;
/** }
* Creates a new RunnerOrganisation entity from this.
*/
public async toEntity(): Promise<RunnerOrganisation> {
let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation();
newRunnerOrganisation.name = this.name;
newRunnerOrganisation.contact = await this.getContact();
newRunnerOrganisation.address = await this.getAddress();
return newRunnerOrganisation;
}
} }

View File

@ -1,44 +1,46 @@
import { IsBoolean, IsInt, IsOptional } from 'class-validator'; import { IsBoolean, IsInt, IsOptional } from 'class-validator';
import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors';
import { Donor } from '../../entities/Donor'; import { Address } from '../../entities/Address';
import { CreateParticipant } from '../create/CreateParticipant'; import { Donor } from '../../entities/Donor';
import { CreateParticipant } from '../create/CreateParticipant';
/**
* This class is used to update a Donor entity (via put request). /**
*/ * This class is used to update a Donor entity (via put request).
export class UpdateDonor extends CreateParticipant { */
export class UpdateDonor extends CreateParticipant {
/**
* The updated donor's id. /**
* This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). * The updated donor's id.
*/ * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
@IsInt() */
id: number; @IsInt()
id: number;
/**
* Does the updated donor need a receipt? /**
*/ * Does the updated donor need a receipt?
@IsBoolean() */
@IsOptional() @IsBoolean()
receiptNeeded?: boolean; @IsOptional()
receiptNeeded?: boolean;
/**
* Updates a provided Donor entity based on this. /**
*/ * Updates a provided Donor entity based on this.
public async update(donor: Donor): Promise<Donor> { */
donor.firstname = this.firstname; public async update(donor: Donor): Promise<Donor> {
donor.middlename = this.middlename; donor.firstname = this.firstname;
donor.lastname = this.lastname; donor.middlename = this.middlename;
donor.phone = this.phone; donor.lastname = this.lastname;
donor.email = this.email; donor.phone = this.phone;
donor.receiptNeeded = this.receiptNeeded; donor.email = this.email;
donor.address = await this.getAddress(); donor.receiptNeeded = this.receiptNeeded;
if (!this.address) { donor.address.reset(); }
if (this.receiptNeeded == true && this.address == null) { else { donor.address = this.address; }
throw new DonorReceiptAddressNeededError() Address.validate(donor.address);
} if (this.receiptNeeded == true && Address.isValidAddress(donor.address) == false) {
throw new DonorReceiptAddressNeededError()
return donor; }
}
return donor;
}
} }

View File

@ -0,0 +1,106 @@
import { IsEmail, IsInt, IsNotEmpty, IsObject, IsOptional, IsPhoneNumber, IsString } from 'class-validator';
import { getConnectionManager } from 'typeorm';
import { config } from '../../../config';
import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors';
import { Address } from '../../entities/Address';
import { GroupContact } from '../../entities/GroupContact';
import { RunnerGroup } from '../../entities/RunnerGroup';
/**
* This class is used to update a GroupContact entity (via put request).
*/
export class UpdateGroupContact {
/**
* The updated contact's id.
* This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
*/
@IsInt()
id: number;
/**
* The updated contact's first name.
*/
@IsNotEmpty()
@IsString()
firstname: string;
/**
* The updated contact's middle name.
*/
@IsOptional()
@IsString()
middlename?: string;
/**
* The updated contact's last name.
*/
@IsNotEmpty()
@IsString()
lastname: string;
/**
* The updated contact's address.
*/
@IsOptional()
@IsObject()
address?: Address;
/**
* The updated contact's phone number.
* This will be validated against the configured country phone numer syntax (default: international).
*/
@IsOptional()
@IsPhoneNumber(config.phone_validation_countrycode)
phone?: string;
/**
* The updated contact's email address.
*/
@IsOptional()
@IsEmail()
email?: string;
/**
* The updated contacts's groups' ids.
* You can provide either one groupId or an array of groupIDs.
*/
@IsOptional()
groups?: number[] | number
/**
* Get's all groups for this contact by their id's;
*/
public async getGroups(): Promise<RunnerGroup[]> {
if (!this.groups) { return null; }
let groups = new Array<RunnerGroup>();
if (!Array.isArray(this.groups)) {
this.groups = [this.groups]
}
for (let group of this.groups) {
let found = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: group });
if (!found) { throw new RunnerGroupNotFoundError(); }
groups.push(found);
}
return groups;
}
/**
* Updates a provided Donor entity based on this.
* @param contact the contact you want to update.
*/
public async update(contact: GroupContact): Promise<GroupContact> {
contact.firstname = this.firstname; GroupContact
contact.middlename = this.middlename;
contact.lastname = this.lastname;
contact.phone = this.phone;
contact.email = this.email;
if (!this.address) { contact.address.reset(); }
else { contact.address = this.address; }
Address.validate(contact.address);
contact.groups = await this.getGroups();
return contact;
}
}

View File

@ -1,54 +1,57 @@
import { IsInt, IsPositive } from 'class-validator'; import { IsInt, IsPositive } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { getConnectionManager } from 'typeorm';
import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors';
import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors';
import { Runner } from '../../entities/Runner'; import { Address } from '../../entities/Address';
import { RunnerGroup } from '../../entities/RunnerGroup'; import { Runner } from '../../entities/Runner';
import { CreateParticipant } from '../create/CreateParticipant'; import { RunnerGroup } from '../../entities/RunnerGroup';
import { CreateParticipant } from '../create/CreateParticipant';
/**
* This class is used to update a Runner entity (via put request). /**
*/ * This class is used to update a Runner entity (via put request).
export class UpdateRunner extends CreateParticipant { */
export class UpdateRunner extends CreateParticipant {
/**
* The updated runner's id. /**
* This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). * The updated runner's id.
*/ * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
@IsInt() */
id: number; @IsInt()
id: number;
/**
* The updated runner's group's id. /**
*/ * The updated runner's group's id.
@IsInt() */
@IsPositive() @IsInt()
group: number; @IsPositive()
group: number;
/**
* Updates a provided Runner entity based on this. /**
*/ * Updates a provided Runner entity based on this.
public async update(runner: Runner): Promise<Runner> { */
runner.firstname = this.firstname; public async update(runner: Runner): Promise<Runner> {
runner.middlename = this.middlename; runner.firstname = this.firstname;
runner.lastname = this.lastname; runner.middlename = this.middlename;
runner.phone = this.phone; runner.lastname = this.lastname;
runner.email = this.email; runner.phone = this.phone;
runner.group = await this.getGroup(); runner.email = this.email;
runner.address = await this.getAddress(); runner.group = await this.getGroup();
if (!this.address) { runner.address.reset(); }
return runner; else { runner.address = this.address; }
} Address.validate(runner.address);
/** return runner;
* Loads the updated runner's group based on it's id. }
*/
public async getGroup(): Promise<RunnerGroup> { /**
if (this.group === undefined || this.group === null) { * Loads the updated runner's group based on it's id.
throw new RunnerTeamNeedsParentError(); */
} public async getGroup(): Promise<RunnerGroup> {
let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group }); if (this.group === undefined || this.group === null) {
if (!group) { throw new RunnerGroupNotFoundError; } throw new RunnerTeamNeedsParentError();
return group; }
} let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group });
if (!group) { throw new RunnerGroupNotFoundError; }
return group;
}
} }

View File

@ -1,48 +1,38 @@
import { IsInt, IsOptional } from 'class-validator'; import { IsInt, IsObject, IsOptional } from 'class-validator';
import { getConnectionManager } from 'typeorm'; import { Address } from '../../entities/Address';
import { AddressNotFoundError } from '../../../errors/AddressErrors'; import { RunnerOrganisation } from '../../entities/RunnerOrganisation';
import { Address } from '../../entities/Address'; import { CreateRunnerGroup } from '../create/CreateRunnerGroup';
import { RunnerOrganisation } from '../../entities/RunnerOrganisation';
import { CreateRunnerGroup } from '../create/CreateRunnerGroup'; /**
* This class is used to update a RunnerOrganisation entity (via put request).
/** */
* This class is used to update a RunnerOrganisation entity (via put request). export class UpdateRunnerOrganisation extends CreateRunnerGroup {
*/
export class UpdateRunnerOrganisation extends CreateRunnerGroup { /**
* The updated orgs's id.
/** * This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to).
* The updated orgs's id. */
* This shouldn't have changed but it is here in case anyone ever wants to enable id changes (whyever they would want to). @IsInt()
*/ id: number;
@IsInt()
id: number; /**
* The updated organisation's address.
/** */
* The updated organisation's address's id. @IsOptional()
*/ @IsObject()
@IsInt() address?: Address;
@IsOptional()
address?: number; /**
* Updates a provided RunnerOrganisation entity based on this.
/** */
* Loads the organisation's address based on it's id. public async update(organisation: RunnerOrganisation): Promise<RunnerOrganisation> {
*/
public async getAddress(): Promise<Address> { organisation.name = this.name;
if (!this.address) { return null; } organisation.contact = await this.getContact();
let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); if (!this.address) { organisation.address.reset(); }
if (!address) { throw new AddressNotFoundError; } else { organisation.address = this.address; }
return address; Address.validate(organisation.address);
}
return organisation;
/** }
* Updates a provided RunnerOrganisation entity based on this.
*/
public async update(organisation: RunnerOrganisation): Promise<RunnerOrganisation> {
organisation.name = this.name;
organisation.contact = await this.getContact();
organisation.address = await this.getAddress();
return organisation;
}
} }

View File

@ -1,90 +1,86 @@
import { import {
IsInt, IsPostalCode,
IsNotEmpty, IsString
IsOptional, } from "class-validator";
IsPostalCode, import { Column } from "typeorm";
IsString import ValidatorJS from 'validator';
} from "class-validator"; import { config } from '../../config';
import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { AddressCityEmptyError, AddressCountryEmptyError, AddressFirstLineEmptyError, AddressPostalCodeEmptyError, AddressPostalCodeInvalidError } from '../../errors/AddressErrors';
import { config } from '../../config';
import { IAddressUser } from './IAddressUser'; /**
* Defines the Address class.
/** * Implemented this way to prevent any formatting differences.
* Defines the Address entity. */
* Implemented this way to prevent any formatting differences. export class Address {
*/ /**
@Entity() * The address's first line.
export class Address { * Containing the street and house number.
/** */
* Autogenerated unique id (primary key). @Column({ nullable: true })
*/ @IsString()
@PrimaryGeneratedColumn() address1?: string;
@IsInt()
id: number; /**
* The address's second line.
/** * Containing optional information.
* The address's description. */
* Optional and mostly for UX. @Column({ nullable: true })
*/ @IsString()
@Column({ nullable: true }) address2?: string;
@IsString()
@IsOptional() /**
description?: string; * The address's postal code.
* This will get checked against the postal code syntax for the configured country.
/** */
* The address's first line. @Column({ nullable: true })
* Containing the street and house number. @IsString()
*/ @IsPostalCode(config.postalcode_validation_countrycode)
@Column() postalcode: string;
@IsString()
@IsNotEmpty() /**
address1: string; * The address's city.
*/
/** @Column({ nullable: true })
* The address's second line. @IsString()
* Containing optional information. city: string;
*/
@Column({ nullable: true }) /**
@IsString() * The address's country.
@IsOptional() */
address2?: string; @Column({ nullable: true })
@IsString()
/** country: string;
* The address's postal code.
* This will get checked against the postal code syntax for the configured country. public reset() {
*/ this.address1 = null;
@Column() this.address2 = null;
@IsString() this.city = null;
@IsNotEmpty() this.country = null;
@IsPostalCode(config.postalcode_validation_countrycode) this.postalcode = null;
postalcode: string; }
/** /**
* The address's city. * Checks if this is a valid address
*/ */
@Column() public static isValidAddress(address: Address): Boolean {
@IsString() if (address == null) { return false; }
@IsNotEmpty() if (address.address1 == null || address.city == null || address.country == null || address.postalcode == null) { return false; }
city: string; if (ValidatorJS.isPostalCode(address.postalcode, config.postalcode_validation_countrycode) == false) { return false; }
return true;
/** }
* The address's country.
*/ /**
@Column() * This function validates addresses.
@IsString() * This is a workaround for non-existant class validation for embedded entities.
@IsNotEmpty() * @param address The address that shall get validated.
country: string; */
public static validate(address: Address) {
/** if (address == null) { return; }
* Used to link the address to participants. if (address.address1 == null && address.city == null && address.country == null && address.postalcode == null) { return; }
*/ if (address.address1 == null) { throw new AddressFirstLineEmptyError(); }
@OneToMany(() => IAddressUser, addressUser => addressUser.address, { nullable: true }) if (address.postalcode == null) { throw new AddressPostalCodeEmptyError(); }
addressUsers: IAddressUser[]; if (address.city == null) { throw new AddressCityEmptyError(); }
if (address.country == null) { throw new AddressCountryEmptyError(); }
/** if (ValidatorJS.isPostalCode(address.postalcode.toString(), config.postalcode_validation_countrycode) == false) { throw new AddressPostalCodeInvalidError(); }
* Turns this entity into it's response class. }
*/ }
public toResponse() {
return new Error("NotImplemented");
}
}

View File

@ -7,10 +7,10 @@ import {
IsString IsString
} from "class-validator"; } from "class-validator";
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { config } from '../../config'; import { config } from '../../config';
import { ResponseGroupContact } from '../responses/ResponseGroupContact';
import { Address } from "./Address"; import { Address } from "./Address";
import { IAddressUser } from './IAddressUser';
import { RunnerGroup } from "./RunnerGroup"; import { RunnerGroup } from "./RunnerGroup";
/** /**
@ -18,7 +18,7 @@ import { RunnerGroup } from "./RunnerGroup";
* Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups. * Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups.
*/ */
@Entity() @Entity()
export class GroupContact implements IAddressUser { export class GroupContact {
/** /**
* Autogenerated unique id (primary key). * Autogenerated unique id (primary key).
*/ */
@ -54,8 +54,7 @@ export class GroupContact implements IAddressUser {
* The contact's address. * The contact's address.
* This is a address object to prevent any formatting differences. * This is a address object to prevent any formatting differences.
*/ */
@IsOptional() @Column(type => Address)
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true })
address?: Address; address?: Address;
/** /**
@ -85,7 +84,7 @@ export class GroupContact implements IAddressUser {
/** /**
* Turns this entity into it's response class. * Turns this entity into it's response class.
*/ */
public toResponse() { public toResponse(): ResponseGroupContact {
return new Error("NotImplemented"); return new ResponseGroupContact(this);
} }
} }

View File

@ -1,20 +0,0 @@
import { Entity, ManyToOne, PrimaryColumn } from 'typeorm';
import { Address } from './Address';
/**
* The interface(tm) all entities using addresses have to implement.
* This is a abstract class, because apparently typeorm can't really work with interfaces :/
*/
@Entity()
export abstract class IAddressUser {
@PrimaryColumn()
id: number;
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true })
address?: Address
/**
* Turns this entity into it's response class.
*/
public abstract toResponse();
}

View File

@ -7,11 +7,10 @@ import {
IsString IsString
} from "class-validator"; } from "class-validator";
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; import { Column, Entity, PrimaryGeneratedColumn, TableInheritance } from "typeorm";
import { config } from '../../config'; import { config } from '../../config';
import { ResponseParticipant } from '../responses/ResponseParticipant'; import { ResponseParticipant } from '../responses/ResponseParticipant';
import { Address } from "./Address"; import { Address } from "./Address";
import { IAddressUser } from './IAddressUser';
/** /**
* Defines the Participant entity. * Defines the Participant entity.
@ -19,7 +18,7 @@ import { IAddressUser } from './IAddressUser';
*/ */
@Entity() @Entity()
@TableInheritance({ column: { name: "type", type: "varchar" } }) @TableInheritance({ column: { name: "type", type: "varchar" } })
export abstract class Participant implements IAddressUser { export abstract class Participant {
/** /**
* Autogenerated unique id (primary key). * Autogenerated unique id (primary key).
*/ */
@ -55,7 +54,7 @@ export abstract class Participant implements IAddressUser {
* The participant's address. * The participant's address.
* This is a address object to prevent any formatting differences. * This is a address object to prevent any formatting differences.
*/ */
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) @Column(type => Address)
address?: Address; address?: Address;
/** /**

View File

@ -1,65 +1,64 @@
import { IsInt, IsOptional } from "class-validator"; import { IsInt, IsOptional } from "class-validator";
import { ChildEntity, ManyToOne, OneToMany } from "typeorm"; import { ChildEntity, Column, OneToMany } from "typeorm";
import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation'; import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation';
import { Address } from './Address'; import { Address } from './Address';
import { IAddressUser } from './IAddressUser'; import { Runner } from './Runner';
import { Runner } from './Runner'; import { RunnerGroup } from "./RunnerGroup";
import { RunnerGroup } from "./RunnerGroup"; import { RunnerTeam } from "./RunnerTeam";
import { RunnerTeam } from "./RunnerTeam";
/**
/** * Defines the RunnerOrganisation entity.
* Defines the RunnerOrganisation entity. * This usually is a school, club or company.
* This usually is a school, club or company. */
*/ @ChildEntity()
@ChildEntity() export class RunnerOrganisation extends RunnerGroup {
export class RunnerOrganisation extends RunnerGroup implements IAddressUser {
/**
/** * The organisations's address.
* The organisations's address. */
*/ @IsOptional()
@IsOptional() @Column(type => Address)
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) address?: Address;
address?: Address;
/**
/** * The organisation's teams.
* The organisation's teams. * Used to link teams to a organisation.
* Used to link teams to a organisation. */
*/ @OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true })
@OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true }) teams: RunnerTeam[];
teams: RunnerTeam[];
/**
/** * Returns all runners associated with this organisation (directly or indirectly via teams).
* Returns all runners associated with this organisation (directly or indirectly via teams). */
*/ public get allRunners(): Runner[] {
public get allRunners(): Runner[] { let returnRunners: Runner[] = new Array<Runner>();
let returnRunners: Runner[] = new Array<Runner>(); returnRunners.push(...this.runners);
returnRunners.push(...this.runners); for (let team of this.teams) {
for (let team of this.teams) { returnRunners.push(...team.runners)
returnRunners.push(...team.runners) }
} return returnRunners;
return returnRunners; }
}
/**
/** * Returns the total distance ran by this group's runners based on all their valid scans.
* Returns the total distance ran by this group's runners based on all their valid scans. */
*/ @IsInt()
@IsInt() public get distance(): number {
public get distance(): number { return this.allRunners.reduce((sum, current) => sum + current.distance, 0);
return this.allRunners.reduce((sum, current) => sum + current.distance, 0); }
}
/**
/** * Returns the total donations a runner has collected based on his linked donations and distance ran.
* Returns the total donations a runner has collected based on his linked donations and distance ran. */
*/ @IsInt()
@IsInt() public get distanceDonationAmount(): number {
public get distanceDonationAmount(): number { return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0);
return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0); }
}
/**
/** * Turns this entity into it's response class.
* Turns this entity into it's response class. */
*/ public toResponse(): ResponseRunnerOrganisation {
public toResponse(): ResponseRunnerOrganisation { return new ResponseRunnerOrganisation(this);
return new ResponseRunnerOrganisation(this); }
}
} }

View File

@ -14,5 +14,6 @@ export enum PermissionTarget {
SCAN = 'SCAN', SCAN = 'SCAN',
STATION = 'STATION', STATION = 'STATION',
CARD = 'CARD', CARD = 'CARD',
DONATION = 'DONATION' DONATION = 'DONATION',
CONTACT = 'CONTACT'
} }

View File

@ -0,0 +1,76 @@
import { IsInt, IsObject, IsString } from "class-validator";
import { Address } from '../entities/Address';
import { GroupContact } from '../entities/GroupContact';
import { ResponseRunnerGroup } from './ResponseRunnerGroup';
/**
* Defines the group contact response.
*/
export class ResponseGroupContact {
/**
* The contact's id.
*/
@IsInt()
id: number;
/**
* The contact's first name.
*/
@IsString()
firstname: string;
/**
* The contact's middle name.
*/
@IsString()
middlename?: string;
/**
* The contact's last name.
*/
@IsString()
lastname: string;
/**
* The contact's phone number.
*/
@IsString()
phone?: string;
/**
* The contact's e-mail address.
*/
@IsString()
email?: string;
/**
* The contact's associated runner groups.
*/
@IsObject()
groups: ResponseRunnerGroup[];
/**
* The contact's address.
* This is a address object to prevent any formatting differences.
*/
@IsObject()
address?: Address;
/**
* Creates a ResponseGroupContact object from a contact.
* @param contact The contact the response shall be build for.
*/
public constructor(contact: GroupContact) {
this.id = contact.id;
this.firstname = contact.firstname;
this.middlename = contact.middlename;
this.lastname = contact.lastname;
this.phone = contact.phone;
this.email = contact.email;
this.address = contact.address;
this.groups = new Array<ResponseRunnerGroup>();
for (let group of contact.groups) {
this.groups.push(group.toResponse());
}
}
}

View File

@ -1,56 +1,65 @@
import { IsInt, IsString } from "class-validator"; import { IsInt, IsObject, IsOptional, IsString } from "class-validator";
import { Participant } from '../entities/Participant'; import { Address } from '../entities/Address';
import { Participant } from '../entities/Participant';
/**
* Defines the participant response. /**
*/ * Defines the participant response.
export abstract class ResponseParticipant { */
/** export abstract class ResponseParticipant {
* The participant's id. /**
*/ * The participant's id.
@IsInt() */
id: number; @IsInt()
id: number;
/**
* The participant's first name. /**
*/ * The participant's first name.
@IsString() */
firstname: string; @IsString()
firstname: string;
/**
* The participant's middle name. /**
*/ * The participant's middle name.
@IsString() */
middlename?: string; @IsString()
middlename?: string;
/**
* The participant's last name. /**
*/ * The participant's last name.
@IsString() */
lastname: string; @IsString()
lastname: string;
/**
* The participant's phone number. /**
*/ * The participant's phone number.
@IsString() */
phone?: string; @IsString()
phone?: string;
/**
* The participant's e-mail address. /**
*/ * The participant's e-mail address.
@IsString() */
email?: string; @IsString()
email?: string;
/**
* Creates a ResponseParticipant object from a participant. /**
* @param participant The participant the response shall be build for. * The participant's address.
*/ */
public constructor(participant: Participant) { @IsOptional()
this.id = participant.id; @IsObject()
this.firstname = participant.firstname; address?: Address;
this.middlename = participant.middlename;
this.lastname = participant.lastname; /**
this.phone = participant.phone; * Creates a ResponseParticipant object from a participant.
this.email = participant.email; * @param participant The participant the response shall be build for.
} */
} public constructor(participant: Participant) {
this.id = participant.id;
this.firstname = participant.firstname;
this.middlename = participant.middlename;
this.lastname = participant.lastname;
this.phone = participant.phone;
this.email = participant.email;
this.address = participant.address;
}
}

View File

@ -0,0 +1,216 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let access_token;
let axios_config;
beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"];
axios_config = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
// ---------------
describe('POST /api/contacts with errors', () => {
it('creating a new contact without any parameters should return 400', async () => {
const res = await axios.post(base + '/api/contacts', null, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact without a last name should return 400', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"middlename": "middle"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a invalid phone number should return 400', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"middlename": "middle",
"lastname": "last",
"phone": "123"
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a invalid mail address should return 400', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"phone": null,
"email": "123",
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with an invalid address 400', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"address": {
"city": "Testcity"
}
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a invalid group should return 404', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "string",
"middlename": "string",
"lastname": "string",
"groups": 9999999999999
}, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('POST /api/contacts working (simple)', () => {
it('creating a new contact with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last"
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with all non-relationship optional params should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"middlename": "middle",
"lastname": "last",
"email": "testContact@lauf-fuer-kaya.de",
"phone": "+49017612345678",
"address": {
"address1": "test",
"address2": null,
"city": "herzogenaurach",
"country": "germany",
"postalcode": "91074",
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('POST /api/contacts working (with group)', () => {
let added_org;
let added_team;
let added_contact;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
delete res.data.contact;
delete res.data.teams;
added_org = res.data
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new team with a parent org should return 200', async () => {
const res = await axios.post(base + '/api/teams', {
"name": "test_team",
"parentGroup": added_org.id
}, axios_config);
delete res.data.contact;
delete res.data.parentGroup;
added_team = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a valid org should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": added_org.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
delete res.data.id;
expect(res.data).toEqual({
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_org]
});
});
it('creating a new contact with a valid team should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": added_team.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
delete res.data.id;
expect(res.data).toEqual({
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_team]
});
});
it('creating a new contact with a valid org and team should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": [added_org.id, added_team.id]
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
added_contact = res.data
delete res.data.id;
expect(res.data).toEqual({
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_org, added_team]
});
});
it('checking if the added team\'s contact is the new contact should return 200', async () => {
const res = await axios.get(base + '/api/teams/' + added_team.id, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
delete res.data.contact.groups;
delete res.data.contact.id;
delete added_contact.groups;
expect(res.data.contact).toEqual(added_contact);
});
});

View File

@ -0,0 +1,183 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let access_token;
let axios_config;
beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"];
axios_config = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
describe('adding + deletion (non-existant)', () => {
it('delete', async () => {
const res = await axios.delete(base + '/api/contacts/0', axios_config);
expect(res.status).toEqual(204);
});
});
// ---------------
describe('add+delete (simple)', () => {
let added_contact;
it('creating a new contact with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last"
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('delete contact', async () => {
const res = await axios.delete(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
let deleted_contact = res.data
expect(deleted_contact).toEqual(added_contact);
});
it('check if contact really was deleted', async () => {
const res = await axios.get(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('add+delete (with org)', () => {
let added_org;
let added_contact;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
delete res.data.contact;
delete res.data.teams;
added_org = res.data
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a valid org should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": added_org.id
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('delete contact', async () => {
const res = await axios.delete(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
delete res.data.groups[0].contact;
expect(res.data).toEqual(added_contact);
});
it('check if contact really was deleted', async () => {
const res = await axios.get(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('add+delete (with team)', () => {
let added_org;
let added_team;
let added_contact;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
delete res.data.contact;
delete res.data.teams;
added_org = res.data
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new team with a parent org should return 200', async () => {
const res = await axios.post(base + '/api/teams', {
"name": "test_team",
"parentGroup": added_org.id
}, axios_config);
delete res.data.contact;
delete res.data.parentGroup;
added_team = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a valid team should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": added_team.id
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('delete contact', async () => {
const res = await axios.delete(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
delete res.data.groups[0].contact;
expect(res.data).toEqual(added_contact);
});
it('check if contact really was deleted', async () => {
const res = await axios.get(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('add+delete (with org&team)', () => {
let added_org;
let added_team;
let added_contact;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
delete res.data.contact;
delete res.data.teams;
added_org = res.data
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new team with a parent org should return 200', async () => {
const res = await axios.post(base + '/api/teams', {
"name": "test_team",
"parentGroup": added_org.id
}, axios_config);
delete res.data.contact;
delete res.data.parentGroup;
added_team = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a valid org and team should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": [added_org.id, added_team.id]
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
});
it('delete contact', async () => {
const res = await axios.delete(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
delete res.data.groups[0].contact;
delete res.data.groups[1].contact;
expect(res.data).toEqual(added_contact);
});
it('check if contact really was deleted', async () => {
const res = await axios.get(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json")
});
});

View File

@ -0,0 +1,57 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let access_token;
let axios_config;
beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"];
axios_config = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
describe('GET /api/contacts', () => {
it('basic get should return 200', async () => {
const res = await axios.get(base + '/api/contacts', axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('GET /api/contacts/0', () => {
it('basic get should return 404', async () => {
const res = await axios.get(base + '/api/contacts/0', axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('GET /api/contacts after adding', () => {
let added_contact;
it('creating a new donor with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last"
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('explicit get should return 200', async () => {
const res = await axios.get(base + '/api/contacts/' + added_contact.id, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
let gotten_donor = res.data
expect(gotten_donor).toEqual(added_contact);
});
it('get from all runners should return 200', async () => {
const res = await axios.get(base + '/api/contacts/', axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
let gotten_donors = res.data
expect(gotten_donors).toContainEqual(added_contact);
});
});

View File

@ -0,0 +1,237 @@
import axios from 'axios';
import { config } from '../../config';
const base = "http://localhost:" + config.internal_port
let access_token;
let axios_config;
beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"];
axios_config = {
headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined
};
});
describe('Update contact name after adding', () => {
let added_contact;
it('creating a new contact with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last"
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('valid update should return 200', async () => {
let contact_copy = added_contact
contact_copy.firstname = "second"
const res = await axios.put(base + '/api/contacts/' + added_contact.id, contact_copy, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
expect(res.data).toEqual(contact_copy);
});
});
// ---------------
describe('Update contact id after adding(should fail)', () => {
let added_contact;
it('creating a new donor with only needed params should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last"
}, axios_config);
added_contact = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('invalid update should return 406', async () => {
added_contact.id++;
const res = await axios.put(base + '/api/contacts/' + (added_contact.id - 1), added_contact, axios_config);
expect(res.status).toEqual(406);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('Update contact group after adding (should work)', () => {
let added_org;
let added_team;
let added_contact;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
delete res.data.contact;
delete res.data.teams;
added_org = res.data
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new team with a parent org should return 200', async () => {
const res = await axios.post(base + '/api/teams', {
"name": "test_team",
"parentGroup": added_org.id
}, axios_config);
delete res.data.contact;
delete res.data.parentGroup;
added_team = res.data;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a valid org should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": added_org.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
added_contact = res.data
expect(res.data).toEqual({
"id": res.data.id,
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_org]
});
});
it('valid group update to single team should return 200', async () => {
const res = await axios.put(base + '/api/contacts/' + added_contact.id, {
"id": added_contact.id,
"firstname": "first",
"lastname": "last",
"groups": added_team.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": res.data.id,
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_team]
});
});
it('valid group update to org and team should return 200', async () => {
const res = await axios.put(base + '/api/contacts/' + added_contact.id, {
"id": added_contact.id,
"firstname": "first",
"lastname": "last",
"groups": [added_org.id, added_team.id]
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": res.data.id,
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_org, added_team]
});
});
it('valid group update to none should return 200', async () => {
const res = await axios.put(base + '/api/contacts/' + added_contact.id, {
"id": added_contact.id,
"firstname": "first",
"lastname": "last",
"groups": null
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": res.data.id,
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": []
});
});
});
// ---------------
describe('Update contact group invalid after adding (should fail)', () => {
let added_org;
let added_contact;
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
delete res.data.contact;
delete res.data.teams;
added_org = res.data
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('creating a new contact with a valid org should return 200', async () => {
const res = await axios.post(base + '/api/contacts', {
"firstname": "first",
"lastname": "last",
"groups": added_org.id
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
added_contact = res.data
expect(res.data).toEqual({
"id": res.data.id,
"firstname": "first",
"middlename": null,
"lastname": "last",
"phone": null,
"email": null,
"address": {
"address1": null,
"address2": null,
"postalcode": null,
"city": null,
"country": null
},
"groups": [added_org]
});
});
it('invalid group update to single team should return 404', async () => {
const res = await axios.put(base + '/api/contacts/' + added_contact.id, {
"id": added_contact.id,
"firstname": "first",
"lastname": "last",
"groups": 999999999999999
}, axios_config);
expect(res.status).toEqual(404);
expect(res.headers['content-type']).toContain("application/json");
});
});

View File

@ -1,94 +1,84 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
// --------------- // ---------------
describe('POST /api/donors with errors', () => { describe('POST /api/donors with errors', () => {
it('creating a new donor without any parameters should return 400', async () => { it('creating a new donor without any parameters should return 400', async () => {
const res1 = await axios.post(base + '/api/donors', null, axios_config); const res1 = await axios.post(base + '/api/donors', null, axios_config);
expect(res1.status).toEqual(400); expect(res1.status).toEqual(400);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('creating a new donor without a last name should return 400', async () => { it('creating a new donor without a last name should return 400', async () => {
const res2 = await axios.post(base + '/api/donors', { const res2 = await axios.post(base + '/api/donors', {
"firstname": "first", "firstname": "first",
"middlename": "middle" "middlename": "middle"
}, axios_config); }, axios_config);
expect(res2.status).toEqual(400); expect(res2.status).toEqual(400);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('creating a new donor with a invalid address should return 404', async () => { it('creating a new donor with a invalid phone number should return 400', async () => {
const res2 = await axios.post(base + '/api/donors', { const res2 = await axios.post(base + '/api/donors', {
"firstname": "first", "firstname": "first",
"middlename": "middle", "middlename": "middle",
"lastname": "last", "lastname": "last",
"address": 99999999999999999999999999 "phone": "123"
}, axios_config); }, axios_config);
expect(res2.status).toEqual(404); expect(res2.status).toEqual(400);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('creating a new donor with a invalid phone number should return 400', async () => { it('creating a new donor with a invalid mail address should return 400', async () => {
const res2 = await axios.post(base + '/api/donors', { const res2 = await axios.post(base + '/api/donors', {
"firstname": "first", "firstname": "string",
"middlename": "middle", "middlename": "string",
"lastname": "last", "lastname": "string",
"phone": "123" "phone": null,
}, axios_config); "email": "123",
expect(res2.status).toEqual(400); }, axios_config);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.status).toEqual(400);
}); expect(res2.headers['content-type']).toContain("application/json")
it('creating a new donor with a invalid mail address should return 400', async () => { });
const res2 = await axios.post(base + '/api/donors', { it('creating a new donor without an address but with receiptNeeded=true 406', async () => {
"firstname": "string", const res2 = await axios.post(base + '/api/donors', {
"middlename": "string", "firstname": "string",
"lastname": "string", "middlename": "string",
"phone": null, "lastname": "string",
"email": "123", "receiptNeeded": true
}, axios_config); }, axios_config);
expect(res2.status).toEqual(400); expect(res2.status).toEqual(406);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('creating a new donor without an address but with receiptNeeded=true 406', async () => { });
const res2 = await axios.post(base + '/api/donors', { // ---------------
"firstname": "string", describe('POST /api/donors working', () => {
"middlename": "string", it('creating a new donor with only needed params should return 200', async () => {
"lastname": "string", const res2 = await axios.post(base + '/api/donors', {
"receiptNeeded": true "firstname": "first",
}, axios_config); "lastname": "last"
expect(res2.status).toEqual(406); }, axios_config);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.status).toEqual(200);
}); expect(res2.headers['content-type']).toContain("application/json")
}); });
// --------------- it('creating a new donor with all non-relationship optional params should return 200', async () => {
describe('POST /api/donors working', () => { const res3 = await axios.post(base + '/api/donors', {
it('creating a new donor with only needed params should return 200', async () => { "firstname": "first",
const res2 = await axios.post(base + '/api/donors', { "middlename": "middle",
"firstname": "first", "lastname": "last",
"lastname": "last" "receiptNeeded": false
}, axios_config); }, axios_config);
expect(res2.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });
it('creating a new donor with all non-relationship optional params should return 200', async () => {
const res3 = await axios.post(base + '/api/donors', {
"firstname": "first",
"middlename": "middle",
"lastname": "last",
"receiptNeeded": false
}, axios_config);
expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json")
});
}); });

View File

@ -1,75 +1,75 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
describe('Update donor name after adding', () => { describe('Update donor name after adding', () => {
let added_donor; let added_donor;
it('creating a new runner with only needed params should return 200', async () => { it('creating a new runner with only needed params should return 200', async () => {
const res2 = await axios.post(base + '/api/donors', { const res2 = await axios.post(base + '/api/donors', {
"firstname": "first", "firstname": "first",
"lastname": "last" "lastname": "last"
}, axios_config); }, axios_config);
added_donor = res2.data; added_donor = res2.data;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('valid update should return 200', async () => { it('valid update should return 200', async () => {
let donor_copy = added_donor let donor_copy = added_donor
donor_copy.firstname = "second" donor_copy.firstname = "second"
const res3 = await axios.put(base + '/api/donors/' + added_donor.id, donor_copy, axios_config); const res3 = await axios.put(base + '/api/donors/' + added_donor.id, donor_copy, axios_config);
expect(res3.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
let updated_donor = res3.data let updated_donor = res3.data
expect(updated_donor).toEqual(donor_copy); expect(updated_donor).toEqual(donor_copy);
}); });
}); });
// --------------- // ---------------
describe('Update donor id after adding(should fail)', () => { describe('Update donor id after adding(should fail)', () => {
let added_donor; let added_donor;
it('creating a new donor with only needed params should return 200', async () => { it('creating a new donor with only needed params should return 200', async () => {
const res2 = await axios.post(base + '/api/donors', { const res2 = await axios.post(base + '/api/donors', {
"firstname": "first", "firstname": "first",
"lastname": "last" "lastname": "last"
}, axios_config); }, axios_config);
added_donor = res2.data; added_donor = res2.data;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('invalid update should return 406', async () => { it('invalid update should return 406', async () => {
added_donor.id++; added_donor.id++;
const res3 = await axios.put(base + '/api/donors/' + (added_donor.id - 1), added_donor, axios_config); const res3 = await axios.put(base + '/api/donors/' + (added_donor.id - 1), added_donor, axios_config);
expect(res3.status).toEqual(406); expect(res3.status).toEqual(406);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });
}); });
// --------------- // ---------------
describe('Update donor without address but receiptNeeded=true should fail', () => { describe('Update donor without address but receiptNeeded=true should fail', () => {
let added_donor; let added_donor;
it('creating a new donor with only needed params should return 200', async () => { it('creating a new donor with only needed params should return 200', async () => {
const res2 = await axios.post(base + '/api/donors', { const res2 = await axios.post(base + '/api/donors', {
"firstname": "first", "firstname": "first",
"lastname": "last", "lastname": "testtest",
}, axios_config); }, axios_config);
added_donor = res2.data; added_donor = res2.data;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('invalid update should return 406', async () => { it('invalid update should return 406', async () => {
added_donor.receiptNeeded = true; added_donor.receiptNeeded = true;
const res3 = await axios.put(base + '/api/donors/' + added_donor.id, added_donor, axios_config); const res3 = await axios.put(base + '/api/donors/' + added_donor.id, added_donor, axios_config);
expect(res3.status).toEqual(406); expect(res3.status).toEqual(406);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });
}); });

View File

@ -1,90 +1,102 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
describe('GET /api/organisations', () => { describe('GET /api/organisations', () => {
it('basic get should return 200', async () => { it('basic get should return 200', async () => {
const res = await axios.get(base + '/api/organisations', axios_config); const res = await axios.get(base + '/api/organisations', axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
}); });
// --------------- // ---------------
describe('POST /api/organisations', () => { describe('POST /api/organisations', () => {
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with without a name should return 400', async () => { it('creating a new org with without a name should return 400', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organisations', {
"name": null "name": null
}, axios_config); }, axios_config);
expect(res.status).toEqual(400); expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
}); });
// --------------- // ---------------
describe('adding + getting from all orgs', () => { describe('adding + getting from all orgs', () => {
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('check if org was added', async () => { it('check if org was added', async () => {
const res = await axios.get(base + '/api/organisations', axios_config); const res = await axios.get(base + '/api/organisations', axios_config);
expect(res.status).toEqual(200); expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
let added_org = res.data[res.data.length - 1] let added_org = res.data[res.data.length - 1]
delete added_org.id delete added_org.id
expect(added_org).toEqual({ expect(added_org).toEqual({
"name": "test123", "name": "test123",
"contact": null, "contact": null,
"address": null, "address": {
"teams": [] "address1": null,
}) "address2": null,
}); "city": null,
}); "country": null,
// --------------- "postalcode": null,
describe('adding + getting explicitly', () => { },
let added_org_id "teams": []
it('creating a new org with just a name should return 200', async () => { })
const res1 = await axios.post(base + '/api/organisations', { });
"name": "test123" });
}, axios_config); // ---------------
let added_org = res1.data describe('adding + getting explicitly', () => {
added_org_id = added_org.id; let added_org_id
expect(res1.status).toEqual(200); it('creating a new org with just a name should return 200', async () => {
expect(res1.headers['content-type']).toContain("application/json") const res1 = await axios.post(base + '/api/organisations', {
}); "name": "test123"
it('check if org was added', async () => { }, axios_config);
const res2 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); let added_org = res1.data
expect(res2.status).toEqual(200); added_org_id = added_org.id;
expect(res2.headers['content-type']).toContain("application/json") expect(res1.status).toEqual(200);
let added_org2 = res2.data expect(res1.headers['content-type']).toContain("application/json")
added_org_id = added_org2.id; });
delete added_org2.id it('check if org was added', async () => {
expect(added_org2).toEqual({ const res2 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config);
"name": "test123", expect(res2.status).toEqual(200);
"contact": null, expect(res2.headers['content-type']).toContain("application/json")
"address": null, let added_org2 = res2.data
"teams": [] added_org_id = added_org2.id;
}) delete added_org2.id
}); expect(added_org2).toEqual({
"name": "test123",
"contact": null,
"address": {
"address1": null,
"address2": null,
"city": null,
"country": null,
"postalcode": null,
},
"teams": []
})
});
}); });

View File

@ -1,132 +1,144 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
// --------------- // ---------------
describe('adding + deletion (non-existant)', () => { describe('adding + deletion (non-existant)', () => {
it('delete', async () => { it('delete', async () => {
const res2 = await axios.delete(base + '/api/organisations/0', axios_config); const res2 = await axios.delete(base + '/api/organisations/0', axios_config);
expect(res2.status).toEqual(204); expect(res2.status).toEqual(204);
}); });
}); });
// --------------- // ---------------
describe('adding + deletion (successfull)', () => { describe('adding + deletion (successfull)', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
added_org_id = added_org.id; added_org_id = added_org.id;
expect(res1.status).toEqual(200); expect(res1.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('delete', async () => { it('delete', async () => {
const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config);
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
let added_org2 = res2.data let added_org2 = res2.data
added_org_id = added_org2.id; added_org_id = added_org2.id;
delete added_org2.id delete added_org2.id
expect(added_org2).toEqual({ expect(added_org2).toEqual({
"name": "test123", "name": "test123",
"contact": null, "contact": null,
"address": null, "address": {
"teams": [] "address1": null,
}); "address2": null,
}); "city": null,
it('check if org really was deleted', async () => { "country": null,
const res3 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); "postalcode": null,
expect(res3.status).toEqual(404); },
expect(res3.headers['content-type']).toContain("application/json") "teams": []
}); });
}); });
// --------------- it('check if org really was deleted', async () => {
describe('adding + deletion with teams still existing (without force)', () => { const res3 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config);
let added_org; expect(res3.status).toEqual(404);
let added_org_id; expect(res3.headers['content-type']).toContain("application/json")
let added_team; });
let added_team_id });
it('creating a new org with just a name should return 200', async () => { // ---------------
const res1 = await axios.post(base + '/api/organisations', { describe('adding + deletion with teams still existing (without force)', () => {
"name": "test123" let added_org;
}, axios_config); let added_org_id;
added_org = res1.data; let added_team;
added_org_id = added_org.id; let added_team_id
expect(res1.status).toEqual(200); it('creating a new org with just a name should return 200', async () => {
expect(res1.headers['content-type']).toContain("application/json") const res1 = await axios.post(base + '/api/organisations', {
}); "name": "test123"
it('creating a new team with a valid org should return 200', async () => { }, axios_config);
const res2 = await axios.post(base + '/api/teams', { added_org = res1.data;
"name": "test123", added_org_id = added_org.id;
"parentGroup": added_org_id expect(res1.status).toEqual(200);
}, axios_config); expect(res1.headers['content-type']).toContain("application/json")
added_team = res2.data; });
added_team_id = added_team.id; it('creating a new team with a valid org should return 200', async () => {
expect(res2.status).toEqual(200); const res2 = await axios.post(base + '/api/teams', {
expect(res2.headers['content-type']).toContain("application/json") "name": "test123",
}); "parentGroup": added_org_id
it('delete org - this should fail with a 406', async () => { }, axios_config);
const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); added_team = res2.data;
expect(res2.status).toEqual(406); added_team_id = added_team.id;
expect(res2.headers['content-type']).toContain("application/json") expect(res2.status).toEqual(200);
}); expect(res2.headers['content-type']).toContain("application/json")
}); });
// --------------- it('delete org - this should fail with a 406', async () => {
describe('adding + deletion with teams still existing (with force)', () => { const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config);
let added_org; expect(res2.status).toEqual(406);
let added_org_id; expect(res2.headers['content-type']).toContain("application/json")
let added_team; });
let added_team_id });
it('creating a new org with just a name should return 200', async () => { // ---------------
const res1 = await axios.post(base + '/api/organisations', { describe('adding + deletion with teams still existing (with force)', () => {
"name": "test123" let added_org;
}, axios_config); let added_org_id;
added_org = res1.data; let added_team;
added_org_id = added_org.id; let added_team_id
expect(res1.status).toEqual(200); it('creating a new org with just a name should return 200', async () => {
expect(res1.headers['content-type']).toContain("application/json") const res1 = await axios.post(base + '/api/organisations', {
}); "name": "test123"
it('creating a new team with a valid org should return 200', async () => { }, axios_config);
const res2 = await axios.post(base + '/api/teams', { added_org = res1.data;
"name": "test123", added_org_id = added_org.id;
"parentGroup": added_org_id expect(res1.status).toEqual(200);
}, axios_config); expect(res1.headers['content-type']).toContain("application/json")
added_team = res2.data; });
added_team_id = added_team.id; it('creating a new team with a valid org should return 200', async () => {
expect(res2.status).toEqual(200); const res2 = await axios.post(base + '/api/teams', {
expect(res2.headers['content-type']).toContain("application/json") "name": "test123",
}); "parentGroup": added_org_id
it('delete', async () => { }, axios_config);
const res2 = await axios.delete(base + '/api/organisations/' + added_org_id + '?force=true', axios_config); added_team = res2.data;
expect(res2.status).toEqual(200); added_team_id = added_team.id;
expect(res2.headers['content-type']).toContain("application/json") expect(res2.status).toEqual(200);
let added_org2 = res2.data expect(res2.headers['content-type']).toContain("application/json")
added_org_id = added_org2.id; });
delete added_org2.id; it('delete', async () => {
delete added_org2.teams; const res2 = await axios.delete(base + '/api/organisations/' + added_org_id + '?force=true', axios_config);
expect(added_org2).toEqual({ expect(res2.status).toEqual(200);
"name": "test123", expect(res2.headers['content-type']).toContain("application/json")
"contact": null, let added_org2 = res2.data
"address": null added_org_id = added_org2.id;
}); delete added_org2.id;
}); delete added_org2.teams;
it('check if org really was deleted', async () => { expect(added_org2).toEqual({
const res3 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); "name": "test123",
expect(res3.status).toEqual(404); "contact": null,
expect(res3.headers['content-type']).toContain("application/json") "address": {
}); "address1": null,
"address2": null,
"city": null,
"country": null,
"postalcode": null,
},
});
});
it('check if org really was deleted', async () => {
const res3 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config);
expect(res3.status).toEqual(404);
expect(res3.headers['content-type']).toContain("application/json")
});
}); });

View File

@ -1,73 +1,383 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
// --------------- // ---------------
describe('adding + updating name', () => { describe('adding + updating name', () => {
let added_org_id let added_org_id
let added_org let added_org
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res.data
added_org_id = added_org.id; added_org_id = added_org.id;
expect(res1.status).toEqual(200); expect(res.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
}); });
it('update org', async () => { it('update org', async () => {
const res2 = await axios.put(base + '/api/organisations/' + added_org_id, { const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id, "id": added_org_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
"address": null, "address": null,
}, axios_config); }, axios_config);
expect(res2.status).toEqual(200); expect(res.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res.headers['content-type']).toContain("application/json")
let added_org2 = res2.data let added_org2 = res.data
added_org_id = added_org2.id; added_org_id = added_org2.id;
delete added_org2.id delete added_org2.id
expect(added_org2).toEqual({ expect(added_org2).toEqual({
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
"address": null, "address": {
"teams": [] "address1": null,
}) "address2": null,
}); "city": null,
}); "country": null,
// --------------- "postalcode": null,
describe('adding + try updating id (should return 406)', () => { },
let added_org_id "teams": []
let added_org })
it('creating a new org with just a name should return 200', async () => { });
const res1 = await axios.post(base + '/api/organisations', { });
"name": "test123" // ---------------
}, axios_config); describe('adding + try updating id (should return 406)', () => {
added_org = res1.data let added_org_id
added_org_id = added_org.id; let added_org
expect(res1.status).toEqual(200); it('creating a new org with just a name should return 200', async () => {
expect(res1.headers['content-type']).toContain("application/json") const res = await axios.post(base + '/api/organisations', {
}); "name": "test123"
it('update org', async () => { }, axios_config);
const res2 = await axios.put(base + '/api/organisations/' + added_org_id, { added_org = res.data
"id": added_org_id + 1, added_org_id = added_org.id;
"name": "testlelele", expect(res.status).toEqual(200);
"contact": null, expect(res.headers['content-type']).toContain("application/json")
"address": null, });
}, axios_config); it('update org', async () => {
expect(res2.status).toEqual(406); const res = await axios.put(base + '/api/organisations/' + added_org_id, {
expect(res2.headers['content-type']).toContain("application/json") "id": added_org_id + 1,
}); "name": "testlelele",
"contact": null,
"address": null,
}, axios_config);
expect(res.status).toEqual(406);
expect(res.headers['content-type']).toContain("application/json")
});
});
// ---------------
describe('adding + updateing address valid)', () => {
let added_org_id
let added_org
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
added_org = res.data
added_org_id = added_org.id;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('adding address to org should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test1",
"address2": null,
"city": "Herzogenaurach",
"country": "Burkina Faso",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test1",
"address2": null,
"city": "Herzogenaurach",
"country": "Burkina Faso",
"postalcode": "90174"
},
"teams": []
});
});
it('updateing address\'s first line should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": null,
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": null,
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": "90174"
},
"teams": []
});
});
it('updateing address\'s second line should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": "90174"
},
"teams": []
});
});
it('updateing address\'s city should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "Kaya",
"country": "Burkina Faso",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "Kaya",
"country": "Burkina Faso",
"postalcode": "90174"
},
"teams": []
});
});
it('updateing address\'s country should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "Kaya",
"country": "Germany",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "Kaya",
"country": "Germany",
"postalcode": "90174"
},
"teams": []
});
});
it('updateing address\'s postal code should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "Kaya",
"country": "Germany",
"postalcode": "91065"
}
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test2",
"address2": "Test3",
"city": "Kaya",
"country": "Germany",
"postalcode": "91065"
},
"teams": []
});
});
it('removing org\'s should return 200', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null
}, axios_config);
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json");
expect(res.data).toEqual({
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": null,
"address2": null,
"city": null,
"country": null,
"postalcode": null
},
"teams": []
});
});
});
// ---------------
describe('adding + updateing address invalid)', () => {
let added_org_id
let added_org
it('creating a new org with just a name should return 200', async () => {
const res = await axios.post(base + '/api/organisations', {
"name": "test123"
}, axios_config);
added_org = res.data
added_org_id = added_org.id;
expect(res.status).toEqual(200);
expect(res.headers['content-type']).toContain("application/json")
});
it('adding address to org w/o address1 should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": null,
"address2": null,
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('adding address to org w/o city should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test1",
"address2": null,
"city": null,
"country": "Burkina Faso",
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('adding address to org w/o country should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test1",
"address2": null,
"city": "TestCity",
"country": null,
"postalcode": "90174"
}
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('adding address to org w/o postal code should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test1",
"address2": null,
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": null
}
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
it('adding address to org w/ invalid postal code should return 400', async () => {
const res = await axios.put(base + '/api/organisations/' + added_org_id, {
"id": added_org_id,
"name": "testlelele",
"contact": null,
"address": {
"address1": "Test1",
"address2": null,
"city": "TestCity",
"country": "Burkina Faso",
"postalcode": "-1"
}
}, axios_config);
expect(res.status).toEqual(400);
expect(res.headers['content-type']).toContain("application/json");
});
}); });

View File

@ -1,131 +1,130 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
// --------------- // ---------------
describe('adding + updating name', () => { describe('adding + updating name', () => {
let added_org; let added_org;
let added_org_id; let added_org_id;
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
added_org_id = added_org.id; added_org_id = added_org.id;
expect(res1.status).toEqual(200); expect(res1.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('creating a new team with a valid org should return 200', async () => { it('creating a new team with a valid org should return 200', async () => {
const res2 = await axios.post(base + '/api/teams', { const res2 = await axios.post(base + '/api/teams', {
"name": "test123", "name": "test123",
"parentGroup": added_org_id "parentGroup": added_org_id
}, axios_config); }, axios_config);
added_team = res2.data; added_team = res2.data;
added_team_id = added_team.id; added_team_id = added_team.id;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('update name', async () => { it('update name', async () => {
const res3 = await axios.put(base + '/api/teams/' + added_team_id, { const res3 = await axios.put(base + '/api/teams/' + added_team_id, {
"id": added_team_id, "id": added_team_id,
"name": "testlelele", "name": "testlelele",
"contact": null, "contact": null,
"parentGroup": added_org.id "parentGroup": added_org.id
}, axios_config); }, axios_config);
expect(res3.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
let updated_team = res3.data; let updated_team = res3.data;
added_team.name = "testlelele"; added_team.name = "testlelele";
expect(updated_team).toEqual(added_team) expect(updated_team).toEqual(added_team)
}); });
}); });
// --------------- // ---------------
describe('adding + try updating id (should return 406)', () => { describe('adding + try updating id (should return 406)', () => {
let added_org; let added_org;
let added_org_id; let added_org_id;
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
added_org_id = added_org.id; added_org_id = added_org.id;
expect(res1.status).toEqual(200); expect(res1.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('creating a new team with a valid org should return 200', async () => { it('creating a new team with a valid org should return 200', async () => {
const res2 = await axios.post(base + '/api/teams', { const res2 = await axios.post(base + '/api/teams', {
"name": "test123", "name": "test123",
"parentGroup": added_org_id "parentGroup": added_org_id
}, axios_config); }, axios_config);
added_team = res2.data; added_team = res2.data;
added_team_id = added_team.id; added_team_id = added_team.id;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('update team', async () => { it('update team', async () => {
added_team.id = added_team.id + 1; added_team.id = added_team.id + 1;
added_team.parentGroup = added_team.parentGroup.id; added_team.parentGroup = added_team.parentGroup.id;
const res3 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); const res3 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config);
expect(res3.status).toEqual(406); expect(res3.status).toEqual(406);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });
}); });
// --------------- // ---------------
describe('add+update parent org (valid)', () => { describe('add+update parent org (valid)', () => {
let added_org; let added_org;
let added_org2; let added_org2;
let added_team; let added_team;
let added_team_id let added_team_id
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data; added_org = res1.data;
expect(res1.status).toEqual(200); expect(res1.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('creating a new team with a valid org should return 200', async () => { it('creating a new team with a valid org should return 200', async () => {
const res2 = await axios.post(base + '/api/teams', { const res2 = await axios.post(base + '/api/teams', {
"name": "test123", "name": "test123",
"parentGroup": added_org.id "parentGroup": added_org.id
}, axios_config); }, axios_config);
added_team = res2.data; added_team = res2.data;
added_team_id = added_team.id; added_team_id = added_team.id;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res3 = await axios.post(base + '/api/organisations', { const res3 = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org2 = res3.data; added_org2 = res3.data;
expect(res3.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
}); });
it('update team', async () => { it('update team', async () => {
added_team.parentGroup = added_org2.id; added_team.parentGroup = added_org2.id;
const res4 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); const res4 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config);
let updated_team = res4.data; let updated_team = res4.data;
expect(res4.status).toEqual(200); expect(res4.status).toEqual(200);
expect(res4.headers['content-type']).toContain("application/json") expect(res4.headers['content-type']).toContain("application/json")
delete added_org2.address; delete added_org2.contact;
delete added_org2.contact; delete added_org2.teams;
delete added_org2.teams; expect(updated_team.parentGroup).toEqual(added_org2)
expect(updated_team.parentGroup).toEqual(added_org2) });
});
}); });

View File

@ -1,160 +1,156 @@
import axios from 'axios'; import axios from 'axios';
import { config } from '../../config'; import { config } from '../../config';
const base = "http://localhost:" + config.internal_port const base = "http://localhost:" + config.internal_port
let access_token; let access_token;
let axios_config; let axios_config;
beforeAll(async () => { beforeAll(async () => {
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" }); const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
access_token = res.data["access_token"]; access_token = res.data["access_token"];
axios_config = { axios_config = {
headers: { "authorization": "Bearer " + access_token }, headers: { "authorization": "Bearer " + access_token },
validateStatus: undefined validateStatus: undefined
}; };
}); });
describe('Update runner name after adding', () => { describe('Update runner name after adding', () => {
let added_org; let added_org;
let added_runner; let added_runner;
let updated_runner; let updated_runner;
it('creating a new org with just a name should return 200', async () => { it('creating a new org with just a name should return 200', async () => {
const res1 = await axios.post(base + '/api/organisations', { const res1 = await axios.post(base + '/api/organisations', {
"name": "test123" "name": "test123"
}, axios_config); }, axios_config);
added_org = res1.data added_org = res1.data
expect(res1.status).toEqual(200); expect(res1.status).toEqual(200);
expect(res1.headers['content-type']).toContain("application/json") expect(res1.headers['content-type']).toContain("application/json")
}); });
it('creating a new runner with only needed params should return 200', async () => { it('creating a new runner with only needed params should return 200', async () => {
const res2 = await axios.post(base + '/api/runners', { const res2 = await axios.post(base + '/api/runners', {
"firstname": "first", "firstname": "first",
"lastname": "last", "lastname": "last",
"group": added_org.id "group": added_org.id
}, axios_config); }, axios_config);
added_runner = res2.data; added_runner = res2.data;
expect(res2.status).toEqual(200); expect(res2.status).toEqual(200);
expect(res2.headers['content-type']).toContain("application/json") expect(res2.headers['content-type']).toContain("application/json")
}); });
it('valid update should return 200', async () => { it('valid update should return 200', async () => {
let runnercopy = added_runner let runnercopy = added_runner
runnercopy.firstname = "second" runnercopy.firstname = "second"
runnercopy.group = added_runner.group.id; runnercopy.group = added_runner.group.id;
const res3 = await axios.put(base + '/api/runners/' + added_runner.id, runnercopy, axios_config); const res3 = await axios.put(base + '/api/runners/' + added_runner.id, runnercopy, axios_config);
expect(res3.status).toEqual(200); expect(res3.status).toEqual(200);
expect(res3.headers['content-type']).toContain("application/json") expect(res3.headers['content-type']).toContain("application/json")
updated_runner = res3.data; updated_runner = res3.data;
delete added_org.address; delete added_org.contact;
delete added_org.contact; delete added_org.teams;
delete added_org.teams; runnercopy.group = added_org;
runnercopy.group = added_org; expect(updated_runner).toEqual(runnercopy);
expect(updated_runner).toEqual(runnercopy); });
}); });
}); // ---------------
// --------------- describe('Update runner group after adding', () => {
describe('Update runner group after adding', () => { let added_org_id;
let added_org_id; let added_org_2;
let added_org_2; let added_runner;
let added_runner; it('creating a new org with just a name should return 200', async () => {
let updated_runner; const res1 = await axios.post(base + '/api/organisations', {
it('creating a new org with just a name should return 200', async () => { "name": "test123"
const res1 = await axios.post(base + '/api/organisations', { }, axios_config);
"name": "test123" let added_org = res1.data
}, axios_config); added_org_id = added_org.id;
let added_org = res1.data expect(res1.status).toEqual(200);
added_org_id = added_org.id; expect(res1.headers['content-type']).toContain("application/json")
expect(res1.status).toEqual(200); });
expect(res1.headers['content-type']).toContain("application/json") it('creating a new runner with only needed params should return 200', async () => {
}); const res2 = await axios.post(base + '/api/runners', {
it('creating a new runner with only needed params should return 200', async () => { "firstname": "first",
const res2 = await axios.post(base + '/api/runners', { "lastname": "last",
"firstname": "first", "group": added_org_id
"lastname": "last", }, axios_config);
"group": added_org_id added_runner = res2.data;
}, axios_config); expect(res2.status).toEqual(200);
added_runner = res2.data; expect(res2.headers['content-type']).toContain("application/json")
expect(res2.status).toEqual(200); });
expect(res2.headers['content-type']).toContain("application/json") it('creating a new org with just a name should return 200', async () => {
}); const res3 = await axios.post(base + '/api/organisations', {
it('creating a new org with just a name should return 200', async () => { "name": "test123"
const res3 = await axios.post(base + '/api/organisations', { }, axios_config);
"name": "test123" added_org_2 = res3.data
}, axios_config); delete added_org_2.contact;
added_org_2 = res3.data delete added_org_2.teams;
delete added_org_2.address; expect(res3.status).toEqual(200);
delete added_org_2.contact; expect(res3.headers['content-type']).toContain("application/json")
delete added_org_2.teams; });
expect(res3.status).toEqual(200); it('valid group update should return 200', async () => {
expect(res3.headers['content-type']).toContain("application/json") added_runner.group = added_org_2.id;
}); const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config);
it('valid group update should return 200', async () => { expect(res3.status).toEqual(200);
added_runner.group = added_org_2.id; expect(res3.headers['content-type']).toContain("application/json")
const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config); expect(res3.data.group).toEqual(added_org_2);
expect(res3.status).toEqual(200); });
expect(res3.headers['content-type']).toContain("application/json") });
updated_runner = res3.data // ---------------
expect(updated_runner.group).toEqual(added_org_2); describe('Update runner id after adding(should fail)', () => {
}); let added_org_id;
}); let added_runner;
// --------------- let added_runner_id;
describe('Update runner id after adding(should fail)', () => { it('creating a new org with just a name should return 200', async () => {
let added_org_id; const res1 = await axios.post(base + '/api/organisations', {
let added_runner; "name": "test123"
let added_runner_id; }, axios_config);
it('creating a new org with just a name should return 200', async () => { let added_org = res1.data
const res1 = await axios.post(base + '/api/organisations', { added_org_id = added_org.id;
"name": "test123" expect(res1.status).toEqual(200);
}, axios_config); expect(res1.headers['content-type']).toContain("application/json")
let added_org = res1.data });
added_org_id = added_org.id; it('creating a new runner with only needed params should return 200', async () => {
expect(res1.status).toEqual(200); const res2 = await axios.post(base + '/api/runners', {
expect(res1.headers['content-type']).toContain("application/json") "firstname": "first",
}); "lastname": "last",
it('creating a new runner with only needed params should return 200', async () => { "group": added_org_id
const res2 = await axios.post(base + '/api/runners', { }, axios_config);
"firstname": "first", added_runner = res2.data;
"lastname": "last", added_runner_id = added_runner.id;
"group": added_org_id expect(res2.status).toEqual(200);
}, axios_config); expect(res2.headers['content-type']).toContain("application/json")
added_runner = res2.data; });
added_runner_id = added_runner.id; it('invalid update should return 406', async () => {
expect(res2.status).toEqual(200); added_runner.id++;
expect(res2.headers['content-type']).toContain("application/json") added_runner.group = added_runner.group.id;
}); const res3 = await axios.put(base + '/api/runners/' + added_runner_id, added_runner, axios_config);
it('invalid update should return 406', async () => { expect(res3.status).toEqual(406);
added_runner.id++; expect(res3.headers['content-type']).toContain("application/json")
added_runner.group = added_runner.group.id; });
const res3 = await axios.put(base + '/api/runners/' + added_runner_id, added_runner, axios_config); });
expect(res3.status).toEqual(406); // ---------------
expect(res3.headers['content-type']).toContain("application/json") describe('Update runner group with invalid group after adding', () => {
}); let added_org;
}); let added_runner;
// --------------- it('creating a new org with just a name should return 200', async () => {
describe('Update runner group with invalid group after adding', () => { const res1 = await axios.post(base + '/api/organisations', {
let added_org; "name": "test123"
let added_runner; }, axios_config);
it('creating a new org with just a name should return 200', async () => { added_org = res1.data
const res1 = await axios.post(base + '/api/organisations', { expect(res1.status).toEqual(200);
"name": "test123" expect(res1.headers['content-type']).toContain("application/json")
}, axios_config); });
added_org = res1.data it('creating a new runner with only needed params should return 200', async () => {
expect(res1.status).toEqual(200); const res2 = await axios.post(base + '/api/runners', {
expect(res1.headers['content-type']).toContain("application/json") "firstname": "first",
}); "lastname": "last",
it('creating a new runner with only needed params should return 200', async () => { "group": added_org.id
const res2 = await axios.post(base + '/api/runners', { }, axios_config);
"firstname": "first", added_runner = res2.data;
"lastname": "last", expect(res2.status).toEqual(200);
"group": added_org.id expect(res2.headers['content-type']).toContain("application/json")
}, axios_config); });
added_runner = res2.data; it('invalid group update should return 404', async () => {
expect(res2.status).toEqual(200); added_runner.group = 99999999999999999;
expect(res2.headers['content-type']).toContain("application/json") const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config);
}); expect(res3.status).toEqual(404);
it('invalid group update should return 404', async () => { expect(res3.headers['content-type']).toContain("application/json")
added_runner.group = 99999999999999999; });
const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config);
expect(res3.status).toEqual(404);
expect(res3.headers['content-type']).toContain("application/json")
});
}); });