-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(stage3e2de): formulaire de candidature (backend) (#2573)
* feat(stage3e2de): recuperer les label metiers par appellationCodes - repo * feat(stage3e2de): récupérer les appelations metiers par appelations code - usecase * feat(stage3e2de): récupérer les appelations metiers par appellation code - controller WIP * feat(stage3e2de): envoyer candidature (back) * feat(stage3e2de): passer le mapping du wording de mode de contact vers le front * feat(stage3eme): enum ModeDeContact * feat(stage3eme): ajout données dans objet stage3eme2de * fix(stage3e2de): test controller renommage handler en pagesHandler * fix: retour review * fix: retour review * refacto(stage3eme): fix import --------- Co-authored-by: Suxue LI <[email protected]>
- Loading branch information
Showing
25 changed files
with
863 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
...mponents/features/Stages3eEt2de/Rechercher/FormulaireRecherche/getModeDeContactWording.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { ModeDeContact } from '~/server/stage-3e-et-2de/domain/candidatureStage3eEt2de'; | ||
|
||
export function getModeDeContactWording(modeDeContact: ModeDeContact): string | undefined { | ||
switch (modeDeContact) { | ||
case ModeDeContact.IN_PERSON: | ||
return 'Candidature en personne'; | ||
case ModeDeContact.EMAIL: | ||
return 'Candidature par e-mail'; | ||
case ModeDeContact.PHONE: | ||
return 'Candidature par téléphone'; | ||
default: | ||
return undefined; | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
src/pages/api/stages-3e-et-2de/candidature/index.controller.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { testApiHandler } from 'next-test-api-route-handler'; | ||
import nock from 'nock'; | ||
|
||
import handler from '~/pages/api/stages-3e-et-2de/candidature/index.controller'; | ||
import { ModeDeContact } from '~/server/stage-3e-et-2de/domain/candidatureStage3eEt2de'; | ||
import { aCandidatureStage3eEt2de } from '~/server/stage-3e-et-2de/domain/candidatureStage3eEt2de.fixture'; | ||
import { | ||
anApiImmersionFacileStage3eEt2deCandidature, | ||
} from '~/server/stage-3e-et-2de/infra/repositories/apiImmersionFacileStage3eEt2de.fixture'; | ||
|
||
describe('candidature stage 3e et 2de', () => { | ||
it('envoie une candidature', async () => { | ||
// Given | ||
const candidature = aCandidatureStage3eEt2de(); | ||
|
||
nock('https://staging.immersion-facile.beta.gouv.fr/api/v2', { | ||
reqheaders: { Authorization: 'API_IMMERSION_FACILE_STAGE_3EME_API_KEY' }, | ||
}) | ||
.post('/contact-establishment', | ||
{ ...anApiImmersionFacileStage3eEt2deCandidature() }) | ||
.reply(201); | ||
|
||
// When | ||
await testApiHandler({ | ||
pagesHandler: (req, res) => handler(req, res), | ||
params: { ...candidature }, | ||
test: async ({ fetch }) => { | ||
const response = await fetch({ | ||
body: JSON.stringify(candidature), | ||
method: 'POST', | ||
}); | ||
|
||
// Then | ||
expect(response.status).toBe(200); | ||
}, | ||
url: '/stages-3e-et-2de/candidature', | ||
}); | ||
}); | ||
|
||
it.each([ | ||
{ modeDeContact: 'invalid' }, | ||
{ appellationCode: undefined }, | ||
{ email: 1 }, | ||
])('répond une 400 quand le paramètre %o est incorrect', async (candidature) => { | ||
// When | ||
await testApiHandler({ | ||
pagesHandler: (req, res) => handler(req, res), | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-expect-error | ||
params: { ...aCandidatureStage3eEt2de(candidature) }, | ||
test: async ({ fetch }) => { | ||
const response = await fetch({ | ||
body: JSON.stringify(candidature), | ||
method: 'POST', | ||
}); | ||
|
||
// Then | ||
expect(response.status).toBe(400); | ||
}, | ||
url: '/stages-3e-et-2de/candidature', | ||
}); | ||
}); | ||
|
||
it.each([ | ||
{ modeDeContact: ModeDeContact.PHONE }, | ||
{ modeDeContact: ModeDeContact.EMAIL }, | ||
{ modeDeContact: ModeDeContact.IN_PERSON }, | ||
{ otherQuery: 'otherQuery' }, | ||
])('répond une 200 quand le paramètre %o est correct', async (candidature) => { | ||
// Given | ||
nock('https://staging.immersion-facile.beta.gouv.fr/api/v2', { | ||
reqheaders: { Authorization: 'API_IMMERSION_FACILE_STAGE_3EME_API_KEY' }, | ||
}) | ||
.post('/contact-establishment', | ||
{ ...anApiImmersionFacileStage3eEt2deCandidature(candidature.modeDeContact ? { contactMode: candidature.modeDeContact } : {}) }) | ||
.reply(201); | ||
|
||
// When | ||
await testApiHandler({ | ||
pagesHandler: (req, res) => handler(req, res), | ||
params: { ...aCandidatureStage3eEt2de(candidature) }, | ||
test: async ({ fetch }) => { | ||
const response = await fetch({ | ||
body: JSON.stringify(candidature), | ||
method: 'POST', | ||
}); | ||
|
||
// Then | ||
expect(response.status).toBe(200); | ||
}, | ||
url: '/stages-3e-et-2de/candidature', | ||
}); | ||
}); | ||
}); |
41 changes: 41 additions & 0 deletions
41
src/pages/api/stages-3e-et-2de/candidature/index.controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Joi from 'joi'; | ||
import { NextApiRequest, NextApiResponse } from 'next'; | ||
|
||
import { withMonitoring } from '~/pages/api/middlewares/monitoring/monitoring.middleware'; | ||
import { withValidation } from '~/pages/api/middlewares/validation/validation.middleware'; | ||
import { ErrorHttpResponse } from '~/pages/api/utils/response/response.type'; | ||
import { handleResponse } from '~/pages/api/utils/response/response.util'; | ||
import { | ||
CandidatureStage3eEt2de, | ||
ModeDeContact, | ||
} from '~/server/stage-3e-et-2de/domain/candidatureStage3eEt2de'; | ||
import { dependencies } from '~/server/start'; | ||
|
||
export const envoyerCandidatureStage3eEt2deQuerySchema = Joi.object({ | ||
appellationCode: Joi.string().required(), | ||
email: Joi.string().email().required(), | ||
modeDeContact: Joi.string().valid(...Object.values(ModeDeContact)).required(), | ||
nom: Joi.string().required(), | ||
prenom: Joi.string().required(), | ||
siret: Joi.string().required(), | ||
}).options({ allowUnknown: true }); | ||
|
||
export async function envoyerCandidatureStage3eEt2deHandler(req: NextApiRequest, res: NextApiResponse<undefined | ErrorHttpResponse>) { | ||
const candidature = mapCandidature(req); | ||
const reponseEnvoieCandidature = await dependencies.stage3eEt2deDependencies.envoyerCandidatureStage3eEt2deUseCase.handle(candidature); | ||
return handleResponse(reponseEnvoieCandidature, res); | ||
} | ||
|
||
export default withMonitoring(withValidation({ query: envoyerCandidatureStage3eEt2deQuerySchema }, envoyerCandidatureStage3eEt2deHandler)); | ||
|
||
function mapCandidature(req: NextApiRequest): CandidatureStage3eEt2de { | ||
const query = req.query; | ||
return { | ||
appellationCode: String(query.appellationCode), | ||
email: String(query.email), | ||
modeDeContact: ModeDeContact[query.modeDeContact as keyof typeof ModeDeContact], | ||
nom: String(query.nom), | ||
prenom: String(query.prenom), | ||
siret: String(query.siret), | ||
}; | ||
} |
Oops, something went wrong.