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
10 changes: 9 additions & 1 deletion .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@ POSTGRES_PORT=5432
POSTGRES_USER=local_user
POSTGRES_DB=local_db
POSTGRES_PASSWORD=local_password
DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB
DATABASE_URL=postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/$POSTGRES_DB

EMAIL_SMTP_HOST=localhost
EMAIL_SMTP_PORT=1025
EMAIL_SMTP_USER=
EMAIL_SMTP_PASSWORD=

EMAIL_HTTP_HOST=localhost
EMAIL_HTTP_PORT=1080
6 changes: 6 additions & 0 deletions infra/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ services:
- ../.env.development
ports:
- "5432:5432"
mailcatcher:
container_name: "mailcatcher-dev"
image: "sj26/mailcatcher"
ports:
- "1025:1025"
- "1080:1080"
21 changes: 21 additions & 0 deletions infra/email.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import nodemailer from "nodemailer";

const transporter = nodemailer.createTransport({
host: process.env.EMAIL_SMTP_HOST,
port: process.env.EMAIL_SMTP_PORT,
auth: {
user: process.env.EMAIL_SMTP_USER,
pass: process.env.EMAIL_SMTP_PASSWORD,
},
secure: process.env.NODE_ENV === "production" ? true : false,
});

async function send(mailOptions) {
await transporter.sendMail(mailOptions);
}

const email = {
send,
};

export default email;
10 changes: 10 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"next": "16.2.6",
"next-connect": "1.0.0",
"node-pg-migrate": "^7.9.1",
"nodemailer": "7.0.5",
"pg": "8.20.0",
"react": "19.2.6",
"react-dom": "19.2.6",
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/migrations/get.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import orchestrator from "../orchestrator";
import orchestrator from "../../../../orchestrator";

beforeAll(async () => {
await orchestrator.waitForAllServices();
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/migrations/post.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import orchestrator from "../orchestrator";
import orchestrator from "../../../../orchestrator";

beforeAll(async () => {
await orchestrator.waitForAllServices();
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/sessions/delete.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { version as uuidVersion } from "uuid";
import setCookieParser from "set-cookie-parser";
import orchestrator from "../orchestrator";
import orchestrator from "../../../../orchestrator";
import session from "models/session";

beforeAll(async () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/sessions/post.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { version as uuidVersion } from "uuid";
import setCookieParser from "set-cookie-parser";
import orchestrator from "../orchestrator";
import orchestrator from "../../../../orchestrator";
import session from "models/session";

beforeAll(async () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/status/get.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import orchestrator from "../orchestrator.js";
import orchestrator from "../../../../orchestrator.js";

beforeAll(async () => {
await orchestrator.waitForAllServices();
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/status/post.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import orchestrator from "../orchestrator.js";
import orchestrator from "../../../../orchestrator.js";

beforeAll(async () => {
await orchestrator.waitForAllServices();
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/user/get.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { version as uuidVersion } from "uuid";
import setCookieParser from "set-cookie-parser";
import orchestrator from "../orchestrator";
import orchestrator from "../../../../orchestrator";
import session from "models/session";

beforeAll(async () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/users/[username]/get.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { version as uuidVersion } from "uuid";
import orchestrator from "../../orchestrator";
import orchestrator from "../../../../../orchestrator";

beforeAll(async () => {
await orchestrator.waitForAllServices();
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/users/[username]/patch.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { version as uuidVersion } from "uuid";
import orchestrator from "../../orchestrator";
import orchestrator from "../../../../../orchestrator";
import user from "models/user";
import password from "models/password";

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/api/v1/users/post.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { version as uuidVersion } from "uuid";
import orchestrator from "../orchestrator";
import orchestrator from "../../../../orchestrator";
import user from "models/user";
import password from "models/password";

Expand Down
31 changes: 31 additions & 0 deletions tests/integration/infra/email.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import email from "infra/email.js";
import orchestrator from "tests/orchestrator";

beforeAll(async () => {
await orchestrator.waitForAllServices();
});

describe("infra/email.js", () => {
test("Send()", async () => {
await orchestrator.deleteAllEmails();

await email.send({
from: "Xedit <contato@xedit.com.br>",
to: "contato@gmail.com",
subject: "Teste de assunto",
text: "Teste de corpo.",
});
await email.send({
from: "Xedit <contato@xedit.com.br>",
to: "contato@gmail.com",
subject: "Último email enviado.",
text: "Corpo do ultimo email.",
});

const lastEmail = await orchestrator.getLastEmail();
expect(lastEmail.sender).toBe("<contato@xedit.com.br>");
expect(lastEmail.recipients[0]).toBe("<contato@gmail.com>");
expect(lastEmail.subject).toBe("Último email enviado.");
expect(lastEmail.text).toBe("Corpo do ultimo email.\n");
});
});
47 changes: 47 additions & 0 deletions tests/integration/api/v1/orchestrator.js → tests/orchestrator.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import retry from "async-retry";
import { faker } from "@faker-js/faker";
import dotenv from "dotenv";

import database from "infra/database";
import migrator from "models/migrator";
import user from "models/user";
import session from "models/session";

dotenv.config({
path: ".env.development", // ou .env.test, se você usar isso
});

const emailHttpUrl = `http://${process.env.EMAIL_HTTP_HOST}:${process.env.EMAIL_HTTP_PORT}`;

async function waitForAllServices() {
await waitForWebServer();
await waitForEmailServer();

async function waitForWebServer() {
return retry(fetchStatusPage, {
Expand All @@ -24,6 +32,23 @@ async function waitForAllServices() {
await response.json();
}
}

async function waitForEmailServer() {
return retry(fetchEmailPage, {
retries: 100,
maxTimeout: 1000,
});

async function fetchEmailPage() {
const response = await fetch(`${emailHttpUrl}/messages`);

if (response.status !== 200) {
throw Error();
}

await response.json();
}
}
}

async function clearDatabase() {
Expand All @@ -47,12 +72,34 @@ async function createUser(userObject) {
});
}

async function deleteAllEmails() {
await fetch(`${emailHttpUrl}/messages`, {
method: "DELETE",
});
}

async function getLastEmail() {
const emailListResponse = await fetch(`${emailHttpUrl}/messages`);
const emailListBody = await emailListResponse.json();
const lastEmailItem = emailListBody.pop();

const emailTextResponse = await fetch(
`${emailHttpUrl}/messages/${lastEmailItem.id}.plain`,
);
const emailTextBody = await emailTextResponse.text();

lastEmailItem.text = emailTextBody;
return lastEmailItem;
}

const orchestrator = {
waitForAllServices,
clearDatabase,
runPendingMigrations,
createUser,
createSession,
deleteAllEmails,
getLastEmail,
};

export default orchestrator;
Loading