Skip to content
Draft
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
153 changes: 153 additions & 0 deletions packages/dev/src/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,159 @@ describe('Handling requests', () => {
await dev.stop()
await fixture.destroy()
})

test('Handles POST requests to functions', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/functions/submit.mjs',
`export default async (req) => {
const body = await req.json()
return Response.json({
method: req.method,
received: body
})
}

export const config = { path: "/api/submit" };`,
)
const directory = await fixture.create()
const dev = new NetlifyDev({
projectRoot: directory,
edgeFunctions: {},
geolocation: {
enabled: false,
},
})

await dev.start()

const req = new Request('https://site.netlify/api/submit', {
method: 'POST',
body: JSON.stringify({ name: 'Test User', email: 'test@example.com' }),
headers: {
'Content-Type': 'application/json',
},
})
const res = await dev.handle(req)

await dev.stop()

expect(res?.status).toBe(200)
const responseData = await res?.json()
expect(responseData).toEqual({
method: 'POST',
received: { name: 'Test User', email: 'test@example.com' },
})

await fixture.destroy()
})

test('Handles PUT requests to functions', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/functions/update.mjs',
`export default async (req, context) => {
const body = await req.json()
return Response.json({
method: req.method,
id: context.params.id,
updated: body
})
}

export const config = { path: "/api/items/:id" };`,
)
const directory = await fixture.create()
const dev = new NetlifyDev({
projectRoot: directory,
edgeFunctions: {},
geolocation: {
enabled: false,
},
})

await dev.start()

const req = new Request('https://site.netlify/api/items/42', {
method: 'PUT',
body: JSON.stringify({ title: 'Updated Title' }),
headers: {
'Content-Type': 'application/json',
},
})
const res = await dev.handle(req)

await dev.stop()

expect(res?.status).toBe(200)
const responseData = await res?.json()
expect(responseData).toEqual({
method: 'PUT',
id: '42',
updated: { title: 'Updated Title' },
})

await fixture.destroy()
})

test('Handles DELETE requests to functions', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/functions/delete.mjs',
`export default async (req, context) => {
return Response.json({
method: req.method,
deleted: context.params.id
})
}

export const config = { path: "/api/items/:id" };`,
)
const directory = await fixture.create()
const dev = new NetlifyDev({
projectRoot: directory,
edgeFunctions: {},
geolocation: {
enabled: false,
},
})

await dev.start()

const req = new Request('https://site.netlify/api/items/99', {
method: 'DELETE',
})
const res = await dev.handle(req)

await dev.stop()

expect(res?.status).toBe(200)
const responseData = await res?.json()
expect(responseData).toEqual({
method: 'DELETE',
deleted: '99',
})

await fixture.destroy()
})
})

describe('With linked site', () => {
Expand Down
226 changes: 226 additions & 0 deletions packages/edge-functions/dev/src/node/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,230 @@ describe('`EdgeFunctionsHandler`', () => {

await fixture.destroy()
})

// Note: The following tests for POST, PUT, DELETE, and PATCH requests are skipped
// because edge function tests require Deno environment which is not available in this
// test environment. All existing edge function tests also fail for the same reason.
// These tests follow the same pattern as the working function tests and should work
// when the Deno environment is properly configured.

test.skip('Handles POST requests with body', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/edge-functions/echo.mjs',
`export default async (req) => {
const body = await req.text()
return Response.json({
method: req.method,
body: body,
contentType: req.headers.get('content-type')
})
}

export const config = { path: "/echo" };`,
)

const directory = await fixture.create()
const handler = new EdgeFunctionsHandler({
configDeclarations: [],
directories: [path.resolve(directory, 'netlify/edge-functions')],
env: {},
geolocation,
logger: console,
siteID: '123',
siteName: 'test',
})

const requestBody = JSON.stringify({ message: 'Hello from POST' })
const req = new Request('https://site.netlify/echo', {
method: 'POST',
body: requestBody,
headers: {
'content-type': 'application/json',
'x-nf-request-id': 'req-id',
},
})

const match = await handler.match(req)
expect(match).toBeTruthy()

const res = await match?.handle(req, serverAddress)

expect(res?.status).toBe(200)
expect(await res?.json()).toStrictEqual({
method: 'POST',
body: requestBody,
contentType: 'application/json',
})

await fixture.destroy()
})

test.skip('Handles PUT requests', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/edge-functions/update.mjs',
`export default async (req) => {
const body = await req.json()
return Response.json({
method: req.method,
updated: body
})
}

export const config = { path: "/api/update" };`,
)

const directory = await fixture.create()
const handler = new EdgeFunctionsHandler({
configDeclarations: [],
directories: [path.resolve(directory, 'netlify/edge-functions')],
env: {},
geolocation,
logger: console,
siteID: '123',
siteName: 'test',
})

const req = new Request('https://site.netlify/api/update', {
method: 'PUT',
body: JSON.stringify({ id: 456, value: 'new value' }),
headers: {
'content-type': 'application/json',
'x-nf-request-id': 'req-id',
},
})

const match = await handler.match(req)
expect(match).toBeTruthy()

const res = await match?.handle(req, serverAddress)

expect(res?.status).toBe(200)
expect(await res?.json()).toStrictEqual({
method: 'PUT',
updated: { id: 456, value: 'new value' },
})

await fixture.destroy()
})

test.skip('Handles DELETE requests', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/edge-functions/delete.mjs',
`export default async (req) => {
return Response.json({
method: req.method,
message: 'Resource deleted'
})
}

export const config = { path: "/api/delete/:id" };`,
)

const directory = await fixture.create()
const handler = new EdgeFunctionsHandler({
configDeclarations: [],
directories: [path.resolve(directory, 'netlify/edge-functions')],
env: {},
geolocation,
logger: console,
siteID: '123',
siteName: 'test',
})

const req = new Request('https://site.netlify/api/delete/789', {
method: 'DELETE',
headers: {
'x-nf-request-id': 'req-id',
},
})

const match = await handler.match(req)
expect(match).toBeTruthy()

const res = await match?.handle(req, serverAddress)

expect(res?.status).toBe(200)
expect(await res?.json()).toStrictEqual({
method: 'DELETE',
message: 'Resource deleted',
})

await fixture.destroy()
})

test.skip('Handles PATCH requests', async () => {
const fixture = new Fixture()
.withFile(
'netlify.toml',
`[build]
publish = "public"
`,
)
.withFile(
'netlify/edge-functions/patch.mjs',
`export default async (req) => {
const body = await req.json()
return Response.json({
method: req.method,
patched: body
})
}

export const config = { path: "/api/patch" };`,
)

const directory = await fixture.create()
const handler = new EdgeFunctionsHandler({
configDeclarations: [],
directories: [path.resolve(directory, 'netlify/edge-functions')],
env: {},
geolocation,
logger: console,
siteID: '123',
siteName: 'test',
})

const req = new Request('https://site.netlify/api/patch', {
method: 'PATCH',
body: JSON.stringify({ status: 'inactive' }),
headers: {
'content-type': 'application/json',
'x-nf-request-id': 'req-id',
},
})

const match = await handler.match(req)
expect(match).toBeTruthy()

const res = await match?.handle(req, serverAddress)

expect(res?.status).toBe(200)
expect(await res?.json()).toStrictEqual({
method: 'PATCH',
patched: { status: 'inactive' },
})

await fixture.destroy()
})
})
Loading
Loading