Skip to content

Commit

Permalink
add parallel route and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
khuezy committed Aug 22, 2023
1 parent b60bed5 commit 8499e25
Show file tree
Hide file tree
Showing 13 changed files with 149 additions and 17 deletions.
4 changes: 3 additions & 1 deletion example/.sst/outputs.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"frank-example-Site": {}
}
3 changes: 3 additions & 0 deletions packages/app-dir/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export default function Home() {
<Nav href={"/api"} title='API'>
Calls an API endpoint defined in app/api/hello/route and middleware
</Nav>
<Nav href={"/parallel"} title='Parallel'>
Parallel routing
</Nav>
</main>
</>
)
Expand Down
3 changes: 3 additions & 0 deletions packages/app-dir/app/parallel/@a/a-page/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function APage() {
return <div>A Page</div>
}
9 changes: 9 additions & 0 deletions packages/app-dir/app/parallel/@a/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Link from "next/link";

export default function A() {
return <div className="border p-4">
<h1>Parallel Route A</h1>
<Link href="/parallel/a-page">Go to a-page</Link>

</div>
}
3 changes: 3 additions & 0 deletions packages/app-dir/app/parallel/@b/b-page/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function BPage() {
return <div>B Page</div>
}
9 changes: 9 additions & 0 deletions packages/app-dir/app/parallel/@b/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Link from "next/link";

export default function B() {
return <div className="border p-4">
<h1>Parallel Route B</h1>

<Link href="/parallel/b-page">Go to b-page</Link>
</div>
}
29 changes: 29 additions & 0 deletions packages/app-dir/app/parallel/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client'
import { ReactNode, useState } from "react";

