Skip to content
Merged
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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
| **Postman** | Documentação e testes manuais de API. | 🟠 | [Acessar Doc](https://learning.postman.com/) |
| **Zod** | Validação de schemas e contratos de API. | 🛡️ | [Acessar Doc](https://zod.dev/) |

### Ferramentas de Setup:
* [ESLint](https://eslint.org/) - Análise estática do código.
* [Prettier](https://prettier.io/) - Formatação automática de arquivos.
* [Husky](https://typicode.github.io/husky/) - Git Hooks para automação de tarefas.
* [lint-staged](https://github.com/lint-staged/lint-staged) - Verificação de arquivos modificados antes do commit.




Expand Down Expand Up @@ -75,5 +81,6 @@ Este projeto entrega um **framework de automação E2E robusto e escalável**, d
* **Arquitetura Multicamadas**: Implementação rigorosa do padrão **Page Object Model (POM)**, garantindo a separação entre a lógica de teste e a interação com elementos da interface.
* **Programação Orientada a Objetos (POO)**: Utilização de classes e métodos para encapsular comportamentos, facilitando a reutilização de código e a legibilidade dos cenários.
* **Isolamento e Independência**: Testes desenhados para serem independentes, com setups e cleanups que garantem a confiabilidade da execução (evitando estados compartilhados).
* **Qualidade Contínua (CI/CD)**: Pipeline totalmente integrada via GitHub Actions, validando o projeto em múltiplos motores de renderização (Chromium e Firefox) a cada nova alteração.
* **Entrega Contínua (CI/CD)**: Pipeline totalmente integrada via GitHub Actions, validando o projeto em múltiplos motores de renderização (Chromium e Firefox) a cada nova alteração.
* **Testes de API com Validação de Contrato**: Além da UI, o projeto integra validações de camada de serviço utilizando **Zod**, garantindo que a comunicação com o backend siga rigorosamente os schemas e status definidos.
* **Qualidade de Código e Git Hooks**: Para garantir a consistência do código e evitar que erros simples subam para o repositório, este projeto utiliza **ESLint** e **Prettier**, que sçao ferramentas que analisam estaticamente e identifica os padrões de código problemáticos, e formatam para garantir que todos os arquivos sigam o mesmo estilo. O projeto, na etapa de pré-commit, também utiliza **Husky** na gerência dos Git Hooks garantindo que o código seja automaticamente formatado e verificado. Se houver algum erro de linting que não possa ser corrigido automaticamente, o commit será bloqueado, garantindo que apenas código limpo chegue ao GitHub a cada branch.
8 changes: 8 additions & 0 deletions pages/CheckoutPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export class CheckoutPage {
readonly zipCodeInput: Locator;
readonly continueBtn: Locator;
readonly subtotalLabel: Locator;
readonly finishBtn: Locator;
readonly successHeader: Locator;

constructor(page: Page) {
this.page = page;
Expand All @@ -15,6 +17,8 @@ export class CheckoutPage {
this.zipCodeInput = page.locator('[data-test="postalCode"]');
this.continueBtn = page.locator('[data-test="continue"]');
this.subtotalLabel = page.locator('[data-test="subtotal-label"]');
this.finishBtn = page.locator('[data-test="finish"]');
this.successHeader = page.locator('.complete-header');
}

async preencherDadosEContinuar(first: string, last: string, zip: string) {
Expand All @@ -23,4 +27,8 @@ export class CheckoutPage {
await this.zipCodeInput.fill(zip);
await this.continueBtn.click();
}

async finalizarCompra() {
await this.finishBtn.click();
}
}
10 changes: 10 additions & 0 deletions pages/ItensPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export class ItensPage {
readonly bikeLightAddToCartBtn: Locator;
readonly boltTshirtAddToCartBtn: Locator;
readonly cartLink: Locator;
readonly removeBackpackButton: Locator;
readonly cartItem: Locator;
readonly backpackInCart: Locator;

constructor(page: Page) {
this.page = page;
Expand All @@ -16,11 +19,18 @@ export class ItensPage {
this.bikeLightAddToCartBtn = page.locator('[data-test="add-to-cart-sauce-labs-bike-light"]');
this.boltTshirtAddToCartBtn = page.locator('[data-test="add-to-cart-sauce-labs-bolt-t-shirt"]');
this.cartLink = page.locator('[data-test="shopping-cart-link"]');
this.removeBackpackButton = page.locator('[data-test="remove-sauce-labs-backpack"]');
this.cartItem = page.locator('.cart_item');
this.backpackInCart = page.locator('.cart_item').filter({ hasText: 'Sauce Labs Backpack' });
}

async adicionarBackpackAoCarrinho() {
await this.backpackAddToCartBtn.click();
await this.bikeLightAddToCartBtn.click();
await this.boltTshirtAddToCartBtn.click();
}

async removeBackPack() {
await this.removeBackpackButton.click();
}
}
21 changes: 20 additions & 1 deletion tests/e2e/checkout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { test, expect } from '@playwright/test';
import { CartFlows } from '../../fluxos/cartilhaFluxos';
import { CheckoutPage } from '../../pages/CheckoutPage';
import { LoginPage } from '../../pages/LoginPage';
import { ItensPage } from '../../pages/ItensPage';

test.describe('Cenários de Checkout', () => {
// Setup de Login obrigatório para acessar o inventário
test.beforeEach(async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.acessarPagina();
Expand All @@ -22,4 +22,23 @@ test.describe('Cenários de Checkout', () => {

await expect(checkout.subtotalLabel).toContainText('55.97');
});

test('Fluxo completo do checkout com sucesso após adicionar itens', async ({ page }) => {
const itens = new ItensPage(page);
const checkout = new CheckoutPage(page);

await itens.adicionarBackpackAoCarrinho();
await itens.cartLink.click();
await page.locator('[data-test="checkout"]').click();

await checkout.preencherDadosEContinuar('Marcus', 'Machado', '31030080');

await expect(checkout.subtotalLabel).toContainText('Item total: $');
await expect(
page.locator('.inventory_item_name').filter({ hasText: 'Sauce Labs Backpack' })
).toBeVisible();

await checkout.finalizarCompra();
await expect(checkout.successHeader).toHaveText('Thank you for your order!');
});
});
17 changes: 16 additions & 1 deletion tests/e2e/itensCarrinho.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { test, expect } from '@playwright/test';
import { LoginPage } from '../../pages/LoginPage';
import { ItensPage } from '../../pages/ItensPage';

test.describe('Cenários de adicionar itens no Carrinho', () => {
test.describe('Cenários de adicionar e remover itens no Carrinho', () => {
test.beforeEach(async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.acessarPagina();
Expand All @@ -17,4 +17,19 @@ test.describe('Cenários de adicionar itens no Carrinho', () => {
await expect(item.cartBadge).toHaveText('3');
await expect(page.locator('[data-test="remove-sauce-labs-backpack"]')).toBeVisible();
});

test('Remover item do carrinho e validar a exclusão', async ({ page }) => {
const item = new ItensPage(page);

await item.adicionarBackpackAoCarrinho();
await item.cartLink.click();

await expect(item.backpackInCart).toBeVisible();

await item.removeBackPack();

await expect(item.backpackInCart).not.toBeAttached();

await expect(item.cartBadge).toHaveText('2');
});
});
Loading