Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.5 KiB
5.5 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Choose Browser-Based Runner for Style and DOM Event Testing | MEDIUM | Node-based runners cannot test real CSS behavior, native DOM events, cookies, or computed styles | capability |
|
Choose Browser-Based Runner for Style and DOM Event Testing
Impact: MEDIUM - Node-based test runners (Vitest with jsdom/happy-dom) simulate the DOM but cannot test real CSS rendering, native browser events, cookies, computed styles, or cross-browser behavior. Use browser-based runners when these matter.
Use Vitest for most component tests (fast), but use Vitest Browser Mode when testing visual/DOM-dependent features.
Task Checklist
- Use Vitest (node) for logic-focused component tests
- Use Vitest Browser Mode for style-dependent tests
- Use Vitest Browser Mode for native events (focus, drag, resize)
- Use Vitest Browser Mode for cookies and computed CSS styles
- Accept slower speed tradeoff for browser accuracy
When to Use Each Approach
Node-Based Runner (Vitest + happy-dom/jsdom)
Best for:
- Pure logic testing
- State management
- Event emission
- Props/slots behavior
- Most component interactions
- Fast CI/CD pipelines
// vitest.config.js
export default defineConfig({
test: {
environment: 'happy-dom', // or 'jsdom'
}
})
// Fast but limited - fine for most tests
test('button emits click event', async () => {
const wrapper = mount(Button)
await wrapper.trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
})
Vitest Browser Mode
Required for:
- CSS computed styles verification
- CSS transitions/animations
- Real focus/blur behavior
- Drag and drop
- Cookie operations
- Viewport-dependent behavior
- Cross-browser validation
Vitest Browser Mode Setup
npm install -D @vitest/browser playwright
// vitest.config.js
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
browser: {
enabled: true,
name: 'chromium',
provider: 'playwright',
},
},
})
// Button.browser.test.js
import { render } from 'vitest-browser-vue'
import Button from './Button.vue'
test('has correct hover styling', async () => {
const { getByRole } = render(Button, { props: { label: 'Click me' } })
const button = getByRole('button')
// Check initial style
await expect.element(button).toHaveStyle({
backgroundColor: 'rgb(59, 130, 246)' // blue
})
})
test('maintains focus after click', async () => {
const { getByRole } = render(Button)
const button = getByRole('button')
await button.click()
await expect.element(button).toHaveFocus()
})
Examples: What Each Runner Can/Cannot Test
Styles - Browser Required
// Node runner: CANNOT verify actual CSS
test('danger button has red background', () => {
const wrapper = mount(Button, { props: { variant: 'danger' } })
// This only checks class exists, not actual color
expect(wrapper.classes()).toContain('bg-red-500')
})
// Vitest Browser Mode: CAN verify computed styles
test('danger button renders red', async () => {
const { getByRole } = render(Button, { props: { variant: 'danger' } })
await expect.element(getByRole('button')).toHaveStyle({
backgroundColor: 'rgb(239, 68, 68)'
})
})
Computed CSS Styles - Browser Required
// Node runner: CANNOT get real computed styles
test('button has correct padding', () => {
const wrapper = mount(Button)
// getComputedStyle returns empty/default values in jsdom
const style = window.getComputedStyle(wrapper.element)
// style.padding will be empty string, not actual computed value
})
// Vitest Browser Mode: Real computed styles
test('button has correct padding', async () => {
const { getByRole } = render(Button)
const button = getByRole('button')
await expect.element(button).toHaveStyle({
padding: '12px 24px'
})
})
Native Events - Browser Required
// Node runner: Synthetic events only
test('handles drag and drop', async () => {
const wrapper = mount(DraggableList)
// trigger('dragstart') is synthetic - may not work as expected
await wrapper.find('.item').trigger('dragstart')
})
// Vitest Browser Mode: Real native events via userEvent
import { userEvent } from '@vitest/browser/context'
test('reorders items on drag', async () => {
const { getByTestId } = render(DraggableList)
const item = getByTestId('item-1')
const target = getByTestId('item-3')
await userEvent.dragAndDrop(item, target)
// Assert reordering
})
Recommended Testing Strategy
// vitest.config.js - Separate test configurations
export default defineConfig({
test: {
// Default: Node environment for speed
environment: 'happy-dom',
// Browser tests in separate directory
include: ['src/**/*.test.{js,ts}'],
},
})
// Run browser tests separately
// npx vitest --browser.enabled
Directory Structure
tests/
├── unit/ # Fast node-based tests
│ ├── Button.test.js
│ └── useCounter.test.js
├── component/ # Slower browser-based tests
│ ├── Button.browser.test.js
│ └── DragDrop.browser.test.js
└── e2e/ # Full E2E tests (Playwright)
└── user-flow.spec.ts