From f4a6ea28655abf8b370d158b1a11d08eccfa79cd Mon Sep 17 00:00:00 2001 From: HangLe Date: Fri, 8 Jan 2021 16:38:00 +0200 Subject: [PATCH 01/11] Add test for Analysis object Fill form and check Summary amount of objects --- cypress/integration/app.spec.js | 88 +++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-) diff --git a/cypress/integration/app.spec.js b/cypress/integration/app.spec.js index 3010c975..8e01faf3 100644 --- a/cypress/integration/app.spec.js +++ b/cypress/integration/app.spec.js @@ -19,7 +19,7 @@ describe("Basic e2e", function () { cy.get("textarea[name='description']").type("Test description") cy.get("button[type=button]").contains("Next").click() - // Fill a study form and submit object + // Fill a Study form and submit object cy.get("div[role=button]").contains("Study").click() cy.get("div[role=button]").contains("Fill Form").click() cy.get("input[name='descriptor.studyTitle']").type("Test title") @@ -27,7 +27,7 @@ describe("Basic e2e", function () { cy.get("button[type=submit]").contains("Submit").click() cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 1) - // Upload an xml file. + // Upload a Study xml file. cy.get("div[role=button]").contains("Upload XML File").click() cy.fixture("study_test.xml").then(fileContent => { cy.get('input[type="file"]').attachFile({ @@ -40,11 +40,91 @@ describe("Basic e2e", function () { // Hacky way to get past RHF watch -method problem that doesn't allow cypress to get updated value for file cy.get("form").submit() - // Saved objects list should have newly added item + // Saved objects list should have newly added item from Study object cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 2) - // // Navigate to summary and publish + // Fill an Analysis form and submit object + cy.get("div[role=button]") + .contains("Analysis") + .then($analysis => { + $analysis.click() + cy.get("div").contains("Fill Form").click() + }) + + cy.get("form").within(() => { + // Experiment + cy.get("input[name='experimentRef.accessionId']").type("Experiement Test Accession Id") + cy.get("input[name='experimentRef.identifiers.submitterId.namespace']").type("Experiement Test Namespace") + cy.get("input[name='experimentRef.identifiers.submitterId.value']").type("Experiement Test Value") + + // Study + cy.get("input[name='studyRef.accessionId']").type("Study Test Accession Id") + cy.get("input[name='studyRef.identifiers.submitterId.namespace']").type("Study Test Namespace") + cy.get("input[name='studyRef.identifiers.submitterId.value']").type("Study Test Value") + + // Sample + cy.get("input[name='sampleRef.accessionId']").type("Sample Test Accession Id") + cy.get("input[name='sampleRef.identifiers.submitterId.namespace']").type("Sample Test Namespace") + cy.get("input[name='sampleRef.identifiers.submitterId.value']").type("Sample Test Value") + + // Run + cy.get("input[name='runRef.accessionId']").type("Run Test Accession Id") + cy.get("input[name='runRef.identifiers.submitterId.namespace']").type("Run Test Namespace") + cy.get("input[name='runRef.identifiers.submitterId.value']").type("Run Test Value") + + // Analysis + cy.get("input[name='analysisRef.accessionId']").type("Analysis Test Accession Id") + cy.get("input[name='analysisRef.identifiers.submitterId.namespace']").type("Analysis Test Namespace") + cy.get("input[name='analysisRef.identifiers.submitterId.value']").type("Analysis Test Value") + + cy.get("h3") + .contains("Reference Alignment") + .parent("div.formSection") + .within(() => { + cy.get("button").contains("Add new item").click() + cy.get("input[name='analysisType.referenceAlignment.sequence[0].accessionId']").type("Reference Accession Id") + }) + + cy.get("h3") + .contains("Sequence Variation") + .parent("div.formSection") + .within(() => { + cy.get("input[name='analysisType.sequenceVariation.assembly.standard.accessionId']").type( + "Sequence Standard Accession Id" + ) + cy.get("button").contains("Add new item").click() + cy.get("input[name='analysisType.sequenceVariation.sequence[0].accessionId']").type( + "Squence Sequence Accession Id" + ) + }) + + cy.get("h3") + .contains("Processed Reads") + .parent("div.formSection") + .within(() => { + cy.get("input[name='analysisType.processedReads.assembly.standard.accessionId']").type( + "Processed Standard Accession Id" + ) + cy.get("button").contains("Add new item").click() + + cy.get("input[name='analysisType.processedReads.sequence[0].accessionId']").type( + "Processed Sequence Accession Id" + ) + }) + cy.root().submit() + }) + + // Saved objects list should have newly added item from Analysis object + cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 1) + + // Navigate to summary cy.get("button[type=button]").contains("Next").click() + + // Check the amount of submitted objects in each object type + cy.get("h6").contains("Study").parent("div").children().eq(1).should("have.text", 2) + cy.get("h6").contains("Analysis").parent("div").children().eq(1).should("have.text", 1) + + // Navigate to publish cy.get("button[type=button]").contains("Publish").click() cy.get('button[aria-label="Publish folder contents and move to frontpage"]').contains("Publish").click() }) From 73c5dabd615c67cb47b301cd3f5c41da200b55b6 Mon Sep 17 00:00:00 2001 From: HangLe Date: Fri, 8 Jan 2021 21:25:57 +0200 Subject: [PATCH 02/11] Try to fix Fill form error --- cypress/integration/app.spec.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cypress/integration/app.spec.js b/cypress/integration/app.spec.js index 8e01faf3..bfed0e8a 100644 --- a/cypress/integration/app.spec.js +++ b/cypress/integration/app.spec.js @@ -6,7 +6,7 @@ describe("Basic e2e", function () { cy.get('[alt="CSC Login"]').click() }) - it("should create new folder, add study form and publish folder", () => { + it("should create new folder, add Study form, upload Study XML file, add Analysis form and publish folder", () => { cy.visit(baseUrl) cy.get('[alt="CSC Login"]').click() cy.visit(baseUrl + "newdraft") @@ -44,12 +44,8 @@ describe("Basic e2e", function () { cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 2) // Fill an Analysis form and submit object - cy.get("div[role=button]") - .contains("Analysis") - .then($analysis => { - $analysis.click() - cy.get("div").contains("Fill Form").click() - }) + cy.get("div[role=button]").contains("Analysis").click() + cy.get("div[role=button]").contains("Fill Form").click() cy.get("form").within(() => { // Experiment From 8e35b7dda5f9fd87e0e2d55511dd54b0d506bf81 Mon Sep 17 00:00:00 2001 From: HangLe Date: Mon, 11 Jan 2021 10:42:18 +0200 Subject: [PATCH 03/11] Fix for Fill Form button not clicking --- cypress/integration/app.spec.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cypress/integration/app.spec.js b/cypress/integration/app.spec.js index bfed0e8a..813096af 100644 --- a/cypress/integration/app.spec.js +++ b/cypress/integration/app.spec.js @@ -45,7 +45,10 @@ describe("Basic e2e", function () { // Fill an Analysis form and submit object cy.get("div[role=button]").contains("Analysis").click() - cy.get("div[role=button]").contains("Fill Form").click() + cy.get("div[role=button]") + .contains("Fill Form") + .should("be.visible") + .then($btn => $btn.click()) cy.get("form").within(() => { // Experiment From b4d408d09a4750501bdc6314cd1e347df3446ef3 Mon Sep 17 00:00:00 2001 From: Hang Le Date: Mon, 11 Jan 2021 11:45:17 +0200 Subject: [PATCH 04/11] Fix Experiment typos Co-authored-by: Stefan Negru --- cypress/integration/app.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/integration/app.spec.js b/cypress/integration/app.spec.js index 813096af..c950593f 100644 --- a/cypress/integration/app.spec.js +++ b/cypress/integration/app.spec.js @@ -52,9 +52,9 @@ describe("Basic e2e", function () { cy.get("form").within(() => { // Experiment - cy.get("input[name='experimentRef.accessionId']").type("Experiement Test Accession Id") - cy.get("input[name='experimentRef.identifiers.submitterId.namespace']").type("Experiement Test Namespace") - cy.get("input[name='experimentRef.identifiers.submitterId.value']").type("Experiement Test Value") + cy.get("input[name='experimentRef.accessionId']").type("Experiment Test Accession Id") + cy.get("input[name='experimentRef.identifiers.submitterId.namespace']").type("Experiment Test Namespace") + cy.get("input[name='experimentRef.identifiers.submitterId.value']").type("Experiment Test Value") // Study cy.get("input[name='studyRef.accessionId']").type("Study Test Accession Id") From 38274e627c2d8cfe3bde4759092ec21f531026cf Mon Sep 17 00:00:00 2001 From: Stefan Negru Date: Mon, 11 Jan 2021 18:08:40 +0200 Subject: [PATCH 05/11] update packages especially apisauce --- package-lock.json | 157 ++++++++++++++++++++-------------------------- package.json | 12 ++-- 2 files changed, 73 insertions(+), 96 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4e3c6c2..206a96f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2704,9 +2704,9 @@ } }, "@testing-library/dom": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.28.1.tgz", - "integrity": "sha512-acv3l6kDwZkQif/YqJjstT3ks5aaI33uxGNVIQmdKzbZ2eMKgg3EV2tB84GDdc72k3Kjhl6mO8yUt6StVIdRDg==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.2.tgz", + "integrity": "sha512-CBMELfyY1jKdtLcSRmEnZWRzRkCRVSNPTzhzrn8wY8OnzUo7Pe/W+HgLzt4TDnWIPYeusHBodf9wUjJF48kPmA==", "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -2719,17 +2719,17 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "requires": { "@babel/highlight": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" }, "@babel/highlight": { "version": "7.10.4", @@ -2869,9 +2869,9 @@ } }, "@testing-library/react": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.2.tgz", - "integrity": "sha512-jaxm0hwUjv+hzC+UFEywic7buDC9JQ1q3cDsrWVSDAPmLotfA6E6kUHlYm/zOeGCac6g48DR36tFHxl7Zb+N5A==", + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.3.tgz", + "integrity": "sha512-BirBUGPkTW28ULuCwIbYo0y2+0aavHczBT6N9r3LrsswEW3pg25l1wgoE7I8QBIy1upXWkwKpYdWY7NYYP0Bxw==", "requires": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^7.28.1" @@ -3689,11 +3689,11 @@ } }, "apisauce": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-1.1.2.tgz", - "integrity": "sha512-AqOrOVk71JPSqugA6PdrkE2S0w1GC/f3xPZPMHJ1O+Z73pwT2uoGnr8JbfmB/gvO2cnygYzlBOnkD/mN6W1FMQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-2.0.1.tgz", + "integrity": "sha512-mJBw3pKmtfVoP6oifnf7/iRJQtNkVb6GkYsVOXN2pidootj1mhGBtzYHOX9FVBzAz5QV2GMu8IJtiNIgZ44kHQ==", "requires": { - "axios": "^0.19.0", + "axios": "^0.21.1", "ramda": "^0.25.0" } }, @@ -3988,34 +3988,11 @@ "integrity": "sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ==" }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "1.5.10" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "follow-redirects": "^1.10.0" } }, "axobject-query": { @@ -6073,9 +6050,9 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, "cypress": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-6.2.0.tgz", - "integrity": "sha512-m/rkcogYM9MTy8rbsZgyS5wT2L/J+B5V2bY2ztkDNMyqhk/oZgUF4KTWVLzkW2I+scg0iAddca95tLlt7XnAtw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-6.2.1.tgz", + "integrity": "sha512-OYkSgzA4J4Q7eMjZvNf5qWpBLR4RXrkqjL3UZ1UzGGLAskO0nFTi/RomNTG6TKvL3Zp4tw4zFY1gp5MtmkCZrA==", "dev": true, "requires": { "@cypress/listr-verbose-renderer": "^0.4.1", @@ -7470,9 +7447,9 @@ } }, "eslint-plugin-prettier": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz", - "integrity": "sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -8325,12 +8302,12 @@ } }, "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, "requires": { - "semver-regex": "^2.0.0" + "semver-regex": "^3.1.2" } }, "flat-cache": { @@ -9171,18 +9148,18 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" }, "husky": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.6.tgz", - "integrity": "sha512-o6UjVI8xtlWRL5395iWq9LKDyp/9TE7XMOTvIpEVzW638UcGxTmV5cfel6fsk/jbZSTlvfGVJf2svFtybcIZag==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.7.tgz", + "integrity": "sha512-0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqjw==", "dev": true, "requires": { "chalk": "^4.0.0", "ci-info": "^2.0.0", "compare-versions": "^3.6.0", "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", + "find-versions": "^4.0.0", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" @@ -9223,12 +9200,12 @@ "dev": true }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, @@ -9239,38 +9216,32 @@ "dev": true }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9278,12 +9249,12 @@ "dev": true }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^5.0.0" } }, "supports-color": { @@ -15629,9 +15600,9 @@ "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" }, "react-hook-form": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.14.0.tgz", - "integrity": "sha512-yj4aqASmyxFPyDtDLKBae+AazFv5vcC5CEpDlh1+r5k5BTH/J/CTG6q0H5lSinm0B0F6P7oTmXIYB75ZmuQz6g==" + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.14.1.tgz", + "integrity": "sha512-Bf2fWcL2F34hUUqrx1rpgZ8ZErQ4/DvrPs6Je+lUYL59km8PXIQqyCTz/NbggC1RQUj7rChSmTx6eFap+mCttw==" }, "react-is": { "version": "16.13.1", @@ -16626,9 +16597,9 @@ "dev": true }, "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", + "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", "dev": true }, "send": { @@ -20056,6 +20027,12 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 4e2b3291..f886e147 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,14 @@ "@material-ui/lab": "^4.0.0-alpha.57", "@reduxjs/toolkit": "^1.5.0", "@testing-library/jest-dom": "^5.11.8", - "@testing-library/react": "^11.1.1", + "@testing-library/react": "^11.2.3", "ajv": "^6.12.6", - "apisauce": "^1.1.2", + "apisauce": "^2.0.1", "jest-environment-jsdom-sixteen": "^1.0.3", "lodash": "^4.17.20", "react": "^16.14.0", "react-dom": "^16.14.0", - "react-hook-form": "^6.14.0", + "react-hook-form": "^6.14.1", "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "^4.0.0" @@ -57,17 +57,17 @@ "devDependencies": { "@testing-library/user-event": "^12.6.0", "concurrently": "^5.3.0", - "cypress": "^6.2.0", + "cypress": "^6.2.1", "cypress-file-upload": "^4.1.1", "eslint-config-prettier": "^6.15.0", "eslint-plugin-cypress": "^2.11.2", "eslint-plugin-flowtype": "^5.2.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jest": "^24.1.3", - "eslint-plugin-prettier": "^3.3.0", + "eslint-plugin-prettier": "^3.3.1", "flow-bin": "^0.126.1", "http-proxy-middleware": "^1.0.6", - "husky": "^4.3.6", + "husky": "^4.3.7", "jest-environment-jsdom-sixteen": "^1.0.3", "prettier": "^2.2.1", "redux-mock-store": "^1.5.4", From fd328def01e52fa5c1973d51e3ade4205f743e42 Mon Sep 17 00:00:00 2001 From: Liisa Lado-Villar <47525503+lilachic@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:32:49 +0200 Subject: [PATCH 06/11] remove warnings caused by wrong error type in folder creation --- .../NewDraftWizard/WizardSteps/WizardCreateFolderStep.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js b/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js index 4d8d9bb7..979da4da 100644 --- a/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js +++ b/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js @@ -63,7 +63,7 @@ const CreateFolderForm = ({ createFolderFormRef }: { createFolderFormRef: Create fullWidth inputRef={register({ required: true, validate: { name: value => value.length > 0 } })} helperText={errors.name ? "Please give a name for folder." : null} - error={errors.name} + error={errors.name ? true : false} disabled={isSubmitting} defaultValue={folder ? folder.name : ""} > @@ -76,7 +76,7 @@ const CreateFolderForm = ({ createFolderFormRef }: { createFolderFormRef: Create rows={5} inputRef={register({ required: true, validate: { description: value => value.length > 0 } })} helperText={errors.description ? "Please give a description for folder." : null} - error={errors.description} + error={errors.description ? true : false} disabled={isSubmitting} defaultValue={folder ? folder.description : ""} > From 0a706c5336c71658911092b1bc4c36e2625f358b Mon Sep 17 00:00:00 2001 From: saulipurhonen Date: Mon, 4 Jan 2021 10:42:46 +0200 Subject: [PATCH 07/11] Draft listing with draft continue and delete functiontality --- .gitignore | 1 + src/__tests__/WizardDraftObjectPicker.test.js | 40 ++++++ .../WizardFillObjectDetailsForm.test.js | 8 +- .../WizardComponents/WizardAddObjectCard.js | 11 +- .../WizardComponents/WizardAlert.js | 69 ++++++--- .../WizardDraftObjectPicker.js | 118 +++++++++++++++ .../WizardComponents/WizardObjectIndex.js | 5 +- .../WizardSavedObjectsList.js | 2 +- .../WizardFillObjectDetailsForm.js | 134 ++++++++++++------ .../WizardSteps/WizardCreateFolderStep.js | 10 +- src/features/wizardSubmissionFolderSlice.js | 31 +++- src/services/draftAPI.js | 8 ++ src/setupTests.js | 4 +- 13 files changed, 356 insertions(+), 85 deletions(-) create mode 100644 src/__tests__/WizardDraftObjectPicker.test.js create mode 100644 src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js diff --git a/.gitignore b/.gitignore index c7a69e95..b69a434e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ yarn-error.log* # IDE settings .idea/ +.vscode/ diff --git a/src/__tests__/WizardDraftObjectPicker.test.js b/src/__tests__/WizardDraftObjectPicker.test.js new file mode 100644 index 00000000..85b3e5b4 --- /dev/null +++ b/src/__tests__/WizardDraftObjectPicker.test.js @@ -0,0 +1,40 @@ +import React from "react" + +import "@testing-library/jest-dom/extend-expect" +import { render, screen } from "@testing-library/react" +import { Provider } from "react-redux" +import configureStore from "redux-mock-store" +import { toMatchDiffSnapshot } from "snapshot-diff" + +import WizardDraftObjectPicker from "../components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker" + +const mockStore = configureStore([]) + +expect.extend({ toMatchDiffSnapshot }) + +describe("WizardStepper", () => { + const store = mockStore({ + objectType: "study", + submissionType: "existing", + submissionFolder: { + description: "AWD", + id: "FOL90524783", + name: "Testname", + published: false, + drafts: [ + { accessionId: "TESTID1", schema: "draft-study" }, + { accessionId: "TESTID2", schema: "draft-study" }, + { accessionId: "TESTID3", schema: "draft-sample" }, + ], + }, + }) + + it("should have drafts listed for selected object type", async () => { + render( + + + + ) + expect(screen.getAllByRole("button")).toHaveLength(4) + }) +}) diff --git a/src/__tests__/WizardFillObjectDetailsForm.test.js b/src/__tests__/WizardFillObjectDetailsForm.test.js index 0f3ba226..b0b2ad24 100644 --- a/src/__tests__/WizardFillObjectDetailsForm.test.js +++ b/src/__tests__/WizardFillObjectDetailsForm.test.js @@ -41,9 +41,9 @@ describe("WizardFillObjectDetailsForm", () => { }, }) - localStorage.setItem(`cached_study_schema`, JSON.stringify(schema)) + sessionStorage.setItem(`cached_study_schema`, JSON.stringify(schema)) - it("should create study form from schema in localstorage", async () => { + it("should create study form from schema in sessionStorage", async () => { render( @@ -53,8 +53,8 @@ describe("WizardFillObjectDetailsForm", () => { expect(screen.getByText("Study Description")).toBeDefined() }) - // Note: If this test runs before form creation, form creation fails because getItem spy messes localstorage init somehow - it("should call localstorage", async () => { + // Note: If this test runs before form creation, form creation fails because getItem spy messes sessionStorage init somehow + it("should call sessionStorage", async () => { const spy = jest.spyOn(Storage.prototype, "getItem") render( diff --git a/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js b/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js index 3e17b4f0..5f9b9820 100644 --- a/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js +++ b/src/components/NewDraftWizard/WizardComponents/WizardAddObjectCard.js @@ -8,6 +8,7 @@ import CardHeader from "@material-ui/core/CardHeader" import { makeStyles } from "@material-ui/core/styles" import { useDispatch, useSelector } from "react-redux" +import WizardDraftObjectPicker from "components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker" import WizardFillObjectDetailsForm from "components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm" import WizardUploadObjectXMLForm from "components/NewDraftWizard/WizardForms/WizardUploadObjectXMLForm" import { resetObjectType } from "features/wizardObjectTypeSlice" @@ -28,7 +29,7 @@ const useStyles = makeStyles(theme => ({ marginTop: "-4px", marginBottom: "-4px", }, - cardContent: { + cardCenterContent: { flexGrow: 1, display: "flex", justifyContent: "center", @@ -97,15 +98,17 @@ const WizardAddObjectCard = () => { testId: "xml", }, existing: { - title: "Choose existing object", - component:
Not implemented yet
, + title: "Choose from drafts", + component: , testId: "existing", }, } return ( - {cards[submissionType]["component"]} + + {cards[submissionType]["component"]} + ) } diff --git a/src/components/NewDraftWizard/WizardComponents/WizardAlert.js b/src/components/NewDraftWizard/WizardComponents/WizardAlert.js index 98648a01..767f6a59 100644 --- a/src/components/NewDraftWizard/WizardComponents/WizardAlert.js +++ b/src/components/NewDraftWizard/WizardComponents/WizardAlert.js @@ -10,6 +10,7 @@ import DialogTitle from "@material-ui/core/DialogTitle" import Alert from "@material-ui/lab/Alert" import { useDispatch, useSelector } from "react-redux" +import { resetDraftStatus } from "features/draftStatusSlice" import { setAlert, resetAlert } from "features/wizardAlertSlice" import { resetDraftObject } from "features/wizardDraftObjectSlice" import { updateStatus } from "features/wizardStatusMessageSlice" @@ -17,8 +18,8 @@ import { addObjectToDrafts } from "features/wizardSubmissionFolderSlice" import draftAPIService from "services/draftAPI" // Simple template for error messages -const ErrorMessage = () => { - return Connection error, cannot save draft. +const ErrorMessage = message => { + return {message} } /* @@ -39,31 +40,53 @@ const CancelFormDialog = ({ const draftObject = useSelector(state => state.draftObject) const objectType = useSelector(state => state.objectType) const [error, setError] = useState(false) + const [errorMessage, setErrorMessage] = useState("") const dispatch = useDispatch() - // Draft save logic. Get response depending on submission type + // Draft save logic const saveDraft = async () => { setError(false) - const response = await draftAPIService.createFromJSON(objectType, draftObject) - dispatch( - updateStatus({ - successStatus: "success", - response: response, - errorPrefix: "", - }) - ) - - if (response.ok) { - dispatch( - addObjectToDrafts(submissionFolder.id, { - accessionId: response.data.accessionId, - schema: objectType, - }) - ) - dispatch(resetDraftObject()) - handleDialog(true) + const err = "Connection error, cannot save draft." + if (draftObject.draftId) { + const response = await draftAPIService.patchFromJSON(objectType, draftObject.draftId, draftObject) + if (response.ok) { + dispatch(resetDraftStatus()) + dispatch( + updateStatus({ + successStatus: "success", + response: response, + errorPrefix: "", + }) + ) + dispatch(resetDraftObject()) + handleDialog(true) + } else { + setError(true) + setErrorMessage(err) + } } else { - setError(true) + const response = await draftAPIService.createFromJSON(objectType, draftObject) + if (response.ok) { + dispatch( + updateStatus({ + successStatus: "success", + response: response, + errorPrefix: "", + }) + ) + dispatch(resetDraftStatus()) + dispatch( + addObjectToDrafts(submissionFolder.id, { + accessionId: response.data.accessionId, + schema: "draft-" + objectType, + }) + ) + dispatch(resetDraftObject()) + handleDialog(true) + } else { + setError(true) + setErrorMessage(err) + } } } @@ -233,7 +256,7 @@ const CancelFormDialog = ({ {dialogContent} - {error && } + {error && } {dialogActions} ) diff --git a/src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js b/src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js new file mode 100644 index 00000000..1485ffb8 --- /dev/null +++ b/src/components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker.js @@ -0,0 +1,118 @@ +//@flow +import React, { useState } from "react" + +import Button from "@material-ui/core/Button" +import ButtonGroup from "@material-ui/core/ButtonGroup" +import List from "@material-ui/core/List" +import ListItem from "@material-ui/core/ListItem" +import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction" +import ListItemText from "@material-ui/core/ListItemText" +import { makeStyles } from "@material-ui/core/styles" +import { useSelector, useDispatch } from "react-redux" + +import WizardStatusMessageHandler from "../WizardForms/WizardStatusMessageHandler" + +import { setDraftObject } from "features/wizardDraftObjectSlice" +import { deleteObjectFromFolder } from "features/wizardSubmissionFolderSlice" +import { setSubmissionType } from "features/wizardSubmissionTypeSlice" +import draftAPIService from "services/draftAPI" + +const useStyles = makeStyles(theme => ({ + objectList: { + padding: "0 1rem", + width: "100%", + }, + objectListItems: { + border: "none", + borderRadius: 3, + margin: theme.spacing(1, 0), + boxShadow: "0px 3px 10px -5px rgba(0,0,0,0.49)", + alignItems: "flex-start", + padding: ".5rem", + }, + buttonContinue: { + color: "#007bff", + }, + buttonDelete: { + color: "#dc3545", + }, +})) + +/** + * List drafts by submission type. Enables fetch and deletion of drafts + */ +const WizardDraftObjectPicker = () => { + const classes = useStyles() + const dispatch = useDispatch() + const objectType = useSelector(state => state.objectType) + const folder = useSelector(state => state.submissionFolder) + const currentObjectTypeDrafts = folder.drafts.filter(draft => draft.schema === "draft-" + objectType) + + const [connError, setConnError] = useState(false) + const [responseError, setResponseError] = useState({}) + const [errorPrefix, setErrorPrefix] = useState("") + + const handleObjectContinue = async objectId => { + setConnError(false) + const response = await draftAPIService.getObjectByAccessionId(objectType, objectId) + if (response.ok) { + dispatch(setDraftObject(response.data)) + dispatch(setSubmissionType("form")) + } else { + setConnError(true) + setResponseError(response) + setErrorPrefix("Draft fetching error.") + } + } + + const handleObjectDelete = objectId => { + setConnError(false) + dispatch(deleteObjectFromFolder("draft", objectId, objectType)).catch(error => { + setConnError(true) + setResponseError(JSON.parse(error)) + setErrorPrefix("Can't delete draft") + }) + } + + return ( +
+ {currentObjectTypeDrafts.length > 0 ? ( + + {currentObjectTypeDrafts.map(submission => { + return ( + + + + + + + + + + ) + })} + + ) : ( +

No {objectType} drafts.

+ )} + + {connError && ( + + )} +
+ ) +} + +export default WizardDraftObjectPicker diff --git a/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js b/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js index 5d694951..b4c71837 100644 --- a/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js +++ b/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js @@ -16,6 +16,7 @@ import { useDispatch, useSelector } from "react-redux" import WizardAlert from "./WizardAlert" import { resetDraftStatus } from "features/draftStatusSlice" +import { resetDraftObject } from "features/wizardDraftObjectSlice" import { setObjectType } from "features/wizardObjectTypeSlice" import { setSubmissionType } from "features/wizardSubmissionTypeSlice" @@ -116,7 +117,7 @@ const SubmissionTypeList = ({ const submissionTypeMap = { form: "Fill Form", xml: "Upload XML File", - existing: "Choose existing object", + existing: "Choose from drafts", } const classes = useStyles() @@ -169,6 +170,7 @@ const WizardObjectIndex = () => { } const handleSubmissionTypeChange = (submissionType: string) => { + dispatch(resetDraftObject()) if (currentSubmissionType === "") { dispatch(setSubmissionType(submissionType)) dispatch(setObjectType(expandedObjectType)) @@ -177,6 +179,7 @@ const WizardObjectIndex = () => { setClickedSubmissionType(submissionType) setCancelFormOpen(true) } else { + dispatch(resetDraftObject()) dispatch(resetDraftStatus()) dispatch(setSubmissionType(submissionType)) dispatch(setObjectType(expandedObjectType)) diff --git a/src/components/NewDraftWizard/WizardComponents/WizardSavedObjectsList.js b/src/components/NewDraftWizard/WizardComponents/WizardSavedObjectsList.js index 69b5994b..d3706bdf 100644 --- a/src/components/NewDraftWizard/WizardComponents/WizardSavedObjectsList.js +++ b/src/components/NewDraftWizard/WizardComponents/WizardSavedObjectsList.js @@ -75,7 +75,7 @@ const WizardSavedObjectsList = ({ submissionType, submissions }: { submissionTyp const handleObjectDelete = objectId => { setConnError(false) - dispatch(deleteObjectFromFolder(objectId, objectType)).catch(error => { + dispatch(deleteObjectFromFolder("submitted", objectId, objectType)).catch(error => { setConnError(true) setResponseError(JSON.parse(error)) setErrorPrefix("Can't delete object") diff --git a/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js b/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js index 741d867d..f7a41e05 100644 --- a/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js +++ b/src/components/NewDraftWizard/WizardForms/WizardFillObjectDetailsForm.js @@ -18,7 +18,7 @@ import WizardStatusMessageHandler from "./WizardStatusMessageHandler" import { setDraftStatus, resetDraftStatus } from "features/draftStatusSlice" import { setDraftObject } from "features/wizardDraftObjectSlice" import { updateStatus } from "features/wizardStatusMessageSlice" -import { addObjectToFolder, addObjectToDrafts } from "features/wizardSubmissionFolderSlice" +import { addObjectToFolder, addObjectToDrafts, deleteObjectFromFolder } from "features/wizardSubmissionFolderSlice" import draftAPIService from "services/draftAPI" import objectAPIService from "services/objectAPI" import schemaAPIService from "services/schemaAPI" @@ -81,33 +81,45 @@ type FormContentProps = { } /* - * Return react-hook-form based form which is rendered from schema and checked against resolver + * Return react-hook-form based form which is rendered from schema and checked against resolver. Set default values when continuing draft */ const FormContent = ({ resolver, formSchema, onSubmit, objectType, folderId }: FormContentProps) => { const classes = useStyles() - const methods = useForm({ mode: "onBlur", resolver }) const draftStatus = useSelector(state => state.draftStatus) + const draftObject = useSelector(state => state.draftObject) + const alert = useSelector(state => state.alert) + const methods = useForm({ mode: "onBlur", resolver, defaultValues: draftObject }) const dispatch = useDispatch() const [cleanedValues, setCleanedValues] = useState({}) + const [currentDraftId, setCurrentDraftId] = useState(draftObject?.accessionId) const [timer, setTimer] = useState(0) const increment = useRef(null) - const alert = useSelector(state => state.alert) const resetForm = () => { methods.reset() } + const checkDirty = () => { + if (methods.formState.isDirty && draftStatus === "") { + dispatch(setDraftStatus("notSaved")) + } + } + useEffect(() => { - methods.formState.isDirty ? dispatch(setDraftStatus("notSaved")) : dispatch(resetDraftStatus()) + checkDirty() }, [methods.formState.isDirty]) const handleChange = () => { - setCleanedValues(JSONSchemaParser.cleanUpFormValues(methods.getValues())) - dispatch(setDraftObject(cleanedValues)) + const values = JSONSchemaParser.cleanUpFormValues(methods.getValues()) + setCleanedValues(values) + dispatch(setDraftObject(Object.assign(values, { draftId: currentDraftId }))) + checkDirty() + } - if (methods.formState.isDirty && draftStatus === "") { - dispatch(setDraftStatus("notSaved")) - } + const handleDraftDelete = draftId => { + dispatch(deleteObjectFromFolder("draft", draftId, objectType)) + setCurrentDraftId(() => null) + handleChange() } /* @@ -137,33 +149,65 @@ const FormContent = ({ resolver, formSchema, onSubmit, objectType, folderId }: F }, []) const saveDraft = async () => { - const response = await draftAPIService.createFromJSON(objectType, cleanedValues) - if (response.ok) { - dispatch(resetDraftStatus()) - dispatch( - addObjectToDrafts(folderId, { - accessionId: response.data.accessionId, - schema: objectType, - }) - ) - .then(() => { - dispatch( - updateStatus({ - successStatus: "success", - response: response, - errorPrefix: "", - }) - ) - }) - .catch(error => { - dispatch( - updateStatus({ - successStatus: "error", - response: error, - errorPrefix: "Cannot connect to folder API", - }) - ) - }) + handleReset() + if (currentDraftId || draftObject.accessionId) { + const response = await draftAPIService.patchFromJSON(objectType, currentDraftId, cleanedValues) + if (response.ok) { + dispatch(resetDraftStatus()) + dispatch( + updateStatus({ + successStatus: "success", + response: response, + errorPrefix: "", + }) + ) + } else { + dispatch( + updateStatus({ + successStatus: "error", + response: response, + errorPrefix: "Unexpected error", + }) + ) + } + } else { + const response = await draftAPIService.createFromJSON(objectType, cleanedValues) + if (response.ok) { + setCurrentDraftId(response.data.accessionId) + dispatch(resetDraftStatus()) + dispatch( + addObjectToDrafts(folderId, { + accessionId: response.data.accessionId, + schema: "draft-" + objectType, + }) + ) + .then(() => { + dispatch( + updateStatus({ + successStatus: "success", + response: response, + errorPrefix: "", + }) + ) + }) + .catch(error => { + dispatch( + updateStatus({ + successStatus: "error", + response: error, + errorPrefix: "Cannot connect to folder API", + }) + ) + }) + } else { + dispatch( + updateStatus({ + successStatus: "error", + response: response, + errorPrefix: "Unexpected error", + }) + ) + } } } @@ -204,7 +248,17 @@ const FormContent = ({ resolver, formSchema, onSubmit, objectType, folderId }: F > Clear form - @@ -270,13 +324,13 @@ const WizardFillObjectDetailsForm = () => { */ useEffect(() => { const fetchSchema = async () => { - let schema = localStorage.getItem(`cached_${objectType}_schema`) + let schema = sessionStorage.getItem(`cached_${objectType}_schema`) if (!schema || !new Ajv().validateSchema(JSON.parse(schema))) { const response = await schemaAPIService.getSchemaByObjectType(objectType) setResponseInfo(response) if (response.ok) { schema = response.data - localStorage.setItem(`cached_${objectType}_schema`, JSON.stringify(schema)) + sessionStorage.setItem(`cached_${objectType}_schema`, JSON.stringify(schema)) } else { setError(true) setErrorPrefix("Unfortunately an error happened while catching form fields") diff --git a/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js b/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js index 4d8d9bb7..10590ad4 100644 --- a/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js +++ b/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js @@ -39,13 +39,13 @@ const CreateFolderForm = ({ createFolderFormRef }: { createFolderFormRef: Create const onSubmit = data => { setConnError(false) - if (folder) { - dispatch(updateNewDraftFolder(Object.assign({ ...data, folder }))).then(dispatch(increment())) + if (folder && (folder.name !== data.name || folder.description !== data.description)) { + dispatch(updateNewDraftFolder(folder.id, Object.assign({ ...data, folder }))) + .then(() => dispatch(increment())) + .catch(() => setConnError(true)) } else { dispatch(createNewDraftFolder(data)) - .then(() => { - dispatch(increment()) - }) + .then(() => dispatch(increment())) .catch(error => { setConnError(true) setResponseError(JSON.parse(error)) diff --git a/src/features/wizardSubmissionFolderSlice.js b/src/features/wizardSubmissionFolderSlice.js index 7594cb2e..022b8bec 100644 --- a/src/features/wizardSubmissionFolderSlice.js +++ b/src/features/wizardSubmissionFolderSlice.js @@ -3,6 +3,7 @@ import { createSlice } from "@reduxjs/toolkit" import _extend from "lodash/extend" import _reject from "lodash/reject" +import draftAPIService from "../services/draftAPI" import objectAPIService from "../services/objectAPI" import folderAPIService from "services/folderAPI" @@ -54,6 +55,7 @@ type ObjectInFolder = { accessionId: string, schema: string, } + type FolderNoId = { name: string, description: string, @@ -86,12 +88,27 @@ export const createNewDraftFolder = (folderDetails: FolderFromForm) => async (di }) } -export const updateNewDraftFolder = (folderDetails: FolderFromForm) => async (dispatch: any => void) => { +export const updateNewDraftFolder = (folderId: string, folderDetails: FolderFromForm) => async ( + dispatch: any => void +) => { const updatedFolder = _extend( { ...folderDetails.folder }, { name: folderDetails.name, description: folderDetails.description } ) - dispatch(setFolder(updatedFolder)) + const changes = [ + { op: "add", path: "/name", value: folderDetails.name }, + { op: "add", path: "/description", value: folderDetails.description }, + ] + const response = await folderAPIService.patchFolderById(folderId, changes) + + return new Promise((resolve, reject) => { + if (response.ok) { + dispatch(setFolder(updatedFolder)) + resolve(response) + } else { + reject(JSON.stringify(response)) + } + }) } export const addObjectToFolder = (folderID: string, objectDetails: ObjectInFolder) => async (dispatch: any => void) => { @@ -121,11 +138,15 @@ export const addObjectToDrafts = (folderID: string, objectDetails: ObjectInFolde }) } -export const deleteObjectFromFolder = (objectId: string, objectType: string) => async (dispatch: any => void) => { - const response = await objectAPIService.deleteObjectByAccessionId(objectType, objectId) +// Delete object from either metaDataObjects or drafts depending on savedType +export const deleteObjectFromFolder = (savedType: string, objectId: string, objectType: string) => async ( + dispatch: any => void +) => { + const service = savedType === "submitted" ? objectAPIService : draftAPIService + const response = await service.deleteObjectByAccessionId(objectType, objectId) return new Promise((resolve, reject) => { if (response.ok) { - dispatch(deleteObject(objectId)) + savedType === "submitted" ? dispatch(deleteObject(objectId)) : dispatch(deleteDraftObject(objectId)) resolve(response) } else { reject(JSON.stringify(response)) diff --git a/src/services/draftAPI.js b/src/services/draftAPI.js index 9780f46c..e62ee969 100644 --- a/src/services/draftAPI.js +++ b/src/services/draftAPI.js @@ -1,7 +1,10 @@ //@flow import { create } from "apisauce" +import { errorMonitor } from "./errorMonitor" + const api = create({ baseURL: "/drafts" }) +api.addMonitor(errorMonitor) const createFromJSON = async (objectType: string, JSONContent: any) => { return await api.post(`/${objectType}`, JSONContent) @@ -11,6 +14,10 @@ const getObjectByAccessionId = async (objectType: string, accessionId: string) = return await api.get(`/${objectType}/${accessionId}`) } +const patchFromJSON = async (objectType: string, accessionId: any, JSONContent: any) => { + return await api.patch(`/${objectType}/${accessionId}`, JSONContent) +} + const getAllObjectsByObjectType = async (objectType: string) => { return await api.get(`/${objectType}`) } @@ -22,6 +29,7 @@ const deleteObjectByAccessionId = async (objectType: string, accessionId: string export default { createFromJSON, getObjectByAccessionId, + patchFromJSON, getAllObjectsByObjectType, deleteObjectByAccessionId, } diff --git a/src/setupTests.js b/src/setupTests.js index 502e50cf..1b610624 100644 --- a/src/setupTests.js +++ b/src/setupTests.js @@ -1,6 +1,6 @@ -const localStorageMock = { +const sessionStorageMock = { getItem: jest.fn(), setItem: jest.fn(), clear: jest.fn(), } -global.localStorage = localStorageMock +global.sessionStorage = sessionStorageMock From bd8e422eada7a88b1b02800955b40b7d58d54257 Mon Sep 17 00:00:00 2001 From: Sauli Purhonen Date: Fri, 8 Jan 2021 10:20:12 +0200 Subject: [PATCH 08/11] Draft integration and E2E tests Draft integration and E2E tests Configure store with thunk Added draft testing Get badge values from schemas with 'draft-' prefix Test draft saving from dialog More convenient slice name More detailed comment on XML upload test Resolved conflict in E2E Try to fix Fill form error Fix for Fill Form button not clicking Fix Experiment typos Co-authored-by: Stefan Negru --- cypress/integration/app.spec.js | 93 +++++++++++++++++-- cypress/integration/draft.spec.js | 58 ++++++++++++ src/__tests__/WizardDraftObjectPicker.test.js | 7 +- src/__tests__/WizardObjectIndex.test.js | 8 +- src/__tests__/WizardSavedObjectsList.test.js | 2 +- .../WizardComponents/WizardObjectIndex.js | 7 +- src/features/wizardSubmissionFolderSlice.js | 2 +- 7 files changed, 159 insertions(+), 18 deletions(-) create mode 100644 cypress/integration/draft.spec.js diff --git a/cypress/integration/app.spec.js b/cypress/integration/app.spec.js index 3010c975..d99ec9ee 100644 --- a/cypress/integration/app.spec.js +++ b/cypress/integration/app.spec.js @@ -6,7 +6,7 @@ describe("Basic e2e", function () { cy.get('[alt="CSC Login"]').click() }) - it("should create new folder, add study form and publish folder", () => { + it("should create new folder, add Study form, upload Study XML file, add Analysis form and publish folder", () => { cy.visit(baseUrl) cy.get('[alt="CSC Login"]').click() cy.visit(baseUrl + "newdraft") @@ -19,15 +19,17 @@ describe("Basic e2e", function () { cy.get("textarea[name='description']").type("Test description") cy.get("button[type=button]").contains("Next").click() - // Fill a study form and submit object + // Fill a Study form and submit object cy.get("div[role=button]").contains("Study").click() cy.get("div[role=button]").contains("Fill Form").click() cy.get("input[name='descriptor.studyTitle']").type("Test title") cy.get("select[name='descriptor.studyType']").select("Metagenomics") + + // Submit form cy.get("button[type=submit]").contains("Submit").click() cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 1) - // Upload an xml file. + // Upload a Study xml file. cy.get("div[role=button]").contains("Upload XML File").click() cy.fixture("study_test.xml").then(fileContent => { cy.get('input[type="file"]').attachFile({ @@ -37,14 +39,93 @@ describe("Basic e2e", function () { force: true, }) }) - // Hacky way to get past RHF watch -method problem that doesn't allow cypress to get updated value for file + // Cypress doesn't allow form validation status to update and therefore "send" button is disabled cy.get("form").submit() - // Saved objects list should have newly added item + // Saved objects list should have newly added item from Study object cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 2) - // // Navigate to summary and publish + // Fill an Analysis form and submit object + cy.get("div[role=button]").contains("Analysis").click() + cy.get("div[role=button]") + .contains("Fill Form") + .should("be.visible") + .then($btn => $btn.click()) + + cy.get("form").within(() => { + // Experiment + cy.get("input[name='experimentRef.accessionId']").type("Experiment Test Accession Id") + cy.get("input[name='experimentRef.identifiers.submitterId.namespace']").type("Experiment Test Namespace") + cy.get("input[name='experimentRef.identifiers.submitterId.value']").type("Experiment Test Value") + + // Study + cy.get("input[name='studyRef.accessionId']").type("Study Test Accession Id") + cy.get("input[name='studyRef.identifiers.submitterId.namespace']").type("Study Test Namespace") + cy.get("input[name='studyRef.identifiers.submitterId.value']").type("Study Test Value") + + // Sample + cy.get("input[name='sampleRef.accessionId']").type("Sample Test Accession Id") + cy.get("input[name='sampleRef.identifiers.submitterId.namespace']").type("Sample Test Namespace") + cy.get("input[name='sampleRef.identifiers.submitterId.value']").type("Sample Test Value") + + // Run + cy.get("input[name='runRef.accessionId']").type("Run Test Accession Id") + cy.get("input[name='runRef.identifiers.submitterId.namespace']").type("Run Test Namespace") + cy.get("input[name='runRef.identifiers.submitterId.value']").type("Run Test Value") + + // Analysis + cy.get("input[name='analysisRef.accessionId']").type("Analysis Test Accession Id") + cy.get("input[name='analysisRef.identifiers.submitterId.namespace']").type("Analysis Test Namespace") + cy.get("input[name='analysisRef.identifiers.submitterId.value']").type("Analysis Test Value") + + cy.get("h3") + .contains("Reference Alignment") + .parent("div.formSection") + .within(() => { + cy.get("button").contains("Add new item").click() + cy.get("input[name='analysisType.referenceAlignment.sequence[0].accessionId']").type("Reference Accession Id") + }) + + cy.get("h3") + .contains("Sequence Variation") + .parent("div.formSection") + .within(() => { + cy.get("input[name='analysisType.sequenceVariation.assembly.standard.accessionId']").type( + "Sequence Standard Accession Id" + ) + cy.get("button").contains("Add new item").click() + cy.get("input[name='analysisType.sequenceVariation.sequence[0].accessionId']").type( + "Squence Sequence Accession Id" + ) + }) + + cy.get("h3") + .contains("Processed Reads") + .parent("div.formSection") + .within(() => { + cy.get("input[name='analysisType.processedReads.assembly.standard.accessionId']").type( + "Processed Standard Accession Id" + ) + cy.get("button").contains("Add new item").click() + + cy.get("input[name='analysisType.processedReads.sequence[0].accessionId']").type( + "Processed Sequence Accession Id" + ) + }) + cy.root().submit() + }) + + // Saved objects list should have newly added item from Analysis object + cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 1) + + // Navigate to summary cy.get("button[type=button]").contains("Next").click() + + // Check the amount of submitted objects in each object type + cy.get("h6").contains("Study").parent("div").children().eq(1).should("have.text", 2) + cy.get("h6").contains("Analysis").parent("div").children().eq(1).should("have.text", 1) + + // Navigate to publish cy.get("button[type=button]").contains("Publish").click() cy.get('button[aria-label="Publish folder contents and move to frontpage"]').contains("Publish").click() }) diff --git a/cypress/integration/draft.spec.js b/cypress/integration/draft.spec.js new file mode 100644 index 00000000..4e364957 --- /dev/null +++ b/cypress/integration/draft.spec.js @@ -0,0 +1,58 @@ +describe("Draft operations", function () { + const baseUrl = "http://localhost:" + Cypress.env("port") + "/" + + it("should create new folder, save, delete and continue draft", () => { + cy.visit(baseUrl) + cy.get('[alt="CSC Login"]').click() + cy.visit(baseUrl + "newdraft") + + // Navigate to folder creation + cy.get("button[type=button]").contains("New folder").click() + + // Add folder name & description, navigate to submissions + cy.get("input[name='name']").type("Test name") + cy.get("textarea[name='description']").type("Test description") + cy.get("button[type=button]").contains("Next").click() + + // Fill a Study form + cy.get("div[role=button]").contains("Study").click() + cy.get("div[role=button]").contains("Fill Form").click() + cy.get("input[name='descriptor.studyTitle']").type("Test title") + + // Save a draft + cy.get("button[type=button]").contains("Save as Draft").click() + cy.get("div[role=alert]", { timeout: 10000 }).contains("Draft saved with") + cy.get("div[role=button]").contains("Choose from drafts").click() + cy.get("div[data-testid='existing']").find("li").should("have.length", 1) + + // Save another draft + cy.get("div[role=button]").contains("Fill Form").click() + cy.get("input[name='descriptor.studyTitle']").type("Test title 2") + cy.get("button[type=button]").contains("Save as Draft").click() + cy.get("div[role=alert]", { timeout: 10000 }).contains("Draft saved with") + + // Update draft, save from dialog + cy.get("input[name='descriptor.studyTitle']").type(" second save") + cy.get("div[role=button]").contains("Choose from drafts").click() + cy.get("h2").contains("Would you like to save draft version of this form") + cy.get("div[role=dialog]").contains("Save").click() + cy.get("div[data-testid='existing']").find("li").should("have.length", 2) + + // Delete a draft + cy.get("button[aria-label='Delete draft']").first().click() + cy.get("div[data-testid='existing']").find("li").should("have.length", 1) + + // Continue draft + cy.get("button[aria-label='Continue draft']").first().click() + cy.get("input[name='descriptor.studyTitle']").should("have.value", "Test title 2 second save") + cy.get("select[name='descriptor.studyType']").select("Metagenomics") + + // Submit form + cy.get("button[type=submit]").contains("Submit").click() + cy.get(".MuiListItem-container", { timeout: 10000 }).should("have.length", 1) + + // Drafts should be empty + cy.get("div[role=button]").contains("Choose from drafts").click() + cy.get("h3").contains("No study drafts.") + }) +}) diff --git a/src/__tests__/WizardDraftObjectPicker.test.js b/src/__tests__/WizardDraftObjectPicker.test.js index 85b3e5b4..0bc16022 100644 --- a/src/__tests__/WizardDraftObjectPicker.test.js +++ b/src/__tests__/WizardDraftObjectPicker.test.js @@ -4,13 +4,12 @@ import "@testing-library/jest-dom/extend-expect" import { render, screen } from "@testing-library/react" import { Provider } from "react-redux" import configureStore from "redux-mock-store" -import { toMatchDiffSnapshot } from "snapshot-diff" +import thunk from "redux-thunk" import WizardDraftObjectPicker from "../components/NewDraftWizard/WizardComponents/WizardDraftObjectPicker" -const mockStore = configureStore([]) - -expect.extend({ toMatchDiffSnapshot }) +const middlewares = [thunk] +const mockStore = configureStore(middlewares) describe("WizardStepper", () => { const store = mockStore({ diff --git a/src/__tests__/WizardObjectIndex.test.js b/src/__tests__/WizardObjectIndex.test.js index 107bda63..d6d9821d 100644 --- a/src/__tests__/WizardObjectIndex.test.js +++ b/src/__tests__/WizardObjectIndex.test.js @@ -14,10 +14,10 @@ describe("WizardObjectIndex", () => { const store = mockStore({ submissionFolder: { drafts: [ - { accessionId: "TESTID1234", schema: "study" }, - { accessionId: "TESTID5678", schema: "study" }, - { accessionId: "TESTID0101", schema: "analysis" }, - { accessionId: "TESTID0202", schema: "experiment" }, + { accessionId: "TESTID1234", schema: "draft-study" }, + { accessionId: "TESTID5678", schema: "draft-study" }, + { accessionId: "TESTID0101", schema: "draft-analysis" }, + { accessionId: "TESTID0202", schema: "draft-experiment" }, ], }, }) diff --git a/src/__tests__/WizardSavedObjectsList.test.js b/src/__tests__/WizardSavedObjectsList.test.js index 39af4aba..39fd2d34 100644 --- a/src/__tests__/WizardSavedObjectsList.test.js +++ b/src/__tests__/WizardSavedObjectsList.test.js @@ -20,7 +20,7 @@ describe("WizardStepper", () => { { accessionId: "EDAG2", schema: "sample" }, ] - it("should have 'Added!' message rendered on item that has 'new' property", () => { + it("should have saved objects listed", () => { render( diff --git a/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js b/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js index b4c71837..af114625 100644 --- a/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js +++ b/src/components/NewDraftWizard/WizardComponents/WizardObjectIndex.js @@ -170,7 +170,6 @@ const WizardObjectIndex = () => { } const handleSubmissionTypeChange = (submissionType: string) => { - dispatch(resetDraftObject()) if (currentSubmissionType === "") { dispatch(setSubmissionType(submissionType)) dispatch(setObjectType(expandedObjectType)) @@ -215,7 +214,11 @@ const WizardObjectIndex = () => { id="type-header" > {typeCapitalized} - + action.payload, From 3ad141094963dfc95010002b67ac88241309e0d3 Mon Sep 17 00:00:00 2001 From: Liisa Lado-Villar <47525503+lilachic@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:32:49 +0200 Subject: [PATCH 09/11] remove warnings caused by wrong error type in folder creation --- .../NewDraftWizard/WizardSteps/WizardCreateFolderStep.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js b/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js index 10590ad4..a92bd1f2 100644 --- a/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js +++ b/src/components/NewDraftWizard/WizardSteps/WizardCreateFolderStep.js @@ -63,7 +63,7 @@ const CreateFolderForm = ({ createFolderFormRef }: { createFolderFormRef: Create fullWidth inputRef={register({ required: true, validate: { name: value => value.length > 0 } })} helperText={errors.name ? "Please give a name for folder." : null} - error={errors.name} + error={errors.name ? true : false} disabled={isSubmitting} defaultValue={folder ? folder.name : ""} > @@ -76,7 +76,7 @@ const CreateFolderForm = ({ createFolderFormRef }: { createFolderFormRef: Create rows={5} inputRef={register({ required: true, validate: { description: value => value.length > 0 } })} helperText={errors.description ? "Please give a description for folder." : null} - error={errors.description} + error={errors.description ? true : false} disabled={isSubmitting} defaultValue={folder ? folder.description : ""} > From a43809f44f74a1f679af78852b1791bffe8d8af3 Mon Sep 17 00:00:00 2001 From: Stefan Negru Date: Mon, 11 Jan 2021 18:08:40 +0200 Subject: [PATCH 10/11] update packages especially apisauce --- package-lock.json | 157 ++++++++++++++++++++-------------------------- package.json | 12 ++-- 2 files changed, 73 insertions(+), 96 deletions(-) diff --git a/package-lock.json b/package-lock.json index f4e3c6c2..206a96f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2704,9 +2704,9 @@ } }, "@testing-library/dom": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.28.1.tgz", - "integrity": "sha512-acv3l6kDwZkQif/YqJjstT3ks5aaI33uxGNVIQmdKzbZ2eMKgg3EV2tB84GDdc72k3Kjhl6mO8yUt6StVIdRDg==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-7.29.2.tgz", + "integrity": "sha512-CBMELfyY1jKdtLcSRmEnZWRzRkCRVSNPTzhzrn8wY8OnzUo7Pe/W+HgLzt4TDnWIPYeusHBodf9wUjJF48kPmA==", "requires": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -2719,17 +2719,17 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "requires": { "@babel/highlight": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" }, "@babel/highlight": { "version": "7.10.4", @@ -2869,9 +2869,9 @@ } }, "@testing-library/react": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.2.tgz", - "integrity": "sha512-jaxm0hwUjv+hzC+UFEywic7buDC9JQ1q3cDsrWVSDAPmLotfA6E6kUHlYm/zOeGCac6g48DR36tFHxl7Zb+N5A==", + "version": "11.2.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-11.2.3.tgz", + "integrity": "sha512-BirBUGPkTW28ULuCwIbYo0y2+0aavHczBT6N9r3LrsswEW3pg25l1wgoE7I8QBIy1upXWkwKpYdWY7NYYP0Bxw==", "requires": { "@babel/runtime": "^7.12.5", "@testing-library/dom": "^7.28.1" @@ -3689,11 +3689,11 @@ } }, "apisauce": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-1.1.2.tgz", - "integrity": "sha512-AqOrOVk71JPSqugA6PdrkE2S0w1GC/f3xPZPMHJ1O+Z73pwT2uoGnr8JbfmB/gvO2cnygYzlBOnkD/mN6W1FMQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/apisauce/-/apisauce-2.0.1.tgz", + "integrity": "sha512-mJBw3pKmtfVoP6oifnf7/iRJQtNkVb6GkYsVOXN2pidootj1mhGBtzYHOX9FVBzAz5QV2GMu8IJtiNIgZ44kHQ==", "requires": { - "axios": "^0.19.0", + "axios": "^0.21.1", "ramda": "^0.25.0" } }, @@ -3988,34 +3988,11 @@ "integrity": "sha512-5Kgy8Cz6LPC9DJcNb3yjAXTu3XihQgEdnIg50c//zOC/MyLP0Clg+Y8Sh9ZjjnvBrDZU4DgXS9C3T9r4/scGZQ==" }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "requires": { - "follow-redirects": "1.5.10" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "follow-redirects": "^1.10.0" } }, "axobject-query": { @@ -6073,9 +6050,9 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, "cypress": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-6.2.0.tgz", - "integrity": "sha512-m/rkcogYM9MTy8rbsZgyS5wT2L/J+B5V2bY2ztkDNMyqhk/oZgUF4KTWVLzkW2I+scg0iAddca95tLlt7XnAtw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-6.2.1.tgz", + "integrity": "sha512-OYkSgzA4J4Q7eMjZvNf5qWpBLR4RXrkqjL3UZ1UzGGLAskO0nFTi/RomNTG6TKvL3Zp4tw4zFY1gp5MtmkCZrA==", "dev": true, "requires": { "@cypress/listr-verbose-renderer": "^0.4.1", @@ -7470,9 +7447,9 @@ } }, "eslint-plugin-prettier": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz", - "integrity": "sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" @@ -8325,12 +8302,12 @@ } }, "find-versions": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", - "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz", + "integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==", "dev": true, "requires": { - "semver-regex": "^2.0.0" + "semver-regex": "^3.1.2" } }, "flat-cache": { @@ -9171,18 +9148,18 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" }, "husky": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.6.tgz", - "integrity": "sha512-o6UjVI8xtlWRL5395iWq9LKDyp/9TE7XMOTvIpEVzW638UcGxTmV5cfel6fsk/jbZSTlvfGVJf2svFtybcIZag==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.3.7.tgz", + "integrity": "sha512-0fQlcCDq/xypoyYSJvEuzbDPHFf8ZF9IXKJxlrnvxABTSzK1VPT2RKYQKrcgJ+YD39swgoB6sbzywUqFxUiqjw==", "dev": true, "requires": { "chalk": "^4.0.0", "ci-info": "^2.0.0", "compare-versions": "^3.6.0", "cosmiconfig": "^7.0.0", - "find-versions": "^3.2.0", + "find-versions": "^4.0.0", "opencollective-postinstall": "^2.0.2", - "pkg-dir": "^4.2.0", + "pkg-dir": "^5.0.0", "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" @@ -9223,12 +9200,12 @@ "dev": true }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, @@ -9239,38 +9216,32 @@ "dev": true }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9278,12 +9249,12 @@ "dev": true }, "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "dev": true, "requires": { - "find-up": "^4.0.0" + "find-up": "^5.0.0" } }, "supports-color": { @@ -15629,9 +15600,9 @@ "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" }, "react-hook-form": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.14.0.tgz", - "integrity": "sha512-yj4aqASmyxFPyDtDLKBae+AazFv5vcC5CEpDlh1+r5k5BTH/J/CTG6q0H5lSinm0B0F6P7oTmXIYB75ZmuQz6g==" + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-6.14.1.tgz", + "integrity": "sha512-Bf2fWcL2F34hUUqrx1rpgZ8ZErQ4/DvrPs6Je+lUYL59km8PXIQqyCTz/NbggC1RQUj7rChSmTx6eFap+mCttw==" }, "react-is": { "version": "16.13.1", @@ -16626,9 +16597,9 @@ "dev": true }, "semver-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", - "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.2.tgz", + "integrity": "sha512-bXWyL6EAKOJa81XG1OZ/Yyuq+oT0b2YLlxx7c+mrdYPaPbnj6WgVULXhinMIeZGufuUBu/eVRqXEhiv4imfwxA==", "dev": true }, "send": { @@ -20056,6 +20027,12 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 4e2b3291..f886e147 100644 --- a/package.json +++ b/package.json @@ -9,14 +9,14 @@ "@material-ui/lab": "^4.0.0-alpha.57", "@reduxjs/toolkit": "^1.5.0", "@testing-library/jest-dom": "^5.11.8", - "@testing-library/react": "^11.1.1", + "@testing-library/react": "^11.2.3", "ajv": "^6.12.6", - "apisauce": "^1.1.2", + "apisauce": "^2.0.1", "jest-environment-jsdom-sixteen": "^1.0.3", "lodash": "^4.17.20", "react": "^16.14.0", "react-dom": "^16.14.0", - "react-hook-form": "^6.14.0", + "react-hook-form": "^6.14.1", "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "^4.0.0" @@ -57,17 +57,17 @@ "devDependencies": { "@testing-library/user-event": "^12.6.0", "concurrently": "^5.3.0", - "cypress": "^6.2.0", + "cypress": "^6.2.1", "cypress-file-upload": "^4.1.1", "eslint-config-prettier": "^6.15.0", "eslint-plugin-cypress": "^2.11.2", "eslint-plugin-flowtype": "^5.2.0", "eslint-plugin-import": "^2.22.1", "eslint-plugin-jest": "^24.1.3", - "eslint-plugin-prettier": "^3.3.0", + "eslint-plugin-prettier": "^3.3.1", "flow-bin": "^0.126.1", "http-proxy-middleware": "^1.0.6", - "husky": "^4.3.6", + "husky": "^4.3.7", "jest-environment-jsdom-sixteen": "^1.0.3", "prettier": "^2.2.1", "redux-mock-store": "^1.5.4", From 2703ba724c64bb4d3cc89837cd688f16cd446100 Mon Sep 17 00:00:00 2001 From: Stefan Negru Date: Thu, 14 Jan 2021 09:38:05 +0200 Subject: [PATCH 11/11] bump metadata-submitter to 0.7.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 206a96f4..31e8fe6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "metadata-submitter-frontend", - "version": "0.6.0", + "version": "0.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f886e147..64489c9a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metadata-submitter-frontend", - "version": "0.6.0", + "version": "0.7.0", "private": true, "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.6",