Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feat: Fetching available theaters with escape game #15

Merged
merged 7 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ class App {
this.app.use('/movies', moviesRouter);
this.app.use('/theaters', theatersRouter);


}

private errorHandler() {
Expand Down
18 changes: 18 additions & 0 deletions src/controllers/theaters/theaters.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,22 @@ export default class TheatersController implements BaseController {
}
}

public async getAvailableTheatersEscapeGame(res: Response): Promise<Response> {
try {
const data = await this.scrappingService.AvailableTheatersEscapeGame();
return res.status(StatusCodes.OK).json(data);

}catch(error) {
const e = error as Error;

this.logger.warn('getTheatersNames');
this.logger.warn(e.message);

return res.status(StatusCodes.BAD_REQUEST).json({
message: ReasonPhrases.BAD_REQUEST,
errors: e.message,
})
}
}

}
37 changes: 30 additions & 7 deletions src/docs/swagger-output.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,20 @@
}
}
},
"/status": {
"get": {
"tags": [
"/"
],
"summary": "Redirect to the health status page",
"description": "",
"responses": {
"default": {
"description": ""
}
}
}
},
"/movies": {
"get": {
"tags": [
Expand Down Expand Up @@ -251,7 +265,7 @@
}
}
},
"/movies/{theater}": {
"/movies/{theaterSlug}": {
"get": {
"tags": [
"Movies"
Expand All @@ -260,7 +274,7 @@
"description": "Fetch all the available movies at a given theater",
"parameters": [
{
"name": "theater",
"name": "theaterSlug",
"in": "path",
"required": true,
"schema": {
Expand Down Expand Up @@ -710,7 +724,7 @@
}
},
{
"name": "theater",
"name": "theaterSlug",
"in": "query",
"schema": {
"type": "string"
Expand Down Expand Up @@ -1000,7 +1014,17 @@
}
}
},
"/theaters/infos/{theater}": {
"/theaters/escape-game": {
"get": {
"description": "",
"responses": {
"default": {
"description": ""
}
}
}
},
"/theaters/infos/{theaterSlug}": {
"get": {
"tags": [
"Theaters"
Expand All @@ -1009,7 +1033,7 @@
"description": "Fetch informations about a specified theater giving his name",
"parameters": [
{
"name": "theater",
"name": "theaterSlug",
"in": "path",
"required": true,
"schema": {
Expand Down Expand Up @@ -1431,6 +1455,5 @@
}
}
}
},
"url": "http://51.91.76.77:3123"
}
}
11 changes: 11 additions & 0 deletions src/models/theater-escape-game.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default interface TheaterEscapeGameModel {
theaterName : string ,
name: string,
img: string,
price: number,
groupSizeMin: number,
groupSizeMax: number,
difficulty: number,
description: string,
minAge: number,
}
12 changes: 12 additions & 0 deletions src/routes/theaters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ router.get(
}
);

router.get('/escape-game',

ExpressValidatorMiddleware,

async function (req, res, _next) {
const response = theatersController.getAvailableTheatersEscapeGame(res);
return response;
}

);



router.get(
'/infos/:theaterSlug',
Expand Down
76 changes: 76 additions & 0 deletions src/services/scapping/scrapping.servive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import TheaterInfosModel from "../../models/theater-info.model";
import TheaterNameModel from "@/models/theater-name.model";
import axios, { AxiosError, AxiosResponse } from "axios";
import * as cheerio from 'cheerio';
import TheaterEscapeGameModel from "@/models/theater-escape-game.model";

export default class ScrappingService implements BaseService {

Expand Down Expand Up @@ -431,6 +432,81 @@ export default class ScrappingService implements BaseService {
return theaterInfos;
}

public async escapeGameByTheaters() {
let response: AxiosResponse;
try {
response = await axios.get(infos.baseUrl);
} catch (error) {

const e = error as AxiosError;

this.logger.fatal('theatersNames');
this.logger.fatal(e);

throw Error(e.message);
}

// escape game by theaters


}

public async AvailableTheatersEscapeGame(): Promise<TheaterEscapeGameModel[]> {
let response: AxiosResponse;
try {
response = await axios.get(`${infos.baseUrl}/escape-game/`);
} catch (error) {

const e = error as AxiosError;

this.logger.fatal('theatersNames');
this.logger.fatal(e);

throw Error(e.message);
}
const theaterEscapeGame: TheaterEscapeGameModel[] = [];
const htmlRoot = cheerio.load(response.data);

const avalaibleTheatherNames = htmlRoot("ul.theaters li").map((index, element) => htmlRoot(element).data("set") as String);

avalaibleTheatherNames.each((_, theaterName) => {

htmlRoot(`article[data-${theaterName}]`).each((index, element) => {
const name = htmlRoot(element).children("h1").text();

const e = htmlRoot(element).children();

const description = e.find(".info-bloc p").text();
const difficulty = e.find("li.full").length;
const groupSizeMin = parseInt(e.find(".price").text().match(/Groupe de (\d+)/)?.[1] || "0");
const groupSizeMax = parseInt(e.find(".price").text().match(/à (\d+) personnes/)?.[1] || "0");
const price = parseInt(e.find(".price").text().match(/Tarif unique (\d+)/)?.[1] || "0")
const minAge = parseInt(e.find(".age-info").text().match(/\d+/)?.[0] || "0");
const image = e.find("figure img").attr("src");

theaterEscapeGame.push(
{
theaterName: theaterName as string,
name: name,
img: image!,
price: price,
groupSizeMin: groupSizeMin,
groupSizeMax: groupSizeMax,
difficulty: difficulty,
description: description,
minAge: minAge,
}
);

});


});

return theaterEscapeGame;

}

}


Expand Down
19 changes: 13 additions & 6 deletions src/tests/api/theaters-route.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import request from 'supertest';
describe('Testing theaters routes', () => {

const reqApp = request(app);

test('if /GET is working', async () => {

const res = await reqApp.get('/');
Expand All @@ -27,8 +27,8 @@ describe('Testing theaters routes', () => {
test('if /GET theaters/infos/ is working', async () => {

const res = await reqApp.get('/theaters/infos/wologuede');


expect(res.statusCode).toBe(200);

});
Expand All @@ -37,17 +37,17 @@ describe('Testing theaters routes', () => {
test('if /GET theaters/infos/ with bad theater slug is not working', async () => {

const res = await reqApp.get('/theaters/infos/123');

expect(res.statusCode).not.toBe(200);

});


test('if /GET theaters/infos/ with bad lang is not working', async () => {

const res = await reqApp.get('/theaters/infos/wologuede?lang=zk');
const res = await reqApp.get('/theaters/infos/wologuede?lang=zk');

expect(res.statusCode).not.toBe(200);
expect(res.statusCode).not.toBe(200);

});

Expand All @@ -60,5 +60,12 @@ describe('Testing theaters routes', () => {

});

test('if /GET theaters/escap-game is working ', async () => {

const res = await reqApp.get('/theaters/escape-game');

expect(res.statusCode).toBe(200);
})

})

22 changes: 15 additions & 7 deletions src/tests/services/scrapping.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('Test on Scapping Service', () => {
const names = await scrappingService.theatersNames();

expect(names.length).toBeGreaterThan(0);

const name = names[0];
expect(name.country).toBeDefined();
expect(name.cities.length).toBeGreaterThan(0);
Expand All @@ -25,7 +25,7 @@ describe('Test on Scapping Service', () => {
return scrappingService.theaterMovies('wologuede').then((movies) => {

expect(movies.length).toBeGreaterThan(0);

});

});
Expand Down Expand Up @@ -70,7 +70,7 @@ describe('Test on Scapping Service', () => {
test('if movieInfoBySlug is not working with bad slug', async () => {

return scrappingService.movieInfoBySlug('zkk').then((info) => {

expect(info).toBeNull();

});
Expand Down Expand Up @@ -174,11 +174,11 @@ describe('Test on Scapping Service', () => {
expect(movies.length).toBeGreaterThan(0);

const movie = movies[0];

expect(movie.title).not.toBeNull();
expect(movie.slug).toBeDefined();
expect(movie.img).toBeDefined();

});

});
Expand All @@ -190,13 +190,21 @@ describe('Test on Scapping Service', () => {

expect(movies.length).toBeGreaterThan(0);

const movie = movies[0];
const movie = movies[0];

expect(movie.title).not.toBeNull();
expect(movie.img).toBeDefined();
expect(movie.slug).toBeDefined();

});

});


test("if available escape game theaters is wroking ", async () => {
return scrappingService.AvailableTheatersEscapeGame().then((theaterEscapeGame => {
expect(theaterEscapeGame.length).toBeGreaterThan(0);
})
);
})
})