Teste de Software

Open in GitHub Open in Codespaces

Arquivos
invest-app-test
├── package-lock.json
├── package.json
├── playwright.config.js
├── prisma
│   ├── dev.db
│   ├── migrations
│   │   ├── 20230826214323_init
│   │   │   └── migration.sql
│   │   ├── 20230902014613_create_category
│   │   │   └── migration.sql
│   │   ├── 20230902065351_create_user
│   │   │   └── migration.sql
│   │   ├── 20230902111235_create_investment_broker_interest_created_at
│   │   │   └── migration.sql
│   │   ├── 20230902131930_create_investment_user_cascade
│   │   │   └── migration.sql
│   │   ├── 20230905183705_user_image
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   ├── schema.prisma
│   ├── seed.js
│   └── seeders.json
├── public
│   ├── css
│   │   └── style.css
│   ├── home.html
│   ├── imgs
│   │   └── profile
│   │       ├── 9948180954ee1846a214c710ada7a2a5-avatar.png
│   │       └── avatar.png
│   ├── js
│   │   ├── home.js
│   │   ├── lib
│   │   │   ├── auth.js
│   │   │   └── format.js
│   │   ├── profile.js
│   │   ├── services
│   │   │   └── api.js
│   │   ├── signin.js
│   │   └── signup.js
│   ├── profile.html
│   ├── signin.html
│   └── signup.html
├── requests.http
├── src
│   ├── config
│   │   ├── mail.js
│   │   └── multer.js
│   ├── database
│   │   └── database.js
│   ├── index.js
│   ├── middleware
│   │   ├── auth.js
│   │   └── validate.js
│   ├── models
│   │   ├── Category.js
│   │   ├── Image.js
│   │   ├── Investment.js
│   │   └── User.js
│   ├── routes.js
│   ├── routes.test.js
│   └── services
│       └── SendMail.js
└── tests
    └── invest-app.spec.js
Arquivos
invest-app-test
├── package-lock.json
├── package.json
├── playwright.config.js
├── prisma
│   ├── dev.db
│   ├── migrations
│   │   ├── 20230826214323_init
│   │   │   └── migration.sql
│   │   ├── 20230902014613_create_category
│   │   │   └── migration.sql
│   │   ├── 20230902065351_create_user
│   │   │   └── migration.sql
│   │   ├── 20230902111235_create_investment_broker_interest_created_at
│   │   │   └── migration.sql
│   │   ├── 20230902131930_create_investment_user_cascade
│   │   │   └── migration.sql
│   │   ├── 20230905183705_user_image
│   │   │   └── migration.sql
│   │   └── migration_lock.toml
│   ├── schema.prisma
│   ├── seed.js
│   └── seeders.json
├── public
│   ├── css
│   │   └── style.css
│   ├── home.html
│   ├── imgs
│   │   └── profile
│   │       ├── 9948180954ee1846a214c710ada7a2a5-avatar.png
│   │       └── avatar.png
│   ├── js
│   │   ├── home.js
│   │   ├── lib
│   │   │   ├── auth.js
│   │   │   └── format.js
│   │   ├── profile.js
│   │   ├── services
│   │   │   └── api.js
│   │   ├── signin.js
│   │   └── signup.js
│   ├── profile.html
│   ├── signin.html
│   └── signup.html
├── requests.http
├── src
│   ├── config
│   │   ├── mail.js
│   │   └── multer.js
│   ├── database
│   │   └── database.js
│   ├── index.js
│   ├── middleware
│   │   ├── auth.js
│   │   └── validate.js
│   ├── models
│   │   ├── Category.js
│   │   ├── Image.js
│   │   ├── Investment.js
│   │   └── User.js
│   ├── routes.js
│   ├── routes.test.js
│   └── services
│       └── SendMail.js
└── tests
    └── invest-app.spec.js

Back-end

