You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
snabbdom/test/unit/thunk.ts

232 lines
7.3 KiB
TypeScript

import { assert } from 'chai'
import { init, h, thunk, VNode } from '../../src/index';
const patch = init([
])
describe('thunk', function () {
let elm: any, vnode0: any
beforeEach(function () {
elm = vnode0 = document.createElement('div')
})
it('returns vnode with data and render function', function () {
function numberInSpan (n: number) {
return h('span', 'Number is ' + n)
}
const vnode = thunk('span', 'num', numberInSpan, [22])
assert.deepEqual(vnode.sel, 'span')
assert.deepEqual(vnode.data.key, 'num')
assert.deepEqual(vnode.data.args, [22])
})
it('calls render function once on data change', function () {
let called = 0
function numberInSpan (n: number) {
called++
return h('span', { key: 'num' }, 'Number is ' + n)
}
const vnode1 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
const vnode2 = h('div', [
thunk('span', 'num', numberInSpan, [2])
])
patch(vnode0, vnode1)
assert.strictEqual(called, 1)
patch(vnode1, vnode2)
assert.strictEqual(called, 2)
})
it('does not call render function on data unchanged', function () {
let called = 0
function numberInSpan (n: number) {
called++
return h('span', { key: 'num' }, 'Number is ' + n)
}
const vnode1 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
const vnode2 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
patch(vnode0, vnode1)
assert.strictEqual(called, 1)
patch(vnode1, vnode2)
assert.strictEqual(called, 1)
})
it('calls render function once on data-length change', function () {
let called = 0
function numberInSpan (n: number) {
called++
return h('span', { key: 'num' }, 'Number is ' + n)
}
const vnode1 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
const vnode2 = h('div', [
thunk('span', 'num', numberInSpan, [1, 2])
])
patch(vnode0, vnode1)
assert.strictEqual(called, 1)
patch(vnode1, vnode2)
assert.strictEqual(called, 2)
})
it('calls render function once on function change', function () {
let called = 0
function numberInSpan (n: number) {
called++
return h('span', { key: 'num' }, 'Number is ' + n)
}
function numberInSpan2 (n: number) {
called++
return h('span', { key: 'num' }, 'Number really is ' + n)
}
const vnode1 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
const vnode2 = h('div', [
thunk('span', 'num', numberInSpan2, [1])
])
patch(vnode0, vnode1)
assert.strictEqual(called, 1)
patch(vnode1, vnode2)
assert.strictEqual(called, 2)
})
it('renders correctly', function () {
let called = 0
function numberInSpan (n: number) {
called++
return h('span', { key: 'num' }, 'Number is ' + n)
}
const vnode1 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
const vnode2 = h('div', [
thunk('span', 'num', numberInSpan, [1])
])
const vnode3 = h('div', [
thunk('span', 'num', numberInSpan, [2])
])
elm = patch(vnode0, vnode1).elm
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 1')
elm = patch(vnode1, vnode2).elm
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 1')
elm = patch(vnode2, vnode3).elm
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 2')
assert.strictEqual(called, 2)
})
it('supports leaving out the `key` argument', function () {
function vnodeFn (s: string) {
return h('span.number', 'Hello ' + s)
}
const vnode1 = thunk('span.number', vnodeFn, ['World!'])
elm = patch(vnode0, vnode1).elm
assert.strictEqual(elm.innerText, 'Hello World!')
})
it('renders correctly when root', function () {
let called = 0
function numberInSpan (n: number) {
called++
return h('span', { key: 'num' }, 'Number is ' + n)
}
const vnode1 = thunk('span', 'num', numberInSpan, [1])
const vnode2 = thunk('span', 'num', numberInSpan, [1])
const vnode3 = thunk('span', 'num', numberInSpan, [2])
elm = patch(vnode0, vnode1).elm
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.innerHTML, 'Number is 1')
elm = patch(vnode1, vnode2).elm
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.innerHTML, 'Number is 1')
elm = patch(vnode2, vnode3).elm
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.innerHTML, 'Number is 2')
assert.strictEqual(called, 2)
})
it('can be replaced and removed', function () {
function numberInSpan (n: number) {
return h('span', { key: 'num' }, 'Number is ' + n)
}
function oddEven (n: number): VNode {
const prefix = (n % 2) === 0 ? 'Even' : 'Odd'
return h('div', { key: oddEven as any }, prefix + ': ' + n)
}
const vnode1 = h('div', [thunk('span', 'num', numberInSpan, [1])])
const vnode2 = h('div', [thunk('div', 'oddEven', oddEven, [4])])
elm = patch(vnode0, vnode1).elm
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.firstChild.innerHTML, 'Number is 1')
elm = patch(vnode1, vnode2).elm
assert.strictEqual(elm.firstChild.tagName.toLowerCase(), 'div')
assert.strictEqual(elm.firstChild.innerHTML, 'Even: 4')
})
it('can be replaced and removed when root', function () {
function numberInSpan (n: number) {
return h('span', { key: 'num' }, 'Number is ' + n)
}
function oddEven (n: number): VNode {
const prefix = (n % 2) === 0 ? 'Even' : 'Odd'
return h('div', { key: oddEven as any }, prefix + ': ' + n)
}
const vnode1 = thunk('span', 'num', numberInSpan, [1])
const vnode2 = thunk('div', 'oddEven', oddEven, [4])
elm = patch(vnode0, vnode1).elm
assert.strictEqual(elm.tagName.toLowerCase(), 'span')
assert.strictEqual(elm.innerHTML, 'Number is 1')
elm = patch(vnode1, vnode2).elm
assert.strictEqual(elm.tagName.toLowerCase(), 'div')
assert.strictEqual(elm.innerHTML, 'Even: 4')
})
it('invokes destroy hook on thunks', function () {
let called = 0
function destroyHook () {
called++
}
function numberInSpan (n: number) {
return h('span', { key: 'num', hook: { destroy: destroyHook } }, 'Number is ' + n)
}
const vnode1 = h('div', [
h('div', 'Foo'),
thunk('span', 'num', numberInSpan, [1]),
h('div', 'Foo')
])
const vnode2 = h('div', [
h('div', 'Foo'),
h('div', 'Foo')
])
patch(vnode0, vnode1)
patch(vnode1, vnode2)
assert.strictEqual(called, 1)
})
it('invokes remove hook on thunks', function () {
let called = 0
function hook () {
called++
}
function numberInSpan (n: number) {
return h('span', { key: 'num', hook: { remove: hook } }, 'Number is ' + n)
}
const vnode1 = h('div', [
h('div', 'Foo'),
thunk('span', 'num', numberInSpan, [1]),
h('div', 'Foo')
])
const vnode2 = h('div', [
h('div', 'Foo'),
h('div', 'Foo')
])
patch(vnode0, vnode1)
patch(vnode1, vnode2)
assert.strictEqual(called, 1)
})
})