Compare commits
23 Commits
v0.0.9
...
e40e6faebd
| Author | SHA1 | Date | |
|---|---|---|---|
| e40e6faebd | |||
| 3d07aac944 | |||
| 1a5493facf | |||
| 9013b9492c | |||
| 188f26ad65 | |||
| 3ceb5a0c0f | |||
| e1ce052d3c | |||
| 70a379edef | |||
| 35ea3154d1 | |||
| ebf66821a2 | |||
| 8463bee253 | |||
| 860680d001 | |||
| df39166279 | |||
| 32fda46f0a | |||
| 36ecae7e6e | |||
| a5bfe4e3d5 | |||
| 4faeddc3f3 | |||
| 98f7bf366f | |||
| af3a9e5ce2 | |||
| 52eb7b1afe | |||
| 490fbd241d | |||
| f132131156 | |||
| c1e680a063 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@odit/lfk-backend",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.10",
|
||||
"main": "src/app.ts",
|
||||
"repository": "https://git.odit.services/lfk/backend",
|
||||
"author": {
|
||||
|
||||
106
src/controllers/RunnerCardController.ts
Normal file
106
src/controllers/RunnerCardController.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers';
|
||||
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
|
||||
import { getConnectionManager, Repository } from 'typeorm';
|
||||
import { RunnerCardHasScansError, RunnerCardIdsNotMatchingError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors';
|
||||
import { RunnerNotFoundError } from '../errors/RunnerErrors';
|
||||
import { CreateRunnerCard } from '../models/actions/CreateRunnerCard';
|
||||
import { UpdateRunnerCard } from '../models/actions/UpdateRunnerCard';
|
||||
import { RunnerCard } from '../models/entities/RunnerCard';
|
||||
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
|
||||
import { ResponseRunnerCard } from '../models/responses/ResponseRunnerCard';
|
||||
import { ScanController } from './ScanController';
|
||||
|
||||
@JsonController('/cards')
|
||||
@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
||||
export class RunnerCardController {
|
||||
private cardRepository: Repository<RunnerCard>;
|
||||
|
||||
/**
|
||||
* Gets the repository of this controller's model/entity.
|
||||
*/
|
||||
constructor() {
|
||||
this.cardRepository = getConnectionManager().get().getRepository(RunnerCard);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@Authorized("CARD:GET")
|
||||
@ResponseSchema(ResponseRunnerCard, { isArray: true })
|
||||
@OpenAPI({ description: 'Lists all card.' })
|
||||
async getAll() {
|
||||
let responseCards: ResponseRunnerCard[] = new Array<ResponseRunnerCard>();
|
||||
const cards = await this.cardRepository.find({ relations: ['runner'] });
|
||||
cards.forEach(card => {
|
||||
responseCards.push(new ResponseRunnerCard(card));
|
||||
});
|
||||
return responseCards;
|
||||
}
|
||||
|
||||
@Get('/:id')
|
||||
@Authorized("CARD:GET")
|
||||
@ResponseSchema(ResponseRunnerCard)
|
||||
@ResponseSchema(RunnerCardNotFoundError, { statusCode: 404 })
|
||||
@OnUndefined(RunnerCardNotFoundError)
|
||||
@OpenAPI({ description: "Lists all information about the card whose id got provided." })
|
||||
async getOne(@Param('id') id: number) {
|
||||
let card = await this.cardRepository.findOne({ id: id }, { relations: ['runner'] });
|
||||
if (!card) { throw new RunnerCardNotFoundError(); }
|
||||
return card.toResponse();
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Authorized("CARD:CREATE")
|
||||
@ResponseSchema(ResponseRunnerCard)
|
||||
@ResponseSchema(RunnerNotFoundError, { statusCode: 404 })
|
||||
@OpenAPI({ description: "Create a new card. <br> You can provide a associated runner by id but you don't have to." })
|
||||
async post(@Body({ validate: true }) createCard: CreateRunnerCard) {
|
||||
let card = await createCard.toEntity();
|
||||
card = await this.cardRepository.save(card);
|
||||
return (await this.cardRepository.findOne({ id: card.id }, { relations: ['runner'] })).toResponse();
|
||||
}
|
||||
|
||||
@Put('/:id')
|
||||
@Authorized("CARD:UPDATE")
|
||||
@ResponseSchema(ResponseRunnerCard)
|
||||
@ResponseSchema(RunnerCardNotFoundError, { statusCode: 404 })
|
||||
@ResponseSchema(RunnerNotFoundError, { statusCode: 404 })
|
||||
@ResponseSchema(RunnerCardIdsNotMatchingError, { statusCode: 406 })
|
||||
@OpenAPI({ description: "Update the card whose id you provided. <br> Scans created via this card will still be associated with the old runner. <br> Please remember that ids can't be changed." })
|
||||
async put(@Param('id') id: number, @Body({ validate: true }) card: UpdateRunnerCard) {
|
||||
let oldCard = await this.cardRepository.findOne({ id: id });
|
||||
|
||||
if (!oldCard) {
|
||||
throw new RunnerCardNotFoundError();
|
||||
}
|
||||
|
||||
if (oldCard.id != card.id) {
|
||||
throw new RunnerCardIdsNotMatchingError();
|
||||
}
|
||||
|
||||
await this.cardRepository.save(await card.update(oldCard));
|
||||
return (await this.cardRepository.findOne({ id: id }, { relations: ['runner'] })).toResponse();
|
||||
}
|
||||
|
||||
@Delete('/:id')
|
||||
@Authorized("CARD:DELETE")
|
||||
@ResponseSchema(ResponseRunnerCard)
|
||||
@ResponseSchema(ResponseEmpty, { statusCode: 204 })
|
||||
@ResponseSchema(RunnerCardHasScansError, { statusCode: 406 })
|
||||
@OnUndefined(204)
|
||||
@OpenAPI({ description: "Delete the card whose id you provided. <br> If no card with this id exists it will just return 204(no content). <br> If the card still has scans associated you have to provide the force=true query param (warning: this deletes all scans associated with by this card - please disable it instead or just remove the runner association)." })
|
||||
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
|
||||
let card = await this.cardRepository.findOne({ id: id });
|
||||
if (!card) { return null; }
|
||||
|
||||
const cardScans = (await this.cardRepository.findOne({ id: id }, { relations: ["scans"] })).scans;
|
||||
if (cardScans.length != 0 && !force) {
|
||||
throw new RunnerCardHasScansError();
|
||||
}
|
||||
const scanController = new ScanController;
|
||||
for (let scan of cardScans) {
|
||||
await scanController.remove(scan.id, force);
|
||||
}
|
||||
|
||||
await this.cardRepository.delete(card);
|
||||
return card.toResponse();
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import { UpdateRunner } from '../models/actions/UpdateRunner';
|
||||
import { Runner } from '../models/entities/Runner';
|
||||
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
|
||||
import { ResponseRunner } from '../models/responses/ResponseRunner';
|
||||
import { RunnerCardController } from './RunnerCardController';
|
||||
import { ScanController } from './ScanController';
|
||||
|
||||
@JsonController('/runners')
|
||||
@OpenAPI({ security: [{ "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
||||
@@ -27,7 +29,7 @@ export class RunnerController {
|
||||
@OpenAPI({ description: 'Lists all runners from all teams/orgs. <br> This includes the runner\'s group and distance ran.' })
|
||||
async getAll() {
|
||||
let responseRunners: ResponseRunner[] = new Array<ResponseRunner>();
|
||||
const runners = await this.runnerRepository.find({ relations: ['scans', 'group'] });
|
||||
const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'scans.track', 'cards'] });
|
||||
runners.forEach(runner => {
|
||||
responseRunners.push(new ResponseRunner(runner));
|
||||
});
|
||||
@@ -41,7 +43,7 @@ export class RunnerController {
|
||||
@OnUndefined(RunnerNotFoundError)
|
||||
@OpenAPI({ description: 'Lists all information about the runner whose id got provided.' })
|
||||
async getOne(@Param('id') id: number) {
|
||||
let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] })
|
||||
let runner = await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'scans.track', 'cards'] })
|
||||
if (!runner) { throw new RunnerNotFoundError(); }
|
||||
return new ResponseRunner(runner);
|
||||
}
|
||||
@@ -61,7 +63,7 @@ export class RunnerController {
|
||||
}
|
||||
|
||||
runner = await this.runnerRepository.save(runner)
|
||||
return new ResponseRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group'] }));
|
||||
return new ResponseRunner(await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'scans.track', 'cards'] }));
|
||||
}
|
||||
|
||||
@Put('/:id')
|
||||
@@ -82,7 +84,7 @@ export class RunnerController {
|
||||
}
|
||||
|
||||
await this.runnerRepository.save(await runner.updateRunner(oldRunner));
|
||||
return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group'] }));
|
||||
return new ResponseRunner(await this.runnerRepository.findOne({ id: id }, { relations: ['scans', 'group', 'scans.track', 'cards'] }));
|
||||
}
|
||||
|
||||
@Delete('/:id')
|
||||
@@ -94,12 +96,24 @@ export class RunnerController {
|
||||
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
|
||||
let runner = await this.runnerRepository.findOne({ id: id });
|
||||
if (!runner) { return null; }
|
||||
const responseRunner = await this.runnerRepository.findOne(runner, { relations: ['scans', 'group'] });
|
||||
const responseRunner = await this.runnerRepository.findOne(runner, { relations: ['scans', 'group', 'scans.track', 'cards'] });
|
||||
|
||||
if (!runner) {
|
||||
throw new RunnerNotFoundError();
|
||||
}
|
||||
|
||||
const runnerCards = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["cards"] })).cards;
|
||||
const cardController = new RunnerCardController;
|
||||
for (let scan of runnerCards) {
|
||||
await cardController.remove(scan.id, force);
|
||||
}
|
||||
|
||||
const runnerScans = (await this.runnerRepository.findOne({ id: runner.id }, { relations: ["scans"] })).scans;
|
||||
const scanController = new ScanController;
|
||||
for (let scan of runnerScans) {
|
||||
await scanController.remove(scan.id, force);
|
||||
}
|
||||
|
||||
await this.runnerRepository.delete(runner);
|
||||
return new ResponseRunner(responseRunner);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, UseBefore } from 'routing-controllers';
|
||||
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
|
||||
import { getConnectionManager, Repository } from 'typeorm';
|
||||
import { getConnection, getConnectionManager, Repository } from 'typeorm';
|
||||
import { RunnerNotFoundError } from '../errors/RunnerErrors';
|
||||
import { ScanIdsNotMatchingError, ScanNotFoundError } from '../errors/ScanErrors';
|
||||
import ScanAuth from '../middlewares/ScanAuth';
|
||||
@@ -8,6 +8,7 @@ import { CreateScan } from '../models/actions/CreateScan';
|
||||
import { CreateTrackScan } from '../models/actions/CreateTrackScan';
|
||||
import { UpdateScan } from '../models/actions/UpdateScan';
|
||||
import { Scan } from '../models/entities/Scan';
|
||||
import { TrackScan } from '../models/entities/TrackScan';
|
||||
import { ResponseEmpty } from '../models/responses/ResponseEmpty';
|
||||
import { ResponseScan } from '../models/responses/ResponseScan';
|
||||
import { ResponseTrackScan } from '../models/responses/ResponseTrackScan';
|
||||
@@ -31,7 +32,7 @@ export class ScanController {
|
||||
@OpenAPI({ description: 'Lists all scans (normal or track) from all runners. <br> This includes the scan\'s runner\'s distance ran.' })
|
||||
async getAll() {
|
||||
let responseScans: ResponseScan[] = new Array<ResponseScan>();
|
||||
const scans = await this.scanRepository.find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] });
|
||||
const scans = await this.scanRepository.find({ relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] });
|
||||
scans.forEach(scan => {
|
||||
responseScans.push(scan.toResponse());
|
||||
});
|
||||
@@ -46,7 +47,7 @@ export class ScanController {
|
||||
@OnUndefined(ScanNotFoundError)
|
||||
@OpenAPI({ description: 'Lists all information about the scan whose id got provided. This includes the scan\'s runner\'s distance ran.' })
|
||||
async getOne(@Param('id') id: number) {
|
||||
let scan = await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'runner.scans', 'runner.scans.track'] })
|
||||
let scan = await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })
|
||||
if (!scan) { throw new ScanNotFoundError(); }
|
||||
return scan.toResponse();
|
||||
}
|
||||
@@ -59,7 +60,7 @@ export class ScanController {
|
||||
async post(@Body({ validate: true }) createScan: CreateScan) {
|
||||
let scan = await createScan.toScan();
|
||||
scan = await this.scanRepository.save(scan);
|
||||
return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner'] })).toResponse();
|
||||
return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse();
|
||||
}
|
||||
|
||||
@Post("/trackscans")
|
||||
@@ -68,7 +69,9 @@ export class ScanController {
|
||||
@ResponseSchema(RunnerNotFoundError, { statusCode: 404 })
|
||||
@OpenAPI({ description: 'Create a new track scan. <br> This is just a alias for posting /scans', security: [{ "ScanApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
||||
async postTrackScans(@Body({ validate: true }) createScan: CreateTrackScan) {
|
||||
return this.post(createScan);
|
||||
let scan = await createScan.toScan();
|
||||
scan = await getConnection().getRepository(TrackScan).save(scan);
|
||||
return (await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse();
|
||||
}
|
||||
|
||||
@Put('/:id')
|
||||
@@ -90,7 +93,7 @@ export class ScanController {
|
||||
}
|
||||
|
||||
await this.scanRepository.save(await scan.updateScan(oldScan));
|
||||
return (await this.scanRepository.findOne({ id: id }, { relations: ['runner'] })).toResponse();
|
||||
return (await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] })).toResponse();
|
||||
}
|
||||
|
||||
@Delete('/:id')
|
||||
@@ -102,7 +105,7 @@ export class ScanController {
|
||||
async remove(@Param("id") id: number, @QueryParam("force") force: boolean) {
|
||||
let scan = await this.scanRepository.findOne({ id: id });
|
||||
if (!scan) { return null; }
|
||||
const responseScan = await this.scanRepository.findOne({ id: scan.id }, { relations: ["runner"] });
|
||||
const responseScan = await this.scanRepository.findOne({ id: scan.id }, { relations: ['runner', 'track', 'runner.scans', 'runner.scans.track', 'card', 'station'] });
|
||||
|
||||
await this.scanRepository.delete(scan);
|
||||
return responseScan.toResponse();
|
||||
|
||||
@@ -98,7 +98,7 @@ export class ScanStationController {
|
||||
}
|
||||
const scanController = new ScanController;
|
||||
for (let scan of stationScans) {
|
||||
scanController.remove(scan.id, force);
|
||||
await scanController.remove(scan.id, force);
|
||||
}
|
||||
|
||||
const responseStation = await this.stationRepository.findOne({ id: station.id }, { relations: ["track"] });
|
||||
|
||||
@@ -94,9 +94,9 @@ export class TrackController {
|
||||
if (trackStations.length != 0 && !force) {
|
||||
throw new TrackHasScanStationsError();
|
||||
}
|
||||
const scanController = new ScanStationController;
|
||||
const stationController = new ScanStationController;
|
||||
for (let station of trackStations) {
|
||||
scanController.remove(station.id, force);
|
||||
await stationController.remove(station.id, force);
|
||||
}
|
||||
|
||||
await this.trackRepository.delete(track);
|
||||
|
||||
@@ -25,7 +25,7 @@ export class UserController {
|
||||
|
||||
@Get()
|
||||
@Authorized("USER:GET")
|
||||
@ResponseSchema(User, { isArray: true })
|
||||
@ResponseSchema(ResponseUser, { isArray: true })
|
||||
@OpenAPI({ description: 'Lists all users. <br> This includes their groups and permissions directly granted to them (if existing/associated).' })
|
||||
async getAll() {
|
||||
let responseUsers: ResponseUser[] = new Array<ResponseUser>();
|
||||
@@ -38,7 +38,7 @@ export class UserController {
|
||||
|
||||
@Get('/:id')
|
||||
@Authorized("USER:GET")
|
||||
@ResponseSchema(User)
|
||||
@ResponseSchema(ResponseUser)
|
||||
@ResponseSchema(UserNotFoundError, { statusCode: 404 })
|
||||
@OnUndefined(UserNotFoundError)
|
||||
@OpenAPI({ description: 'Lists all information about the user whose id got provided. <br> Please remember that only permissions granted directly to the user will show up here, not permissions inherited from groups.' })
|
||||
@@ -50,7 +50,7 @@ export class UserController {
|
||||
|
||||
@Post()
|
||||
@Authorized("USER:CREATE")
|
||||
@ResponseSchema(User)
|
||||
@ResponseSchema(ResponseUser)
|
||||
@ResponseSchema(UserGroupNotFoundError)
|
||||
@OpenAPI({ description: 'Create a new user. <br> If you want to grant permissions to the user you have to create them seperately by posting to /api/permissions after creating the user.' })
|
||||
async post(@Body({ validate: true }) createUser: CreateUser) {
|
||||
@@ -67,7 +67,7 @@ export class UserController {
|
||||
|
||||
@Put('/:id')
|
||||
@Authorized("USER:UPDATE")
|
||||
@ResponseSchema(User)
|
||||
@ResponseSchema(ResponseUser)
|
||||
@ResponseSchema(UserNotFoundError, { statusCode: 404 })
|
||||
@ResponseSchema(UserIdsNotMatchingError, { statusCode: 406 })
|
||||
@OpenAPI({ description: "Update the user whose id you provided. <br> To change the permissions directly granted to the user please use /api/permissions instead. <br> Please remember that ids can't be changed." })
|
||||
@@ -88,7 +88,7 @@ export class UserController {
|
||||
|
||||
@Delete('/:id')
|
||||
@Authorized("USER:DELETE")
|
||||
@ResponseSchema(User)
|
||||
@ResponseSchema(ResponseUser)
|
||||
@ResponseSchema(ResponseEmpty, { statusCode: 204 })
|
||||
@OnUndefined(204)
|
||||
@OpenAPI({ description: 'Delete the user whose id you provided. <br> If there are any permissions directly granted to the user they will get deleted as well. <br> If no user with this id exists it will just return 204(no content).' })
|
||||
|
||||
@@ -88,9 +88,9 @@ export class UserGroupController {
|
||||
if (!group) { return null; }
|
||||
const responseGroup = await this.userGroupsRepository.findOne({ id: id }, { relations: ['permissions'] });
|
||||
|
||||
const permissionControler = new PermissionController();
|
||||
const permissionController = new PermissionController();
|
||||
for (let permission of responseGroup.permissions) {
|
||||
await permissionControler.remove(permission.id, true);
|
||||
await permissionController.remove(permission.id, true);
|
||||
}
|
||||
|
||||
await this.userGroupsRepository.delete(group);
|
||||
|
||||
48
src/errors/RunnerCardErrors.ts
Normal file
48
src/errors/RunnerCardErrors.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { IsString } from 'class-validator';
|
||||
import { NotAcceptableError, NotFoundError } from 'routing-controllers';
|
||||
|
||||
/**
|
||||
* Error to throw when a card couldn't be found.
|
||||
*/
|
||||
export class RunnerCardNotFoundError extends NotFoundError {
|
||||
@IsString()
|
||||
name = "RunnerCardNotFoundError"
|
||||
|
||||
@IsString()
|
||||
message = "Card not found!"
|
||||
}
|
||||
|
||||
/**
|
||||
* Error to throw when two cards' ids don't match.
|
||||
* Usually occurs when a user tries to change a card's id.
|
||||
*/
|
||||
export class RunnerCardIdsNotMatchingError extends NotAcceptableError {
|
||||
@IsString()
|
||||
name = "RunnerCardIdsNotMatchingError"
|
||||
|
||||
@IsString()
|
||||
message = "The ids don't match! \n And if you wanted to change a cards's id: This isn't allowed"
|
||||
}
|
||||
|
||||
/**
|
||||
* Error to throw when a card still has scans associated.
|
||||
*/
|
||||
export class RunnerCardHasScansError extends NotAcceptableError {
|
||||
@IsString()
|
||||
name = "RunnerCardHasScansError"
|
||||
|
||||
@IsString()
|
||||
message = "This card still has scans associated with it. \n If you want to delete this card with all it's scans add `?force` to your query. \n Otherwise please consider just diableing it."
|
||||
}
|
||||
|
||||
/**
|
||||
* Error to throw when a card's id is too big to generate a ean-13 barcode for it.
|
||||
* This error should never reach a enduser.
|
||||
*/
|
||||
export class RunnerCardIdOutOfRangeError extends Error {
|
||||
@IsString()
|
||||
name = "RunnerCardIdOutOfRangeError"
|
||||
|
||||
@IsString()
|
||||
message = "The card's id is too big to fit into a ean-13 barcode. \n This has a very low probability of happening but means that you might want to switch your barcode format for something that can accept numbers over 9999999999."
|
||||
}
|
||||
45
src/models/actions/CreateRunnerCard.ts
Normal file
45
src/models/actions/CreateRunnerCard.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { IsBoolean, IsInt, IsOptional } from 'class-validator';
|
||||
import { getConnection } from 'typeorm';
|
||||
import { RunnerNotFoundError } from '../../errors/RunnerErrors';
|
||||
import { Runner } from '../entities/Runner';
|
||||
import { RunnerCard } from '../entities/RunnerCard';
|
||||
|
||||
/**
|
||||
* This classed is used to create a new RunnerCard entity from a json body (post request).
|
||||
*/
|
||||
export class CreateRunnerCard {
|
||||
/**
|
||||
* The card's associated runner.
|
||||
*/
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
runner?: number;
|
||||
|
||||
/**
|
||||
* Is the new card enabled (for fraud reasons)?
|
||||
* Default: true
|
||||
*/
|
||||
@IsBoolean()
|
||||
enabled: boolean = true;
|
||||
|
||||
/**
|
||||
* Creates a new RunnerCard entity from this.
|
||||
*/
|
||||
public async toEntity(): Promise<RunnerCard> {
|
||||
let newCard: RunnerCard = new RunnerCard();
|
||||
|
||||
newCard.enabled = this.enabled;
|
||||
newCard.runner = await this.getRunner();
|
||||
|
||||
return newCard;
|
||||
}
|
||||
|
||||
public async getRunner(): Promise<Runner> {
|
||||
if (!this.runner) { return null; }
|
||||
const runner = await getConnection().getRepository(Runner).findOne({ id: this.runner });
|
||||
if (!runner) {
|
||||
throw new RunnerNotFoundError();
|
||||
}
|
||||
return runner;
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,28 @@
|
||||
import { IsNotEmpty } from 'class-validator';
|
||||
import { IsInt, IsPositive } from 'class-validator';
|
||||
import { getConnection } from 'typeorm';
|
||||
import { RunnerNotFoundError } from '../../errors/RunnerErrors';
|
||||
import { RunnerCard } from '../entities/RunnerCard';
|
||||
import { ScanStation } from '../entities/ScanStation';
|
||||
import { TrackScan } from '../entities/TrackScan';
|
||||
import { CreateScan } from './CreateScan';
|
||||
|
||||
/**
|
||||
* This classed is used to create a new Scan entity from a json body (post request).
|
||||
*/
|
||||
export class CreateTrackScan extends CreateScan {
|
||||
|
||||
/**
|
||||
* The scan's associated track.
|
||||
* This is used to determine the scan's distance.
|
||||
*/
|
||||
@IsNotEmpty()
|
||||
track: number;
|
||||
|
||||
export class CreateTrackScan {
|
||||
/**
|
||||
* The runnerCard associated with the scan.
|
||||
* This get's saved for documentation and management purposes.
|
||||
*/
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@IsPositive()
|
||||
card: number;
|
||||
|
||||
/**
|
||||
* The scanning station that created the scan.
|
||||
* Mainly used for logging and traceing back scans (or errors)
|
||||
*/
|
||||
@IsNotEmpty()
|
||||
@IsInt()
|
||||
@IsPositive()
|
||||
station: number;
|
||||
|
||||
/**
|
||||
|
||||
51
src/models/actions/UpdateRunnerCard.ts
Normal file
51
src/models/actions/UpdateRunnerCard.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { IsBoolean, IsInt, IsOptional, IsPositive } from 'class-validator';
|
||||
import { getConnection } from 'typeorm';
|
||||
import { RunnerNotFoundError } from '../../errors/RunnerErrors';
|
||||
import { Runner } from '../entities/Runner';
|
||||
import { RunnerCard } from '../entities/RunnerCard';
|
||||
|
||||
/**
|
||||
* This class is used to update a RunnerCard entity (via put request).
|
||||
*/
|
||||
export class UpdateRunnerCard {
|
||||
/**
|
||||
* The updated card'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()
|
||||
@IsPositive()
|
||||
id?: number;
|
||||
|
||||
/**
|
||||
* The updated card's associated runner.
|
||||
*/
|
||||
@IsInt()
|
||||
@IsOptional()
|
||||
runner?: number;
|
||||
|
||||
/**
|
||||
* Is the updated card enabled (for fraud reasons)?
|
||||
* Default: true
|
||||
*/
|
||||
@IsBoolean()
|
||||
enabled: boolean = true;
|
||||
|
||||
/**
|
||||
* Creates a new RunnerCard entity from this.
|
||||
*/
|
||||
public async update(card: RunnerCard): Promise<RunnerCard> {
|
||||
card.enabled = this.enabled;
|
||||
card.runner = await this.getRunner();
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
public async getRunner(): Promise<Runner> {
|
||||
if (!this.runner) { return null; }
|
||||
const runner = await getConnection().getRepository(Runner).findOne({ id: this.runner });
|
||||
if (!runner) {
|
||||
throw new RunnerNotFoundError();
|
||||
}
|
||||
return runner;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEAN,
|
||||
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
IsOptional,
|
||||
IsString
|
||||
|
||||
IsOptional
|
||||
} from "class-validator";
|
||||
import { Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm";
|
||||
import { RunnerCardIdOutOfRangeError } from '../../errors/RunnerCardErrors';
|
||||
import { ResponseRunnerCard } from '../responses/ResponseRunnerCard';
|
||||
import { Runner } from "./Runner";
|
||||
import { TrackScan } from "./TrackScan";
|
||||
|
||||
@@ -32,17 +33,6 @@ export class RunnerCard {
|
||||
@ManyToOne(() => Runner, runner => runner.cards, { nullable: true })
|
||||
runner: Runner;
|
||||
|
||||
/**
|
||||
* The card's code.
|
||||
* This has to be able to being converted to something barcode compatible.
|
||||
* Will get automaticlly generated (not implemented yet).
|
||||
*/
|
||||
@Column()
|
||||
@IsEAN()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
code: string;
|
||||
|
||||
/**
|
||||
* Is the card enabled (for fraud reasons)?
|
||||
* Default: true
|
||||
@@ -58,10 +48,37 @@ export class RunnerCard {
|
||||
@OneToMany(() => TrackScan, scan => scan.track, { nullable: true })
|
||||
scans: TrackScan[];
|
||||
|
||||
/**
|
||||
* Generates a ean-13 compliant string for barcode generation.
|
||||
*/
|
||||
public get code(): string {
|
||||
const multiply = [1, 3];
|
||||
let total = 0;
|
||||
this.paddedId.split('').forEach((letter, index) => {
|
||||
total += parseInt(letter, 10) * multiply[index % 2];
|
||||
});
|
||||
const checkSum = (Math.ceil(total / 10) * 10) - total;
|
||||
return this.paddedId + checkSum.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this card's id as a string padded to the length of 12 characters with leading zeros.
|
||||
*/
|
||||
private get paddedId(): string {
|
||||
let id: string = this.id.toString();
|
||||
|
||||
if (id.length > 12) {
|
||||
throw new RunnerCardIdOutOfRangeError();
|
||||
}
|
||||
while (id.length < 12) { id = '0' + id; }
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this entity into it's response class.
|
||||
*/
|
||||
public toResponse() {
|
||||
return new Error("NotImplemented");
|
||||
return new ResponseRunnerCard(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,5 +12,6 @@ export enum PermissionTarget {
|
||||
STATSCLIENT = 'STATSCLIENT',
|
||||
DONOR = 'DONOR',
|
||||
SCAN = 'SCAN',
|
||||
STATION = 'STATION'
|
||||
STATION = 'STATION',
|
||||
CARD = 'CARD'
|
||||
}
|
||||
53
src/models/responses/ResponseRunnerCard.ts
Normal file
53
src/models/responses/ResponseRunnerCard.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { IsBoolean, IsEAN, IsInt, IsNotEmpty, IsObject, IsString } from "class-validator";
|
||||
import { RunnerCard } from '../entities/RunnerCard';
|
||||
import { ResponseRunner } from './ResponseRunner';
|
||||
|
||||
/**
|
||||
* Defines the runner card response.
|
||||
*/
|
||||
export class ResponseRunnerCard {
|
||||
/**
|
||||
* The card's id.
|
||||
*/
|
||||
@IsInt()
|
||||
id: number;;
|
||||
|
||||
/**
|
||||
* The card's associated runner.
|
||||
* This is important to link scans to runners.
|
||||
*/
|
||||
@IsObject()
|
||||
runner: ResponseRunner | null;
|
||||
|
||||
/**
|
||||
* The card's code.
|
||||
*/
|
||||
@IsEAN()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
code: string;
|
||||
|
||||
/**
|
||||
* Is the enabled valid (for fraud reasons).
|
||||
* The determination of validity will work differently for every child class.
|
||||
*/
|
||||
@IsBoolean()
|
||||
enabled: boolean = true;
|
||||
|
||||
/**
|
||||
* Creates a ResponseRunnerCard object from a runner card.
|
||||
* @param card The card the response shall be build for.
|
||||
*/
|
||||
public constructor(card: RunnerCard) {
|
||||
this.id = card.id;
|
||||
if (!card.runner) { this.runner = null }
|
||||
else { this.runner = card.runner.toResponse(); }
|
||||
try {
|
||||
this.code = card.code;
|
||||
} catch (error) {
|
||||
this.code = "0000000000000"
|
||||
}
|
||||
|
||||
this.enabled = card.enabled;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { IsDateString, IsNotEmpty } from "class-validator";
|
||||
import { RunnerCard } from '../entities/RunnerCard';
|
||||
import { ScanStation } from '../entities/ScanStation';
|
||||
import { TrackScan } from '../entities/TrackScan';
|
||||
import { ResponseRunnerCard } from './ResponseRunnerCard';
|
||||
import { ResponseScan } from './ResponseScan';
|
||||
import { ResponseScanStation } from './ResponseScanStation';
|
||||
import { ResponseTrack } from './ResponseTrack';
|
||||
|
||||
/**
|
||||
@@ -19,13 +19,13 @@ export class ResponseTrackScan extends ResponseScan {
|
||||
* The runnerCard associated with the scan.
|
||||
*/
|
||||
@IsNotEmpty()
|
||||
card: RunnerCard;
|
||||
card: ResponseRunnerCard;
|
||||
|
||||
/**
|
||||
* The scanning station that created the scan.
|
||||
*/
|
||||
@IsNotEmpty()
|
||||
station: ScanStation;
|
||||
station: ResponseScanStation;
|
||||
|
||||
/**
|
||||
* The scan's creation timestamp.
|
||||
@@ -41,8 +41,9 @@ export class ResponseTrackScan extends ResponseScan {
|
||||
public constructor(scan: TrackScan) {
|
||||
super(scan);
|
||||
this.track = new ResponseTrack(scan.track);
|
||||
this.card = scan.card;
|
||||
this.station = scan.station;
|
||||
this.card = scan.card.toResponse();
|
||||
this.station = scan.station.toResponse();
|
||||
this.timestamp = scan.timestamp;
|
||||
this.distance = scan.distance;
|
||||
}
|
||||
}
|
||||
|
||||
144
src/tests/cards/cards_add.spec.ts
Normal file
144
src/tests/cards/cards_add.spec.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import axios from 'axios';
|
||||
import { config } from '../../config';
|
||||
const base = "http://localhost:" + config.internal_port
|
||||
|
||||
let access_token;
|
||||
let axios_config;
|
||||
|
||||
beforeAll(async () => {
|
||||
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
|
||||
access_token = res.data["access_token"];
|
||||
axios_config = {
|
||||
headers: { "authorization": "Bearer " + access_token },
|
||||
validateStatus: undefined
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
describe('POST /api/cards illegally', () => {
|
||||
it('non-existant runner input should return 404', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"runner": 999999999999999999999999
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(404);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('POST /api/cards successfully (without runner)', () => {
|
||||
it('creating a card with the minimum amount of parameters should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', null, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": null,
|
||||
"enabled": true
|
||||
});
|
||||
});
|
||||
it('creating a disabled card should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"enabled": false
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": null,
|
||||
"enabled": false
|
||||
});
|
||||
});
|
||||
it('creating a enabled card should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"enabled": true
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": null,
|
||||
"enabled": true
|
||||
});
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('POST /api/cards successfully (with runner)', () => {
|
||||
let added_org;
|
||||
let added_runner;
|
||||
it('creating a new org with just a name should return 200', async () => {
|
||||
const res1 = await axios.post(base + '/api/organisations', {
|
||||
"name": "test123"
|
||||
}, axios_config);
|
||||
added_org = res1.data
|
||||
expect(res1.status).toEqual(200);
|
||||
expect(res1.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('creating a new runner with only needed params should return 200', async () => {
|
||||
const res2 = await axios.post(base + '/api/runners', {
|
||||
"firstname": "first",
|
||||
"lastname": "last",
|
||||
"group": added_org.id
|
||||
}, axios_config);
|
||||
delete res2.data.group;
|
||||
added_runner = res2.data;
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('creating a card with the minimum amount of parameters should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"runner": added_runner.id
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"enabled": true
|
||||
});
|
||||
});
|
||||
it('creating a card with runner (no optional params) should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"runner": added_runner.id
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"enabled": true
|
||||
});
|
||||
});
|
||||
it('creating a enabled card with runner should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"runner": added_runner.id,
|
||||
"enabled": true
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"enabled": true
|
||||
});
|
||||
});
|
||||
it('creating a disabled card with runner should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', {
|
||||
"runner": added_runner.id,
|
||||
"enabled": false
|
||||
}, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.code;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"enabled": false
|
||||
});
|
||||
});
|
||||
});
|
||||
45
src/tests/cards/cards_delete.spec.ts
Normal file
45
src/tests/cards/cards_delete.spec.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import axios from 'axios';
|
||||
import { config } from '../../config';
|
||||
const base = "http://localhost:" + config.internal_port
|
||||
|
||||
let access_token;
|
||||
let axios_config;
|
||||
|
||||
beforeAll(async () => {
|
||||
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
|
||||
access_token = res.data["access_token"];
|
||||
axios_config = {
|
||||
headers: { "authorization": "Bearer " + access_token },
|
||||
validateStatus: undefined
|
||||
};
|
||||
});
|
||||
|
||||
// ---------------
|
||||
|
||||
describe('DELETE card', () => {
|
||||
let added_card;
|
||||
it('creating card without runner should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', null, axios_config);
|
||||
added_card = res.data;
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('delete card', async () => {
|
||||
const res2 = await axios.delete(base + '/api/cards/' + added_card.id, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
expect(res2.data).toEqual(added_card);
|
||||
});
|
||||
it('check if card really was deleted', async () => {
|
||||
const res3 = await axios.get(base + '/api/cards/' + added_card.id, axios_config);
|
||||
expect(res3.status).toEqual(404);
|
||||
expect(res3.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('DELETE card (non-existant)', () => {
|
||||
it('delete', async () => {
|
||||
const res2 = await axios.delete(base + '/api/cards/0', axios_config);
|
||||
expect(res2.status).toEqual(204);
|
||||
});
|
||||
});
|
||||
46
src/tests/cards/cards_get.spec.ts
Normal file
46
src/tests/cards/cards_get.spec.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import axios from 'axios';
|
||||
import { config } from '../../config';
|
||||
const base = "http://localhost:" + config.internal_port
|
||||
|
||||
let access_token;
|
||||
let axios_config;
|
||||
|
||||
beforeAll(async () => {
|
||||
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
|
||||
access_token = res.data["access_token"];
|
||||
axios_config = {
|
||||
headers: { "authorization": "Bearer " + access_token },
|
||||
validateStatus: undefined
|
||||
};
|
||||
});
|
||||
|
||||
describe('GET /api/cards sucessfully', () => {
|
||||
it('basic get should return 200', async () => {
|
||||
const res = await axios.get(base + '/api/cards', axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('GET /api/cards illegally', () => {
|
||||
it('get for non-existant track should return 404', async () => {
|
||||
const res = await axios.get(base + '/api/cards/-1', axios_config);
|
||||
expect(res.status).toEqual(404);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('adding + getting cards (no runner)', () => {
|
||||
let added_card;
|
||||
it('correct distance and runner input should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', null, axios_config);
|
||||
added_card = res.data;
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('check if scans was added (no parameter validation)', async () => {
|
||||
const res = await axios.get(base + '/api/cards/' + added_card.id, axios_config);
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
});
|
||||
});
|
||||
163
src/tests/cards/cards_update.spec.ts
Normal file
163
src/tests/cards/cards_update.spec.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import axios from 'axios';
|
||||
import { config } from '../../config';
|
||||
const base = "http://localhost:" + config.internal_port
|
||||
|
||||
let access_token;
|
||||
let axios_config;
|
||||
|
||||
beforeAll(async () => {
|
||||
const res = await axios.post(base + '/api/auth/login', { username: "demo", password: "demo" });
|
||||
access_token = res.data["access_token"];
|
||||
axios_config = {
|
||||
headers: { "authorization": "Bearer " + access_token },
|
||||
validateStatus: undefined
|
||||
};
|
||||
});
|
||||
|
||||
describe('adding + updating illegally', () => {
|
||||
let added_card;
|
||||
it('creating card without runner should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', null, axios_config);
|
||||
added_card = res.data;
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('updating empty should return 400', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, null, axios_config);
|
||||
expect(res2.status).toEqual(400);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('updating with wrong id should return 406', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id + 1
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(406);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('update with invalid runner id should return 404', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id,
|
||||
"runner": 9999999999999999999999999
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(404);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('adding + updating card.runner successfully', () => {
|
||||
let added_org;
|
||||
let added_runner;
|
||||
let added_runner2;
|
||||
let added_card;
|
||||
it('creating a new org with just a name should return 200', async () => {
|
||||
const res1 = await axios.post(base + '/api/organisations', {
|
||||
"name": "test123"
|
||||
}, axios_config);
|
||||
added_org = res1.data
|
||||
expect(res1.status).toEqual(200);
|
||||
expect(res1.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('creating a new runner with only needed params should return 200', async () => {
|
||||
const res2 = await axios.post(base + '/api/runners', {
|
||||
"firstname": "first",
|
||||
"lastname": "last",
|
||||
"group": added_org.id
|
||||
}, axios_config);
|
||||
delete res2.data.group;
|
||||
added_runner = res2.data;
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('creating a new runner with only needed params should return 200', async () => {
|
||||
const res2 = await axios.post(base + '/api/runners', {
|
||||
"firstname": "first",
|
||||
"lastname": "last",
|
||||
"group": added_org.id
|
||||
}, axios_config);
|
||||
delete res2.data.group;
|
||||
added_runner2 = res2.data;
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('creating card without runner should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', null, axios_config);
|
||||
added_card = res.data;
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('valid runner update (add runner) should return 200', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id,
|
||||
"runner": added_runner.id
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json");
|
||||
expect(res2.data).toEqual({
|
||||
"id": added_card.id,
|
||||
"runner": added_runner,
|
||||
"enabled": true,
|
||||
"code": added_card.code
|
||||
});
|
||||
});
|
||||
it('valid runner update (change runner) should return 200', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id,
|
||||
"runner": added_runner2.id
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json");
|
||||
expect(res2.data).toEqual({
|
||||
"id": added_card.id,
|
||||
"runner": added_runner2,
|
||||
"enabled": true,
|
||||
"code": added_card.code
|
||||
});
|
||||
});
|
||||
});
|
||||
// ---------------
|
||||
describe('adding + updating other values successfully', () => {
|
||||
let added_card;
|
||||
it('creating card without runner should return 200', async () => {
|
||||
const res = await axios.post(base + '/api/cards', null, axios_config);
|
||||
added_card = res.data;
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
it('valid update changeing nothing should return 200', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json");
|
||||
expect(res2.data).toEqual(added_card);
|
||||
});
|
||||
it('valid disable update should return 200', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id,
|
||||
"enabled": false
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json");
|
||||
expect(res2.data).toEqual({
|
||||
"id": added_card.id,
|
||||
"runner": null,
|
||||
"enabled": false,
|
||||
"code": added_card.code
|
||||
});
|
||||
});
|
||||
it('valid enable update should return 200', async () => {
|
||||
const res2 = await axios.put(base + '/api/cards/' + added_card.id, {
|
||||
"id": added_card.id,
|
||||
"enabled": true
|
||||
}, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json");
|
||||
expect(res2.data).toEqual({
|
||||
"id": added_card.id,
|
||||
"runner": null,
|
||||
"enabled": true,
|
||||
"code": added_card.code
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -84,6 +84,7 @@ describe('POST /api/scans successfully', () => {
|
||||
"group": added_org.id
|
||||
}, axios_config);
|
||||
delete res2.data.group;
|
||||
delete res2.data.distance;
|
||||
added_runner = res2.data;
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
@@ -96,6 +97,7 @@ describe('POST /api/scans successfully', () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"distance": 200,
|
||||
@@ -111,6 +113,7 @@ describe('POST /api/scans successfully', () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"distance": 200,
|
||||
@@ -126,6 +129,7 @@ describe('POST /api/scans successfully', () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"distance": 200,
|
||||
@@ -154,6 +158,7 @@ describe('POST /api/scans successfully via scan station', () => {
|
||||
"group": added_org.id
|
||||
}, axios_config);
|
||||
delete res2.data.group;
|
||||
delete res2.data.distance;
|
||||
added_runner = res2.data;
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
@@ -186,6 +191,7 @@ describe('POST /api/scans successfully via scan station', () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"distance": 200,
|
||||
@@ -204,6 +210,7 @@ describe('POST /api/scans successfully via scan station', () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"distance": 200,
|
||||
@@ -222,6 +229,7 @@ describe('POST /api/scans successfully via scan station', () => {
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json");
|
||||
delete res.data.id;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.data).toEqual({
|
||||
"runner": added_runner,
|
||||
"distance": 200,
|
||||
|
||||
@@ -44,6 +44,7 @@ describe('DELETE scan', () => {
|
||||
"distance": 1000
|
||||
}, axios_config);
|
||||
added_scan = res.data;
|
||||
delete res.data.runner.distance;
|
||||
expect(res.status).toEqual(200);
|
||||
expect(res.headers['content-type']).toContain("application/json")
|
||||
});
|
||||
@@ -51,6 +52,7 @@ describe('DELETE scan', () => {
|
||||
const res2 = await axios.delete(base + '/api/scans/' + added_scan.id, axios_config);
|
||||
expect(res2.status).toEqual(200);
|
||||
expect(res2.headers['content-type']).toContain("application/json")
|
||||
delete res2.data.runner.distance;
|
||||
expect(res2.data).toEqual(added_scan);
|
||||
});
|
||||
it('check if scan really was deleted', async () => {
|
||||
|
||||
Reference in New Issue
Block a user