$ npm install supertest -D
$ npm install supertest -D
/codes/expressjs/invest-app-test/src/routes.test.js
import { describe, it, before } from 'node:test';
import assert from 'node:assert';
import request from 'supertest';
import crypto from 'crypto';
import app from './index.js';
 
let categoryPos;
let createdInvestment;
 
const newInvestment = {
  name: 'Tesouro Selic 2029',
  value: 10000,
  interest: '100% Selic',
  createdAt: '2025-01-01',
  broker: 'Banco Inter',
};
 
const updatedInvestment = {
  name: 'Tesouro Selic 2029',
  value: 10000,
  interest: '100% Selic',
  createdAt: '2025-01-01',
  broker: 'Banco Inter',
};
 
let validUser;
 
const invalidUser = {
  name: 'Invalid',
  email: 'invalid@email.com',
  password: '12345678',
  confirmationPassword: '12345678',
};
 
async function loadToken(user) {
  const response = await request(app).post('/api/signin').send(user);
  return response.body.token;
}
 
function createValidUser() {
  const validUser = {
    password: '12345678',
    confirmationPassword: '12345678',
  };
 
  const hash = crypto.randomBytes(20).toString('hex');
  validUser.name = `Valid ${hash}`;
  validUser.email = `valid-${hash}@email.com`;
 
  return validUser;
}
 
describe('Invest App', () => {
  before(() => {
    validUser = createValidUser();
  });
 
  describe('User Endpoints', () => {
    describe('POST /api/users', () => {
      it('should create a new user', async () => {
        const response = await request(app).post('/api/users').send(validUser);
        assert.strictEqual(response.statusCode, 201);
      });
 
      it('should not create a new user with same email', async () => {
        const response = await request(app).post('/api/users').send(validUser);
        assert.strictEqual(response.statusCode, 400);
      });
 
      it('should not create a new user without email', async () => {
        const { name, password } = validUser;
        const response = await request(app)
          .post('/api/users')
          .send({ name, password });
        assert.strictEqual(response.statusCode, 400);
      });
    });
 
    describe('GET /users/me', () => {
      it('should not show the current user without login', async () => {
        const response = await request(app).get('/api/users/me');
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show the current user', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/users/me')
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
    });
  });
 
  describe('Sign in Endpoints', () => {
    describe('POST /signin', () => {
      it('should login a valid user', async () => {
        const response = await request(app).post('/api/signin').send(validUser);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should not login an invalid user', async () => {
        const response = await request(app)
          .post('/api/signin')
          .send(invalidUser);
        assert.strictEqual(response.statusCode, 401);
      });
    });
  });
 
  describe('Category Endpoints', () => {
    describe('GET /categories', () => {
      it('should not show categories without login', async () => {
        const response = await request(app).get(`/api/categories`);
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show categories', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/categories`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should show categories with specific name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/categories?name=Pós`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
    });
  });
 
  describe('Investments Endpoints', () => {
    describe('POST /investments', () => {
      it('should not create a new investment without login', async () => {
        const token = await loadToken(validUser);
        let response = await request(app)
          .get(`/api/categories?name=Pós`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
 
        categoryPos = response.body;
        newInvestment.categoryId = categoryPos.id;
 
        response = await request(app)
          .post('/api/investments')
          .send(newInvestment);
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should create a new investment', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .post('/api/investments')
          .set('Authorization', 'bearer ' + token)
          .send(newInvestment);
        createdInvestment = response.body;
        assert.strictEqual(response.statusCode, 201);
      });
 
      it('should not create a new investment without name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .post('/api/investments')
          .set('Authorization', 'bearer ' + token)
          .send({
            name: 'Tesouro Selic 2029',
          });
        assert.strictEqual(response.statusCode, 400);
      });
    });
 
    describe('GET /investments', () => {
      it('should not show all investments without login', async () => {
        const response = await request(app).get('/api/investments');
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show all investments', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments')
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should list the valid host', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments')
          .set('Authorization', 'bearer ' + token);
        const hasValidInvestment = response.body.some(
          (investment) => investment.name === createdInvestment.name
        );
        assert.strictEqual(hasValidInvestment, true);
      });
 
      it('should show all investments by name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments?name=Tesouro')
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
    });
 
    describe('GET /investments/:investmentId', () => {
      it('should not show a investment by id without login', async () => {
        const response = await request(app).get(
          `/api/investments/${createdInvestment.id}`
        );
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show a investment by id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
        assert.strictEqual(response.body.name, createdInvestment.name);
      });
 
      it('should not show a investment with invalid id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/investments/x`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.body[0].message, 'Invalid uuid');
      });
    });
 
    describe('PUT /investments/:investmentId', () => {
      it('should not update a investment without login', async () => {
        const token = await loadToken(validUser);
        let response = await request(app)
          .get(`/api/categories?name=Pós`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
 
        categoryPos = response.body;
        updatedInvestment.categoryId = categoryPos.id;
 
        response = await request(app)
          .put(`/api/investments/${createdInvestment.id}`)
          .send(updatedInvestment);
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should update a investment', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .put(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token)
          .send(updatedInvestment);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should list an updated investment', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments')
          .set('Authorization', 'bearer ' + token);
        const hasValidInvestment = response.body.some(
          (investment) => investment.name === updatedInvestment.name
        );
        assert.strictEqual(hasValidInvestment, true);
      });
 
      it('should not update a investment without name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .put(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token)
          .send({
            name: 'Tesouro Selic 2029',
          });
        assert.strictEqual(response.statusCode, 400);
      });
 
      it('should not update a investment with invalid id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .put(`/api/investments/x`)
          .set('Authorization', 'bearer ' + token)
          .send(updatedInvestment);
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.body[0].message, 'Invalid uuid');
      });
    });
 
    describe('DELETE /investments/:investmentId', () => {
      it('should not remove a investment without login', async () => {
        const response = await request(app).delete(
          `/api/investments/${createdInvestment.id}`
        );
 
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should remove a investment', async () => {
        const token = await loadToken(validUser);
 
        const response = await request(app)
          .delete(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token);
 
        assert.strictEqual(response.statusCode, 204);
      });
 
      it('should not delete a investment with invalid id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .delete(`/api/investments/x`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.body[0].message, 'Invalid uuid');
      });
    });
  });
 
  describe('404 Endpoints', () => {
    describe('GET /unknown-endpoint', () => {
      it('should show 404', async () => {
        const response = await request(app).get(`/api/unknown-endpoint`);
        assert.strictEqual(response.statusCode, 404);
      });
    });
  });
});
 
