| 1 | import test from "ava";
|
| 2 | import request from "supertest";
|
| 3 | import { createApp } from "../../src/create-app.js";
|
| 4 | import { setupTestDb, cleanupTestDb } from "../test-helper.js";
|
| 5 |
|
| 6 | let app;
|
| 7 | let db;
|
| 8 |
|
| 9 | test.before(() => {
|
| 10 | db = setupTestDb();
|
| 11 | app = createApp(db);
|
| 12 | });
|
| 13 |
|
| 14 | test.beforeEach(() => {
|
| 15 | cleanupTestDb();
|
| 16 | });
|
| 17 |
|
| 18 | test("Criar usuário com todos os campos válidos", async (t) => {
|
| 19 | const res = await request(app)
|
| 20 | .post("/users")
|
| 21 | .send({
|
| 22 | email: "usuario@example.com",
|
| 23 | password: "senha123",
|
| 24 | first_name: "João",
|
| 25 | last_name: "Silva",
|
| 26 | timezone: "America/Sao_Paulo"
|
| 27 | });
|
| 28 |
|
| 29 | t.is(res.status, 201);
|
| 30 | t.truthy(res.body.id);
|
| 31 | });
|
| 32 |
|
| 33 | test("Criar usuário com timezone padrão (UTC)", async (t) => {
|
| 34 | const res = await request(app)
|
| 35 | .post("/users")
|
| 36 | .send({
|
| 37 | email: "utc@example.com",
|
| 38 | password: "senha123",
|
| 39 | first_name: "Maria",
|
| 40 | last_name: "Santos"
|
| 41 | });
|
| 42 |
|
| 43 | t.is(res.status, 201);
|
| 44 |
|
| 45 | // Verify timezone was set to UTC
|
| 46 | const user = db.prepare("SELECT timezone FROM users WHERE id = ?").get(res.body.id);
|
| 47 | t.is(user.timezone, 'UTC');
|
| 48 | });
|
| 49 |
|
| 50 | test("Falha ao criar usuário sem email", async (t) => {
|
| 51 | const res = await request(app)
|
| 52 | .post("/users")
|
| 53 | .send({
|
| 54 | password: "senha123",
|
| 55 | first_name: "João",
|
| 56 | last_name: "Silva"
|
| 57 | });
|
| 58 |
|
| 59 | t.is(res.status, 400);
|
| 60 | t.is(res.body.error, "Campos faltantes");
|
| 61 | t.true(res.body.missing.includes('email'));
|
| 62 | });
|
| 63 |
|
| 64 | test("Falha ao criar usuário sem senha", async (t) => {
|
| 65 | const res = await request(app)
|
| 66 | .post("/users")
|
| 67 | .send({
|
| 68 | email: "usuario@example.com",
|
| 69 | first_name: "João",
|
| 70 | last_name: "Silva"
|
| 71 | });
|
| 72 |
|
| 73 | t.is(res.status, 400);
|
| 74 | t.is(res.body.error, "Campos faltantes");
|
| 75 | t.true(res.body.missing.includes('password'));
|
| 76 | });
|
| 77 |
|
| 78 | test("Falha ao criar usuário sem primeiro nome", async (t) => {
|
| 79 | const res = await request(app)
|
| 80 | .post("/users")
|
| 81 | .send({
|
| 82 | email: "usuario@example.com",
|
| 83 | password: "senha123",
|
| 84 | last_name: "Silva"
|
| 85 | });
|
| 86 |
|
| 87 | t.is(res.status, 400);
|
| 88 | t.is(res.body.error, "Campos faltantes");
|
| 89 | t.true(res.body.missing.includes('first_name'));
|
| 90 | });
|
| 91 |
|
| 92 | test("Falha ao criar usuário sem último nome", async (t) => {
|
| 93 | const res = await request(app)
|
| 94 | .post("/users")
|
| 95 | .send({
|
| 96 | email: "usuario@example.com",
|
| 97 | password: "senha123",
|
| 98 | first_name: "João"
|
| 99 | });
|
| 100 |
|
| 101 | t.is(res.status, 400);
|
| 102 | t.is(res.body.error, "Campos faltantes");
|
| 103 | t.true(res.body.missing.includes('last_name'));
|
| 104 | });
|
| 105 |
|
| 106 | test("Falha ao criar usuário com múltiplos campos faltantes", async (t) => {
|
| 107 | const res = await request(app)
|
| 108 | .post("/users")
|
| 109 | .send({
|
| 110 | first_name: "João"
|
| 111 | });
|
| 112 |
|
| 113 | t.is(res.status, 400);
|
| 114 | t.is(res.body.error, "Campos faltantes");
|
| 115 | t.true(res.body.missing.includes('email'));
|
| 116 | t.true(res.body.missing.includes('password'));
|
| 117 | t.true(res.body.missing.includes('last_name'));
|
| 118 | });
|
| 119 |
|
| 120 | test("Falha ao criar usuário com email inválido (sem @)", async (t) => {
|
| 121 | const res = await request(app)
|
| 122 | .post("/users")
|
| 123 | .send({
|
| 124 | email: "emailinvalido",
|
| 125 | password: "senha123",
|
| 126 | first_name: "João",
|
| 127 | last_name: "Silva"
|
| 128 | });
|
| 129 |
|
| 130 | t.is(res.status, 400);
|
| 131 | t.is(res.body.error, "Email inválido");
|
| 132 | });
|
| 133 |
|
| 134 | test("Falha ao criar usuário com email inválido (sem domínio)", async (t) => {
|
| 135 | const res = await request(app)
|
| 136 | .post("/users")
|
| 137 | .send({
|
| 138 | email: "usuario@",
|
| 139 | password: "senha123",
|
| 140 | first_name: "João",
|
| 141 | last_name: "Silva"
|
| 142 | });
|
| 143 |
|
| 144 | t.is(res.status, 400);
|
| 145 | t.is(res.body.error, "Email inválido");
|
| 146 | });
|
| 147 |
|
| 148 | test("Falha ao criar usuário com email inválido (formato incorreto)", async (t) => {
|
| 149 | const res = await request(app)
|
| 150 | .post("/users")
|
| 151 | .send({
|
| 152 | email: "@example.com",
|
| 153 | password: "senha123",
|
| 154 | first_name: "João",
|
| 155 | last_name: "Silva"
|
| 156 | });
|
| 157 |
|
| 158 | t.is(res.status, 400);
|
| 159 | t.is(res.body.error, "Email inválido");
|
| 160 | });
|
| 161 |
|
| 162 | test("Falha ao criar usuário com senha muito curta (menos de 6 caracteres)", async (t) => {
|
| 163 | const res = await request(app)
|
| 164 | .post("/users")
|
| 165 | .send({
|
| 166 | email: "usuario@example.com",
|
| 167 | password: "123",
|
| 168 | first_name: "João",
|
| 169 | last_name: "Silva"
|
| 170 | });
|
| 171 |
|
| 172 | t.is(res.status, 400);
|
| 173 | t.is(res.body.error, "Senha deve ter pelo menos 6 caracteres");
|
| 174 | });
|
| 175 |
|
| 176 | test("Falha ao criar usuário com senha vazia", async (t) => {
|
| 177 | const res = await request(app)
|
| 178 | .post("/users")
|
| 179 | .send({
|
| 180 | email: "usuario@example.com",
|
| 181 | password: "",
|
| 182 | first_name: "João",
|
| 183 | last_name: "Silva"
|
| 184 | });
|
| 185 |
|
| 186 | t.is(res.status, 400);
|
| 187 | t.is(res.body.error, "Campos faltantes");
|
| 188 | });
|
| 189 |
|
| 190 | test("Falha ao criar usuário com email duplicado", async (t) => {
|
| 191 | // Create first user
|
| 192 | await request(app)
|
| 193 | .post("/users")
|
| 194 | .send({
|
| 195 | email: "duplicado@example.com",
|
| 196 | password: "senha123",
|
| 197 | first_name: "João",
|
| 198 | last_name: "Silva"
|
| 199 | });
|
| 200 |
|
| 201 | // Try to create with same email
|
| 202 | const res = await request(app)
|
| 203 | .post("/users")
|
| 204 | .send({
|
| 205 | email: "duplicado@example.com",
|
| 206 | password: "outrasenha",
|
| 207 | first_name: "Maria",
|
| 208 | last_name: "Santos"
|
| 209 | });
|
| 210 |
|
| 211 | t.is(res.status, 400);
|
| 212 | t.is(res.body.error, "Email já cadastrado");
|
| 213 | });
|
| 214 |
|
| 215 | test("Email deve ser case-insensitive para duplicação", async (t) => {
|
| 216 | // Create with lowercase
|
| 217 | await request(app)
|
| 218 | .post("/users")
|
| 219 | .send({
|
| 220 | email: "usuario@example.com",
|
| 221 | password: "senha123",
|
| 222 | first_name: "João",
|
| 223 | last_name: "Silva"
|
| 224 | });
|
| 225 |
|
| 226 | // Try with uppercase
|
| 227 | const res = await request(app)
|
| 228 | .post("/users")
|
| 229 | .send({
|
| 230 | email: "USUARIO@EXAMPLE.COM",
|
| 231 | password: "senha123",
|
| 232 | first_name: "Maria",
|
| 233 | last_name: "Santos"
|
| 234 | });
|
| 235 |
|
| 236 | t.is(res.status, 400);
|
| 237 | t.is(res.body.error, "Email já cadastrado");
|
| 238 | });
|
| 239 |
|
| 240 | test("Sanitização de strings longas no nome", async (t) => {
|
| 241 | const longName = "A".repeat(600); // 600 characters
|
| 242 |
|
| 243 | const res = await request(app)
|
| 244 | .post("/users")
|
| 245 | .send({
|
| 246 | email: "longname@example.com",
|
| 247 | password: "senha123",
|
| 248 | first_name: longName,
|
| 249 | last_name: longName
|
| 250 | });
|
| 251 |
|
| 252 | t.is(res.status, 201);
|
| 253 |
|
| 254 | // Check that name was truncated to 500 chars
|
| 255 | const user = db.prepare("SELECT first_name, last_name FROM users WHERE id = ?").get(res.body.id);
|
| 256 | t.is(user.first_name.length, 500);
|
| 257 | t.is(user.last_name.length, 500);
|
| 258 | });
|