Skip to content

Commit

Permalink
Implement backend into client e2e tests (#123)
Browse files Browse the repository at this point in the history
* Add testing env to server, Add clear-db endpoint for testing env
* Add testing env to client
* Integrate backend into client e2e tests
* Add cy commands, update tests
* Update ci to incorporate the changes made to client e2e testing
* Add signup/login e2e tests
* Add auth based routing e2e tests
  • Loading branch information
floydnant authored Nov 20, 2022
1 parent 0b842d5 commit 752813e
Show file tree
Hide file tree
Showing 31 changed files with 692 additions and 64 deletions.
45 changes: 39 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ jobs:
- run: npm run comp:ci
working-directory: ./client-v2

- run: npm run e2e:ci
working-directory: ./client-v2

# - name: Upload coverage artifacts
# uses: actions/upload-artifact@v3
# with:
Expand Down Expand Up @@ -73,9 +70,6 @@ jobs:
- run: npm run lint
working-directory: ./server

- run: npm run unit:ci
working-directory: ./server

- name: Setup Postgres
uses: Daniel-Marynicz/postgresql-action@master
with:
Expand All @@ -84,6 +78,9 @@ jobs:
app_user_password: ${{ env.DB_PWD }}
app_db: ${{ env.DB_NAME }}

- run: npm run unit:ci
working-directory: ./server

- run: npm run e2e:ci
working-directory: ./server

Expand All @@ -94,3 +91,39 @@ jobs:
# path: server/coverage
# retention-days: 7

run-full-e2e-tests:
runs-on: ubuntu-latest
env:
DB_USER: app
DB_PWD: develop
DB_NAME: todo-app-testing
TESTING_DATABASE_URL: postgresql://app:develop@localhost:5432/todo-app-testing?schema=public
JWT_SECRET: this is the secret that nobody should know

steps:
- uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 16.x
cache: 'npm'
cache-dependency-path: client-v2/package-lock.json

- name: Setup Postgres
uses: Daniel-Marynicz/postgresql-action@master
with:
postgres_image_tag: 12-alpine
app_user: ${{ env.DB_USER }}
app_user_password: ${{ env.DB_PWD }}
app_db: ${{ env.DB_NAME }}

- name: Run npm ci in server
run: npm ci
working-directory: ./server

- name: Run npm ci in client
run: npm ci
working-directory: ./client-v2

- run: npm run e2e:ci
working-directory: ./client-v2
2 changes: 1 addition & 1 deletion client-v2/.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ NG_APP_PACKAGE_VERSION=$npm_package_version

# prod
NG_APP_REVIEW_ID=$REVIEW_ID
NG_APP_CONTEXT=$CONTEXT
NG_APP_NETLIFY_CONTEXT=$CONTEXT
51 changes: 51 additions & 0 deletions client-v2/cypress/e2e/auth.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { credentials } from 'cypress/fixtures/user-credentials'
import { login, signup } from 'cypress/support/auth-helpers'
import { testName } from 'cypress/support/helpers'

beforeEach(() => {
cy.clearDb()
})

describe('Authentication', () => {
describe('Signup', () => {
it('can sign up', () => {
signup()
cy.get(testName('user-menu-toggle')).invoke('attr', 'data-logged-in').should('eq', 'true')
})
it('cannot signup up with the same email twice', () => {
signup()
cy.visit('about:blank')

signup()
cy.get(testName('signup-page'))
cy.get(testName('workspace-page')).should('not.exist')
cy.get(testName('user-menu-toggle')).should('not.exist')
})
})

describe('Login', () => {
it('can login', () => {
signup()
cy.visit('about:blank')

login()
cy.get(testName('user-menu-toggle')).invoke('attr', 'data-logged-in').should('eq', 'true')
})
it('cannot login with the wrong email', () => {
signup()
cy.visit('about:blank')

login({ ...credentials['jonathan'], email: 'some.other@email.com' })
cy.get(testName('workspace-page')).should('not.exist')
cy.get(testName('user-menu-toggle')).should('not.exist')
})
it('cannot login with the wrong password', () => {
signup()
cy.visit('about:blank')

login({ ...credentials['jonathan'], password: 'someOtherPwd-123' })
cy.get(testName('workspace-page')).should('not.exist')
cy.get(testName('user-menu-toggle')).should('not.exist')
})
})
})
94 changes: 75 additions & 19 deletions client-v2/cypress/e2e/routing.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { authSuccessResponse } from 'cypress/fixtures/auth-responses'
import { credentials } from 'cypress/fixtures/user-credentials'
import {
signup,
login,
typeLoginCredentialsAndSubmit,
typeSignupCredentialsAndSubmit,
} from 'cypress/support/auth-helpers'
import { testName } from 'cypress/support/helpers'

beforeEach(() => {
cy.clearDb()
})

const testName = (testName: string) => `[data-test-name="${testName}"]`
describe('Routing', () => {
it('can visit the app', () => {
cy.visit('/')
Expand Down Expand Up @@ -31,13 +39,16 @@ describe('Routing', () => {
cy.url().should('contain', '/signup')
})

it('signing up redirects to the workspace', () => {
signup()

cy.get(testName('workspace-page')).should('exist')
})
it('logging in redirects to the workspace', () => {
cy.visit('/auth/login')
signup()
cy.visit('about:blank')

cy.intercept('http://localhost:3000/auth/login', authSuccessResponse)
cy.get(testName('input-email')).type(credentials.jonathan.email)
cy.get(testName('input-password')).type(credentials.jonathan.password)
cy.get(testName('submit-button')).click()
login()

cy.get(testName('workspace-page')).should('exist')
})
Expand All @@ -50,20 +61,34 @@ describe('Routing', () => {
cy.url().should('contain', '/login')
})

it.skip('successful login after redirect, redirects back to /home', () => {
// @TODO:
})
it('successful login after redirect, redirects back to /home', () => {
signup()
cy.clearLocalStorage()

it.skip('show login loading screen when visting with stored token', () => {
cy.setLocalStorage('todo-authToken', credentials.jonathan.token)
cy.visit('/home')
cy.get(testName('workspace-page')).should('not.exist')
cy.get(testName('login-page')).should('exist')

// cy.intercept({ method: 'GET', path: '/auth/me', hostname: 'localhost', port: 3000 }, authSuccessResponse)
// cy.intercept('http://localhost:3000/auth/me', authSuccessResponse)
cy.wait(0)
typeLoginCredentialsAndSubmit()

cy.get(testName('login-loading-page')).should('exist')
cy.get(testName('workspace-page')).should('exist')
cy.url().should('contain', '/home')
})

it('can visit with stored token', () => {
signup()
cy.get(testName('workspace-page'))
cy.window().then(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const token = window.localStorage.getItem('todo-authToken')!

cy.clearLocalStorage()

cy.setLocalStorage('todo-authToken', token)
cy.visit('/home')

cy.get(testName('workspace-page')).should('exist')
})
})
})

Expand All @@ -73,9 +98,40 @@ describe('Routing', () => {
cy.get(testName('settings-page')).should('not.exist')
cy.url().should('contain', '/login')
})
it('does not redirect when visiting /settings with valid login', () => {
signup()
cy.get(testName('settings-link')).click()

cy.url().should('contain', '/settings')
cy.get(testName('settings-page')).should('exist')
})

it('successful signup after redirect, redirects back to /settings', () => {
cy.visit('/settings')

cy.get(testName('settings-page')).should('not.exist')
cy.get(testName('login-page')).should('exist')
cy.get(testName('signup-link')).click()

cy.get(testName('signup-page')).should('exist')
typeSignupCredentialsAndSubmit()

cy.get(testName('settings-page')).should('exist')
cy.url().should('contain', '/settings')
})

it('successful login after redirect, redirects back to /settings', () => {
signup()
cy.clearLocalStorage()

cy.visit('/settings')
cy.get(testName('settings-page')).should('not.exist')
cy.get(testName('login-page')).should('exist')

typeLoginCredentialsAndSubmit()

it.skip('successful login after redirect, redirects back to /settings', () => {
// @TODO:
cy.get(testName('settings-page')).should('exist')
cy.url().should('contain', '/settings')
})
})

Expand Down
9 changes: 8 additions & 1 deletion client-v2/cypress/fixtures/user-credentials.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
export const credentials = {
export interface Credentials {
email: string
username: string
password: string
token: string
}

export const credentials: Record<string, Credentials> = {
jonathan: {
email: 'jonathan.butler@cy.com',
username: 'Jonathan Butler',
Expand Down
26 changes: 26 additions & 0 deletions client-v2/cypress/support/auth-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { credentials, Credentials } from 'cypress/fixtures/user-credentials'
import { testName } from './helpers'

export const typeSignupCredentialsAndSubmit = (creds: Credentials = credentials['jonathan']) => {
cy.get(testName('input-username')).type(creds.username)
cy.get(testName('input-email')).type(creds.email)
cy.get(testName('input-password')).type(creds.password)
cy.get(testName('input-confirmPassword')).type(creds.password)
cy.get(testName('submit-button')).click()
}
export const signup = (creds: Credentials = credentials['jonathan']) => {
cy.visit('/auth/signup')
cy.get(testName('signup-page'))
typeSignupCredentialsAndSubmit(creds)
}

export const typeLoginCredentialsAndSubmit = (creds: Credentials = credentials['jonathan']) => {
cy.get(testName('input-email')).type(creds.email)
cy.get(testName('input-password')).type(creds.password)
cy.get(testName('submit-button')).click()
}
export const login = (creds: Credentials = credentials['jonathan']) => {
cy.visit('/auth/login')
cy.get(testName('login-page'))
typeLoginCredentialsAndSubmit(creds)
}
6 changes: 6 additions & 0 deletions client-v2/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ declare namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
interface Chainable<Subject = any> {
setLocalStorage: typeof setLocalStorage
clearDb: typeof clearDb
}
}

Expand All @@ -20,6 +21,11 @@ function setLocalStorage(itemName: string, itemValue: string) {
}
Cypress.Commands.add('setLocalStorage', setLocalStorage)

function clearDb() {
cy.request('http://localhost:3001/clear-db')
}
Cypress.Commands.add('clearDb', clearDb)

//
// ***********************************************
// This example commands.js shows you how to
Expand Down
1 change: 1 addition & 0 deletions client-v2/cypress/support/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const testName = (testName: string) => `[data-test-name="${testName}"]`
Loading

0 comments on commit 752813e

Please sign in to comment.