/codes/expressjs/invest-app-test/src/routes.test.js
import { describe, it, before } from 'node:test';
import assert from 'node:assert';
import request from 'supertest';
import crypto from 'crypto';
import app from './index.js';
 
let categoryPos;
let createdInvestment;
 
const newInvestment = {
  name: 'Tesouro Selic 2029',
  value: 10000,
  interest: '100% Selic',
  createdAt: '2025-01-01',
  broker: 'Banco Inter',
};
 
const updatedInvestment = {
  name: 'Tesouro Selic 2029',
  value: 10000,
  interest: '100% Selic',
  createdAt: '2025-01-01',
  broker: 'Banco Inter',
};
 
let validUser;
 
const invalidUser = {
  name: 'Invalid',
  email: 'invalid@email.com',
  password: '12345678',
  confirmationPassword: '12345678',
};
 
async function loadToken(user) {
  const response = await request(app).post('/api/signin').send(user);
  return response.body.token;
}
 
function createValidUser() {
  const validUser = {
    password: '12345678',
    confirmationPassword: '12345678',
  };
 
  const hash = crypto.randomBytes(20).toString('hex');
  validUser.name = `Valid ${hash}`;
  validUser.email = `valid-${hash}@email.com`;
 
  return validUser;
}
 
describe('Invest App', () => {
  before(() => {
    validUser = createValidUser();
  });
 
  describe('User Endpoints', () => {
    describe('POST /api/users', () => {
      it('should create a new user', async () => {
        const response = await request(app).post('/api/users').send(validUser);
        assert.strictEqual(response.statusCode, 201);
      });
 
      it('should not create a new user with same email', async () => {
        const response = await request(app).post('/api/users').send(validUser);
        assert.strictEqual(response.statusCode, 400);
      });
 
      it('should not create a new user without email', async () => {
        const { name, password } = validUser;
        const response = await request(app)
          .post('/api/users')
          .send({ name, password });
        assert.strictEqual(response.statusCode, 400);
      });
    });
 
    describe('GET /users/me', () => {
      it('should not show the current user without login', async () => {
        const response = await request(app).get('/api/users/me');
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show the current user', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/users/me')
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
    });
  });
 
  describe('Sign in Endpoints', () => {
    describe('POST /signin', () => {
      it('should login a valid user', async () => {
        const response = await request(app).post('/api/signin').send(validUser);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should not login an invalid user', async () => {
        const response = await request(app)
          .post('/api/signin')
          .send(invalidUser);
        assert.strictEqual(response.statusCode, 401);
      });
    });
  });
 
  describe('Category Endpoints', () => {
    describe('GET /categories', () => {
      it('should not show categories without login', async () => {
        const response = await request(app).get(`/api/categories`);
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show categories', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/categories`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should show categories with specific name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/categories?name=Pós`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
    });
  });
 
  describe('Investments Endpoints', () => {
    describe('POST /investments', () => {
      it('should not create a new investment without login', async () => {
        const token = await loadToken(validUser);
        let response = await request(app)
          .get(`/api/categories?name=Pós`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
 
        categoryPos = response.body;
        newInvestment.categoryId = categoryPos.id;
 
        response = await request(app)
          .post('/api/investments')
          .send(newInvestment);
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should create a new investment', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .post('/api/investments')
          .set('Authorization', 'bearer ' + token)
          .send(newInvestment);
        createdInvestment = response.body;
        assert.strictEqual(response.statusCode, 201);
      });
 
      it('should not create a new investment without name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .post('/api/investments')
          .set('Authorization', 'bearer ' + token)
          .send({
            name: 'Tesouro Selic 2029',
          });
        assert.strictEqual(response.statusCode, 400);
      });
    });
 
    describe('GET /investments', () => {
      it('should not show all investments without login', async () => {
        const response = await request(app).get('/api/investments');
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show all investments', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments')
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should list the valid host', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments')
          .set('Authorization', 'bearer ' + token);
        const hasValidInvestment = response.body.some(
          (investment) => investment.name === createdInvestment.name
        );
        assert.strictEqual(hasValidInvestment, true);
      });
 
      it('should show all investments by name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments?name=Tesouro')
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
      });
    });
 
    describe('GET /investments/:investmentId', () => {
      it('should not show a investment by id without login', async () => {
        const response = await request(app).get(
          `/api/investments/${createdInvestment.id}`
        );
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should show a investment by id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
        assert.strictEqual(response.body.name, createdInvestment.name);
      });
 
      it('should not show a investment with invalid id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get(`/api/investments/x`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.body[0].message, 'Invalid uuid');
      });
    });
 
    describe('PUT /investments/:investmentId', () => {
      it('should not update a investment without login', async () => {
        const token = await loadToken(validUser);
        let response = await request(app)
          .get(`/api/categories?name=Pós`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 200);
 
        categoryPos = response.body;
        updatedInvestment.categoryId = categoryPos.id;
 
        response = await request(app)
          .put(`/api/investments/${createdInvestment.id}`)
          .send(updatedInvestment);
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should update a investment', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .put(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token)
          .send(updatedInvestment);
        assert.strictEqual(response.statusCode, 200);
      });
 
      it('should list an updated investment', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .get('/api/investments')
          .set('Authorization', 'bearer ' + token);
        const hasValidInvestment = response.body.some(
          (investment) => investment.name === updatedInvestment.name
        );
        assert.strictEqual(hasValidInvestment, true);
      });
 
      it('should not update a investment without name', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .put(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token)
          .send({
            name: 'Tesouro Selic 2029',
          });
        assert.strictEqual(response.statusCode, 400);
      });
 
      it('should not update a investment with invalid id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .put(`/api/investments/x`)
          .set('Authorization', 'bearer ' + token)
          .send(updatedInvestment);
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.body[0].message, 'Invalid uuid');
      });
    });
 
    describe('DELETE /investments/:investmentId', () => {
      it('should not remove a investment without login', async () => {
        const response = await request(app).delete(
          `/api/investments/${createdInvestment.id}`
        );
 
        assert.strictEqual(response.statusCode, 401);
      });
 
      it('should remove a investment', async () => {
        const token = await loadToken(validUser);
 
        const response = await request(app)
          .delete(`/api/investments/${createdInvestment.id}`)
          .set('Authorization', 'bearer ' + token);
 
        assert.strictEqual(response.statusCode, 204);
      });
 
      it('should not delete a investment with invalid id', async () => {
        const token = await loadToken(validUser);
        const response = await request(app)
          .delete(`/api/investments/x`)
          .set('Authorization', 'bearer ' + token);
        assert.strictEqual(response.statusCode, 400);
        assert.strictEqual(response.body[0].message, 'Invalid uuid');
      });
    });
  });
 
  describe('404 Endpoints', () => {
    describe('GET /unknown-endpoint', () => {
      it('should show 404', async () => {
        const response = await request(app).get(`/api/unknown-endpoint`);
        assert.strictEqual(response.statusCode, 404);
      });
    });
  });
});
 
