import {isIE10} from './setup'; import * as assert from 'assert'; import isolate from '@cycle/isolate'; import xs, {Stream, MemoryStream} from 'xstream'; import delay from 'xstream/extra/delay'; import concat from 'xstream/extra/concat'; import {setup, run as cycleRun} from '@cycle/run'; const Snabbdom = require('snabbdom-pragma'); import { h, svg, div, thunk, span, h2, h3, h4, button, select, option, p, makeDOMDriver, DOMSource, MainDOMSource, VNode, } from '../../src/index'; declare global { namespace JSX { interface Element extends VNode {} // tslint:disable-line interface IntrinsicElements { [elemName: string]: any; } } } function createRenderTarget(id: string | null = null) { const element = document.createElement('div'); element.className = 'cycletest'; if (id) { element.id = id; } document.body.appendChild(element); return element; } describe('DOM Rendering', function() { it('should render DOM elements even when DOMSource is not utilized', function(done) { function main() { return { DOM: xs.of( div('.my-render-only-container', [h2('Cycle.js framework')]) ), }; } cycleRun(main, { DOM: makeDOMDriver(createRenderTarget()), }); setTimeout(() => { const myContainer = document.querySelector( '.my-render-only-container' ) as HTMLElement; assert.notStrictEqual(myContainer, null); assert.notStrictEqual(typeof myContainer, 'undefined'); assert.strictEqual(myContainer.tagName, 'DIV'); const header = myContainer.querySelector('h2') as HTMLElement; assert.notStrictEqual(header, null); assert.notStrictEqual(typeof header, 'undefined'); assert.strictEqual(header.textContent, 'Cycle.js framework'); done(); }, 150); }); it('should support snabbdom dataset module by default', function(done) { const thisBrowserSupportsDataset = typeof document.createElement('DIV').dataset !== 'undefined'; function app(_sources: {DOM: MainDOMSource}) { return { DOM: xs.of( div('.my-class', { dataset: {foo: 'Foo'}, }) ), }; } if (!thisBrowserSupportsDataset) { done(); } else { const {sinks, sources, run} = setup(app, { DOM: makeDOMDriver(createRenderTarget()), }); let dispose: any; sources.DOM.select(':root') .element() .drop(1) .take(1) .addListener({ next: (root: Element) => { const elem = root.querySelector('.my-class') as HTMLElement; assert.notStrictEqual(elem, null); assert.notStrictEqual(typeof elem, 'undefined'); assert.strictEqual(elem.tagName, 'DIV'); assert.strictEqual(elem.dataset.foo, 'Foo'); setTimeout(() => { dispose(); done(); }); }, }); dispose = run(); } }); it('should render in a DocumentFragment as container', function(done) { if (isIE10) { done(); return; } function app(_sources: {DOM: MainDOMSource}) { return { DOM: xs.of( select('.my-class', [ option({attrs: {value: 'foo'}}, 'Foo'), option({attrs: {value: 'bar'}}, 'Bar'), option({attrs: {value: 'baz'}}, 'Baz'), ]) ), }; } const docfrag = document.createDocumentFragment(); const {sinks, sources, run} = setup(app, { DOM: makeDOMDriver(docfrag), }); let dispose: any; sources.DOM.select(':root') .element() .drop(1) .take(1) .addListener({ next: (root: Element) => { const selectEl = root.querySelector('.my-class') as HTMLElement; assert.notStrictEqual(selectEl, null); assert.notStrictEqual(typeof selectEl, 'undefined'); assert.strictEqual(selectEl.tagName, 'SELECT'); const options = selectEl.querySelectorAll('option'); assert.strictEqual(options.length, 3); setTimeout(() => { dispose(); done(); }); }, }); dispose = run(); }); it('should convert a simple virtual-dom (JSX) to DOM element', function(done) { function app(_sources: {DOM: DOMSource}) { return { DOM: xs.of( ), }; } const {sinks, sources, run} = setup(app, { DOM: makeDOMDriver(createRenderTarget()), }); let dispose: any; sources.DOM.select(':root') .element() .drop(1) .take(1) .addListener({ next: (root: Element) => { const selectEl = root.querySelector('.my-class') as HTMLSelectElement; assert.notStrictEqual(selectEl, null); assert.notStrictEqual(typeof selectEl, 'undefined'); assert.strictEqual(selectEl.tagName, 'SELECT'); setTimeout(() => { dispose(); done(); }); }, }); dispose = run(); }); it('should reuse existing DOM tree under the given root element', function(done) { function app(_sources: {DOM: MainDOMSource}) { return { DOM: xs.of( select('.my-class', [ option({attrs: {value: 'foo'}}, 'Foo'), option({attrs: {value: 'bar'}}, 'Bar'), option({attrs: {value: 'baz'}}, 'Baz'), ]) ), }; } // Create DOM tree with 2