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>
6.1 KiB
6.1 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Configure Pinia Testing with createTestingPinia and setActivePinia | HIGH | Missing Pinia configuration causes 'injection Symbol(pinia) not found' errors and failing tests | gotcha |
|
Configure Pinia Testing with createTestingPinia and setActivePinia
Impact: HIGH - Testing components or composables that use Pinia stores without proper configuration results in "[Vue warn]: injection Symbol(pinia) not found" errors. Tests will fail or behave unexpectedly.
Use @pinia/testing package with createTestingPinia for component tests and setActivePinia(createPinia()) for unit testing stores directly.
Task Checklist
- Install
@pinia/testingas a dev dependency - Use
createTestingPiniain component tests withglobal.plugins - Use
setActivePinia(createPinia())inbeforeEachfor store unit tests - Configure
createSpy: vi.fnwhen NOT usingglobals: truein Vitest - Initialize store inside each test to get fresh state
- Use
stubActions: falsewhen you need real action execution
Incorrect:
import { mount } from '@vue/test-utils'
import UserProfile from './UserProfile.vue'
// BAD: Missing Pinia - causes injection error
test('displays user name', () => {
const wrapper = mount(UserProfile) // ERROR: injection "Symbol(pinia)" not found
expect(wrapper.text()).toContain('John')
})
import { useUserStore } from '@/stores/user'
// BAD: No active Pinia instance
test('user store actions', () => {
const store = useUserStore() // ERROR: no active Pinia
store.login('john', 'password')
})
Correct - Component Testing:
import { mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
import { vi } from 'vitest'
import UserProfile from './UserProfile.vue'
import { useUserStore } from '@/stores/user'
// CORRECT: Provide testing pinia with stubbed actions
test('displays user name', () => {
const wrapper = mount(UserProfile, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn, // Required if not using globals: true
initialState: {
user: { name: 'John', email: 'john@example.com' }
}
})
]
}
})
expect(wrapper.text()).toContain('John')
})
// CORRECT: Test with stubbed actions (default behavior)
test('calls logout action', async () => {
const wrapper = mount(UserProfile, {
global: {
plugins: [createTestingPinia({ createSpy: vi.fn })]
}
})
// Get store AFTER mounting with createTestingPinia
const store = useUserStore()
await wrapper.find('[data-testid="logout"]').trigger('click')
// Actions are stubbed and wrapped in spies
expect(store.logout).toHaveBeenCalled()
})
Correct - Store Unit Testing:
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '@/stores/user'
describe('User Store', () => {
beforeEach(() => {
// Create fresh Pinia instance for each test
setActivePinia(createPinia())
})
it('initializes with empty user', () => {
const store = useUserStore()
expect(store.user).toBeNull()
expect(store.isLoggedIn).toBe(false)
})
it('updates user on login', async () => {
const store = useUserStore()
// Real action executes - not stubbed
await store.login('john', 'password')
expect(store.user).toEqual({ name: 'John' })
expect(store.isLoggedIn).toBe(true)
})
it('clears user on logout', () => {
const store = useUserStore()
store.user = { name: 'John' } // Set initial state
store.logout()
expect(store.user).toBeNull()
})
})
Testing with Real Actions vs Stubbed Actions
import { createTestingPinia } from '@pinia/testing'
// Stubbed actions (default) - for isolation
const wrapper = mount(Component, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
// stubActions: true (default) - actions are mocked
})
]
}
})
// Real actions - for integration testing
const wrapper = mount(Component, {
global: {
plugins: [
createTestingPinia({
createSpy: vi.fn,
stubActions: false // Actions execute normally
})
]
}
})
Mocking Specific Action Implementations
import { mount } from '@vue/test-utils'
import { createTestingPinia } from '@pinia/testing'
import { vi } from 'vitest'
import { useCartStore } from '@/stores/cart'
test('handles checkout failure', async () => {
const wrapper = mount(Checkout, {
global: {
plugins: [createTestingPinia({ createSpy: vi.fn })]
}
})
const cartStore = useCartStore()
// Mock specific action behavior
cartStore.checkout.mockRejectedValue(new Error('Payment failed'))
await wrapper.find('[data-testid="checkout"]').trigger('click')
await flushPromises()
expect(wrapper.find('.error').text()).toContain('Payment failed')
})
Spying on Actions with vi.spyOn
import { setActivePinia, createPinia } from 'pinia'
import { vi } from 'vitest'
import { useUserStore } from '@/stores/user'
test('tracks action calls', async () => {
setActivePinia(createPinia())
const store = useUserStore()
const loginSpy = vi.spyOn(store, 'login')
loginSpy.mockResolvedValue({ success: true })
await store.login('john', 'password')
expect(loginSpy).toHaveBeenCalledWith('john', 'password')
})
Testing Store $subscribe
import { setActivePinia, createPinia } from 'pinia'
import { useUserStore } from '@/stores/user'
test('subscription triggers on state change', () => {
setActivePinia(createPinia())
const store = useUserStore()
const callback = vi.fn()
store.$subscribe(callback)
store.user = { name: 'John' }
expect(callback).toHaveBeenCalled()
})