Nuxt, тестирование и Storybook
Модуль Nuxt
ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['vue-feature-toggles/nuxt'],
featureToggles: {
flags: { newDashboard: true, betaSearch: false },
urlOverrides: true,
urlPrefix: 'feature',
defaultValue: false,
reloadInterval: 0,
meta: { newDashboard: { owner: 'alice', addedAt: '2025-03-01' } },
expiry: { betaBanner: '2025-06-01' },
groups: { beta: ['betaSearch'] },
dependencies: { aiSuggestions: ['newSearch'] },
liveUpdates: { type: 'sse', url: '/api/flags/stream' },
},
})<Feature>,<FeatureVariant>иv-featureрегистрируются глобально- SSR-гидратация через
nuxtApp.payloadобрабатывается автоматически — конфигурацияssrStateне нужна $featureTogglesвнедряется вnuxtApp
ts
// plugins/my-plugin.ts
export default defineNuxtPlugin((nuxtApp) => {
const { $featureToggles } = nuxtApp
console.log($featureToggles.flags.value)
})Пользовательский загрузчик с Nuxt
Опция loader — это функция, и она не может быть сериализована в nuxt.config. Вместо этого используйте плагин:
ts
// plugins/feature-toggles.ts
import { FeatureToggles } from 'vue-feature-toggles'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(FeatureToggles, {
loader: async () => {
return $fetch('/api/flags')
},
urlOverrides: true,
})
})Утилиты для тестирования
ts
import {
createTestFeatureProvider,
withFeatures,
setTestFlag,
resetTestProvider,
} from 'vue-feature-toggles/testing'Монтирование с флагами
ts
import { mount } from '@vue/test-utils'
import { withFeatures } from 'vue-feature-toggles/testing'
const wrapper = mount(
MyComponent,
withFeatures({
newDashboard: true,
betaSearch: false,
}),
)Полный доступ к провайдеру в тестах
ts
import { createTestFeatureProvider } from 'vue-feature-toggles/testing'
const { install, provider } = createTestFeatureProvider({ newDashboard: true })
const wrapper = mount(MyComponent, {
global: { plugins: [{ install }] },
})
provider.setFlag('newDashboard', false)
await nextTick()Изменение флагов посреди теста
ts
import { setTestFlag } from 'vue-feature-toggles/testing'
it('hides the component when flag is off', async () => {
const wrapper = mount(MyComponent, withFeatures({ betaSearch: true }))
expect(wrapper.find('[data-testid="beta"]').exists()).toBe(true)
await setTestFlag('betaSearch', false) // автоматически дожидается nextTick
expect(wrapper.find('[data-testid="beta"]').exists()).toBe(false)
})Очистка
ts
import { resetTestProvider } from 'vue-feature-toggles/testing'
afterEach(() => resetTestProvider())Точка входа vue-feature-toggles/testing исключена из продакшен-бандла.
Аддон Storybook
ts
// .storybook/preview.ts
import { withFeatureToggles } from 'vue-feature-toggles/storybook'
export const decorators = [
withFeatureToggles({ betaSearch: false }), // глобальные значения по умолчанию
]ts
// MyComponent.stories.ts
export const WithBetaSearch: Story = {
parameters: {
featureToggles: {
betaSearch: true,
newDashboard: false,
},
},
}parameters.featureToggles каждой истории объединяется поверх глобальных значений по умолчанию. Точка входа vue-feature-toggles/storybook исключена из продакшен-бандла.