Files
YTandleaysgur b8ba9ae45f fix(formatter): print decorators on rest parameters (#28731)
oxfmt deletes a decorator on a rest parameter. This happens with the
default settings, and oxfmt reports no error.

```ts
class C {
  m(@Dec() ...args: string[]) {}
}

// before
class C {
  m(...args: string[]) {}
}
```

The parser and codegen support these decorators (#18938, #20132), but
the formatter printed only the rest element and its type annotation.
This PR prints the decorators in the same way as for `FormalParameter`.

The new fixture `ts/parameters/rest-decorators.ts` covers single and
multiple decorators, `@(await p)`, a decorator after another parameter,
and long parameter lists. The output matches Prettier 3.9.10 for every
case.

---

AI assistance was used for this change. I reviewed and tested it.

---------

Co-authored-by: leaysgur <6259812+leaysgur@users.noreply.github.com>
2026-11-04 02:08:56 +00:00
..
…

Oxc Formatter Tests

This directory contains snapshot-based tests for the oxc_formatter crate.

Overview

The test infrastructure is designed to be simple and flexible:

  • File-based testing: Just create .{js,jsx,ts,tsx,mjs,cjs,mts,cts} files in the fixtures/ directory
  • Hierarchical options: Configure format options via options.json files at any directory level
  • Automatic discovery: Tests are automatically discovered via build script - no manual registration needed
  • Nested modules: Directory structure becomes module hierarchy, enabling targeted test execution
  • Individual test functions: Each file gets its own test function, visible in cargo test output
  • Snapshot testing: Uses insta for snapshot testing with easy review workflow
  • Co-located snapshots: Snapshots are stored next to test files for easy navigation

Directory Structure

tests/
├── mod.rs                    # Main test runner
└── fixtures/                 # Test input files
    ├── js/                  # JavaScript/JSX tests
    │   ├── options.json     # Shared options for all js tests
    │   ├── arrow-functions.js
    │   ├── arrow-functions.js.snap   # Snapshot file (includes extension)
    │   ├── simple.jsx
    │   ├── simple.jsx.snap
    │   └── nested/
    │       ├── options.json # Overrides parent options
    │       ├── example.js
    │       └── example.js.snap
    └── ts/                  # TypeScript/TSX tests
        ├── generics.ts
        └── generics.ts.snap

Adding New Tests

Simple Test (using default options)

Just create a new file in fixtures/js/ or fixtures/ts/:

# Create a new test file
echo "const foo = bar;" > tests/fixtures/js/my-test.js

# The test is automatically discovered - just run tests
cargo test -p oxc_formatter --test mod

The test function is automatically generated by the build script in the module fixtures::js::my_test. The snapshot will be created as tests/fixtures/js/my-test.js.snap next to your test file.

Test with Custom Options

Create an options.json file in the same directory (or parent directory):

[
  {
    "semi": true,
    "singleQuote": false
  },
  {
    "semi": false,
    "singleQuote": true,
    "printWidth": 120
  }
]

Note: Each object in the array is a separate option set. The options are displayed in the snapshot output.

Nested/Organized Tests

Create subdirectories to organize related tests:

mkdir -p tests/fixtures/js/classes
echo "class Foo {}" > tests/fixtures/js/classes/simple.js

The test will inherit options from the nearest options.json file in the directory tree.

Supported Options

The core options (printWidth, tabWidth, useTabs, endOfLine) and the keys apply_option in tests/fixtures/mod.rs maps are supported, any other key fails the test.

Running Tests

Run all tests

cargo test -p oxc_formatter --test mod

Run tests in a specific directory

# Run all tests in the js/comments directory
cargo test -p oxc_formatter fixtures::js::comments

# Run all tests in the js directory (including subdirectories)
cargo test -p oxc_formatter fixtures::js

# Run a specific test file
cargo test -p oxc_formatter fixtures::js::comments::test

Accept new/changed snapshots

cargo insta test --accept -p oxc_formatter --test mod

Accept snapshots for specific tests

# Test names containing `arrow`
cargo insta test --accept -p oxc_formatter --test mod -- arrow

Review snapshots interactively

cargo insta review -p oxc_formatter

How It Works

  1. Build-time Discovery: The build script (build.rs) scans tests/fixtures/ for all .{js,jsx,ts,tsx,mjs,cjs,mts,cts} files
  2. Module Generation: Directories become nested modules matching the file system structure
  3. Code Generation: For each file, a test function is generated in the appropriate module
    • Example: fixtures/js/comments/test.js → fixtures::js::comments::test()
  4. Test Execution: Each generated test function calls the shared test_file() helper
  5. Option Resolution: For each file, walk up the directory tree to find options.json
  6. Formatting: Format the file with each option set
  7. Snapshot: Generate a snapshot showing input + all outputs (stored next to test file)
  8. Comparison: Compare with existing snapshot (if any)

Tips

  • Auto-discovery: Just add a .{js,jsx,ts,tsx,mjs,cjs,mts,cts} file to fixtures/ - no need to register it anywhere
  • Nested Modules: Directories become modules, enabling targeted test execution:
    • fixtures/js/comments/test.js → cargo test fixtures::js::comments::test
    • fixtures/js/comments/ → cargo test fixtures::js::comments (all tests in directory)
    • fixtures/js/ → cargo test fixtures::js (all tests including subdirectories)
  • Organization: Use subdirectories to group related tests (e.g., fixtures/js/arrows/, fixtures/js/classes/)
  • Shared Options: Put options.json at the directory level to apply to all files in that directory
  • Override Options: Create options.json in a subdirectory to override parent options
  • Default Options: If no options.json is found, FormatOptions::default() is used
  • File Extensions: The source type is detected automatically from the file extension
  • Co-located Snapshots: Snapshots are stored next to test files for easy navigation and review
  • Rebuilds: The build script automatically rebuilds when files in tests/fixtures/ change