Agent skill

Write Tests

by openplayerjs in openplayerjs/openplayerjs

Write or extend Jest tests for OpenPlayerJS to this repo's exact conventions — makeCore factories, typed internals handles instead of as any, media property mocking, fake timers, ads/vast mocks, and…

MITAuto-check passedTesting & QA

Install Write Tests

skills CLI
$ npx skills add openplayerjs/openplayerjs --skill write-tests -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install openplayerjs/openplayerjs write-tests --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/openplayerjs/openplayerjs.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/write-tests .claude/skills/write-tests && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
write-tests
GitHub stars
649
Token cost
~1.8k tokens
SKILL.md length
657 words
Files
1
Skills in repo
5
Repo updated
First seen
Licence
MIT

At a glance

Write or extend Jest tests for OpenPlayerJS to this repo's exact conventions — makeCore factories, typed internals handles instead of as any, media property mocking, fake timers, ads/vast mocks, and…

  • Works in 7 steps: Target the right gap → File placement and skeleton → Standard levers → …
  • Asked to add tests
  • SKILL.md covers Step 0 — Target the right gap, Step 1 — File placement and…, Step 2 — Standard levers and Step 3 — Typed access instead…, plus 3 more sections
  • Calls pnpm and git

What it does

Write Tests is an agent skill from openplayerjs/openplayerjs. Write or extend Jest tests for OpenPlayerJS to this repo's exact conventions — makeCore factories, typed internals handles instead of as any, media property mocking, fake timers, ads/vast mocks, and coverage-gap targeting. Use when asked to add tests, raise coverage, fix the 85% threshold, or when a bug fix needs its regression test.

Its SKILL.md is about 1.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Testing & QA, covering Test generation, Unit testing and Debugging. It works with Jest and TypeScript. The repository describes itself as: Lightweight HTML5 video/audio player with smooth controls and ability to play VAST/VMAP/SIMID/OMID/non-linear ads. The licence is MIT.

When your agent uses it

  • Asked to add tests
  • Fix the 85% threshold
  • A bug fix needs its regression test

Example prompts

  • “/write-tests”

Workflow steps

7 steps, taken from the step headings in SKILL.md.

  1. Target the right gap
  2. File placement and skeleton
  3. Standard levers
  4. Typed access instead of as any (mandatory)
  5. Package-specific rules
  6. Assert like the spec
  7. Verify

What it can do on your machine

Read from SKILL.md and the folder at commit c26914a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • pnpm
    • git

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use pnpm and git, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Write Tests loads about 1.8k tokens when it runs. Until then it costs about 87 tokens; SKILL.md has 657 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~87
When it runs · the whole SKILL.md, loaded when a task matches
~1.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from openplayerjs/openplayerjs at commit c26914a, republished under its MIT licence (© openplayerjs). 657 words, ~1,804 tokens.

