Skip to content

GlIntersperse renders extra separators for conditional elements in Vue 3

Description

GlIntersperse allows us to pass conditional/empty nodes to it, for example:

<gl-intersperse>
  <span>one</span>
  <span>two</span>
  <span v-if="condition">three</span>
</gl-intersperse>

Should yield one, two, three or one, two depending on the value of condition.

However, in Vue, 3 it renders one, two, three or one, two,, as it considers the node with v-if a non-empty.

How to reproduce

I was able to reproduce this in our unit tests by adding a new case with a v-if.

diff --git a/src/components/utilities/intersperse/intersperse.spec.js b/src/components/utilities/intersperse/intersperse.spec.js
index 7c7a2aa22..25f570295 100644
--- a/src/components/utilities/intersperse/intersperse.spec.js
+++ b/src/components/utilities/intersperse/intersperse.spec.js
@@ -91,6 +91,7 @@ describe('Intersperse Component', () => {
     ${'<i>Foo</i>&nbsp;<i>Bar</i>'} | ${'Foo, Bar'}
     ${'<i>Foo</i><i>Bar</i>  '}     | ${'Foo, Bar'}
     ${'<i>Foo</i><i>Bar</i>\n'}     | ${'Foo, Bar'}
+    ${'<i>Foo</i><i>Bar</i><i v-if="false">Baz</i>\n'}     | ${'Foo, Bar'}
   `(
     'strips whitespace elements that are direct children of the slot',
     ({ defaultSlotContent, expectedText }) => {

When running $ yarn test:unit-vue3:watch, this test fails due to the extra comma in the result:

  ● Intersperse Component › strips whitespace elements that are direct children of the slot

    expect(received).toBe(expected) // Object.is equality

    Expected: "Foo, Bar"
    Received: "Foo, Bar,"

       98 |       createComponent(defaultSlotContent);
       99 |
    > 100 |       expect(wrapper.text()).toBe(expectedText);
          |                              ^
      101 |     }
      102 |   );
      103 |

      at toBe (src/components/utilities/intersperse/intersperse.spec.js:100:30)

Impact

I first noticed this when fixing Vue 3 tests for GitLab at:

Edited by Miguel Rincon