Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 3 additions & 1 deletion .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ jobs:
cache: pnpm
- name: Install dependencies
run: pnpm install --ignore-scripts --frozen-lockfile --filter nuqs...
- name: Install Playwright Chromium
run: pnpm exec playwright install chromium --with-deps
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: It looks like this step fails:

  pnpm exec playwright install chromium --with-deps
  shell: /usr/bin/bash -e {0}
  env:
    FORCE_COLOR: 3
    PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin
undefined
 ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL  Command "playwright" not found
Error: Process completed with exit code 254.

https://github.com/47ng/nuqs/actions/runs/19972510720/job/57284417778?pr=1254#step:6:9

Do we need to add playwright as a devDependency?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes we do, I'ma fix that

Copy link
Contributor Author

@ntatoud ntatoud Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added it in the pnpm e2e catalog like cypress since you intend to migrate to it anyway.
I also removed jsdom that was still hanging there

- name: Run tests
run: pnpm run test ${{ github.event_name == 'workflow_dispatch' && '--force' || '' }} --filter nuqs
env:
Expand Down Expand Up @@ -141,7 +143,7 @@ jobs:
- "14.2.0"
# - '14.2.3' # before vercel/next.js#66755
- "14.2.4" # after vercel/next.js#66755
# - '14.2.7' # before vercel/next.js#69509
# - "14.2.7" # before vercel/next.js#69509
- "14.2.8" # after vercel/next.js#69509
- "15.0.0"
- "15.1.0"
Expand Down
1 change: 1 addition & 0 deletions packages/nuqs/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
size.json
src/__screenshots__
14 changes: 7 additions & 7 deletions packages/nuqs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@
"build": "tsdown",
"build:size-json": "size-limit --json > size.json",
"test": "pnpm run --stream '/^test:/'",
"test:unit": "vitest run --typecheck",
"test:unit": "vitest run --project unit",
"test:browser": "vitest run --project browser --browser.headless",
"test:types": "vitest run --project types",
"test:size": "size-limit",
"prepack": "./scripts/prepack.sh"
},
Expand Down Expand Up @@ -168,15 +170,12 @@
"devDependencies": {
"@remix-run/react": "^2.17.0",
"@size-limit/preset-small-lib": "^11.2.0",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^24.3.0",
"@types/react": "catalog:react19",
"@types/react-dom": "catalog:react19",
"@vitejs/plugin-react": "^5.0.4",
"@vitest/coverage-v8": "^4.0.1",
"@vitest/browser-playwright": "^4.0.15",
"@vitest/coverage-v8": "^4.0.15",
"arktype": "^2.1.20",
"fast-check": "^4.2.0",
"jsdom": "^27.0.1",
Expand All @@ -188,7 +187,8 @@
"tsdown": "^0.15.9",
"typescript": "^5.9.2",
"valibot": "^1.2.0",
"vitest": "^4.0.1",
"vitest": "^4.0.15",
"vitest-browser-react": "2.0.2",
"vitest-package-exports": "^0.1.1",
"zod": "^4.1.5"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { describe, expect, it, vi } from 'vitest'
import { describe, expect, it } from 'vitest'
import { getSearchParams } from './patch-history'

describe('patch-history/getSearchParams', () => {
Expand All @@ -13,7 +13,6 @@ describe('patch-history/getSearchParams', () => {
expect(received).toEqual(expected)
})
it('extracts search params from a pathname', () => {
vi.stubGlobal('location', { origin: 'http://example.com' })
const received = getSearchParams('/?foo=bar')
const expected = new URLSearchParams('?foo=bar')
expect(received).toEqual(expected)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import { act, renderHook } from '@testing-library/react'
import { useRef } from 'react'
import { describe, expect, it } from 'vitest'
import { renderHook } from 'vitest-browser-react'
import { createEmitter } from '../emitter'
import { useSyncExternalStores } from './useSyncExternalStores'

describe('useSyncExternalStores', () => {
it('should handle an empty array of keys', () => {
it('should handle an empty array of keys', async () => {
const useTest = () =>
useSyncExternalStores(
[],
(_, callback) => callback,
_ => 'snapshot'
)
const { result } = renderHook(useTest)
const { result } = await renderHook(useTest)
expect(result.current).toEqual({})
})
it('should handle a single key', () => {
it('should handle a single key', async () => {
const useTest = () =>
useSyncExternalStores(
['a'],
(_, callback) => callback,
_ => 'snapshot'
)
const { result } = renderHook(useTest)
const { result } = await renderHook(useTest)
expect(result.current).toEqual({ a: 'snapshot' })
})
it('should be reactive to changes in the store', () => {
it('should be reactive to changes in the store', async () => {
const emitter = createEmitter()
const store: Record<string, number> = {
a: 0
Expand All @@ -39,7 +39,7 @@ describe('useSyncExternalStores', () => {
},
key => store[key]
)
const { result } = renderHook(useTest)
const { result, act } = await renderHook(useTest)
expect(result.current).toEqual({ a: 0 })
// Update the store
act(() => {
Expand All @@ -48,7 +48,7 @@ describe('useSyncExternalStores', () => {
})
expect(result.current).toEqual({ a: 1 })
})
it('should be reactive to changes in the keys', () => {
it('should be reactive to changes in the keys', async () => {
const emitter = createEmitter()
const store: Record<string, number> = {
a: 0,
Expand All @@ -63,12 +63,12 @@ describe('useSyncExternalStores', () => {
},
key => store[key]
)
const { result, rerender } = renderHook(useTest)
const { result, rerender } = await renderHook(useTest)
expect(result.current).toEqual({ a: 0 })
rerender({ keys: ['b'] })
expect(result.current).toEqual({ b: 0 })
})
it('should not re-render when a non-listened key changes', () => {
it('should not re-render when a non-listened key changes', async () => {
const emitter = createEmitter()
const store: Record<string, number> = {
a: 0,
Expand All @@ -89,7 +89,7 @@ describe('useSyncExternalStores', () => {
result
}
}
const { result } = renderHook(useTest)
const { result, act } = await renderHook(useTest)
expect(result.current.result).toEqual({ a: 0 })
expect(result.current.renderCount).toBe(1)
// Update another key
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import React from 'react'
import { describe, expect, it } from 'vitest'
import { page, userEvent } from 'vitest/browser'
import { withNuqsTestingAdapter } from '../adapters/testing'
import { parseAsInteger, useQueryState, useQueryStates } from '../index'
import { render } from 'vitest-browser-react'

type TestComponentProps = {
testId: string
Expand All @@ -24,7 +24,7 @@ describe('sync', () => {
}

const user = userEvent.setup()
render(
await render(
<>
<TestComponent testId="a" />
<TestComponent testId="b" />
Expand All @@ -34,14 +34,14 @@ describe('sync', () => {
}
)
// Act
const buttonA = screen.getByTestId('a')
const buttonB = screen.getByTestId('b')
const buttonA = page.getByTestId('a')
const buttonB = page.getByTestId('b')
await user.click(buttonA)
expect(buttonA).toHaveTextContent('count is 1')
expect(buttonB).toHaveTextContent('count is 1')
await expect.element(buttonA).toHaveTextContent('count is 1')
await expect.element(buttonB).toHaveTextContent('count is 1')
await user.click(buttonB)
expect(buttonA).toHaveTextContent('count is 2')
expect(buttonB).toHaveTextContent('count is 2')
await expect.element(buttonA).toHaveTextContent('count is 2')
await expect.element(buttonB).toHaveTextContent('count is 2')
})

it('should sync useQueryState and useQueryStates', async () => {
Expand Down Expand Up @@ -71,7 +71,7 @@ describe('sync', () => {
}

const user = userEvent.setup()
render(
await render(
<>
<TestComponentA testId="a" />
<TestComponentB testId="b" />
Expand All @@ -81,13 +81,13 @@ describe('sync', () => {
}
)
// Act
const buttonA = screen.getByTestId('a')
const buttonB = screen.getByTestId('b')
const buttonA = page.getByTestId('a')
const buttonB = page.getByTestId('b')
await user.click(buttonA)
expect(buttonA).toHaveTextContent('count is 1')
expect(buttonB).toHaveTextContent('count is 1')
await expect.element(buttonA).toHaveTextContent('count is 1')
await expect.element(buttonB).toHaveTextContent('count is 1')
await user.click(buttonB)
expect(buttonA).toHaveTextContent('count is 2')
expect(buttonB).toHaveTextContent('count is 2')
await expect.element(buttonA).toHaveTextContent('count is 2')
await expect.element(buttonB).toHaveTextContent('count is 2')
})
})
Loading
Loading