( serverLayer: Layer.Layer<never, any, any>, )
| 94 | > => makeTestHttpServer(serverLayer); |
| 95 | |
| 96 | const makeTestHttpServer = ( |
| 97 | serverLayer: Layer.Layer<never, any, any>, |
| 98 | ): Effect.Effect< |
| 99 | TestHttpServerShape, |
| 100 | TestHttpServerAddressError | TestHttpServerServeError, |
| 101 | EffectScope.Scope |
| 102 | > => |
| 103 | Effect.gen(function* () { |
| 104 | const context = yield* Layer.build( |
| 105 | Layer.fresh(serverLayer.pipe(Layer.provideMerge(NodeHttpServer.layerTest))), |
| 106 | ).pipe(Effect.mapError((cause) => new TestHttpServerServeError({ cause }))); |
| 107 | const server = Context.get(context, HttpServer.HttpServer); |
| 108 | const address = server.address; |
| 109 | if (!Predicate.isTagged(address, "TcpAddress")) { |
| 110 | return yield* new TestHttpServerAddressError({ address }); |
| 111 | } |
| 112 | const client = Context.get(context, HttpClient.HttpClient); |
| 113 | // Under a loaded machine the listen callback can fire before the socket |
| 114 | // reliably accepts; probe at the TCP level (no HTTP request, so handlers |
| 115 | // that record requests never see it) until a connect succeeds. |
| 116 | yield* Effect.callback<void, TestHttpServerServeError>((resume) => { |
| 117 | const socket = createConnection({ host: "127.0.0.1", port: address.port }, () => { |
| 118 | socket.end(); |
| 119 | resume(Effect.void); |
| 120 | }); |
| 121 | socket.on("error", (cause) => resume(Effect.fail(new TestHttpServerServeError({ cause })))); |
| 122 | }).pipe(Effect.retry(Schedule.both(Schedule.spaced("10 millis"), Schedule.recurs(100)))); |
| 123 | const baseUrl = `http://127.0.0.1:${address.port}`; |
| 124 | return { |
| 125 | baseUrl, |
| 126 | httpClientLayer: Layer.succeed(HttpClient.HttpClient, client), |
| 127 | url: (path = "") => new URL(path, baseUrl).toString(), |
| 128 | }; |
| 129 | }); |
no test coverage detected