Skip to content

Organizing your suite

Organize the suite so the relationship between trials, features, and layers is easy to see.

The test tree should follow the product and the testing layers, not the framework name.

A strong default structure

text
tests/
  unit/
    helpers/
  functional/
    pages/
    api/
  e2e/
    pages/
      auth/
      billing/
      dashboard/
      issues/
  factories/
  scenarios/

This gives you three useful separations:

  • by layer: unit vs functional vs browser
  • by product surface: auth, billing, issues, dashboard
  • by setup vocabulary: factories and scenarios live under tests/

Why not tests/sounding/

A folder like tests/sounding/ makes the framework more visible than the product. Prefer grouping by layer and feature instead.

Unit tests

Keep fast helper and business-logic trials under tests/unit/.

text
tests/unit/
  helpers/
    capitalize.test.js
    get-user-initials.test.js

This is where light, app-aware helper trials belong.

Functional and browser trials

Put request-driven and Inertia-driven page contracts under tests/functional/, and keep browser-capable trials under tests/e2e/pages/.

text
tests/functional/pages/
  blog.test.js
  story.test.js
  auth/
    login.test.js
  issues/
    contracts.test.js
tests/e2e/pages/
  home.test.js
  auth/
    magic-link-browser.test.js
  issues/
    reader-access.test.js
  dashboard/
    editor.test.js

This layout keeps related behaviors together while separating non-browser checks from browser journeys.

Split by behavior, not by tool

A good file should answer this question clearly:

What family of trials lives here?

Names like reader-access.test.js and magic-link-browser.test.js are clearer than vague names like issues.test.js when the feature has multiple distinct behaviors.

Inside a feature folder, split files by behavior and runtime value, not by arbitrary naming.

For example:

  • magic-link-request.test.js for request/mail behavior
  • magic-link-browser.test.js for the full browser sign-in flow
  • contracts.test.js for request or Inertia-level issue contracts
  • reader-access.test.js for browser-capable reading flows

This keeps the suite fast, legible, and easy to maintain.

Factories belong under tests/factories

Factories should live under tests/factories because they are test vocabulary, not app runtime code.

If you want the full factory API and loading behavior, read Factories.

A practical layout might look like:

text
tests/factories/
  user.js
  issue.js
  subscription.js

Each factory should model one record shape well.

Scenarios belong under tests/scenarios

Scenarios should live under tests/scenarios because they define business situations.

text
tests/scenarios/
  issue-access.js
  publisher-editor.js
  magic-link-signin.js
tests/world-helpers/
    create-user-with-team.js

A good scenario name should tell you the situation before you open the file.

If a helper exists only to keep a scenario readable, keep it near the scenarios. Use a named folder such as tests/world-helpers/ instead of a vague tests/support/ folder.

If you want the full scenario API and loading behavior, read Scenarios.

A useful rule of thumb

If a trial reads better with a named business situation, add or reuse a scenario.

If a trial just needs one more field value, prefer:

  • a trait
  • a small override
  • a helper inside the scenario

If that helper grows into product-state setup, keep it in a named nearby folder like tests/world-helpers/, not inside the auto-loaded tests/scenarios/ tree.

Do not create a new scenario for every tiny variation.

Keep feature folders focused

A few practical rules help a lot:

  • keep one file focused on one kind of behavior
  • prefer contracts.test.js for request/Inertia contracts
  • prefer *-browser.test.js for true browser journeys
  • group by feature before grouping by runtime detail
  • do not let one giant file become the whole feature

Example layout

This is a layout that works well in a real app:

text
tests/
  unit/
    helpers/
      capitalize.test.js
      get-user-initials.test.js
  functional/
    pages/
      auth/
        login.test.js
      issues/
        contracts.test.js
    api/
      issues/
        create.test.js
  e2e/
    pages/
      auth/
        magic-link-browser.test.js
      billing/
        pricing.test.js
      dashboard/
        editor.test.js
      issues/
        reader-access.test.js
      home.test.js
      blog.test.js
      contact.test.js
      story.test.js
  world-helpers/
    create-user-with-team.js
  scenarios/
    issue-access.js
    publisher-editor.js

This structure is simple and scalable.

Summary

A Sounding suite should look like a well-organized product codebase that uses Sounding.

All open source projects are released under the MIT License.