Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 101 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```bash
```bash

npm install
```

Copy link
Owner

Choose a reason for hiding this comment

The 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`.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O mesmo aqui.

Suggested change


### 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
```

Copy link
Owner

Choose a reason for hiding this comment

The 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
```

Copy link
Owner

Choose a reason for hiding this comment

The 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
```

Copy link
Owner

Choose a reason for hiding this comment

The 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
12 changes: 12 additions & 0 deletions cypress.config.js
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,
Copy link
Owner

Choose a reason for hiding this comment

The 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 cypress/support/e2e.js e dentro dele importe o arquivo cypress/support/commands.js.

fixturesFolder: false,
env: {
apiUrl: "http://localhost:3001"
},
},
})
135 changes: 135 additions & 0 deletions cypress/e2e/api/engageSphere.cy.js
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);
Copy link
Owner

Choose a reason for hiding this comment

The 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,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se o teste é para a query string page, não há necessidades de passar limit, size e industry, ainda mais passando-os com seus valores padrão.

size: 'All',
industry: 'All'
}
}).then((response) => {
Copy link
Owner

Choose a reason for hiding this comment

The 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 response.

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,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se o teste é para a query string limit, não há necessidade de passar page, size e industry.

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);
Copy link
Owner

Choose a reason for hiding this comment

The 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])
  })
})

Copy link
Owner

Choose a reason for hiding this comment

The 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)', () => {
Copy link
Owner

Choose a reason for hiding this comment

The 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 page e limit são iguais a 0?

cy.request({
method: 'GET',
url: `${Cypress.env("apiUrl")}/customers`,
Copy link
Owner

Choose a reason for hiding this comment

The 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 CUSTOMERS_API_URL no início do arquivo, a qual poderia ser reaproveitada ao longo de todos os testes sem repetir ${Cypress.env("apiUrl")}/customers?

qs: { page: -1, limit: 5, size: 'All', industry: 'All' },
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basta passar page. Deixe a API usar seus defaults para o resto.

failOnStatusCode: false
}).then((response) => {
Copy link
Owner

Choose a reason for hiding this comment

The 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 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, limite negativo)', () => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basta passar limit. Deixe a API usar seus defaults para o resto.

cy.request({
method: 'GET',
url: `${Cypress.env("apiUrl")}/customers`,
qs: { page: 1, limit: -5, size: 'All', industry: 'All' },
failOnStatusCode: false
}).then((response) => {
Copy link
Owner

Choose a reason for hiding this comment

The 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' },
Copy link
Owner

Choose a reason for hiding this comment

The 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) => {
Copy link
Owner

Choose a reason for hiding this comment

The 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
Copy link
Owner

Choose a reason for hiding this comment

The 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
size: 'InvalidSize', // Valor não suportado
size: 'InvalidSize',

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
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
industry: 'InvalidIndustry' // Valor não suportado
industry: 'InvalidIndustry'

},
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.');
});
});

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change


Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

});
Loading