Skip to content

Commit

Permalink
Merge pull request #76 from LeohsPaixao/story/inicia-os-testes-playwr…
Browse files Browse the repository at this point in the history
…ight

Story/inicia os testes playwright
  • Loading branch information
LeohsPaixao authored Dec 3, 2024
2 parents f33521e + 70ace60 commit 5555a65
Show file tree
Hide file tree
Showing 19 changed files with 460 additions and 24 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,15 @@ jobs:
- name: Iniciar backend
run: |
cd backend
yarn api &
chmod +x .github/scripts/wait_until.sh
.github/scripts/wait_until.sh localhost:3001
nohup yarn api &
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}

- name: Iniciar frontend
run: |
cd frontend
yarn serve &
chmod +x .github/scripts/wait_until.sh
.github/scripts/wait_until.sh 127.0.0.1:8181
nohup yarn serve &
- name: Executar testes Cypress
run: |
Expand Down Expand Up @@ -142,6 +138,9 @@ jobs:
run: |
cd test/playwright
yarn play:run
env:
PLAY_API_URL: ${{ secrets.PLAY_API_URL }}
PLAY_BASE_URL: ${{ secrets.PLAY_BASE_URL }}

- name: Upload de relatório Playwright
if: ${{ failure() }}
Expand Down
6 changes: 6 additions & 0 deletions test/cypress/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# cypress-ui-tests

## 1.3.1

### Patch Changes

- 5c19a98: test: remove o uso da funcao fillUserForm nos testes

## 1.3.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cypress-ui-tests",
"version": "1.3.0",
"version": "1.3.1",
"description": "Project Tests Cypress",
"author": "Leonardo Paixao <[email protected]>",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/tests/e2e/shared/fillUserForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function fillUserForm() {
{ element: cy.get('[data-testid="input-socialname"]'), valor: faker.person.middleName() },
{ element: cy.get('[data-testid="input-document"]'), valor: cpf },
{ element: cy.get('[data-testid="input-phone"]'), valor: faker.phone.number({ style: 'national' }) },
{ element: cy.get('[data-testid="input-email"]'), valor: faker.internet.email() },
{ element: cy.get('[data-testid="input-email"]'), valor: faker.internet.email({ provider: 'example.qa.solar' }) },
{ element: cy.get('[data-testid="input-password"]'), valor: '123456' },
];

Expand Down
10 changes: 0 additions & 10 deletions test/cypress/tests/e2e/specs/registerUser.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,20 @@ describe('Tela de Cadastro de Usuário', () => {
});

it('Não deveria ser possivel criar o usuário com o Nome Completo errado', () => {
fillUserForm();
cy.get('[data-testid="input-fullname"]').type('{selectall}Teste');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-fullname"]').should('be.visible').and('have.text', 'O Nome Completo deve conter pelo menos Nome e Sobrenome.');
});

it('Não deveria ser possivel criar o usuário com o CPF inválido', () => {
fillUserForm();
cy.get('[data-testid="input-document"]').type('{selectall}123.456.789-10');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-cpfcnpj"]').should('be.visible').and('have.text', 'CPF inválido.');
});

