ci(app): testing and other app config changes
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -54,6 +54,8 @@
|
||||
"alplaprod",
|
||||
"Datamart",
|
||||
"intiallally",
|
||||
"OCME",
|
||||
"onnotice",
|
||||
"ppoo",
|
||||
"prodlabels"
|
||||
],
|
||||
|
||||
47
README.md
47
README.md
@@ -1,3 +1,46 @@
|
||||
# lst_v3
|
||||
# Logistics support tool
|
||||
|
||||
The tool that supports us in our everyday alplaprod adventures
|
||||
> The support tool for ALPLA Prod
|
||||
|
||||
## Overview
|
||||
|
||||
Quick summary of current rewrite/migration goal.
|
||||
|
||||
- **Phase:** Backend rewrite
|
||||
- **Last updated:** 2024-05-01
|
||||
|
||||
---
|
||||
|
||||
## Feature Status
|
||||
|
||||
| Feature | Description | Status |
|
||||
|----------|--------------|--------|
|
||||
| User Authentication | Login, Signup, JWT refresh, API Key | 🟨 In Progress |
|
||||
| User Profile | Edit profile, upload avatar | ⏳ Not Started |
|
||||
| Notifications | Subscribe, Create, Update | ⏳ Not Started |
|
||||
| Datamart | Create, Update, Run | 🔧 In Progress |
|
||||
| Frontend | Analytics and charts | ⏳ Not Started |
|
||||
| One Click Print | Printing system | ⏳ Not Started |
|
||||
| Silo Adjustments | Adjustments | ⏳ Not Started |
|
||||
| Demand Management | Orders, Forecast | ⏳ Not Started |
|
||||
| Open Docks | Integrations | ⏳ Not Started |
|
||||
| Transport Insight | Integrations | ⏳ Not Started |
|
||||
| Quality | Request Tool | ⏳ Not Started |
|
||||
| OCME | Custom integration | ⏳ Not Started |
|
||||
| API Migration | Moving to new REST endpoints | 🔧 In Progress |
|
||||
| System | Tests, Updates, Remote Logging | ⏳ Not Started |
|
||||
|
||||
_Status legend:_
|
||||
✅ Complete 🟨 In Progress ⏳ Not Started
|
||||
|
||||
---
|
||||
|
||||
## Setup / Installation
|
||||
|
||||
How to run the current version of the app.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/youruser/yourrepo.git
|
||||
cd yourrepo
|
||||
npm install
|
||||
npm run dev
|
||||
@@ -1,28 +0,0 @@
|
||||
type Success<T> = { data: T; error: null };
|
||||
type Failure<E> = { data: null; error: E };
|
||||
|
||||
export type Result<T, E = Error> = Success<T> | Failure<E>;
|
||||
|
||||
/**
|
||||
* A universal tryCatch wrapper that:
|
||||
* - Never throws
|
||||
* - Always resolves to Result<T,E>
|
||||
* - Allows optional error mapping function for strong typing
|
||||
*/
|
||||
|
||||
export async function tryCatch<T, E = Error>(
|
||||
promise: Promise<T>,
|
||||
onError?: (error: unknown) => E,
|
||||
): Promise<Result<T, E>> {
|
||||
try {
|
||||
const data = await promise;
|
||||
return { data, error: null };
|
||||
} catch (err: unknown) {
|
||||
const error = onError
|
||||
? onError(err)
|
||||
: err instanceof Error
|
||||
? (err as E)
|
||||
: (new Error(String(err)) as E);
|
||||
return { data: null, error };
|
||||
}
|
||||
}
|
||||
7140
package-lock.json
generated
7140
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@@ -4,9 +4,9 @@
|
||||
"description": "The tool that supports us in our everyday alplaprod",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"test": "dotenvx run -f .env -- vitest",
|
||||
"dev": "dotenvx run -f .env -- npm run dev:app",
|
||||
"dev:app": "cd backend && tsx watch app.ts",
|
||||
"dev:app": "cd backend && tsx watch server.ts",
|
||||
"dev:db:migrate": "npx drizzle-kit push",
|
||||
"dev:db:generate": "tsc && npx drizzle-kit generate --config=drizzle.config.ts",
|
||||
"build": "npm run specCheck && npm run lint && npm run dev:db:generate && npm run dev:db:migrate && npm run build:app && rimraf dist/backend",
|
||||
@@ -33,17 +33,24 @@
|
||||
"@commitlint/cli": "^18.4.0",
|
||||
"@commitlint/config-conventional": "^18.4.0",
|
||||
"@scalar/express-api-reference": "^0.8.28",
|
||||
"@swc/core": "^1.15.7",
|
||||
"@swc/jest": "^0.2.39",
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/morgan": "^1.9.10",
|
||||
"@types/mssql": "^9.1.8",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/nodemailer": "^7.0.4",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.6",
|
||||
"@types/pg": "^8.16.0",
|
||||
"@types/supertest": "^6.0.3",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"@vercel/ncc": "^0.38.4",
|
||||
"axios": "^1.13.2",
|
||||
"better-auth": "^1.4.6",
|
||||
"better-auth": "^1.4.9",
|
||||
"commitizen": "^4.3.0",
|
||||
"cors": "^2.8.5",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"drizzle-kit": "^0.31.8",
|
||||
"drizzle-orm": "^0.45.1",
|
||||
@@ -52,18 +59,24 @@
|
||||
"husky": "^8.0.3",
|
||||
"morgan": "^1.10.1",
|
||||
"mssql": "^12.2.0",
|
||||
"nodemailer": "^7.0.12",
|
||||
"nodemailer-express-handlebars": "^7.0.0",
|
||||
"npm-check-updates": "^19.1.2",
|
||||
"openapi-types": "^12.1.3",
|
||||
"pg": "^8.16.3",
|
||||
"pino": "^10.1.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
"postgres": "^3.4.7",
|
||||
"supertest": "^7.1.4",
|
||||
"ts-jest": "^29.4.6",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3"
|
||||
"typescript": "^5.9.3",
|
||||
"vite-tsconfig-paths": "^6.0.3",
|
||||
"vitest": "^4.0.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.51.2",
|
||||
"postgres": "^3.4.7"
|
||||
"@dotenvx/dotenvx": "^1.51.2"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
||||
29
tests/examplequery.test.ts
Normal file
29
tests/examplequery.test.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
|
||||
import { connectProdSql } from "../backend/src/prodSql/prodSqlConnection.controller.js";
|
||||
|
||||
let pool: any;
|
||||
|
||||
describe("Prod SQL connection", () => {
|
||||
// This may take seconds, so give plenty of time
|
||||
vi.setTimeout(30000);
|
||||
|
||||
beforeAll(async () => {
|
||||
pool = await connectProdSql();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (pool && pool.close) await pool.close();
|
||||
});
|
||||
|
||||
it("should connect and return expected data", async () => {
|
||||
// Example query — use something safe and consistent
|
||||
const result = await pool
|
||||
.request()
|
||||
.query("SELECT TOP 1 id, name FROM Users ORDER BY id ASC");
|
||||
|
||||
expect(result.recordset).toBeDefined();
|
||||
expect(Array.isArray(result.recordset)).toBe(true);
|
||||
expect(result.recordset.length).toBeGreaterThan(0);
|
||||
expect(result.recordset[0]).toHaveProperty("id");
|
||||
});
|
||||
});
|
||||
42
tests/sendEmail.test.ts
Normal file
42
tests/sendEmail.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import { sendEmail } from "../backend/src/utils/sendEmail.utils";
|
||||
|
||||
// Mock the logger before imports
|
||||
vi.mock("../backend/src/logger/logger.controller", () => ({
|
||||
createLogger: () => ({
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
fatal: vi.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
describe("Mail sending", () => {
|
||||
test("should send an email successfully", async () => {
|
||||
const result = await sendEmail({
|
||||
email: "blake.matthes@alpla.com",
|
||||
subject: "LST - Testing system",
|
||||
template: "testEmail",
|
||||
context: { name: "blake" },
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
success: true,
|
||||
});
|
||||
|
||||
expect(result?.message).toContain("blake.matthes@alpla.com");
|
||||
});
|
||||
|
||||
test("should handle email send failure gracefully", async () => {
|
||||
const badResult = await sendEmail({
|
||||
email: "invalid-address",
|
||||
subject: "LST - Testing system",
|
||||
template: "",
|
||||
context: {},
|
||||
});
|
||||
|
||||
expect(badResult).toMatchObject({
|
||||
success: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,7 +5,7 @@
|
||||
"moduleResolution": "nodenext",
|
||||
"strict": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"types": ["node", "better-auth"],
|
||||
"types": ["node", "better-auth", "jest"],
|
||||
"jsx": "react-jsx",
|
||||
"outDir": "./dist",
|
||||
"removeComments": true,
|
||||
|
||||
11
tsconfig.test.json
Normal file
11
tsconfig.test.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ESNext",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["tests/**/*", "backend/**/*"]
|
||||
}
|
||||
8
vitest.config.ts
Normal file
8
vitest.config.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
include: ["tests/**/*.test.ts"], // ← point to your tests folder
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user