-
Notifications
You must be signed in to change notification settings - Fork 3
Add Cypress tests for UI interactions and form validations #2
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
base: main
Are you sure you want to change the base?
Changes from all commits
540342c
56248f1
6c81181
4ed90d7
cb66467
049d0c6
aab44f6
571c6e6
abb5339
2e7f039
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -11,7 +11,7 @@ Read the following [doc](./docs/Requirements.md) to understand all the EngageSph | |||
| To run this project, you will need: | ||||
|
|
||||
| - [git](https://git-scm.com/downloads) (I've used version `2.42.1` while writing this doc) | ||||
| - [Node.js](https://nodejs.org/en/) (I've used version `v2#.13.1` while writing this doc) | ||||
| - [Node.js](https://nodejs.org/en/) (I've used version `v22.13.1` while writing this doc) | ||||
| - npm (I've used version `10.9.2` while writing this doc) | ||||
|
|
||||
| **Note:** When installing Node.js, npm is automatically installed too. | ||||
|
|
@@ -24,6 +24,104 @@ Read the following [doc](./docs/TestEnvironment.md) to install and start the bac | |||
|
|
||||
| Read the following [doc](./docs/TestCases.md) to get a list of test cases. | ||||
|
|
||||
| ___ | ||||
| ## Running Cypress Tests | ||||
|
|
||||
| Made with ❤️ by [Walmyr](https://walmyr.dev). | ||||
| This project includes end-to-end tests using Cypress, separated into API and GUI test categories. Follow the instructions below to install and run these tests: | ||||
|
|
||||
| ### Installing Cypress | ||||
|
|
||||
| 1. Install Cypress as a development dependency by running: | ||||
| ```bash | ||||
| npm install | ||||
| ``` | ||||
|
|
||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uma linha em branco já é o suficiente.
Suggested change
|
||||
|
|
||||
| ### Folder Structure for Tests | ||||
|
|
||||
| The test files are organized as follows: | ||||
|
|
||||
| - **API Tests**: Located in `cypress/e2e/api/engageSphere.cy.js`. | ||||
| - **GUI Tests**: Located in `cypress/e2e/gui/engageSphere.cy.js`. | ||||
|
|
||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. O mesmo aqui.
Suggested change
|
||||
|
|
||||
brunonf15 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
| ### Running Tests | ||||
|
|
||||
| You can run API and GUI tests separately or together using Cypress commands: | ||||
|
|
||||
| #### Running All Tests | ||||
|
|
||||
| To run all tests (both API and GUI): | ||||
|
|
||||
| - **Interactive Mode**: Launch Cypress Test Runner with: | ||||
|
|
||||
| ```bash | ||||
| npm run cy:open | ||||
| ``` | ||||
|
|
||||
| Select either individual test files or all available tests from the runner interface. | ||||
|
|
||||
| - **Headless Mode**: Run all tests without opening the graphical interface using: | ||||
|
|
||||
| ```bash | ||||
| npm test | ||||
| ``` | ||||
|
|
||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
|
|
||||
| #### Running API Tests Only | ||||
|
|
||||
| To run only the API tests: | ||||
|
|
||||
| - **Interactive Mode**: Open Cypress Test Runner: | ||||
|
|
||||
| ```bash | ||||
| npm run cy:open | ||||
| ``` | ||||
|
|
||||
| Then select `cypress/e2e/api/engageAPI.cy.js`. | ||||
|
|
||||
| - **Headless Mode**: Run only this specific test file: | ||||
|
|
||||
| ```bash | ||||
| npm run test:api | ||||
| ``` | ||||
|
|
||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
|
|
||||
| #### Running GUI Tests Only | ||||
|
|
||||
| To run only the GUI tests: | ||||
|
|
||||
| - **Interactive Mode**: Open Cypress Test Runner: | ||||
|
|
||||
| ```bash | ||||
| npm run cy:open | ||||
| ``` | ||||
|
|
||||
| Then select `cypress/e2e/e2e/engageGUI.cy.js`. | ||||
|
|
||||
| - **Headless Mode**: Run only this specific test file: | ||||
|
|
||||
| ```bash | ||||
| npm run test:gui | ||||
| ``` | ||||
|
|
||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
|
|
||||
| ### Additional Commands | ||||
|
|
||||
| - Run tests in a specific browser (e.g., Chrome): | ||||
|
|
||||
| ```bash | ||||
| npm test --browser chrome | ||||
| ``` | ||||
|
|
||||
| - Run tests in headed mode (with browser UI visible): | ||||
|
|
||||
| ```bash | ||||
| npm test --headed | ||||
| ``` | ||||
|
|
||||
| For more details on writing and running Cypress tests, refer to the official [Cypress documentation](https://docs.cypress.io). | ||||
|
|
||||
| --- | ||||
|
|
||||
| Made with ❤️ by [Walmyr](https://walmyr.dev). \ | ||||
| Tests by Bruno Figueiredo | ||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| const { defineConfig } = require("cypress"); | ||
|
|
||
| module.exports = defineConfig({ | ||
| e2e: { | ||
| baseUrl: "http://localhost:3000", | ||
| supportFile: false, | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Visto que você criou o comando customizado, remova esta configuração, crie o arquivo |
||
| fixturesFolder: false, | ||
| env: { | ||
| apiUrl: "http://localhost:3001" | ||
| }, | ||
| }, | ||
| }) | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,135 @@ | ||||||
| describe('EngageSphere API - Customers', () => { | ||||||
| it('Recupera clientes com sucesso (por exemplo, verifica o código de status 200)', () => { | ||||||
| cy.request(`${Cypress.env("apiUrl")}/customers`).as('getCustomers'); | ||||||
|
|
||||||
| cy.get('@getCustomers').should((response) => { | ||||||
| expect(response).to.have.property('status', 200); | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Outra alternativa (usando desestruturação de objetos) seria: cy.get('@getCustomers').should(({ status }) => {
expect(status).to.eq(200);
}); |
||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Realiza a paginação de clientes corretamente', () => { | ||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { | ||||||
| page: 2, | ||||||
| limit: 1, | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Se o teste é para a query string |
||||||
| size: 'All', | ||||||
| industry: 'All' | ||||||
| } | ||||||
| }).then((response) => { | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Usando desestruturação de objetos, ficaria assim: }).then(({ body, status }) => {
expect(status).to.eq(200);
expect(body).to.have.property('pageInfo');
expect(body.pageInfo).to.deep.include({
currentPage: 2,
});Perceba que dessa forma, não se repete |
||||||
| expect(response.status).to.eq(200); | ||||||
| expect(response.body).to.have.property('pageInfo'); | ||||||
| expect(response.body.pageInfo).to.deep.include({ | ||||||
| currentPage: 2, | ||||||
| }); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Filtra corretamente o limite de clientes', () => { | ||||||
| const limit = 2; | ||||||
|
|
||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { | ||||||
| page: 2, | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Se o teste é para a query string Foque no que está sendo testado e deixe a API usar seus padrões para o resto. |
||||||
| limit: limit, | ||||||
| size: 'All', | ||||||
| industry: 'All' | ||||||
| } | ||||||
| }).then((response) => { | ||||||
| const totalCustomers = response.body.pageInfo.totalCustomers; | ||||||
| const expectedTotalPages = Math.ceil(totalCustomers / limit); | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Não acho uma boa haver cálculos no meio de um teste. Veja minha implementação abaixo: it('filters by limit of customers', () => {
const resultsPerPageLimit = [5, 10, 20, 50]
const totalPagesPerLimit = [10, 5, 3, 1] // Supposing there are 50 clients in the database.
resultsPerPageLimit.forEach((limit, index) => {
cy.request('GET', `${CUSTOMERS_API_URL}?limit=${limit}`).as('getLimittedCustomers')
cy.get('@getLimittedCustomers')
.its('body.customers')
.should('have.length', limit)
cy.get('@getLimittedCustomers')
.its('body.pageInfo.totalPages')
.should('be.eq', totalPagesPerLimit[index])
})
})
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Explicarei com detalhes esse teste no encontro de amanhã. |
||||||
|
|
||||||
| expect(response.body.pageInfo).to.deep.include({ | ||||||
| totalPages: expectedTotalPages, | ||||||
| totalCustomers: totalCustomers | ||||||
| }); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Trata requisições inválidas (por exemplo, página negativa)', () => { | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Que tal criar também casos de testes para os cenários onde |
||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Visto que esta URL se repete em vários testes, que tal criar uma variável chamada |
||||||
| qs: { page: -1, limit: 5, size: 'All', industry: 'All' }, | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basta passar |
||||||
| failOnStatusCode: false | ||||||
| }).then((response) => { | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use desestruturação de objetos, conforme exemplificado anteriormente, dessa forma, evita-se repetir |
||||||
| expect(response.status).to.eq(400); | ||||||
| expect(response.body).to.have.property('error', 'Invalid page or limit. Both must be positive numbers.'); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Trata requisições inválidas (por exemplo, limite negativo)', () => { | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basta passar |
||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { page: 1, limit: -5, size: 'All', industry: 'All' }, | ||||||
| failOnStatusCode: false | ||||||
| }).then((response) => { | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Desestruturação de objetos. |
||||||
| expect(response.status).to.eq(400); | ||||||
| expect(response.body).to.have.property('error', 'Invalid page or limit. Both must be positive numbers.'); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Trata requisições inválidas (por exemplo, página como string)', () => { | ||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { page: 'abc', limit: 5, size: 'All', industry: 'All' }, | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. O mesmo aqui. Passe só a query string alvo do teste. |
||||||
| failOnStatusCode: false | ||||||
| }).then((response) => { | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use desestruturação de objetos. |
||||||
| expect(response.status).to.eq(400); | ||||||
| expect(response.body).to.have.property('error', 'Invalid page or limit. Both must be positive numbers.'); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Trata requisições inválidas (por exemplo, limite como booleano)', () => { | ||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { page: 1, limit: false, size: 'All', industry: 'All' }, | ||||||
| failOnStatusCode: false | ||||||
| }).then((response) => { | ||||||
| expect(response.status).to.eq(400); | ||||||
| expect(response.body).to.have.property('error', 'Invalid page or limit. Both must be positive numbers.'); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Trata requisições inválidas (por exemplo, tamanho não suportado)', () => { | ||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { | ||||||
| page: 1, | ||||||
| limit: 5, | ||||||
| size: 'InvalidSize', // Valor não suportado | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Precisa mesmo desse comentário? Seu valor já deixa isso claro, não?
Suggested change
|
||||||
| industry: 'All' | ||||||
| }, | ||||||
| failOnStatusCode: false | ||||||
| }).then((response) => { | ||||||
| expect(response.status).to.eq(400); | ||||||
| expect(response.body).to.have.property('error', 'Unsupported size value. Supported values are All, Small, Medium, Enterprise, Large Enterprise, and Very Large Enterprise.'); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| it('Trata requisições inválidas (por exemplo, indústria não suportada)', () => { | ||||||
| cy.request({ | ||||||
| method: 'GET', | ||||||
| url: `${Cypress.env("apiUrl")}/customers`, | ||||||
| qs: { | ||||||
| page: 1, | ||||||
| limit: 5, | ||||||
| size: 'All', | ||||||
| industry: 'InvalidIndustry' // Valor não suportado | ||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| }, | ||||||
| failOnStatusCode: false | ||||||
| }).then((response) => { | ||||||
| expect(response.status).to.eq(400); | ||||||
| expect(response.body).to.have.property('error', 'Unsupported industry value. Supported values are All, Logistics, Retail, Technology, HR, and Finance.'); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| }); | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.