Skip to content

Commit 7857035

Browse files
feat: Add CI for Deno tests and refactor task-management function
Refactored `supabase/functions/task-management/index.ts` to allow the `createToken` function to be exported and used directly in tests. - Moved `createToken` to the top-level scope. - Exported `createToken`. Updated `supabase/functions/task-management/index.test.ts`: - Removed the local `createTokenForTest` definition. - Imported and used the `createToken` function from `index.ts`. This change helps prevent TS2322 type errors by ensuring the test uses the actual function implementation. Added a GitHub Actions workflow (`.github/workflows/deno-test.yml`) to automate Deno testing for functions under `supabase/functions/`. - The workflow triggers on pushes and pull requests to the main branch affecting files in `supabase/functions/`. - It checks out the code, sets up Deno, and runs `deno test` with necessary permissions.
1 parent 0a82448 commit 7857035

File tree

3 files changed

+63
-61
lines changed

3 files changed

+63
-61
lines changed

.github/workflows/deno-test.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Deno Test
2+
3+
on:
4+
push:
5+
branches:
6+
- main # Or your default branch
7+
paths:
8+
- 'supabase/functions/**'
9+
pull_request:
10+
paths:
11+
- 'supabase/functions/**'
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Setup Deno
22+
uses: denoland/setup-deno@v1
23+
with:
24+
deno-version: v1.x # Use a specific version or v1.x for latest 1.x
25+
26+
- name: Run Deno tests
27+
run: |
28+
deno test --allow-read --allow-env --allow-net supabase/functions/task-management/index.test.ts
29+
# Optional: If tests need to be run from a specific directory:
30+
# working-directory: ./supabase/functions/task-management

supabase/functions/task-management/index.test.ts

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,10 @@ import {
55
assertObjectMatch,
66
} from "https://deno.land/std@0.192.0/testing/asserts.ts"; // Using a specific version for stability
77
import * as djwt from "https://deno.land/x/djwt@v2.8/mod.ts";
8+
import { createToken } from "./index.ts";
89
// Assuming the createToken function is exported from index.ts or can be extracted/adapted
910
// For this test, let's copy a simplified version of createToken here or make it accessible.
1011

