Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EQS] EngageSphere Automated Tests #9

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: CI

on:
pull_request:
push:
branches:
- main

jobs:
eslint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install modules
run: npm install
- name: Run ESLint
run: npm run lint

api-tests:
needs: eslint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install backend modules
uses: cypress-io/github-action@v6
with:
install-command: npm run install:backend
runTests: false
- name: Run API tests
uses: cypress-io/github-action@v6
with:
start: npm run start:server & wait-on http://localhost:3001
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
command: npm run test:api

gui-tests:
needs: eslint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install frontend modules
uses: cypress-io/github-action@v6
with:
install-command: npm run install:frontend
runTests: false
- name: Run GUI tests
uses: cypress-io/github-action@v6
with:
start: npm run start:frontend & wait-on http://localhost:3000
command: npm run test:gui
10 changes: 10 additions & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { defineConfig } = require('cypress')

module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
env: {
apiUrl: 'http://localhost:3001'
}
}
})
162 changes: 162 additions & 0 deletions cypress/e2e/api.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
describe('EngageSphere', () => {
it('returns the correct status and body structure', () => {
cy.api({
method: 'GET',
url: `${Cypress.env('apiUrl')}/customers`
}).then(({ status, body }) => {
expect(status).to.eq(200)
expect(body).to.have.property('customers')
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved

expect(body.customers[0]).to.have.property('id')
expect(body.customers[0]).to.have.property('name')
expect(body.customers[0]).to.have.property('employees')
expect(body.customers[0]).to.have.property('industry')
expect(body.customers[0]).to.have.property('contactInfo')
expect(body.customers[0]).to.have.property('address')
expect(body.customers[0]).to.have.property('size')

if (body.customers[0].contactInfo) {
expect(body.customers[0].contactInfo).to.have.property('name')
expect(body.customers[0].contactInfo).to.have.property('email')
}

if (body.customers[0].address) {
expect(body.customers[0].address).to.have.property('street')
expect(body.customers[0].address).to.have.property('city')
expect(body.customers[0].address).to.have.property('state')
expect(body.customers[0].address).to.have.property('zipCode')
expect(body.customers[0].address).to.have.property('country')
}

expect(body).to.have.property('pageInfo')
expect(body.pageInfo).to.have.property('currentPage')
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
expect(body.pageInfo).to.have.property('totalPages')
expect(body.pageInfo).to.have.property('totalCustomers')
})
})

it('paginates the customer list correctly', () => {
cy.api({
method: 'GET',
url: `${Cypress.env('apiUrl')}/customers`,
qs: {
'page': 6
}
}).then(({ status, body }) => {
expect(status).to.eq(200)
expect(body.pageInfo).to.have.property('currentPage', 6)
})
})

it('filters the limit of customers correctly', () => {
cy.api({
method: 'GET',
url: `${Cypress.env('apiUrl')}/customers`,
qs: {
'limit': 10
}
}).then(({ status, body }) => {
expect(status).to.eq(200)
expect(body.customers).to.have.length(10)
})
})

it('filters customers by size correctly', () => {
cy.api({
method: 'GET',
url: `${Cypress.env('apiUrl')}/customers`,
qs: {
'size': 'Small'
}
}).then(({ status, body }) => {
expect(status).to.eq(200)
expect(body.customers[0]).to.have.property('size', 'Small')
})
})

it('filters customers by industry correctly', () => {
cy.api({
method: 'GET',
url: `${Cypress.env('apiUrl')}/customers`,
qs: {
'industry': 'Logistics'
}
}).then(({ status, body }) => {
expect(status).to.eq(200)
expect(body.customers[0]).to.have.property('industry', 'Logistics')
})
})

context('Invalid Requests', () => {

const invalidData = [
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
{
scenario: 'negative page',
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
page: -1,
limit: 5,
size: 'All',
industry: 'All',
errorMessage: 'Invalid page or limit. Both must be positive numbers.'
},
{
scenario: 'negative limit',
page: 1,
limit: -5,
size: 'All',
industry: 'All',
errorMessage: 'Invalid page or limit. Both must be positive numbers.'
},
{
scenario: 'page as a string',
page: 'one',
limit: 5,
size: 'All',
industry: 'All',
errorMessage: 'Invalid page or limit. Both must be positive numbers.'
},
{
scenario: 'limit as a boolean',
page: 1,
limit: true,
size: 'All',
industry: 'All',
errorMessage: 'Invalid page or limit. Both must be positive numbers.'
},
{
scenario: 'unsupported size',
page: 1,
limit: 5,
size: 'Big',
industry: 'All',
errorMessage: 'Unsupported size value. Supported values are All, Small, Medium, Enterprise, Large Enterprise, and Very Large Enterprise.'
},
{
scenario: 'unsupported industry',
page: 1,
limit: 5,
size: 'All',
industry: 'Food',
errorMessage: 'Unsupported industry value. Supported values are All, Logistics, Retail, Technology, HR, and Finance.'
}
]

invalidData.forEach(data => {
it(`handles invalid requests gracefully (e.g., ${data.scenario})`, () => {
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
cy.api({
method: 'GET',
url: `${Cypress.env('apiUrl')}/customers`,
qs: {
'page': data.page,
'limit': data.limit,
'size': data.size,
'industry': data.industry
},
failOnStatusCode: false
}).then(({ status, body }) => {
expect(status).to.eq(400)
expect(body).to.have.property('error', data.errorMessage)
})
})
})
})
})
43 changes: 43 additions & 0 deletions cypress/e2e/gui/a11y.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
describe('EngageSphere', () => {
beforeEach(() => {
cy.mockCustomers().as('getCustomer')

cy.visit('/')
cy.injectAxe()
})

it('It finds no a11y issues in light mode in the customer table', () => {
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
cy.checkA11y()
})

it('It finds no a11y issues in dark mode in the customer table', () => {
cy.get('[aria-label*="theme"]').click()

cy.checkA11y()
})

it('It finds on a11y issues with the messenger\'s bubble button in dark mode', () => {
cy.get('[aria-label*="theme"]').click()

cy.checkA11y('[aria-label*="messenger"]')
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved
})

context('Customer View page', () => {
beforeEach(() => {
cy.wait('@getCustomer')
EduQuaresimin marked this conversation as resolved.
Show resolved Hide resolved

cy.contains('button', 'View').click()
cy.contains('button', 'Show address').click()
})

it('It finds no a11y issues in light mode in the customer details and address view', () => {
cy.checkA11y()
})

it('It finds no a11y issues in dark mode in the customer details and address view', () => {
cy.get('[aria-label*="theme"]').click()

cy.checkA11y()
})
})
})
44 changes: 44 additions & 0 deletions cypress/e2e/gui/customerView.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
describe('EngageSphere', () => {
beforeEach(() => {
cy.mockCustomers().as('getCustomer')

cy.visit('/')

cy.wait('@getCustomer')
})

it('keeps the filters when coming back from the customer details view', () => {
cy.get('[data-testid="size-filter"]').select('Small')
cy.get('[data-testid="industry-filter"]').select('Technology')
cy.contains('button', 'View').click()
cy.contains('h2', 'Customer Details').should('be.visible')

cy.contains('button', 'Back').click()

cy.contains('h1', 'EngageSphere').should('be.visible')
cy.get('[data-testid="size-filter"]').should('have.value', 'Small')
cy.get('[data-testid="industry-filter"]').should('have.value', 'Technology')
})

it('goes back to the customers list when clicking the "Back" button', () => {
cy.contains('button', 'View').click()
cy.contains('h2', 'Customer Details').should('be.visible')

cy.contains('button', 'Back').click()

cy.get('[data-testid="table"]').should('be.visible')
})

context('Mobile Viewport', { viewportWidth: 468 }, () => {
it(
'shows the Company name and Action columns and hides the ID, Industry, Number of Employees, and Size columns',
() => {
cy.contains('th', 'ID').should('not.be.visible')
cy.contains('th', 'Company name').should('be.visible')
cy.contains('th', 'Industry').should('not.be.visible')
cy.contains('th', 'Number of employees ').should('not.be.visible')
cy.contains('th', 'Size').should('not.be.visible')
cy.contains('th', 'Action').should('be.visible')
})
})
})
17 changes: 17 additions & 0 deletions cypress/e2e/gui/greetings.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe('EngageSphere', () => {
beforeEach(() => {
cy.mockCustomers().as('getCustomer')

cy.visit('/')
cy.wait('@getCustomer')
})

it('renders the "Hi there" greeting when no name is provided', () => {
cy.contains('h2', 'Hi there!').should('be.visible')
})

it('renders the "Hi Joe" greeting when name is provided', () => {
cy.get('[data-testid="name"]').type('Joe')
cy.contains('h2', 'Hi Joe!').should('be.visible')
})
})
28 changes: 28 additions & 0 deletions cypress/e2e/gui/headerAndFooter.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
describe('EngageSphere', () => {
beforeEach(() => {
cy.visit('/')
})

it('renders the footer with the right text and links', () => {
cy.contains('a', 'Hotmart')
.should('be.visible')
.and('have.attr', 'href', 'https://hotmart.com/pt-br/club/cypress-playground-ate-a-nuvem')
cy.contains('a', 'Udemy')
.should('be.visible')
.and('have.attr', 'href', 'https://udemy.com/user/walmyr')
cy.contains('a', 'Blog')
.should('be.visible')
.and('have.attr', 'href', 'https://talkingabouttesting.com')
cy.contains('a', 'YouTube')
.should('be.visible')
.and('have.attr', 'href', 'https://youtube.com/@talkingabouttesting')
cy.contains('p', 'Copyright 2024 - Talking About Testing')
.should('be.visible')
})

it('renders the header with a heading, theme\'s toggle, and a text input field', () => {
cy.contains('h1', 'EngageSphere').should('be.visible')
cy.get('[aria-label*="theme"]').should('be.visible')
cy.get('[data-testid="name"]').should('be.visible')
})
})
Loading