import { Progress } from '../..'; import { bind } from './bind'; import { frag, html } from 'typed-dom/dom'; describe('Unit: api/bind', () => { describe('bind', () => { function inspect(iter: IterableIterator, count = Infinity) { const acc: (string | undefined)[] = []; for (let i = 0; i < count; ++i) { const result = iter.next(); if (result.done) break; switch (result.value.type) { case 'segment': case 'figure': case 'note': case 'break': --i; continue; case 'block': result.value.value.parentNode ? acc.push(result.value.value.outerHTML) : --i; continue; default: acc.push(undefined); continue; } } return acc; } const cfgs = { notes: { references: html('ol') } }; it('empty', () => { const el = html('div'); const update = bind(el, cfgs).parse; // init with empty assert.deepStrictEqual(inspect(update('')), []); assert(el.innerHTML === ''); // update with no changes assert.deepStrictEqual(inspect(update('')), []); assert(el.innerHTML === ''); }); it('update', () => { const el = html('div', [html('ol')]); const update = bind(el, cfgs).parse; // init with nonempty assert.deepStrictEqual(inspect(update('0')), ['

0

']); assert(el.innerHTML === '

0

    '); // update with no changes assert.deepStrictEqual(inspect(update('0')), []); assert(el.innerHTML === '

    0

      '); // clear assert.deepStrictEqual(inspect(update('')), []); assert(el.innerHTML === '
        '); // format assert.deepStrictEqual(inspect(update('1\n\n0\n\n9\n\n')), ['

        1

        ', '

        0

        ', '

        9

        ']); assert(el.innerHTML === '

        1

        0

        9

          '); // change top segments assert.deepStrictEqual(inspect(update('9\n\n5\n\n9\n\n')), ['

          9

          ', '

          5

          ']); assert(el.innerHTML === '

          9

          5

          9

            '); // change bottom segments assert.deepStrictEqual(inspect(update('9\n\n0\n\n1\n\n')), ['

            0

            ', '

            1

            ']); assert(el.innerHTML === '

            9

            0

            1

              '); // change middle segments assert.deepStrictEqual(inspect(update('9\n\n5\n\n1\n\n')), ['

              5

              ']); assert(el.innerHTML === '

              9

              5

              1

                '); // change segments at the both ends assert.deepStrictEqual(inspect(update('1\n\n5\n\n9\n\n')), ['

                1

                ', '

                5

                ', '

                9

                ']); assert(el.innerHTML === '

                1

                5

                9

                  '); // insert assert.deepStrictEqual(inspect(update('1\n\n2\n\n3\n\n9\n\n')), ['

                  2

                  ', '

                  3

                  ']); assert(el.innerHTML === '

                  1

                  2

                  3

                  9

                    '); // remove assert.deepStrictEqual(inspect(update('1\n\n0\n\n9\n\n')), ['

                    0

                    ']); assert(el.innerHTML === '

                    1

                    0

                    9

                      '); // format assert.deepStrictEqual(inspect(update('1\n\n0\n\n9\n\n')), []); assert(el.innerHTML === '

                      1

                      0

                      9

                        '); // repeat the top segment assert.deepStrictEqual(inspect(update('1\n\n1\n\n0\n\n9\n\n')), ['

                        1

                        ']); assert(el.innerHTML === '

                        1

                        1

                        0

                        9

                          '); // repeat the bottom segment assert.deepStrictEqual(inspect(update('1\n\n1\n\n0\n\n9\n\n9\n\n')), ['

                          9

                          ']); assert(el.innerHTML === '

                          1

                          1

                          0

                          9

                          9

                            '); // format assert.deepStrictEqual(inspect(update('1\n\n0\n\n9\n\n'.repeat(1))), ['

                            0

                            ']); assert(el.innerHTML === '

                            1

                            0

                            9

                              '); // repeat assert.deepStrictEqual(inspect(update('1\n\n0\n\n9\n\n'.repeat(2))), ['

                              1

                              ', '

                              0

                              ', '

                              9

                              ']); assert(el.innerHTML === '

                              1

                              0

                              9

                              1

                              0

                              9

                                '); // unrepeat assert.deepStrictEqual(inspect(update('1\n\n0\n\n9\n\n'.repeat(1))), []); assert(el.innerHTML === '

                                1

                                0

                                9

                                  '); }); it('complex', () => { assert.deepStrictEqual(inspect(bind(html('div'), cfgs).parse('# a\n# b')), ['

                                  a

                                  ', '

                                  b

                                  ']); }); it('normalize', () => { assert.deepStrictEqual(inspect(bind(html('div'), cfgs).parse('a\\\r\nb')), ['

                                  a
                                  b

                                  ']); }); it('reentrant', () => { const el = html('div'); const update = bind(el, cfgs).parse; const iter = update('0\n\n1\n'); assert.deepStrictEqual(inspect(iter, 1), ['

                                  0

                                  ']); assert.deepStrictEqual(inspect(update('0\n\n1\n\n2')), ['

                                  1

                                  ', '

                                  2

                                  ']); assert(el.innerHTML === '

                                  0

                                  1

                                  2

                                  '); assert.deepStrictEqual(inspect(update('3\n')), ['

                                  3

                                  ']); assert(el.innerHTML === '

                                  3

                                  '); assert.deepStrictEqual(inspect(iter, 1), [undefined]); assert.deepStrictEqual(inspect(iter, 1), []); assert(el.innerHTML === '

                                  3

                                  '); assert.deepStrictEqual(inspect(update('3\n\n4')), ['

                                  4

                                  ']); assert(el.innerHTML === '

                                  3

                                  4

                                  '); }); it('concurrency', () => { const el = html('div'); const update = bind(el, cfgs).parse; assert.deepStrictEqual(inspect(update('1\n'), 1), ['

                                  1

                                  ']); assert(el.innerHTML === '

                                  1

                                  '); assert.deepStrictEqual(inspect(update('1\n\n3\n\n4'), 1), ['

                                  3

                                  ']); assert(el.innerHTML === '

                                  1

                                  3

                                  '); assert.deepStrictEqual(inspect(update('1\n\n2\n\n4'), 4), ['

                                  2

                                  ', '

                                  4

                                  ']); assert(el.innerHTML === '

                                  1

                                  2

                                  4

                                  '); [...update('')]; assert(el.innerHTML === ''); assert.deepStrictEqual(inspect(update('# a\n# b'), 1), ['

                                  a

                                  ']); assert(el.innerHTML === '

                                  a

                                  '); assert.deepStrictEqual(inspect(update('# a\n# b'), 2), ['

                                  b

                                  ']); assert(el.innerHTML === '

                                  a

                                  b

                                  '); }); it('chunk', () => { const el = html('div'); const chunk = frag(); const update = bind(chunk, { ...cfgs, chunk: true }).parse; const iter = update([...Array(3)].map((_, i) => `[[${i + 1}]]`).join('\n\n')); inspect(iter, 2); el.appendChild(chunk); assert.deepStrictEqual( [...el.children].map(el => el.outerHTML), [ html('p', [html('sup', { class: "reference" }, [html('span', '1')]),]).outerHTML, html('p', [html('sup', { class: "reference" }, [html('span', '2')]),]).outerHTML, ]); inspect(iter, 1); el.appendChild(chunk); assert.deepStrictEqual( [...el.children].map(el => el.outerHTML), [ html('p', [html('sup', { class: "reference" }, [html('span', '1')]),]).outerHTML, html('p', [html('sup', { class: "reference" }, [html('span', '2')]),]).outerHTML, html('p', [html('sup', { class: "reference" }, [html('span', '3')]),]).outerHTML, ]); inspect(iter); assert.deepStrictEqual( [...el.children].map(el => el.outerHTML), [ html('p', [ html('sup', { class: "reference", id: "reference::ref:1:1", title: "1" }, [ html('a', { href: "#reference::def:1" }, '[1]'), ]), ]).outerHTML, html('p', [ html('sup', { class: "reference", id: "reference::ref:2:1", title: "2" }, [ html('a', { href: "#reference::def:2" }, '[2]'), ]), ]).outerHTML, html('p', [ html('sup', { class: "reference", id: "reference::ref:3:1", title: "3" }, [ html('a', { href: "#reference::def:3" }, '[3]'), ]), ]).outerHTML, ]); assert.deepStrictEqual( cfgs.notes.references?.outerHTML, html('ol', [ html('li', { id: 'reference::def:1' }, [ html('span', '1'), html('sup', [html('a', { href: '#reference::ref:1:1' }, '^1')]), ]), html('li', { id: 'reference::def:2' }, [ html('span', '2'), html('sup', [html('a', { href: '#reference::ref:2:1' }, '^2')]), ]), html('li', { id: 'reference::def:3' }, [ html('span', '3'), html('sup', [html('a', { href: '#reference::ref:3:1' }, '^3')]), ]), ]).outerHTML); assert.throws(() => update('').next()); }); }); });