Something went wrong. Try again.
Dedicated SSR (Server-side-rendered) Astro native Headless CMS, build from the ground up for the Astro community and by Astro community memb github.com/withstudiocms/studiocms
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254import * as HttpServerRequest from '@effect/platform/HttpServerRequest';import * as allure from 'allure-js-commons';import { Exit } from 'effect';import * as Effect from 'effect/Effect';import * as Layer from 'effect/Layer';import { describe, expect, test } from 'vitest';import { processUrl, ResponseToHttpServerResponse, ServerRequestToRequest, tryWebHandler, WebHandlerError, webHandlerToEffectHttpHandler,} from '../src/webHandler';import { parentSuiteName, sharedTags } from './test-utils.js';
const localSuiteName = 'Web Handler Tests';
// Mock HttpServerRequest implementationconst createMockRequest = ( url: string, method = 'GET', headers: Record<string, string> = {}, body?: ArrayBuffer): HttpServerRequest.HttpServerRequest => ({ url, method, headers, originalUrl: 'http://localhost:3000', arrayBuffer: body ? Effect.succeed(body) : Effect.succeed(new ArrayBuffer(0)), }) as unknown as HttpServerRequest.HttpServerRequest;
describe(parentSuiteName, () => { test('webHandlerError - should create a tagged error with request context', async () => { await allure.parentSuite(parentSuiteName); await allure.suite(localSuiteName); await allure.subSuite('WebHandlerError'); await allure.tags(...sharedTags);
await allure.step('should create a tagged error with request context', async (ctx) => { const mockRequest = createMockRequest('/test'); const error = new WebHandlerError({ request: mockRequest, description: 'Test error', cause: new Error('Original error'), });
expect(error._tag).toBe('effectify/webHandler.WebHandlerError'); expect(error.request).toBe(mockRequest); expect(error.description).toBe('Test error');
await ctx.parameter('error', String(error)); }); });
[ { name: 'should process URL with default protocol and host', headers: new Headers(), request: createMockRequest('/api/test'), expected: 'http://localhost:3000/api/test', }, { name: 'should use x-forwarded-proto header when present', headers: new Headers({ 'x-forwarded-proto': 'https' }), request: createMockRequest('/api/test'), expected: 'https://localhost:3000/api/test', }, { name: 'should use host header when present', headers: new Headers({ host: 'example.com' }), request: createMockRequest('/api/test'), expected: 'http://example.com/api/test', }, { name: 'should handle URLs without leading slash', headers: new Headers(), request: createMockRequest('api/test'), expected: 'http://localhost:3000/api/test', }, ].forEach(({ name, headers, request, expected }) => { test(`processUrl - ${name}`, async () => { await allure.parentSuite(parentSuiteName); await allure.suite(localSuiteName); await allure.subSuite('processUrl'); await allure.tags(...sharedTags);
await allure.step(name, async (ctx) => { const result = await Effect.runPromise(processUrl(headers, request)); expect(result).toBe(expected); await ctx.parameter('result', result); }); }); });
[ { name: 'should convert GET request without body', request: createMockRequest('/test', 'GET', { 'content-type': 'application/json', }),
validate: (result: Request) => { expect(result).toBeInstanceOf(Request); expect(result.method).toBe('GET'); expect(result.headers.get('content-type')).toBe('application/json'); }, }, { name: 'should convert POST request with body', request: createMockRequest( '/test', 'POST', { 'content-type': 'application/json' }, new TextEncoder().encode('{"test": "data"}').buffer ),
validate: async (result: Request) => { expect(result.method).toBe('POST'); const body = await result.text(); expect(body).toBe('{"test": "data"}'); }, }, { name: 'should handle empty body for POST request', request: createMockRequest('/test', 'POST', {}, new ArrayBuffer(0)),
validate: (result: Request) => { expect(result.method).toBe('POST'); }, }, { name: 'should not include body for HEAD request', request: createMockRequest('/test', 'HEAD'),
validate: (result: Request) => { expect(result.method).toBe('HEAD'); expect(result.body).toBeNull(); }, }, ].forEach(({ name, request, validate }) => { test(`ServerRequestToRequest - ${name}`, async () => { await allure.parentSuite(parentSuiteName); await allure.suite(localSuiteName); await allure.subSuite('ServerRequestToRequest'); await allure.tags(...sharedTags);
await allure.step(name, async (ctx) => { const result = await Effect.runPromise(ServerRequestToRequest(request)); validate(result); await ctx.parameter('result', String(result)); }); }); });
[ { name: 'should convert Response with body', response: new Response('test body', { status: 200, headers: { 'content-type': 'text/plain' }, }), }, { name: 'should convert Response without body', response: new Response(null, { status: 204, }), }, { name: 'should preserve response headers', response: new Response('test', { status: 200, headers: { 'content-type': 'application/json', 'x-custom-header': 'custom-value', }, }), }, ].forEach(({ name, response }) => { test(`ResponseToHttpServerResponse - ${name}`, async () => { await allure.parentSuite(parentSuiteName); await allure.suite(localSuiteName); await allure.subSuite('ResponseToHttpServerResponse'); await allure.tags(...sharedTags);
await allure.step(name, async (ctx) => { const result = await Effect.runPromise(ResponseToHttpServerResponse(response)); expect(result).toBeDefined(); await ctx.parameter('result', String(result)); }); }); });
[ { name: 'should successfully process handler', handler: async (_request: Request) => new Response('success', { status: 200 }), validate: async (result: Exit.Exit<Response, WebHandlerError>) => { expect(result).toStrictEqual( Exit.succeed(expect.objectContaining({ status: 200, body: expect.anything() })) ); }, }, { name: 'should catch handler errors and wrap them', handler: async (_request: Request) => { throw new Error('Handler failed'); }, validate: async (result: Exit.Exit<Response, WebHandlerError>) => { expect(result).toStrictEqual( Exit.fail(expect.objectContaining({ _tag: 'effectify/webHandler.WebHandlerError' })) ); }, }, ].forEach(({ name, handler, validate }) => { test(`tryWebHandler - ${name}`, async () => { await allure.parentSuite(parentSuiteName); await allure.suite(localSuiteName); await allure.subSuite('tryWebHandler'); await allure.tags(...sharedTags);
const mockRequest = createMockRequest('/test'); const result = await Effect.runPromiseExit(tryWebHandler(handler, mockRequest)); await validate(result); }); });
test('webHandlerToEffectHttpHandler - should convert web handler to Effect handler', async () => { await allure.parentSuite(parentSuiteName); await allure.suite(localSuiteName); await allure.subSuite('webHandlerToEffectHttpHandler'); await allure.tags(...sharedTags);
const handler = async (request: Request) => new Response(JSON.stringify({ url: request.url }), { status: 200, headers: { 'content-type': 'application/json' }, });
const mockRequest = createMockRequest('/test'); const requestLayer = Layer.succeed(HttpServerRequest.HttpServerRequest, mockRequest);
await allure.step('should convert web handler to Effect handler', async (ctx) => { const effect = webHandlerToEffectHttpHandler(handler); const result = await Effect.runPromise(Effect.provide(effect, requestLayer));
expect(result).toBeDefined(); await ctx.parameter('result', String(result)); }); });});