From aa15e0ff4f075ced0a9f589e85703612061345d4 Mon Sep 17 00:00:00 2001 From: mahula Date: Tue, 28 Feb 2023 10:49:48 +0100 Subject: [PATCH 01/14] adapt registration page model for registration e2e test --- e2e-tests/cypress/e2e/models/RegistrationPage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/cypress/e2e/models/RegistrationPage.ts b/e2e-tests/cypress/e2e/models/RegistrationPage.ts index 8cae26a26..2e9b48648 100644 --- a/e2e-tests/cypress/e2e/models/RegistrationPage.ts +++ b/e2e-tests/cypress/e2e/models/RegistrationPage.ts @@ -4,7 +4,7 @@ export class RegistrationPage { // selectors firstnameInput = '#registerFirstname' lastnameInput = '#registerLastname' - emailInput = '#Email-input-field' + emailInput = 'input[type=email]' checkbox = '#registerCheckbox' submitBtn = '[type=submit]' @@ -35,7 +35,7 @@ export class RegistrationPage { cy.get(this.checkbox).click({ force: true }) } - submitRegistrationPage() { + submitRegistrationForm() { cy.get(this.submitBtn).should('be.enabled') cy.get(this.submitBtn).click() } From d60a79b6075ff6b55abdf041c7a02b34fbd3203a Mon Sep 17 00:00:00 2001 From: mahula Date: Tue, 28 Feb 2023 10:51:55 +0100 Subject: [PATCH 02/14] deactivate worklfows for testing --- .github/workflows/test_dht-node.yml | 2 +- .github/workflows/test_federation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_dht-node.yml b/.github/workflows/test_dht-node.yml index 5b3a65a70..5b260478d 100644 --- a/.github/workflows/test_dht-node.yml +++ b/.github/workflows/test_dht-node.yml @@ -1,6 +1,6 @@ name: gradido test_dht-node CI -on: push +on: none jobs: ############################################################################## diff --git a/.github/workflows/test_federation.yml b/.github/workflows/test_federation.yml index 2da78758e..0dd8e6196 100644 --- a/.github/workflows/test_federation.yml +++ b/.github/workflows/test_federation.yml @@ -1,6 +1,6 @@ name: gradido test_federation CI -on: push +on: none jobs: ############################################################################## From 48cede92226f08092cd50a38225531d77d8f88da Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 09:52:56 +0100 Subject: [PATCH 03/14] add email step definition for registration test --- e2e-tests/cypress.config.ts | 7 +++ .../support/step_definitions/email_steps.ts | 46 +++++++++++++++++-- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/e2e-tests/cypress.config.ts b/e2e-tests/cypress.config.ts index 16ebb0e97..1fd10f157 100644 --- a/e2e-tests/cypress.config.ts +++ b/e2e-tests/cypress.config.ts @@ -2,6 +2,7 @@ import { defineConfig } from 'cypress' import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor' import browserify from '@badeball/cypress-cucumber-preprocessor/browserify' +let activationLink:string let resetPasswordLink: string async function setupNodeEvents( @@ -24,6 +25,12 @@ async function setupNodeEvents( getResetPasswordLink: () => { return resetPasswordLink }, + setActivationLink: (val) => { + return (activationLink = val) + }, + getActivationLink: () => { + return activationLink + }, }) on('after:run', (results) => { diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index b313442f2..d06c3879b 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -12,7 +12,7 @@ Then('the user receives an e-mail containing the password reset link', () => { (userEMailSite) => { const linkPattern = /\/reset-password\/[0-9]+\d/ - cy.visit('/') // navigate to user's e-maile site (on fake mail server) + cy.visit('/') // navigate to user's e-mail site (on fake mail server) cy.get(userEMailSite.emailInbox).should('be.visible') cy.get(userEMailSite.emailList) @@ -24,9 +24,9 @@ Then('the user receives an e-mail containing the password reset link', () => { cy.get(userEMailSite.emailMeta) .find(userEMailSite.emailSubject) .contains('asswor') - + cy.get('.email-content') - .find('.plain-text') + .find('.plain-text', { timeout: 2000 }) .contains(linkPattern) .invoke('text') .then((text) => { @@ -37,9 +37,49 @@ Then('the user receives an e-mail containing the password reset link', () => { ) }) +Then('the user receives an e-mail containing the activation link', () => { + cy.origin( + Cypress.env('mailserverURL'), + { args: userEMailSite }, + (userEMailSite) => { + const linkPattern = /\/checkEmail\/[0-9]+\d/ + + cy.visit('/') // navigate to user's e-mail site (on fake mail server) + cy.get(userEMailSite.emailInbox).should('be.visible') + + cy.get(userEMailSite.emailList) + .find('.email-item') + .filter(':contains(E-Mail Überprüfung)') + .first() + .click() + + cy.get(userEMailSite.emailMeta) + .find(userEMailSite.emailSubject) + .contains('E-Mail Überprüfung') + + cy.get('.email-content') + .wait(2000) + .find('.plain-text') + .contains(linkPattern) + .invoke('text') + .then((text) => { + const activationLink = text.match(linkPattern)[0] + cy.task('setActivationLink', activationLink) + }) + } + ) +}) + When('the user opens the password reset link in the browser', () => { cy.task('getResetPasswordLink').then((passwordResetLink) => { cy.visit(passwordResetLink) }) cy.get(resetPasswordPage.newPasswordRepeatBlock).should('be.visible') }) + +When('the user opens the activation link in the browser', () => { + cy.task('getActivationLink').then((activationLink) => { + cy.visit(activationLink) + }) + cy.get(resetPasswordPage.newPasswordRepeatBlock).should('be.visible') +}) From fede39f30845bfaf80f05e005066c2d69d3678cf Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 09:59:18 +0100 Subject: [PATCH 04/14] correct method call in step definition --- .../cypress/support/step_definitions/user_registration_steps.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/cypress/support/step_definitions/user_registration_steps.ts b/e2e-tests/cypress/support/step_definitions/user_registration_steps.ts index 8f12338b0..e90956b6e 100644 --- a/e2e-tests/cypress/support/step_definitions/user_registration_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/user_registration_steps.ts @@ -18,7 +18,7 @@ And('the user agrees to the privacy policy', () => { }) And('the user submits the registration form', () => { - registrationPage.submitRegistrationPage() + registrationPage.submitRegistrationForm() cy.get(registrationPage.RegistrationThanxHeadline).should('be.visible') cy.get(registrationPage.RegistrationThanxText).should('be.visible') }) From 84b031c967270fcbf110bd79c5d5cc061b16630b Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 10:00:26 +0100 Subject: [PATCH 05/14] rewrite registration scenarion to use the email steps --- e2e-tests/cypress/e2e/User.Registration.feature | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e-tests/cypress/e2e/User.Registration.feature b/e2e-tests/cypress/e2e/User.Registration.feature index ed53bb4b0..9e6d82c20 100644 --- a/e2e-tests/cypress/e2e/User.Registration.feature +++ b/e2e-tests/cypress/e2e/User.Registration.feature @@ -2,12 +2,12 @@ Feature: User registration As a user I want to register to create an account - @skip Scenario: Register successfully Given the user navigates to page "/register" When the user fills name and email "Regina" "Register" "regina@register.com" And the user agrees to the privacy policy And the user submits the registration form - Then the user can use a provided activation link - And the user can set a password "Aa12345_" + Then the user receives an e-mail containing the activation link + When the user opens the activation link in the browser + Then the user can set a password "Aa12345_" And the user can login with the credentials "regina@register.com" "Aa12345_" From 2ded17348aa328b889686d293d8094390e4b4834 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 10:52:24 +0100 Subject: [PATCH 06/14] refactor naming in reset password page model --- e2e-tests/cypress/e2e/models/ResetPasswordPage.ts | 8 ++++---- e2e-tests/cypress/support/step_definitions/email_steps.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e-tests/cypress/e2e/models/ResetPasswordPage.ts b/e2e-tests/cypress/e2e/models/ResetPasswordPage.ts index 20134de6d..153b41a82 100644 --- a/e2e-tests/cypress/e2e/models/ResetPasswordPage.ts +++ b/e2e-tests/cypress/e2e/models/ResetPasswordPage.ts @@ -2,19 +2,19 @@ export class ResetPasswordPage { // selectors - newPasswordBlock = '#new-password-input-field' - newPasswordRepeatBlock = '#repeat-new-password-input-field' + newPasswordInput = '#new-password-input-field' + newPasswordRepeatInput = '#repeat-new-password-input-field' resetPasswordBtn = 'button[type=submit]' resetPasswordMessageBlock = '[data-test="reset-password-message"]' signinBtn = '.btn.test-message-button' enterNewPassword(password: string) { - cy.get(this.newPasswordBlock).find('input[type=password]').type(password) + cy.get(this.newPasswordInput).find('input[type=password]').type(password) return this } repeatNewPassword(password: string) { - cy.get(this.newPasswordRepeatBlock) + cy.get(this.newPasswordRepeatInput) .find('input[type=password]') .type(password) return this diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index d06c3879b..53dbb6d5d 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -74,12 +74,12 @@ When('the user opens the password reset link in the browser', () => { cy.task('getResetPasswordLink').then((passwordResetLink) => { cy.visit(passwordResetLink) }) - cy.get(resetPasswordPage.newPasswordRepeatBlock).should('be.visible') + cy.get(resetPasswordPage.newPasswordInput).should('be.visible') }) When('the user opens the activation link in the browser', () => { cy.task('getActivationLink').then((activationLink) => { cy.visit(activationLink) }) - cy.get(resetPasswordPage.newPasswordRepeatBlock).should('be.visible') + cy.get(resetPasswordPage.newPasswordInput).should('be.visible') }) From 77ee852c1a227007a87f4f936088a6ab12f59265 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 10:53:21 +0100 Subject: [PATCH 07/14] refactor e2e test register scenario --- e2e-tests/cypress/e2e/User.Registration.feature | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/e2e-tests/cypress/e2e/User.Registration.feature b/e2e-tests/cypress/e2e/User.Registration.feature index 9e6d82c20..c9b10b466 100644 --- a/e2e-tests/cypress/e2e/User.Registration.feature +++ b/e2e-tests/cypress/e2e/User.Registration.feature @@ -9,5 +9,9 @@ Feature: User registration And the user submits the registration form Then the user receives an e-mail containing the activation link When the user opens the activation link in the browser - Then the user can set a password "Aa12345_" - And the user can login with the credentials "regina@register.com" "Aa12345_" + And the user enters the password "12345Aa_" + And the user repeats the password "12345Aa_" + And the user submits the password form + And the user clicks the sign in button + Then the user submits the credentials "regina@register.com" "12345Aa_" + And the user is logged in with username "Regina Register" From 86286023fa3e10532a4defa41aaf3cbe90d48fb3 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 10:54:18 +0100 Subject: [PATCH 08/14] add registration test to e2e test job in workflow --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index badb47e87..5eadf1e94 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -550,7 +550,7 @@ jobs: run: | cd e2e-tests/ yarn - yarn run cypress run --spec cypress/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature + yarn run cypress run --spec cypress/e2e/User.Authentication.feature,cypress/e2e/User.Authentication.ResetPassword.feature,cypress/e2e/User.Registration.feature - name: End-to-end tests | if tests failed, upload screenshots if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} uses: actions/upload-artifact@v3 From d66356c040b808ef9b5341c1cf6f155f1a114b95 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 13:26:58 +0100 Subject: [PATCH 09/14] refactor email step definitions --- .../User.Authentication.ResetPassword.feature | 4 +- .../cypress/e2e/User.Registration.feature | 4 +- .../support/step_definitions/email_steps.ts | 77 +++++++------------ 3 files changed, 30 insertions(+), 55 deletions(-) diff --git a/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature b/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature index 55ca87215..b0f660709 100644 --- a/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature +++ b/e2e-tests/cypress/e2e/User.Authentication.ResetPassword.feature @@ -13,8 +13,8 @@ Feature: User Authentication - reset password And the user navigates to the forgot password page When the user enters the e-mail address "bibi@bloxberg.de" And the user submits the e-mail form - Then the user receives an e-mail containing the password reset link - When the user opens the password reset link in the browser + Then the user receives an e-mail containing the "password reset" link + When the user opens the "password reset" link in the browser And the user enters the password "12345Aa_" And the user repeats the password "12345Aa_" And the user submits the password form diff --git a/e2e-tests/cypress/e2e/User.Registration.feature b/e2e-tests/cypress/e2e/User.Registration.feature index c9b10b466..a50d57ea2 100644 --- a/e2e-tests/cypress/e2e/User.Registration.feature +++ b/e2e-tests/cypress/e2e/User.Registration.feature @@ -7,8 +7,8 @@ Feature: User registration When the user fills name and email "Regina" "Register" "regina@register.com" And the user agrees to the privacy policy And the user submits the registration form - Then the user receives an e-mail containing the activation link - When the user opens the activation link in the browser + Then the user receives an e-mail containing the "activation" link + When the user opens the "activation" link in the browser And the user enters the password "12345Aa_" And the user repeats the password "12345Aa_" And the user submits the password form diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index 53dbb6d5d..5b21c7993 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -5,57 +5,39 @@ import { UserEMailSite } from '../../e2e/models/UserEMailSite' const userEMailSite = new UserEMailSite() const resetPasswordPage = new ResetPasswordPage() -Then('the user receives an e-mail containing the password reset link', () => { +Then('the user receives an e-mail containing the {string} link', (linkName: string) => { + let emailSubject: string + let linkPattern: RegExp + + switch (linkName) { + case 'activation': + emailSubject = 'Email Verification' + linkPattern = /\/checkEmail\/[0-9]+\d/ + break + case 'password reset': + emailSubject = 'asswor' + linkPattern = /\/reset-password\/[0-9]+\d/ + break + default: + throw new Error(`Error in "Then the user receives an e-mail containing the {string} link" step: incorrect linkname string "${linkName}"`) + } + cy.origin( Cypress.env('mailserverURL'), - { args: userEMailSite }, - (userEMailSite) => { - const linkPattern = /\/reset-password\/[0-9]+\d/ - + { args: { emailSubject, linkPattern, userEMailSite } }, + ({ emailSubject, linkPattern, userEMailSite }) => { cy.visit('/') // navigate to user's e-mail site (on fake mail server) cy.get(userEMailSite.emailInbox).should('be.visible') cy.get(userEMailSite.emailList) .find('.email-item') - .filter(':contains(asswor)') + .filter(`:contains(${emailSubject})`) .first() .click() cy.get(userEMailSite.emailMeta) .find(userEMailSite.emailSubject) - .contains('asswor') - - cy.get('.email-content') - .find('.plain-text', { timeout: 2000 }) - .contains(linkPattern) - .invoke('text') - .then((text) => { - const resetPasswordLink = text.match(linkPattern)[0] - cy.task('setResetPasswordLink', resetPasswordLink) - }) - } - ) -}) - -Then('the user receives an e-mail containing the activation link', () => { - cy.origin( - Cypress.env('mailserverURL'), - { args: userEMailSite }, - (userEMailSite) => { - const linkPattern = /\/checkEmail\/[0-9]+\d/ - - cy.visit('/') // navigate to user's e-mail site (on fake mail server) - cy.get(userEMailSite.emailInbox).should('be.visible') - - cy.get(userEMailSite.emailList) - .find('.email-item') - .filter(':contains(E-Mail Überprüfung)') - .first() - .click() - - cy.get(userEMailSite.emailMeta) - .find(userEMailSite.emailSubject) - .contains('E-Mail Überprüfung') + .contains(emailSubject) cy.get('.email-content') .wait(2000) @@ -63,23 +45,16 @@ Then('the user receives an e-mail containing the activation link', () => { .contains(linkPattern) .invoke('text') .then((text) => { - const activationLink = text.match(linkPattern)[0] - cy.task('setActivationLink', activationLink) + const emailLink = text.match(linkPattern)[0] + cy.task('setEmailLink', emailLink) }) } ) }) -When('the user opens the password reset link in the browser', () => { - cy.task('getResetPasswordLink').then((passwordResetLink) => { - cy.visit(passwordResetLink) - }) - cy.get(resetPasswordPage.newPasswordInput).should('be.visible') -}) - -When('the user opens the activation link in the browser', () => { - cy.task('getActivationLink').then((activationLink) => { - cy.visit(activationLink) +When('the user opens the {string} link in the browser', (linkName: string) => { + cy.task('getEmailLink').then((emailLink) => { + cy.visit(emailLink) }) cy.get(resetPasswordPage.newPasswordInput).should('be.visible') }) From 10c7e8e2deff8ed6000491681919b97bd5367a6a Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 13:26:58 +0100 Subject: [PATCH 10/14] refactor email step definitions --- e2e-tests/cypress.config.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/e2e-tests/cypress.config.ts b/e2e-tests/cypress.config.ts index 1fd10f157..9dff98a9b 100644 --- a/e2e-tests/cypress.config.ts +++ b/e2e-tests/cypress.config.ts @@ -2,8 +2,7 @@ import { defineConfig } from 'cypress' import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor' import browserify from '@badeball/cypress-cucumber-preprocessor/browserify' -let activationLink:string -let resetPasswordLink: string +let emailLink: string async function setupNodeEvents( on: Cypress.PluginEvents, @@ -19,17 +18,11 @@ async function setupNodeEvents( ) on('task', { - setResetPasswordLink: (val) => { - return (resetPasswordLink = val) + setEmailLink: (link: string) => { + return (emailLink = link) }, - getResetPasswordLink: () => { - return resetPasswordLink - }, - setActivationLink: (val) => { - return (activationLink = val) - }, - getActivationLink: () => { - return activationLink + getEmailLink: () => { + return emailLink }, }) From 567961947c672457dc0c5702ba37c80abacf5682 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 13:52:10 +0100 Subject: [PATCH 11/14] set timeout instead of wait in email step definition --- e2e-tests/cypress/support/step_definitions/email_steps.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/e2e-tests/cypress/support/step_definitions/email_steps.ts b/e2e-tests/cypress/support/step_definitions/email_steps.ts index 5b21c7993..d31e2474e 100644 --- a/e2e-tests/cypress/support/step_definitions/email_steps.ts +++ b/e2e-tests/cypress/support/step_definitions/email_steps.ts @@ -39,8 +39,7 @@ Then('the user receives an e-mail containing the {string} link', (linkName: stri .find(userEMailSite.emailSubject) .contains(emailSubject) - cy.get('.email-content') - .wait(2000) + cy.get('.email-content', { timeout: 2000}) .find('.plain-text') .contains(linkPattern) .invoke('text') From b84bf9c868cb8fb2d1f2b5263dcb1455ae6f8755 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 14:15:43 +0100 Subject: [PATCH 12/14] set test workflow triggers back to push --- .github/workflows/test_dht-node.yml | 2 +- .github/workflows/test_federation.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_dht-node.yml b/.github/workflows/test_dht-node.yml index 5b260478d..5b3a65a70 100644 --- a/.github/workflows/test_dht-node.yml +++ b/.github/workflows/test_dht-node.yml @@ -1,6 +1,6 @@ name: gradido test_dht-node CI -on: none +on: push jobs: ############################################################################## diff --git a/.github/workflows/test_federation.yml b/.github/workflows/test_federation.yml index 0dd8e6196..2da78758e 100644 --- a/.github/workflows/test_federation.yml +++ b/.github/workflows/test_federation.yml @@ -1,6 +1,6 @@ name: gradido test_federation CI -on: none +on: push jobs: ############################################################################## From 4136592f11abcd05e42701eb1f621c55cca941dd Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 14:31:08 +0100 Subject: [PATCH 13/14] upgrade cypress to v12.7.0 --- e2e-tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/package.json b/e2e-tests/package.json index a6f817503..e8e8285e2 100644 --- a/e2e-tests/package.json +++ b/e2e-tests/package.json @@ -22,7 +22,7 @@ "@cypress/browserify-preprocessor": "^3.0.2", "@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/parser": "^5.38.0", - "cypress": "^10.4.0", + "cypress": "12.7.0", "eslint": "^8.23.1", "eslint-config-prettier": "^8.3.0", "eslint-config-standard": "^16.0.3", From e360212b58be13f856bae075ebe8066b3e778868 Mon Sep 17 00:00:00 2001 From: mahula Date: Thu, 2 Mar 2023 14:31:08 +0100 Subject: [PATCH 14/14] upgrade cypress to v12.7.0 --- e2e-tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e-tests/package.json b/e2e-tests/package.json index e8e8285e2..fc6403905 100644 --- a/e2e-tests/package.json +++ b/e2e-tests/package.json @@ -22,7 +22,7 @@ "@cypress/browserify-preprocessor": "^3.0.2", "@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/parser": "^5.38.0", - "cypress": "12.7.0", + "cypress": "^12.7.0", "eslint": "^8.23.1", "eslint-config-prettier": "^8.3.0", "eslint-config-standard": "^16.0.3",