Skip to content

Commit

Permalink
Add first integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
morajabi committed Dec 11, 2024
1 parent eac5aca commit 4ef61b0
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 12 deletions.
25 changes: 24 additions & 1 deletion .github/workflows/server-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,23 @@ jobs:
test:
name: Server Typecheck, Lint, and Tests
runs-on: ubuntu-latest
timeout-minutes: 3
timeout-minutes: 5

services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test_db
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4

Expand All @@ -30,6 +46,13 @@ jobs:
- name: Install dependencies
run: bun install

- name: Setup environment
run: |
echo "DATABASE_URL=postgres://postgres:postgres@localhost:5432/test_db" >> $GITHUB_ENV
- name: Run database migrations
run: bun db:migrate

- name: Run tests
run: bun test

Expand Down
3 changes: 2 additions & 1 deletion server/scripts/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ try {
})

console.info("🚧 Migrations applied successfully")
migrationClient.end({ timeout: 5_000 })
await migrationClient.end({ timeout: 5_000 })
process.exit(0)
} catch (error) {
console.error("🔥 Error applying migrations", error)
process.exit(1)
Expand Down
37 changes: 37 additions & 0 deletions server/src/__tests__/api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import "./setup"

import { describe, expect, it, beforeAll, afterAll } from "bun:test"
import { app } from "../index" // Adjust this import based on your app structure

describe("API Endpoints", () => {
const testServer = app // Your Elysia app instance

// Example test
it(
"should return 200 for health check",
async () => {
const response = await testServer.handle(new Request("http://localhost/"))
expect(response.status).toBe(200)
expect(await response.text()).toContain("running")
},
{ timeout: 10000 },
)

// Add more endpoint tests here
// Example:
// it("should create a new user", async () => {
// const response = await testServer.handle(
// new Request("http://localhost/api/users", {
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify({
// name: "Test User",
// email: "test@example.com",
// }),
// })
// );
// expect(response.status).toBe(201);
// });
})
30 changes: 30 additions & 0 deletions server/src/__tests__/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { mock } from "bun:test"

// Mock external services for testing
process.env.NODE_ENV = "test"

if (!process.env.RESEND_API_KEY) {
process.env.RESEND_API_KEY = "test-key"
}

if (!process.env.ENCRYPTION_KEY) {
process.env.ENCRYPTION_KEY = "test-key"
}
// If some services are not needed during testing, you can use dummy values
if (!process.env.AMAZON_ACCESS_KEY) {
process.env.AMAZON_ACCESS_KEY = "test-key"
}
if (!process.env.AMAZON_SECRET_ACCESS_KEY) {
process.env.AMAZON_SECRET_ACCESS_KEY = "test-secret"
}
// ... add other environment variables as needed

// You might want to mock external services
mock.module("../libs/resend", () => ({
sendEmail: mock().mockResolvedValue(true),
}))

// doesn't work
// mock.module("../libs/apn.ts", () => ({
// apnProvider: mock().mockReturnValue(undefined),
// }))
2 changes: 1 addition & 1 deletion server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if (process.env.NODE_ENV !== "development") {
console.info(`🚧 Starting server • ${process.env.NODE_ENV}${version}${gitCommitHash}`)
}

const app = new Elysia()
export const app = new Elysia()
.use(root)
.use(apiV1)
.use(webSocket)
Expand Down
28 changes: 20 additions & 8 deletions server/src/libs/apn.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import APN from "apn"

// Configure APN provider
export const apnProvider = new APN.Provider({
token: {
key: Buffer.from(process.env["APN_KEY"] ?? "", "base64").toString("utf-8"),
keyId: process.env["APN_KEY_ID"] as string,
teamId: process.env["APN_TEAM_ID"] as string,
},
production: process.env["NODE_ENV"] === "production",
})
let apnProvider: APN.Provider | undefined

export const getApnProvider = () => {
if (process.env["NODE_ENV"] === "test") {
return undefined
}

if (!apnProvider) {
apnProvider = new APN.Provider({
token: {
key: Buffer.from(process.env["APN_KEY"] ?? "", "base64").toString("utf-8"),
keyId: process.env["APN_KEY_ID"] as string,
teamId: process.env["APN_TEAM_ID"] as string,
},
production: process.env["NODE_ENV"] === "production",
})
}
return apnProvider
}

// Shutdown provider TODO: call on server close
// apnProvider.shutdown()
8 changes: 7 additions & 1 deletion server/src/methods/sendMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { connectionManager } from "@in/server/ws/connections"
import { getUpdateGroup } from "@in/server/utils/updates"
import * as APN from "apn"
import type { HandlerContext } from "../controllers/v1/helpers"
import { apnProvider } from "../libs/apn"
import { apnProvider, getApnProvider } from "../libs/apn"
import { SessionsModel } from "@in/server/db/models/sessions"
import { encryptMessage } from "@in/server/utils/encryption/encryptMessage"
import { TInputId } from "@in/server/types/methods"
Expand Down Expand Up @@ -298,6 +298,12 @@ const sendPushNotificationToUser = async ({
body: message,
}

let apnProvider = getApnProvider()
if (!apnProvider) {
Log.shared.error("APN provider not found", { userId })
return
}

try {
const result = await apnProvider.send(notification, session.applePushToken)
if (result.failed.length > 0) {
Expand Down

0 comments on commit 4ef61b0

Please sign in to comment.