From ba7944461deb553a1b7119e69497a88f69eb50b0 Mon Sep 17 00:00:00 2001 From: Jeevananthan Kesavan <49391725+jeevananthank@users.noreply.github.com> Date: Mon, 3 Jan 2022 09:53:33 +0100 Subject: [PATCH] Test/add missing frontend tests (#7747) * new tests for app frontend * new tests for studio designer * new tests for studio * removed unused data * formatted * run with 3 machines * updated app deploy test * changed logic for favorites * removed only clause * corrected text resource test * updated test name * wcag test in altinn studio * added extra wait * updated deps * changed to beforeeach hook * changed inprogress selector * added script for deleted old cypress binaries * moved prune command one step down --- .../workflows/cypress-altinn-app-frontend.yml | 2 +- src/test/cypress/e2e/config/studio/dev.json | 2 - src/test/cypress/e2e/config/studio/local.json | 2 - src/test/cypress/e2e/config/studio/prod.json | 2 - .../cypress/e2e/config/studio/staging.json | 2 - src/test/cypress/e2e/fixtures/texts.json | 3 +- .../integration/app-frontend/formatting.js | 5 +- .../e2e/integration/app-frontend/group.js | 1 + .../e2e/integration/app-frontend/summary.js | 17 +++ .../e2e/integration/studio/dashboard.js | 23 +++- .../cypress/e2e/integration/studio/deploy.js | 32 +++-- .../e2e/integration/studio/designer.js | 79 +++++++++-- .../cypress/e2e/integration/studio/repos.js | 24 ++++ .../e2e/integration/studio/sync-app.js | 76 ++++++++++ .../cypress/e2e/integration/studio/wcag.js | 35 +++++ .../e2e/integration/usecase/usecase.js | 4 +- .../cypress/e2e/pageobjects/app-frontend.js | 2 + src/test/cypress/e2e/pageobjects/designer.js | 46 +++++++ src/test/cypress/e2e/pageobjects/header.js | 1 + src/test/cypress/e2e/support/index.d.ts | 6 + src/test/cypress/e2e/support/studio.js | 13 +- src/test/cypress/package.json | 7 +- src/test/cypress/use-cases.yaml | 4 +- src/test/cypress/yarn.lock | 130 ++++++++---------- 24 files changed, 399 insertions(+), 119 deletions(-) create mode 100644 src/test/cypress/e2e/integration/studio/repos.js create mode 100644 src/test/cypress/e2e/integration/studio/sync-app.js create mode 100644 src/test/cypress/e2e/integration/studio/wcag.js diff --git a/.github/workflows/cypress-altinn-app-frontend.yml b/.github/workflows/cypress-altinn-app-frontend.yml index c7686442846..6323a140fa1 100644 --- a/.github/workflows/cypress-altinn-app-frontend.yml +++ b/.github/workflows/cypress-altinn-app-frontend.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - machines: [1, 2] + machines: [1, 2, 3] steps: - name: Checkout diff --git a/src/test/cypress/e2e/config/studio/dev.json b/src/test/cypress/e2e/config/studio/dev.json index dfc3b7ecbd4..6c211b3003e 100644 --- a/src/test/cypress/e2e/config/studio/dev.json +++ b/src/test/cypress/e2e/config/studio/dev.json @@ -3,12 +3,10 @@ "baseUrl": "https://dev.altinn.studio", "env": { "autoTestUser": "AutoTest", - "noDeployUser": "AutoTest2", "useCaseUser": "bruksmonsterDev", "deployApp": "ttd/autodeploy-v3", "designerApp": "AutoTest/auto-designer-app", "withoutDataModelApp": "AutoTest/appwithout-dm", - "rulesApp": "AutoTest/rulesservice", "appOwner": "Testdepartementet" }, "defaultCommandTimeout": 20000, diff --git a/src/test/cypress/e2e/config/studio/local.json b/src/test/cypress/e2e/config/studio/local.json index 379b68fcf9f..79fdba468e1 100644 --- a/src/test/cypress/e2e/config/studio/local.json +++ b/src/test/cypress/e2e/config/studio/local.json @@ -4,12 +4,10 @@ "env": { "autoTestUser": "testuser", "autoTestUserPwd": "Studio@123", - "noDeployUser": "automatedtest@email.com", "testEmail": "test1@test.com", "deployApp": "ttd/deploy", "designerApp": "ttd/designer", "withoutDataModelApp": "ttd/appwithout-dm", - "rulesApp": "ttd/rulesservice", "appOwner": "ttd" }, "defaultCommandTimeout": 20000, diff --git a/src/test/cypress/e2e/config/studio/prod.json b/src/test/cypress/e2e/config/studio/prod.json index 6b698fb78df..6d2e24cd2be 100644 --- a/src/test/cypress/e2e/config/studio/prod.json +++ b/src/test/cypress/e2e/config/studio/prod.json @@ -3,12 +3,10 @@ "baseUrl": "https://altinn.studio", "env": { "autoTestUser": "AutoTest", - "noDeployUser": "noDeployUser", "useCaseUser": "bruksmonster", "deployApp": "ttd/auto-deploy-app-v2", "designerApp": "AutoTest/auto-designer-app", "withoutDataModelApp": "AutoTest/appwithout-dm", - "rulesApp": "AutoTest/rules-service", "appOwner": "Testdepartementet" }, "defaultCommandTimeout": 20000, diff --git a/src/test/cypress/e2e/config/studio/staging.json b/src/test/cypress/e2e/config/studio/staging.json index d89ecde949a..4464f8cbce9 100644 --- a/src/test/cypress/e2e/config/studio/staging.json +++ b/src/test/cypress/e2e/config/studio/staging.json @@ -3,11 +3,9 @@ "baseUrl": "https://staging.altinn.studio", "env": { "autoTestUser": "AutoTest", - "noDeployUser": "automatedtest@email.com", "deployApp": "ttd/autodeploy-v3", "designerApp": "AutoTest/auto-designer-app", "withoutDataModelApp": "AutoTest/appwithout-dm", - "rulesApp": "AutoTest/rulesservice", "appOwner": "Testdepartementet" }, "defaultCommandTimeout": 20000, diff --git a/src/test/cypress/e2e/fixtures/texts.json b/src/test/cypress/e2e/fixtures/texts.json index 98e120cfc24..e0a77905f02 100644 --- a/src/test/cypress/e2e/fixtures/texts.json +++ b/src/test/cypress/e2e/fixtures/texts.json @@ -19,5 +19,6 @@ "alreadyStartedForm": "Du har allerede startet å fylle ut dette skjemaet.", "continueOrStartNew": "Velg om du vil fortsette på et skjema du har begynt på, eller om du vil starte på ny.", "welcome": "Velkommen til Altinn Studio", - "appExists": "En app med det navnet finnes allerede." + "appExists": "En app med det navnet finnes allerede.", + "noDeployAccess": "Du har ikke rettigheter til å starte en deploy til AT21-miljøet. Tilgang kan delegeres av owners" } diff --git a/src/test/cypress/e2e/integration/app-frontend/formatting.js b/src/test/cypress/e2e/integration/app-frontend/formatting.js index 31c99fda409..5c774773205 100644 --- a/src/test/cypress/e2e/integration/app-frontend/formatting.js +++ b/src/test/cypress/e2e/integration/app-frontend/formatting.js @@ -9,7 +9,10 @@ describe('Formatting', () => { it('Number formatting', () => { cy.navigateToChangeName(); cy.get('#form-content-newFirstName').siblings().should('have.class', 'MuiGrid-grid-md-6'); - cy.get('#form-content-newFirstName').siblings().parent().should('have.css', 'border-bottom', '1px dashed rgb(148, 148, 148)'); + cy.get('#form-content-newFirstName') + .siblings() + .parent() + .should('have.css', 'border-bottom', '1px dashed rgb(148, 148, 148)'); cy.get(appFrontend.changeOfName.mobilenummer) .should('be.visible') .type('44444444') diff --git a/src/test/cypress/e2e/integration/app-frontend/group.js b/src/test/cypress/e2e/integration/app-frontend/group.js index 90a88bdf1d9..fc52688351a 100644 --- a/src/test/cypress/e2e/integration/app-frontend/group.js +++ b/src/test/cypress/e2e/integration/app-frontend/group.js @@ -68,6 +68,7 @@ describe('Group', () => { cy.get(appFrontend.group.currentValue).should('be.visible').type('1337').blur().tab(); // DataProcessingHandler.cs for frontend-test changes 1337 to 1338. cy.get(appFrontend.group.currentValue).should('have.value', 'NOK 1 338'); + cy.get(appFrontend.group.newValueLabel).should('contain.text', '2. Endre verdi 1338 til'); }); it('Validation on group', () => { diff --git a/src/test/cypress/e2e/integration/app-frontend/summary.js b/src/test/cypress/e2e/integration/app-frontend/summary.js index 1bf0a753273..ba9fb27dd5c 100644 --- a/src/test/cypress/e2e/integration/app-frontend/summary.js +++ b/src/test/cypress/e2e/integration/app-frontend/summary.js @@ -68,4 +68,21 @@ describe('Summary', () => { cy.get(summaryDate).contains(mui.gridContainer, texts.requiredField).should('not.exist'); }); }); + + it('is possible to view summary of repeating group', () => { + cy.compelteTask3Form(); + cy.get(appFrontend.group.mainGroupSummary).should('be.visible').and('have.length', 1); + cy.get(appFrontend.group.mainGroupSummary) + .first() + .children(mui.gridItem) + .then((item) => { + cy.get(item).should('have.length', 4); + cy.get(item).find(mui.buttonIcon).should('have.length', 3); + cy.get(item) + .eq(1) + .children(mui.gridContainer) + .should('have.css', 'border-bottom', '1px dashed rgb(0, 143, 214)'); + cy.get(item).eq(3).should('contain.text', 'automation'); + }); + }); }); diff --git a/src/test/cypress/e2e/integration/studio/dashboard.js b/src/test/cypress/e2e/integration/studio/dashboard.js index 00a2874f6c8..4704969371c 100644 --- a/src/test/cypress/e2e/integration/studio/dashboard.js +++ b/src/test/cypress/e2e/integration/studio/dashboard.js @@ -11,8 +11,10 @@ const common = new Common(); context('Dashboard', () => { beforeEach(() => { cy.visit('/'); + cy.intercept('GET', '**/repos/search**').as('fetchApps'); cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); cy.get(dashboard.searchApp).should('be.visible'); + cy.wait('@fetchApps').its('response.statusCode').should('eq', 200); }); it('is possible to view apps, add and remove favourites', () => { @@ -23,11 +25,11 @@ context('Dashboard', () => { .find(common.gridRow) .then((apps) => { cy.get(apps).should('have.length.gte', 1); + cy.get(apps).find(dashboard.apps.favourite).click({ multiple: true }); + cy.wait('@addFavourite').its('response.statusCode').should('eq', 204); cy.get(apps) .first() .then((app) => { - cy.get(app).find(dashboard.apps.favourite).click(); - cy.wait('@addFavourite').its('response.statusCode').should('eq', 204); cy.get(app).children(dashboard.apps.name).invoke('text').should('not.be.empty'); cy.get(app).children(dashboard.apps.createdBy).should('have.text', Cypress.env('autoTestUser')); cy.get(app).children(dashboard.apps.updatedAt).invoke('text').should('not.be.empty'); @@ -46,18 +48,16 @@ context('Dashboard', () => { it('is possible to change context and view all apps', () => { if (Cypress.env('environment') == 'local') cy.intercept('GET', '**/user/repos', repos(10)); - cy.intercept('**/repos/search**').as('getAllRepos'); cy.get(header.profileIcon).should('be.visible').click(); cy.get(header.menu.all).should('be.visible').click(); - cy.wait('@getAllRepos'); + cy.wait('@fetchApps'); cy.contains('h2', 'Alle applikasjoner').should('be.visible'); }); it('is possible to search an app by name', () => { if (Cypress.env('environment') == 'local') cy.intercept('GET', '**/user/repos', repos(10)); - cy.intercept('**/repos/search**').as('searchRepos'); cy.get(dashboard.searchApp).type('auto'); - cy.wait('@searchRepos'); + cy.wait('@fetchApps'); cy.contains('h2', 'Søkeresultat') .siblings() .then((searchResult) => { @@ -65,4 +65,15 @@ context('Dashboard', () => { cy.get(searchResult).find(common.gridRow).first().find(dashboard.apps.name).should('contain.text', 'auto'); }); }); + + it('is not possible to find an app that does not exist', () => { + cy.get(dashboard.searchApp).type('cannotfindapp'); + cy.wait('@fetchApps'); + cy.contains('h2', 'Søkeresultat') + .siblings() + .then((searchResult) => { + cy.get(searchResult).find(common.gridRow).should('have.length', 0); + cy.get(searchResult).find('p').should('contain.text', 'Ingen applikasjoner funnet'); + }); + }); }); diff --git a/src/test/cypress/e2e/integration/studio/deploy.js b/src/test/cypress/e2e/integration/studio/deploy.js index fe7cf861b09..e21f89bf7d3 100644 --- a/src/test/cypress/e2e/integration/studio/deploy.js +++ b/src/test/cypress/e2e/integration/studio/deploy.js @@ -4,9 +4,9 @@ import { designer } from '../../pageobjects/designer'; import Common from '../../pageobjects/common'; import { header } from '../../pageobjects/header'; -import { dashboard } from '../../pageobjects/dashboard'; import { builds } from '../../fixtures/builds'; import { deploys } from '../../fixtures/deploys'; +import * as texts from '../../fixtures/texts.json'; const common = new Common(); @@ -23,13 +23,11 @@ context('Deploy', () => { beforeEach(() => { cy.visit('/'); cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); - var appName = Cypress.env('deployApp').split('/')[1]; - cy.get(dashboard.searchApp).type(appName); - cy.contains(dashboard.apps.name, appName).siblings(dashboard.apps.links).find(dashboard.apps.edit).click(); + cy.searchAndOpenApp(Cypress.env('deployApp')); cy.get(designer.appMenu['deploy']).click(); }); - it('Inprogress build', () => { + it('is possible to view an inprogress build', () => { cy.intercept('GET', `**/designer/api/v1/${Cypress.env('deployApp')}/releases**`, builds('inprogress')).as( 'buildstatus', ); @@ -41,7 +39,7 @@ context('Deploy', () => { }); }); - it('Failed build', () => { + it('is possible to view the status of a failed build', () => { cy.intercept('GET', `**/designer/api/v1/${Cypress.env('deployApp')}/releases**`, builds('failed')).as( 'buildstatus', ); @@ -53,7 +51,7 @@ context('Deploy', () => { }); }); - it('Successful build', () => { + it('is possible to view status of a successful build', () => { cy.intercept('GET', `**/designer/api/v1/${Cypress.env('deployApp')}/releases**`, builds('succeeded')).as( 'buildstatus', ); @@ -65,10 +63,20 @@ context('Deploy', () => { }); }); - it('App Deploy', () => { - cy.intercept('GET', '**/designer/api/v1/*/*/Deployments**', deploys()).as('deploys'); - cy.wait('@deploys').its('response.statusCode').should('eq', 200); - cy.contains('div', 'AT22').should('be.visible'); - cy.get(designer.deployHistory.at22).find('tbody > tr').should('contain.text', 'testuser'); + it('is possible to view history of app deploys', () => { + if (Cypress.env('environment') == 'local') + cy.intercept('GET', '**/designer/api/v1/*/*/Deployments**', deploys()).as('deploys'); + if (Cypress.env('environment') != 'prod') { + cy.contains('div', 'AT22').scrollIntoView().should('be.visible'); + cy.get(designer.deployHistory.at22).find('tbody > tr').should('contain.text', Cypress.env('autoTestUser')); + } else { + cy.contains('div', 'PRODUCTION').scrollIntoView().should('be.visible'); + cy.get(designer.deployHistory.prod).find('tbody > tr').should('contain.text', Cypress.env('autoTestUser')); + } + }); + + it('is not possible to deploy without access', () => { + if (Cypress.env('environment') == 'local') cy.intercept('GET', '**/permissions', '["AT22"]'); + cy.contains(common.gridContainer, texts.noDeployAccess).should('exist').and('be.visible'); }); }); diff --git a/src/test/cypress/e2e/integration/studio/designer.js b/src/test/cypress/e2e/integration/studio/designer.js index 947d6e04076..720ed185aeb 100644 --- a/src/test/cypress/e2e/integration/studio/designer.js +++ b/src/test/cypress/e2e/integration/studio/designer.js @@ -2,7 +2,6 @@ /// import { designer } from '../../pageobjects/designer'; -import { dashboard } from '../../pageobjects/dashboard'; import { header } from '../../pageobjects/header'; import Common from '../../pageobjects/common'; @@ -14,28 +13,27 @@ context('Designer', () => { cy.visit('/'); cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); cy.createapp(Cypress.env('appOwner'), 'designer'); - cy.get(header.profileIcon).click(); + cy.get(header.profileIconDesigner).click(); cy.contains(header.menuItem, 'Logout').click(); } }); beforeEach(() => { cy.visit('/'); cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); - var appName = Cypress.env('deployApp').split('/')[1]; - cy.get(dashboard.searchApp).type(appName); - cy.contains(dashboard.apps.name, appName).siblings(dashboard.apps.links).find(dashboard.apps.edit).click(); }); - it('About App', () => { + it('is possible to edit information about the app', () => { + cy.searchAndOpenApp(Cypress.env('designerApp')); cy.contains(designer.aboutApp.appHeader, 'Om appen').should('be.visible'); cy.contains(common.button, 'Endre').click(); cy.get(designer.aboutApp.appName).clear().type('New app name'); - cy.get(designer.aboutApp.appDescription).clear().type('App description'); + cy.get(designer.aboutApp.appDescription).click().clear().type('App description'); cy.get(designer.aboutApp.appName).invoke('val').should('contain', 'New app name'); cy.get(designer.aboutApp.appDescription).invoke('val').should('contain', 'App description'); }); - it('UI Editor', () => { + it('is possible to add and delete form components', () => { + cy.searchAndOpenApp(Cypress.env('designerApp')); cy.get(designer.appMenu['edit']).click(); cy.get(common.leftDrawer).trigger('mouseover', { force: true }); cy.get(designer.appEditorMenu['datamodel']).should('be.visible'); @@ -43,5 +41,70 @@ context('Designer', () => { cy.get(designer.formComponents.shortAnswer).parents(designer.draggable).trigger('dragstart'); cy.get(designer.dragToArea).parents(designer.draggable).trigger('drop'); cy.deletecomponents(); + cy.get(header.profileIconDesigner).click(); + cy.get(header.menu.openRepo) + .invoke('attr', 'href') + .should('include', `/repos/${Cypress.env('designerApp')}`); + cy.get(header.menu.docs).should('be.visible'); + cy.contains('li', 'Logout').should('be.visible'); + }); + + it('is possible to add and delete text resources', () => { + cy.searchAndOpenApp(Cypress.env('designerApp')); + cy.get(designer.appMenu.texts).click(); + cy.getIframeBody().find(designer.texts.root).find(designer.texts.new).should('be.visible').click(); + cy.getIframeBody() + .find(designer.texts.resources) + .last() + .then((newText) => { + cy.get(newText).find(designer.texts.resourceId).should('be.visible').type('test').tab(); + cy.get(newText).find(designer.texts.resourceValue).should('be.visible').type('automation').tab(); + cy.get(newText).find(designer.texts.requiredError).should('be.visible'); + cy.getIframeBody().find(designer.texts.save).should('be.visible').focus().click(); + cy.get(newText).find(designer.texts.delete).should('be.visible').click(); + cy.getIframeBody().find(designer.texts.save).should('be.visible').focus().click(); + }); + }); + + it('is possible to configure rules and dynamics ', () => { + cy.searchAndOpenApp(Cypress.env('designerApp')); + cy.get(designer.appMenu['edit']).click(); + cy.contains('span', 'Rediger dynamikk').should('be.visible'); + cy.get(designer.rules.add).should('be.visible').click(); + cy.get(designer.rules.list).should('be.visible').select('sum'); + cy.get(designer.rules.paramA).parents('.col').siblings().find(designer.rules.paramValue).click(); + cy.get(designer.rules.dataModelBinding).should('have.length.above', 0); + cy.get(designer.submit).scrollIntoView().should('be.visible').click(); + cy.contains(common.gridItem, 'sum').should('be.visible').click(); + cy.get(designer.delete).scrollIntoView().should('be.visible').click(); + cy.contains(common.gridItem, 'sum').should('not.exist'); + cy.get(designer.dynamics.add).should('be.visible').click(); + cy.get(designer.dynamics.list).should('be.visible').select('biggerThan10'); + cy.get(designer.dynamics.action).should('be.visible'); + cy.get(designer.submit).scrollIntoView().should('be.visible').click(); + cy.contains(common.gridItem, 'biggerThan10').should('be.visible').click(); + cy.get(designer.delete).scrollIntoView().should('be.visible').click(); + cy.contains(common.gridItem, 'biggerThan10').should('not.exist'); + }); + + it('is possible to delete local changes of an app ', () => { + cy.searchAndOpenApp(Cypress.env('designerApp')); + cy.get(designer.appMenu['edit']).click(); + cy.intercept('GET', '**/status').as('getRepoStatus'); + cy.get(designer.formComponents.shortAnswer).parents(designer.draggable).click().type('{enter}'); + cy.wait('@getRepoStatus'); + cy.get(designer.syncApp.push).scrollIntoView().isVisible(); + cy.deleteLocalChanges(Cypress.env('designerApp')); + cy.get(designer.syncApp.noChanges).scrollIntoView().isVisible(); + }); + + it('is possible details of the clone modal ', () => { + cy.searchAndOpenApp(Cypress.env('withoutDataModelApp')); + cy.get(designer.appMenu['edit']).click(); + cy.contains('button', 'Clone').scrollIntoView().should('be.visible').click(); + cy.get(designer.clone.docs).should('be.visible'); + cy.contains('p', designer.clone.missingDatamodel).should('be.visible'); + cy.get(designer.clone.datamodelLink).should('be.visible'); + cy.get(designer.clone.copyRepo).should('be.visible'); }); }); diff --git a/src/test/cypress/e2e/integration/studio/repos.js b/src/test/cypress/e2e/integration/studio/repos.js new file mode 100644 index 00000000000..c224263dd9b --- /dev/null +++ b/src/test/cypress/e2e/integration/studio/repos.js @@ -0,0 +1,24 @@ +/// +/// + +import { header } from '../../pageobjects/header'; + +context('Repository', () => { + beforeEach(() => { + cy.visit('/'); + cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); + cy.searchAndOpenApp(Cypress.env('designerApp')); + }); + + it('is possible to open repository of an app', () => { + cy.get(header.profileIconDesigner).click(); + cy.get(header.menu.openRepo) + .invoke('attr', 'href') + .then((href) => { + cy.visit(href); + }); + cy.get('.repo-header').should('be.visible'); + cy.get('a[href="/repos/"]').should('be.visible').click(); + cy.get('img[alt="Altinn logo"]').should('be.visible'); + }); +}); diff --git a/src/test/cypress/e2e/integration/studio/sync-app.js b/src/test/cypress/e2e/integration/studio/sync-app.js new file mode 100644 index 00000000000..62c36558792 --- /dev/null +++ b/src/test/cypress/e2e/integration/studio/sync-app.js @@ -0,0 +1,76 @@ +/* eslint-disable cypress/no-unnecessary-waiting */ +/// +/// + +import { designer } from '../../pageobjects/designer'; +import Common from '../../pageobjects/common'; + +const common = new Common(); + +if (Cypress.env('environment') != 'local') { + context('Sync app and deploy', () => { + beforeEach(() => { + cy.intercept('GET', '**/status').as('getRepoStatus'); + cy.intercept('POST', '**/commit').as('commitChanges'); + cy.intercept('GET', '**/pull').as('pullChanges'); + cy.intercept('POST', '**/push').as('pushChanges'); + cy.intercept('GET', '**/releases**').as('getAppBuilds'); + cy.intercept('POST', '**/releases**').as('startAppBuild'); + cy.intercept('GET', '**/Deployments**').as('getAppDeploys'); + }); + it('is possible sync changes, build and deploy app', () => { + cy.visit('/'); + cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); + cy.searchAndOpenApp(Cypress.env('deployApp')); + + // Sync app changes + cy.get(designer.appMenu.edit).click(); + cy.deletecomponents(); + cy.get(designer.formComponents.shortAnswer).parents(designer.draggable).trigger('dragstart'); + cy.get(designer.dragToArea).parents(designer.draggable).trigger('drop'); + cy.wait('@getRepoStatus').its('response.statusCode').should('eq', 200); + cy.get(designer.syncApp.push).scrollIntoView().isVisible(); + cy.get(designer.syncApp.push).click(); + cy.get(designer.syncApp.commitMessage).should('be.visible').clear().type('automation'); + cy.get(designer.syncApp.pushButton).should('be.visible').click(); + cy.wait('@commitChanges').its('response.statusCode').should('eq', 200); + cy.wait('@pullChanges').its('response.statusCode').should('eq', 200); + cy.get(designer.syncApp.pushButton).should('be.visible').click(); + cy.wait('@pushChanges').its('response.statusCode').should('eq', 200); + cy.get(designer.syncApp.pushSuccess).isVisible(); + cy.reload(); + + // Start app build + cy.get(designer.appMenu.deploy).click(); + cy.wait('@getAppBuilds').then((res) => { + expect(res.response.statusCode).to.eq(200); + var builds = res.response.body; + var latestBuildTag = builds.results[0].tagName; + cy.get(designer.build.versionNum) + .scrollIntoView() + .clear() + .type(`${parseInt(latestBuildTag) + 1}`); + cy.get(designer.build.versionDesc).clear().type('automation'); + cy.contains('button', 'Bygg versjon').should('be.visible').focus().click(); + cy.wait('@startAppBuild').its('response.statusCode').should('eq', 201); + }); + + cy.wait('@getAppDeploys').its('response.statusCode').should('eq', 200); + // Wait before starting app deploy + cy.wait(20000); + + // Start app deploy + var deployVerions = + Cypress.env('environment') != 'prod' ? designer.deploy.at22Versions : designer.deploy.prodVersions; + var deployButton = Cypress.env('environment') != 'prod' ? designer.deploy.at22Deploy : designer.deploy.prodDeploy; + cy.get(deployVerions).scrollIntoView().find('.select__indicators').should('be.visible').click(); + cy.get(designer.deploy.versions).scrollIntoView().children().should('have.length.above', 0); + cy.get(designer.deploy.latestBuild).scrollIntoView().click(); + cy.get(deployButton).should('be.visible').focus().click(); + cy.get(designer.deploy.confirm).should('be.visible').focus().click(); + cy.wait('@getAppDeploys').its('response.statusCode').should('eq', 200); + cy.wait(5000); + cy.get(deployVerions).siblings(common.gridContainer).find(designer.deploy.inProgress).should('be.visible'); + }); + }); +} diff --git a/src/test/cypress/e2e/integration/studio/wcag.js b/src/test/cypress/e2e/integration/studio/wcag.js new file mode 100644 index 00000000000..f82d52cc7db --- /dev/null +++ b/src/test/cypress/e2e/integration/studio/wcag.js @@ -0,0 +1,35 @@ +/// +/// + +import { dashboard } from '../../pageobjects/dashboard'; +import { designer } from '../../pageobjects/designer'; + +context('WCAG', () => { + beforeEach(() => { + cy.visit('/'); + cy.intercept('GET', '**/repos/search**').as('fetchApps'); + cy.studiologin(Cypress.env('autoTestUser'), Cypress.env('autoTestUserPwd')); + cy.get(dashboard.searchApp).should('be.visible'); + cy.wait('@fetchApps').its('response.statusCode').should('eq', 200); + }); + + it('accessibility test for dashboard', () => { + cy.testWcag(); + }); + + it('accessibility test for new app', () => { + cy.get(dashboard.newApp).should('be.visible').click(); + cy.testWcag(); + }); + + it('accessibility test for app designer', () => { + cy.searchAndOpenApp(Cypress.env('designerApp')); + cy.testWcag(); + cy.get(designer.appMenu.edit).click(); + cy.testWcag(); + cy.get(designer.appMenu.texts).click(); + cy.testWcag(); + cy.get(designer.appMenu.deploy).click(); + cy.testWcag(); + }); +}); diff --git a/src/test/cypress/e2e/integration/usecase/usecase.js b/src/test/cypress/e2e/integration/usecase/usecase.js index e54edc3b377..877ca73a6f2 100644 --- a/src/test/cypress/e2e/integration/usecase/usecase.js +++ b/src/test/cypress/e2e/integration/usecase/usecase.js @@ -20,10 +20,8 @@ context( beforeEach(() => { cy.intercept(/(s|RepoS)tatus/).as('repoStatus'); Cypress.Cookies.preserveOnce('AltinnStudioDesigner', 'i_like_gitea', 'XSRF-TOKEN', 'AS-XSRF-TOKEN'); - var appName = Cypress.env('deployApp').split('/')[1]; cy.visit('/'); - cy.get(dashboard.searchApp).should('be.visible').type(appName); - cy.contains(dashboard.apps.name, appName).siblings(dashboard.apps.links).find(dashboard.apps.edit).click(); + cy.searchAndOpenApp(Cypress.env('deployApp')); cy.wait('@repoStatus'); cy.get(designer.layOutContainer).should('be.visible'); }); diff --git a/src/test/cypress/e2e/pageobjects/app-frontend.js b/src/test/cypress/e2e/pageobjects/app-frontend.js index fa496112f88..e25b3d90258 100644 --- a/src/test/cypress/e2e/pageobjects/app-frontend.js +++ b/src/test/cypress/e2e/pageobjects/app-frontend.js @@ -71,6 +71,7 @@ export default class AppFrontend { subGroup: '[id^="group-subGroup"]', currentValue: 'input[id^="currentValue"]', newValue: 'input[id^="newValue"]', + newValueLabel: 'label[for^="newValue"]', addNewItem: 'div[class*="addButton"]', comments: 'input[id^="comments"]', delete: 'button[class*="makeStyles-deleteButton"]', @@ -81,6 +82,7 @@ export default class AppFrontend { summaryText: '#send-in-text', next: 'button[aria-label="Neste"]', back: 'button[aria-label="Tilbake"]', + mainGroupSummary: '[id^="mainGroup-"][id$="-summary"]', }; //Stateless-app diff --git a/src/test/cypress/e2e/pageobjects/designer.js b/src/test/cypress/e2e/pageobjects/designer.js index 642ab36e29c..f1e12e57551 100644 --- a/src/test/cypress/e2e/pageobjects/designer.js +++ b/src/test/cypress/e2e/pageobjects/designer.js @@ -10,6 +10,20 @@ export const designer = { inprogressSpinner: "[role='progressbar']", failedCheck: "i[class*='ai-circle-exclamation']", successCheck: "i[class*='ai-check-circle']", + build: { + versionNum: 'input[aria-label="Versjonsnummer"]', + versionDesc: 'textarea', + }, + deploy: { + at22Versions: '#deploy-select-at22', + prodVersions: '#deploy-select-production', + versions: '.select__menu-list', + latestBuild: '.select__option--is-focused', + confirm: '#deployPopover', + at22Deploy: '#deploy-button-at22', + prodDeploy: '#deploy-button-production', + inProgress: 'div[class*="MuiCircularProgress-indeterminate"][role="progressbar"]', + }, deployHistory: { at22: '#deploy-history-table-at22', prod: '#deploy-history-table-production', @@ -25,6 +39,8 @@ export const designer = { push: '#changes_to_share_btn', noChanges: '#no_changes_to_share_btn', pushButton: '#share_changes_modal_button', + commitMessage: 'textarea[id="test"]', + pushSuccess: '.fa.fa-circlecheck', }, deleteChanges: { reset: '#reset-repo-button', @@ -51,4 +67,34 @@ export const designer = { formButton: "i[class^='fa fa-button']", }, deleteComponent: '.fa-circletrash', + rules: { + add: 'button[aria-label="Legg til regel for beregninger"]', + list: 'select[name="selectRule"]', + paramA: '#a', + paramValue: 'div[class$="indicatorContainer"]', + dataModelBinding: 'div[class$="option"][id^="react-select"]', + }, + dynamics: { + add: 'button[aria-label="Legg til regel for vis/skjul felt"]', + list: '#selectConditionalRule', + action: '#select_action', + }, + submit: 'button[type="submit"]', + delete: '.a-btn-danger', + clone: { + copyRepo: '#copy-repository-url-button', + missingDatamodel: 'Datamodell mangler', + datamodelLink: 'a[href$="datamodel"]', + docs: 'a[href="https://docs.altinn.studio/"]', + }, + texts: { + new: '.json-editor-btn-add', + root: 'div[data-schemapath="root.resources"]', + resources: 'tr[data-schemapath^="root.resources"]', + resourceId: 'input[name$="[id]"]', + resourceValue: 'input[name$="[value]"]', + requiredError: '.help-block.errormsg', + save: 'input[onclick="submitForm()"]', + delete: '.json-editor-btn-delete', + }, }; diff --git a/src/test/cypress/e2e/pageobjects/header.js b/src/test/cypress/e2e/pageobjects/header.js index cc6367d1846..906fc4f80d7 100644 --- a/src/test/cypress/e2e/pageobjects/header.js +++ b/src/test/cypress/e2e/pageobjects/header.js @@ -9,5 +9,6 @@ export const header = { gitea: '#menu-gitea', logOut: '#menu-logout', openRepo: 'a[href*="repos"]', + docs: 'a[href="https://docs.altinn.studio/"]', }, }; diff --git a/src/test/cypress/e2e/support/index.d.ts b/src/test/cypress/e2e/support/index.d.ts index 0e0d14c4c82..b2bbc84de7c 100644 --- a/src/test/cypress/e2e/support/index.d.ts +++ b/src/test/cypress/e2e/support/index.d.ts @@ -128,5 +128,11 @@ declare namespace Cypress { * check visibility of an element whose parent is found hidden by cypress */ isVisible(): Chainable; + + /** + * Custom command to search and open an app + * @example cy.searchAndOpenApp('ttd/app') + */ + searchAndOpenApp(appId: string): Chainable; } } diff --git a/src/test/cypress/e2e/support/studio.js b/src/test/cypress/e2e/support/studio.js index 68f8f7f2514..901099e4a63 100644 --- a/src/test/cypress/e2e/support/studio.js +++ b/src/test/cypress/e2e/support/studio.js @@ -50,7 +50,7 @@ Cypress.Commands.add('deletecomponents', () => { Cypress.Commands.add('deleteLocalChanges', (appId) => { cy.getCookie('AltinnStudioDesigner').should('exist'); cy.intercept(/(s|RepoS)tatus/).as('repoStatus'); - cy.visit(`designer/${Cypress.env('deployApp')}#/about`); + cy.visit(`designer/${appId}#/about`); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(5000); cy.wait('@repoStatus'); @@ -66,7 +66,9 @@ Cypress.Commands.add('deleteLocalChanges', (appId) => { .should('be.visible') .type(`${appId.split('/')[1]}`) .blur(); + cy.intercept('GET', '**/reset').as('resetRepo'); cy.get(designer.deleteChanges.confirm).should('be.visible').click(); + cy.wait('@resetRepo'); cy.get(designer.deleteChanges.name).should('not.exist'); }); @@ -76,3 +78,12 @@ Cypress.Commands.add('deleteLocalChanges', (appId) => { Cypress.Commands.add('getIframeBody', () => { return cy.get('iframe').its('0.contentDocument.body').should('not.be.empty').then(cy.wrap); }); + +/** + * Search an app from dashboard and open app + */ +Cypress.Commands.add('searchAndOpenApp', (appId) => { + var appName = appId.split('/')[1]; + cy.get(dashboard.searchApp).type(appName); + cy.contains(dashboard.apps.name, appName).siblings(dashboard.apps.links).find(dashboard.apps.edit).click(); +}); diff --git a/src/test/cypress/package.json b/src/test/cypress/package.json index 51244a82835..45d5561c3a3 100644 --- a/src/test/cypress/package.json +++ b/src/test/cypress/package.json @@ -18,6 +18,7 @@ "cy:version": "cypress -v", "cy:cachelist": "cypress cache list", "cy:run": "cypress run", + "cy:prunecache": "cypress cache prune", "before:all": "cypress run -b chrome -s 'e2e/integration/setup/before.js'", "after:all": "cypress run -b chrome -s 'e2e/integration/setup/after.js'", "test:studio": "cypress run -b chrome -s 'e2e/integration/studio/*.js'", @@ -34,16 +35,16 @@ }, "devDependencies": { "axe-core": "^4.3.5", - "cypress": "^9.1.0", + "cypress": "^9.2.0", "cypress-axe": "^0.13.0", "cypress-file-upload": "^5.0.8", "cypress-plugin-tab": "^1.0.5", - "eslint": "^8.3.0", + "eslint": "^8.5.0", "eslint-plugin-cypress": "^2.12.1", "faker": "^5.5.3", "fs-extra": "^10.0.0", "path": "^0.12.7", - "prettier": "^2.5.0", + "prettier": "^2.5.1", "start-server-and-test": "^1.14.0" }, "packageManager": "yarn@3.1.0" diff --git a/src/test/cypress/use-cases.yaml b/src/test/cypress/use-cases.yaml index 9b694f22d0a..7835c2e7d46 100644 --- a/src/test/cypress/use-cases.yaml +++ b/src/test/cypress/use-cases.yaml @@ -30,7 +30,9 @@ steps: - bash: | yarn --immutable - + + yarn run cy:prunecache + yarn run cy:cachelist yarn run cy:version diff --git a/src/test/cypress/yarn.lock b/src/test/cypress/yarn.lock index 7d58968d035..0331c928e65 100644 --- a/src/test/cypress/yarn.lock +++ b/src/test/cypress/yarn.lock @@ -5,9 +5,9 @@ __metadata: version: 5 cacheKey: 8 -"@cypress/request@npm:^2.88.7": - version: 2.88.7 - resolution: "@cypress/request@npm:2.88.7" +"@cypress/request@npm:^2.88.10": + version: 2.88.10 + resolution: "@cypress/request@npm:2.88.10" dependencies: aws-sign2: ~0.7.0 aws4: ^1.8.0 @@ -16,8 +16,7 @@ __metadata: extend: ~3.0.2 forever-agent: ~0.6.1 form-data: ~2.3.2 - har-validator: ~5.1.3 - http-signature: ~1.2.0 + http-signature: ~1.3.6 is-typedarray: ~1.0.0 isstream: ~0.1.2 json-stringify-safe: ~5.0.1 @@ -28,7 +27,7 @@ __metadata: tough-cookie: ~2.5.0 tunnel-agent: ^0.6.0 uuid: ^8.3.2 - checksum: 21544e555afd0841a8a189d4a4af7695c918bc782db3c636f56cadfed9ea1620c2ef43d94a709de984660c4fe9407dd8446f9f65fbe56f4eafa26a0c05792a64 + checksum: 69c3e3b332e9be4866a900f6bcca5d274d8cea6c99707fbcce061de8dbab11c9b1e39f4c017f6e83e6e682717781d4f6106fd6b7cf9546580fcfac353b6676cf languageName: node linkType: hard @@ -42,20 +41,20 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^1.0.4": - version: 1.0.4 - resolution: "@eslint/eslintrc@npm:1.0.4" +"@eslint/eslintrc@npm:^1.0.5": + version: 1.0.5 + resolution: "@eslint/eslintrc@npm:1.0.5" dependencies: ajv: ^6.12.4 debug: ^4.3.2 - espree: ^9.0.0 + espree: ^9.2.0 globals: ^13.9.0 ignore: ^4.0.6 import-fresh: ^3.2.1 js-yaml: ^4.1.0 minimatch: ^3.0.4 strip-json-comments: ^3.1.1 - checksum: 570f87e216944830b3761889f14cdf1e9bc7dcc2211e941585cfc2768575954e26852605eb441e21c9581472f89ea0e9cfdb8309523e9fe0a57fe9342bda4fe0 + checksum: b35b50d7b65bd8acd92a05b6fb15ac62c0cefa40dfef0324ca5bf8632bf3679bab6e173c53b3ad1e1d837701cecdbd9c144b35f46588cdf4e046a9caa272488d languageName: node linkType: hard @@ -75,18 +74,18 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.6.0": - version: 0.6.0 - resolution: "@humanwhocodes/config-array@npm:0.6.0" +"@humanwhocodes/config-array@npm:^0.9.2": + version: 0.9.2 + resolution: "@humanwhocodes/config-array@npm:0.9.2" dependencies: - "@humanwhocodes/object-schema": ^1.2.0 + "@humanwhocodes/object-schema": ^1.2.1 debug: ^4.1.1 minimatch: ^3.0.4 - checksum: 1025b07514b7bfd10a05e8b6cb5e6520878e9c8836b3dd0569fc07df29a09e428c2df1e0760b1d461da8ed6f81ca83ecb02e24198f80b0a177a2acbf532e267c + checksum: 28a9e2974c50a86765cb6cc96e03d29187ea33fdaba62c4f35db89002e3cfbd340e64c9f6cf869e33e2e5cdcc06e78763458f4178d38a6f30aea1308787ca706 languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^1.2.0": +"@humanwhocodes/object-schema@npm:^1.2.1": version: 1.2.1 resolution: "@humanwhocodes/object-schema@npm:1.2.1" checksum: a824a1ec31591231e4bad5787641f59e9633827d0a2eaae131a288d33c9ef0290bd16fda8da6f7c0fcb014147865d12118df10db57f27f41e20da92369fcb3f1 @@ -181,7 +180,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.12.3, ajv@npm:^6.12.4": +"ajv@npm:^6.10.0, ajv@npm:^6.12.4": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -573,25 +572,25 @@ __metadata: resolution: "cypress-studio@workspace:." dependencies: axe-core: ^4.3.5 - cypress: ^9.1.0 + cypress: ^9.2.0 cypress-axe: ^0.13.0 cypress-file-upload: ^5.0.8 cypress-plugin-tab: ^1.0.5 - eslint: ^8.3.0 + eslint: ^8.5.0 eslint-plugin-cypress: ^2.12.1 faker: ^5.5.3 fs-extra: ^10.0.0 path: ^0.12.7 - prettier: ^2.5.0 + prettier: ^2.5.1 start-server-and-test: ^1.14.0 languageName: unknown linkType: soft -"cypress@npm:^9.1.0": - version: 9.1.0 - resolution: "cypress@npm:9.1.0" +"cypress@npm:^9.2.0": + version: 9.2.0 + resolution: "cypress@npm:9.2.0" dependencies: - "@cypress/request": ^2.88.7 + "@cypress/request": ^2.88.10 "@cypress/xvfb": ^1.2.4 "@types/node": ^14.14.31 "@types/sinonjs__fake-timers": ^6.0.2 @@ -634,7 +633,7 @@ __metadata: yauzl: ^2.10.0 bin: cypress: bin/cypress - checksum: 37f2cd704d9e67c4b525e2e8a723f82b0e0eb573cd276fa6460d86ce665cf2a53fd490a4a0ca79394694ba0d91306a03194479089b57457fdc6b9cb9e9747b54 + checksum: 1378c4d0822c52505cdd71b3bd567c0399bac054a1f99f5e8d9adfb3f6991a0dcbb58de7662b7dbfd2b302bb94dc924c22047152ea8777661fa9b8819308d69f languageName: node linkType: hard @@ -800,12 +799,12 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.3.0": - version: 8.3.0 - resolution: "eslint@npm:8.3.0" +"eslint@npm:^8.5.0": + version: 8.5.0 + resolution: "eslint@npm:8.5.0" dependencies: - "@eslint/eslintrc": ^1.0.4 - "@humanwhocodes/config-array": ^0.6.0 + "@eslint/eslintrc": ^1.0.5 + "@humanwhocodes/config-array": ^0.9.2 ajv: ^6.10.0 chalk: ^4.0.0 cross-spawn: ^7.0.2 @@ -816,7 +815,7 @@ __metadata: eslint-scope: ^7.1.0 eslint-utils: ^3.0.0 eslint-visitor-keys: ^3.1.0 - espree: ^9.1.0 + espree: ^9.2.0 esquery: ^1.4.0 esutils: ^2.0.2 fast-deep-equal: ^3.1.3 @@ -844,18 +843,18 @@ __metadata: v8-compile-cache: ^2.0.3 bin: eslint: bin/eslint.js - checksum: c0338471fc787384077b132fb1496f264a4d7ed032b9072b2f6b8b1c833edc89b0a4890080576781ce6101a2700341af413ecbf1b66f0780aa02601c40fb2008 + checksum: c1a9e26070520a308cc30b62ba0d37d5b115ed23987a93219819537bdea9398e6ebe57c27d97be36ecc83b5162c72e82ecb0a9e5b44b7992980f9be90eb5c4b3 languageName: node linkType: hard -"espree@npm:^9.0.0, espree@npm:^9.1.0": - version: 9.1.0 - resolution: "espree@npm:9.1.0" +"espree@npm:^9.2.0": + version: 9.2.0 + resolution: "espree@npm:9.2.0" dependencies: acorn: ^8.6.0 acorn-jsx: ^5.3.1 eslint-visitor-keys: ^3.1.0 - checksum: ba9b0f759c49c19a098e0bb97f3b9b05441a60dec3f868bc412ae300e00ba20cb0bd2c6a1bdd6c4f0056e6382650bf45b4982d81e67ad0210c1c16b336f73c39 + checksum: ae533a058036e3efeeac43a0ee39c74ab347e2a73bbe2946fba33cc0d84aca657e675bc317ed9afd95338f79d5d5a862afec2f717d2539ae13fa9f1638371761 languageName: node linkType: hard @@ -1227,23 +1226,6 @@ __metadata: languageName: node linkType: hard -"har-schema@npm:^2.0.0": - version: 2.0.0 - resolution: "har-schema@npm:2.0.0" - checksum: d8946348f333fb09e2bf24cc4c67eabb47c8e1d1aa1c14184c7ffec1140a49ec8aa78aa93677ae452d71d5fc0fdeec20f0c8c1237291fc2bcb3f502a5d204f9b - languageName: node - linkType: hard - -"har-validator@npm:~5.1.3": - version: 5.1.5 - resolution: "har-validator@npm:5.1.5" - dependencies: - ajv: ^6.12.3 - har-schema: ^2.0.0 - checksum: b998a7269ca560d7f219eedc53e2c664cd87d487e428ae854a6af4573fc94f182fe9d2e3b92ab968249baec7ebaf9ead69cf975c931dc2ab282ec182ee988280 - languageName: node - linkType: hard - "has-flag@npm:^4.0.0": version: 4.0.0 resolution: "has-flag@npm:4.0.0" @@ -1251,14 +1233,14 @@ __metadata: languageName: node linkType: hard -"http-signature@npm:~1.2.0": - version: 1.2.0 - resolution: "http-signature@npm:1.2.0" +"http-signature@npm:~1.3.6": + version: 1.3.6 + resolution: "http-signature@npm:1.3.6" dependencies: assert-plus: ^1.0.0 - jsprim: ^1.2.2 - sshpk: ^1.7.0 - checksum: 3324598712266a9683585bb84a75dec4fd550567d5e0dd4a0fff6ff3f74348793404d3eeac4918fa0902c810eeee1a86419e4a2e92a164132dfe6b26743fb47c + jsprim: ^2.0.2 + sshpk: ^1.14.1 + checksum: 10be2af4764e71fee0281392937050201ee576ac755c543f570d6d87134ce5e858663fe999a7adb3e4e368e1e356d0d7fec6b9542295b875726ff615188e7a0c languageName: node linkType: hard @@ -1462,10 +1444,10 @@ __metadata: languageName: node linkType: hard -"json-schema@npm:0.2.3": - version: 0.2.3 - resolution: "json-schema@npm:0.2.3" - checksum: bbc2070988fb5f2a2266a31b956f1b5660e03ea7eaa95b33402901274f625feb586ae0c485e1df854fde40a7f0dc679f3b3ca8e5b8d31f8ea07a0d834de785c7 +"json-schema@npm:0.4.0": + version: 0.4.0 + resolution: "json-schema@npm:0.4.0" + checksum: 66389434c3469e698da0df2e7ac5a3281bcff75e797a5c127db7c5b56270e01ae13d9afa3c03344f76e32e81678337a8c912bdbb75101c62e487dc3778461d72 languageName: node linkType: hard @@ -1496,15 +1478,15 @@ __metadata: languageName: node linkType: hard -"jsprim@npm:^1.2.2": - version: 1.4.1 - resolution: "jsprim@npm:1.4.1" +"jsprim@npm:^2.0.2": + version: 2.0.2 + resolution: "jsprim@npm:2.0.2" dependencies: assert-plus: 1.0.0 extsprintf: 1.3.0 - json-schema: 0.2.3 + json-schema: 0.4.0 verror: 1.10.0 - checksum: 6bcb20ec265ae18bb48e540a6da2c65f9c844f7522712d6dfcb01039527a49414816f4869000493363f1e1ea96cbad00e46188d5ecc78257a19f152467587373 + checksum: d175f6b1991e160cb0aa39bc857da780e035611986b5492f32395411879fdaf4e513d98677f08f7352dac93a16b66b8361c674b86a3fa406e2e7af6b26321838 languageName: node linkType: hard @@ -1813,12 +1795,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.5.0": - version: 2.5.0 - resolution: "prettier@npm:2.5.0" +"prettier@npm:^2.5.1": + version: 2.5.1 + resolution: "prettier@npm:2.5.1" bin: prettier: bin-prettier.js - checksum: aad1b35b73e7c14596d389d90977a83dad0db689ba5802a0ef319c357b7867f55b885db197972aa6a56c30f53088c9f8e0d7f7930ae074c275a4e9cbe091d21d + checksum: 21b9408476ea1c544b0e45d51ceb94a84789ff92095abb710942d780c862d0daebdb29972d47f6b4d0f7ebbfb0ffbf56cc2cfa3e3e9d1cca54864af185b15b66 languageName: node linkType: hard @@ -2045,7 +2027,7 @@ __metadata: languageName: node linkType: hard -"sshpk@npm:^1.7.0": +"sshpk@npm:^1.14.1": version: 1.16.1 resolution: "sshpk@npm:1.16.1" dependencies: