UNPKG

@idooel/runtime-context

Version:

Runtime data pool with namespaces, stackable contexts, subscriptions and optional persistence. Vue adapter included.

208 lines (158 loc) 5.88 kB
import { describe, it, expect, beforeEach, vi } from 'vitest' import { Vue2DataPoolPlugin } from '../../src/vue2/plugin' describe('Vue2DataPoolPlugin', () => { let mockVue: any beforeEach(() => { mockVue = { prototype: {}, $idooelDataPool: null, mixin: vi.fn(), observable: vi.fn((obj) => obj) } vi.clearAllMocks() }) it('should install plugin with default options', () => { Vue2DataPoolPlugin.install(mockVue) expect(mockVue.prototype.$idooelDataPool).toBeDefined() expect(mockVue.$idooelDataPool).toBeDefined() expect(mockVue.mixin).toHaveBeenCalled() }) it('should install plugin with custom pool', () => { const customPool = { custom: 'pool' } as any Vue2DataPoolPlugin.install(mockVue, { pool: customPool }) expect(mockVue.prototype.$idooelDataPool).toBe(customPool) expect(mockVue.$idooelDataPool).toBe(customPool) }) it('should skip global inject when disabled', () => { Vue2DataPoolPlugin.install(mockVue, { globalInject: false }) expect(mockVue.prototype.$idooelDataPool).toBeUndefined() expect(mockVue.$idooelDataPool).toBeNull() }) it('should skip mixin when disabled', () => { Vue2DataPoolPlugin.install(mockVue, { mixin: false }) expect(mockVue.mixin).not.toHaveBeenCalled() }) it('should add mixin for subscription management', () => { Vue2DataPoolPlugin.install(mockVue) expect(mockVue.mixin).toHaveBeenCalledWith( expect.objectContaining({ created: expect.any(Function), beforeDestroy: expect.any(Function) }) ) }) }) describe('Vue Integration - Component Lifecycle', () => { let mockVue: any let mockComponent: any let mixinOptions: any beforeEach(() => { mockVue = { prototype: {}, $idooelDataPool: null, mixin: vi.fn() } mockComponent = { _idooelDataPoolSubscriptions: [] } Vue2DataPoolPlugin.install(mockVue) // Get the mixin options mixinOptions = mockVue.mixin.mock.calls[0][0] }) it('should initialize subscription array on component creation', () => { mixinOptions.created.call(mockComponent) expect(mockComponent._idooelDataPoolSubscriptions).toEqual([]) }) it('should cleanup subscriptions on component destroy', () => { const unsubscribe1 = vi.fn() const unsubscribe2 = vi.fn() mockComponent._idooelDataPoolSubscriptions = [unsubscribe1, unsubscribe2] mixinOptions.beforeDestroy.call(mockComponent) expect(unsubscribe1).toHaveBeenCalled() expect(unsubscribe2).toHaveBeenCalled() expect(mockComponent._idooelDataPoolSubscriptions).toEqual([]) }) it('should handle cleanup when no subscriptions exist', () => { delete mockComponent._idooelDataPoolSubscriptions expect(() => mixinOptions.beforeDestroy.call(mockComponent)).not.toThrow() }) it('should handle errors in subscription lifecycle gracefully', () => { const badUnsubscribe = vi.fn(() => { throw new Error('Unsubscribe error') }) mockComponent._idooelDataPoolSubscriptions = [badUnsubscribe] // Should not throw even if unsubscribe fails expect(() => mixinOptions.beforeDestroy.call(mockComponent)).not.toThrow() // Bad unsubscribe should still be called expect(badUnsubscribe).toHaveBeenCalled() // Subscriptions should be cleared even if errors occurred expect(mockComponent._idooelDataPoolSubscriptions).toEqual([]) }) }) describe('Vue Integration - Data Pool Integration', () => { let mockVue: any let mockPool: any beforeEach(() => { mockPool = { get: vi.fn(), set: vi.fn(), delete: vi.fn(), subscribe: vi.fn(() => vi.fn()), createDataPool: vi.fn(() => mockPool) } mockVue = { prototype: {}, $idooelDataPool: null, mixin: vi.fn(), observable: vi.fn((obj) => obj) } Vue2DataPoolPlugin.install(mockVue, { pool: mockPool }) }) it('should provide data pool through prototype', () => { const mockComponent = {} // Simulate Vue instance access Object.setPrototypeOf(mockComponent, mockVue.prototype) expect(mockComponent.$idooelDataPool).toBe(mockPool) }) it('should allow direct pool operations through prototype', () => { mockPool.get.mockReturnValue('test-value') const mockComponent = {} Object.setPrototypeOf(mockComponent, mockVue.prototype) mockComponent.$idooelDataPool.set('test', 'key', 'value') const value = mockComponent.$idooelDataPool.get('test', 'key') expect(mockPool.set).toHaveBeenCalledWith('test', 'key', 'value') expect(mockPool.get).toHaveBeenCalledWith('test', 'key') expect(value).toBe('test-value') }) }) describe('Vue Integration - Observable Integration', () => { let mockVue: any let mockPool: any beforeEach(() => { mockPool = { get: vi.fn(), subscribe: vi.fn(() => vi.fn()) } mockVue = { prototype: {}, $idooelDataPool: null, mixin: vi.fn(), observable: vi.fn((obj) => obj) } Vue2DataPoolPlugin.install(mockVue, { pool: mockPool }) }) it('should provide Vue.observable for reactive values', () => { mockPool.get.mockReturnValue('initial') const mockComponent = {} Object.setPrototypeOf(mockComponent, mockVue.prototype) // Test that Vue.observable is called (simulating usePoolValue behavior) mockVue.observable({ data: 'initial' }) expect(mockVue.observable).toHaveBeenCalledWith({ data: 'initial' }) }) it('should handle Vue.observable errors gracefully', () => { mockVue.observable.mockImplementation(() => { throw new Error('Observable error') }) expect(() => mockVue.observable({ data: 'test' })).toThrow('Observable error') }) })