Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Tests

on:
pull_request:
push:
branches:
- main
- rc
workflow_dispatch:

jobs:
autotests:
name: Run tests
strategy:
matrix:
node: ['18']

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}

- name: Install dependencies
working-directory: test
run: npm ci

- id: meta
uses: docker/metadata-action@v4
with:
images: |
edge-runtime:test

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Build test image
uses: docker/build-push-action@v4
with:
file: ./Dockerfile
push: false
load: true
platforms: linux/amd64
tags: edge-runtime:test
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Run Test
working-directory: test
run: npm run test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ temp/
.idea/
.idea

node_modules/
.DS_Store
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,24 @@ docker run -it --rm -p 9000:9000 -v /path/to/supabase/functions:/usr/services su

* Select the Deno version to upgrade and visit its tag on GitHub (eg: https://github.com/denoland/deno/blob/v1.30.3/Cargo.toml)
* Open the `Cargo.toml` at the root of of this repo and modify all `deno_*` modules to match to the selected tag of Deno.

## How to run tests

make sure the docker daemon is running and create a docker image:

```bash
docker build -t edge-runtime:test .
```

install tests dependencies:

```bash
cd test
npm install
```

run tests:

```bash
npm run test
```
2 changes: 1 addition & 1 deletion examples/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ serve(async (req: Request) => {
{ status: 500, headers: { "Content-Type": "application/json" } },
)
}
})
})
3 changes: 3 additions & 0 deletions test/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
package-lock.json
docker*
7 changes: 7 additions & 0 deletions test/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 100
}
4 changes: 4 additions & 0 deletions test/functions/_shared/cors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}
14 changes: 14 additions & 0 deletions test/functions/hello/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { serve } from 'https://deno.land/std/http/server.ts'
import { corsHeaders } from 'shared_cors'

serve((req: Request) => {
if (req.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}
return new Response('Hello World', {
headers: {
...corsHeaders,
'content-type': 'text/plain',
},
})
})
23 changes: 23 additions & 0 deletions test/functions/hijack/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { serve } from 'https://deno.land/std@0.130.0/http/server.ts'

serve((req) => {
const p = Deno.upgradeHttp(req);

(
// Run this async IIFE concurrently, first packet won't arrive
// until we return HTTP101 response.
async () => {
const [conn, firstPacket] = await p
const decoder = new TextDecoder()
const text = decoder.decode(firstPacket)
console.log(text)
// Hello
const uint8Array = new Uint8Array([72, 101, 108, 108, 111])
conn.write(uint8Array)
conn.close()
}
)()

// HTTP101 - Switching Protocols
return new Response(null, { status: 101 })
})
6 changes: 6 additions & 0 deletions test/functions/import_map.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"imports": {
"oak": "https://deno.land/x/oak@v11.1.0/mod.ts",
"shared_cors": "./_shared/cors.ts"
}
}
42 changes: 42 additions & 0 deletions test/functions/main/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { serve } from 'https://deno.land/std@0.131.0/http/server.ts'

serve(async (req: Request) => {
const url = new URL(req.url)
const { pathname } = url
const pathParts = pathname.split('/')
const serviceName = pathParts[1]

if (!serviceName || serviceName === '') {
const error = { msg: 'missing function name in request' }
return new Response(JSON.stringify(error), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}

const servicePath = `/usr/services/${serviceName}`
console.log(`serving the request with ${servicePath}`)

const memoryLimitMb = 150
const workerTimeoutMs = 5 * 60 * 1000
const noModuleCache = false
const importMapPath = `/usr/services/import_map.json`
const envVars = []
try {
const worker = await EdgeRuntime.userWorkers.create({
servicePath,
memoryLimitMb,
workerTimeoutMs,
noModuleCache,
importMapPath,
envVars,
})
return worker.fetch(req)
} catch (e) {
const error = { msg: e.toString() }
return new Response(JSON.stringify(error), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})
}
})
68 changes: 68 additions & 0 deletions test/functions/mirror/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { serve } from 'https://deno.land/std/http/server.ts'
import { corsHeaders } from 'shared_cors'

serve(async (request: Request) => {
if (request.method === 'OPTIONS') {
return new Response('ok', { headers: corsHeaders })
}

let body
let contentType = 'application/json'
switch (request.headers.get('response-type')) {
case 'json': {
body = await request.json()
break
}
case 'form': {
const formBody = await request.formData()
body = []
for (const e of formBody.entries()) {
body.push(e)
}
break
}
case 'blob': {
const data = await request.blob()
body = await data.text()
contentType = 'application/octet-stream'
break
}
case 'arrayBuffer': {
const data = await request.arrayBuffer()
body = new TextDecoder().decode(data || new Uint8Array())
contentType = 'application/octet-stream'
break
}
default: {
body = await request.text()
contentType = 'text/plain'
break
}
}
const headers = []
for (const h of request.headers.entries()) {
headers.push(h)
}
const resp = {
url: request.url ?? 'empty',
method: request.method ?? 'empty',
headers: headers ?? 'empty',
body: body ?? 'empty',
}

let responseData
if (request.headers.get('response-type') === 'blob') {
responseData = new Blob([JSON.stringify(resp)], {
type: 'application/json',
})
} else {
responseData = JSON.stringify(resp)
}
return new Response(responseData, {
status: 200,
headers: {
...corsHeaders,
'content-type': 'application/json',
},
})
})
22 changes: 22 additions & 0 deletions test/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Config } from '@jest/types'

const config: Config.InitialOptions = {
preset: 'ts-jest',
transform: {
'^.+\\.ts?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'cjs', 'json', 'node'],
setupFilesAfterEnv: ['./utils/jest-custom-reporter.ts'],
testTimeout: 60000,
collectCoverageFrom: ['!**/node_modules/**'],
coverageProvider: 'v8',
coverageThreshold: {
global: {
branches: 0,
functions: 0,
lines: 0,
statements: 0,
},
},
}
export default config
6 changes: 6 additions & 0 deletions test/models/mirrorResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface MirrorResponse {
url: string
method: string
headers: string | {}
body: string | {}
}
Loading