diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml
index 01859332..252fd782 100644
--- a/.github/workflows/cypress.yml
+++ b/.github/workflows/cypress.yml
@@ -36,6 +36,12 @@ jobs:
- name: Run Cypress tests
uses: cypress-io/github-action@v6
+ env:
+ AUTH0_DOMAIN: ${{ secrets.AUTH0_DOMAIN }}
+ AUTH0_USERNAME: ${{ secrets.AUTH0_USERNAME }}
+ AUTH0_PASSWORD: ${{ secrets.AUTH0_PASSWORD }}
+ with:
+ command: yarn test:e2e:ci
- name: Upload screenshots
uses: actions/upload-artifact@v4
diff --git a/.gitignore b/.gitignore
index 90667264..781f0268 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,5 +22,9 @@ eslint-results.sarif
cypress/videos
*.DS_Store
+# Env
.env
+.env.test
+
+# VS Code
.vscode
diff --git a/cypress.config.ts b/cypress.config.ts
index bfeced1d..4641e285 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -1,15 +1,30 @@
+/* eslint-disable @typescript-eslint/no-namespace */
import { defineConfig } from 'cypress'
+declare global {
+ namespace NodeJS {
+ interface ProcessEnv {
+ AUTH0_DOMAIN: string
+ AUTH0_USERNAME: string
+ AUTH0_PASSWORD: string
+ }
+ }
+}
+
const config = defineConfig({
projectId: 'brkojt',
e2e: {
+ env: {
+ AUTH0_DOMAIN: process.env.AUTH0_DOMAIN,
+ AUTH0_USERNAME: process.env.AUTH0_USERNAME,
+ AUTH0_PASSWORD: process.env.AUTH0_PASSWORD
+ },
setupNodeEvents() { },
// Path to e2e specs folder
specPattern: './test/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
// Path to the fake data
fixturesFolder: './test/fake_data',
- supportFolder: './test/cypress/support',
- supportFile: './test/cypress/support/e2e.js',
+ supportFile: './test/cypress/support/e2e.ts',
baseUrl: 'http://localhost:3000',
testIsolation: false,
experimentalRunAllSpecs: true,
diff --git a/eslint.config.js b/eslint.config.js
index 50ee4c2b..fc63ca95 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -2,7 +2,7 @@ import globals from 'globals'
import eslintJsPlugin from '@eslint/js'
import tseslint from 'typescript-eslint'
import stylistic from '@stylistic/eslint-plugin'
-import pluginCypress from 'eslint-plugin-cypress'
+import pluginCypress from 'eslint-plugin-cypress/flat'
import pluginVue from 'eslint-plugin-vue'
import withNuxt from './.nuxt/eslint.config.mjs'
@@ -14,8 +14,8 @@ export default withNuxt(
'.output/*',
'.nuxt/*',
'coverage/*',
- 'cypress/*',
'.yarn/*',
+ 'test/vitest',
'typedefs/gqlTypes.ts'
]
},
@@ -36,7 +36,7 @@ export default withNuxt(
'@typescript-eslint': tseslint.plugin,
'@stylistic': stylistic
},
- ignores: ['./typeDefs/gqlTypes.ts', './typesgeneratorconfig.ts', 'cypress/**/*'],
+ ignores: ['./typeDefs/gqlTypes.ts', './typesgeneratorconfig.ts'],
rules: {
...tseslint.configs.recommended,
// TS specific rules
@@ -94,32 +94,12 @@ export default withNuxt(
'vue/html-indent': ['error', 4]
}
},
- // Linting for tests (cypress + pinia)
+ // Linting for Cypress (https://www.npmjs.com/package/eslint-plugin-cypress)
{
- languageOptions: {
- globals: {
- cy: true,
- it: true,
- describe: true,
- context: true,
- beforeEach: true,
- before: true
- }
- },
- files: ['cypress/e2e/*.ts', 'test/**/*'],
- plugins: {
- cypress: pluginCypress
- },
+ files: ['test/cypress/**/*'],
+ ...pluginCypress.configs.recommended,
rules: {
- //this is to support chai chaining syntax
- '@typescript-eslint/no-unused-expressions': 'off'
- // 'cypress/no-assigning-return-values": "error",
- // "cypress/no-unnecessary-waiting": "error",
- // "cypress/assertion-before-screenshot": "warn",
- // "cypress/no-force": "warn",
- // "cypress/no-async-tests": "error",
- // "cypress/no-async-before": "error",
- // "cypress/no-pause": "error"
+ 'cypress/no-unnecessary-waiting': 'off'
}
}
)
diff --git a/package.json b/package.json
index 6585b3db..6b02fe6c 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,8 @@
"test": "yarn test:pinia --run && yarn test:e2e",
"test:pinia": "nuxi prepare && nuxi generate && vitest",
"test:pinia:coverage": "vitest run --coverage",
- "test:e2e": "cypress run --e2e --browser chrome --record --key 04a1fe54-0011-407b-b7d7-fcb9b2daf1e6"
+ "test:e2e": "dotenv -e .env.test -o -- cypress open",
+ "test:e2e:ci": "dotenv -e .env.test -o -- cypress run --e2e"
},
"packageManager": "yarn@4.4.0",
"engines": {
@@ -59,6 +60,7 @@
"autoprefixer": "^10.4.20",
"cypress": "^13.13.2",
"cypress-plugin-tab": "^1.0.5",
+ "dotenv-cli": "^8.0.0",
"eslint": "^9.8.0",
"eslint-plugin-cypress": "^3.4.0",
"eslint-plugin-json": "^4.0.1",
diff --git a/test/cypress/e2e/moderationDashboard.cy.ts b/test/cypress/e2e/moderationDashboard.cy.ts
index bf67f113..35ba5d59 100644
--- a/test/cypress/e2e/moderationDashboard.cy.ts
+++ b/test/cypress/e2e/moderationDashboard.cy.ts
@@ -1,417 +1,109 @@
-import 'cypress-real-events'
-import 'cypress-plugin-tab'
import enUS from '../../../i18n/locales/en.json'
+import fakeSubmissionResponse from '../../fake_data/moderation_dashboard/fakeSubmissionResponse.json'
+import { aliasQuery } from '../utils'
-const FAKE_SUBMISSION_RESPONSE_PATH = 'moderation_dashboard/fakeSubmissionResponse.json'
-
-describe(
- 'Moderation dashboard',
- () => {
- // Before starting the execution, we need to load the fixture data using "this" context of the
- // test object. We need to use regular function() callbacks instead of arrow functions when
- // we need to access the "this" context.
- before(function() {
- cy.fixture(FAKE_SUBMISSION_RESPONSE_PATH).then(fakeSubmissionResponse => {
- this.fakeSubmissionResponse = fakeSubmissionResponse
- })
- })
-
- context('Landscape mode', () => {
- beforeEach(function() {
- // The resolution is in the beforeEach() instead of before() to
- // prevent Cypress from defaulting to other screen sizes between tests.
- cy.viewport('macbook-16')
- cy.visit('/login')
- Cypress.session.clearCurrentSessionData()
-
- // This intercepts the call to the GraphQL API in order to use fake data in the tests to protect the real data.
- cy.intercept('POST', '**/', req => {
- if (req.body.query && req.body.query.includes('query Submissions')) {
- req.reply({
- statusCode: 200,
- body: this.fakeSubmissionResponse
- })
- } else {
- req.continue()
- }
- }).as('getSubmissions')
-
- cy.origin('https://findadoc.jp.auth0.com/', () => {
- cy.get('input#username').should('be.visible').type('findadoctest@proton.me')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- cy.get('input#password').should('be.visible').type('vCnL5J8agHg6m2f')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- })
-
- cy.url({ timeout: 10000 }).should('equal', 'http://localhost:3000/')
-
- /* Chaining of visit was used here to make sure the user was logged in and that it would
- 100 percent visit moderation */
- cy.get('[data-testid=top-nav-mod-link]').click().visit('/moderation')
-
- cy.url({ timeout: 10000 }).should('include', '/moderation')
-
- cy.wait('@getSubmissions')
- })
-
- it('shows mod dashboard left navbar buttons with correct counts and functionality', () => {
- // The number for include text is for the status in the fake data.
- cy.get('[data-testid=mod-dashboard-leftnav-for-review]')
- .should('exist')
- .should(
- 'include.text',
- enUS.modDashboardLeftNav.forReview
- )
- .should(
- 'include.text',
- '1'
- )
-
- cy.get('[data-testid=mod-dashboard-leftnav-approved]')
- .should('exist')
- .should(
- 'include.text',
- enUS.modDashboardLeftNav.approved
- )
- .should(
- 'include.text',
- '1'
- )
-
- cy.get('[data-testid=mod-dashboard-leftnav-rejected]')
- .should('exist')
- .should(
- 'include.text',
- enUS.modDashboardLeftNav.rejected
- )
- .should(
- 'include.text',
- '0'
- )
-
- cy.get('[data-testid="mod-submission-list-item-1"]').should('exist')
-
- cy.get('[data-testid=mod-dashboard-leftnav-approved]')
- .click()
-
- cy.get('[data-testid="mod-submission-list-item-1"]').should('exist')
-
- cy.get('[data-testid=mod-dashboard-leftnav-rejected]')
- .click()
-
- cy.get('[data-testid="mod-submission-list-item-1"]').should('not.exist')
-
- cy.get('[data-testid=mod-dashboard-leftnav-for-review]')
- .click()
-
- cy.get('[data-testid="mod-submission-list-item-1"]').should('exist')
- })
-
- it('it shows the moderation top nav', () => {
- cy.get('[data-testid="mod-submission-list-item-1"]').click()
- cy.get('[data-testid="mod-edit-submission-copy-submission-id"]').click()
-
- // Check that the value copied to the clipboard is the same that's displayed.
- const clipboardResult = cy.window().then(win => win.navigator.clipboard.readText())
-
- // The timeout is to give time for the clipboard to be read.
- clipboardResult.should('exist', 10000)
- })
-
- it('toggle between submissions and healthcare professionals submissions', () => {
- cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('not.exist')
- cy.get('[data-testid="mod-facility-list-item-1"]').should('not.exist')
- cy.get('[data-testid="mod-submission-list-item-1').should('exist')
-
- cy.get('[data-testid="submission-type-select"]').select('FACILITIES')
- cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('not.exist')
- cy.get('[data-testid="mod-facility-list-item-1"]').should('exist')
- cy.get('[data-testid="mod-submission-list-item-1').should('not.exist')
-
- cy.get('[data-testid="submission-type-select"]').select('HEALTHCARE_PROFESSIONALS')
- cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('exist')
- cy.get('[data-testid="mod-facility-list-item-1"]').should('not.exist')
- cy.get('[data-testid="mod-submission-list-item-1').should('not.exist')
-
- cy.get('[data-testid="submission-type-select"]').select('SUBMISSIONS')
- cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('not.exist')
- cy.get('[data-testid="mod-facility-list-item-1"]').should('not.exist')
- cy.get('[data-testid="mod-submission-list-item-1').should('exist')
- })
+before(() => {
+ cy.login()
+})
- after(() => {
- Cypress.session.clearCurrentSessionData()
- })
+describe('Moderation dashboard', () => {
+ before(() => {
+ cy.intercept('POST', '**/', req => {
+ aliasQuery(req, 'query Submissions', fakeSubmissionResponse)
})
- }
-)
-describe('Moderation Edit Submission Form', () => {
- before(function() {
- cy.fixture(FAKE_SUBMISSION_RESPONSE_PATH).then(fakeSubmissionResponse => {
- this.fakeSubmissionResponse = fakeSubmissionResponse
- })
+ cy.visit('/moderation')
+ cy.wait('@query Submissions')
})
context('Landscape mode', () => {
- before(function() {
+ beforeEach(() => {
cy.viewport('macbook-16')
-
- cy.visit('/login')
- Cypress.session.clearCurrentSessionData()
-
- // This intercepts the call to the graphQL api in order to use fake data in the tests to protect
- // the real data.
- cy.intercept('POST', '**/', req => {
- if (req.body.query && req.body.query.includes('query Submissions')) {
- req.reply({
- statusCode: 200,
- body: this.fakeSubmissionResponse
- })
- } else {
- req.continue()
- }
- }).as('getSubmissions')
-
- cy.origin('https://findadoc.jp.auth0.com/', () => {
- cy.get('input#username').should('be.visible').type('findadoctest@proton.me')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- cy.get('input#password').should('be.visible').type('vCnL5J8agHg6m2f')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- })
-
- cy.url({ timeout: 10000 }).should('equal', 'http://localhost:3000/')
-
- /* Chaining of visit was used here to make sure the user was logged in and that it would
- 100 percent visit moderation */
- cy.get('[data-testid=top-nav-mod-link]').click().visit('/moderation')
-
- cy.url({ timeout: 10000 }).should('include', '/moderation')
-
- cy.wait('@getSubmissions')
-
- cy.get('[data-testid="mod-submission-list-item-1"]').click()
- })
-
- after(() => {
- Cypress.session.clearCurrentSessionData()
- })
-
- it('contains the following input fields', () => {
- cy.get('[data-testid="submission-form-nameEn"]').should('exist')
- cy.get('[data-testid="submission-form-nameJa"]').should('exist')
- cy.get('[data-testid="submission-form-phone"]').should('exist')
- cy.get('[data-testid="submission-form-email"]').should('exist')
- cy.get('[data-testid="submission-form-website"]').should('exist')
- cy.get('[data-testid="submission-form-postalCode"]').should('exist')
- cy.get('[data-testid="submission-form-cityEn"]').should('exist')
- cy.get('[data-testid="submission-form-addressLine1En"]').should('exist')
- cy.get('[data-testid="submission-form-addressLine2En"]').should('exist')
- cy.get('[data-testid=submission-form-cityJa]').should('exist')
- cy.get('[data-testid="submission-form-addressLine1Ja"]').should('exist')
- cy.get('[data-testid="submission-form-addressLine2Ja"]').should('exist')
- cy.get('[data-testid="submission-form-google-maps"]').should('exist')
- cy.get('[data-testid="submission-form-mapLatitude"]').should('exist')
- cy.get('[data-testid="submission-form-mapLongitude"]').should('exist')
- })
-
- it('contains the following left nav buttons for navigation', () => {
- cy.get('[data-testid="submission-form-leftnav-contact-information"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.contactInformation)
- cy.get('[data-testid="submission-form-leftnav-addresses"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.addresses)
- cy.get('[data-testid="submission-form-leftnav-google-maps-information"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.googleMapsInformation)
- cy.get('[data-testid="submission-form-leftnav-healthcare-professional-ids"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.healthcareProfessionalIds)
- cy.get('[data-testid="submission-form-leftnav-change-log"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.changeLog)
- cy.get('[data-testid="submission-form-leftnav-healthcare-professional-name"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.healthcareProfessionalName)
- cy.get('[data-testid="submission-form-leftnav-healthcare-professional-medical-info"]').should('exist')
- .should('contain', enUS.modPanelSubmissionLeftNavbar.healthcareProfessionalMedicalInfo)
- })
-
- it('should contain the following select field', () => {
- cy.get('[data-testid="submission-form-prefectureEn"]').should('exist')
- cy.get('[data-testid="submission-form-prefectureJa"]').should('exist')
- cy.get('[data-testid="submission-form-accepted-insurances"]').should('exist')
- cy.get('[data-testid="submission-form-degrees"]').should('exist')
- cy.get('[data-testid="submission-form-specialties"]').should('exist')
- cy.get('[data-testid="submission-form-locales"]').should('exist')
})
- it('should autofill the form', function() {
- const submission = this.fakeSubmissionResponse.data.submissions[1].facility
-
- cy.get('[data-testid="submission-form-nameEn"]').find('input')
- .should('have.value', submission.nameEn)
-
- cy.get('[data-testid="submission-form-nameJa"]').find('input')
- .should('have.value', submission.nameJa)
-
- cy.get('[data-testid="submission-form-phone"]').find('input')
- .should('have.value', submission.contact.phone)
- })
-
- it('should be able to type in all input fields', () => {
- cy.get('[data-testid="submission-form-nameEn"]').find('input').type('Hospital')
- cy.get('[data-testid="submission-form-nameJa"]').find('input').type('立川中央病院')
- cy.get('[data-testid="submission-form-phone"]').find('input').type('08080939393')
- cy.get('[data-testid="submission-form-email"]').find('input').type('example@mail.com')
- cy.get('[data-testid="submission-form-website"]').find('input').type('http://example.com')
- cy.get('[data-testid="submission-form-postalCode"]').find('input').type('180-0000')
- cy.get('[data-testid="submission-form-cityEn"]').find('input').type('Shibuya')
- cy.get('[data-testid="submission-form-addressLine1En"]').find('input').type('some address line 1')
- cy.get('[data-testid="submission-form-addressLine2En"]').find('input').type('some address line 2')
- cy.get('[data-testid=submission-form-cityJa]').find('input').type('渋谷区')
- cy.get('[data-testid="submission-form-addressLine1Ja"]').find('input').type('道の駅')
- cy.get('[data-testid="submission-form-addressLine2Ja"]').find('input').type('道の')
- cy.get('[data-testid="submission-form-google-maps"]')
- .find('input')
- .type('www.google.com/maps/place/82+Yamatech%C5%8D,+Naka+Ward,+Yokohama'
- + ',+Kanagawa+231-0862,+Japan/@35.437123,139.651471,16z/data=!4m6!3m5!1s'
- + '0x60185d201648e7c1:0x8f37d37bb381e29!8m2!3d35.4371228!4d139.6514712!16s%2Fg%2F11clpxxvx5?hl=en-US&entry=ttu')
- cy.get('[data-testid="submission-form-mapLatitude"]').find('input').type('35.437123')
- cy.get('[data-testid="submission-form-mapLongitude"]').find('input').type('139.651471')
- })
-
- it('should be able to select a field', () => {
- cy.get('[data-testid="submission-form-prefectureEn"]').select('Hokkaido')
- cy.get('[data-testid="submission-form-prefectureJa"]').select('北海道')
- })
-
- it('should be display error messages', () => {
- cy.get('[data-testid="submission-form-nameEn"]').find('input').clear().type('立川中央病院').realPress('Tab')
- cy.get('[data-testid="submission-form-nameEn"]')
- .find('p').should('exist').contains('Invalid English Name')
-
- cy.get('[data-testid="submission-form-nameJa"]').find('input').clear().type('Tachikawa Hospital').realPress('Tab')
- cy.get('[data-testid="submission-form-nameJa"]')
- .find('p').should('exist').contains('Invalid Japanese Name')
-
- cy.get('[data-testid="submission-form-phone"]').find('input').clear().type('Hello').realPress('Tab')
- cy.get('[data-testid="submission-form-phone"]')
- .find('p').should('exist').contains('Invalid Phone Number')
-
- cy.get('[data-testid="submission-form-email"]').find('input').clear().type('example').realPress('Tab')
- cy.get('[data-testid="submission-form-email"]')
- .find('p').should('exist').contains('Invalid Email Address')
-
- cy.get('[data-testid="submission-form-website"]').find('input').clear().type('example').realPress('Tab')
- cy.get('[data-testid="submission-form-website"]')
- .find('p').should('exist').contains('Invalid Website URL')
-
- cy.get('[data-testid="submission-form-postalCode"]').find('input').clear().type('180-0').realPress('Tab')
- cy.get('[data-testid="submission-form-postalCode"]')
- .find('p').should('exist').contains('Invalid Postal Code')
-
- cy.get('[data-testid="submission-form-cityEn"]').find('input').clear().type('渋谷区').realPress('Tab')
- cy.get('[data-testid="submission-form-cityEn"]')
- .find('p').should('exist').contains('Invalid English City Name')
-
- cy.get('[data-testid="submission-form-addressLine1En"]').find('input').clear().type('道の駅').realPress('Tab')
- cy.get('[data-testid="submission-form-addressLine1En"]')
- .find('p').should('exist').contains('Invalid English Address')
-
- cy.get('[data-testid="submission-form-addressLine2En"]').find('input').clear().type('道の駅').realPress('Tab')
- cy.get('[data-testid="submission-form-addressLine2En"]')
- .find('p').should('exist').contains('Invalid English Address')
-
- cy.get('[data-testid=submission-form-cityJa]').find('input').clear().type('Shibuya').realPress('Tab')
- cy.get('[data-testid=submission-form-cityJa]')
- .find('p').should('exist').contains('Invalid Japanese City Name')
-
- cy.get('[data-testid="submission-form-addressLine1Ja"]')
- .find('input').clear().type('Peanutbutter street').realPress('Tab')
- cy.get('[data-testid="submission-form-addressLine1Ja"]').should('exist').contains('Invalid Japanese Address')
-
- cy.get('[data-testid="submission-form-addressLine2Ja"]').find('input').clear().type('Jelly street').realPress('Tab')
- cy.get('[data-testid="submission-form-addressLine2Ja"]').should('exist').contains('Invalid Japanese Address')
-
- cy.get('[data-testid="submission-form-mapLatitude"]')
- .find('input').clear().type('Not Number Latitude').realPress('Tab')
- cy.get('[data-testid="submission-form-mapLatitude"]')
- .find('p').should('exist').contains('Invalid Latitude')
-
- cy.get('[data-testid="submission-form-mapLongitude"]')
- .find('input').clear().type('Not Number Longitude').realPress('Tab')
- cy.get('[data-testid="submission-form-mapLongitude"]')
- .find('p').should('exist').contains('Invalid Longitude')
- })
- })
-})
-
-describe('Moderation Edit Submission Modal', () => {
- before(function() {
- cy.fixture(FAKE_SUBMISSION_RESPONSE_PATH).then(fakeSubmissionResponse => {
- console.log(fakeSubmissionResponse)
- this.fakeSubmissionResponse = fakeSubmissionResponse
- })
- })
-
- context('Landscape mode', () => {
- before(function() {
- cy.viewport('macbook-16')
-
- cy.visit('/login')
- Cypress.session.clearCurrentSessionData()
-
- // This intercepts the call to the graphQL api in order to use fake data in the tests to protect
- // the real data.
- cy.intercept('POST', '**/', req => {
- if (req.body.query && req.body.query.includes('query Submissions')) {
- req.reply({
- statusCode: 200,
- body: this.fakeSubmissionResponse
- })
- } else {
- req.continue()
- }
- }).as('getSubmissions')
-
- cy.origin('https://findadoc.jp.auth0.com/', () => {
- cy.get('input#username').should('be.visible').type('findadoctest@proton.me')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- cy.get('input#password').should('be.visible').type('vCnL5J8agHg6m2f')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- })
-
- cy.url({ timeout: 10000 }).should('equal', 'http://localhost:3000/')
-
- cy.get('[data-testid=top-nav-mod-link]').click().visit('/moderation')
-
- cy.url({ timeout: 10000 }).should('include', '/moderation')
-
- cy.wait('@getSubmissions')
-
+ it('shows mod dashboard left navbar buttons with correct counts and functionality', () => {
+ // The number for include text is for the status in the fake data.
+ cy.get('[data-testid=mod-dashboard-leftnav-for-review]')
+ .should('exist')
+ .should(
+ 'include.text',
+ enUS.modDashboardLeftNav.forReview
+ )
+ .should(
+ 'include.text',
+ '1'
+ )
+
+ cy.get('[data-testid=mod-dashboard-leftnav-approved]')
+ .should('exist')
+ .should(
+ 'include.text',
+ enUS.modDashboardLeftNav.approved
+ )
+ .should(
+ 'include.text',
+ '1'
+ )
+
+ cy.get('[data-testid=mod-dashboard-leftnav-rejected]')
+ .should('exist')
+ .should(
+ 'include.text',
+ enUS.modDashboardLeftNav.rejected
+ )
+ .should(
+ 'include.text',
+ '0'
+ )
+
+ cy.get('[data-testid="mod-submission-list-item-1"]').should('exist')
+
+ cy.get('[data-testid=mod-dashboard-leftnav-approved]')
+ .click()
+
+ cy.get('[data-testid="mod-submission-list-item-1"]').should('exist')
+
+ cy.get('[data-testid=mod-dashboard-leftnav-rejected]')
+ .click()
+
+ cy.get('[data-testid="mod-submission-list-item-1"]').should('not.exist')
+
+ cy.get('[data-testid=mod-dashboard-leftnav-for-review]')
+ .click()
+
+ cy.get('[data-testid="mod-submission-list-item-1"]').should('exist')
+ })
+
+ it('toggle between submissions and healthcare professionals submissions', () => {
+ cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('not.exist')
+ cy.get('[data-testid="mod-facility-list-item-1"]').should('not.exist')
+ cy.get('[data-testid="mod-submission-list-item-1').should('exist')
+
+ cy.get('[data-testid="submission-type-select"]').select('FACILITIES')
+ cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('not.exist')
+ cy.get('[data-testid="mod-facility-list-item-1"]').should('exist')
+ cy.get('[data-testid="mod-submission-list-item-1').should('not.exist')
+
+ cy.get('[data-testid="submission-type-select"]').select('HEALTHCARE_PROFESSIONALS')
+ cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('exist')
+ cy.get('[data-testid="mod-facility-list-item-1"]').should('not.exist')
+ cy.get('[data-testid="mod-submission-list-item-1').should('not.exist')
+
+ cy.get('[data-testid="submission-type-select"]').select('SUBMISSIONS')
+ cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').should('not.exist')
+ cy.get('[data-testid="mod-facility-list-item-1"]').should('not.exist')
+ cy.get('[data-testid="mod-submission-list-item-1').should('exist')
+ })
+
+ it('it shows the moderation top nav', () => {
cy.get('[data-testid="mod-submission-list-item-1"]').click()
- })
+ cy.get('[data-testid="mod-edit-submission-copy-submission-id"]').click()
- after(() => {
- Cypress.session.clearCurrentSessionData()
- })
+ // Check that the value copied to the clipboard is the same that's displayed.
+ const clipboardResult = cy.window().then(win => win.navigator.clipboard.readText())
- it('should display modal if user navigates back with unsaved changes', () => {
- // When the user clicks the back button on their browser with unsaved changes...
- cy.get('[data-testid="submission-form-nameEn"]').find('input').type('Hospital')
- cy.go('back')
- // ...the modal with the confirmation button should be visible.
- cy.get('[data-testid="submission-form-modal"]').should('be.visible')
- // When the user clicks the confirmation button on the modal...
- cy.get('[data-testid="submission-form-modal-confirmation-btn"]').click()
- // ...they should be navigated back to the moderation screen.
- cy.location('pathname').should('eq', '/moderation')
- })
-
- it('should not display modal if user navigates back without making changes', () => {
- cy.get('[data-testid="mod-submission-list-item-1"]').click()
- // When the user clicks the back button on their browser without making changes...
- cy.go('back')
- // ...the modal with the confirmation button should not exist...
- cy.get('[data-testid="submission-form-modal"]').should('not.exist')
- // ... and they should be navigated back to the moderation screen.
- cy.location('pathname').should('eq', '/moderation')
+ // The timeout is to give time for the clipboard to be read.
+ clipboardResult.should('exist', 10000)
})
})
})
diff --git a/test/cypress/e2e/moderationEditFacility.cy.ts b/test/cypress/e2e/moderationEditFacility.cy.ts
index 018dfbe6..80b1eb07 100644
--- a/test/cypress/e2e/moderationEditFacility.cy.ts
+++ b/test/cypress/e2e/moderationEditFacility.cy.ts
@@ -1,68 +1,37 @@
-import 'cypress-real-events'
-import 'cypress-plugin-tab'
-import facilityData from '../../fake_data/moderation_dashboard/fakeModFacilityData.json'
import enUS from '../../../i18n/locales/en.json'
+import fakeFacilityResult from '../../fake_data/moderation_dashboard/fakeModFacilityData.json'
+import { aliasQuery } from '../utils'
-const FAKE_FACILITY_RESPONSE_PATH = 'moderation_dashboard/fakeModFacilityData.json'
+before(() => {
+ cy.login()
+})
describe('Moderation edit facility form', () => {
context('Landscape mode', () => {
- // Before starting the execution, we need to load the fixture data using "this" context of the
- // test object. We need to use regular function() callbacks instead of arrow functions when
- // we need to access the "this" context.
- before(function() {
- cy.fixture(FAKE_FACILITY_RESPONSE_PATH).then(fakeFacilityResult => {
- this.fakeFacilityResult = fakeFacilityResult
- })
-
- cy.viewport('macbook-16')
- cy.visit('/login')
- Cypress.session.clearCurrentSessionData()
-
- // This intercepts the call to the GraphQL API in order to use fake data in the tests to protect the real data.
+ before(() => {
cy.intercept('POST', '**/', req => {
- if (req.body.query && req.body.query.includes('query Facilities')) {
- req.reply({
- statusCode: 200,
- body: this.fakeFacilityResult
- })
- } else {
- req.continue()
- }
- }).as('getFacilities')
-
- cy.origin('https://findadoc.jp.auth0.com/', () => {
- cy.get('input#username').should('be.visible').type('findadoctest@proton.me')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- cy.get('input#password').should('be.visible').type('vCnL5J8agHg6m2f')
- cy.get('[data-action-button-primary]').should('be.visible').click()
+ aliasQuery(req, 'query Facilities', fakeFacilityResult)
})
- cy.url({ timeout: 10000 }).should('equal', 'http://localhost:3000/')
+ cy.visit('/moderation')
- /* Chaining of visit was used here to make sure the user was logged in and that it would
- 100 percent visit moderation */
- cy.get('[data-testid=top-nav-mod-link]').click().visit('/moderation')
+ cy.wait('@query Facilities')
- cy.url({ timeout: 10000 }).should('include', '/moderation')
-
- cy.wait('@getFacilities')
cy.get('[data-testid="submission-type-select"]').select('FACILITIES')
-
cy.get('[data-testid="mod-facility-list-item-1"]').click()
})
- after(() => {
- Cypress.session.clearCurrentSessionData()
+ beforeEach(() => {
+ cy.viewport('macbook-16')
})
- it('contains the following fields and buttons in the topbar'), () => {
+ it('contains the following fields and buttons in the topbar', () => {
cy.get('[data-testid="mod-edit-facility-hp-topbar-update"]').should('exist')
.contains(enUS.modEditFacilityOrHPTopbar.updateAndExit)
cy.get('[data-testid="mod-edit-facility-hp-topbar-delete"]').should('exist')
.contains(enUS.modEditFacilityOrHPTopbar.delete)
cy.get('[data-testid="mod-edit-facility-hp-topbar-copy-id"]').should('exist')
- }
+ })
it('it copies the selected id', () => {
cy.get('[data-testid="mod-edit-facility-hp-topbar-copy-id"]').click()
@@ -100,35 +69,35 @@ describe('Moderation edit facility form', () => {
it('should autofill all the form fields for an existing facility', () => {
cy.get('[data-testid="mod-facility-section-nameEn"]')
- .find('input').should('have.value', facilityData.data.facilities[0].nameEn)
+ .find('input').should('have.value', fakeFacilityResult.data.facilities[0].nameEn)
cy.get('[data-testid="mod-facility-section-nameJa"]')
- .find('input').should('have.value', facilityData.data.facilities[0].nameJa)
+ .find('input').should('have.value', fakeFacilityResult.data.facilities[0].nameJa)
cy.get('[data-testid="mod-facility-section-phone"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.phone)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.phone)
cy.get('[data-testid="mod-facility-section-email"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.email)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.email)
cy.get('[data-testid="mod-facility-section-website"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.website)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.website)
cy.get('[data-testid="mod-facility-section-postalCode"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.postalCode)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.postalCode)
cy.get('[data-testid="mod-facility-section-cityEn"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.cityEn)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.cityEn)
cy.get('[data-testid="mod-facility-section-addressLine1En"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.addressLine1En)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.addressLine1En)
cy.get('[data-testid="mod-facility-section-addressLine2En"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.addressLine2En)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.addressLine2En)
cy.get('[data-testid="mod-facility-section-cityJa"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.cityJa)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.cityJa)
cy.get('[data-testid="mod-facility-section-addressLine1Ja"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.addressLine1Ja)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.addressLine1Ja)
cy.get('[data-testid="mod-facility-section-addressLine2Ja"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.address.addressLine2Ja)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.address.addressLine2Ja)
cy.get('[data-testid="mod-facility-section-google-maps"]').find('input')
- .should('have.value', facilityData.data.facilities[0].contact.googleMapsUrl)
+ .should('have.value', fakeFacilityResult.data.facilities[0].contact.googleMapsUrl)
cy.get('[data-testid="mod-facility-section-mapLatitude"]').find('input')
- .should('have.value', facilityData.data.facilities[0].mapLatitude)
+ .should('have.value', fakeFacilityResult.data.facilities[0].mapLatitude)
cy.get('[data-testid="mod-facility-section-mapLongitude"]').find('input')
- .should('have.value', facilityData.data.facilities[0].mapLongitude)
+ .should('have.value', fakeFacilityResult.data.facilities[0].mapLongitude)
})
it('should be able to type in all input fields', () => {
diff --git a/test/cypress/e2e/moderationEditHealthcareProfessional.cy.ts b/test/cypress/e2e/moderationEditHealthcareProfessional.cy.ts
index 9f203387..0279504e 100644
--- a/test/cypress/e2e/moderationEditHealthcareProfessional.cy.ts
+++ b/test/cypress/e2e/moderationEditHealthcareProfessional.cy.ts
@@ -1,59 +1,29 @@
-import 'cypress-real-events'
-import 'cypress-plugin-tab'
+import fakeHealthcareProfessionalResult from '../../fake_data/moderation_dashboard/fakeModHealthcareProfessionalData.json'
+import { aliasQuery } from '../utils'
-const FAKE_HEALTHCARE_PROFESSIONAL_RESPONSE_PATH = 'moderation_dashboard/fakeModHealthcareprofessionalData.json'
-const AUTH_URL = 'https://findadoc.jp.auth0.com/'
-const SITE_URL = 'http://localhost:3000/'
+before(() => {
+ cy.login()
+})
describe('Moderation edit professional healthcare form', () => {
context('Landscape mode', () => {
- // Before starting the execution, we need to load the fixture data using "this" context of the
- // test object. We need to use regular function() callbacks instead of arrow functions when
- // we need to access the "this" context.
- before(function() {
- cy.fixture(FAKE_HEALTHCARE_PROFESSIONAL_RESPONSE_PATH).then(fakeHealthcareprofessionalResult => {
- this.fakeHealthcareprofessionalResult = fakeHealthcareprofessionalResult
- })
-
+ before(() => {
cy.viewport('macbook-16')
- cy.visit('/login', { timeout: 10000 })
- Cypress.session.clearCurrentSessionData()
- // This intercepts the call to the GraphQL API in order to use fake data in the tests to protect the real data.
cy.intercept('POST', '**/', req => {
- if (req.body.query && req.body.query.includes('query HealthcareProfessionals')) {
- req.reply({
- statusCode: 200,
- body: this.fakeHealthcareprofessionalResult
- })
- } else {
- req.continue()
- }
- }).as('getHealthcareProfessionals')
-
- cy.origin(AUTH_URL, () => {
- cy.get('input#username').should('be.visible').type('findadoctest@proton.me')
- cy.get('[data-action-button-primary]').should('be.visible').click()
- cy.get('input#password').should('be.visible').type('vCnL5J8agHg6m2f')
- cy.get('[data-action-button-primary]').should('be.visible').click()
+ aliasQuery(req, 'HealthcareProfessionalSearchFilters', fakeHealthcareProfessionalResult)
})
- cy.url({ timeout: 10000 }).should('equal', SITE_URL)
+ cy.visit('/moderation')
- /* Chaining of visit was used here to make sure the user was logged in and that it would
- 100 percent visit moderation */
- cy.get('[data-testid=top-nav-mod-link]', { timeout: 10000 }).click().visit('/moderation')
+ cy.wait('@HealthcareProfessionalSearchFilters')
- cy.url({ timeout: 10000 }).should('include', '/moderation')
-
- cy.wait('@getHealthcareProfessionals', { timeout: 10000 })
- cy.get('[data-testid="submission-type-select"]', { timeout: 10000 }).select('HEALTHCARE_PROFESSIONALS')
-
- cy.get('[data-testid="mod-healthcare-professional-list-item-1"]', { timeout: 10000 }).click()
+ cy.get('[data-testid="submission-type-select"]').select('HEALTHCARE_PROFESSIONALS')
+ cy.get('[data-testid="mod-healthcare-professional-list-item-1"]').click()
})
- after(() => {
- Cypress.session.clearCurrentSessionData()
+ beforeEach(() => {
+ cy.viewport('macbook-16')
})
it('contains the following input and select fields', () => {
diff --git a/test/cypress/e2e/moderationEditSubmissionForm.cy.ts b/test/cypress/e2e/moderationEditSubmissionForm.cy.ts
new file mode 100644
index 00000000..c777c395
--- /dev/null
+++ b/test/cypress/e2e/moderationEditSubmissionForm.cy.ts
@@ -0,0 +1,168 @@
+import enUS from '../../../i18n/locales/en.json'
+import { aliasQuery } from '../utils'
+import fakeSubmissionResponse from '../../fake_data/moderation_dashboard/fakeSubmissionResponse.json'
+
+before(() => {
+ cy.login()
+})
+
+describe('Moderation Edit Submission Form', () => {
+ context('Landscape mode', () => {
+ before(() => {
+ cy.intercept('POST', '**/', req => {
+ aliasQuery(req, 'query Submissions', fakeSubmissionResponse)
+ })
+
+ cy.visit('/moderation')
+ cy.wait('@query Submissions')
+ cy.get('[data-testid="mod-submission-list-item-1"]').click()
+ })
+
+ beforeEach(() => {
+ cy.viewport('macbook-16')
+ })
+
+ it('contains the following input fields', () => {
+ cy.get('[data-testid="submission-form-nameEn"]').should('exist')
+ cy.get('[data-testid="submission-form-nameJa"]').should('exist')
+ cy.get('[data-testid="submission-form-phone"]').should('exist')
+ cy.get('[data-testid="submission-form-email"]').should('exist')
+ cy.get('[data-testid="submission-form-website"]').should('exist')
+ cy.get('[data-testid="submission-form-postalCode"]').should('exist')
+ cy.get('[data-testid="submission-form-cityEn"]').should('exist')
+ cy.get('[data-testid="submission-form-addressLine1En"]').should('exist')
+ cy.get('[data-testid="submission-form-addressLine2En"]').should('exist')
+ cy.get('[data-testid=submission-form-cityJa]').should('exist')
+ cy.get('[data-testid="submission-form-addressLine1Ja"]').should('exist')
+ cy.get('[data-testid="submission-form-addressLine2Ja"]').should('exist')
+ cy.get('[data-testid="submission-form-google-maps"]').should('exist')
+ cy.get('[data-testid="submission-form-mapLatitude"]').should('exist')
+ cy.get('[data-testid="submission-form-mapLongitude"]').should('exist')
+ })
+
+ it('contains the following left nav buttons for navigation', () => {
+ cy.get('[data-testid="submission-form-leftnav-contact-information"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.contactInformation)
+ cy.get('[data-testid="submission-form-leftnav-addresses"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.addresses)
+ cy.get('[data-testid="submission-form-leftnav-google-maps-information"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.googleMapsInformation)
+ cy.get('[data-testid="submission-form-leftnav-healthcare-professional-ids"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.healthcareProfessionalIds)
+ cy.get('[data-testid="submission-form-leftnav-change-log"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.changeLog)
+ cy.get('[data-testid="submission-form-leftnav-healthcare-professional-name"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.healthcareProfessionalName)
+ cy.get('[data-testid="submission-form-leftnav-healthcare-professional-medical-info"]').should('exist')
+ .should('contain', enUS.modPanelSubmissionLeftNavbar.healthcareProfessionalMedicalInfo)
+ })
+
+ it('should contain the following select field', () => {
+ cy.get('[data-testid="submission-form-prefectureEn"]').should('exist')
+ cy.get('[data-testid="submission-form-prefectureJa"]').should('exist')
+ cy.get('[data-testid="submission-form-accepted-insurances"]').should('exist')
+ cy.get('[data-testid="submission-form-degrees"]').should('exist')
+ cy.get('[data-testid="submission-form-specialties"]').should('exist')
+ cy.get('[data-testid="submission-form-locales"]').should('exist')
+ })
+
+ it('should autofill the form', () => {
+ const submission = fakeSubmissionResponse.data.submissions[1].facility
+
+ cy.get('[data-testid="submission-form-nameEn"]').find('input')
+ .should('have.value', submission.nameEn)
+
+ cy.get('[data-testid="submission-form-nameJa"]').find('input')
+ .should('have.value', submission.nameJa)
+
+ cy.get('[data-testid="submission-form-phone"]').find('input')
+ .should('have.value', submission.contact.phone)
+ })
+
+ it('should be able to type in all input fields', () => {
+ cy.get('[data-testid="submission-form-nameEn"]').find('input').type('Hospital')
+ cy.get('[data-testid="submission-form-nameJa"]').find('input').type('立川中央病院')
+ cy.get('[data-testid="submission-form-phone"]').find('input').type('08080939393')
+ cy.get('[data-testid="submission-form-email"]').find('input').type('example@mail.com')
+ cy.get('[data-testid="submission-form-website"]').find('input').type('http://example.com')
+ cy.get('[data-testid="submission-form-postalCode"]').find('input').type('180-0000')
+ cy.get('[data-testid="submission-form-cityEn"]').find('input').type('Shibuya')
+ cy.get('[data-testid="submission-form-addressLine1En"]').find('input').type('some address line 1')
+ cy.get('[data-testid="submission-form-addressLine2En"]').find('input').type('some address line 2')
+ cy.get('[data-testid=submission-form-cityJa]').find('input').type('渋谷区')
+ cy.get('[data-testid="submission-form-addressLine1Ja"]').find('input').type('道の駅')
+ cy.get('[data-testid="submission-form-addressLine2Ja"]').find('input').type('道の')
+ cy.get('[data-testid="submission-form-google-maps"]')
+ .find('input')
+ .type('www.google.com/maps/place/82+Yamatech%C5%8D,+Naka+Ward,+Yokohama'
+ + ',+Kanagawa+231-0862,+Japan/@35.437123,139.651471,16z/data=!4m6!3m5!1s'
+ + '0x60185d201648e7c1:0x8f37d37bb381e29!8m2!3d35.4371228!4d139.6514712!16s%2Fg%2F11clpxxvx5?hl=en-US&entry=ttu')
+ cy.get('[data-testid="submission-form-mapLatitude"]').find('input').type('35.437123')
+ cy.get('[data-testid="submission-form-mapLongitude"]').find('input').type('139.651471')
+ })
+
+ it('should be able to select a field', () => {
+ cy.get('[data-testid="submission-form-prefectureEn"]').select('Hokkaido')
+ cy.get('[data-testid="submission-form-prefectureJa"]').select('北海道')
+ })
+
+ it('should be display error messages', () => {
+ cy.get('[data-testid="submission-form-nameEn"]').find('input').clear().type('立川中央病院').realPress('Tab')
+ cy.get('[data-testid="submission-form-nameEn"]')
+ .find('p').should('exist').contains('Invalid English Name')
+
+ cy.get('[data-testid="submission-form-nameJa"]').find('input').clear().type('Tachikawa Hospital').realPress('Tab')
+ cy.get('[data-testid="submission-form-nameJa"]')
+ .find('p').should('exist').contains('Invalid Japanese Name')
+
+ cy.get('[data-testid="submission-form-phone"]').find('input').clear().type('Hello').realPress('Tab')
+ cy.get('[data-testid="submission-form-phone"]')
+ .find('p').should('exist').contains('Invalid Phone Number')
+
+ cy.get('[data-testid="submission-form-email"]').find('input').clear().type('example').realPress('Tab')
+ cy.get('[data-testid="submission-form-email"]')
+ .find('p').should('exist').contains('Invalid Email Address')
+
+ cy.get('[data-testid="submission-form-website"]').find('input').clear().type('example').realPress('Tab')
+ cy.get('[data-testid="submission-form-website"]')
+ .find('p').should('exist').contains('Invalid Website URL')
+
+ cy.get('[data-testid="submission-form-postalCode"]').find('input').clear().type('180-0').realPress('Tab')
+ cy.get('[data-testid="submission-form-postalCode"]')
+ .find('p').should('exist').contains('Invalid Postal Code')
+
+ cy.get('[data-testid="submission-form-cityEn"]').find('input').clear().type('渋谷区').realPress('Tab')
+ cy.get('[data-testid="submission-form-cityEn"]')
+ .find('p').should('exist').contains('Invalid English City Name')
+
+ cy.get('[data-testid="submission-form-addressLine1En"]').find('input').clear().type('道の駅').realPress('Tab')
+ cy.get('[data-testid="submission-form-addressLine1En"]')
+ .find('p').should('exist').contains('Invalid English Address')
+
+ cy.get('[data-testid="submission-form-addressLine2En"]').find('input').clear().type('道の駅').realPress('Tab')
+ cy.get('[data-testid="submission-form-addressLine2En"]')
+ .find('p').should('exist').contains('Invalid English Address')
+
+ cy.get('[data-testid=submission-form-cityJa]').find('input').clear().type('Shibuya').realPress('Tab')
+ cy.get('[data-testid=submission-form-cityJa]')
+ .find('p').should('exist').contains('Invalid Japanese City Name')
+
+ cy.get('[data-testid="submission-form-addressLine1Ja"]')
+ .find('input').clear().type('Peanutbutter street').realPress('Tab')
+ cy.get('[data-testid="submission-form-addressLine1Ja"]').should('exist').contains('Invalid Japanese Address')
+
+ cy.get('[data-testid="submission-form-addressLine2Ja"]').find('input').clear().type('Jelly street').realPress('Tab')
+ cy.get('[data-testid="submission-form-addressLine2Ja"]').should('exist').contains('Invalid Japanese Address')
+
+ cy.get('[data-testid="submission-form-mapLatitude"]')
+ .find('input').clear().type('Not Number Latitude').realPress('Tab')
+ cy.get('[data-testid="submission-form-mapLatitude"]')
+ .find('p').should('exist').contains('Invalid Latitude')
+
+ cy.get('[data-testid="submission-form-mapLongitude"]')
+ .find('input').clear().type('Not Number Longitude').realPress('Tab')
+ cy.get('[data-testid="submission-form-mapLongitude"]')
+ .find('p').should('exist').contains('Invalid Longitude')
+ })
+ })
+})
diff --git a/test/cypress/e2e/moderationEditSubmissionModal.cy.ts b/test/cypress/e2e/moderationEditSubmissionModal.cy.ts
new file mode 100644
index 00000000..508232c6
--- /dev/null
+++ b/test/cypress/e2e/moderationEditSubmissionModal.cy.ts
@@ -0,0 +1,46 @@
+import fakeSubmissionResponse from '../../fake_data/moderation_dashboard/fakeSubmissionResponse.json'
+import { aliasQuery } from '../utils'
+
+before(() => {
+ cy.login()
+})
+
+describe('Moderation Edit Submission Modal', () => {
+ before(() => {
+ cy.viewport('macbook-16')
+
+ cy.intercept('POST', '**/', req => {
+ aliasQuery(req, 'query Submissions', fakeSubmissionResponse)
+ })
+
+ cy.visit('/moderation')
+ cy.wait('@query Submissions')
+ })
+
+ context('Landscape mode', () => {
+ it('should display modal if user navigates back with unsaved changes', () => {
+ cy.get('[data-testid="mod-submission-list-item-1"]').click()
+
+ // When the user clicks the back button on their browser with unsaved changes...
+ cy.get('[data-testid="submission-form-nameEn"]').find('input').type('Hospital')
+ cy.go('back')
+ // ...the modal with the confirmation button should be visible.
+ cy.get('[data-testid="submission-form-modal"]').should('be.visible')
+ // When the user clicks the confirmation button on the modal...
+ cy.get('[data-testid="submission-form-modal-confirmation-btn"]').click()
+ // ...they should be navigated back to the moderation screen.
+ cy.location('pathname').should('eq', '/moderation')
+ })
+
+ it('should not display modal if user navigates back without making changes', () => {
+ cy.get('[data-testid="mod-submission-list-item-1"]').click()
+
+ // When the user clicks the back button on their browser without making changes...
+ cy.go('back')
+ // ...the modal with the confirmation button should not exist...
+ cy.get('[data-testid="submission-form-modal"]').should('not.exist')
+ // ... and they should be navigated back to the moderation screen.
+ cy.location('pathname').should('eq', '/moderation')
+ })
+ })
+})
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
deleted file mode 100644
index 119ab03f..00000000
--- a/test/cypress/support/commands.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// ***********************************************
-// This example commands.js shows you how to
-// create various custom commands and overwrite
-// existing commands.
-//
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-//
-//
-// -- This is a parent command --
-// Cypress.Commands.add('login', (email, password) => { ... })
-//
-//
-// -- This is a child command --
-// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
-//
-//
-// -- This is a dual command --
-// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
-//
-//
-// -- This will overwrite an existing command --
-// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
diff --git a/test/cypress/support/commands.ts b/test/cypress/support/commands.ts
new file mode 100644
index 00000000..f01828dd
--- /dev/null
+++ b/test/cypress/support/commands.ts
@@ -0,0 +1,54 @@
+// ***********************************************
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
+
+// https://docs.cypress.io/app/guides/authentication-testing/auth0-authentication
+import { auth0Login } from '../utils'
+
+Cypress.Commands.add('login', () => {
+ const auth0UserName = Cypress.env('AUTH0_USERNAME')
+
+ const log = Cypress.log({
+ displayName: 'AUTH0_LOGIN',
+ message: [`🔐 Authenticating | ${auth0UserName}`],
+ autoEnd: false
+ })
+
+ log.snapshot('Connecting to auth0')
+
+ cy.session(`auth0-${auth0UserName}`, () => {
+ auth0Login()
+ }, {
+ validate: () => {
+ // https://auth0.com/docs/manage-users/cookies/authentication-api-cookies
+ // https://docs.cypress.io/api/commands/getcookie
+ cy.getCookie('auth0', { domain: 'findadoc.jp.auth0.com' }).should('exist')
+ },
+ cacheAcrossSpecs: true
+ })
+
+ log.snapshot('Successfully logged in')
+ log.end()
+})
diff --git a/test/cypress/support/e2e.js b/test/cypress/support/e2e.ts
similarity index 64%
rename from test/cypress/support/e2e.js
rename to test/cypress/support/e2e.ts
index d1dd1353..c099f1bd 100644
--- a/test/cypress/support/e2e.js
+++ b/test/cypress/support/e2e.ts
@@ -18,3 +18,15 @@ import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
+
+// https://github.com/dmtrKovalenko/cypress-real-events#readme
+import 'cypress-real-events'
+
+// https://www.npmjs.com/package/cypress-plugin-tab
+import 'cypress-plugin-tab'
+
+// https://docs.cypress.io/api/cypress-api/screenshot-api
+// ! Be careful ! Enabling --record (Test Replay) hides the runner UI !
+Cypress.Screenshot.defaults({
+ capture: 'runner'
+})
diff --git a/test/cypress/support/index.d.ts b/test/cypress/support/index.d.ts
index 9a1fd9b5..196e1116 100644
--- a/test/cypress/support/index.d.ts
+++ b/test/cypress/support/index.d.ts
@@ -1,10 +1,8 @@
-export { }
+///
-declare global {
- namespace Cypress {
- interface Chainable {
- isInViewport(args?: string): Chainable>
- isNotInViewport(args?: string): Chainable>
- }
+// https://docs.cypress.io/app/tooling/typescript-support#Types-for-Custom-Commands
+declare namespace Cypress{
+ interface Chainable {
+ login(): Chainable
}
}
diff --git a/test/cypress/tsconfig.json b/test/cypress/tsconfig.json
index 62c9e373..31f6cae9 100644
--- a/test/cypress/tsconfig.json
+++ b/test/cypress/tsconfig.json
@@ -7,7 +7,9 @@
],
"types": [
"cypress",
- "node"
+ "node",
+ "cypress-real-events",
+ "cypress-plugin-tab"
],
"sourceMap": false,
"resolveJsonModule": true,
diff --git a/test/cypress/utils.ts b/test/cypress/utils.ts
new file mode 100644
index 00000000..be392ee9
--- /dev/null
+++ b/test/cypress/utils.ts
@@ -0,0 +1,69 @@
+import type { CyHttpMessages } from 'cypress/types/net-stubbing'
+
+export type IncomingHttpRequest = CyHttpMessages.IncomingHttpRequest
+
+// https://docs.cypress.io/app/guides/authentication-testing/auth0-authentication
+export const auth0Login = () => {
+ cy.visit('/login')
+ cy.origin(Cypress.env('AUTH0_DOMAIN'), () => {
+ const auth0UserName = Cypress.env('AUTH0_USERNAME')
+ const auth0Password = Cypress.env('AUTH0_PASSWORD')
+
+ cy.get('input#username').type(auth0UserName)
+ cy.get('[data-action-button-primary]').click()
+ cy.get('input#password').type(auth0Password)
+ cy.get('[data-action-button-primary]').click()
+ })
+
+ const baseUrl = `${Cypress.config().baseUrl}/`
+
+ cy.url().should('equal', baseUrl)
+}
+
+/**
+ * https://docs.cypress.io/app/guides/network-requests#Working-with-GraphQL
+ *
+ * Set the alias for a request based on the operation name. After setting it we can use cy.wait(@{alias}).
+ *
+ * e.g. operation: query Submissions / cy.wait('@query Submissions')
+ **/
+export const aliasQuery = (req: IncomingHttpRequest, operation: string, responseBody: unknown) => {
+ /**
+ * Check if the GraphQL operation is included in the request body
+ **/
+ const hasOperation = (req: IncomingHttpRequest, operation: string): boolean => {
+ const { query } = req.body
+ return query && query.includes(operation)
+ }
+
+ /**
+ * https://docs.cypress.io/api/commands/intercept#Interception-lifecycle
+ *
+ * https://docs.cypress.io/api/commands/intercept#cyintercept-and-request-caching
+ *
+ * Sometimes Cypress.intercept() cannot intercept a request due to the request being cached and not hitting the
+ * network layer (where Cypress.intercept() works).
+ *
+ * To prevent this, we set 'cache-control' to 'no-store', this prevents all the requests to be cached.
+ **/
+ const preventRequestCache = (req: IncomingHttpRequest) => {
+ req.on('before:response', res => {
+ // force all API responses to not be cached
+ res.headers['cache-control'] = 'no-store'
+ })
+ }
+
+ preventRequestCache(req)
+
+ if (!hasOperation(req, operation)) {
+ req.continue()
+ return
+ }
+
+ req.alias = operation
+
+ req.reply({
+ statusCode: 200,
+ body: responseBody
+ })
+}
diff --git a/test/fake_data/moderation_dashboard/fakeModHealthcareprofessionalData.json b/test/fake_data/moderation_dashboard/fakeModHealthcareProfessionalData.json
similarity index 95%
rename from test/fake_data/moderation_dashboard/fakeModHealthcareprofessionalData.json
rename to test/fake_data/moderation_dashboard/fakeModHealthcareProfessionalData.json
index 572630d2..4c832f05 100644
--- a/test/fake_data/moderation_dashboard/fakeModHealthcareprofessionalData.json
+++ b/test/fake_data/moderation_dashboard/fakeModHealthcareProfessionalData.json
@@ -1,6 +1,6 @@
{
"data": {
- "healthcareprofessionals": [
+ "healthcareProfessionals": [
{
"acceptedInsurance": [
"UNINSURED"
diff --git a/yarn.lock b/yarn.lock
index 246260ee..2b3a1a44 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7243,6 +7243,17 @@ __metadata:
languageName: node
linkType: hard
+"cross-spawn@npm:^7.0.6":
+ version: 7.0.6
+ resolution: "cross-spawn@npm:7.0.6"
+ dependencies:
+ path-key: "npm:^3.1.0"
+ shebang-command: "npm:^2.0.0"
+ which: "npm:^2.0.1"
+ checksum: 10/0d52657d7ae36eb130999dffff1168ec348687b48dd38e2ff59992ed916c88d328cf1d07ff4a4a10bc78de5e1c23f04b306d569e42f7a2293915c081e4dfee86
+ languageName: node
+ linkType: hard
+
"crossws@npm:^0.2.0, crossws@npm:^0.2.4":
version: 0.2.4
resolution: "crossws@npm:0.2.4"
@@ -7895,6 +7906,27 @@ __metadata:
languageName: node
linkType: hard
+"dotenv-cli@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "dotenv-cli@npm:8.0.0"
+ dependencies:
+ cross-spawn: "npm:^7.0.6"
+ dotenv: "npm:^16.3.0"
+ dotenv-expand: "npm:^10.0.0"
+ minimist: "npm:^1.2.6"
+ bin:
+ dotenv: cli.js
+ checksum: 10/3acbc2712f97de5a7b916e2e611682377b5f62efb7ebe63ede314800bedd9c63e9ae1e8b1f819efe0e87f9d813842695cfed991a276290a79cac63d48c60df05
+ languageName: node
+ linkType: hard
+
+"dotenv-expand@npm:^10.0.0":
+ version: 10.0.0
+ resolution: "dotenv-expand@npm:10.0.0"
+ checksum: 10/b41eb278bc96b92cbf3037ca5f3d21e8845bf165dc06b6f9a0a03d278c2bd5a01c0cfbb3528ae3a60301ba1a8a9cace30e748c54b460753bc00d4c014b675597
+ languageName: node
+ linkType: hard
+
"dotenv@npm:^16.0.0, dotenv@npm:^16.4.5":
version: 16.4.5
resolution: "dotenv@npm:16.4.5"
@@ -7902,6 +7934,13 @@ __metadata:
languageName: node
linkType: hard
+"dotenv@npm:^16.3.0":
+ version: 16.4.7
+ resolution: "dotenv@npm:16.4.7"
+ checksum: 10/f13bfe97db88f0df4ec505eeffb8925ec51f2d56a3d0b6d916964d8b4af494e6fb1633ba5d09089b552e77ab2a25de58d70259b2c5ed45ec148221835fc99a0c
+ languageName: node
+ linkType: hard
+
"dset@npm:^3.1.2":
version: 3.1.3
resolution: "dset@npm:3.1.3"
@@ -9266,6 +9305,7 @@ __metadata:
cypress: "npm:^13.13.2"
cypress-plugin-tab: "npm:^1.0.5"
cypress-real-events: "npm:^1.13.0"
+ dotenv-cli: "npm:^8.0.0"
eslint: "npm:^9.8.0"
eslint-plugin-cypress: "npm:^3.4.0"
eslint-plugin-json: "npm:^4.0.1"
@@ -11966,7 +12006,7 @@ __metadata:
languageName: node
linkType: hard
-"minimist@npm:^1.2.8":
+"minimist@npm:^1.2.6, minimist@npm:^1.2.8":
version: 1.2.8
resolution: "minimist@npm:1.2.8"
checksum: 10/908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f