11-
// Simplified/adapted createToken for testing.
12-
// In a real scenario, you'd import this from your actual index.ts.
13-
// To make this self-contained for the tool, I'm redefining it.
14-
// IMPORTANT: This definition MUST match the one in index.ts for the test to be valid.
15-
async function createTokenForTest(
16-
userId: string,
17-
currentJwtSecret: string,
18-
currentSupabaseUrl: string,
19-
) {
20-
const payload = {
21-
sub: userId,
22-
role: "authenticated",
23-
aud: "authenticated",
24-
iss: currentSupabaseUrl,
25-
iat: Math.floor(Date.now() / 1000),
26-
exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour expiration
27-
};
28-
29-
const secretKeyData = new TextEncoder().encode(currentJwtSecret);
30-
const key = await crypto.subtle.importKey(
31-
"raw",
32-
secretKeyData,
33-
{ name: "HMAC", hash: "SHA-256" },
34-
false,
35-
["sign", "verify"], // Ensure "verify" is also here if using the same key for djwt.verify
36-
);
37-
return await djwt.create({ alg: "HS256", typ: "JWT" }, payload, key);
38-
}
39-
4012
// Helper to import a key for djwt.verify, similar to how createToken does for signing
4113
async function importKeyForVerification(jwtSecret: string) {
4214
const secretKeyData = new TextEncoder().encode(jwtSecret);
@@ -68,7 +40,7 @@ Deno.test("createToken generates a valid JWT with correct claims", async () => {
6840
try {
6941
// In a real test, you'd call the original createToken function from index.ts
7042
// For now, calling the adapted version:
71-
token = await createTokenForTest(
43+
token = await createToken(
7244
mockUserId,
7345
mockJwtSecret,
7446
mockSupabaseUrl,
@@ -160,16 +132,16 @@ Deno.test(
160132

161133
let error: Error | undefined;
162134
try {
163-
// We are calling createTokenForTest directly, which doesn't have the Deno.env.get('SUPABASE_JWT_SECRET') check.
135+
// We are calling createToken directly, which doesn't have the Deno.env.get('SUPABASE_JWT_SECRET') check.
164136
// The error will likely come from crypto.subtle.importKey.
165-
await createTokenForTest(mockUserId, weakSecret, mockSupabaseUrl);
137+
await createToken(mockUserId, weakSecret, mockSupabaseUrl);
166138
} catch (e) {
167139
error = e;
168140
}
169141

170142
assertExists(
171143
error,
172-
"createTokenForTest should throw an error with an empty secret.",
144+
"createToken should throw an error with an empty secret.",
173145
);
174146
// The error message might vary: "Key length is zero" or similar from crypto.subtle, or from djwt.
175147
// For now, just checking an error is thrown is sufficient for this conceptual test.

supabase/functions/task-management/index.ts

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,33 @@ function validateTaskData(data: any): { valid: boolean; errors?: string[] } {
5858
};
5959
}
6060

61+
// JWTを生成する関数
62+
// jwtSecret and supabaseUrl are passed directly as they are already retrieved and checked
63+
export async function createToken(
64+
userId: string,
65+
currentJwtSecret: string,
66+
currentSupabaseUrl: string,
67+
) {
68+
const payload = {
69+
sub: userId,
70+
role: "authenticated",
71+
aud: "authenticated",
72+
iss: currentSupabaseUrl,
73+
iat: Math.floor(Date.now() / 1000),
74+
exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour expiration
75+
};
76+
77+
const secretKeyData = new TextEncoder().encode(currentJwtSecret);
78+
const key = await crypto.subtle.importKey(
79+
"raw",
80+
secretKeyData,
81+
{ name: "HMAC", hash: "SHA-256" },
82+
false,
83+
["sign", "verify"],
84+
);
85+
return await djwt.create({ alg: "HS256", typ: "JWT" }, payload, key);
86+
}
87+
6188
console.log("Task Management Function initialized");
6289

6390
Deno.serve(async (req) => {
@@ -185,37 +212,10 @@ Deno.serve(async (req) => {
185212

186213
const actualUserId = keyData.user_id;
187214

188-
// JWTを生成する関数
189-
// jwtSecret and supabaseUrl are passed directly as they are already retrieved and checked
190-
async function createToken(
191-
userId: string,
192-
currentJwtSecret: string,
193-
currentSupabaseUrl: string,
194-
) {
195-
const payload = {
196-
sub: userId,
197-
role: "authenticated",
198-
aud: "authenticated",
199-
iss: currentSupabaseUrl,
200-
iat: Math.floor(Date.now() / 1000),
201-
exp: Math.floor(Date.now() / 1000) + 3600, // 1 hour expiration
202-
};
203-
204-
const secretKeyData = new TextEncoder().encode(currentJwtSecret);
205-
const key = await crypto.subtle.importKey(
206-
"raw",
207-
secretKeyData,
208-
{ name: "HMAC", hash: "SHA-256" },
209-
false,
210-
["sign", "verify"],
211-
);
212-
return await djwt.create({ alg: "HS256", typ: "JWT" }, payload, key);
213-
}
214-
215215
let token;
216216
try {
217217
// supabaseUrl and jwtSecret are already confirmed to exist from the top check
218-
token = await createToken(actualUserId, jwtSecret, supabaseUrl);
218+
token = await createToken(actualUserId, jwtSecret!, supabaseUrl!); // jwtSecret and supabaseUrl are checked at the beginning of Deno.serve
219219
} catch (e) {
220220
// This catch block is now for unexpected errors during token creation itself,
221221
// as specific env var checks are done earlier or within createToken.

0 commit comments

Comments
 (0)