WR

Provides the TestBuilder API to write tests for Syncpack features and commands.

Install

mkdir -p .claude/skills/write-tests && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4655" && unzip -o skill.zip -d .claude/skills/write-tests && rm skill.zip

Installs to .claude/skills/write-tests

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Write tests for Syncpack using the TestBuilder pattern. Use when adding tests for commands, validation logic, or any new functionality. Covers TestBuilder API, assertion patterns, and common test scenarios.
206 chars✓ has a “when” trigger
Intermediate

Key capabilities

  • Write unit tests using TestBuilder
  • Implement assertion patterns
  • Verify validation logic
  • Test command functionality

How it works

Uses a TestBuilder pattern to construct test contexts and verify outcomes with standardized assertions.

Inputs & outputs

You give it
Test scenario
You get back
Validated test suite

When to use write-tests

  • Write tests for new commands
  • Add validation for configuration logic
  • Implement assertion patterns

About this skill

Write Tests

Golden rules

  • Use TestBuilder — never construct Context manually.
  • Assert with expect(&ctx).to_have_instances(vec![...]) — never index ctx.instances.
  • Async-first: #[tokio::test] + .run().await is the canonical entry.

TDD

  1. Read 2-3 tests in the same *_test.rs and copy the pattern
  2. Write failing test → just test → confirm RED
  3. Ask before implementing
  4. Implement minimal code → GREEN → just format

Quick start

use {
  crate::{
    instance::{FixableInstance::*, InstanceState, SuspectInstance::*, UnfixableInstance::*, ValidInstance::*},
    test::{
      builder::TestBuilder,
      expect::{expect, ExpectedInstance},
    },
  },
  serde_json::json,
};

#[tokio::test]
async fn pinned_version_replaces_anything_different() {
  let ctx = TestBuilder::new()
    .with_package(json!({
      "name": "package-a",
      "version": "1.0.0",
      "devDependencies": {"foo": "workspace:*"}
    }))
    .with_version_group(json!({
      "dependencies": ["foo"],
      "pinVersion": "1.2.0"
    }))
    .run()
    .await;
  expect(&ctx).to_have_instances(vec![
    ExpectedInstance {
      state: InstanceState::valid(IsLocalAndValid),
      dependency_name: "package-a",
      id: "package-a in /version of package-a",
      actual: "1.0.0",
      expected: Some("1.0.0"),
      overridden: None,
    },
    ExpectedInstance {
      state: InstanceState::fixable(DiffersToPin),
      dependency_name: "foo",
      id: "foo in /devDependencies of package-a",
      actual: "workspace:*",
      expected: Some("1.2.0"),
      overridden: None,
    },
  ]);
}

Sub-module organisation

Group related scenarios under nested modules — see pinned_test.rs, catalog_defs_test.rs:

mod local {
  use super::*;
  #[tokio::test] async fn refuses_to_pin_local_version() { ... }
}

mod normal {
  use super::*;
  #[tokio::test] async fn an_already_pinned_version_is_valid() { ... }
}

mod registry_updates {
  use super::*;
  #[tokio::test] async fn def_marked_outdated_when_registry_has_newer_version() { ... }
}

File location

Test typeLocation
Version-group behaviour (pin, ban, ranges …)src/version_group/<group>_test.rs
Catalog discovery wiringsrc/version_group/{catalog,bun_catalog}_test.rs
Fix mutationssrc/commands/fix_test.rs
Format passsrc/visit_formatting/format_test.rs
Other unit testsCo-located: src/foo.rssrc/foo_test.rs

Builder methods

Source of truth: src/test/builder.rs.

MethodPurpose
.with_package(json!({...}))Add one package.json
.with_packages(vec![...])Add many
.with_version_group(json!({...}))Add one version group
.with_version_groups(vec![...])Add many
.with_semver_group(json!({...}))Add a semver group
.with_config(json!({...}))Base config (e.g. customTypes, dependencyGroups)
.with_strict(bool)Strict mode (Suspect → error)
.with_subcommand("update")Override subcommand (default: lint, or update if registry set)
.with_pnpm_catalogs(yaml)Inject pnpm-workspace.yaml; implies pnpm PM
.with_bun_catalogs(json!({...}))Synthetic Bun root with /catalog, /catalogs/{n}; implies Bun PM
.with_bun_workspaces_catalogs(json!({...}))Same, nested under /workspaces/
.with_{pnpm,bun,npm,yarn,unknown}_package_manager()Force PM detection
.with_registry_updates(json!({"react":[...]}))Mock npm registry; implies subcommand=update
.with_update_target(UpdateTarget::Minor)Bound update target
.run().awaitContextPrimary end-to-end (full pipeline through disk + discovery)
.build()Sync, no visit — context-wiring tests
.build_and_visit_packages()Sync + visit_packages — fix tests, older suites
.build_and_visit_formatting()Sync + visit_formatting
.build_with_registry_and_visit().awaitSync wiring + async registry mock + visit