it('Não deveria ser possivel criar o usuário com o CNPJ inválido', () => {
fillUserForm();
cy.get('[data-testid="select-document-type"]').select('cnpj');
cy.get('[data-testid="input-document"]').type('{selectall}12.456.789/1110-60');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
Expand All @@ -50,47 +47,41 @@ describe('Tela de Cadastro de Usuário', () => {
});

it('Não deveria ser possivel colocar letras no campo de telefone', () => {
fillUserForm();
cy.get('[data-testid="input-phone"]').type('{selectall}sdadfafsa');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-phone"]').should('be.visible').and('have.text', 'O telefone deve conter apenas números.');
});

it('Não deveria ser possivel colocar mais do que 11 dígitos no campo de telefone', () => {
fillUserForm();
cy.get('[data-testid="input-phone"]').type('{selectall}154542165455454');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-phone"]').should('be.visible').and('have.text', 'O telefone deve ter no máximo 11 dígitos.');
});

it('Não deveria ser possivel colocar menos do que 10 dígitos no campo de telefone', () => {
fillUserForm();
cy.get('[data-testid="input-phone"]').type('{selectall}123');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-phone"]').should('be.visible').and('have.text', 'O telefone deve ter no mínimo 10 dígitos.');
});

it('Não deveria ser possivel criar o usuário com o email inválido', () => {
fillUserForm();
cy.get('[data-testid="input-email"]').type('{selectall}email@email');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-email"]').should('be.visible').and('have.text', 'Email inválido.');
});

it('Não deveria ser possivel cadastrar o usuário com uma senha com menos de 6 caracteres', () => {
fillUserForm();
cy.get('[data-testid="input-password"]').type('{selectall}12345');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
cy.get('[data-testid="input-error-password"]').should('be.visible').and('have.text', 'A Senha deve ter no mínimo 6 caracteres.');
});

it('Não deveria ser possivel cadastrar o usuário com uma senha com mais de 20 caracteres', () => {
fillUserForm();
cy.get('[data-testid="input-password"]').type('{selectall}1234567891012141516131');
cy.get('[data-testid="btn-register"]').should('be.enabled').click();
cy.get('[data-testid="toast-content"]').should('have.text', 'Por favor, corrija os erros no formulário.');
Expand All @@ -108,5 +99,4 @@ describe('Tela de Cadastro de Usuário', () => {
cy.get('[data-testid="form-login"]').should('be.visible');
cy.get('[data-testid="btn-login"]').should('be.visible');
});

});
2 changes: 2 additions & 0 deletions test/playwright/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PLAY_BASE_URL = "http://localhost:8181"
PLAY_API_URL = "http://localhost:3001"
13 changes: 13 additions & 0 deletions test/playwright/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# playwright-ui-tests

## 1.2.0

### Minor Changes

- c647a81: test: adiciona testes na tela de listagem de usuários com o projeto Playwright
- 5c19a98: test: adiciona testes na tela de cadastro do usuário com o projeto Playwright
- 5c19a98: test: adiciona testes na tela de recuperação de senha com o projeto Playwright
- 8b293f3: test: adiciona testes na tela de perfil do usuário com o projeto Playwright

### Patch Changes

- ffccc3d: test: adiciona variaveis de ambiente para o projeto Playwright

## 1.1.5

### Patch Changes
Expand Down
9 changes: 5 additions & 4 deletions test/playwright/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "playwright-ui-tests",
"version": "1.1.5",
"version": "1.2.0",
"description": "Project Tests Playwright",
"author": "Leonardo Paixao <[email protected]>",
"license": "MIT",
Expand All @@ -10,11 +10,12 @@
"play:open": "playwright test --ui",
"play:report": "playwright show-report"
},
"dependencies": {
"@faker-js/faker": "^9.2.0",
"dotenv": "^16.4.5"
},
"devDependencies": {
"@playwright/test": "^1.49.0",
"@types/node": "^22.9.1"
},
"dependencies": {
"dotenv": "^16.4.5"
}
}
7 changes: 5 additions & 2 deletions test/playwright/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { defineConfig, devices } from '@playwright/test';
import dotenv from 'dotenv'

dotenv.config()