$ node --test **/*.test.js
$ npm run test
$ node --test **/*.test.js
$ npm run test

Front-end

$ npm init playwright
$ npm init playwright
/codes/expressjs/invest-app-test/tests/invest-app.spec.js
import { test, expect } from '@playwright/test';
import crypto from 'crypto';
 
function createValidUser() {
  const hash = crypto.randomBytes(20).toString('hex');
 
  const name = `Valid ${hash}`;
  const email = `valid-${hash}@email.com`;
 
  return {
    name,
    email,
    password: '12345678',
  };
}
 
test.describe('Invest App', () => {
  let validUser;
 
  test.beforeAll(() => {
    validUser = createValidUser();
  });
 
  test('should sign up, sign in, and manage investments', async ({ page }) => {
    // Signup
    await page.goto('/signup.html');
    await page.getByRole('textbox', { name: 'Nome' }).fill(validUser.name);
    await page.getByRole('textbox', { name: 'Email' }).fill(validUser.email);
    await page
      .getByRole('textbox', { name: 'Senha', exact: true })
      .fill(validUser.password);
    await page
      .getByRole('textbox', { name: 'Confirmar Senha' })
      .fill(validUser.password);
    await page.getByRole('button', { name: 'Cadastrar' }).click();
    await expect(page.getByRole('heading', { name: 'Entrar' })).toBeVisible();
 
    // Signin
    await page.goto('/signin.html');
    await page.getByRole('textbox', { name: 'Email' }).fill(validUser.email);
    await page.getByRole('textbox', { name: 'Senha' }).fill(validUser.password);
    await page.getByRole('button', { name: 'Entrar' }).click();
    await expect(
      page.getByRole('heading', { name: 'Investimentos' })
    ).toBeVisible();
 
    // Home - Add Investment
    await page.goto('/home.html');
    await page.getByRole('button', { name: '+' }).click();
 
    await page.getByRole('textbox', { name: 'Nome' }).fill('Tesouro Selic');
    await page.getByRole('spinbutton', { name: 'Valor' }).fill('155');
    await page.getByRole('textbox', { name: 'Taxa' }).fill('100% Selic');
    await page.getByRole('textbox', { name: 'Corretora' }).fill('Inter');
    await page.getByRole('textbox', { name: 'Data' }).fill('2025-02-10');
    await page.getByRole('button', { name: 'Submit' }).click();
 
    await expect(page.getByText('Tesouro Selic')).toBeVisible();
 
    // Edit Investment
    await page.locator('svg').nth(1).click();
    await page
      .getByRole('textbox', { name: 'Nome' })
      .fill('Tesouro Selic 2029');
    await page.getByRole('button', { name: 'Submit' }).click();
 
    await expect(page.getByText('Tesouro Selic 2029')).toBeVisible();
 
    // Delete Investment
    await page.locator('svg').first().click();
    await page.getByRole('button', { name: 'Confirmar' }).click();
 
    await expect(page.getByText('Tesouro Selic 2029')).not.toBeVisible();
  });
});
 