export default function Layout({ a, b, children }: { children: ReactNode, a: ReactNode, b: ReactNode }) {
const [routeA, setRouteA] = useState(false)
const [routeB, setRouteB] = useState(false)

return <div>

<div className="flex flex-col mb-10">
<label htmlFor="a">
Enable A
<input name="a" type="checkbox" checked={routeA} onChange={(e) => {
setRouteA(e.target.checked)
}} />
</label>
<label htmlFor="b">
Enable B
<input name="b" type="checkbox" checked={routeB} onChange={(e) => {
setRouteB(e.target.checked)
}} />
</label>
</div>

{routeA && a}
{routeB && b}
{/* {children} */}
</div>
}
3 changes: 3 additions & 0 deletions packages/app-dir/app/parallel/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Page() {
return null
}
4 changes: 3 additions & 1 deletion packages/core/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export async function getSongs() {

export async function getSong(album: string, title: string) {
return data.songs.find(
(song) => song.album === decodeURIComponent(album) && song.title === decodeURIComponent(title)
(song) =>
song.album === decodeURIComponent(album) &&
song.title === decodeURIComponent(title)
);
}
1 change: 1 addition & 0 deletions packages/core/sst-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference path="../../example/.sst/types/index.ts" />
52 changes: 39 additions & 13 deletions packages/open-next/src/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export async function build(opts: BuildOptions = {}) {
// Initialize options
options = normalizeOptions(opts);

console.log("~~hi");
// Pre-build validation
checkRunningInsideNextjsApp();
printNextjsVersion();
Expand Down Expand Up @@ -131,7 +130,8 @@ function setStandaloneBuildMode(monorepoRoot: string) {
function buildNextjsApp(packager: "npm" | "yarn" | "pnpm") {
const { appPath } = options;
const command =
options.buildCommand ?? (packager === "npm" ? "npm run build" : `${packager} build`);
options.buildCommand ??
(packager === "npm" ? "npm run build" : `${packager} build`);
cp.execSync(command, {
stdio: "inherit",
cwd: appPath,
Expand All @@ -155,7 +155,10 @@ function printNextjsVersion() {
const { appPath } = options;
cp.spawnSync(
"node",
["-e", `"console.info('Next.js v' + require('next/package.json').version)"`],
[
"-e",
`"console.info('Next.js v' + require('next/package.json').version)"`,
],
{
stdio: "inherit",
cwd: appPath,
Expand Down Expand Up @@ -248,7 +251,9 @@ function createImageOptimizationBundle() {
// "@aws-sdk/client-s3" package which is not a dependency in user's
// Next.js app.
esbuildSync({
entryPoints: [path.join(__dirname, "adapters", "image-optimization-adapter.js")],
entryPoints: [
path.join(__dirname, "adapters", "image-optimization-adapter.js"),
],
external: ["sharp", "next"],
outfile: path.join(outputPath, "index.mjs"),
});
Expand Down Expand Up @@ -301,10 +306,17 @@ function createStaticAssets() {
// - .next/BUILD_ID => _next/BUILD_ID
// - .next/static => _next/static
// - public/* => *
fs.copyFileSync(path.join(appPath, ".next/BUILD_ID"), path.join(outputPath, "BUILD_ID"));
fs.cpSync(path.join(appPath, ".next/static"), path.join(outputPath, "_next", "static"), {
recursive: true,
});
fs.copyFileSync(
path.join(appPath, ".next/BUILD_ID"),
path.join(outputPath, "BUILD_ID")
);
fs.cpSync(
path.join(appPath, ".next/static"),
path.join(outputPath, "_next", "static"),
{
recursive: true,
}
);
if (fs.existsSync(appPublicPath)) {
fs.cpSync(appPublicPath, outputPath, { recursive: true });
}
Expand Down Expand Up @@ -478,7 +490,10 @@ function addPublicFilesList(outputPath: string, packagePath: string) {
// Save the list
const outputOpenNextPath = path.join(outputPath, packagePath, ".open-next");
fs.mkdirSync(outputOpenNextPath, { recursive: true });
fs.writeFileSync(path.join(outputOpenNextPath, "public-files.json"), JSON.stringify(acc));
fs.writeFileSync(
path.join(outputOpenNextPath, "public-files.json"),
JSON.stringify(acc)
);
}

function removeCachedPages(outputPath: string, packagePath: string) {
Expand Down Expand Up @@ -532,14 +547,20 @@ function esbuildSync(esbuildOptions: ESBuildOptions) {
// "process.env.OPEN_NEXT_DEBUG" determines if the logger writes to console.log
define: {
...esbuildOptions.define,
"process.env.OPEN_NEXT_DEBUG": process.env.OPEN_NEXT_DEBUG ? "true" : "false",
"process.env.OPEN_NEXT_DEBUG": process.env.OPEN_NEXT_DEBUG
? "true"
: "false",
"process.env.OPEN_NEXT_VERSION": `"${openNextVersion}"`,
},
});

if (result.errors.length > 0) {
result.errors.forEach((error) => console.error(error));
throw new Error(`There was a problem bundling ${(esbuildOptions.entryPoints as string[])[0]}.`);
throw new Error(
`There was a problem bundling ${
(esbuildOptions.entryPoints as string[])[0]
}.`
);
}
}

Expand Down Expand Up @@ -571,7 +592,10 @@ function getHtmlPages(dotNextPath: string) {
// 'csr.html',
// 'image-html-tag.html',
// ])
const manifestPath = path.join(dotNextPath, ".next/server/pages-manifest.json");
const manifestPath = path.join(
dotNextPath,
".next/server/pages-manifest.json"
);
const manifest = fs.readFileSync(manifestPath, "utf-8");
return Object.entries(JSON.parse(manifest))
.filter(([_, value]) => (value as string).endsWith(".html"))
Expand All @@ -583,7 +607,9 @@ function getHtmlPages(dotNextPath: string) {
}

function getBuildId(dotNextPath: string) {
return fs.readFileSync(path.join(dotNextPath, ".next/BUILD_ID"), "utf-8").trim();
return fs
.readFileSync(path.join(dotNextPath, ".next/BUILD_ID"), "utf-8")
.trim();
}

function getOpenNextVersion() {
Expand Down
4 changes: 2 additions & 2 deletions packages/tests-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"version": "0.0.0",
"private": true,
"scripts": {
"e2e:dev": "playwright test",
"e2e:test": "playwright test",
"e2e:dev": "playwright test --retries=5",
"e2e:test": "playwright test --retries=5",
"clean": "rm -rf .turbo && rm -rf node_modules"
},
"dependencies": {
Expand Down
42 changes: 42 additions & 0 deletions packages/tests-e2e/tests/appDirOnly/parallel.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { test, expect } from "@playwright/test";

test("Parallel routes", async ({ page }) => {
await page.goto("/");
await page.getByRole("link", { name: "Parallel" }).click();

await page.waitForURL(`/parallel`);

// Neither are selected, so A/B shouldn't be rendered
let routeA = page.getByText("Parallel Route A");
let routeB = page.getByText("Parallel Route B");
await expect(routeA).not.toBeVisible();
await expect(routeB).not.toBeVisible();

// Enable A, which should be visible but not B
await page.locator('input[name="a"]').check();
routeA = page.getByText("Parallel Route A");
await expect(routeA).toBeVisible();
await expect(routeB).not.toBeVisible();

// Enable B, both should be visible
await page.locator('input[name="b"]').check();
routeB = page.getByText("Parallel Route B");
await expect(routeA).toBeVisible();
await expect(routeB).toBeVisible();

// Click on A, should go to a-page
await page.getByText("Go to a-page").click();
await page.waitForURL("/parallel/a-page");

// Should render contents of a-page
routeA = page.getByText("A Page");
await expect(routeA).toBeVisible();

// Click on B, should go to b-page
await page.getByText("Go to b-page").click();
await page.waitForURL("/parallel/b-page");

// Should render contents of b-page
routeB = page.getByText("B Page");
await expect(routeB).toBeVisible();
});

0 comments on commit 8499e25

Please sign in to comment.