@idiosync/react-observable
Version:
State management control layer for React projects
277 lines (276 loc) • 13.3 kB
JavaScript
"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();
});
});
});