/codes/expressjs/invest-app-test/tests/invest-app.spec.js
import { test, expect } from '@playwright/test';
import crypto from 'crypto';
 
function createValidUser() {
  const hash = crypto.randomBytes(20).toString('hex');
 
  const name = `Valid ${hash}`;
  const email = `valid-${hash}@email.com`;
 
  return {
    name,
    email,
    password: '12345678',
  };
}
 
test.describe('Invest App', () => {
  let validUser;
 
  test.beforeAll(() => {
    validUser = createValidUser();
  });
 
  test('should sign up, sign in, and manage investments', async ({ page }) => {
    // Signup
    await page.goto('/signup.html');
    await page.getByRole('textbox', { name: 'Nome' }).fill(validUser.name);
    await page.getByRole('textbox', { name: 'Email' }).fill(validUser.email);
    await page
      .getByRole('textbox', { name: 'Senha', exact: true })
      .fill(validUser.password);
    await page
      .getByRole('textbox', { name: 'Confirmar Senha' })
      .fill(validUser.password);
    await page.getByRole('button', { name: 'Cadastrar' }).click();
    await expect(page.getByRole('heading', { name: 'Entrar' })).toBeVisible();
 
    // Signin
    await page.goto('/signin.html');
    await page.getByRole('textbox', { name: 'Email' }).fill(validUser.email);
    await page.getByRole('textbox', { name: 'Senha' }).fill(validUser.password);
    await page.getByRole('button', { name: 'Entrar' }).click();
    await expect(
      page.getByRole('heading', { name: 'Investimentos' })
    ).toBeVisible();
 
    // Home - Add Investment
    await page.goto('/home.html');
    await page.getByRole('button', { name: '+' }).click();
 
    await page.getByRole('textbox', { name: 'Nome' }).fill('Tesouro Selic');
    await page.getByRole('spinbutton', { name: 'Valor' }).fill('155');
    await page.getByRole('textbox', { name: 'Taxa' }).fill('100% Selic');
    await page.getByRole('textbox', { name: 'Corretora' }).fill('Inter');
    await page.getByRole('textbox', { name: 'Data' }).fill('2025-02-10');
    await page.getByRole('button', { name: 'Submit' }).click();
 
    await expect(page.getByText('Tesouro Selic')).toBeVisible();
 
    // Edit Investment
    await page.locator('svg').nth(1).click();
    await page
      .getByRole('textbox', { name: 'Nome' })
      .fill('Tesouro Selic 2029');
    await page.getByRole('button', { name: 'Submit' }).click();
 
    await expect(page.getByText('Tesouro Selic 2029')).toBeVisible();
 
    // Delete Investment
    await page.locator('svg').first().click();
    await page.getByRole('button', { name: 'Confirmar' }).click();
 
    await expect(page.getByText('Tesouro Selic 2029')).not.toBeVisible();
  });
});
 
$ npx playwright test --ui
$ npm run e2e
$ npx playwright test --ui
$ npm run e2e

Editar esta página