ExpectedInstance fields

ExpectedInstance {
  state: InstanceState::fixable(DiffersToPin),  // valid / fixable / unfixable / suspect
  dependency_name: "react",                     // = `internal_name` (alias-aware)
  id: "react in /dependencies of package-a",    // {dep} in {/path} of {package_or_yaml}
  actual: "17.0.0",                             // raw specifier on disk
  expected: Some("18.0.0"),                     // None = ignore; Some("") = remove
  overridden: None,                             // semver-group override target, if any
}

id location examples:

  • /dependencies, /devDependencies, /peerDependencies
  • /version of package-a (local version)
  • /packageManager, /engines/node
  • /catalog of pnpm-workspace.yaml, /catalogs/<name> of pnpm-workspace.yaml
  • /customVersion, /custom/config/version (via customTypes)

Patterns

patterns.md: banned, pinned, sameRange, pnpm catalogs, bun catalogs, semver ranges, registry updates.

Fix tests

src/commands/fix_test.rs builds with .build_and_visit_packages() then runs fix::run(ctx, &SilentReporter, &disk). dry_run = true is the default (set by mock::config_from_mock), so is_dirty() and post-fix contents stay observable. Set ctx.config.cli.dry_run = false only when asserting writes through a recording MockDiskIo (see pnpm_fix_writes_yaml_to_disk).

Common mistakes

WrongRight
#[test] fn foo() + .run().await#[tokio::test] async fn foo()
use crate::instance_state::*use crate::instance::*
"pinned": "1.0.0""pinVersion": "1.0.0"
Context { ... }TestBuilder::new()...
ctx.instances[0]expect(&ctx).to_have_instances(vec![...])
.build() then check states.run().await (or .build_and_visit_packages() for sync)
Missing SuspectInstance::* importImport all 4: FixableInstance::*, ValidInstance::*, SuspectInstance::*, UnfixableInstance::*

Running

just test                            # all
cargo test pinned_test               # pattern match
cargo test test_name -- --nocapture  # with stdout

Reference tests

  • src/version_group/banned_test.rs — banned + custom types
  • src/version_group/pinned_test.rs — sub-modules, semver-group interaction
  • src/version_group/same_range_test.rs — range satisfaction
  • src/version_group/catalog_test.rs — pnpm catalogs
  • src/version_group/bun_catalog_test.rs — bun catalogs (sync .build())
  • src/version_group/preferred_semver_test.rs — registry updates, update targets

When not to use it

  • Manual Context construction
  • Testing non-Syncpack projects

Prerequisites

tokiojust

Limitations

  • Requires TestBuilder pattern usage

How it compares

Uses a dedicated builder pattern to ensure test consistency compared to manual setup.

Compared to similar skills

write-tests side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
write-tests (this skill)13moReviewIntermediate
ui-ux-expert-skill919moReviewAdvanced
dependency-upgrade265moReviewIntermediate
vitest416moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

ui-ux-expert-skill

fercracix33

Technical workflow for implementing accessible React user interfaces with shadcn/ui, Tailwind CSS, and TanStack Query. Includes 6-phase process with mandatory Style Guide compliance, Context7 best practices consultation, Chrome DevTools validation, and WCAG 2.1 AA accessibility standards. Use after Test Agent, Implementer, and Supabase agents complete their work.

91244

dependency-upgrade

wshobson

Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.

26240

vitest

antfu

Vitest fast unit testing framework powered by Vite with Jest-compatible API. Use when writing tests, mocking, configuring coverage, or working with test filtering and fixtures.

41183

chrome-devtools

mrgoonie

Browser automation, debugging, and performance analysis using Puppeteer CLI scripts. Use for automating browsers, taking screenshots, analyzing performance, monitoring network traffic, web scraping, form automation, and JavaScript debugging.

41157

playwright-browser-automation

lackeyjb

Complete browser automation with Playwright. Auto-detects dev servers, writes clean test scripts to /tmp. Test pages, fill forms, take screenshots, check responsive design, validate UX, test login flows, check links, automate any browser task. Use when user wants to test websites, automate browser interactions, validate web functionality, or perform any browser-based testing.

29146

angular-best-practices

sickn33

Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and rendering efficiency.

2192

Search skills

Search the agent skills registry