Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas committed Apr 3, 2024
1 parent a47cac9 commit e8057fc
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 73 deletions.
21 changes: 2 additions & 19 deletions integration-test/nextjs/src/app/cc/ApolloWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import React from "react";
import { ApolloLink, HttpLink, Observable } from "@apollo/client";
import { HttpLink } from "@apollo/client";
import {
ApolloNextAppProvider,
NextSSRInMemoryCache,
Expand All @@ -15,29 +15,12 @@ import { delayLink } from "@/shared/delayLink";
import { schema } from "../graphql/schema";

import { useSSROnlySecret } from "ssr-only-secrets";
import { GraphQLError } from "graphql";
import { errorLink } from "../../shared/errorLink";

setVerbosity("debug");
loadDevMessages();
loadErrorMessages();

const errorLink = new ApolloLink((operation, forward) => {
const context = operation.getContext();
if (
context.error === "always" ||
(typeof window === "undefined" && context.error === "ssr") ||
(typeof window !== "undefined" && context.error === "browser")
) {
return new Observable((subscriber) => {
subscriber.next({
data: null,
errors: [new GraphQLError("Simulated error")],
});
});
}
return forward(operation);
});

export function ApolloWrapper({
children,
nonce,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const QUERY: TypedDocumentNode<Data> = gql`
export const dynamic = "force-dynamic";

export default function Page() {
const [queryRef] = useBackgroundQuery(QUERY, { context: { delay: 2000 } });
const [queryRef] = useBackgroundQuery(QUERY, {
context: { delay: 2000, error: "browser" },
});
return (
<Suspense fallback={<p>loading</p>}>
<DisplayData queryRef={queryRef} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ const QUERY: TypedDocumentNode<{
export const dynamic = "force-dynamic";

export default function Page() {
const { data } = useSuspenseQuery(QUERY);
const { data } = useSuspenseQuery(QUERY, {
context: { delay: 1000, error: "browser" },
});
globalThis.hydrationFinished?.();

return (
Expand Down
9 changes: 2 additions & 7 deletions integration-test/nextjs/src/app/rsc/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { registerApolloClient } from "@apollo/experimental-nextjs-app-support/rs
import { loadErrorMessages, loadDevMessages } from "@apollo/client/dev";
import { setVerbosity } from "ts-invariant";
import { delayLink } from "@/shared/delayLink";
import { errorLink } from "@/shared/errorLink";
import { SchemaLink } from "@apollo/client/link/schema";

import { schema } from "../graphql/schema";
Expand All @@ -15,12 +16,6 @@ loadErrorMessages();
export const { getClient } = registerApolloClient(() => {
return new ApolloClient({
cache: new InMemoryCache(),
link: delayLink.concat(
typeof window === "undefined"
? new SchemaLink({ schema })
: new HttpLink({
uri: "/graphql",
})
),
link: delayLink.concat(errorLink.concat(new SchemaLink({ schema }))),
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use client";

import { useSuspenseQuery } from "@apollo/client";
import { QUERY } from "./shared";

export function ClientChild() {
const { data } = useSuspenseQuery(QUERY, { context: { error: "always" } });
return (
<ul>
{data.products.map(({ id, title }) => (
<li key={id}>{title}</li>
))}
</ul>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { expect } from "@playwright/test";
import { test } from "../../../../../fixture";

test.describe("PreloadQuery", () => {
test("query resolves on the server", async ({ page, blockRequest }) => {
await page.goto(
"http://localhost:3000/rsc/dynamic/PreloadQuery?errorIn=ssr,browser",
{
waitUntil: "commit",
}
);

await expect(page).toBeInitiallyLoading(true);
await expect(page.getByText("loading")).not.toBeVisible();
await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});

test("query errors on the server, restarts in the browser", async ({
page,
}) => {
page.allowErrors?.();
await page.goto(
"http://localhost:3000/rsc/dynamic/PreloadQuery?errorIn=rsc",
{
waitUntil: "commit",
}
);

await expect(page).toBeInitiallyLoading(true);

await page.waitForEvent("pageerror", (error) => {
return (
/* prod */ error.message.includes("Minified React error #419") ||
/* dev */ error.message.includes("Query failed upstream.")
);
});

await expect(page.getByText("loading")).not.toBeVisible();
await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});
});
29 changes: 29 additions & 0 deletions integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { ApolloWrapper } from "@/app/cc/ApolloWrapper";
import { PreloadQuery } from "@apollo/client-react-streaming";
import { ClientChild } from "./ClientChild";
import { QUERY } from "./shared";

export const dynamic = "force-dynamic";
import { getClient } from "../../client";
import { Suspense } from "react";

export default function Page({ searchParams }: { searchParams?: any }) {
return (
<ApolloWrapper>
<PreloadQuery
options={{
query: QUERY,
context: {
delay: 1000,
error: searchParams?.errorIn || undefined,
},
}}
getClient={getClient}
>
<Suspense fallback={<>loading</>}>
<ClientChild />
</Suspense>
</PreloadQuery>
</ApolloWrapper>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { TypedDocumentNode, gql } from "@apollo/client";

export const QUERY: TypedDocumentNode<{
products: {
id: string;
title: string;
}[];
}> = gql`
query dynamicProducts {
products {
id
title
}
}
`;
6 changes: 6 additions & 0 deletions integration-test/nextjs/src/shared/delayLink.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { ApolloLink, Observable } from "@apollo/client";

declare module "@apollo/client" {
export interface DefaultContext {
delay?: number;
}
}

export const delayLink = new ApolloLink((operation, forward) => {
if (operation.operationName?.includes("dynamic")) {
operation.setContext({
Expand Down
30 changes: 30 additions & 0 deletions integration-test/nextjs/src/shared/errorLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ApolloLink, Observable } from "@apollo/client";
import { GraphQLError } from "graphql";
import * as entryPoint from "@apollo/client-react-streaming";

declare module "@apollo/client" {
type Env = "ssr" | "browser" | "rsc";
export interface DefaultContext {
error?: "always" | Env | `${Env},${Env}`;
}
}

export const errorLink = new ApolloLink((operation, forward) => {
const context = operation.getContext();
if (
context.error === "always" ||
("built_for_ssr" in entryPoint &&
context.error?.split(",").includes("ssr")) ||
("built_for_browser" in entryPoint &&
context.error?.split(",").includes("browser")) ||
("built_for_rsc" in entryPoint && context.error?.split(",").includes("rsc"))
) {
return new Observable((subscriber) => {
subscriber.next({
data: null,
errors: [new GraphQLError("Simulated error")],
});
});
}
return forward(operation);
});
2 changes: 1 addition & 1 deletion integration-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"*"
],
"scripts": {
"trigger-rebuild": "find . -regextype posix-extended -regex '.*/node_modules/@apollo/(client-react-streaming|experimental-nextjs-app-support)' -printf 'rm -r %p\n' -exec rm -r {} +; glob \"../.yarn/cache/@apollo-*exec*\" \"$HOME/.yarn/berry/cache/@apollo-*exec*\" --cmd='rm -v' ; yarn"
"trigger:rebuild": "find . -regextype posix-extended -regex '.*/node_modules/@apollo/(client-react-streaming|experimental-nextjs-app-support)' -printf 'rm -r %p\n' -exec rm -r {} +; glob \"../.yarn/cache/@apollo-*exec*\" \"$HOME/.yarn/berry/cache/@apollo-*exec*\" --cmd='rm -v' ; yarn"
},
"devDependencies": {
"glob": "^10.3.10"
Expand Down
10 changes: 5 additions & 5 deletions integration-test/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ __metadata:
linkType: hard

"@apollo/client-react-streaming@exec:./shared/build-client-react-streaming.cjs::locator=%40integration-test%2Froot%40workspace%3A.":
version: 0.8.0
version: 0.9.2
resolution: "@apollo/client-react-streaming@exec:./shared/build-client-react-streaming.cjs#./shared/build-client-react-streaming.cjs::hash=48b117&locator=%40integration-test%2Froot%40workspace%3A."
dependencies:
superjson: "npm:^1.12.2 || ^2.0.0"
ts-invariant: "npm:^0.10.3"
peerDependencies:
"@apollo/client": ^3.9.0
"@apollo/client": ^3.9.6
react: ^18
checksum: 10/8e12155ebcb9672f5b645c364d356018014df750412c61613341121ebb4d4eabb5f42cd9018cc3a81ad988f1b425548d68254ca49ede19c31d0d9e5a9a4f240a
languageName: node
Expand Down Expand Up @@ -82,12 +82,12 @@ __metadata:
linkType: hard

"@apollo/experimental-nextjs-app-support@exec:./shared/build-experimental-nextjs-app-support.cjs::locator=%40integration-test%2Froot%40workspace%3A.":
version: 0.8.0
version: 0.9.2
resolution: "@apollo/experimental-nextjs-app-support@exec:./shared/build-experimental-nextjs-app-support.cjs#./shared/build-experimental-nextjs-app-support.cjs::hash=fd83cc&locator=%40integration-test%2Froot%40workspace%3A."
dependencies:
"@apollo/client-react-streaming": "npm:^0.9.0"
"@apollo/client-react-streaming": "npm:0.9.2"
peerDependencies:
"@apollo/client": ^3.9.0
"@apollo/client": ^3.9.6
next: ^13.4.1 || ^14.0.0
react: ^18
checksum: 10/505b723bac0f3a7f15287ea32fab9f2e8c0cd567149abf11d750855f8a9bfc0aa26e44179ad10c32f7d162ad86318717032413ef8e1a25385185178e022588fa
Expand Down
Loading

0 comments on commit e8057fc

Please sign in to comment.