import { Stream , empty } from 'most' ; import { DomSource } from './types' ; import { VNode } from 'mostly-dom' ; export interface MockConfig { readonly [ key ] : MockConfig | Stream < any > ; } export function mockDomSource ( mockConfig ? ) { return new MockDomSource ( mockConfig || { } , [ ] ) ; } const SCOPE_PREFIX = `___` ; class MockDomSource implements DomSource { private mockConfig : MockConfig & { elements ? : Stream < Array < HTMLElement > > ; } ; private internalNamespace : Array < string > ; public isolateSink = isolateSink ; public isolateSource = isolateSource ; constructor ( mockConfig , namespace ) { this . mockConfig = mockConfig ; this . internalNamespace = namespace ; } public namespace ( ) { return this . internalNamespace ; } public select ( selector ) { const trimmedSelector = selector . trim ( ) ; const updatedNamespace = this . internalNamespace . concat ( trimmedSelector ) ; const mockConfig = this . mockConfig [ selector ] as MockConfig || { } ; return new MockDomSource ( mockConfig , updatedNamespace ) ; } public elements < T extends Element > ( ) { return ( this . mockConfig . elements || empty ( ) ) as Stream < Array < T > > ; } public events < T extends Event > ( eventType ) { return ( this . mockConfig [ eventType ] || empty ( ) ) as Stream < T > ; } } function isolateSource ( source , scope ) { return source . select ( `${ SCOPE_PREFIX }${ scope }` ) ; } function isolateSink < T extends VNode > ( vNode$ , scope ) { const generatedScope = `${ SCOPE_PREFIX }${ scope }` ; return vNode$ . tap ( ( vNode ) => { if ( vNode . className && vNode . className . indexOf ( generatedScope ) === - 1 ) vNode . className = ( ( vNode . className || '' ) + generatedScope ) . trim ( ) ; } ) ; }