1/**
2 * @title Testing code that uses a GraphQL client
3 *
4 * Replace a client service with `GraphQLClient.layerTest`, answering each
5 * operation from a handler instead of a server.
6 */
7import { assert, describe, it } from "@effect/vitest"
8import { Effect } from "effect"
9import { GitHub } from "./10_basics.ts"
10
11// Code under test that depends on the `GitHub` client service.
12const issueTitles = (owner: string, name: string) =>
13 GitHub.use((github) => github.RepoIssues({ owner, name })).pipe(
14 Effect.map(({ repository }) => repository?.issues.nodes?.map((issue) => issue?.title) ?? [])
15 )
16
17// The service binds `GraphQLClient.layerTest(GitHub, GitHubGraphQLGroup)` once
18// as a static helper. Handlers are keyed by operation name, receive the
19// caller's variables and options, and return results in their decoded form.
20// Nothing is encoded or decoded and no middleware runs. An operation without
21// a handler dies with an `UnimplementedError` defect.
22const GitHubTest = GitHub.layerTest({
23 RepoIssues: ({ owner, name }) =>
24 Effect.succeed({
25 repository: {
26 issues: {
27 pageInfo: { hasNextPage: false, endCursor: null },
28 nodes: [{ number: 1, title: `Hello from ${owner}/${name}` }]
29 }
30 }
31 })
32})
33
34describe("issueTitles", () => {
35 it.effect("returns the titles of the first page", () =>
36 Effect.gen(function*() {
37 const titles = yield* issueTitles("Effect-TS", "effect")
38 assert.deepStrictEqual(titles, ["Hello from Effect-TS/effect"])
39 }).pipe(Effect.provide(GitHubTest)))
40})
41
42// `layerTest` uses `makeTest`, which skips the protocol and cannot return
43// partial data together with `errors`. To test that, or the encode and decode
44// path, build the real client with `GraphQLClient.make` over a scripted
45// `GraphQLProtocol` layer (see `GraphQLProtocol`).