Merge branch 'master' into WORK-RHA

WORK-RHA
Rayhân HASSOU 2 years ago
commit 5bbb5e37c4

@ -25,7 +25,7 @@ steps:
- npm install
- npm run build
- name: test
- name: publish-jest-reports
image: node:latest
environment:
DB_USERNAME:
@ -40,7 +40,7 @@ steps:
from_secret: SECRET_DB_PORT
commands:
- cd ./API-Project
- npm run test
- npm run test:coverage
depends_on: [ api-build ]
- name: docker-build-and-push
@ -94,7 +94,10 @@ steps:
SONAR_TOKEN:
from_secret: SONAR_TOKEN
settings:
sources: ./API-Project
sources: ./API-Project/src
tests: ./API-Project/tests
sonar.testExecutionReportPaths: ./API-Project/coverage/sonar-report.xml
javascript.lcov.reportPaths: ./API-Project/coverage/lcov.info
commands:
- export SONAR_SCANNER_VERSION=4.7.0.2747
- export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
@ -102,5 +105,5 @@ steps:
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
- export PATH=$SONAR_SCANNER_HOME/bin:$PATH
- export SONAR_SCANNER_OPTS="-server"
- sonar-scanner -D sonar.projectKey=LeftOvers_Api -D sonar.sources=. -D sonar.host.url=https://codefirst.iut.uca.fr/sonar
depends_on: [ api-build ]
- sonar-scanner -X -D sonar.projectKey=LeftOvers_Api -D sonar.host.url=https://codefirst.iut.uca.fr/sonar
depends_on: [ publish-jest-reports ]

File diff suppressed because it is too large Load Diff

@ -7,7 +7,9 @@
"start": "node dist/server.js",
"build": "tsup src/server.ts --format cjs --clean",
"dev": "nodemon --watch src -e js,ts,json --exec \"ts-node src/server.ts\"",
"test": "jest --passWithNoTests"
"test": "jest --detectOpenHandles",
"test:watch": "jest --watchAll",
"test:coverage": "jest --coverage"
},
"author": "",
"license": "ISC",
@ -21,6 +23,7 @@
"morgan": "^1.10.0",
"nodemon": "^3.0.1",
"pg": "^8.11.3",
"supertest": "^6.3.3",
"ts-node": "^10.9.1",
"tsup": "^7.2.0",
"typescript": "^5.2.2"
@ -29,7 +32,18 @@
"@types/cors": "^2.8.17",
"@types/jest": "^29.5.8",
"@types/pg": "^8.10.9",
"@types/supertest": "^2.0.16",
"jest": "^29.7.0",
"jest-sonar-reporter": "^2.0.0",
"ts-jest": "^29.1.1"
},
"jest": {
"preset": "ts-jest",
"testMatch": ["<rootDir>/tests/**/*.spec.ts"],
"testResultsProcessor": "jest-sonar-reporter"
},
"jestSonar": {
"reportPath": "./coverage",
"reportFile": "sonar-report.xml"
}
}

@ -51,7 +51,6 @@ IngredientsController.get('/letter/:letter', async (req, res) => {
/** To get one ingredient by id */
IngredientsController.get('/:id', async (req, res) => {
console
const id = Number(req.params.id);
if (!Number.isInteger(id)) {

@ -40,4 +40,30 @@ RecipesController.get('/:id', async (req, res) => {
}
})
RecipesController.get('/withingr/:ids', async (req, res) => {
let ids: number[] = [];
let raw_ids = String(req.params.ids).split(':')
for (let key in raw_ids) {
const test = Number(raw_ids[key])
if (Number.isNaN(test) || !Number.isInteger(test)) {
res.status(400).json('A parameter is not an integer')
}
ids.push(Number(test))
}
try {
const recipes = await recipes_gw.getIdsRecipesThatContainsIngredients(ids)
if (recipes.length == 0) {
res.status(404).json('no data found')
}
else {
res.status(200).json(recipes)
}
} catch (error) {
const error_error = error as Error
res.status(500).send(error_error.message)
}
})
export { RecipesController }

@ -74,7 +74,7 @@ export class IngredientsGateway {
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT * FROM Ingredients i WHERE LOWER(SUBSTRING(i.name, 1, 1)) = $1',
text: 'SELECT * FROM Ingredients i WHERE LOWER(SUBSTRING(i.name, 1, 1)) = $1 ORDER BY i.name',
values: [letter.toLowerCase()],
};
@ -100,9 +100,16 @@ export class IngredientsGateway {
const client = await this.connection.getPoolClient()
const query = {
text: 'SELECT * FROM Ingredients WHERE LOWER(name) LIKE $1',
values: [`%${prompt.toLowerCase()}%`],
text: `
CREATE EXTENSION IF NOT EXISTS pg_trgm;
SELECT *
FROM Ingredients
WHERE LOWER(name) LIKE $1
ORDER BY similarity(name, $2) DESC, name ASC;
`,
values: [`%${prompt.toLowerCase()}%`, prompt.toLowerCase()],
};
const res = await client.query(query);

@ -29,7 +29,7 @@ export class RecipeGateway {
recipes.push(recipe);
}
return recipes
return recipes as Recipe[];
}
async getById(id: number) : Promise<Recipe | null>{
@ -55,8 +55,37 @@ export class RecipeGateway {
res.rows[0].description,
Number(res.rows[0].time),
steps, ingredients);
console.log(ingredients);
return recipe;
}
async getIdsRecipesThatContainsIngredients(ids: number[]) : Promise<Recipe[]> {
let recipes: Recipe[] = []
const client = await this.connection.getPoolClient()
let query_list_text = '($1'
for (let count = 1; count < ids.length; count++) {
query_list_text = query_list_text + ', $' + String(count+1)
}
query_list_text = query_list_text + ')'
const query = {
text: 'SELECT idRecipe FROM Composed GROUP BY idRecipe HAVING COUNT(DISTINCT idIngredient) = COUNT(DISTINCT CASE WHEN idIngredient IN ' + query_list_text + ' THEN idIngredient END)',
values: ids
}
const res = await client.query(query)
client.release()
for(let key in res.rows) {
const recipe = await this.getById(Number(res.rows[key].idrecipe))
if (recipe != null) {
recipes.push(recipe)
}
}
return recipes as Recipe[];
}
}

@ -8,7 +8,7 @@ import { StepsController } from "./controllers/steps.controller";
let helmet = require("helmet");
let app = express();
const app = express();
app.use(helmet.hidePoweredBy());
// Configuration du middleware CORS pour autoriser toutes les origines
@ -26,4 +26,6 @@ app.use('/steps', StepsController);
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`App listening on PORT ${port}`));
export const server = app.listen(port, () => console.log(`App listening on PORT ${port}`));
export default app;

@ -0,0 +1,13 @@
import request from 'supertest';
import app, {server} from '../src/server';
describe('GET /api/endpoint', () => {
it('should return a 200 status code', async () => {
const response = await request(app).get('/');
expect(response.status).toBe(200);
});
// Ecrire d'autres tests ici
server.close()
});

@ -26,7 +26,7 @@
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */
"rootDir": ".", /* Specify the root folder within your source files. */
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */

Loading…
Cancel
Save