UNPKG

@idiosync/react-observable

Version:

State management control layer for React projects

277 lines (276 loc) 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const stream_1 = require("./stream"); const observable_1 = require("../factories/observable"); describe('Stream utilities', () => { describe('createStreamName', () => { it('should create stream name with default prefix', () => { const name = (0, stream_1.createStreamName)(); expect(typeof name).toBe('string'); expect(name.length).toBeGreaterThan(0); expect(name).toMatch(/^stream:/); }); it('should create stream name with custom prefix', () => { const name = (0, stream_1.createStreamName)('custom'); expect(typeof name).toBe('string'); expect(name).toMatch(/^custom:/); }); it('should create unique names', () => { const name1 = (0, stream_1.createStreamName)(); const name2 = (0, stream_1.createStreamName)(); expect(name1).not.toBe(name2); }); it('should handle empty prefix', () => { const name = (0, stream_1.createStreamName)(''); expect(typeof name).toBe('string'); expect(name.length).toBeGreaterThan(0); }); }); describe('getIsAppropriateStream', () => { it('should return true for appropriate stream', () => { const executionId = 'test-execution-123'; const entryEmitCount = 5; const stack = [ { id: 'obs-1', name: 'test-observable', emitCount: 3, isError: false, }, { id: executionId, name: `createStream:${executionId}`, emitCount: entryEmitCount, isError: false, }, ]; const result = (0, stream_1.getIsAppropriateStream)(stack, executionId, entryEmitCount); expect(result).toBe(true); }); it('should return false for inappropriate stream', () => { const executionId = 'test-execution-123'; const entryEmitCount = 5; const stack = [ { id: 'obs-1', name: 'test-observable', emitCount: 3, isError: false, }, { id: 'different-execution', name: 'createStream:different-execution', emitCount: 10, isError: false, }, ]; const result = (0, stream_1.getIsAppropriateStream)(stack, executionId, entryEmitCount); expect(result).toBe(false); }); it('should return false for empty stack', () => { const executionId = 'test-execution-123'; const entryEmitCount = 5; const result = (0, stream_1.getIsAppropriateStream)([], executionId, entryEmitCount); expect(result).toBe(false); }); it('should return false for undefined stack', () => { const executionId = 'test-execution-123'; const entryEmitCount = 5; const result = (0, stream_1.getIsAppropriateStream)(undefined, executionId, entryEmitCount); expect(result).toBe(false); }); it('should handle stack with multiple execution IDs', () => { const executionId = 'test-execution-123'; const entryEmitCount = 5; const stack = [ { id: 'obs-1', name: 'test-observable', emitCount: 3, isError: false, }, { id: 'old-execution', name: 'createStream:old-execution', emitCount: 2, isError: false, }, { id: executionId, name: `createStream:${executionId}`, emitCount: entryEmitCount, isError: false, }, ]; const result = (0, stream_1.getIsAppropriateStream)(stack, executionId, entryEmitCount); expect(result).toBe(true); }); it('should handle error stack items', () => { const executionId = 'test-execution-123'; const entryEmitCount = 5; const stack = [ { id: 'obs-1', name: 'test-observable', emitCount: 3, isError: true, }, { id: executionId, name: `createStream:${executionId}`, emitCount: entryEmitCount, isError: false, }, ]; const result = (0, stream_1.getIsAppropriateStream)(stack, executionId, entryEmitCount); expect(result).toBe(true); }); }); describe('wrapObservable', () => { it('should wrap observable with subscription tracking', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'test' }); const unsubscribeSpy = jest.fn(); const handleSubscription = jest.fn().mockReturnValue(unsubscribeSpy); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); expect(wrapped).toBe(obs); // Should return same observable expect(handleSubscription).toHaveBeenCalled(); }); it('should track subscriptions when observable is used', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'test' }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); const unsubscribe = wrapped.subscribe(() => { }); expect(handleSubscription).toHaveBeenCalledWith(unsubscribe); }); it('should handle multiple subscriptions', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'test' }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); const unsubscribe1 = wrapped.subscribe(() => { }); const unsubscribe2 = wrapped.subscribe(() => { }); expect(handleSubscription).toHaveBeenCalledWith(unsubscribe1); expect(handleSubscription).toHaveBeenCalledWith(unsubscribe2); expect(handleSubscription).toHaveBeenCalledTimes(2); }); it('should handle different subscription types', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'test' }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); // Test different subscription methods const sub1 = wrapped.subscribe(() => { }); const sub2 = wrapped.subscribeOnce(() => { }); const sub3 = wrapped.subscribeWithValue(() => { }); expect(handleSubscription).toHaveBeenCalledTimes(3); }); it('should maintain observable functionality', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'initial' }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); // Test that wrapped observable maintains all functionality expect(wrapped.get()).toBe('initial'); wrapped.set('updated'); expect(wrapped.get()).toBe('updated'); const listener = jest.fn(); wrapped.subscribe(listener); wrapped.set('new value'); expect(listener).toHaveBeenCalledWith('new value', expect.any(Array)); }); it('should handle stream operations', () => { const obs = (0, observable_1.createObservable)({ initialValue: 5 }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); const streamed = wrapped.stream((val) => val * 2); expect(streamed.get()).toBe(10); // Should track subscriptions from stream operations const listener = jest.fn(); streamed.subscribe(listener); expect(handleSubscription).toHaveBeenCalled(); }); it('should handle async stream operations', async () => { const obs = (0, observable_1.createObservable)({ initialValue: 5 }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); const streamed = wrapped.streamAsync(async (val) => { await new Promise((resolve) => setTimeout(resolve, 10)); return val * 2; }); // Wait for async operation await new Promise((resolve) => setTimeout(resolve, 20)); expect(streamed.get()).toBe(10); expect(handleSubscription).toHaveBeenCalled(); }); it('should handle combination operations', () => { const obs1 = (0, observable_1.createObservable)({ initialValue: 'a' }); const obs2 = (0, observable_1.createObservable)({ initialValue: 1 }); const handleSubscription = jest.fn(); const wrapped1 = (0, stream_1.wrapObservable)(obs1, handleSubscription); const wrapped2 = (0, stream_1.wrapObservable)(obs2, handleSubscription); const combined = wrapped1.combineLatestFrom(wrapped2); expect(combined.get()).toEqual(['a', 1]); expect(handleSubscription).toHaveBeenCalled(); }); it('should handle error operations', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'test' }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); const errorHandler = jest.fn(); wrapped.subscribe(undefined, errorHandler); wrapped.emitError(new Error('Test error')); expect(errorHandler).toHaveBeenCalledWith(expect.any(Error), expect.any(Array)); }); it('should handle completion operations', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'test' }); const handleSubscription = jest.fn(); const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); const completeHandler = jest.fn(); wrapped.subscribe(undefined, undefined, completeHandler); wrapped.emitComplete(); expect(completeHandler).toHaveBeenCalledWith(expect.any(Array)); }); }); describe('Integration tests', () => { it('should work together in complex scenarios', () => { const obs = (0, observable_1.createObservable)({ initialValue: 'initial' }); const handleSubscription = jest.fn(); // Create wrapped observable const wrapped = (0, stream_1.wrapObservable)(obs, handleSubscription); // Create stream name const streamName = (0, stream_1.createStreamName)('test'); expect(streamName).toMatch(/^test:/); // Test stream operations const streamed = wrapped.stream((val) => val.toUpperCase()); expect(streamed.get()).toBe('INITIAL'); // Test subscription tracking const listener = jest.fn(); streamed.subscribe(listener); expect(handleSubscription).toHaveBeenCalled(); // Test stack tracking const executionId = 'test-execution-123'; const entryEmitCount = 5; const stack = [ { id: executionId, name: `createStream:${executionId}`, emitCount: entryEmitCount, isError: false, }, ]; const isAppropriate = (0, stream_1.getIsAppropriateStream)(stack, executionId, entryEmitCount); expect(isAppropriate).toBe(true); }); it('should handle multiple observables and streams', () => { const obs1 = (0, observable_1.createObservable)({ initialValue: 'a' }); const obs2 = (0, observable_1.createObservable)({ initialValue: 1 }); const handleSubscription = jest.fn(); const wrapped1 = (0, stream_1.wrapObservable)(obs1, handleSubscription); const wrapped2 = (0, stream_1.wrapObservable)(obs2, handleSubscription); const combined = wrapped1.combineLatestFrom(wrapped2); const streamed = combined.stream(([str, num]) => `${str}-${num}`); expect(streamed.get()).toBe('a-1'); // Test subscription tracking for all observables const listener = jest.fn(); streamed.subscribe(listener); expect(handleSubscription).toHaveBeenCalled(); }); }); });