Skip to content

Commit

Permalink
restart simulated streamed request on stream close (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
phryneas authored Jul 24, 2023
1 parent 0860926 commit 2a21911
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 71 deletions.
1 change: 0 additions & 1 deletion integration-test/fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ expect.extend({
});

export const test = base.extend<{
withHar: import("@playwright/test").Page;
blockRequest: import("@playwright/test").Page;
}>({
page: async ({ page }, use) => {
Expand Down
42 changes: 0 additions & 42 deletions integration-test/src/app/cc/dynamic/apollo-client.test.ts

This file was deleted.

62 changes: 62 additions & 0 deletions integration-test/src/app/cc/dynamic/dynamic.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { expect } from "@playwright/test";
import { test } from "../../../../fixture";

test.describe("CC dynamic", () => {
test.describe("useSuspenseQuery", () => {
test("one query", async ({ page, blockRequest }) => {
await page.goto("http://localhost:3000/cc/dynamic/useSuspenseQuery", {
waitUntil: "commit",
});

await expect(page).toBeInitiallyLoading(false);
await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});
});
test.describe("useBackgroundQuery", () => {
test("one query", async ({ page, blockRequest }) => {
await page.goto("http://localhost:3000/cc/dynamic/useBackgroundQuery", {
waitUntil: "commit",
});

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

// this will close the connection before the final result is received, so it can never be forwarded
test("no `useReadQuery` on the server", async ({ page }) => {
await page.goto(
"http://localhost:3000/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery",
{
waitUntil: "commit",
}
);

await expect(page.getByText("rendered on server")).toBeVisible();
await expect(page.getByText("rendered on client")).toBeVisible();
await expect(page.getByText("loading")).toBeVisible();
await expect(page.getByText("loading")).not.toBeVisible();
await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});
});
test.describe("useQuery", () => {
test("without cache value", async ({ page }) => {
await page.goto("http://localhost:3000/cc/dynamic/useQuery", {
waitUntil: "commit",
});

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

test("with cache value", async ({ page }) => {
await page.goto("http://localhost:3000/cc/dynamic/useQueryWithCache", {
waitUntil: "commit",
});

await expect(page).toBeInitiallyLoading(false);
await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use client";

import {
useBackgroundQuery,
useReadQuery,
} from "@apollo/experimental-nextjs-app-support/ssr";
import type { TypedDocumentNode } from "@apollo/client";
import { gql, QueryReference } from "@apollo/client";
import { Suspense, useState, useEffect } from "react";

interface Data {
products: {
id: string;
title: string;
}[];
}

const QUERY: TypedDocumentNode<Data> = gql`
query dynamicProducts {
products {
id
title
}
}
`;

export const dynamic = "force-dynamic";

export default function Page() {
const [queryRef] = useBackgroundQuery(QUERY, { context: { delay: 2000 } });
const [isClient, setIsClient] = useState(false);
useEffect(() => setIsClient(true), []);
return (
<>
{isClient ? "rendered on client" : "rendered on server"}
<Suspense fallback={<p>loading</p>}>
{isClient ? <DisplayData queryRef={queryRef} /> : null}
</Suspense>
</>
);
}

function DisplayData({ queryRef }: { queryRef: QueryReference<Data> }) {
const { data } = useReadQuery(queryRef);
return (
<ul>
{data.products.map(({ id, title }) => (
<li key={id}>{title}</li>
))}
</ul>
);
}
12 changes: 0 additions & 12 deletions integration-test/src/app/cc/static/apollo-client.test.ts

This file was deleted.

32 changes: 32 additions & 0 deletions integration-test/src/app/cc/static/static.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect } from "@playwright/test";
import { test } from "../../../../fixture";

test.describe("CC static", () => {
test.describe("useSuspenseQuery", () => {
test("one query", async ({ page, blockRequest }) => {
await page.goto("http://localhost:3000/cc/static/useSuspenseQuery", {
waitUntil: "commit",
});

await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});
});

test.describe("useBackgroundQuery", () => {
// this will close the connection before the final result is received, so it can never be forwarded
test("no `useReadQuery` on the server", async ({ page }) => {
await page.goto(
"http://localhost:3000/cc/static/useBackgroundQueryWithoutSsrReadQuery",
{
waitUntil: "commit",
}
);

await expect(page.getByText("rendered on server")).toBeVisible();
await expect(page.getByText("rendered on client")).toBeVisible();
await expect(page.getByText("loading")).toBeVisible();
await expect(page.getByText("loading")).not.toBeVisible();
await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client";

import {
useBackgroundQuery,
useReadQuery,
} from "@apollo/experimental-nextjs-app-support/ssr";
import type { TypedDocumentNode } from "@apollo/client";
import { gql, QueryReference } from "@apollo/client";
import { Suspense, useState, useEffect } from "react";

interface Data {
products: {
id: string;
title: string;
}[];
}

const QUERY: TypedDocumentNode<Data> = gql`
query dynamicProducts {
products {
id
title
}
}
`;

export default function Page() {
const [queryRef] = useBackgroundQuery(QUERY, { context: { delay: 2000 } });
const [isClient, setIsClient] = useState(false);
useEffect(() => setIsClient(true), []);
return (
<>
{isClient ? "rendered on client" : "rendered on server"}
<Suspense fallback={<p>loading</p>}>
{isClient ? <DisplayData queryRef={queryRef} /> : null}
</Suspense>
</>
);
}

function DisplayData({ queryRef }: { queryRef: QueryReference<Data> }) {
const { data } = useReadQuery(queryRef);
return (
<ul>
{data.products.map(({ id, title }) => (
<li key={id}>{title}</li>
))}
</ul>
);
}
2 changes: 1 addition & 1 deletion integration-test/src/shared/delayLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const delayLink = new ApolloLink((operation, forward) => {
return new Observable((observer) => {
const timeout = setTimeout(() => {
forward(operation).subscribe(observer);
}, 1500);
}, operation.getContext().delay ?? 1500);
return () => clearTimeout(timeout);
});
});
Loading

0 comments on commit 2a21911

Please sign in to comment.