Преглед на файлове

Bug - morph lookahead and keys (#2544)

* Add failing tests

* Set lookahead default value to false and fix bugs

Co-authored-by: Caleb Porzio <calebporzio@gmail.com>
Simone Todaro преди 3 години
родител
ревизия
ef6511e59c
променени са 2 файла, в които са добавени 128 реда и са изтрити 7 реда
  1. 14 6
      packages/morph/src/morph.js
  2. 114 1
      tests/cypress/integration/plugins/morph.spec.js

+ 14 - 6
packages/morph/src/morph.js

@@ -57,7 +57,7 @@ function assignOptions(options = {}) {
     adding = options.adding || noop
     adding = options.adding || noop
     added = options.added || noop
     added = options.added || noop
     key = options.key || defaultGetKey
     key = options.key || defaultGetKey
-    lookahead = options.lookahead || true
+    lookahead = options.lookahead || false
     debug = options.debug || false
     debug = options.debug || false
 }
 }
 
 
@@ -190,7 +190,7 @@ async function patchChildren(from, to) {
             if (toKey && domKeyHoldovers[toKey]) {
             if (toKey && domKeyHoldovers[toKey]) {
                 let holdover = domKeyHoldovers[toKey]
                 let holdover = domKeyHoldovers[toKey]
 
 
-                dom.append(from, holdover)
+                dom(from).append(holdover)
                 currentFrom = holdover
                 currentFrom = holdover
 
 
                 await breakpoint('Add element (from key)')
                 await breakpoint('Add element (from key)')
@@ -208,12 +208,20 @@ async function patchChildren(from, to) {
         if (lookahead) {
         if (lookahead) {
             let nextToElementSibling = dom(currentTo).next()
             let nextToElementSibling = dom(currentTo).next()
 
 
-            if (nextToElementSibling && currentFrom.isEqualNode(nextToElementSibling)) {
-                currentFrom = addNodeBefore(currentTo, currentFrom)
+            let found = false
+
+            while (!found && nextToElementSibling) {
+                if (currentFrom.isEqualNode(nextToElementSibling)) {
+                    found = true
+
+                    currentFrom = addNodeBefore(currentTo, currentFrom)
+
+                    domKey = getKey(currentFrom)
 
 
-                domKey = getKey(currentFrom)
+                    await breakpoint('Move element (lookahead)')
+                }
 
 
-                await breakpoint('Move element (lookahead)')
+                nextToElementSibling = dom(nextToElementSibling).next()
             }
             }
         }
         }
 
 

+ 114 - 1
tests/cypress/integration/plugins/morph.spec.js

@@ -1,4 +1,4 @@
-import { haveText, haveHtml, html, test } from '../../utils'
+import { haveLength, haveText, haveValue, haveHtml, html, test } from '../../utils'
 
 
 test('can morph components and preserve Alpine state',
 test('can morph components and preserve Alpine state',
     [html`
     [html`
@@ -134,6 +134,119 @@ test('can morph teleports',
     },
     },
 )
 )
 
 
+test('can morph',
+    [html`
+        <ul>
+            <li>foo<input></li>
+        </ul>
+    `],
+    ({ get }, reload, window, document) => {
+        let toHtml = html`
+            <ul>
+                <li>bar<input></li>
+                <li>foo<input></li>
+            </ul>
+        `
+
+        get('input').type('foo')
+
+        get('ul').then(([el]) => window.Alpine.morph(el, toHtml))
+
+        get('li').should(haveLength(2))
+        get('li:nth-of-type(1)').should(haveText('bar'))
+        get('li:nth-of-type(2)').should(haveText('foo'))
+        get('li:nth-of-type(1) input').should(haveValue('foo'))
+        get('li:nth-of-type(2) input').should(haveValue(''))
+    },
+)
+
+test('can morph using lookahead',
+    [html`
+        <ul>
+            <li>foo<input></li>
+        </ul>
+    `],
+    ({ get }, reload, window, document) => {
+        let toHtml = html`
+            <ul>
+                <li>bar<input></li>
+                <li>baz<input></li>
+                <li>foo<input></li>
+            </ul>
+        `
+
+        get('input').type('foo')
+
+        get('ul').then(([el]) => window.Alpine.morph(el, toHtml, {lookahead: true}))
+
+        get('li').should(haveLength(3))
+        get('li:nth-of-type(1)').should(haveText('bar'))
+        get('li:nth-of-type(2)').should(haveText('baz'))
+        get('li:nth-of-type(3)').should(haveText('foo'))
+        get('li:nth-of-type(1) input').should(haveValue(''))
+        get('li:nth-of-type(2) input').should(haveValue(''))
+        get('li:nth-of-type(3) input').should(haveValue('foo'))
+    },
+)
+
+test('can morph using keys',
+    [html`
+        <ul>
+            <li key="1">foo<input></li>
+        </ul>
+    `],
+    ({ get }, reload, window, document) => {
+        let toHtml = html`
+            <ul>
+                <li key="2">bar<input></li>
+                <li key="3">baz<input></li>
+                <li key="1">foo<input></li>
+            </ul>
+        `
+
+        get('input').type('foo')
+
+        get('ul').then(([el]) => window.Alpine.morph(el, toHtml))
+
+        get('li').should(haveLength(3))
+        get('li:nth-of-type(1)').should(haveText('bar'))
+        get('li:nth-of-type(2)').should(haveText('baz'))
+        get('li:nth-of-type(3)').should(haveText('foo'))
+        get('li:nth-of-type(1) input').should(haveValue(''))
+        get('li:nth-of-type(2) input').should(haveValue(''))
+        get('li:nth-of-type(3) input').should(haveValue('foo'))
+    },
+)
+
+test('can morph using a custom key function',
+    [html`
+        <ul>
+            <li data-key="1">foo<input></li>
+        </ul>
+    `],
+    ({ get }, reload, window, document) => {
+        let toHtml = html`
+            <ul>
+                <li data-key="2">bar<input></li>
+                <li data-key="3">baz<input></li>
+                <li data-key="1">foo<input></li>
+            </ul>
+        `
+
+        get('input').type('foo')
+
+        get('ul').then(([el]) => window.Alpine.morph(el, toHtml, {key(el) {return el.dataset.key}}))
+
+        get('li').should(haveLength(3))
+        get('li:nth-of-type(1)').should(haveText('bar'))
+        get('li:nth-of-type(2)').should(haveText('baz'))
+        get('li:nth-of-type(3)').should(haveText('foo'))
+        get('li:nth-of-type(1) input').should(haveValue(''))
+        get('li:nth-of-type(2) input').should(haveValue(''))
+        get('li:nth-of-type(3) input').should(haveValue('foo'))
+    },
+)
+
 test('can morph text nodes',
 test('can morph text nodes',
     [html`<h2>Foo <br> Bar</h2>`],
     [html`<h2>Foo <br> Bar</h2>`],
     ({ get }, reload, window, document) => {
     ({ get }, reload, window, document) => {