From 311c69f7706cc843fb4b78ce8e219c6f1e7478d5 Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 10:02:38 +0200 Subject: [PATCH 1/9] feat(Cypress): :white_check_mark: implemented JWT retrieval, binaryTest --- cypress/integration/api.spec.js | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 cypress/integration/api.spec.js diff --git a/cypress/integration/api.spec.js b/cypress/integration/api.spec.js new file mode 100644 index 00000000..50dced03 --- /dev/null +++ b/cypress/integration/api.spec.js @@ -0,0 +1,81 @@ +/// + +describe("it test the api", () => { + let jsonWebToken = ""; + const apiUrl = "https://fhir-api.public.post-prod.lifen.fr" + + it("I have a JWT", () => { + + cy.request({ + url: "https://lifen-post-prod.eu.auth0.com/oauth/token", + method: "POST", + body: { + client_id: 'szVsMPaDPUdwqngGiLoHfXFT5XCYPFcy', + client_secret: 'sMp2PB-QWBZupCB4IXJrWDJ-7tlpUl09vQ2tMKdy049He7-g93ofbXz7ESlAc82B', + audience: 'post-prod-apis', + grant_type: 'client_credentials', + } + }).its('body').then((body) => { + jsonWebToken = body.access_token; + //cy.log(json_web_token); + expect(jsonWebToken).to.not.be.empty; + }); + + }); + + it("I have a the document #1615660", () => { + cy.request({ + url:`${apiUrl}/fhir/Binary/1615660`, + method:'GET', + headers: { + "Authorization" : `Bearer ${jsonWebToken}`, + "contet-type": "application/json", + "Prefer": "return=presentation" + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers["content-type"]).to.eq("application/pdf"); + }) + }); + + it("I prepare the DocumentReference", () => { + cy.request({ + url:`${apiUrl}/fhir/DocumentReference`, + method:'POST', + headers: { + "Authorization" : `Bearer ${jsonWebToken}`, + "contet-type": "application/json", + "Prefer": "return=presentation" + }, + body: { + "status": "current", + "docStatus": "final", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "34109-9", + "display": "Document médical" + } + ] + }, + "indexed": "2021-02-11T09:25:39Z", + "description": "aelgain-copiepatient.pdf", + "content": [ + { + "attachment": { + "contentType": "application/pdf", + "url": "Binary/1615660", + "title": "aelgain-copiepatient.pdf" + } + } + ], + "resourceType": "DocumentReference" + } + }).then(response => { + + }); + + + }); +}); -- 2.47.2 From facf129f65f08888d441608adad465aa2fc1ea6c Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 10:04:37 +0200 Subject: [PATCH 2/9] refactor(Cypress): Reordered test cases in the feature code file. --- cypress/integration/inbox/inbox.js | 58 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/cypress/integration/inbox/inbox.js b/cypress/integration/inbox/inbox.js index 38329078..d22e2946 100644 --- a/cypress/integration/inbox/inbox.js +++ b/cypress/integration/inbox/inbox.js @@ -1,32 +1,5 @@ /* global Given, When, Then */ -import { Given, When, Then, And } from "cypress-cucumber-preprocessor/steps"; - -describe("Connect to the mailbox", () => { - - Given("I log with my credentials", () => { - cy.visit('/'); - cy.get('#email').type("candidature-qa@example.org"); - cy.get('#password').type("kHwWawhH5ADNuFb"); - cy.get('#continueButton').click(); - }); - - And("I receive a code by SMS", () => { - cy.get("#challenge_mfa_form_candidate_otp").should("be.visible"); - }); - - When("I put the code", () => { - cy.wait(20000).then(() => { - cy.get('#validateButton').click(); - }); - }); - - Then("I am connected", () => { - cy.get("#account-menu div[title]").should((elm) => { - expect(elm).to.contain("candidature-qa@example.org") - }); - }); - -}) +import { Given, When, Then, And, Before } from "cypress-cucumber-preprocessor/steps"; describe("Send a document", () => { @@ -54,4 +27,31 @@ describe("Send a document", () => { //? }); -}); \ No newline at end of file +}); + +describe("Connect to the mailbox", () => { + + Given("I log with my credentials", () => { + cy.visit('/'); + cy.get('#email').type("candidature-qa@example.org"); + cy.get('#password').type("kHwWawhH5ADNuFb"); + cy.get('#continueButton').click(); + }); + + And("I receive a code by SMS", () => { + cy.get("#challenge_mfa_form_candidate_otp").should("be.visible"); + }); + + When("I put the code", () => { + cy.wait(20000).then(() => { + cy.get('#validateButton').click(); + }); + }); + + Then("I am connected", () => { + cy.get("#account-menu div[title]").should((elm) => { + expect(elm).to.contain("candidature-qa@example.org") + }); + }); + +}) -- 2.47.2 From 88c1226aaf480c9d9521dc058d3e021b66fedc1f Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 10:05:17 +0200 Subject: [PATCH 3/9] revert(Cypress): temporaly disabled feature test locally to debug the api testing --- cypress.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cypress.json b/cypress.json index 87c9f4a5..52122158 100644 --- a/cypress.json +++ b/cypress.json @@ -2,7 +2,5 @@ "baseUrl": "https://app.post-prod.lifen.fr", "env": { "MAILOSAUR_API_KEY": "your-key-here" - }, - "testFiles": "**/*.feature", - "ignoreTestFiles": "**/*.spec.js" + } } -- 2.47.2 From 84d3acdc7e81fd76aaaf39ae2156d4b1e0197933 Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 10:56:29 +0200 Subject: [PATCH 4/9] feat(Cypress): Implemented test step POST DocumentReference --- cypress/integration/api.spec.js | 110 ++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 12 deletions(-) diff --git a/cypress/integration/api.spec.js b/cypress/integration/api.spec.js index 50dced03..d945a071 100644 --- a/cypress/integration/api.spec.js +++ b/cypress/integration/api.spec.js @@ -2,7 +2,8 @@ describe("it test the api", () => { let jsonWebToken = ""; - const apiUrl = "https://fhir-api.public.post-prod.lifen.fr" + const apiUrl = "https://fhir-api.public.post-prod.lifen.fr"; + let documentReferenceId, communicationRequestId = ""; it("I have a JWT", () => { @@ -23,14 +24,14 @@ describe("it test the api", () => { }); - it("I have a the document #1615660", () => { + it.skip("I have a the document #1615660", () => { cy.request({ url:`${apiUrl}/fhir/Binary/1615660`, method:'GET', headers: { - "Authorization" : `Bearer ${jsonWebToken}`, - "contet-type": "application/json", - "Prefer": "return=presentation" + "authorization" : `Bearer ${jsonWebToken}`, + "content-type": "application/json", + "Prefer": "return=representation" } }).then((response) => { expect(response.status).to.eq(200); @@ -43,10 +44,11 @@ describe("it test the api", () => { url:`${apiUrl}/fhir/DocumentReference`, method:'POST', headers: { - "Authorization" : `Bearer ${jsonWebToken}`, - "contet-type": "application/json", - "Prefer": "return=presentation" + authorization : `Bearer ${jsonWebToken}`, + 'content-type': 'application/json', + "Prefer": "return=representation" }, + json: true, body: { "status": "current", "docStatus": "final", @@ -72,10 +74,94 @@ describe("it test the api", () => { ], "resourceType": "DocumentReference" } - }).then(response => { - + }).then((response) => { + expect(response.status).to.eq(201); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "DocumentReference"); + expect(response.body).to.have.property('id'); + documentReferenceId = response.body.id }); - - + //cy.log(documentReferenceId); }); + + it("I prepare the CommunicationRequest", () => { + cy.request({ + url: `${apiUrl}/fhir/CommunicationRequest`, + method: 'POST', + headers: { + authorization: `Bearer ${jsonWebToken}`, + 'content-type': 'application/json', + "Prefer": "return=representation" + }, + json: true, + body: { + "meta": { + "tag": [ + { + "system": "http://lifen.fr/fhir/tag/verified/sender", + "code": "SENDER_VERIFIED", + "display": "Sender is verified and should not be changed." + }, + { + "system": "http://lifen.fr/fhir/tag/processing/mode", + "code": "IMMEDIATE_MODE", + "display": "request should be treated in immediate mode" + }, + { + "system": "http://lifen.fr/fhir/CodeSystem/Resource/Tag/PatientAutomaticResending", + "code": "NONE", + "display": "Patient communication should not be resent" + } + ] + }, + "status": "draft", + "category": [ + { + "coding": [ + { + "system": "http://lifen.fr/fhir/CodeSystem/communication-category", + "code": "MEDICAL_REPORT" + } + ] + } + ], + "priority": "routine", + "payload": [ + { + "contentReference": { + "reference": `DocumentReference/${documentReferenceId}` + } + } + ], + "sender": { + "extension": [ + { + "url": "http://lifen.fr/fhir/StructureDefinition/Resource/Extension/Source", + "valueCode": "USER" + } + ], + "reference": "Organization/2" + }, + "requester": { + "agent": { + "extension": [ + { + "url": "http://lifen.fr/fhir/StructureDefinition/communicationrequest-requester-user-uuid", + "valueString": "ea07d7c6-ff4b-43fc-9765-e4235886d30c" + } + ], + "reference": "Organization/2" + } + }, + "resourceType": "CommunicationRequest" + } + }).then((response) => { + expect(response.status).to.eq(201); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "CommunicationRequest"); + expect(response.body).to.have.property('id'); + communicationRequestId = response.body.id + }); + }); + }); -- 2.47.2 From 7a751125aab6b33f23557c90d6c97cae9f832d82 Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 10:59:14 +0200 Subject: [PATCH 5/9] feat(Cypress): Implemented test step POST CommunicationRequest --- cypress/integration/api.spec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cypress/integration/api.spec.js b/cypress/integration/api.spec.js index d945a071..b8174ea7 100644 --- a/cypress/integration/api.spec.js +++ b/cypress/integration/api.spec.js @@ -160,8 +160,11 @@ describe("it test the api", () => { expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); expect(response.body).to.have.property("resourceType", "CommunicationRequest"); expect(response.body).to.have.property('id'); + expect(response.body).to.have.property('status', 'draft'); communicationRequestId = response.body.id }); }); + + }); -- 2.47.2 From 7e88cf0482cd8dfb01d116d29737356159018945 Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 11:13:58 +0200 Subject: [PATCH 6/9] feat(Cypress): Implemented test step GET CommunicationRequest --- cypress/integration/api.spec.js | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/cypress/integration/api.spec.js b/cypress/integration/api.spec.js index b8174ea7..b5df212f 100644 --- a/cypress/integration/api.spec.js +++ b/cypress/integration/api.spec.js @@ -3,7 +3,7 @@ describe("it test the api", () => { let jsonWebToken = ""; const apiUrl = "https://fhir-api.public.post-prod.lifen.fr"; - let documentReferenceId, communicationRequestId = ""; + let documentReferenceId, communicationRequestId, patientId = ""; it("I have a JWT", () => { @@ -24,13 +24,12 @@ describe("it test the api", () => { }); - it.skip("I have a the document #1615660", () => { + it("I have a the document #1615660", () => { cy.request({ url:`${apiUrl}/fhir/Binary/1615660`, method:'GET', headers: { "authorization" : `Bearer ${jsonWebToken}`, - "content-type": "application/json", "Prefer": "return=representation" } }).then((response) => { @@ -165,6 +164,26 @@ describe("it test the api", () => { }); }); + it("I fetch the CommunicationRequest after waiting 10sec for the IA to process it", () => { + cy.wait(10000); + cy.request({ + url: `${apiUrl}/fhir/CommunicationRequest/${communicationRequestId}`, + method: 'GET', + headers: { + authorization: `Bearer ${jsonWebToken}` + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "CommunicationRequest"); + expect(response.body).to.have.property('id'); + expect(response.body).to.have.property('status', 'suspended'); + expect(response.body).to.have.property('subject'); + expect(response.body).to.have.property('recipient'); + expect(response.body.subject).to.have.property('reference'); + patientId = response.body.subject.reference; + }); + }); }); -- 2.47.2 From 68acc2a949c6ba28fb5348fbcfc8dfd6ab9c8b15 Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 11:35:32 +0200 Subject: [PATCH 7/9] feat(Cypress): Implemented test step GET Patient --- cypress/integration/api.spec.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/cypress/integration/api.spec.js b/cypress/integration/api.spec.js index b5df212f..a75eefde 100644 --- a/cypress/integration/api.spec.js +++ b/cypress/integration/api.spec.js @@ -164,8 +164,11 @@ describe("it test the api", () => { }); }); - it("I fetch the CommunicationRequest after waiting 10sec for the IA to process it", () => { + it("I fetch the CommunicationRequest's PatientId after waiting 10 sec for the IA to process it", () => { cy.wait(10000); + // avec cypress-recurse, on surveille jusqu'a ce que l'IA ai finit son traitement ; plutot que d'attendre un temps arbitraire. + // import { recurse } from 'cypress-recurse' // a placer en début de fichier. + // recurse(() => cy.request(...), (response) => { expect(response.body).to.have.property('status', 'suspended') } ).then((response) => {...}) cy.request({ url: `${apiUrl}/fhir/CommunicationRequest/${communicationRequestId}`, method: 'GET', @@ -181,7 +184,23 @@ describe("it test the api", () => { expect(response.body).to.have.property('subject'); expect(response.body).to.have.property('recipient'); expect(response.body.subject).to.have.property('reference'); - patientId = response.body.subject.reference; + let patient = response.body.subject.reference; + patientId = patient.split("/")[1]; + }); + }); + + it("I get the Patient", () => { + cy.request({ + url: `${apiUrl}/fhir/Patient/${patientId}`, + method: 'GET', + headers: { + authorization: `Bearer ${jsonWebToken}` + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "Patient"); + expect(response.body).to.have.property('id', patientId); }); }); -- 2.47.2 From ed9a550d5e771cccfeba4b4e5537cfca6e42f31a Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 12:25:55 +0200 Subject: [PATCH 8/9] feat(Cypress-Gherkin): :sparkles: Implemented the whole test in cypress and updated documentation accordingly --- .vscode/settings.json | 3 +- README.md | 18 +- cypress.json | 4 +- cypress/fixtures/example.json | 5 - cypress/integration/api.spec.js | 208 ---------------- cypress/integration/inbox.feature | 3 +- cypress/integration/inbox.spec.js | 77 ------ cypress/integration/inbox/inbox.js | 2 +- cypress/integration/sendDocument.feature | 14 ++ .../integration/sendDocument/sendDocument.js | 230 ++++++++++++++++++ cypress/support/commands.js | 15 +- package.json | 7 +- 12 files changed, 269 insertions(+), 317 deletions(-) delete mode 100644 cypress/fixtures/example.json delete mode 100644 cypress/integration/api.spec.js delete mode 100644 cypress/integration/inbox.spec.js create mode 100644 cypress/integration/sendDocument.feature create mode 100644 cypress/integration/sendDocument/sendDocument.js diff --git a/.vscode/settings.json b/.vscode/settings.json index b4dec6a7..b7f5259c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "conventionalCommits.scopes": [ - "Cypress" + "Cypress", + "Cypress-Gherkin" ] } \ No newline at end of file diff --git a/README.md b/README.md index 90a479fc..7224b90f 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,23 @@ # Lifen Autotest Hangout with Simon Priet -Description +Please find in this project my hangout of your technical test. The test is performed with `cypress`, and include `cypress-cucumber-preprocessor`. This module process `.feature` files and find matching `.js` files to run them by cypress runner. I initially coded cypress to do the part 2 only, but took time to include the part one as well. Now cypress run the api to generate the communication with the document, then connect the user to send the mail. + +Currently, cypress is still challenged with a SMS code, and I have not implemented a workaround. Cypress wait 20 for me to put the code in the GUI, then continue. Please feel free to reconfigure your environment with your own phone number to try out. **However**, this automate can't be industrialized into a CI/CD pipeline. + +I fond 2 tools that can help us more: + +* [`cypress-recurse` 🌐](https://github.com/bahmutov/cypress-recurse) can retry several time a request until a certain condition is meet. This can help us wait for Irène to process the CommunicationRequest (`draft` → `suspended`), before going any further. +* [`cypress-mailosaur` 🌐](https://mailosaur.com/docs/frameworks-and-tools/cypress/) is a mail and text provided that can help us read texts content sent by the server to a predefined phone number, and work around the text code challenge. # Installation -The code has been written with VSC in mind, so a launch.json is available to help run and debug the softwares. No helpers are available for other IDE. +The code has been written with VSC in mind, on a Windows 10 machine, so a launch.json is available to help run and debug the softwares. No helpers are available for other IDE. 1. Clone the repo to your local computer. You will need the following requierement: * Node.js 16 * Git -2. In VS code, run `Test Cypress via NPM`. The `Launch.json` file will trigger the `test` script configured in the `package.json`. -5. Then, type `npm run test` to launch the script via CLI. \ No newline at end of file +2. Open a terminal in your project folder +2. Purge the `node_module` folder ( `rm -rf ./node_modules/`) +3. Run `npm install` to reinstall cypress and it's dependences according to your OS's environment. npm will use the `package.json` to find what to do. +2. Type `npm run test` to launch the script. In VS code, run `Test Cypress via NPM` from the *Run and Debug* tab. The `Launch.json` file will trigger the `test` script configured in the `package.json`. +6. On the cypress GUI, select `sendDocument` for the throughout test, and `inbox` for some subtests in the Inbox website. \ No newline at end of file diff --git a/cypress.json b/cypress.json index 52122158..87c9f4a5 100644 --- a/cypress.json +++ b/cypress.json @@ -2,5 +2,7 @@ "baseUrl": "https://app.post-prod.lifen.fr", "env": { "MAILOSAUR_API_KEY": "your-key-here" - } + }, + "testFiles": "**/*.feature", + "ignoreTestFiles": "**/*.spec.js" } diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json deleted file mode 100644 index 6cd3360c..00000000 --- a/cypress/fixtures/example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "login": "candidature-qa@example.org", - "mdp": "kHwWawhH5ADNuFb", - "phone": "0643779588" -} diff --git a/cypress/integration/api.spec.js b/cypress/integration/api.spec.js deleted file mode 100644 index a75eefde..00000000 --- a/cypress/integration/api.spec.js +++ /dev/null @@ -1,208 +0,0 @@ -/// - -describe("it test the api", () => { - let jsonWebToken = ""; - const apiUrl = "https://fhir-api.public.post-prod.lifen.fr"; - let documentReferenceId, communicationRequestId, patientId = ""; - - it("I have a JWT", () => { - - cy.request({ - url: "https://lifen-post-prod.eu.auth0.com/oauth/token", - method: "POST", - body: { - client_id: 'szVsMPaDPUdwqngGiLoHfXFT5XCYPFcy', - client_secret: 'sMp2PB-QWBZupCB4IXJrWDJ-7tlpUl09vQ2tMKdy049He7-g93ofbXz7ESlAc82B', - audience: 'post-prod-apis', - grant_type: 'client_credentials', - } - }).its('body').then((body) => { - jsonWebToken = body.access_token; - //cy.log(json_web_token); - expect(jsonWebToken).to.not.be.empty; - }); - - }); - - it("I have a the document #1615660", () => { - cy.request({ - url:`${apiUrl}/fhir/Binary/1615660`, - method:'GET', - headers: { - "authorization" : `Bearer ${jsonWebToken}`, - "Prefer": "return=representation" - } - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers["content-type"]).to.eq("application/pdf"); - }) - }); - - it("I prepare the DocumentReference", () => { - cy.request({ - url:`${apiUrl}/fhir/DocumentReference`, - method:'POST', - headers: { - authorization : `Bearer ${jsonWebToken}`, - 'content-type': 'application/json', - "Prefer": "return=representation" - }, - json: true, - body: { - "status": "current", - "docStatus": "final", - "type": { - "coding": [ - { - "system": "http://loinc.org", - "code": "34109-9", - "display": "Document médical" - } - ] - }, - "indexed": "2021-02-11T09:25:39Z", - "description": "aelgain-copiepatient.pdf", - "content": [ - { - "attachment": { - "contentType": "application/pdf", - "url": "Binary/1615660", - "title": "aelgain-copiepatient.pdf" - } - } - ], - "resourceType": "DocumentReference" - } - }).then((response) => { - expect(response.status).to.eq(201); - expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); - expect(response.body).to.have.property("resourceType", "DocumentReference"); - expect(response.body).to.have.property('id'); - documentReferenceId = response.body.id - }); - //cy.log(documentReferenceId); - }); - - it("I prepare the CommunicationRequest", () => { - cy.request({ - url: `${apiUrl}/fhir/CommunicationRequest`, - method: 'POST', - headers: { - authorization: `Bearer ${jsonWebToken}`, - 'content-type': 'application/json', - "Prefer": "return=representation" - }, - json: true, - body: { - "meta": { - "tag": [ - { - "system": "http://lifen.fr/fhir/tag/verified/sender", - "code": "SENDER_VERIFIED", - "display": "Sender is verified and should not be changed." - }, - { - "system": "http://lifen.fr/fhir/tag/processing/mode", - "code": "IMMEDIATE_MODE", - "display": "request should be treated in immediate mode" - }, - { - "system": "http://lifen.fr/fhir/CodeSystem/Resource/Tag/PatientAutomaticResending", - "code": "NONE", - "display": "Patient communication should not be resent" - } - ] - }, - "status": "draft", - "category": [ - { - "coding": [ - { - "system": "http://lifen.fr/fhir/CodeSystem/communication-category", - "code": "MEDICAL_REPORT" - } - ] - } - ], - "priority": "routine", - "payload": [ - { - "contentReference": { - "reference": `DocumentReference/${documentReferenceId}` - } - } - ], - "sender": { - "extension": [ - { - "url": "http://lifen.fr/fhir/StructureDefinition/Resource/Extension/Source", - "valueCode": "USER" - } - ], - "reference": "Organization/2" - }, - "requester": { - "agent": { - "extension": [ - { - "url": "http://lifen.fr/fhir/StructureDefinition/communicationrequest-requester-user-uuid", - "valueString": "ea07d7c6-ff4b-43fc-9765-e4235886d30c" - } - ], - "reference": "Organization/2" - } - }, - "resourceType": "CommunicationRequest" - } - }).then((response) => { - expect(response.status).to.eq(201); - expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); - expect(response.body).to.have.property("resourceType", "CommunicationRequest"); - expect(response.body).to.have.property('id'); - expect(response.body).to.have.property('status', 'draft'); - communicationRequestId = response.body.id - }); - }); - - it("I fetch the CommunicationRequest's PatientId after waiting 10 sec for the IA to process it", () => { - cy.wait(10000); - // avec cypress-recurse, on surveille jusqu'a ce que l'IA ai finit son traitement ; plutot que d'attendre un temps arbitraire. - // import { recurse } from 'cypress-recurse' // a placer en début de fichier. - // recurse(() => cy.request(...), (response) => { expect(response.body).to.have.property('status', 'suspended') } ).then((response) => {...}) - cy.request({ - url: `${apiUrl}/fhir/CommunicationRequest/${communicationRequestId}`, - method: 'GET', - headers: { - authorization: `Bearer ${jsonWebToken}` - } - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); - expect(response.body).to.have.property("resourceType", "CommunicationRequest"); - expect(response.body).to.have.property('id'); - expect(response.body).to.have.property('status', 'suspended'); - expect(response.body).to.have.property('subject'); - expect(response.body).to.have.property('recipient'); - expect(response.body.subject).to.have.property('reference'); - let patient = response.body.subject.reference; - patientId = patient.split("/")[1]; - }); - }); - - it("I get the Patient", () => { - cy.request({ - url: `${apiUrl}/fhir/Patient/${patientId}`, - method: 'GET', - headers: { - authorization: `Bearer ${jsonWebToken}` - } - }).then((response) => { - expect(response.status).to.eq(200); - expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); - expect(response.body).to.have.property("resourceType", "Patient"); - expect(response.body).to.have.property('id', patientId); - }); - }); - - -}); diff --git a/cypress/integration/inbox.feature b/cypress/integration/inbox.feature index 212cd922..1d1c04b8 100644 --- a/cypress/integration/inbox.feature +++ b/cypress/integration/inbox.feature @@ -1,7 +1,8 @@ Feature: Send a document that is ready As a practiciant, I can send mails that i have prepared - Scenario: Send a document + + Scenario: Send a prepared document Given I am connected to my mailbox And I have a document ready to send When I send the mail diff --git a/cypress/integration/inbox.spec.js b/cypress/integration/inbox.spec.js deleted file mode 100644 index 49b87f46..00000000 --- a/cypress/integration/inbox.spec.js +++ /dev/null @@ -1,77 +0,0 @@ -/// -context('The login page', () => { - - describe.skip('Test the login page', () => { - - it('Access the webpage', function() { - cy.visit('/login'); - cy.get('#email').should("have.attr", "type", "email"); - cy.get('#password').should("have.attr", "type", "password"); - //cy.get('#password').type(mdp); - }); - - it('Log a malformed email', function() { - cy.visit('/login'); - cy.get('#email').type("not an email"); - cy.get('#password').type("somepasseword {enter}"); - cy.url().should('include', 'login?'); - }); - - it('Log an unexisting user', function() { - cy.visit('/login'); - cy.get('#email').type("toto@yopmail.com"); - cy.get('#password').type("somepasseword {enter}"); - cy.get('#error-message').should("have.class", "alert alert-danger").should("be.visible"); - }); - - }); - - /* describe("It send an SMS", function() { - it('Log the candidate user', function(){ - cy.visit('/'); - cy.get('#email').type("candidature-qa@example.org"); - cy.get('#password').type("kHwWawhH5ADNuFb"); - cy.get('#continueButton').click(); - - cy.mailosaurGetMessage(serverId, { - sentTo: smsNumber - }).as('sms'); - - cy.wait(10000).then(() => { - cy.get('#validateButton').click(); - }); - - - }); - }); - */ -}); - -context("The inbox page", function() { - describe("It check the inbox content", function() { - before(() => { - cy.visit('/'); - cy.get('#email').type("candidature-qa@example.org"); - cy.get('#password').type("kHwWawhH5ADNuFb"); - cy.get('#continueButton').click(); - cy.wait(20000).then(() => { - cy.get('#validateButton').click(); - }); - }); - - it("It load the inbox page of a valid user", ()=> { - cy.visit("/request"); - cy.get("#dashboard-dropzone tr:first-child td").eq(1).click(); - cy.get("#sending-button").click(); - }); - - it("It checks for messages in the inbox", () => { - - }); - - it("Open the message for data that has been injected previously", () => { - - }); - - }); -}); \ No newline at end of file diff --git a/cypress/integration/inbox/inbox.js b/cypress/integration/inbox/inbox.js index d22e2946..14d4af3d 100644 --- a/cypress/integration/inbox/inbox.js +++ b/cypress/integration/inbox/inbox.js @@ -1,7 +1,7 @@ /* global Given, When, Then */ import { Given, When, Then, And, Before } from "cypress-cucumber-preprocessor/steps"; -describe("Send a document", () => { +describe("Send a prepared document", () => { Given("I am connected to my mailbox", () => { cy.visit('/'); diff --git a/cypress/integration/sendDocument.feature b/cypress/integration/sendDocument.feature new file mode 100644 index 00000000..d4f38870 --- /dev/null +++ b/cypress/integration/sendDocument.feature @@ -0,0 +1,14 @@ +Feature: Prepare and Send the document #1615660 + + As a practiciant, I can prepare a document to send to my colleague and be helped by Irène to fill contextual data. + + Scenario: Send a document + Given I use the API + And I have the document #1615660 + And I have a DocumentReference + And I have a CommunicationRequest + And Irène prepared the CommunicationRequest + And I have a Patient + And I am connected to my mailbox + When I send the mail + Then the mail is sent \ No newline at end of file diff --git a/cypress/integration/sendDocument/sendDocument.js b/cypress/integration/sendDocument/sendDocument.js new file mode 100644 index 00000000..42e2e852 --- /dev/null +++ b/cypress/integration/sendDocument/sendDocument.js @@ -0,0 +1,230 @@ +/* global Given, When, Then */ +import { Given, When, Then, And, Before } from "cypress-cucumber-preprocessor/steps"; + +describe("Send a document", () => { + const apiUrl = "https://fhir-api.public.post-prod.lifen.fr"; + let jsonWebToken, documentReferenceId, communicationRequestId, patientId = ""; + + Given("I use the API", () => { + cy.request({ + url: "https://lifen-post-prod.eu.auth0.com/oauth/token", + method: "POST", + body: { + client_id: 'szVsMPaDPUdwqngGiLoHfXFT5XCYPFcy', + client_secret: 'sMp2PB-QWBZupCB4IXJrWDJ-7tlpUl09vQ2tMKdy049He7-g93ofbXz7ESlAc82B', + audience: 'post-prod-apis', + grant_type: 'client_credentials', + } + }).its('body').then((body) => { + jsonWebToken = body.access_token; + //cy.log(json_web_token); + expect(jsonWebToken).to.not.be.empty; + }); + }) + + And("I have the document #1615660", () => { + + cy.request({ + url: `${apiUrl}/fhir/Binary/1615660`, + method: 'GET', + headers: { + "authorization": `Bearer ${jsonWebToken}`, + "Prefer": "return=representation" + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers["content-type"]).to.eq("application/pdf"); + }); + }); + + And("I have a DocumentReference", () => { + cy.request({ + url: `${apiUrl}/fhir/DocumentReference`, + method: 'POST', + headers: { + authorization: `Bearer ${jsonWebToken}`, + 'content-type': 'application/json', + "Prefer": "return=representation" + }, + json: true, + body: { + "status": "current", + "docStatus": "final", + "type": { + "coding": [ + { + "system": "http://loinc.org", + "code": "34109-9", + "display": "Document médical" + } + ] + }, + "indexed": "2021-02-11T09:25:39Z", + "description": "aelgain-copiepatient.pdf", + "content": [ + { + "attachment": { + "contentType": "application/pdf", + "url": "Binary/1615660", + "title": "aelgain-copiepatient.pdf" + } + } + ], + "resourceType": "DocumentReference" + } + }).then((response) => { + expect(response.status).to.eq(201); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "DocumentReference"); + expect(response.body).to.have.property('id'); + documentReferenceId = response.body.id + }); + }); + + And("I have a CommunicationRequest", () => { + cy.request({ + url: `${apiUrl}/fhir/CommunicationRequest`, + method: 'POST', + headers: { + authorization: `Bearer ${jsonWebToken}`, + 'content-type': 'application/json', + "Prefer": "return=representation" + }, + json: true, + body: { + "meta": { + "tag": [ + { + "system": "http://lifen.fr/fhir/tag/verified/sender", + "code": "SENDER_VERIFIED", + "display": "Sender is verified and should not be changed." + }, + { + "system": "http://lifen.fr/fhir/tag/processing/mode", + "code": "IMMEDIATE_MODE", + "display": "request should be treated in immediate mode" + }, + { + "system": "http://lifen.fr/fhir/CodeSystem/Resource/Tag/PatientAutomaticResending", + "code": "NONE", + "display": "Patient communication should not be resent" + } + ] + }, + "status": "draft", + "category": [ + { + "coding": [ + { + "system": "http://lifen.fr/fhir/CodeSystem/communication-category", + "code": "MEDICAL_REPORT" + } + ] + } + ], + "priority": "routine", + "payload": [ + { + "contentReference": { + "reference": `DocumentReference/${documentReferenceId}` + } + } + ], + "sender": { + "extension": [ + { + "url": "http://lifen.fr/fhir/StructureDefinition/Resource/Extension/Source", + "valueCode": "USER" + } + ], + "reference": "Organization/2" + }, + "requester": { + "agent": { + "extension": [ + { + "url": "http://lifen.fr/fhir/StructureDefinition/communicationrequest-requester-user-uuid", + "valueString": "ea07d7c6-ff4b-43fc-9765-e4235886d30c" + } + ], + "reference": "Organization/2" + } + }, + "resourceType": "CommunicationRequest" + } + }).then((response) => { + expect(response.status).to.eq(201); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "CommunicationRequest"); + expect(response.body).to.have.property('id'); + expect(response.body).to.have.property('status', 'draft'); + communicationRequestId = response.body.id + }); + }); + + And("Irène prepared the CommunicationRequest", () => { + cy.wait(10000); + // avec cypress-recurse, on surveille jusqu'a ce que l'IA ai finit son traitement ; plutot que d'attendre un temps arbitraire. + // import { recurse } from 'cypress-recurse' // a placer en début de fichier. + // recurse(() => cy.request(...), (response) => { expect(response.body).to.have.property('status', 'suspended') } ).then((response) => {...}) + cy.request({ + url: `${apiUrl}/fhir/CommunicationRequest/${communicationRequestId}`, + method: 'GET', + headers: { + authorization: `Bearer ${jsonWebToken}` + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "CommunicationRequest"); + expect(response.body).to.have.property('id'); + expect(response.body).to.have.property('status', 'suspended'); + expect(response.body).to.have.property('subject'); + expect(response.body).to.have.property('recipient'); + expect(response.body.subject).to.have.property('reference'); + let patient = response.body.subject.reference; + patientId = patient.split("/")[1]; + }); + }); + + And("I have a Patient", () => { + cy.request({ + url: `${apiUrl}/fhir/Patient/${patientId}`, + method: 'GET', + headers: { + authorization: `Bearer ${jsonWebToken}` + } + }).then((response) => { + expect(response.status).to.eq(200); + expect(response.headers["content-type"]).to.eq("application/fhir+json;charset=UTF-8"); + expect(response.body).to.have.property("resourceType", "Patient"); + expect(response.body).to.have.property('id', patientId); + }); + }); + + And("I am connected to my mailbox", () => { + cy.visit('/'); + cy.get('#email').type("candidature-qa@example.org"); + cy.get('#password').type("kHwWawhH5ADNuFb"); + cy.get('#continueButton').click(); + cy.wait(20000).then(() => { + cy.get('#validateButton').click(); + }); + cy.visit("/request"); + + }); + + When("I send the mail", () => { + // Il n'y a pas de moyen fiable de lier la communicationRequestId que l'on a préparer avec l'une des entrée listée. + // Il y a bien un code LT-xxxxxxx, mais il faudrais un moyen d'atteindre de le modèle stoquée dans la vue + cy.get("#dashboard-dropzone tr:first-child td").eq(1).click(); + cy.get("#sending-button").click(); + }); + + Then("the mail is sent", () => { + //? + // On peux essayer d'attendre une requete de repondre un status + // On peux attendre la notification "Envoie du document réussit" + }); + +}); \ No newline at end of file diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 616480fe..66ea16ef 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -22,17 +22,4 @@ // // // -- This will overwrite an existing command -- -// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) -import 'cypress-mailosaur'; - - -Cypress.Commands.add('TokenLogin', (token) => { - const autorisation = `bearer ${ token }`; - cy.request({ - method:'POST', - url:'/request', - headers: { - autorisation, - } - }); -}) +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file diff --git a/package.json b/package.json index 1c040fbb..86f5bc2f 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,8 @@ "description": "run cypress end-2-end tests against post-prod.lifen.fr", "main": "index.js", "dependencies": { - "cypress": "^8.3.1" - }, - "devDependencies": { - "cypress-cucumber-preprocessor": "^4.2.0", - "cypress-mailosaur": "^2.3.3" + "cypress": "^8.3.1", + "cypress-cucumber-preprocessor": "^4.2.0" }, "cypress-cucumber-preprocessor": { "nonGlobalStepDefinitions": true -- 2.47.2 From e4179787de7d5dc397cfe0938817ecf66eb12d02 Mon Sep 17 00:00:00 2001 From: Simon Priet Date: Wed, 8 Sep 2021 12:36:30 +0200 Subject: [PATCH 9/9] refactor(Cypress-Gherkin): :white_check_mark: Added a test expect to check that we are correctly connect after login. --- cypress/integration/sendDocument/sendDocument.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cypress/integration/sendDocument/sendDocument.js b/cypress/integration/sendDocument/sendDocument.js index 42e2e852..7f55f2fe 100644 --- a/cypress/integration/sendDocument/sendDocument.js +++ b/cypress/integration/sendDocument/sendDocument.js @@ -211,7 +211,9 @@ describe("Send a document", () => { cy.get('#validateButton').click(); }); cy.visit("/request"); - + cy.get("#account-menu div[title]").should((elm) => { + expect(elm).to.contain("candidature-qa@example.org") + }); }); When("I send the mail", () => { -- 2.47.2