Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,42 @@
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

e2e-waku:
name: E2E (waku)
runs-on: ubuntu-22.04-arm
needs: [ci-core]
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version-file: .node-version
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile --filter e2e-waku...
- name: Run tests
run: pnpm run test ${{ github.event_name == 'workflow_dispatch' && '--force' || '' }} --filter e2e-waku
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
E2E_NO_CACHE_ON_RERUN: ${{ github.run_attempt }}
- name: Save Playwright report
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
if: failure()
with:
path: packages/e2e/waku/.playwright/*
name: playwright-waku
include-hidden-files: true
- uses: 47ng/actions-slack-notify@main
name: Notify on Slack
if: failure()
with:
status: ${{ job.status }}
jobName: waku
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

ci-notify:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
name: Notify on Slack
runs-on: ubuntu-24.04-arm
needs:
Expand All @@ -378,6 +413,7 @@
- e2e-react-router
- e2e-remix
- e2e-tanstack-router
- e2e-waku
steps:
- uses: 47ng/actions-slack-notify@main
with:
Expand Down Expand Up @@ -405,6 +441,7 @@
- e2e-react-router
- e2e-remix
- e2e-tanstack-router
- e2e-waku
if: ${{ github.ref_name == 'master' || github.ref_name == 'beta' }}
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ When running `next dev`, this will:
- http://localhost:3005 - [React Router v5](./packages/e2e/react-router/v5)
- http://localhost:3006 - [React Router v6](./packages/e2e/react-router/v6)
- http://localhost:3007 - [React Router v7](./packages/e2e/react-router/v7)
- http://localhost:3008 - [Waku](./packages/e2e/waku)
- Start the examples:
- http://localhost:4000 - [tRPC](./packages/examples/trpc)
- http://localhost:4001 - [Next.js - App router](./packages/examples/next-app)
Expand Down
4 changes: 3 additions & 1 deletion packages/e2e/shared/define-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type TestConfig = {
| 'react-router-v7'
| 'remix'
| 'tanstack-router'
| 'waku'
description?: string
}

Expand All @@ -21,7 +22,8 @@ const routerDisplay: Record<NonNullable<TestConfig['router']>, string> = {
'react-router-v6': 'React Router v6',
'react-router-v7': 'React Router v7',
remix: 'Remix',
'tanstack-router': 'TanStack Router'
'tanstack-router': 'TanStack Router',
waku: 'Waku'
}

export function defineTest(
Expand Down
9 changes: 9 additions & 0 deletions packages/e2e/waku/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
node_modules
dist
.env*
*.tsbuildinfo
.cache
.DS_Store
*.pem
src/pages.gen.ts
.playwright/
29 changes: 29 additions & 0 deletions packages/e2e/waku/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "e2e-waku",
"version": "0.0.0",
"type": "module",
"private": true,
"scripts": {
"dev": "waku dev --port 3008",
"build": "waku build",
"start": "waku start --port 3008",
"pretest": "playwright install chromium",
"test": "playwright test --project=chromium"
},
"dependencies": {
"nuqs": "workspace:*",
"react": "catalog:react19",
"react-dom": "catalog:react19",
"react-server-dom-webpack": "catalog:react19",
"waku": "1.0.0-alpha.0"
},
"devDependencies": {
"@playwright/test": "catalog:e2e",
"@types/react": "catalog:react19",
"@types/react-dom": "catalog:react19",
"@vitejs/plugin-react": "^5.1.0",
"babel-plugin-react-compiler": "^1.0.0",
"e2e-shared": "workspace:*",
"typescript": "^5.9.3"
}
}
6 changes: 6 additions & 0 deletions packages/e2e/waku/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { configurePlaywright } from 'e2e-shared/playwright.config.ts'

export default configurePlaywright({
startCommand: 'pnpm run start',
port: 3008
})
3 changes: 3 additions & 0 deletions packages/e2e/waku/specs/shared.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { runSharedTests } from 'e2e-shared/shared.spec.ts'

runSharedTests()
40 changes: 40 additions & 0 deletions packages/e2e/waku/src/lib/nuqs-waku-adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use client'

import {
unstable_createAdapterProvider as createAdapterProvider,
renderQueryString,
unstable_UpdateUrlFunction as UpdateUrlFunction
} from 'nuqs/adapters/custom'
import { useCallback } from 'react'
import { useRouter } from 'waku'

function useNuqsAdapter() {
const { path, query, push, replace } = useRouter()
const searchParams = new URLSearchParams(query)
const updateUrl = useCallback<UpdateUrlFunction>(
(search, options) => {
const query = renderQueryString(search)
const url = path + query + location.hash
if (options.shallow) {
options.history === 'push'
? history.pushState(null, '', url)
: history.replaceState(null, '', url)
} else {
const updateMethod = options.history === 'push' ? push : replace
// bypass waku's typesafe route check by using `as never`
updateMethod(url as never)
}
// Waku router does not scroll unless the pathname changes
if (options.scroll) {
window.scrollTo(0, 0)
}
},
[path, push, replace]
)
return {
searchParams,
updateUrl
}
}

export const NuqsAdapter = createAdapterProvider(useNuqsAdapter)
42 changes: 42 additions & 0 deletions packages/e2e/waku/src/lib/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client'

import { HydrationMarker } from 'e2e-shared/components/hydration-marker'
import { LinkProps, LinkProvider } from 'e2e-shared/components/link'
import { RouterProvider } from 'e2e-shared/components/router'
import type { ReactNode } from 'react'
import { Link as WakuLink, useRouter as useWakuRouter } from 'waku'

function Link(props: LinkProps) {
return (
<WakuLink
// @ts-expect-error Waku is type-safe, but our LinkProps abstraction is not
to={props.href}
{...props}
/>
)
}

export function Providers({ children }: { children: ReactNode }) {
const router = useWakuRouter()
return (
<>
<HydrationMarker />
<LinkProvider Link={Link}>
<RouterProvider
useRouter={() => ({
push(url) {
// @ts-expect-error Waku is type-safe, but our router abstraction is not
return router.push(url)
},
replace(url) {
// @ts-expect-error Waku is type-safe, but our router abstraction is not
return router.replace(url)
}
})}
>
{children}
</RouterProvider>
</LinkProvider>
</>
)
}
19 changes: 19 additions & 0 deletions packages/e2e/waku/src/pages/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { ReactNode } from 'react'
import { NuqsAdapter } from '../lib/nuqs-waku-adapter'
import { Providers } from '../lib/providers'

type RootLayoutProps = { children: ReactNode }

export default function RootLayout({ children }: RootLayoutProps) {
return (
<NuqsAdapter>
<Providers>{children}</Providers>
</NuqsAdapter>
)
}

export const getConfig = async () => {
return {
render: 'static'
} as const
}
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/basic-io/useQueryState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { UseQueryStateBasicIO } from 'e2e-shared/specs/basic-io'

export default UseQueryStateBasicIO
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/basic-io/useQueryStates.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { UseQueryStatesBasicIO } from 'e2e-shared/specs/basic-io'

export default UseQueryStatesBasicIO
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ConditionalRenderingUseQueryState } from 'e2e-shared/specs/conditional-rendering'

export default ConditionalRenderingUseQueryState
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ConditionalRenderingUseQueryStates } from 'e2e-shared/specs/conditional-rendering'

export default ConditionalRenderingUseQueryStates
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/form/useQueryState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TestFormUseQueryState } from 'e2e-shared/specs/form'

export default TestFormUseQueryState
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/form/useQueryStates.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { TestFormUseQueryStates } from 'e2e-shared/specs/form'

export default TestFormUseQueryStates
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/hash-preservation/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { HashPreservation } from 'e2e-shared/specs/hash-preservation'

export default HashPreservation
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/json.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Json } from 'e2e-shared/specs/json'

export default Json
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/life-and-death.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { LifeAndDeath } from 'e2e-shared/specs/life-and-death'

export default LifeAndDeath
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/linking/useQueryState/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { LinkingUseQueryState } from 'e2e-shared/specs/linking'

export default function Page() {
return <LinkingUseQueryState path="/linking/useQueryState" />
}
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/linking/useQueryState/other.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { LinkingUseQueryState } from 'e2e-shared/specs/linking'

export default function Page() {
return <LinkingUseQueryState path="/linking/useQueryState" />
}
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/linking/useQueryStates/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { LinkingUseQueryStates } from 'e2e-shared/specs/linking'

export default function Page() {
return <LinkingUseQueryStates path="/linking/useQueryStates" />
}
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/linking/useQueryStates/other.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { LinkingUseQueryStates } from 'e2e-shared/specs/linking'

export default function Page() {
return <LinkingUseQueryStates path="/linking/useQueryStates" />
}
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/native-array.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { NativeArray } from 'e2e-shared/specs/native-array'

export default NativeArray
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/pretty-urls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { PrettyUrls } from 'e2e-shared/specs/pretty-urls'

export default PrettyUrls
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ReferentialStabilityUseQueryState } from 'e2e-shared/specs/referential-stability'

export default ReferentialStabilityUseQueryState
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ReferentialStabilityUseQueryStates } from 'e2e-shared/specs/referential-stability'

export default ReferentialStabilityUseQueryStates
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/routing/useQueryState/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RoutingUseQueryState } from 'e2e-shared/specs/routing'

export default function Page() {
return <RoutingUseQueryState path="/routing/useQueryState" />
}
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/routing/useQueryState/other.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RoutingUseQueryState } from 'e2e-shared/specs/routing'

export default function Page() {
return <RoutingUseQueryState path="/routing/useQueryState" />
}
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/routing/useQueryStates/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RoutingUseQueryStates } from 'e2e-shared/specs/routing'

export default function Page() {
return <RoutingUseQueryStates path="/routing/useQueryStates" />
}
5 changes: 5 additions & 0 deletions packages/e2e/waku/src/pages/routing/useQueryStates/other.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RoutingUseQueryStates } from 'e2e-shared/specs/routing'

export default function Page() {
return <RoutingUseQueryStates path="/routing/useQueryStates" />
}
3 changes: 3 additions & 0 deletions packages/e2e/waku/src/pages/scroll.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Scroll } from 'e2e-shared/specs/scroll'

export default Scroll
18 changes: 18 additions & 0 deletions packages/e2e/waku/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strict": true,
"target": "esnext",
"noEmit": true,
"isolatedModules": true,
"moduleDetection": "force",
"downlevelIteration": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"jsx": "react-jsx"
}
}
14 changes: 14 additions & 0 deletions packages/e2e/waku/waku.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import react from '@vitejs/plugin-react'
import { defineConfig } from 'waku/config'

export default defineConfig({
vite: {
plugins: [
react({
babel: {
plugins: ['babel-plugin-react-compiler']
}
})
]
}
})
Loading
Loading