diff --git a/.env.ci b/.env.ci index 00bfa4a..389c0fa 100644 --- a/.env.ci +++ b/.env.ci @@ -6,4 +6,4 @@ DB_USER=unused DB_PASSWORD=bla DB_NAME=./test.sqlite NODE_ENV=dev -POSTALCODE_COUNTRYCODE=null \ No newline at end of file +POSTALCODE_COUNTRYCODE=DE \ No newline at end of file diff --git a/.env.example b/.env.example index 5595533..076d8cd 100644 --- a/.env.example +++ b/.env.example @@ -6,4 +6,4 @@ DB_USER=bla DB_PASSWORD=bla DB_NAME=bla NODE_ENV=production -POSTALCODE_COUNTRYCODE=null \ No newline at end of file +POSTALCODE_COUNTRYCODE=DE \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e824ec5..99d01f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,67 @@ 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) +> 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) - 🧾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) @@ -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) - 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] [`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) +- 🧾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) - 🧾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 optional param to being optional [`a334adf`](https://git.odit.services/lfk/backend/commit/a334adffc6d07c8ab340263123e00a96f21acecb) diff --git a/package.json b/package.json index 20b9711..718d8d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@odit/lfk-backend", - "version": "0.1.1", + "version": "0.2.0", "main": "src/app.ts", "repository": "https://git.odit.services/lfk/backend", "author": { diff --git a/src/controllers/GroupContactController.ts b/src/controllers/GroupContactController.ts new file mode 100644 index 0000000..3d6f83e --- /dev/null +++ b/src/controllers/GroupContactController.ts @@ -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; + + /** + * 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.
This includes the contact\'s associated groups.' }) + async getAll() { + let responseContacts: ResponseGroupContact[] = new Array(); + 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.
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.
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.
If no contact with this id exists it will just return 204(no content).
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(); + } +} diff --git a/src/controllers/RunnerOrganisationController.ts b/src/controllers/RunnerOrganisationController.ts index 15c12ff..4d985e4 100644 --- a/src/controllers/RunnerOrganisationController.ts +++ b/src/controllers/RunnerOrganisationController.ts @@ -29,7 +29,7 @@ export class RunnerOrganisationController { @OpenAPI({ description: 'Lists all organisations.
This includes their address, contact and teams (if existing/associated).' }) async getAll() { let responseTeams: ResponseRunnerOrganisation[] = new Array(); - const runners = await this.runnerOrganisationRepository.find({ relations: ['address', 'contact', 'teams'] }); + const runners = await this.runnerOrganisationRepository.find({ relations: ['contact', 'teams'] }); runners.forEach(runner => { responseTeams.push(new ResponseRunnerOrganisation(runner)); }); @@ -43,7 +43,7 @@ export class RunnerOrganisationController { @OnUndefined(RunnerOrganisationNotFoundError) @OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' }) 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(); } return new ResponseRunnerOrganisation(runnerOrg); } @@ -62,7 +62,7 @@ export class RunnerOrganisationController { 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') @@ -84,7 +84,7 @@ export class RunnerOrganisationController { 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') @@ -94,11 +94,11 @@ export class RunnerOrganisationController { @ResponseSchema(RunnerOrganisationHasTeamsError, { statusCode: 406 }) @ResponseSchema(RunnerOrganisationHasRunnersError, { statusCode: 406 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete the organsisation whose id you provided.
If the organisation still has runners and/or teams associated this will fail.
To delete the organisation with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while).
If no organisation with this id exists it will just return 204(no content).' }) + @OpenAPI({ description: 'Delete the organsisation whose id you provided.
If the organisation still has runners and/or teams associated this will fail.
To delete the organisation with all associated runners and teams set the force QueryParam to true (cascading deletion might take a while).
This won\'t delete the associated contact.
If no organisation with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let organisation = await this.runnerOrganisationRepository.findOne({ id: id }); 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 (runnerOrganisation.teams.length != 0) { diff --git a/src/controllers/RunnerTeamController.ts b/src/controllers/RunnerTeamController.ts index 5b97f2b..ce706ec 100644 --- a/src/controllers/RunnerTeamController.ts +++ b/src/controllers/RunnerTeamController.ts @@ -93,7 +93,7 @@ export class RunnerTeamController { @ResponseSchema(ResponseEmpty, { statusCode: 204 }) @ResponseSchema(RunnerTeamHasRunnersError, { statusCode: 406 }) @OnUndefined(204) - @OpenAPI({ description: 'Delete the team whose id you provided.
If the team still has runners associated this will fail.
To delete the team with all associated runners set the force QueryParam to true (cascading deletion might take a while).
If no team with this id exists it will just return 204(no content).' }) + @OpenAPI({ description: 'Delete the team whose id you provided.
If the team still has runners associated this will fail.
To delete the team with all associated runners set the force QueryParam to true (cascading deletion might take a while).
This won\'t delete the associated contact.
If no team with this id exists it will just return 204(no content).' }) async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { let team = await this.runnerTeamRepository.findOne({ id: id }); if (!team) { return null; } diff --git a/src/errors/AddressErrors.ts b/src/errors/AddressErrors.ts index ec68d67..300bb31 100644 --- a/src/errors/AddressErrors.ts +++ b/src/errors/AddressErrors.ts @@ -1,24 +1,57 @@ -import { IsString } from 'class-validator'; -import { NotAcceptableError, NotFoundError } from 'routing-controllers'; - -/** - * Error to throw, when to provided address doesn't belong to the accepted types. - */ -export class AddressWrongTypeError extends NotAcceptableError { - @IsString() - name = "AddressWrongTypeError" - - @IsString() - message = "The address must be an existing address's id. \n You provided a object of another type." -} - -/** - * Error to throw, when a non-existent address get's loaded. - */ -export class AddressNotFoundError extends NotFoundError { - @IsString() - name = "AddressNotFoundError" - - @IsString() - message = "The address you provided couldn't be located in the system. \n Please check your request." +import { IsString } from 'class-validator'; +import { BadRequestError } from 'routing-controllers'; + +/** + * Error to throw when an address's postal code fails validation. + */ +export class AddressPostalCodeInvalidError extends BadRequestError { + @IsString() + name = "AddressPostalCodeInvalidError" + + @IsString() + 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 an non-empty address's first line isn't set. + */ +export class AddressFirstLineEmptyError extends BadRequestError { + @IsString() + name = "AddressFirstLineEmptyError" + + @IsString() + 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" } \ No newline at end of file diff --git a/src/errors/GroupContactErrors.ts b/src/errors/GroupContactErrors.ts index 92fd4a2..fffbdd5 100644 --- a/src/errors/GroupContactErrors.ts +++ b/src/errors/GroupContactErrors.ts @@ -2,18 +2,7 @@ import { IsString } from 'class-validator'; import { NotAcceptableError, NotFoundError } from 'routing-controllers'; /** - * Error to throw, when a provided groupContact doesn't belong to the accepted types. - */ -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. + * Error to throw, when a non-existent contact get's requested. */ export class GroupContactNotFoundError extends NotFoundError { @IsString() @@ -21,4 +10,16 @@ export class GroupContactNotFoundError extends NotFoundError { @IsString() message = "The groupContact you provided couldn't be located in the system. \n Please check your request." -} \ No newline at end of file +} + +/** + * 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!" +} diff --git a/src/models/actions/create/CreateAddress.ts b/src/models/actions/create/CreateAddress.ts deleted file mode 100644 index 77ce4a8..0000000 --- a/src/models/actions/create/CreateAddress.ts +++ /dev/null @@ -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
{ - 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; - } -} \ No newline at end of file diff --git a/src/models/actions/create/CreateDonor.ts b/src/models/actions/create/CreateDonor.ts index a207983..397a8d7 100644 --- a/src/models/actions/create/CreateDonor.ts +++ b/src/models/actions/create/CreateDonor.ts @@ -1,38 +1,39 @@ -import { IsBoolean, IsOptional } from 'class-validator'; -import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; -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). - */ -export class CreateDonor extends CreateParticipant { - - /** - * Does this donor need a receipt? - */ - @IsBoolean() - @IsOptional() - receiptNeeded?: boolean = false; - - /** - * Creates a new Donor entity from this. - */ - public async toEntity(): Promise { - let newDonor: Donor = new Donor(); - - newDonor.firstname = this.firstname; - newDonor.middlename = this.middlename; - newDonor.lastname = this.lastname; - newDonor.phone = this.phone; - newDonor.email = this.email; - newDonor.address = await this.getAddress(); - newDonor.receiptNeeded = this.receiptNeeded; - - if (this.receiptNeeded == true && this.address == null) { - throw new DonorReceiptAddressNeededError() - } - - return newDonor; - } +import { IsBoolean, IsOptional } from 'class-validator'; +import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; +import { Address } from '../../entities/Address'; +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). + */ +export class CreateDonor extends CreateParticipant { + + /** + * Does this donor need a receipt? + */ + @IsBoolean() + @IsOptional() + receiptNeeded?: boolean = false; + + /** + * Creates a new Donor entity from this. + */ + public async toEntity(): Promise { + let newDonor: Donor = new Donor(); + + newDonor.firstname = this.firstname; + newDonor.middlename = this.middlename; + newDonor.lastname = this.lastname; + newDonor.phone = this.phone; + newDonor.email = this.email; + newDonor.receiptNeeded = this.receiptNeeded; + newDonor.address = this.address; + Address.validate(newDonor.address); + if (this.receiptNeeded == true && Address.isValidAddress(newDonor.address) == false) { + throw new DonorReceiptAddressNeededError() + } + + return newDonor; + } } \ No newline at end of file diff --git a/src/models/actions/create/CreateGroupContact.ts b/src/models/actions/create/CreateGroupContact.ts index 2a52341..0775b2d 100644 --- a/src/models/actions/create/CreateGroupContact.ts +++ b/src/models/actions/create/CreateGroupContact.ts @@ -1,78 +1,97 @@ -import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { config } from '../../../config'; -import { AddressNotFoundError } from '../../../errors/AddressErrors'; -import { Address } from '../../entities/Address'; -import { GroupContact } from '../../entities/GroupContact'; - -/** - * This classed is used to create a new Group entity from a json body (post request). - */ -export class CreateGroupContact { - /** - * The new contact's first name. - */ - @IsNotEmpty() - @IsString() - firstname: string; - - /** - * The new contact's middle name. - */ - @IsOptional() - @IsString() - middlename?: string; - - /** - * The new contact's last name. - */ - @IsNotEmpty() - @IsString() - lastname: string; - - /** - * The new contact's address's id. - */ - @IsInt() - @IsOptional() - address?: number; - - /** - * The 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 contact's email address. - */ - @IsOptional() - @IsEmail() - email?: string; - - /** - * Gets the new contact's address by it's id. - */ - public async getAddress(): Promise
{ - if (!this.address) { return null; } - let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); - if (!address) { throw new AddressNotFoundError; } - return address; - } - - /** - * Creates a new Address entity from this. - */ - public async toEntity(): Promise { - let contact: GroupContact = new GroupContact(); - contact.firstname = this.firstname; - contact.middlename = this.middlename; - contact.lastname = this.lastname; - contact.email = this.email; - contact.phone = this.phone; - contact.address = await this.getAddress(); - return null; - } +import { IsEmail, 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 classed is used to create a new GroupContact entity from a json body (post request). + */ +export class CreateGroupContact { + /** + * The new contact's first name. + */ + @IsNotEmpty() + @IsString() + firstname: string; + + /** + * The new contact's middle name. + */ + @IsOptional() + @IsString() + middlename?: string; + + /** + * The new contact's last name. + */ + @IsNotEmpty() + @IsString() + lastname: string; + + /** + * The new contact's address. + */ + @IsOptional() + @IsObject() + address?: Address; + + /** + * The 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 new contact's email address. + */ + @IsOptional() + @IsEmail() + email?: string; + + /** + * The new 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 { + if (!this.groups) { return null; } + let groups = new Array(); + 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; + } + + /** + * Creates a new GroupContact entity from this. + */ + public async toEntity(): Promise { + 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; + } } \ No newline at end of file diff --git a/src/models/actions/create/CreateParticipant.ts b/src/models/actions/create/CreateParticipant.ts index 753822c..8e008e7 100644 --- a/src/models/actions/create/CreateParticipant.ts +++ b/src/models/actions/create/CreateParticipant.ts @@ -1,65 +1,53 @@ -import { IsEmail, IsInt, IsNotEmpty, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { config } from '../../../config'; -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). - */ -export abstract class CreateParticipant { - /** - * The new participant's first name. - */ - @IsString() - @IsNotEmpty() - firstname: string; - - /** - * The new participant's middle name. - */ - @IsString() - @IsOptional() - middlename?: string; - - /** - * The new participant's last name. - */ - @IsString() - @IsNotEmpty() - lastname: string; - - /** - * The new participant's phone number. - * This will be validated against the configured country phone numer syntax (default: international). - */ - @IsString() - @IsOptional() - @IsPhoneNumber(config.phone_validation_countrycode) - phone?: string; - - /** - * The new participant's e-mail address. - */ - @IsString() - @IsOptional() - @IsEmail() - email?: string; - - /** - * The new participant's address's id. - */ - @IsInt() - @IsOptional() - address?: number; - - /** - * Gets the new participant's address by it's id. - */ - public async getAddress(): Promise
{ - if (!this.address) { return null; } - let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); - if (!address) { throw new AddressNotFoundError; } - return address; - } +import { IsEmail, IsNotEmpty, IsObject, IsOptional, IsPhoneNumber, IsString } from 'class-validator'; +import { config } from '../../../config'; +import { Address } from '../../entities/Address'; + +/** + * This classed is used to create a new Participant entity from a json body (post request). + */ +export abstract class CreateParticipant { + /** + * The new participant's first name. + */ + @IsString() + @IsNotEmpty() + firstname: string; + + /** + * The new participant's middle name. + */ + @IsString() + @IsOptional() + middlename?: string; + + /** + * The new participant's last name. + */ + @IsString() + @IsNotEmpty() + lastname: string; + + /** + * The new participant's phone number. + * This will be validated against the configured country phone numer syntax (default: international). + */ + @IsString() + @IsOptional() + @IsPhoneNumber(config.phone_validation_countrycode) + phone?: string; + + /** + * The new participant's e-mail address. + */ + @IsString() + @IsOptional() + @IsEmail() + email?: string; + + /** + * The new participant's address. + */ + @IsOptional() + @IsObject() + address?: Address; } \ No newline at end of file diff --git a/src/models/actions/create/CreateRunner.ts b/src/models/actions/create/CreateRunner.ts index addfee2..9916ba8 100644 --- a/src/models/actions/create/CreateRunner.ts +++ b/src/models/actions/create/CreateRunner.ts @@ -1,53 +1,55 @@ -import { IsInt } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; -import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; -import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; -import { Runner } from '../../entities/Runner'; -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). - */ -export class CreateRunner extends CreateParticipant { - - /** - * The new runner's group's id. - */ - @IsInt() - group: number; - - /** - * Creates a new Runner entity from this. - */ - public async toEntity(): Promise { - let newRunner: Runner = new Runner(); - - newRunner.firstname = this.firstname; - newRunner.middlename = this.middlename; - newRunner.lastname = this.lastname; - newRunner.phone = this.phone; - newRunner.email = this.email; - newRunner.group = await this.getGroup(); - newRunner.address = await this.getAddress(); - - return newRunner; - } - - /** - * Gets the new runner's group by it's id. - */ - public async getGroup(): Promise { - if (this.group === undefined || this.group === null) { - throw new RunnerTeamNeedsParentError(); - } - if (!isNaN(this.group)) { - let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group }); - if (!group) { throw new RunnerGroupNotFoundError; } - return group; - } - - throw new RunnerOrganisationWrongTypeError; - } +import { IsInt } from 'class-validator'; +import { getConnectionManager } from 'typeorm'; +import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; +import { RunnerOrganisationWrongTypeError } from '../../../errors/RunnerOrganisationErrors'; +import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; +import { Address } from '../../entities/Address'; +import { Runner } from '../../entities/Runner'; +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). + */ +export class CreateRunner extends CreateParticipant { + + /** + * The new runner's group's id. + */ + @IsInt() + group: number; + + /** + * Creates a new Runner entity from this. + */ + public async toEntity(): Promise { + let newRunner: Runner = new Runner(); + + newRunner.firstname = this.firstname; + newRunner.middlename = this.middlename; + newRunner.lastname = this.lastname; + newRunner.phone = this.phone; + newRunner.email = this.email; + newRunner.group = await this.getGroup(); + newRunner.address = this.address; + Address.validate(newRunner.address); + + return newRunner; + } + + /** + * Gets the new runner's group by it's id. + */ + public async getGroup(): Promise { + if (this.group === undefined || this.group === null) { + throw new RunnerTeamNeedsParentError(); + } + if (!isNaN(this.group)) { + let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group }); + if (!group) { throw new RunnerGroupNotFoundError; } + return group; + } + + throw new RunnerOrganisationWrongTypeError; + } } \ No newline at end of file diff --git a/src/models/actions/create/CreateRunnerOrganisation.ts b/src/models/actions/create/CreateRunnerOrganisation.ts index f1e6369..e99d851 100644 --- a/src/models/actions/create/CreateRunnerOrganisation.ts +++ b/src/models/actions/create/CreateRunnerOrganisation.ts @@ -1,41 +1,30 @@ -import { IsInt, IsOptional } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { AddressNotFoundError } from '../../../errors/AddressErrors'; -import { Address } from '../../entities/Address'; -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). - */ -export class CreateRunnerOrganisation extends CreateRunnerGroup { - /** - * The new organisation's address's id. - */ - @IsInt() - @IsOptional() - address?: number; - - /** - * Gets the org's address by it's id. - */ - public async getAddress(): Promise
{ - if (!this.address) { return null; } - let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); - if (!address) { throw new AddressNotFoundError; } - return address; - } - - /** - * Creates a new RunnerOrganisation entity from this. - */ - public async toEntity(): Promise { - let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation(); - - newRunnerOrganisation.name = this.name; - newRunnerOrganisation.contact = await this.getContact(); - newRunnerOrganisation.address = await this.getAddress(); - - return newRunnerOrganisation; - } +import { IsObject, IsOptional } from 'class-validator'; +import { Address } from '../../entities/Address'; +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). + */ +export class CreateRunnerOrganisation extends CreateRunnerGroup { + /** + * The new organisation's address. + */ + @IsOptional() + @IsObject() + address?: Address; + + /** + * Creates a new RunnerOrganisation entity from this. + */ + public async toEntity(): Promise { + let newRunnerOrganisation: RunnerOrganisation = new RunnerOrganisation(); + + newRunnerOrganisation.name = this.name; + newRunnerOrganisation.contact = await this.getContact(); + newRunnerOrganisation.address = this.address; + Address.validate(newRunnerOrganisation.address); + + return newRunnerOrganisation; + } } \ No newline at end of file diff --git a/src/models/actions/update/UpdateDonor.ts b/src/models/actions/update/UpdateDonor.ts index 0e35bcf..7b6fcfa 100644 --- a/src/models/actions/update/UpdateDonor.ts +++ b/src/models/actions/update/UpdateDonor.ts @@ -1,44 +1,46 @@ -import { IsBoolean, IsInt, IsOptional } from 'class-validator'; -import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; -import { Donor } from '../../entities/Donor'; -import { CreateParticipant } from '../create/CreateParticipant'; - -/** - * This class is used to update a Donor entity (via put request). - */ -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). - */ - @IsInt() - id: number; - - /** - * Does the updated donor need a receipt? - */ - @IsBoolean() - @IsOptional() - receiptNeeded?: boolean; - - - /** - * Updates a provided Donor entity based on this. - */ - public async update(donor: Donor): Promise { - donor.firstname = this.firstname; - donor.middlename = this.middlename; - donor.lastname = this.lastname; - donor.phone = this.phone; - donor.email = this.email; - donor.receiptNeeded = this.receiptNeeded; - donor.address = await this.getAddress(); - - if (this.receiptNeeded == true && this.address == null) { - throw new DonorReceiptAddressNeededError() - } - - return donor; - } +import { IsBoolean, IsInt, IsOptional } from 'class-validator'; +import { DonorReceiptAddressNeededError } from '../../../errors/DonorErrors'; +import { Address } from '../../entities/Address'; +import { Donor } from '../../entities/Donor'; +import { CreateParticipant } from '../create/CreateParticipant'; + +/** + * This class is used to update a Donor entity (via put request). + */ +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). + */ + @IsInt() + id: number; + + /** + * Does the updated donor need a receipt? + */ + @IsBoolean() + @IsOptional() + receiptNeeded?: boolean; + + + /** + * Updates a provided Donor entity based on this. + */ + public async update(donor: Donor): Promise { + donor.firstname = this.firstname; + donor.middlename = this.middlename; + donor.lastname = this.lastname; + donor.phone = this.phone; + donor.email = this.email; + donor.receiptNeeded = this.receiptNeeded; + if (!this.address) { donor.address.reset(); } + else { donor.address = this.address; } + Address.validate(donor.address); + if (this.receiptNeeded == true && Address.isValidAddress(donor.address) == false) { + throw new DonorReceiptAddressNeededError() + } + + return donor; + } } \ No newline at end of file diff --git a/src/models/actions/update/UpdateGroupContact.ts b/src/models/actions/update/UpdateGroupContact.ts new file mode 100644 index 0000000..72f919a --- /dev/null +++ b/src/models/actions/update/UpdateGroupContact.ts @@ -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 { + if (!this.groups) { return null; } + let groups = new Array(); + 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 { + 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; + } +} \ No newline at end of file diff --git a/src/models/actions/update/UpdateRunner.ts b/src/models/actions/update/UpdateRunner.ts index df98021..2df10fe 100644 --- a/src/models/actions/update/UpdateRunner.ts +++ b/src/models/actions/update/UpdateRunner.ts @@ -1,54 +1,57 @@ -import { IsInt, IsPositive } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; -import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; -import { Runner } from '../../entities/Runner'; -import { RunnerGroup } from '../../entities/RunnerGroup'; -import { CreateParticipant } from '../create/CreateParticipant'; - -/** - * This class is used to update a Runner entity (via put request). - */ -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). - */ - @IsInt() - id: number; - - /** - * The updated runner's group's id. - */ - @IsInt() - @IsPositive() - group: number; - - /** - * Updates a provided Runner entity based on this. - */ - public async update(runner: Runner): Promise { - runner.firstname = this.firstname; - runner.middlename = this.middlename; - runner.lastname = this.lastname; - runner.phone = this.phone; - runner.email = this.email; - runner.group = await this.getGroup(); - runner.address = await this.getAddress(); - - return runner; - } - - /** - * Loads the updated runner's group based on it's id. - */ - public async getGroup(): Promise { - if (this.group === undefined || this.group === null) { - throw new RunnerTeamNeedsParentError(); - } - let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group }); - if (!group) { throw new RunnerGroupNotFoundError; } - return group; - } +import { IsInt, IsPositive } from 'class-validator'; +import { getConnectionManager } from 'typeorm'; +import { RunnerGroupNotFoundError } from '../../../errors/RunnerGroupErrors'; +import { RunnerTeamNeedsParentError } from '../../../errors/RunnerTeamErrors'; +import { Address } from '../../entities/Address'; +import { Runner } from '../../entities/Runner'; +import { RunnerGroup } from '../../entities/RunnerGroup'; +import { CreateParticipant } from '../create/CreateParticipant'; + +/** + * This class is used to update a Runner entity (via put request). + */ +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). + */ + @IsInt() + id: number; + + /** + * The updated runner's group's id. + */ + @IsInt() + @IsPositive() + group: number; + + /** + * Updates a provided Runner entity based on this. + */ + public async update(runner: Runner): Promise { + runner.firstname = this.firstname; + runner.middlename = this.middlename; + runner.lastname = this.lastname; + runner.phone = this.phone; + runner.email = this.email; + runner.group = await this.getGroup(); + if (!this.address) { runner.address.reset(); } + 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 { + if (this.group === undefined || this.group === null) { + throw new RunnerTeamNeedsParentError(); + } + let group = await getConnectionManager().get().getRepository(RunnerGroup).findOne({ id: this.group }); + if (!group) { throw new RunnerGroupNotFoundError; } + return group; + } } \ No newline at end of file diff --git a/src/models/actions/update/UpdateRunnerOrganisation.ts b/src/models/actions/update/UpdateRunnerOrganisation.ts index 2fde7dc..b34bc8f 100644 --- a/src/models/actions/update/UpdateRunnerOrganisation.ts +++ b/src/models/actions/update/UpdateRunnerOrganisation.ts @@ -1,48 +1,38 @@ -import { IsInt, IsOptional } from 'class-validator'; -import { getConnectionManager } from 'typeorm'; -import { AddressNotFoundError } from '../../../errors/AddressErrors'; -import { Address } from '../../entities/Address'; -import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; -import { CreateRunnerGroup } from '../create/CreateRunnerGroup'; - -/** - * This class is used to update a RunnerOrganisation entity (via put request). - */ -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). - */ - @IsInt() - id: number; - - /** - * The updated organisation's address's id. - */ - @IsInt() - @IsOptional() - address?: number; - - /** - * Loads the organisation's address based on it's id. - */ - public async getAddress(): Promise
{ - if (!this.address) { return null; } - let address = await getConnectionManager().get().getRepository(Address).findOne({ id: this.address }); - if (!address) { throw new AddressNotFoundError; } - return address; - } - - /** - * Updates a provided RunnerOrganisation entity based on this. - */ - public async update(organisation: RunnerOrganisation): Promise { - - organisation.name = this.name; - organisation.contact = await this.getContact(); - organisation.address = await this.getAddress(); - - return organisation; - } +import { IsInt, IsObject, IsOptional } from 'class-validator'; +import { Address } from '../../entities/Address'; +import { RunnerOrganisation } from '../../entities/RunnerOrganisation'; +import { CreateRunnerGroup } from '../create/CreateRunnerGroup'; + +/** + * This class is used to update a RunnerOrganisation entity (via put request). + */ +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). + */ + @IsInt() + id: number; + + /** + * The updated organisation's address. + */ + @IsOptional() + @IsObject() + address?: Address; + + /** + * Updates a provided RunnerOrganisation entity based on this. + */ + public async update(organisation: RunnerOrganisation): Promise { + + organisation.name = this.name; + organisation.contact = await this.getContact(); + if (!this.address) { organisation.address.reset(); } + else { organisation.address = this.address; } + Address.validate(organisation.address); + + return organisation; + } } \ No newline at end of file diff --git a/src/models/entities/Address.ts b/src/models/entities/Address.ts index 3728f43..6526c08 100644 --- a/src/models/entities/Address.ts +++ b/src/models/entities/Address.ts @@ -1,90 +1,86 @@ -import { - IsInt, - IsNotEmpty, - IsOptional, - IsPostalCode, - IsString -} from "class-validator"; -import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; -import { config } from '../../config'; -import { IAddressUser } from './IAddressUser'; - -/** - * Defines the Address entity. - * Implemented this way to prevent any formatting differences. -*/ -@Entity() -export class Address { - /** - * Autogenerated unique id (primary key). - */ - @PrimaryGeneratedColumn() - @IsInt() - id: number; - - /** - * The address's description. - * Optional and mostly for UX. - */ - @Column({ nullable: true }) - @IsString() - @IsOptional() - description?: string; - - /** - * The address's first line. - * Containing the street and house number. - */ - @Column() - @IsString() - @IsNotEmpty() - address1: string; - - /** - * The address's second line. - * Containing optional information. - */ - @Column({ nullable: true }) - @IsString() - @IsOptional() - address2?: string; - - /** - * The address's postal code. - * This will get checked against the postal code syntax for the configured country. - */ - @Column() - @IsString() - @IsNotEmpty() - @IsPostalCode(config.postalcode_validation_countrycode) - postalcode: string; - - /** - * The address's city. - */ - @Column() - @IsString() - @IsNotEmpty() - city: string; - - /** - * The address's country. - */ - @Column() - @IsString() - @IsNotEmpty() - country: string; - - /** - * Used to link the address to participants. - */ - @OneToMany(() => IAddressUser, addressUser => addressUser.address, { nullable: true }) - addressUsers: IAddressUser[]; - - /** - * Turns this entity into it's response class. - */ - public toResponse() { - return new Error("NotImplemented"); - } -} +import { + IsPostalCode, + IsString +} from "class-validator"; +import { Column } from "typeorm"; +import ValidatorJS from 'validator'; +import { config } from '../../config'; +import { AddressCityEmptyError, AddressCountryEmptyError, AddressFirstLineEmptyError, AddressPostalCodeEmptyError, AddressPostalCodeInvalidError } from '../../errors/AddressErrors'; + +/** + * Defines the Address class. + * Implemented this way to prevent any formatting differences. +*/ +export class Address { + /** + * The address's first line. + * Containing the street and house number. + */ + @Column({ nullable: true }) + @IsString() + address1?: string; + + /** + * The address's second line. + * Containing optional information. + */ + @Column({ nullable: true }) + @IsString() + address2?: string; + + /** + * The address's postal code. + * This will get checked against the postal code syntax for the configured country. + */ + @Column({ nullable: true }) + @IsString() + @IsPostalCode(config.postalcode_validation_countrycode) + postalcode: string; + + /** + * The address's city. + */ + @Column({ nullable: true }) + @IsString() + city: string; + + /** + * The address's country. + */ + @Column({ nullable: true }) + @IsString() + country: string; + + public reset() { + this.address1 = null; + this.address2 = null; + this.city = null; + this.country = null; + this.postalcode = null; + } + + /** + * Checks if this is a valid address + */ + public static isValidAddress(address: Address): Boolean { + if (address == null) { return false; } + if (address.address1 == null || address.city == null || address.country == null || address.postalcode == null) { return false; } + if (ValidatorJS.isPostalCode(address.postalcode, config.postalcode_validation_countrycode) == false) { return false; } + return true; + } + + /** + * This function validates addresses. + * This is a workaround for non-existant class validation for embedded entities. + * @param address The address that shall get validated. + */ + public static validate(address: Address) { + if (address == null) { return; } + if (address.address1 == null && address.city == null && address.country == null && address.postalcode == null) { return; } + if (address.address1 == null) { throw new AddressFirstLineEmptyError(); } + if (address.postalcode == null) { throw new AddressPostalCodeEmptyError(); } + 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(); } + } +} diff --git a/src/models/entities/GroupContact.ts b/src/models/entities/GroupContact.ts index f650259..dd6eed1 100644 --- a/src/models/entities/GroupContact.ts +++ b/src/models/entities/GroupContact.ts @@ -7,10 +7,10 @@ import { IsString } from "class-validator"; -import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; +import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { config } from '../../config'; +import { ResponseGroupContact } from '../responses/ResponseGroupContact'; import { Address } from "./Address"; -import { IAddressUser } from './IAddressUser'; 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. */ @Entity() -export class GroupContact implements IAddressUser { +export class GroupContact { /** * Autogenerated unique id (primary key). */ @@ -54,8 +54,7 @@ export class GroupContact implements IAddressUser { * The contact's address. * This is a address object to prevent any formatting differences. */ - @IsOptional() - @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) + @Column(type => Address) address?: Address; /** @@ -85,7 +84,7 @@ export class GroupContact implements IAddressUser { /** * Turns this entity into it's response class. */ - public toResponse() { - return new Error("NotImplemented"); + public toResponse(): ResponseGroupContact { + return new ResponseGroupContact(this); } } \ No newline at end of file diff --git a/src/models/entities/IAddressUser.ts b/src/models/entities/IAddressUser.ts deleted file mode 100644 index f3b5d5a..0000000 --- a/src/models/entities/IAddressUser.ts +++ /dev/null @@ -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(); -} diff --git a/src/models/entities/Participant.ts b/src/models/entities/Participant.ts index fa40a8f..ccf7656 100644 --- a/src/models/entities/Participant.ts +++ b/src/models/entities/Participant.ts @@ -7,11 +7,10 @@ import { IsString } from "class-validator"; -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; +import { Column, Entity, PrimaryGeneratedColumn, TableInheritance } from "typeorm"; import { config } from '../../config'; import { ResponseParticipant } from '../responses/ResponseParticipant'; import { Address } from "./Address"; -import { IAddressUser } from './IAddressUser'; /** * Defines the Participant entity. @@ -19,7 +18,7 @@ import { IAddressUser } from './IAddressUser'; */ @Entity() @TableInheritance({ column: { name: "type", type: "varchar" } }) -export abstract class Participant implements IAddressUser { +export abstract class Participant { /** * Autogenerated unique id (primary key). */ @@ -55,7 +54,7 @@ export abstract class Participant implements IAddressUser { * The participant's address. * This is a address object to prevent any formatting differences. */ - @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) + @Column(type => Address) address?: Address; /** diff --git a/src/models/entities/RunnerOrganisation.ts b/src/models/entities/RunnerOrganisation.ts index 9aabe17..e5f3330 100644 --- a/src/models/entities/RunnerOrganisation.ts +++ b/src/models/entities/RunnerOrganisation.ts @@ -1,65 +1,64 @@ -import { IsInt, IsOptional } from "class-validator"; -import { ChildEntity, ManyToOne, OneToMany } from "typeorm"; -import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation'; -import { Address } from './Address'; -import { IAddressUser } from './IAddressUser'; -import { Runner } from './Runner'; -import { RunnerGroup } from "./RunnerGroup"; -import { RunnerTeam } from "./RunnerTeam"; - -/** - * Defines the RunnerOrganisation entity. - * This usually is a school, club or company. -*/ -@ChildEntity() -export class RunnerOrganisation extends RunnerGroup implements IAddressUser { - - /** - * The organisations's address. - */ - @IsOptional() - @ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) - address?: Address; - - /** - * The organisation's teams. - * Used to link teams to a organisation. - */ - @OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true }) - teams: RunnerTeam[]; - - /** - * Returns all runners associated with this organisation (directly or indirectly via teams). - */ - public get allRunners(): Runner[] { - let returnRunners: Runner[] = new Array(); - returnRunners.push(...this.runners); - for (let team of this.teams) { - returnRunners.push(...team.runners) - } - return returnRunners; - } - - /** - * Returns the total distance ran by this group's runners based on all their valid scans. - */ - @IsInt() - public get distance(): number { - 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. - */ - @IsInt() - public get distanceDonationAmount(): number { - return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0); - } - - /** - * Turns this entity into it's response class. - */ - public toResponse(): ResponseRunnerOrganisation { - return new ResponseRunnerOrganisation(this); - } +import { IsInt, IsOptional } from "class-validator"; +import { ChildEntity, Column, OneToMany } from "typeorm"; +import { ResponseRunnerOrganisation } from '../responses/ResponseRunnerOrganisation'; +import { Address } from './Address'; +import { Runner } from './Runner'; +import { RunnerGroup } from "./RunnerGroup"; +import { RunnerTeam } from "./RunnerTeam"; + +/** + * Defines the RunnerOrganisation entity. + * This usually is a school, club or company. +*/ +@ChildEntity() +export class RunnerOrganisation extends RunnerGroup { + + /** + * The organisations's address. + */ + @IsOptional() + @Column(type => Address) + address?: Address; + + /** + * The organisation's teams. + * Used to link teams to a organisation. + */ + @OneToMany(() => RunnerTeam, team => team.parentGroup, { nullable: true }) + teams: RunnerTeam[]; + + /** + * Returns all runners associated with this organisation (directly or indirectly via teams). + */ + public get allRunners(): Runner[] { + let returnRunners: Runner[] = new Array(); + returnRunners.push(...this.runners); + for (let team of this.teams) { + returnRunners.push(...team.runners) + } + return returnRunners; + } + + /** + * Returns the total distance ran by this group's runners based on all their valid scans. + */ + @IsInt() + public get distance(): number { + 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. + */ + @IsInt() + public get distanceDonationAmount(): number { + return this.allRunners.reduce((sum, current) => sum + current.distanceDonationAmount, 0); + } + + /** + * Turns this entity into it's response class. + */ + public toResponse(): ResponseRunnerOrganisation { + return new ResponseRunnerOrganisation(this); + } } \ No newline at end of file diff --git a/src/models/enums/PermissionTargets.ts b/src/models/enums/PermissionTargets.ts index 86c547d..1dac026 100644 --- a/src/models/enums/PermissionTargets.ts +++ b/src/models/enums/PermissionTargets.ts @@ -14,5 +14,6 @@ export enum PermissionTarget { SCAN = 'SCAN', STATION = 'STATION', CARD = 'CARD', - DONATION = 'DONATION' + DONATION = 'DONATION', + CONTACT = 'CONTACT' } \ No newline at end of file diff --git a/src/models/responses/ResponseGroupContact.ts b/src/models/responses/ResponseGroupContact.ts new file mode 100644 index 0000000..291dde5 --- /dev/null +++ b/src/models/responses/ResponseGroupContact.ts @@ -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(); + for (let group of contact.groups) { + this.groups.push(group.toResponse()); + } + } +} diff --git a/src/models/responses/ResponseParticipant.ts b/src/models/responses/ResponseParticipant.ts index 135a837..93a6918 100644 --- a/src/models/responses/ResponseParticipant.ts +++ b/src/models/responses/ResponseParticipant.ts @@ -1,56 +1,65 @@ -import { IsInt, IsString } from "class-validator"; -import { Participant } from '../entities/Participant'; - -/** - * Defines the participant response. -*/ -export abstract class ResponseParticipant { - /** - * The participant's id. - */ - @IsInt() - id: number; - - /** - * The participant's first name. - */ - @IsString() - firstname: string; - - /** - * The participant's middle name. - */ - @IsString() - middlename?: string; - - /** - * The participant's last name. - */ - @IsString() - lastname: string; - - /** - * The participant's phone number. - */ - @IsString() - phone?: string; - - /** - * The participant's e-mail address. - */ - @IsString() - email?: string; - - /** - * Creates a ResponseParticipant object from a participant. - * @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; - } -} +import { IsInt, IsObject, IsOptional, IsString } from "class-validator"; +import { Address } from '../entities/Address'; +import { Participant } from '../entities/Participant'; + +/** + * Defines the participant response. +*/ +export abstract class ResponseParticipant { + /** + * The participant's id. + */ + @IsInt() + id: number; + + /** + * The participant's first name. + */ + @IsString() + firstname: string; + + /** + * The participant's middle name. + */ + @IsString() + middlename?: string; + + /** + * The participant's last name. + */ + @IsString() + lastname: string; + + /** + * The participant's phone number. + */ + @IsString() + phone?: string; + + /** + * The participant's e-mail address. + */ + @IsString() + email?: string; + + /** + * The participant's address. + */ + @IsOptional() + @IsObject() + address?: Address; + + /** + * Creates a ResponseParticipant object from a participant. + * @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; + } +} diff --git a/src/tests/contacts/contact_add.spec.ts b/src/tests/contacts/contact_add.spec.ts new file mode 100644 index 0000000..0cb5160 --- /dev/null +++ b/src/tests/contacts/contact_add.spec.ts @@ -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); + }); +}); \ No newline at end of file diff --git a/src/tests/contacts/contact_delete.spec.ts b/src/tests/contacts/contact_delete.spec.ts new file mode 100644 index 0000000..f8d8c64 --- /dev/null +++ b/src/tests/contacts/contact_delete.spec.ts @@ -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") + }); +}); \ No newline at end of file diff --git a/src/tests/contacts/contact_get.spec.ts b/src/tests/contacts/contact_get.spec.ts new file mode 100644 index 0000000..31aa895 --- /dev/null +++ b/src/tests/contacts/contact_get.spec.ts @@ -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); + }); +}); \ No newline at end of file diff --git a/src/tests/contacts/contact_update.spec.ts b/src/tests/contacts/contact_update.spec.ts new file mode 100644 index 0000000..e6d733d --- /dev/null +++ b/src/tests/contacts/contact_update.spec.ts @@ -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"); + }); +}); \ No newline at end of file diff --git a/src/tests/donors/donor_add.spec.ts b/src/tests/donors/donor_add.spec.ts index 30d84c9..3226b8c 100644 --- a/src/tests/donors/donor_add.spec.ts +++ b/src/tests/donors/donor_add.spec.ts @@ -1,94 +1,84 @@ -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/donors with errors', () => { - it('creating a new donor without any parameters should return 400', async () => { - const res1 = await axios.post(base + '/api/donors', null, axios_config); - expect(res1.status).toEqual(400); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('creating a new donor without a last name should return 400', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "middlename": "middle" - }, axios_config); - expect(res2.status).toEqual(400); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('creating a new donor with a invalid address should return 404', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "middlename": "middle", - "lastname": "last", - "address": 99999999999999999999999999 - }, axios_config); - expect(res2.status).toEqual(404); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('creating a new donor with a invalid phone number should return 400', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "middlename": "middle", - "lastname": "last", - "phone": "123" - }, axios_config); - 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', { - "firstname": "string", - "middlename": "string", - "lastname": "string", - "phone": null, - "email": "123", - }, axios_config); - expect(res2.status).toEqual(400); - 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", - "middlename": "string", - "lastname": "string", - "receiptNeeded": true - }, axios_config); - expect(res2.status).toEqual(406); - expect(res2.headers['content-type']).toContain("application/json") - }); -}); -// --------------- -describe('POST /api/donors working', () => { - it('creating a new donor with only needed params should return 200', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "lastname": "last" - }, axios_config); - 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 () => { - 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") - }); +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/donors with errors', () => { + it('creating a new donor without any parameters should return 400', async () => { + const res1 = await axios.post(base + '/api/donors', null, axios_config); + expect(res1.status).toEqual(400); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new donor without a last name should return 400', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "middlename": "middle" + }, axios_config); + expect(res2.status).toEqual(400); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('creating a new donor with a invalid phone number should return 400', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "middlename": "middle", + "lastname": "last", + "phone": "123" + }, axios_config); + 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', { + "firstname": "string", + "middlename": "string", + "lastname": "string", + "phone": null, + "email": "123", + }, axios_config); + expect(res2.status).toEqual(400); + 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", + "middlename": "string", + "lastname": "string", + "receiptNeeded": true + }, axios_config); + expect(res2.status).toEqual(406); + expect(res2.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('POST /api/donors working', () => { + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + 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 () => { + 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") + }); }); \ No newline at end of file diff --git a/src/tests/donors/donor_update.spec.ts b/src/tests/donors/donor_update.spec.ts index d77824a..a317adc 100644 --- a/src/tests/donors/donor_update.spec.ts +++ b/src/tests/donors/donor_update.spec.ts @@ -1,75 +1,75 @@ -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 donor name after adding', () => { - let added_donor; - it('creating a new runner with only needed params should return 200', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "lastname": "last" - }, axios_config); - added_donor = res2.data; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('valid update should return 200', async () => { - let donor_copy = added_donor - donor_copy.firstname = "second" - const res3 = await axios.put(base + '/api/donors/' + added_donor.id, donor_copy, axios_config); - expect(res3.status).toEqual(200); - expect(res3.headers['content-type']).toContain("application/json") - let updated_donor = res3.data - expect(updated_donor).toEqual(donor_copy); - }); -}); -// --------------- -describe('Update donor id after adding(should fail)', () => { - let added_donor; - it('creating a new donor with only needed params should return 200', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "lastname": "last" - }, axios_config); - added_donor = res2.data; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('invalid update should return 406', async () => { - added_donor.id++; - const res3 = await axios.put(base + '/api/donors/' + (added_donor.id - 1), added_donor, axios_config); - expect(res3.status).toEqual(406); - expect(res3.headers['content-type']).toContain("application/json") - }); -}); -// --------------- -describe('Update donor without address but receiptNeeded=true should fail', () => { - let added_donor; - it('creating a new donor with only needed params should return 200', async () => { - const res2 = await axios.post(base + '/api/donors', { - "firstname": "first", - "lastname": "last", - }, axios_config); - added_donor = res2.data; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('invalid update should return 406', async () => { - added_donor.receiptNeeded = true; - const res3 = await axios.put(base + '/api/donors/' + added_donor.id, added_donor, axios_config); - expect(res3.status).toEqual(406); - expect(res3.headers['content-type']).toContain("application/json") - }); +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 donor name after adding', () => { + let added_donor; + it('creating a new runner with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('valid update should return 200', async () => { + let donor_copy = added_donor + donor_copy.firstname = "second" + const res3 = await axios.put(base + '/api/donors/' + added_donor.id, donor_copy, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + let updated_donor = res3.data + expect(updated_donor).toEqual(donor_copy); + }); +}); +// --------------- +describe('Update donor id after adding(should fail)', () => { + let added_donor; + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "last" + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('invalid update should return 406', async () => { + added_donor.id++; + const res3 = await axios.put(base + '/api/donors/' + (added_donor.id - 1), added_donor, axios_config); + expect(res3.status).toEqual(406); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('Update donor without address but receiptNeeded=true should fail', () => { + let added_donor; + it('creating a new donor with only needed params should return 200', async () => { + const res2 = await axios.post(base + '/api/donors', { + "firstname": "first", + "lastname": "testtest", + }, axios_config); + added_donor = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('invalid update should return 406', async () => { + added_donor.receiptNeeded = true; + const res3 = await axios.put(base + '/api/donors/' + added_donor.id, added_donor, axios_config); + expect(res3.status).toEqual(406); + expect(res3.headers['content-type']).toContain("application/json") + }); }); \ No newline at end of file diff --git a/src/tests/runnerOrgs/org_add.spec.ts b/src/tests/runnerOrgs/org_add.spec.ts index e64a8a2..9d939ef 100644 --- a/src/tests/runnerOrgs/org_add.spec.ts +++ b/src/tests/runnerOrgs/org_add.spec.ts @@ -1,90 +1,102 @@ -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/organisations', () => { - it('basic get should return 200', async () => { - const res = await axios.get(base + '/api/organisations', axios_config); - expect(res.status).toEqual(200); - expect(res.headers['content-type']).toContain("application/json") - }); -}); -// --------------- -describe('POST /api/organisations', () => { - 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); - expect(res.status).toEqual(200); - expect(res.headers['content-type']).toContain("application/json") - }); - it('creating a new org with without a name should return 400', async () => { - const res = await axios.post(base + '/api/organisations', { - "name": null - }, axios_config); - expect(res.status).toEqual(400); - expect(res.headers['content-type']).toContain("application/json") - }); -}); -// --------------- -describe('adding + getting from all orgs', () => { - 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); - expect(res.status).toEqual(200); - expect(res.headers['content-type']).toContain("application/json") - }); - it('check if org was added', async () => { - const res = await axios.get(base + '/api/organisations', axios_config); - expect(res.status).toEqual(200); - expect(res.headers['content-type']).toContain("application/json") - let added_org = res.data[res.data.length - 1] - delete added_org.id - expect(added_org).toEqual({ - "name": "test123", - "contact": null, - "address": null, - "teams": [] - }) - }); -}); -// --------------- -describe('adding + getting explicitly', () => { - let added_org_id - 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 - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('check if org was added', async () => { - const res2 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - let added_org2 = res2.data - added_org_id = added_org2.id; - delete added_org2.id - expect(added_org2).toEqual({ - "name": "test123", - "contact": null, - "address": null, - "teams": [] - }) - }); +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/organisations', () => { + it('basic get should return 200', async () => { + const res = await axios.get(base + '/api/organisations', axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('POST /api/organisations', () => { + 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); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('creating a new org with without a name should return 400', async () => { + const res = await axios.post(base + '/api/organisations', { + "name": null + }, axios_config); + expect(res.status).toEqual(400); + expect(res.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('adding + getting from all orgs', () => { + 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); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + }); + it('check if org was added', async () => { + const res = await axios.get(base + '/api/organisations', axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + let added_org = res.data[res.data.length - 1] + delete added_org.id + expect(added_org).toEqual({ + "name": "test123", + "contact": null, + "address": { + "address1": null, + "address2": null, + "city": null, + "country": null, + "postalcode": null, + }, + "teams": [] + }) + }); +}); +// --------------- +describe('adding + getting explicitly', () => { + let added_org_id + 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 + added_org_id = added_org.id; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('check if org was added', async () => { + const res2 = await axios.get(base + '/api/organisations/' + added_org_id, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + let added_org2 = res2.data + 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": [] + }) + }); }); \ No newline at end of file diff --git a/src/tests/runnerOrgs/org_delete.spec.ts b/src/tests/runnerOrgs/org_delete.spec.ts index 9c023e8..d28faa1 100644 --- a/src/tests/runnerOrgs/org_delete.spec.ts +++ b/src/tests/runnerOrgs/org_delete.spec.ts @@ -1,132 +1,144 @@ -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 res2 = await axios.delete(base + '/api/organisations/0', axios_config); - expect(res2.status).toEqual(204); - }); -}); -// --------------- -describe('adding + deletion (successfull)', () => { - let added_org_id - 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); - added_org = res1.data - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('delete', async () => { - const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - let added_org2 = res2.data - added_org_id = added_org2.id; - delete added_org2.id - expect(added_org2).toEqual({ - "name": "test123", - "contact": null, - "address": null, - "teams": [] - }); - }); - 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") - }); -}); -// --------------- -describe('adding + deletion with teams still existing (without force)', () => { - let added_org; - let added_org_id; - 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', { - "name": "test123" - }, axios_config); - added_org = res1.data; - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('creating a new team with a valid org should return 200', async () => { - const res2 = await axios.post(base + '/api/teams', { - "name": "test123", - "parentGroup": added_org_id - }, axios_config); - added_team = res2.data; - added_team_id = added_team.id; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('delete org - this should fail with a 406', async () => { - const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); - expect(res2.status).toEqual(406); - expect(res2.headers['content-type']).toContain("application/json") - }); -}); -// --------------- -describe('adding + deletion with teams still existing (with force)', () => { - let added_org; - let added_org_id; - 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', { - "name": "test123" - }, axios_config); - added_org = res1.data; - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('creating a new team with a valid org should return 200', async () => { - const res2 = await axios.post(base + '/api/teams', { - "name": "test123", - "parentGroup": added_org_id - }, axios_config); - added_team = res2.data; - added_team_id = added_team.id; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('delete', async () => { - const res2 = await axios.delete(base + '/api/organisations/' + added_org_id + '?force=true', axios_config); - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - let added_org2 = res2.data - added_org_id = added_org2.id; - delete added_org2.id; - delete added_org2.teams; - expect(added_org2).toEqual({ - "name": "test123", - "contact": null, - "address": 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") - }); +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 res2 = await axios.delete(base + '/api/organisations/0', axios_config); + expect(res2.status).toEqual(204); + }); +}); +// --------------- +describe('adding + deletion (successfull)', () => { + let added_org_id + 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); + added_org = res1.data + added_org_id = added_org.id; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('delete', async () => { + const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + let added_org2 = res2.data + 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": [] + }); + }); + 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") + }); +}); +// --------------- +describe('adding + deletion with teams still existing (without force)', () => { + let added_org; + let added_org_id; + 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', { + "name": "test123" + }, axios_config); + added_org = res1.data; + added_org_id = added_org.id; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new team with a valid org should return 200', async () => { + const res2 = await axios.post(base + '/api/teams', { + "name": "test123", + "parentGroup": added_org_id + }, axios_config); + added_team = res2.data; + added_team_id = added_team.id; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('delete org - this should fail with a 406', async () => { + const res2 = await axios.delete(base + '/api/organisations/' + added_org_id, axios_config); + expect(res2.status).toEqual(406); + expect(res2.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('adding + deletion with teams still existing (with force)', () => { + let added_org; + let added_org_id; + 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', { + "name": "test123" + }, axios_config); + added_org = res1.data; + added_org_id = added_org.id; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new team with a valid org should return 200', async () => { + const res2 = await axios.post(base + '/api/teams', { + "name": "test123", + "parentGroup": added_org_id + }, axios_config); + added_team = res2.data; + added_team_id = added_team.id; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('delete', async () => { + const res2 = await axios.delete(base + '/api/organisations/' + added_org_id + '?force=true', axios_config); + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + let added_org2 = res2.data + added_org_id = added_org2.id; + delete added_org2.id; + delete added_org2.teams; + expect(added_org2).toEqual({ + "name": "test123", + "contact": null, + "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") + }); }); \ No newline at end of file diff --git a/src/tests/runnerOrgs/org_update.spec.ts b/src/tests/runnerOrgs/org_update.spec.ts index 96ab8c8..389dc84 100644 --- a/src/tests/runnerOrgs/org_update.spec.ts +++ b/src/tests/runnerOrgs/org_update.spec.ts @@ -1,73 +1,383 @@ -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 + updating name', () => { - let added_org_id - 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); - added_org = res1.data - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('update org', async () => { - const res2 = await axios.put(base + '/api/organisations/' + added_org_id, { - "id": added_org_id, - "name": "testlelele", - "contact": null, - "address": null, - }, axios_config); - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - let added_org2 = res2.data - added_org_id = added_org2.id; - delete added_org2.id - expect(added_org2).toEqual({ - "name": "testlelele", - "contact": null, - "address": null, - "teams": [] - }) - }); -}); -// --------------- -describe('adding + try updating id (should return 406)', () => { - let added_org_id - 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); - added_org = res1.data - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('update org', async () => { - const res2 = await axios.put(base + '/api/organisations/' + added_org_id, { - "id": added_org_id + 1, - "name": "testlelele", - "contact": null, - "address": null, - }, axios_config); - expect(res2.status).toEqual(406); - expect(res2.headers['content-type']).toContain("application/json") - }); +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 + updating name', () => { + 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('update org', async () => { + const res = await axios.put(base + '/api/organisations/' + added_org_id, { + "id": added_org_id, + "name": "testlelele", + "contact": null, + "address": null, + }, axios_config); + expect(res.status).toEqual(200); + expect(res.headers['content-type']).toContain("application/json") + let added_org2 = res.data + added_org_id = added_org2.id; + delete added_org2.id + expect(added_org2).toEqual({ + "name": "testlelele", + "contact": null, + "address": { + "address1": null, + "address2": null, + "city": null, + "country": null, + "postalcode": null, + }, + "teams": [] + }) + }); +}); +// --------------- +describe('adding + try updating id (should return 406)', () => { + 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('update org', async () => { + const res = await axios.put(base + '/api/organisations/' + added_org_id, { + "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"); + }); }); \ No newline at end of file diff --git a/src/tests/runnerTeams/team_update.spec.ts b/src/tests/runnerTeams/team_update.spec.ts index 9ad8030..0257bfd 100644 --- a/src/tests/runnerTeams/team_update.spec.ts +++ b/src/tests/runnerTeams/team_update.spec.ts @@ -1,131 +1,130 @@ -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 + updating name', () => { - let added_org; - let added_org_id; - 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', { - "name": "test123" - }, axios_config); - added_org = res1.data; - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('creating a new team with a valid org should return 200', async () => { - const res2 = await axios.post(base + '/api/teams', { - "name": "test123", - "parentGroup": added_org_id - }, axios_config); - added_team = res2.data; - added_team_id = added_team.id; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('update name', async () => { - const res3 = await axios.put(base + '/api/teams/' + added_team_id, { - "id": added_team_id, - "name": "testlelele", - "contact": null, - "parentGroup": added_org.id - }, axios_config); - expect(res3.status).toEqual(200); - expect(res3.headers['content-type']).toContain("application/json") - let updated_team = res3.data; - added_team.name = "testlelele"; - expect(updated_team).toEqual(added_team) - }); -}); -// --------------- -describe('adding + try updating id (should return 406)', () => { - let added_org; - let added_org_id; - 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', { - "name": "test123" - }, axios_config); - added_org = res1.data; - added_org_id = added_org.id; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('creating a new team with a valid org should return 200', async () => { - const res2 = await axios.post(base + '/api/teams', { - "name": "test123", - "parentGroup": added_org_id - }, axios_config); - added_team = res2.data; - added_team_id = added_team.id; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('update team', async () => { - added_team.id = added_team.id + 1; - added_team.parentGroup = added_team.parentGroup.id; - const res3 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); - expect(res3.status).toEqual(406); - expect(res3.headers['content-type']).toContain("application/json") - }); -}); -// --------------- -describe('add+update parent org (valid)', () => { - let added_org; - let added_org2; - 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', { - "name": "test123" - }, axios_config); - added_org = res1.data; - expect(res1.status).toEqual(200); - expect(res1.headers['content-type']).toContain("application/json") - }); - it('creating a new team with a valid org should return 200', async () => { - const res2 = await axios.post(base + '/api/teams', { - "name": "test123", - "parentGroup": added_org.id - }, axios_config); - added_team = res2.data; - added_team_id = added_team.id; - 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', { - "name": "test123" - }, axios_config); - added_org2 = res3.data; - expect(res3.status).toEqual(200); - expect(res3.headers['content-type']).toContain("application/json") - }); - it('update team', async () => { - added_team.parentGroup = added_org2.id; - const res4 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); - let updated_team = res4.data; - expect(res4.status).toEqual(200); - expect(res4.headers['content-type']).toContain("application/json") - delete added_org2.address; - delete added_org2.contact; - delete added_org2.teams; - expect(updated_team.parentGroup).toEqual(added_org2) - }); +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 + updating name', () => { + let added_org; + let added_org_id; + 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', { + "name": "test123" + }, axios_config); + added_org = res1.data; + added_org_id = added_org.id; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new team with a valid org should return 200', async () => { + const res2 = await axios.post(base + '/api/teams', { + "name": "test123", + "parentGroup": added_org_id + }, axios_config); + added_team = res2.data; + added_team_id = added_team.id; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('update name', async () => { + const res3 = await axios.put(base + '/api/teams/' + added_team_id, { + "id": added_team_id, + "name": "testlelele", + "contact": null, + "parentGroup": added_org.id + }, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + let updated_team = res3.data; + added_team.name = "testlelele"; + expect(updated_team).toEqual(added_team) + }); +}); +// --------------- +describe('adding + try updating id (should return 406)', () => { + let added_org; + let added_org_id; + 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', { + "name": "test123" + }, axios_config); + added_org = res1.data; + added_org_id = added_org.id; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new team with a valid org should return 200', async () => { + const res2 = await axios.post(base + '/api/teams', { + "name": "test123", + "parentGroup": added_org_id + }, axios_config); + added_team = res2.data; + added_team_id = added_team.id; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('update team', async () => { + added_team.id = added_team.id + 1; + added_team.parentGroup = added_team.parentGroup.id; + const res3 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); + expect(res3.status).toEqual(406); + expect(res3.headers['content-type']).toContain("application/json") + }); +}); +// --------------- +describe('add+update parent org (valid)', () => { + let added_org; + let added_org2; + 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', { + "name": "test123" + }, axios_config); + added_org = res1.data; + expect(res1.status).toEqual(200); + expect(res1.headers['content-type']).toContain("application/json") + }); + it('creating a new team with a valid org should return 200', async () => { + const res2 = await axios.post(base + '/api/teams', { + "name": "test123", + "parentGroup": added_org.id + }, axios_config); + added_team = res2.data; + added_team_id = added_team.id; + 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', { + "name": "test123" + }, axios_config); + added_org2 = res3.data; + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + }); + it('update team', async () => { + added_team.parentGroup = added_org2.id; + const res4 = await axios.put(base + '/api/teams/' + added_team_id, added_team, axios_config); + let updated_team = res4.data; + expect(res4.status).toEqual(200); + expect(res4.headers['content-type']).toContain("application/json") + delete added_org2.contact; + delete added_org2.teams; + expect(updated_team.parentGroup).toEqual(added_org2) + }); }); \ No newline at end of file diff --git a/src/tests/runners/runner_update.spec.ts b/src/tests/runners/runner_update.spec.ts index 0cba324..92c80e7 100644 --- a/src/tests/runners/runner_update.spec.ts +++ b/src/tests/runners/runner_update.spec.ts @@ -1,160 +1,156 @@ -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 runner name after adding', () => { - let added_org; - let added_runner; - let updated_runner; - 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); - added_org = res1.data - 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', { - "firstname": "first", - "lastname": "last", - "group": added_org.id - }, axios_config); - added_runner = res2.data; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('valid update should return 200', async () => { - let runnercopy = added_runner - runnercopy.firstname = "second" - runnercopy.group = added_runner.group.id; - const res3 = await axios.put(base + '/api/runners/' + added_runner.id, runnercopy, axios_config); - expect(res3.status).toEqual(200); - expect(res3.headers['content-type']).toContain("application/json") - updated_runner = res3.data; - delete added_org.address; - delete added_org.contact; - delete added_org.teams; - runnercopy.group = added_org; - expect(updated_runner).toEqual(runnercopy); - }); -}); -// --------------- -describe('Update runner group after adding', () => { - let added_org_id; - let added_org_2; - let added_runner; - let updated_runner; - 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 - added_org_id = added_org.id; - 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', { - "firstname": "first", - "lastname": "last", - "group": added_org_id - }, axios_config); - added_runner = res2.data; - 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', { - "name": "test123" - }, axios_config); - added_org_2 = res3.data - delete added_org_2.address; - delete added_org_2.contact; - delete added_org_2.teams; - expect(res3.status).toEqual(200); - expect(res3.headers['content-type']).toContain("application/json") - }); - it('valid group update should return 200', async () => { - added_runner.group = added_org_2.id; - const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config); - 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; - 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 - added_org_id = added_org.id; - 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', { - "firstname": "first", - "lastname": "last", - "group": added_org_id - }, axios_config); - added_runner = res2.data; - added_runner_id = added_runner.id; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('invalid update should return 406', async () => { - added_runner.id++; - 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 () => { - const res1 = await axios.post(base + '/api/organisations', { - "name": "test123" - }, axios_config); - added_org = res1.data - 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', { - "firstname": "first", - "lastname": "last", - "group": added_org.id - }, axios_config); - added_runner = res2.data; - expect(res2.status).toEqual(200); - expect(res2.headers['content-type']).toContain("application/json") - }); - it('invalid group update should return 404', async () => { - 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") - }); +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 runner name after adding', () => { + let added_org; + let added_runner; + let updated_runner; + 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); + added_org = res1.data + 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', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('valid update should return 200', async () => { + let runnercopy = added_runner + runnercopy.firstname = "second" + runnercopy.group = added_runner.group.id; + const res3 = await axios.put(base + '/api/runners/' + added_runner.id, runnercopy, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + updated_runner = res3.data; + delete added_org.contact; + delete added_org.teams; + runnercopy.group = added_org; + expect(updated_runner).toEqual(runnercopy); + }); +}); +// --------------- +describe('Update runner group after adding', () => { + let added_org_id; + let added_org_2; + let added_runner; + 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 + added_org_id = added_org.id; + 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', { + "firstname": "first", + "lastname": "last", + "group": added_org_id + }, axios_config); + added_runner = res2.data; + 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', { + "name": "test123" + }, axios_config); + added_org_2 = res3.data + delete added_org_2.contact; + delete added_org_2.teams; + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + }); + it('valid group update should return 200', async () => { + added_runner.group = added_org_2.id; + const res3 = await axios.put(base + '/api/runners/' + added_runner.id, added_runner, axios_config); + expect(res3.status).toEqual(200); + expect(res3.headers['content-type']).toContain("application/json") + expect(res3.data.group).toEqual(added_org_2); + }); +}); +// --------------- +describe('Update runner id after adding(should fail)', () => { + let added_org_id; + let added_runner; + let added_runner_id; + 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 + added_org_id = added_org.id; + 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', { + "firstname": "first", + "lastname": "last", + "group": added_org_id + }, axios_config); + added_runner = res2.data; + added_runner_id = added_runner.id; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('invalid update should return 406', async () => { + added_runner.id++; + 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 () => { + const res1 = await axios.post(base + '/api/organisations', { + "name": "test123" + }, axios_config); + added_org = res1.data + 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', { + "firstname": "first", + "lastname": "last", + "group": added_org.id + }, axios_config); + added_runner = res2.data; + expect(res2.status).toEqual(200); + expect(res2.headers['content-type']).toContain("application/json") + }); + it('invalid group update should return 404', async () => { + 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") + }); }); \ No newline at end of file