UNPKG

accounts

Version:

Tempo Accounts SDK

692 lines (565 loc) 21.9 kB
import { Elysia } from 'elysia' import express from 'express' import { Hono } from 'hono' import { describe, expect, test } from 'vp/test' import { createServer } from '../../test/utils.js' import * as Handler from './Handler.js' describe('from', () => { describe('cors', () => { test('default: adds CORS headers', async () => { const handler = Handler.from() handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe( 'GET, POST, PUT, DELETE, OPTIONS', ) expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type') }) test('behavior: cors = false disables CORS headers', async () => { const handler = Handler.from({ cors: false }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(response.headers.get('Access-Control-Allow-Origin')).toBeNull() expect(response.headers.get('Access-Control-Allow-Methods')).toBeNull() }) test('behavior: custom cors config', async () => { const handler = Handler.from({ cors: { origin: 'https://example.com', methods: 'GET, POST', headers: 'Content-Type, Authorization', credentials: true, maxAge: 86400, }, }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(response.headers.get('Access-Control-Allow-Origin')).toBe('https://example.com') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('GET, POST') expect(response.headers.get('Access-Control-Allow-Headers')).toBe( 'Content-Type, Authorization', ) expect(response.headers.get('Access-Control-Allow-Credentials')).toBe('true') expect(response.headers.get('Access-Control-Max-Age')).toBe('86400') }) test('behavior: cors with array of origins', async () => { const handler = Handler.from({ cors: { origin: ['https://example.com', 'https://other.com'], }, }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.headers.get('Access-Control-Allow-Origin')).toBe( 'https://example.com, https://other.com', ) }) test('behavior: OPTIONS preflight with default CORS', async () => { const handler = Handler.from() handler.get('/test', () => new Response('test')) const response = await handler.fetch( new Request('http://localhost/test', { method: 'OPTIONS' }), ) expect(response.status).toBe(200) expect(await response.text()).toBe('') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe( 'GET, POST, PUT, DELETE, OPTIONS', ) }) test('behavior: custom headers override CORS headers', async () => { const handler = Handler.from({ cors: { origin: 'https://default.com' }, headers: { 'Access-Control-Allow-Origin': 'https://override.com' }, }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.headers.get('Access-Control-Allow-Origin')).toBe('https://override.com') }) }) }) describe('compose', () => { test('default', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const handler2 = Handler.from() handler2.get('/test2', () => new Response('test2')) const handler = Handler.compose([handler1, handler2]) expect(handler).toBeDefined() { const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') } { const response = await handler.fetch(new Request('http://localhost/test2')) expect(response.status).toBe(200) expect(await response.text()).toBe('test2') } }) test('behavior: path', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const handler2 = Handler.from() handler2.get('/test2', () => new Response('test2')) const handler = Handler.compose([handler1, handler2], { path: '/api', }) expect(handler).toBeDefined() { const response = await handler.fetch(new Request('http://localhost/api/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') } { const response = await handler.fetch(new Request('http://localhost/api/test2')) expect(response.status).toBe(200) expect(await response.text()).toBe('test2') } }) test('behavior: headers', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const handler2 = Handler.from() handler2.get('/test2', () => new Response('test2')) const headers = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }) const handler = Handler.compose([handler1, handler2], { headers, }) { const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') expect(response.headers.get('Access-Control-Allow-Headers')).toBe( 'Content-Type, Authorization', ) } { const response = await handler.fetch(new Request('http://localhost/test2')) expect(response.status).toBe(200) expect(await response.text()).toBe('test2') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') } }) test('behavior: headers + path', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const handler2 = Handler.from() handler2.get('/test2', () => new Response('test2')) const headers = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', }) const handler = Handler.compose([handler1, handler2], { headers, path: '/api', }) { const response = await handler.fetch(new Request('http://localhost/api/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') } { const response = await handler.fetch(new Request('http://localhost/api/test2')) expect(response.status).toBe(200) expect(await response.text()).toBe('test2') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') } }) test('behavior: headers + OPTIONS', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const headers = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', 'Access-Control-Max-Age': '86400', }) const handler = Handler.compose([handler1], { headers, }) const response = await handler.fetch( new Request('http://localhost/test', { method: 'OPTIONS', }), ) expect(response.status).toBe(200) expect(await response.text()).toBe('') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type, Authorization') expect(response.headers.get('Access-Control-Max-Age')).toBe('86400') }) test('behavior: headers + 404', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const headers = new Headers({ 'Access-Control-Allow-Origin': '*', }) const handler = Handler.compose([handler1], { headers, }) const response = await handler.fetch(new Request('http://localhost/nonexistent')) expect(response.status).toBe(404) expect(await response.text()).toBe('Not Found') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') }) test('behavior: headers propagation from child handlers', async () => { const handler1 = Handler.from() handler1.get('/test', () => { const response = new Response('test') response.headers.set('X-Custom-Header', 'custom-value') return response }) const headers = new Headers({ 'Access-Control-Allow-Origin': '*', }) const handler = Handler.compose([handler1], { headers, }) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('X-Custom-Header')).toBe('custom-value') }) test('behavior: headers with child handler headers', async () => { const childHeaders = new Headers({ 'X-Child-Header': 'child-value', }) const handler1 = Handler.from({ headers: childHeaders }) handler1.get('/test', () => new Response('test')) const parentHeaders = new Headers({ 'Access-Control-Allow-Origin': '*', 'X-Parent-Header': 'parent-value', }) const handler = Handler.compose([handler1], { headers: parentHeaders, }) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') // Both parent and child headers should be present expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('X-Parent-Header')).toBe('parent-value') expect(response.headers.get('X-Child-Header')).toBe('child-value') }) test('behavior: headers as object', async () => { const handler1 = Handler.from() handler1.get('/test', () => new Response('test')) const handler = Handler.compose([handler1], { headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }, }) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type, Authorization') }) describe('integration', () => { const handler1 = Handler.from() handler1.get('/foo', () => new Response('foo')) handler1.post('/bar', () => new Response('bar')) const handler2 = Handler.from() handler2.get('/baz', () => new Response('baz')) handler2.post('/qux', () => new Response('qux')) const handler = Handler.compose([handler1, handler2], { path: '/api', }) test('hono', async () => { const app = new Hono() app.all('*', (c) => handler.fetch(c.req.raw)) { const response = await app.request('/api/foo') expect(await response.text()).toBe('foo') } { const response = await app.request('/api/bar', { method: 'POST', }) expect(await response.text()).toBe('bar') } { const response = await app.request('/api/baz', { method: 'GET', }) expect(await response.text()).toBe('baz') } { const response = await app.request('/api/qux', { method: 'POST', }) expect(await response.text()).toBe('qux') } }) test('elysia', async () => { const app = new Elysia().all('*', ({ request }) => handler.fetch(request)) { const response = await app.handle(new Request('http://localhost/api/foo')) expect(await response.text()).toBe('foo') } { const response = await app.handle( new Request('http://localhost/api/bar', { method: 'POST', }), ) expect(await response.text()).toBe('bar') } { const response = await app.handle( new Request('http://localhost/api/baz', { method: 'GET', }), ) expect(await response.text()).toBe('baz') } { const response = await app.handle( new Request('http://localhost/api/qux', { method: 'POST', }), ) expect(await response.text()).toBe('qux') } }) test('node.js', async () => { const server = await createServer(handler.listener) { const response = await fetch(`${server.url}/api/foo`) expect(await response.text()).toBe('foo') } { const response = await fetch(`${server.url}/api/bar`, { method: 'POST', }) expect(await response.text()).toBe('bar') } { const response = await fetch(`${server.url}/api/baz`, { method: 'GET', }) expect(await response.text()).toBe('baz') } { const response = await fetch(`${server.url}/api/qux`, { method: 'POST', }) expect(await response.text()).toBe('qux') } await server.closeAsync() }) test('express', async () => { const app = express() app.use(handler.listener) const server = await createServer(app) { const response = await fetch(`${server.url}/api/foo`) expect(await response.text()).toBe('foo') } { const response = await fetch(`${server.url}/api/bar`, { method: 'POST', }) expect(await response.text()).toBe('bar') } { const response = await fetch(`${server.url}/api/baz`, { method: 'GET', }) expect(await response.text()).toBe('baz') } { const response = await fetch(`${server.url}/api/qux`, { method: 'POST', }) expect(await response.text()).toBe('qux') } await server.closeAsync() }) }) }) describe('from', () => { test('default', () => { const handler = Handler.from() expect(handler).toBeDefined() }) test('.fetch', async () => { const handler = Handler.from() handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') }) test('.listener', async () => { const handler = Handler.from() handler.get('/test', () => Response.json({ message: 'hello from listener' })) const server = await createServer(handler.listener) // Make a request to the server const response = await fetch(`${server.url}/test`) expect(response.status).toBe(200) const data = await response.json() expect(data).toEqual({ message: 'hello from listener' }) }) test('behavior: headers', async () => { const headers = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }) const handler = Handler.from({ headers }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type, Authorization') }) test('behavior: headers + OPTIONS', async () => { const headers = new Headers({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', 'Access-Control-Max-Age': '86400', }) const handler = Handler.from({ headers }) handler.get('/test', () => new Response('test')) const response = await handler.fetch( new Request('http://localhost/test', { method: 'OPTIONS', }), ) expect(response.status).toBe(200) expect(await response.text()).toBe('') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type, Authorization') expect(response.headers.get('Access-Control-Max-Age')).toBe('86400') }) test('behavior: headers + 404', async () => { const headers = new Headers({ 'Access-Control-Allow-Origin': '*', }) const handler = Handler.from({ headers }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/nonexistent')) expect(response.status).toBe(404) expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') }) test('behavior: headers propagation from routes', async () => { const headers = new Headers({ 'Access-Control-Allow-Origin': '*', }) const handler = Handler.from({ headers }) handler.get('/test', () => { const response = new Response('test') response.headers.set('X-Custom-Header', 'custom-value') response.headers.set('Content-Type', 'text/plain') return response }) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('X-Custom-Header')).toBe('custom-value') expect(response.headers.get('Content-Type')).toBe('text/plain') }) test('behavior: headers as object', async () => { const handler = Handler.from({ headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', }, }) handler.get('/test', () => new Response('test')) const response = await handler.fetch(new Request('http://localhost/test')) expect(response.status).toBe(200) expect(await response.text()).toBe('test') expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*') expect(response.headers.get('Access-Control-Allow-Methods')).toBe('POST, OPTIONS') expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type, Authorization') }) describe('integration', () => { const handler = Handler.from() handler.get('/foo', () => new Response('foo')) handler.post('/bar', () => new Response('bar')) test('hono', async () => { const app = new Hono() app.all('*', (c) => handler.fetch(c.req.raw)) { const response = await app.request('/foo') expect(await response.text()).toBe('foo') } { const response = await app.request('/bar', { method: 'POST', }) expect(await response.text()).toBe('bar') } }) test('elysia', async () => { const app = new Elysia().all('*', ({ request }) => handler.fetch(request)) { const response = await app.handle(new Request('http://localhost/foo')) expect(await response.text()).toBe('foo') } { const response = await app.handle( new Request('http://localhost/bar', { method: 'POST', }), ) expect(await response.text()).toBe('bar') } }) test('node.js', async () => { const server = await createServer(handler.listener) { const response = await fetch(`${server.url}/foo`) expect(await response.text()).toBe('foo') } { const response = await fetch(`${server.url}/bar`, { method: 'POST', }) expect(await response.text()).toBe('bar') } await server.closeAsync() }) test('express', async () => { const app = express() app.use(handler.listener) const server = await createServer(app) { const response = await fetch(`${server.url}/foo`) expect(await response.text()).toBe('foo') } { const response = await fetch(`${server.url}/bar`, { method: 'POST', }) expect(await response.text()).toBe('bar') } await server.closeAsync() }) }) })