Merge pull request 'Fully implemented addresses feature/105-addresses' (#107) from feature/105-addresses into dev
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #107
This commit is contained in:
Nicolai Ort 2021-01-19 15:37:35 +00:00
commit 5e368552ea
25 changed files with 1734 additions and 1497 deletions

View File

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

View File

@ -29,7 +29,7 @@ export class RunnerOrganisationController {
@OpenAPI({ description: 'Lists all organisations. <br> This includes their address, contact and teams (if existing/associated).' }) @OpenAPI({ description: 'Lists all organisations. <br> This includes their address, contact and teams (if existing/associated).' })
async getAll() { async getAll() {
let responseTeams: ResponseRunnerOrganisation[] = new Array<ResponseRunnerOrganisation>(); let responseTeams: ResponseRunnerOrganisation[] = new Array<ResponseRunnerOrganisation>();
const runners = await this.runnerOrganisationRepository.find({ relations: ['address', 'contact', 'teams'] }); const runners = await this.runnerOrganisationRepository.find({ relations: ['contact', 'teams'] });
runners.forEach(runner => { runners.forEach(runner => {
responseTeams.push(new ResponseRunnerOrganisation(runner)); responseTeams.push(new ResponseRunnerOrganisation(runner));
}); });
@ -43,7 +43,7 @@ export class RunnerOrganisationController {
@OnUndefined(RunnerOrganisationNotFoundError) @OnUndefined(RunnerOrganisationNotFoundError)
@OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' }) @OpenAPI({ description: 'Lists all information about the organisation whose id got provided.' })
async getOne(@Param('id') id: number) { async getOne(@Param('id') id: number) {
let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['address', 'contact', 'teams'] }); let runnerOrg = await this.runnerOrganisationRepository.findOne({ id: id }, { relations: ['contact', 'teams'] });
if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); } if (!runnerOrg) { throw new RunnerOrganisationNotFoundError(); }
return new ResponseRunnerOrganisation(runnerOrg); return new ResponseRunnerOrganisation(runnerOrg);
} }
@ -62,7 +62,7 @@ export class RunnerOrganisationController {
runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation); runnerOrganisation = await this.runnerOrganisationRepository.save(runnerOrganisation);
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['address', 'contact', 'teams'] })); return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(runnerOrganisation, { relations: ['contact', 'teams'] }));
} }
@Put('/:id') @Put('/:id')
@ -84,7 +84,7 @@ export class RunnerOrganisationController {
await this.runnerOrganisationRepository.save(await updateOrganisation.update(oldRunnerOrganisation)); await this.runnerOrganisationRepository.save(await updateOrganisation.update(oldRunnerOrganisation));
return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['address', 'contact', 'teams'] })); return new ResponseRunnerOrganisation(await this.runnerOrganisationRepository.findOne(id, { relations: ['contact', 'teams'] }));
} }
@Delete('/:id') @Delete('/:id')
@ -98,7 +98,7 @@ export class RunnerOrganisationController {
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) { async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
let organisation = await this.runnerOrganisationRepository.findOne({ id: id }); let organisation = await this.runnerOrganisationRepository.findOne({ id: id });
if (!organisation) { return null; } if (!organisation) { return null; }
let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['address', 'contact', 'runners', 'teams'] }); let runnerOrganisation = await this.runnerOrganisationRepository.findOne(organisation, { relations: ['contact', 'runners', 'teams'] });
if (!force) { if (!force) {
if (runnerOrganisation.teams.length != 0) { if (runnerOrganisation.teams.length != 0) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,10 +7,9 @@ import {
IsString IsString
} from "class-validator"; } from "class-validator";
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from "typeorm";
import { config } from '../../config'; import { config } from '../../config';
import { Address } from "./Address"; import { Address } from "./Address";
import { IAddressUser } from './IAddressUser';
import { RunnerGroup } from "./RunnerGroup"; import { RunnerGroup } from "./RunnerGroup";
/** /**
@ -18,7 +17,7 @@ import { RunnerGroup } from "./RunnerGroup";
* Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups. * Mainly it's own class to reduce duplicate code and enable contact's to be associated with multiple groups.
*/ */
@Entity() @Entity()
export class GroupContact implements IAddressUser { export class GroupContact {
/** /**
* Autogenerated unique id (primary key). * Autogenerated unique id (primary key).
*/ */
@ -55,7 +54,7 @@ export class GroupContact implements IAddressUser {
* This is a address object to prevent any formatting differences. * This is a address object to prevent any formatting differences.
*/ */
@IsOptional() @IsOptional()
@ManyToOne(() => Address, address => address.addressUsers, { nullable: true }) @Column(type => Address)
address?: Address; address?: Address;
/** /**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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