Download SKILL.mdSave it as .claude/skills/write-tests/SKILL.md (or your agent's skills folder).
name
write-tests
description
Write or extend Jest tests for OpenPlayerJS to this repo's exact conventions — makeCore factories, typed internals handles instead of `as any`, media property mocking, fake timers, ads/vast mocks, and coverage-gap targeting. Use when asked to add tests, raise coverage, fix the 85% threshold, or when a bug fix needs its regression test.

Write tests the OpenPlayerJS way

Tests here are the executable spec and are lint-clean (zero no-explicit-any warnings in __tests__/ — a state that took a 394-warning sweep to reach; do not regress it). Follow this playbook exactly.

Step 0 — Target the right gap

  • Regression test for a bug fix: write it FIRST, confirm it fails on the pre-fix code (git stash the fix if needed), then confirm it passes after.
  • Coverage work: find the actual uncovered branches, don't guess:
    sh
    pnpm run test 2>/dev/null | tail -40          # per-file summary
    # then open coverage/lcov-report/<pkg>/<file>.html or:
    pnpm exec jest packages/<pkg> --coverage --collectCoverageFrom='packages/<pkg>/src/**'
  • Skip what's excluded by design: the youtube package, umd.ts, index.ts barrels, and the documented-unreachable CSAI paths (SIMID/OMID/real-browser HLS) — don't burn time there.

Step 1 — File placement and skeleton

  • Location: packages/<pkg>/__tests__/. Naming: feature.test.ts for main coverage, feature.branches.test.ts for edge/error paths, scenario-named files for specific behaviors (player.autoplay.unmute.test.ts).
  • Every file starts with the environment pragma and uses local factories:
ts
/** @jest-environment jsdom */
import { Core } from '@openplayerjs/core'; // always the package alias, never relative

describe('Feature name', () => {
  function makeCore() {
    const v = document.createElement('video');
    v.src = 'https://example.com/video.mp4';
    document.body.appendChild(v);
    return new Core(v, { plugins: [] }); // explicit empty plugins — no accidental engines
  }

  function nn<T>(v: T | null | undefined): T {
    expect(v).toBeTruthy();
    return v as T;
  }

  beforeEach(() => {
    document.body.innerHTML = '';
  });
});

No module-level mutable state. Anything shared goes inside the describe as a factory.

Step 2 — Standard levers

Readiness / playback state (mediaMocks from __tests__/setup/mediaMocks.ts is already loaded globally — play/pause/load/canPlayType are mocked):

ts
p.events.emit('loadedmetadata');            // resolves whenReady()
p.events.emit('playing');                   // drive state transitions

Synchronous play/pause for UI tests:

ts
p.play = jest.fn(async () => { p.events.emit('playing'); }) as unknown as Core['play'];
p.pause = jest.fn(() => { p.emit('cmd:pause'); p.events.emit('pause'); }) as unknown as Core['pause'];

Read-only media properties — always defineProperty, always configurable:

ts
Object.defineProperty(p.media, 'duration', { value: 120, configurable: true });
Object.defineProperty(p.media, 'paused', { value: false, configurable: true });

Timers: jest.useFakeTimers() at the top of the describe; drive with jest.advanceTimersByTime(ms); flush microtask-based logic with await Promise.resolve(). Never a real setTimeout wait.

jsdom quirks: patch window.scrollX/scrollY (the source reads these, not pageXOffset); queueMicrotask-based focus handlers need a microtask flush, not a timer.

Step 3 — Typed access instead of as any (mandatory)

NeedPattern
@internal getters on a plugintype AdsPluginInternals = AdsPlugin & { bus: NonNullable<AdsPlugin['bus']>; active: boolean }; then as unknown as AdsPluginInternals. @internal methods are public — call them directly, no cast.
private membersas unknown as { member: T } — an intersection Class & { privateMember } reduces to never; the double cast is the only way.
Partial mock contextconst ctx = {...} as unknown as PluginContext; — and keep on: a single non-overloaded impl so contextual typing works.
Window/global stubsOne local shape per file: const win = window as unknown as { YT?: { Player: jest.Mock } }; assign/delete through it.
Custom cue propstype RawCue = TextTrackCue & { data?: ArrayBuffer; value?: unknown; scte35Out?: string };
Vendor DOM APIstype VendorElement = HTMLElement & { webkitEnterFullscreen?: () => void };
Config extrasCast to the real config type: { plugins: [], step: 10 } as PlayerUIConfig — never as any.
Wrong-type mock returnsmockResolvedValue(undefined as unknown as boolean) when the signature demands it.
Show full SKILL.md (293 more words)Show less

Step 4 — Package-specific rules

ads — never import @dailymotion/vast-client or @dailymotion/vmap; jest's moduleNameMapper routes them to packages/ads/__tests__/mocks/ (the mocks export shared jest.fn() instances — reset them in beforeEach). VAST XML fixtures live in packages/ads/__tests__/fixtures/ads/*.xml; add a fixture rather than inlining XML. Break configs passed to typed methods need an explicit annotation (const brk: AdsBreakConfig = { at: 0, source: { type: 'VAST', … } }) or the type literal widens to string.

hls — mock event names as constants OUTSIDE the jest.mock() factory (const E = { MANIFEST_PARSED: 'MANIFEST_PARSED' } as const); get the mock instance via engine.getAdapter<HlsMockWithEmit>() and adapter!.emit(E.MANIFEST_PARSED, null, {}). Keep .on/.emit as method calls on the cast object so this stays bound.

youtube / iframe — stub the adapter, not the network: a StubAdapter implements IframeMediaAdapter with a Map<string, Function> listener registry and jest.fn methods; fake the API global via a typed window handle (win.YT = { Player: jest.fn(...) }).

player controls — build through the real factory, drive with dispatched DOM events (el.dispatchEvent(new KeyboardEvent('keydown', { key: 'f' }))), and assert on DOM state + emitted player events, not on private fields, unless a private is the only observable.

Step 5 — Assert like the spec

  • Assert exact payloads and full shapes (toEqual({ id: 'brk-1', kind: 'preroll' })), not toHaveBeenCalled() alone.
  • Every error/early-return branch you're covering gets its own test() with a name that states the behavior ("does not resume content between waterfall attempts"), not the implementation ("calls startBreak with flag").
  • Clean up what you create: if the test attaches engines, mounts UI, or acquires leases, destroy the player at the end so cross-test leaks can't hide.

Step 6 — Verify

sh
pnpm exec jest packages/<pkg>/__tests__/<file>.test.ts   # the new file, fast loop
pnpm run test                                            # full suite + 85% coverage gates
pnpm run lint                                            # zero new warnings, incl. no-explicit-any
pnpm run type-check

A test that passes but emits lint warnings or needs as any is not done. A suite that hangs or times out after your change usually means you removed/renamed an event a test subscribes to — grep the event name across packages/ before anything else.

© openplayerjs, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/write-tests of openplayerjs/openplayerjs.

Open the folder on GitHubat commit c26914a

Compare with similar skills

Write Tests next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Write Tests compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Write Tests this skillopenplayerjs/openplayerjs649—~1.8kAutomated safety check: PassMIT
Write Testsgrafana/synthetic-monitoring-app171—~1.2kAutomated safety check: PassAGPL-3.0
Test Specialisttravisjneuman/.claude101—~3.7kAutomated safety check: PassMIT
Senior QAalirezarezvani/claude-skills28k1 repos~2.1kAutomated safety check: PassMIT
Test Specialistailabs-393/ai-labs-claude-skills454—~3.4kAutomated safety check: PassMIT
TDD Guidealirezarezvani/claude-skills28k—~3.4kAutomated safety check: PassMIT

Similar skills

  • Write Tests

    grafana/synthetic-monitoring-app

    Official

    Write Jest integration and unit tests for the Grafana Synthetic Monitoring app using React Testing Library, MSW, and src/test helpers.

    171 GitHub stars~1.2k tokensUpdated today
    Testing & QAAuto-check passed
  • Test Specialist

    travisjneuman/.claude

    Test-writing patterns for JS/TS, Python, Go, and Rust (unit, integration, E2E, visual regression).

    101 GitHub stars~3.7k tokensUpdated yesterday
    Testing & QAAuto-check passed
  • Senior QA

    alirezarezvani/claude-skills

    Generates unit tests, integration tests, and E2E tests for React/Next.js applications.

    28k GitHub starsUsed in 1 repo~2.1k tokens
    Testing & QAAuto-check passed
  • Test Specialist

    ailabs-393/ai-labs-claude-skills

    This skill should be used when writing test cases, fixing bugs, analyzing code for potential issues, or improving test coverage for JavaScript/TypeScript applications.

    454 GitHub stars~3.4k tokensUpdated 11 mo ago
    Testing & QAAuto-check passed
  • TDD Guide

    alirezarezvani/claude-skills

    Test-driven development skill for writing unit tests, generating test fixtures and mocks, analyzing coverage gaps, and guiding red-green-refactor workflows across Jest, Pytest, JUnit, Vitest, and…

    28k GitHub stars~3.4k tokensUpdated 1 mo ago
    Testing & QAAuto-check passed
  • Code Testing Agent

    microsoft/testfx

    Official

    Generates and writes new unit tests for any programming language — scaffolds .NET test projects, pytest suites, Vitest/Jest suites, Go test files, and JUnit suites, and configures coverage tooling…

    1k GitHub stars~2.7k tokensUpdated today
    Testing & QAAuto-check passed

More from openplayerjs/openplayerjs

  • Add Event

    openplayerjs/openplayerjs

    Add, rename, change the payload of, or remove a typed player event in OpenPlayerJS.

    649 GitHub stars~1.7k tokensUpdated 2 days ago
    Auto-check passed
  • Audit Fix

    openplayerjs/openplayerjs

    Resolve a pnpm audit (dependency-audit CI job) failure — high/critical CVEs in the dependency tree.

    649 GitHub stars~1k tokensUpdated 2 days ago
    Auto-check passed
  • Preship

    openplayerjs/openplayerjs

    Run the full OpenPlayerJS verification gauntlet before committing, opening a PR, or preparing a release.

    649 GitHub stars~1.2k tokensUpdated 2 days ago
    Auto-check passed
  • Optimize

    openplayerjs/openplayerjs

    Find and safely apply ONE worthwhile code optimization (reuse, simplification, efficiency, or a dead-weight cleanup) somewhere in packages//src, with new regression tests proving behavior is…

    649 GitHub stars~1.9k tokensUpdated 2 days ago
    Auto-check passed

Works with

Categories

Questions about Write Tests

What does Write Tests do?

Write or extend Jest tests for OpenPlayerJS to this repo's exact conventions — makeCore factories, typed internals handles instead of as any, media property mocking, fake timers, ads/vast mocks, and…. Write Tests is an agent skill from openplayerjs/openplayerjs. Write or extend Jest tests for OpenPlayerJS to this repo's exact conventions — makeCore factories, typed internals handles instead of as any, media property mocking, fake timers, ads/vast mocks, and coverage-gap targeting.

When should I use Write Tests?

Write Tests fits situations like: asked to add tests; fix the 85% threshold; A bug fix needs its regression test.

How do I install Write Tests in Claude Code?

Run `npx skills add openplayerjs/openplayerjs --skill write-tests -a claude-code`. Or copy the skill folder (.claude/skills/write-tests in openplayerjs/openplayerjs) into .claude/skills/write-tests in your project. Claude Code loads it when a task matches its description.

How do I install Write Tests in Codex?

Run `npx skills add openplayerjs/openplayerjs --skill write-tests -a codex`. Or copy the skill folder (.claude/skills/write-tests in openplayerjs/openplayerjs) into .agents/skills/write-tests in your project. Codex loads it when a task matches its description.

Can I use Write Tests in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add openplayerjs/openplayerjs --skill write-tests -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/write-tests, .gemini/skills/write-tests, .github/skills/write-tests and .opencode/skills/write-tests in your project.

What does Write Tests need to run?

Going by SKILL.md and its folder, Write Tests needs the command-line tools its instructions call (pnpm and git).

Does Write Tests access the network?

SKILL.md contains no URLs. Its commands use git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Write Tests safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Write Tests use?

Write Tests is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Write Tests use?

About 1.8k tokens (SKILL.md is roughly 7.2k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Write Tests?

Skills that share tags, products or a category with Write Tests: Write Tests (grafana/synthetic-monitoring-app, 171 stars), Test Specialist (travisjneuman/.claude, 101 stars), Senior QA (alirezarezvani/claude-skills, 28k stars) and Test Specialist (ailabs-393/ai-labs-claude-skills, 454 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Write Tests?

openplayerjs (a GitHub organization) maintains it in openplayerjs/openplayerjs, which has 649 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on October 5, 2026.

Source: openplayerjs/openplayerjs on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.