UNPKG

bunshine

Version:

A Bun HTTP & WebSocket server that is a little ray of sunshine.

190 lines (188 loc) 6.73 kB
import type { Server } from 'bun'; import { afterEach, beforeEach, describe, expect, it } from 'bun:test'; import HttpRouter from '../../HttpRouter/HttpRouter'; import { cors } from './cors'; describe('cors middleware', () => { let server: Server; let app: HttpRouter; let fetchInit: RequestInit; beforeEach(() => { app = new HttpRouter(); server = app.listen({ port: 0 }); fetchInit = { method: 'OPTIONS', headers: { Origin: 'google.com', }, }; }); afterEach(() => { server.stop(true); }); it('should have proper defaults', async () => { app.use(cors(), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('*'); expect(resp.headers.get('Access-Control-Allow-Methods')).toBe( 'GET,HEAD,PUT,POST,PATCH,DELETE,OPTIONS' ); }); it('should add specific origin', async () => { const options = { origin: 'example.com', }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('example.com'); }); it('should add origin on RegExp', async () => { const options = { origin: /^google.(com|net)$/, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('google.com'); }); it('should add origin on Array<string | RegExp>', async () => { const options = { origin: ['dev.example.com', 'prod.example.com', /^google.(com|net)$/], }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('google.com'); }); it('should parrot origin if true', async () => { const options = { origin: true, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('google.com'); }); it('should omit origin if false', async () => { const options = { origin: false, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe(null); }); it('should allow function that returns true', async () => { const options = { origin: () => true, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('google.com'); }); it('should allow function that returns false', async () => { const options = { origin: () => false, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe(null); }); it('should allow function that returns string', async () => { const options = { origin: () => 'google.com', }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('google.com'); }); it('should ignore function that returns invalid value', async () => { const options = { origin: () => 123, }; // @ts-expect-error - testing invalid input app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe(null); }); it('should allow function-returning arrays (with match)', async () => { const options = { origin: () => ['example.com', 'google.com'], }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('google.com'); }); it('should allow arrays (without match)', async () => { const options = { origin: ['some-other-thing'], }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.has('Access-Control-Allow-Origin')).toBe(false); }); it('should add other headers', async () => { const options = { allowMethods: ['GET', 'POST'], allowHeaders: ['Foo', 'Bar'], exposeHeaders: ['Baz', 'Qux'], maxAge: 60 * 30, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, fetchInit); const text = await resp.text(); expect(text).toBe(''); expect(resp.headers.get('Access-Control-Allow-Methods')).toBe('GET,POST'); expect(resp.headers.get('Access-Control-Allow-Headers')).toBe('Foo,Bar'); expect(resp.headers.get('Access-Control-Max-Age')).toBe('1800'); }); it('should add headers on GET', async () => { const options = { origin: '*', allowMethods: ['GET', 'POST'], allowHeaders: ['Foo', 'Bar'], exposeHeaders: ['Baz', 'Qux'], maxAge: 60 * 30, }; app.use(cors(options), c => c.text('hello')); const resp = await fetch(server.url, { headers: { Origin: 'google.com', }, }); const text = await resp.text(); expect(text).toBe('hello'); expect(resp.headers.get('Access-Control-Allow-Origin')).toBe('*'); expect(resp.headers.has('Access-Control-Allow-Methods')).toBe(false); expect(resp.headers.get('Access-Control-Expose-Headers')).toBe('Baz,Qux'); }); it('should throw on invalid origin option', async () => { const thrower = () => { const options = { origin: new Date(), }; // @ts-expect-error - testing invalid input app.use(cors(options), c => c.text('hello')); }; expect(thrower).toThrowError('Invalid cors origin option'); }); });