🎉 init: 小龙的工作空间

This commit is contained in:
大海
2026-06-06 10:40:48 +08:00
commit a188ee1426
3201 changed files with 231817 additions and 0 deletions
@@ -0,0 +1,124 @@
// ApprovalStep CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
});
after(async () => {
await app.close();
});
describe("GET /api/approval_steps", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/approval_steps",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/approval_steps", () => {
it("creates a approval_step", async () => {
const res = await app.inject({
method: "POST",
url: "/api/approval_steps",
headers: { authorization: `Bearer ${token}` },
payload: {
"approvalId": "00000000-0000-0000-0000-000000000001",
"approverId": "00000000-0000-0000-0000-000000000001",
"stepOrder": 1,
"status": "sample-status",
"comment": "sample-comment",
"actedAt": "sample-actedat"
},
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/approval_steps/:id", () => {
it("returns the created approval_step", async () => {
const res = await app.inject({
method: "GET",
url: `/api/approval_steps/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/approval_steps/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/approval_steps/:id", () => {
it("updates the approval_step", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/approval_steps/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload: {
"approvalId": "00000000-0000-0000-0000-000000000001",
"approverId": "00000000-0000-0000-0000-000000000001",
"stepOrder": 1,
"status": "sample-status",
"comment": "sample-comment",
"actedAt": "sample-actedat"
},
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/approval_steps/:id", () => {
it("deletes the approval_step", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/approval_steps/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/approval_steps/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,121 @@
// Approval CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
let payload: Record<string, unknown>;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
// Resolve user FK references with the registered user's real ID
payload = {
"userId": regRes.json().user.id,
"entityType": "sample-entitytype",
"entityId": "sample-entityid",
"applicantId": regRes.json().user.id,
"status": "sample-status",
"formData": "sample-formdata"
};
});
after(async () => {
await app.close();
});
describe("GET /api/approvals", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/approvals",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/approvals", () => {
it("creates a approval", async () => {
const res = await app.inject({
method: "POST",
url: "/api/approvals",
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/approvals/:id", () => {
it("returns the created approval", async () => {
const res = await app.inject({
method: "GET",
url: `/api/approvals/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/approvals/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/approvals/:id", () => {
it("updates the approval", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/approvals/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/approvals/:id", () => {
it("deletes the approval", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/approvals/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/approvals/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,124 @@
// Attendance CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
});
after(async () => {
await app.close();
});
describe("GET /api/attendance", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/attendance",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/attendance", () => {
it("creates a attendance", async () => {
const res = await app.inject({
method: "POST",
url: "/api/attendance",
headers: { authorization: `Bearer ${token}` },
payload: {
"userId": "00000000-0000-0000-0000-000000000001",
"checkInAt": "sample-checkinat",
"checkOutAt": "sample-checkoutat",
"location": "sample-location",
"type": "sample-type",
"UNIQUE(userId, DATE(checkInAt))": "sample-unique(userid, date(checkinat))"
},
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/attendance/:id", () => {
it("returns the created attendance", async () => {
const res = await app.inject({
method: "GET",
url: `/api/attendance/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/attendance/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/attendance/:id", () => {
it("updates the attendance", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/attendance/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload: {
"userId": "00000000-0000-0000-0000-000000000001",
"checkInAt": "sample-checkinat",
"checkOutAt": "sample-checkoutat",
"location": "sample-location",
"type": "sample-type",
"UNIQUE(userId, DATE(checkInAt))": "sample-unique(userid, date(checkinat))"
},
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/attendance/:id", () => {
it("deletes the attendance", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/attendance/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/attendance/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,96 @@
// Auth routes test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
});
after(async () => {
await app.close();
});
describe("POST /api/auth/register", () => {
it("registers a new user", async () => {
const res = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: "testuser", password: "password123" },
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.token);
assert.equal(body.user.username, "testuser");
token = body.token;
});
it("rejects duplicate username", async () => {
const res = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: "testuser", password: "password123" },
});
assert.equal(res.statusCode, 409);
});
it("rejects short password", async () => {
const res = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: "user2", password: "123" },
});
assert.equal(res.statusCode, 400);
});
});
describe("POST /api/auth/login", () => {
it("logs in with correct credentials", async () => {
const res = await app.inject({
method: "POST",
url: "/api/auth/login",
payload: { username: "testuser", password: "password123" },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(body.token);
token = body.token;
});
it("rejects wrong password", async () => {
const res = await app.inject({
method: "POST",
url: "/api/auth/login",
payload: { username: "testuser", password: "wrongpassword" },
});
assert.equal(res.statusCode, 401);
});
});
describe("GET /api/auth/me", () => {
it("returns current user with valid token", async () => {
const res = await app.inject({
method: "GET",
url: "/api/auth/me",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.username, "testuser");
});
it("rejects without token", async () => {
const res = await app.inject({
method: "GET",
url: "/api/auth/me",
});
assert.equal(res.statusCode, 401);
});
});
@@ -0,0 +1,124 @@
// Contract CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
let payload: Record<string, unknown>;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
// Resolve user FK references with the registered user's real ID
payload = {
"userId": regRes.json().user.id,
"title": "sample-title",
"partyA": "sample-partya",
"partyB": "sample-partyb",
"amount": 1,
"signedAt": "sample-signedat",
"expiresAt": "sample-expiresat",
"status": "sample-status",
"fileUrl": "sample-fileurl"
};
});
after(async () => {
await app.close();
});
describe("GET /api/contracts", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/contracts",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/contracts", () => {
it("creates a contract", async () => {
const res = await app.inject({
method: "POST",
url: "/api/contracts",
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/contracts/:id", () => {
it("returns the created contract", async () => {
const res = await app.inject({
method: "GET",
url: `/api/contracts/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/contracts/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/contracts/:id", () => {
it("updates the contract", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/contracts/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/contracts/:id", () => {
it("deletes the contract", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/contracts/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/contracts/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,122 @@
// Customer CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
let payload: Record<string, unknown>;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
// Resolve user FK references with the registered user's real ID
payload = {
"userId": regRes.json().user.id,
"name": "sample-name",
"email": "sample-email",
"phone": "sample-phone",
"company": "sample-company",
"source": "sample-source",
"tags": "sample-tags"
};
});
after(async () => {
await app.close();
});
describe("GET /api/customers", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/customers",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/customers", () => {
it("creates a customer", async () => {
const res = await app.inject({
method: "POST",
url: "/api/customers",
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/customers/:id", () => {
it("returns the created customer", async () => {
const res = await app.inject({
method: "GET",
url: `/api/customers/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/customers/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/customers/:id", () => {
it("updates the customer", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/customers/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/customers/:id", () => {
it("deletes the customer", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/customers/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/customers/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,118 @@
// Department CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
});
after(async () => {
await app.close();
});
describe("GET /api/departments", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/departments",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/departments", () => {
it("creates a department", async () => {
const res = await app.inject({
method: "POST",
url: "/api/departments",
headers: { authorization: `Bearer ${token}` },
payload: {
"name": "sample-name",
"parentId": "00000000-0000-0000-0000-000000000001",
"managerId": "00000000-0000-0000-0000-000000000001"
},
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/departments/:id", () => {
it("returns the created department", async () => {
const res = await app.inject({
method: "GET",
url: `/api/departments/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/departments/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/departments/:id", () => {
it("updates the department", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/departments/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload: {
"name": "sample-name",
"parentId": "00000000-0000-0000-0000-000000000001",
"managerId": "00000000-0000-0000-0000-000000000001"
},
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/departments/:id", () => {
it("deletes the department", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/departments/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/departments/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,119 @@
// Items CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
let payload: Record<string, unknown>;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
// Resolve user FK references with the registered user's real ID
payload = {
"userId": regRes.json().user.id,
"title": "sample-title",
"description": "sample-description",
"data": "sample-data"
};
});
after(async () => {
await app.close();
});
describe("GET /api/items", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/items",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/items", () => {
it("creates a item", async () => {
const res = await app.inject({
method: "POST",
url: "/api/items",
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/items/:id", () => {
it("returns the created item", async () => {
const res = await app.inject({
method: "GET",
url: `/api/items/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/items/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/items/:id", () => {
it("updates the item", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/items/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/items/:id", () => {
it("deletes the item", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/items/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/items/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,121 @@
// Reminder CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
let payload: Record<string, unknown>;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
// Resolve user FK references with the registered user's real ID
payload = {
"userId": regRes.json().user.id,
"entityType": "sample-entitytype",
"entityId": "sample-entityid",
"remindAt": "sample-remindat",
"message": "sample-message",
"sent": true
};
});
after(async () => {
await app.close();
});
describe("GET /api/reminders", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/reminders",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/reminders", () => {
it("creates a reminder", async () => {
const res = await app.inject({
method: "POST",
url: "/api/reminders",
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/reminders/:id", () => {
it("returns the created reminder", async () => {
const res = await app.inject({
method: "GET",
url: `/api/reminders/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/reminders/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/reminders/:id", () => {
it("updates the reminder", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/reminders/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/reminders/:id", () => {
it("deletes the reminder", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/reminders/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/reminders/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,120 @@
// Tickets CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
let payload: Record<string, unknown>;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
// Resolve user FK references with the registered user's real ID
payload = {
"userId": regRes.json().user.id,
"title": "sample-title",
"description": "sample-description",
"assigneeId": "sample-assigneeid",
"category": "sample-category"
};
});
after(async () => {
await app.close();
});
describe("GET /api/tickets", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/tickets",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/tickets", () => {
it("creates a ticket", async () => {
const res = await app.inject({
method: "POST",
url: "/api/tickets",
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/tickets/:id", () => {
it("returns the created ticket", async () => {
const res = await app.inject({
method: "GET",
url: `/api/tickets/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/tickets/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/tickets/:id", () => {
it("updates the ticket", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/tickets/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload,
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/tickets/:id", () => {
it("deletes the ticket", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/tickets/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/tickets/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
@@ -0,0 +1,118 @@
// User CRUD test
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import { buildApp } from "../index.js";
import type { FastifyInstance } from "fastify";
let app: FastifyInstance;
let token: string;
let createdId: string;
before(async () => {
process.env.JWT_SECRET = "test-secret";
process.env.DATABASE_URL = ":memory:";
app = await buildApp();
await app.ready();
// Register and login to get a token
const regRes = await app.inject({
method: "POST",
url: "/api/auth/register",
payload: { username: `test_${Date.now()}`, password: "password123" },
});
token = regRes.json().token;
});
after(async () => {
await app.close();
});
describe("GET /api/users", () => {
it("returns empty list", async () => {
const res = await app.inject({
method: "GET",
url: "/api/users",
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.ok(Array.isArray(body.data));
});
});
describe("POST /api/users", () => {
it("creates a user", async () => {
const res = await app.inject({
method: "POST",
url: "/api/users",
headers: { authorization: `Bearer ${token}` },
payload: {
"phone": "sample-phone",
"nickname": "sample-nickname",
"avatarUrl": "sample-avatarurl"
},
});
assert.equal(res.statusCode, 201);
const body = res.json();
assert.ok(body.data.id);
createdId = body.data.id;
});
});
describe("GET /api/users/:id", () => {
it("returns the created user", async () => {
const res = await app.inject({
method: "GET",
url: `/api/users/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 200);
const body = res.json();
assert.equal(body.data.id, createdId);
});
it("returns 404 for nonexistent id", async () => {
const res = await app.inject({
method: "GET",
url: `/api/users/nonexistent`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});
describe("PUT /api/users/:id", () => {
it("updates the user", async () => {
const res = await app.inject({
method: "PUT",
url: `/api/users/${createdId}`,
headers: { authorization: `Bearer ${token}` },
payload: {
"phone": "sample-phone",
"nickname": "sample-nickname",
"avatarUrl": "sample-avatarurl"
},
});
assert.equal(res.statusCode, 200);
});
});
describe("DELETE /api/users/:id", () => {
it("deletes the user", async () => {
const res = await app.inject({
method: "DELETE",
url: `/api/users/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 204);
});
it("returns 404 after delete", async () => {
const res = await app.inject({
method: "GET",
url: `/api/users/${createdId}`,
headers: { authorization: `Bearer ${token}` },
});
assert.equal(res.statusCode, 404);
});
});