export default defineConfig({
testDir: './tests/specs',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
workers: 1,
reporter: 'html',
use: {
baseURL: 'http://localhost:8181',
baseURL: process.env.PLAY_BASE_URL,
trace: 'on-first-retry',
},
projects: [
Expand Down
Empty file.
34 changes: 34 additions & 0 deletions test/playwright/tests/shared/commands/fillUserForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { faker } from '@faker-js/faker';
import { Page } from '@playwright/test';
import { generateValidCPF } from './generateValidCPF';

/**
* Esta função preenche um formulário de usuário com dados gerados aleatoriamente usando Playwright e Faker.js.
*
* @observações
* A função utiliza os atributos data-testid para localizar campos específicos no formulário e digita os dados gerados.
*
* @exemplo
* ```typescript
* fillUserForm();
* ```
*
* @retorno {void} A função não retorna nenhum valor.
*/
export async function fillUserForm(page: Page) {
const cpf = generateValidCPF();

const formFields = [
{ element: page.locator('[data-testid="input-fullname"]'), valor: faker.person.fullName() },
{ element: page.locator('[data-testid="input-socialname"]'), valor: faker.person.middleName() },
{ element: page.locator('[data-testid="input-document"]'), valor: cpf },
{ element: page.locator('[data-testid="input-phone"]'), valor: faker.phone.number({ style: 'national' }) },
{ element: page.locator('[data-testid="input-email"]'), valor: faker.internet.email({ provider: 'example.qa.solar' }) },
{ element: page.locator('[data-testid="input-password"]'), valor: '123456' },
];

for (const field of formFields) {
await field.element.waitFor({ state: 'visible' })
await field.element.fill(field.valor);
}
}
44 changes: 44 additions & 0 deletions test/playwright/tests/shared/commands/generateValidCPF.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
function generateRandomDigits(length: number): string {
return Array.from({ length }, () => Math.floor(Math.random() * 10)).join('');
}

function calculateVerifierDigit(base: string): number {
const baseDigits = base.split('').map(Number);
const length = baseDigits.length;
const sum = baseDigits.reduce((acc, digit, index) => acc + digit * (length + 1 - index), 0);
const remainder = sum % 11;
return remainder < 2 ? 0 : 11 - remainder;
}

function formatCPF(cpf: string): string {
return cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
}

/**
* Gera um CPF válido (Cadastro de Pessoas Físicas).
*
* @retorna Uma string representando um CPF válido no formato "XXX.XXX.XXX-XX".
*
* @observações
* Esta função utiliza uma combinação de geração aleatória de dígitos, cálculo de dígitos verificadores
* e formatação para criar um CPF válido. O CPF gerado não está associado a nenhuma pessoa real e
* deve ser usado apenas para fins de teste ou demonstração.
*
* O algoritmo utilizado nesta função segue as regras oficiais de geração de CPF:
* 1. Gera uma base aleatória de 9 dígitos.
* 2. Calcula o primeiro dígito verificador usando a base e a fórmula:
* (10 * d1 + 9 * d2 + 8 * d3 + 7 * d4 + 6 * d5 + 5 * d6 + 4 * d7 + 3 * d8 + 2 * d9) mod 11
* O resultado deve ser 0 ou 11 - resultado.
* 3. Calcula o segundo dígito verificador usando a base, o primeiro dígito verificador e a fórmula:
* (11 * d1 + 10 * d2 + 9 * d3 + 8 * d4 + 7 * d5 + 6 * d6 + 5 * d7 + 4 * d8 + 3 * d9 + 2 * primeiroVerificador) mod 11
* O resultado deve ser 0 ou 11 - resultado.
* 4. Combina a base, o primeiro dígito verificador e o segundo dígito verificador para formar o CPF final.
* 5. Formata o CPF no padrão brasileiro: "XXX.XXX.XXX-XX".
*/
export function generateValidCPF(): string {
const baseDigits = generateRandomDigits(9);
const firstVerifier = calculateVerifierDigit(baseDigits);
const secondVerifier = calculateVerifierDigit(baseDigits + firstVerifier);
const cpf = `${baseDigits}${firstVerifier}${secondVerifier}`;
return formatCPF(cpf);
}
31 changes: 31 additions & 0 deletions test/playwright/tests/shared/commands/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Page } from '@playwright/test';

/**
* Realiza a operação de login simulando uma requisição POST para o endpoint de login da API.
* Armazena o token recebido e o e-mail no local storage do navegador.
*
* @param {Page} page - A página do Playwright onde o localStorage será definido.
* @param {string} email - O email do usuário para login.
* @param {string} password - A senha do usuário para login.
* @returns {Promise<void>} - Uma promise que é resolvida quando a operação de login é concluída.
*/
export async function login(page: Page, email: string, password: string): Promise<void> {

const response = await page.request.fetch(`${process.env.PLAY_API_URL}/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: {
email,
password
}
})

const { token } = JSON.parse(await response.text())

await page.evaluate(({ email, token }) => {
localStorage.setItem('user-token', token);
localStorage.setItem('user-email', email);
}, { email, token });
}
37 changes: 37 additions & 0 deletions test/playwright/tests/shared/mocks/generateUsers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { faker } from '@faker-js/faker';
import { request } from '@playwright/test';
import { generateValidCPF } from '../commands/generateValidCPF';

/**
* Realiza o mock de criação de um usuário através de requisições HTTP.
*/
async function mockGenerateUsers(): Promise<void> {
const apiContext = await request.newContext({
baseURL: `${process.env.PLAY_API_URL}/register`,
});

const response = await apiContext.post('/register', {
data: {
fullName: faker.person.fullName(),
socialName: faker.person.lastName(),
document: generateValidCPF(),
docType: 'cpf',
phone: faker.phone.number({ style: 'national' }),
email: faker.internet.email({ provider: 'example.qa.solar' }),
password: '123456',
},
});

if (!response.ok()) {
throw new Error(`Erro ao criar usuário: ${response.status()}`);
}
}

/**
* Gera múltiplos usuários simulados.
*/
export async function generateUsers(): Promise<void> {
for (let i = 0; i < 10; i++) {
await mockGenerateUsers();
}
}
Empty file.
40 changes: 40 additions & 0 deletions test/playwright/tests/specs/listUsers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { expect, test } from '@playwright/test';
import { login } from '../shared/commands/login';
import { generateUsers } from '../shared/mocks/generateUsers';

test.describe('Tela de listagem de Usuários', () => {

test.beforeAll(async () => {
await generateUsers();
});

test.beforeEach(async ({ page }) => {
login(page, '[email protected]', '123456');
await page.goto('/listusers')
await page.waitForURL('/listusers');
});

test('Deveria ser possível visualizar os elementos da tela de listagem de Usuários', async ({ page }) => {
await expect(page.locator('[data-testid="table-users"]')).toBeVisible();
await expect(page.locator('[data-testid="checkbox-select-all"]')).toBeVisible();
await page.locator('[data-testid="btn-delete-user"]').scrollIntoViewIfNeeded();
await expect(page.locator('[data-testid="btn-delete-user"]')).toBeVisible();
});

test('Deveria ser possível selecionar todos os usuários', async ({ page }) => {
const selectAllCheckbox = page.locator('[data-testid="checkbox-select-all"]');
await selectAllCheckbox.check();
await expect(selectAllCheckbox).toBeChecked();
});

test('Deveria ser possível selecionar um usuário e excluí-lo', async ({ page }) => {
const userCheckbox = page.locator('[data-testid="checkbox-select-users"]').nth(2);
await userCheckbox.check();
const deleteButton = page.locator('[data-testid="btn-delete-user"]');
await deleteButton.scrollIntoViewIfNeeded();
await deleteButton.click();
const toastContent = page.locator('[data-testid="toast-content"]').first();
await expect(toastContent).toBeVisible();
await expect(toastContent).toHaveText('1 usuário(s) excluído(s) com sucesso!');
});
});
Loading

0 comments on commit 5555a65

Please sign in to comment.