Skip to content

Commit

Permalink
feat: add integration tests for supplyHistory
Browse files Browse the repository at this point in the history
  • Loading branch information
Danilo Romano committed May 22, 2024
1 parent 15bec0d commit f9f6c87
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 4 deletions.
13 changes: 13 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
TZ=America/Sao_Paulo

DB_HOST=localhost
DB_PORT=5432
DB_DATABASE_NAME=sos_rs
DB_USER=postgres
DB_PASSWORD=postgres
DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE_NAME}_test?schema=public"

SECRET_KEY=batata

HOST=::0.0.0.0
PORT=4000
54 changes: 54 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest.e2e.config.ts",
"pretest:e2e": "dotenv -e .env.test -- npm run migrations:run",
"test:e2e": "dotenv -e .env.test -- jest --config ./test/jest.e2e.config.ts",
"migrations:run": "npx prisma migrate deploy",
"migrations:dev": "npx prisma migrate dev",
"docker:compose": "docker-compose -f docker-compose.dev.yml up"
Expand All @@ -41,6 +42,7 @@
"zod": "^3.23.6"
},
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
Expand All @@ -51,6 +53,7 @@
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"dotenv-cli": "^7.4.2",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-jest": "^28.5.0",
Expand Down
202 changes: 199 additions & 3 deletions test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { Test, TestingModule } from '@nestjs/testing';
import { fakerPT_BR as faker } from '@faker-js/faker';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { JwtService } from '@nestjs/jwt';
import { Test, TestingModule } from '@nestjs/testing';
import { AccessLevel, Shelter, ShelterSupply } from '@prisma/client';
import { AppModule } from 'src/app.module';

import { PrismaService } from 'src/prisma/prisma.service';
import { TokenPayload } from 'src/sessions/types';
import { UpdateShelterSupplySchema } from 'src/shelter-supply/types';
import { SupplyPriority } from 'src/supply/types';
import * as request from 'supertest';
import { util, z } from 'zod';
import { getTestSessionData, randomEnumValue } from './test-utils';
describe('AppController (e2e)', () => {
let app: INestApplication;

Expand All @@ -19,3 +27,191 @@ describe('AppController (e2e)', () => {
return request(app.getHttpServer()).get('/').expect(404);
});
});

describe('ShelterSupplyController (e2e)', () => {
let app: INestApplication;
let jwtToken: string;
let shelter: Shelter;
let prisma: PrismaService;
let shelterSupplies: ShelterSupply[];
let sessionData: TokenPayload;

const isTestDatabase =
new String(process.env.DB_DATABASE_NAME).toLowerCase().endsWith('test') ||
process.env.NODE_ENV === 'test';

beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();

app = moduleFixture.createNestApplication();
app = await app.init();
prisma = app.get(PrismaService);
if (!isTestDatabase) {
throw new Error('Test database not configured');
}

({ shelter, shelterSupplies } = await seedTestDatabase(prisma));
});

afterAll(async () => {
await clearTestDatabase(prisma);
});

it('/shelter/supplies/{shelterId}/{supplyId} (PUT)', async () => {
sessionData = await getTestSessionData(prisma, AccessLevel.User);
jwtToken = app.get(JwtService).sign(sessionData);

const supplyBefore = shelterSupplies[0];
const nextPriority = randomEnumValue(SupplyPriority);

const incrementedQuantity = (supplyBefore.quantity ?? 0) + 1;

await request(app.getHttpServer())
.put(`/shelter/supplies/${shelter.id}/${supplyBefore.supplyId}`)
.auth(jwtToken, { type: 'bearer' })
.send({
priority: nextPriority,
quantity: incrementedQuantity,
} as z.infer<typeof UpdateShelterSupplySchema>['data'])
.expect(200);

const log = await prisma.suppliesHistory.findFirst({
where: { userId: sessionData.userId },
orderBy: { updatedAt: 'desc' },
});

expect(log).toMatchObject({
previousPriority: supplyBefore.priority,
previousQuantity: supplyBefore.quantity,
// usando mesma lógica aplicada ao serviço
currentQuantity:
nextPriority !== SupplyPriority.UnderControl
? incrementedQuantity
: null,
currentPriority: nextPriority,
shelterName: shelter.name,
userId: sessionData.userId,
});
expect(log?.ipAddress).toBeTruthy();
expect(log?.supplyName).toBeTruthy();
});

it('/shelter/supplies/{shelterId}/supplies/many (PUT)', async () => {
sessionData = await getTestSessionData(
prisma,
AccessLevel.DistributionCenter,
);
jwtToken = app.get(JwtService).sign(sessionData);

const before = await prisma.suppliesHistory.count();
const supplyIds = shelterSupplies.map(({ supplyId }) => supplyId);

await request(app.getHttpServer())
.put(`/shelter/supplies/${shelter.id}/supplies/many`)
.auth(jwtToken, { type: 'bearer' })
.send({
ids: supplyIds,
})
.expect(200);

const after = await prisma.suppliesHistory.count();
const suppliesHistory = await prisma.suppliesHistory.findMany({
orderBy: { updatedAt: 'desc' },
take: supplyIds.length,
});

expect(after).toEqual(before + shelterSupplies.length);
suppliesHistory.forEach((sh) => {
expect(sh.userId).toEqual(sessionData.userId);
});
});
});
async function seedTestDatabase(prisma: PrismaService) {
const users = await prisma.$transaction(
util.getValidEnumValues(AccessLevel).map((accessLevel) =>
prisma.user.create({
data: {
name: faker.person.firstName(),
phone: faker.phone.number(),
password: faker.internet.password(),
login: faker.phone.number(),
lastName: faker.person.lastName(),
createdAt: new Date().toISOString(),
accessLevel,
},
}),
),
);

const supplyCategories = await prisma.$transaction(
[
...new Set(
Array.from({
length: 10,
}).map(() => faker.commerce.department()),
),
].map((name) =>
prisma.supplyCategory.create({
data: {
name,
createdAt: new Date().toISOString(),
},
}),
),
);

const supplies = await prisma.$transaction(
supplyCategories.map((sc) =>
prisma.supply.create({
data: {
supplyCategoryId: sc.id,
name: faker.commerce.productName(),
createdAt: new Date().toISOString(),
},
}),
),
);

const shelter = await prisma.shelter.create({
data: {
address: faker.location.streetAddress(),
name: faker.company.name(),
latitude: faker.location.latitude(),
longitude: faker.location.longitude(),
zipCode: faker.location.zipCode('#####-###'),
capacity: faker.number.int({ max: 1000 }),
street: faker.location.street(),
pix: faker.phone.number(),
createdAt: new Date().toISOString(),
},
});

const shelterSupplies = await prisma.$transaction(
supplies.map((s) =>
prisma.shelterSupply.create({
data: {
shelterId: shelter.id,
supplyId: s.id,
priority: randomEnumValue(SupplyPriority),
quantity: faker.number.int({ max: 100 }),
createdAt: new Date().toISOString(),
},
}),
),
);
return { shelter, supplyCategories, supplies, shelterSupplies, users };
}

async function clearTestDatabase(prisma: PrismaService) {
return prisma.$transaction([
prisma.shelterSupply.deleteMany(),
prisma.supply.deleteMany(),
prisma.suppliesHistory.deleteMany(),
prisma.supplyCategory.deleteMany(),
prisma.shelter.deleteMany(),
prisma.session.deleteMany(),
prisma.user.deleteMany(),
]);
}
Loading

0 comments on commit f9f6c87

Please sign in to comment.