diff --git a/src/Router.ts b/src/Router.ts index 4950c6dcc..39dd477bd 100644 --- a/src/Router.ts +++ b/src/Router.ts @@ -1,19 +1,9 @@ -import { - Cookies, - FetchHttpClient, - Headers, - HttpMiddleware, - HttpRouter, - HttpServerRequest, - HttpServerResponse, -} from '@effect/platform' +import { Cookies, Headers, HttpMiddleware, HttpRouter, HttpServerRequest, HttpServerResponse } from '@effect/platform' import { Effect, identity, Option, pipe, Record } from 'effect' import { format } from 'fp-ts-routing' import { StatusCodes } from 'http-status-codes' import { aboutUs } from './about-us.js' -import { DeprecatedSleepEnv, ExpressConfig, FlashMessage, Locale } from './Context.js' -import * as FptsToEffect from './FptsToEffect.js' -import { GhostApi } from './ghost.js' +import { ExpressConfig, FlashMessage, Locale } from './Context.js' import { PublicUrl } from './public-url.js' import { Redis } from './Redis.js' import { @@ -220,20 +210,7 @@ const WriteCommentFlowRouter = pipe( export const Router = pipe( HttpRouter.empty, - HttpRouter.get( - Routes.AboutUs.path, - pipe( - Effect.gen(function* () { - const locale = yield* Locale - const fetch = yield* FetchHttpClient.Fetch - const ghostApi = yield* GhostApi - const sleep = yield* DeprecatedSleepEnv - - return yield* FptsToEffect.readerTask(aboutUs(locale), { fetch, ghostApi, ...sleep }) - }), - Effect.andThen(toHttpServerResponse), - ), - ), + HttpRouter.get(Routes.AboutUs.path, pipe(aboutUs, Effect.andThen(toHttpServerResponse))), HttpRouter.concat(WriteCommentFlowRouter), HttpRouter.use( HttpMiddleware.make( diff --git a/src/about-us.ts b/src/about-us.ts index c01b9787f..2396ee46e 100644 --- a/src/about-us.ts +++ b/src/about-us.ts @@ -1,20 +1,29 @@ +import { FetchHttpClient } from '@effect/platform' +import { Effect } from 'effect' import { format } from 'fp-ts-routing' -import * as RTE from 'fp-ts/lib/ReaderTaskEither.js' -import { pipe } from 'fp-ts/lib/function.js' -import { getPage } from './ghost.js' +import { DeprecatedSleepEnv, Locale } from './Context.js' +import * as FptsToEffect from './FptsToEffect.js' +import { getPage, GhostApi } from './ghost.js' +import { HavingProblemsPage } from './HavingProblemsPage/index.js' import { type Html, fixHeadingLevels, html, plainText } from './html.js' -import { havingProblemsPage } from './http-error.js' import { type SupportedLocale, translate } from './locales/index.js' import { PageResponse } from './response.js' import { aboutUsMatch } from './routes.js' -export const aboutUs = (locale: SupportedLocale) => - pipe( - RTE.Do, - RTE.apS('content', getPage('6154aa157741400e8722bb14')), - RTE.let('locale', () => locale), - RTE.matchW(() => havingProblemsPage, createPage), - ) +export const aboutUs = Effect.gen(function* () { + const locale = yield* Locale + const fetch = yield* FetchHttpClient.Fetch + const ghostApi = yield* GhostApi + const sleep = yield* DeprecatedSleepEnv + + const content = yield* FptsToEffect.readerTaskEither(getPage('6154aa157741400e8722bb14'), { + fetch, + ghostApi, + ...sleep, + }) + + return createPage({ content, locale }) +}).pipe(Effect.catchAll(() => HavingProblemsPage)) function createPage({ content, locale }: { content: Html; locale: SupportedLocale }) { const t = translate(locale) diff --git a/test/about-us.test.ts b/test/about-us.test.ts index 3c438623c..b312c1713 100644 --- a/test/about-us.test.ts +++ b/test/about-us.test.ts @@ -1,9 +1,13 @@ +import { FetchHttpClient } from '@effect/platform' import { test } from '@fast-check/jest' import { describe, expect } from '@jest/globals' +import { Effect, pipe, TestContext } from 'effect' import fetchMock from 'fetch-mock' import { format } from 'fp-ts-routing' import { Status } from 'hyper-ts' import * as _ from '../src/about-us.js' +import { DeprecatedSleepEnv, Locale } from '../src/Context.js' +import { GhostApi } from '../src/ghost.js' import { aboutUsMatch } from '../src/routes.js' import * as fc from './fc.js' import { shouldNotBeCalled } from './should-not-be-called.js' @@ -11,52 +15,72 @@ import { shouldNotBeCalled } from './should-not-be-called.js' describe('aboutUs', () => { test.prop([fc.supportedLocale(), fc.string({ unit: fc.alphanumeric(), minLength: 1 })])( 'when the page can be loaded', - async (locale, key) => { - const fetch = fetchMock.sandbox().getOnce( - { - url: 'https://content.prereview.org/ghost/api/content/pages/6154aa157741400e8722bb14', - query: { key }, - }, - { body: { pages: [{ html: '
Foo
' }] } }, - ) + (locale, key) => + Effect.gen(function* () { + const fetch = fetchMock.sandbox().getOnce( + { + url: 'https://content.prereview.org/ghost/api/content/pages/6154aa157741400e8722bb14', + query: { key }, + }, + { body: { pages: [{ html: 'Foo
' }] } }, + ) - const actual = await _.aboutUs(locale)({ fetch, ghostApi: { key }, sleep: shouldNotBeCalled })() + const actual = yield* pipe( + _.aboutUs, + Effect.provideService(FetchHttpClient.Fetch, fetch as typeof FetchHttpClient.Fetch.Service), + ) - expect(actual).toStrictEqual({ - _tag: 'PageResponse', - canonical: format(aboutUsMatch.formatter, {}), - current: 'about-us', - status: Status.OK, - title: expect.anything(), - main: expect.anything(), - skipToLabel: 'main', - js: [], - }) - }, + expect(actual).toStrictEqual({ + _tag: 'PageResponse', + canonical: format(aboutUsMatch.formatter, {}), + current: 'about-us', + status: Status.OK, + title: expect.anything(), + main: expect.anything(), + skipToLabel: 'main', + js: [], + }) + }).pipe( + Effect.provideService(Locale, locale), + Effect.provideService(DeprecatedSleepEnv, { sleep: shouldNotBeCalled }), + Effect.provideService(GhostApi, { key }), + Effect.provide(TestContext.TestContext), + Effect.runPromise, + ), ) test.prop([fc.supportedLocale(), fc.string({ unit: fc.alphanumeric(), minLength: 1 }), fc.fetchResponse()])( 'when the page cannot be loaded', - async (locale, key, response) => { - const fetch = fetchMock.sandbox().getOnce( - { - url: 'begin:https://content.prereview.org/ghost/api/content/pages/6154aa157741400e8722bb14?', - query: { key }, - }, - response, - ) + async (locale, key, response) => + Effect.gen(function* () { + const fetch = fetchMock.sandbox().getOnce( + { + url: 'begin:https://content.prereview.org/ghost/api/content/pages/6154aa157741400e8722bb14?', + query: { key }, + }, + response, + ) - const actual = await _.aboutUs(locale)({ fetch, ghostApi: { key }, sleep: shouldNotBeCalled })() + const actual = yield* pipe( + _.aboutUs, + Effect.provideService(FetchHttpClient.Fetch, fetch as typeof FetchHttpClient.Fetch.Service), + ) - expect(actual).toStrictEqual({ - _tag: 'PageResponse', - status: Status.ServiceUnavailable, - title: expect.anything(), - main: expect.anything(), - skipToLabel: 'main', - js: [], - }) - expect(fetch.done()).toBeTruthy() - }, + expect(actual).toStrictEqual({ + _tag: 'PageResponse', + status: Status.ServiceUnavailable, + title: expect.anything(), + main: expect.anything(), + skipToLabel: 'main', + js: [], + }) + expect(fetch.done()).toBeTruthy() + }).pipe( + Effect.provideService(Locale, locale), + Effect.provideService(DeprecatedSleepEnv, { sleep: shouldNotBeCalled }), + Effect.provideService(GhostApi, { key }), + Effect.provide(TestContext.TestContext), + Effect.runPromise, + ), ) })