From f04993d5dede6297d47f3f8a0cfa33f0ec8d17d3 Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Fri, 8 Nov 2024 15:46:44 +0100 Subject: [PATCH 01/18] feat: Reset results on candidature --- package.json | 2 +- .../_post/createCandidature/index.ts | 1 + .../campaignId/candidates/_post/index.spec.ts | 36 ++++++++++++++++++- yarn.lock | 8 ++--- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 59926bcce..648ea0ccd 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "author": "", "license": "ISC", "dependencies": { - "@appquality/tryber-database": "^0.41.10", + "@appquality/tryber-database": "^0.42.0", "@appquality/wp-auth": "^1.0.7", "@googlemaps/google-maps-services-js": "^3.3.7", "@sendgrid/mail": "^7.6.0", diff --git a/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts b/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts index 21a37df4a..7c9d5f987 100644 --- a/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts +++ b/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts @@ -16,6 +16,7 @@ export default async ( accepted: 1, selected_device: selectedDevice, accepted_date: tryber.fn.now(), + results: 0, }) .where("user_id", wpId) .where("campaign_id", campaignId); diff --git a/src/routes/campaigns/campaignId/candidates/_post/index.spec.ts b/src/routes/campaigns/campaignId/candidates/_post/index.spec.ts index de4bedbd3..f6edbcb9b 100644 --- a/src/routes/campaigns/campaignId/candidates/_post/index.spec.ts +++ b/src/routes/campaigns/campaignId/candidates/_post/index.spec.ts @@ -1,6 +1,6 @@ import app from "@src/app"; -import request from "supertest"; import { tryber } from "@src/features/database"; +import request from "supertest"; const profile = { id: 1, wp_user_id: 1, @@ -58,6 +58,7 @@ const authorizedPostCandidate = async ({ .send({ tester_id: tester, device }) .set("authorization", `Bearer tester olp {"appq_tester_selection":[1]}`); }; + const authorizedPostMultiCandidate = async ( list: { tester: number; @@ -197,6 +198,39 @@ describe("POST /campaigns/{campaignId}/candidates", () => { }); }); +describe("POST /campaigns/{campaignId}/candidates - user deselected", () => { + beforeEach(async () => { + await tryber.tables.WpAppqEvdProfile.do().insert([ + { ...profile, id: 100, wp_user_id: 100 }, + ]); + await tryber.tables.WpCrowdAppqHasCandidate.do().insert({ + user_id: 100, + campaign_id: 1, + accepted: 0, + results: -1, + }); + }); + afterEach(async () => { + await tryber.tables.WpAppqEvdProfile.do().delete().where({ id: 100 }); + await tryber.tables.WpCrowdAppqHasCandidate.do() + .delete() + .where({ user_id: 100 }); + }); + + it("Should select with results=0 if user is deselected", async () => { + await authorizedPostCandidate({ tester: 100 }); + const candidature = await getCandidature({ tester: 100, campaign: 1 }); + expect(candidature).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + user_id: 100, + results: 0, + }), + ]) + ); + }); +}); + describe("POST /campaigns/{campaignId}/candidates?device=random when user has not devices", () => { it("Should candidate the user on success with selected_device=0", async () => { const beforeCandidature = await getCandidature({ tester: 1, campaign: 1 }); diff --git a/yarn.lock b/yarn.lock index 5feafab2d..ef5864dd9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -28,10 +28,10 @@ "@babel/parser" "^7.22.5" "@babel/traverse" "^7.22.5" -"@appquality/tryber-database@^0.41.10": - version "0.41.10" - resolved "https://registry.yarnpkg.com/@appquality/tryber-database/-/tryber-database-0.41.10.tgz#b66fd5d5c9874cbc960f50e278682b1a3cd1f2a0" - integrity sha512-HSYe/wpQsD3A8D+ip+6pTL2bEJfwUb3hj2rDrh+LJ2eCSMdIBwNHA67fjlNEtIgUcB/BIokWOi2z+UqIhtaVTQ== +"@appquality/tryber-database@^0.42.0": + version "0.42.0" + resolved "https://registry.npmjs.org/@appquality/tryber-database/-/tryber-database-0.42.0.tgz#4b517d52f61e666e8730c505070db50c0e922940" + integrity sha512-Knxhw6aHWF1d7QnVLiXVkQOPN7pm4uG99pgAtaGZjyhpVBij9BcIZnMFDPxSWO7IHY+JWLfa9PJFjco4SbGG8Q== dependencies: better-sqlite3 "^8.1.0" knex "^2.5.1" From 72e2ebb694d75ebdc0a28f605d82c98f4fb6357d Mon Sep 17 00:00:00 2001 From: Davide Bizzi Date: Fri, 8 Nov 2024 15:48:25 +0100 Subject: [PATCH 02/18] rework: Use on duplicate key update for candidature --- .../_post/createCandidature/index.ts | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts b/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts index 7c9d5f987..d615a37bf 100644 --- a/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts +++ b/src/routes/campaigns/campaignId/candidates/_post/createCandidature/index.ts @@ -5,23 +5,8 @@ export default async ( campaignId: number, selectedDevice: number ) => { - const isCandidate = await tryber.tables.WpCrowdAppqHasCandidate.do() - .select() - .where("user_id", wpId) - .where("campaign_id", campaignId); - - if (isCandidate.length) { - await tryber.tables.WpCrowdAppqHasCandidate.do() - .update({ - accepted: 1, - selected_device: selectedDevice, - accepted_date: tryber.fn.now(), - results: 0, - }) - .where("user_id", wpId) - .where("campaign_id", campaignId); - } else { - await tryber.tables.WpCrowdAppqHasCandidate.do().insert({ + await tryber.tables.WpCrowdAppqHasCandidate.do() + .insert({ user_id: wpId, campaign_id: campaignId, accepted: 1, @@ -30,8 +15,15 @@ export default async ( selected_device: selectedDevice, group_id: 1, accepted_date: tryber.fn.now(), + }) + .onConflict(["user_id", "campaign_id"]) + .merge({ + accepted: 1, + selected_device: selectedDevice, + accepted_date: tryber.fn.now(), + results: 0, }); - } + return { wordpress_id: wpId, campaign_id: campaignId, From 357466192cfa455aa525a2e6f168da3b0e717198 Mon Sep 17 00:00:00 2001 From: "it@app-quality.com" Date: Mon, 14 Oct 2024 10:23:02 +0200 Subject: [PATCH 03/18] Modified 2 files --- .stoplight/styleguide.json | 89 ++++++++++++++++++++++++++++++-------- src/reference/openapi.yml | 81 +++++++++++++++++----------------- 2 files changed, 111 insertions(+), 59 deletions(-) diff --git a/.stoplight/styleguide.json b/.stoplight/styleguide.json index 9da2bc295..fca135622 100644 --- a/.stoplight/styleguide.json +++ b/.stoplight/styleguide.json @@ -13,25 +13,9 @@ ], "aliases": {}, "rules": {}, - "extendedStyleguides": [ - { - "id": "cHJqOjEyMzU4Ng", - "name": "Stoplight Style Guide", - "slug": "stoplight-style-guide", - "workspace": { - "slug": "apistylebook", - "name": "API Stylebook" - }, - "icon": "robot", - "color": "#3898ff", - "description": "Default rules for Stoplight projects", - "latestRelease": { - "release": 31 - } - } - ], "inheritedRules": [ { + "id": "ev_7eYY_fvMC93DmNzqEa", "given": [ "#API_Contact" ], @@ -46,6 +30,7 @@ "message": "Contact object should have \"url\"." }, { + "id": "aHOnvrUi0BMNBQUPLXPYO", "given": [ "#API_Contact" ], @@ -60,6 +45,7 @@ "message": "Contact object should have \"email\"" }, { + "id": "rpuLynhbduRhXu-4Z9HUe", "given": [ "#API_Document" ], @@ -74,6 +60,7 @@ "message": "Info object should have \"contact\" object." }, { + "id": "M_L3UJTUZsN8K4RmUlNUW", "given": [ "#API_Document" ], @@ -88,6 +75,7 @@ "message": "Info object should have \"description\" object." }, { + "id": "FLyyqhfcGuyYb08kPF3Fo", "given": [ "#API_Document" ], @@ -102,6 +90,7 @@ "message": "Info object should have \"license\" object." }, { + "id": "Do9d2t_iEl15N8JY8h7gY", "given": [ "#API_License" ], @@ -116,6 +105,7 @@ "message": "License object should include \"url\"." }, { + "id": "mB0C1J_eJEA3KSXM7zTIO", "given": [ "#All_Markdown" ], @@ -132,6 +122,7 @@ "message": "Markdown descriptions must not have \"eval(\"." }, { + "id": "O9hO4N0qjeqmils9MQ3mW", "given": [ "#All_Markdown" ], @@ -148,6 +139,7 @@ "message": "Markdown descriptions must not have \"