test/unit/features/component/component-slot.spec.ts TYPESCRIPT 1,077 lines View on github.com → Search inside
1import Vue from 'vue'23describe('Component slot', () => {4  let vm, child5  function mount(options) {6    vm = new Vue({7      data: {8        msg: 'parent message'9      },10      template: `<div><test>${options.parentContent || ''}</test></div>`,11      components: {12        test: {13          template: options.childTemplate,14          data() {15            return {16              msg: 'child message'17            }18          }19        }20      }21    }).$mount()22    child = vm.$children[0]23  }2425  it('no content', () => {26    mount({27      childTemplate: '<div><slot></slot></div>'28    })29    expect(child.$el.childNodes.length).toBe(0)30  })3132  it('default slot', done => {33    mount({34      childTemplate: '<div><slot></slot></div>',35      parentContent: '<p>{{ msg }}</p>'36    })37    expect(child.$el.tagName).toBe('DIV')38    expect(child.$el.children[0].tagName).toBe('P')39    expect(child.$el.children[0].textContent).toBe('parent message')40    vm.msg = 'changed'41    waitForUpdate(() => {42      expect(child.$el.children[0].textContent).toBe('changed')43    }).then(done)44  })4546  it('named slot', done => {47    mount({48      childTemplate: '<div><slot name="test"></slot></div>',49      parentContent: '<p slot="test">{{ msg }}</p>'50    })51    expect(child.$el.tagName).toBe('DIV')52    expect(child.$el.children[0].tagName).toBe('P')53    expect(child.$el.children[0].textContent).toBe('parent message')54    vm.msg = 'changed'55    waitForUpdate(() => {56      expect(child.$el.children[0].textContent).toBe('changed')57    }).then(done)58  })5960  it('named slot with 0 as a number', done => {61    mount({62      childTemplate: '<div><slot :name="0"></slot></div>',63      parentContent: '<p :slot="0">{{ msg }}</p>'64    })65    expect(child.$el.tagName).toBe('DIV')66    expect(child.$el.children[0].tagName).toBe('P')67    expect(child.$el.children[0].textContent).toBe('parent message')68    vm.msg = 'changed'69    waitForUpdate(() => {70      expect(child.$el.children[0].textContent).toBe('changed')71    }).then(done)72  })7374  it('fallback content', () => {75    mount({76      childTemplate: '<div><slot><p>{{msg}}</p></slot></div>'77    })78    expect(child.$el.children[0].tagName).toBe('P')79    expect(child.$el.textContent).toBe('child message')80  })8182  it('fallback content with multiple named slots', () => {83    mount({84      childTemplate: `85        <div>86          <slot name="a"><p>fallback a</p></slot>87          <slot name="b">fallback b</slot>88        </div>89      `,90      parentContent: '<p slot="b">slot b</p>'91    })92    expect(child.$el.children.length).toBe(2)93    expect(child.$el.children[0].textContent).toBe('fallback a')94    expect(child.$el.children[1].textContent).toBe('slot b')95  })9697  it('fallback content with mixed named/unnamed slots', () => {98    mount({99      childTemplate: `100        <div>101          <slot><p>fallback a</p></slot>102          <slot name="b">fallback b</slot>103        </div>104      `,105      parentContent: '<p slot="b">slot b</p>'106    })107    expect(child.$el.children.length).toBe(2)108    expect(child.$el.children[0].textContent).toBe('fallback a')109    expect(child.$el.children[1].textContent).toBe('slot b')110  })111112  it('it should work with previous versions of the templates', () => {113    const Test = {114      render() {115        const _vm = this116        // const _h = _vm.$createElement;117        const _c = _vm._self._c || vm._h118        return _c(119          'div',120          [_vm._t('default', [_c('p', [_vm._v('slot default')])])],121          2122        )123      }124    }125    let vm = new Vue({126      template: `<test/>`,127      components: { Test }128    }).$mount()129    expect(vm.$el.textContent).toBe('slot default')130    vm = new Vue({131      template: `<test>custom content</test>`,132      components: { Test }133    }).$mount()134    expect(vm.$el.textContent).toBe('custom content')135  })136137  it('fallback content should not be evaluated when the parent is providing it', () => {138    const test = vi.fn()139    const vm = new Vue({140      template: '<test>slot default</test>',141      components: {142        test: {143          template: '<div><slot>{{test()}}</slot></div>',144          methods: {145            test() {146              test()147              return 'test'148            }149          }150        }151      }152    }).$mount()153    expect(vm.$el.textContent).toBe('slot default')154    expect(test).not.toHaveBeenCalled()155  })156157  it('selector matching multiple elements', () => {158    mount({159      childTemplate: '<div><slot name="t"></slot></div>',160      parentContent: '<p slot="t">1</p><div></div><p slot="t">2</p>'161    })162    expect(child.$el.innerHTML).toBe('<p>1</p><p>2</p>')163  })164165  it('default content should only render parts not selected', () => {166    mount({167      childTemplate: `168        <div>169          <slot name="a"></slot>170          <slot></slot>171          <slot name="b"></slot>172        </div>173      `,174      parentContent: '<div>foo</div><p slot="a">1</p><p slot="b">2</p>'175    })176    expect(child.$el.innerHTML).toBe('<p>1</p> <div>foo</div> <p>2</p>')177  })178179  it('name should only match children', function () {180    mount({181      childTemplate: `182        <div>183          <slot name="a"><p>fallback a</p></slot>184          <slot name="b"><p>fallback b</p></slot>185          <slot name="c"><p>fallback c</p></slot>186        </div>187      `,188      parentContent: `189        '<p slot="b">select b</p>190        '<span><p slot="b">nested b</p></span>191        '<span><p slot="c">nested c</p></span>192      `193    })194    expect(child.$el.children.length).toBe(3)195    expect(child.$el.children[0].textContent).toBe('fallback a')196    expect(child.$el.children[1].textContent).toBe('select b')197    expect(child.$el.children[2].textContent).toBe('fallback c')198  })199200  it('should accept expressions in slot attribute and slot names', () => {201    mount({202      childTemplate: `<div><slot :name="'a'"></slot></div>`,203      parentContent: `<p>one</p><p :slot="'a'">two</p>`204    })205    expect(child.$el.innerHTML).toBe('<p>two</p>')206  })207208  it('slot inside v-if', done => {209    const vm = new Vue({210      data: {211        a: 1,212        b: 2,213        show: true214      },215      template: '<test :show="show"><p slot="b">{{b}}</p><p>{{a}}</p></test>',216      components: {217        test: {218          props: ['show'],219          template: '<div v-if="show"><slot></slot><slot name="b"></slot></div>'220        }221      }222    }).$mount()223    expect(vm.$el.textContent).toBe('12')224    vm.a = 2225    waitForUpdate(() => {226      expect(vm.$el.textContent).toBe('22')227      vm.show = false228    })229      .then(() => {230        expect(vm.$el.textContent).toBe('')231        vm.show = true232        vm.a = 3233      })234      .then(() => {235        expect(vm.$el.textContent).toBe('32')236      })237      .then(done)238  })239240  it('slot inside v-for', () => {241    mount({242      childTemplate: '<div><slot v-for="i in 3" :name="i"></slot></div>',243      parentContent: '<p v-for="i in 3" :slot="i">{{ i - 1 }}</p>'244    })245    expect(child.$el.innerHTML).toBe('<p>0</p><p>1</p><p>2</p>')246  })247248  it('nested slots', done => {249    const vm = new Vue({250      template: '<test><test2><p>{{ msg }}</p></test2></test>',251      data: {252        msg: 'foo'253      },254      components: {255        test: {256          template: '<div><slot></slot></div>'257        },258        test2: {259          template: '<div><slot></slot></div>'260        }261      }262    }).$mount()263    expect(vm.$el.innerHTML).toBe('<div><p>foo</p></div>')264    vm.msg = 'bar'265    waitForUpdate(() => {266      expect(vm.$el.innerHTML).toBe('<div><p>bar</p></div>')267    }).then(done)268  })269270  it('v-if on inserted content', done => {271    const vm = new Vue({272      template: '<test><p v-if="ok">{{ msg }}</p></test>',273      data: {274        ok: true,275        msg: 'hi'276      },277      components: {278        test: {279          template: '<div><slot>fallback</slot></div>'280        }281      }282    }).$mount()283    expect(vm.$el.innerHTML).toBe('<p>hi</p>')284    vm.ok = false285    waitForUpdate(() => {286      expect(vm.$el.innerHTML).toBe('fallback')287      vm.ok = true288      vm.msg = 'bye'289    })290      .then(() => {291        expect(vm.$el.innerHTML).toBe('<p>bye</p>')292      })293      .then(done)294  })295296  it('template slot', function () {297    const vm = new Vue({298      template: '<test><template slot="test">hello</template></test>',299      components: {300        test: {301          template: '<div><slot name="test"></slot> world</div>'302        }303      }304    }).$mount()305    expect(vm.$el.innerHTML).toBe('hello world')306  })307308  it('combined with v-for', () => {309    const vm = new Vue({310      template: '<div><test v-for="i in 3" :key="i">{{ i }}</test></div>',311      components: {312        test: {313          template: '<div><slot></slot></div>'314        }315      }316    }).$mount()317    expect(vm.$el.innerHTML).toBe('<div>1</div><div>2</div><div>3</div>')318  })319320  it('inside template v-if', () => {321    mount({322      childTemplate: `323        <div>324          <template v-if="true"><slot></slot></template>325        </div>326      `,327      parentContent: 'foo'328    })329    expect(child.$el.innerHTML).toBe('foo')330  })331332  it('default slot should use fallback content if has only whitespace', () => {333    mount({334      childTemplate: `335        <div>336          <slot name="first"><p>first slot</p></slot>337          <slot><p>this is the default slot</p></slot>338          <slot name="second"><p>second named slot</p></slot>339        </div>340      `,341      parentContent: `<div slot="first">1</div> <div slot="second">2</div> <div slot="second">2+</div>`342    })343    expect(child.$el.innerHTML).toBe(344      '<div>1</div> <p>this is the default slot</p> <div>2</div><div>2+</div>'345    )346  })347348  it('programmatic access to $slots', () => {349    const vm = new Vue({350      template: '<test><p slot="a">A</p><div>C</div><p slot="b">B</p></test>',351      components: {352        test: {353          render() {354            expect(this.$slots.a.length).toBe(1)355            expect(this.$slots.a[0].tag).toBe('p')356            expect(this.$slots.a[0].children.length).toBe(1)357            expect(this.$slots.a[0].children[0].text).toBe('A')358359            expect(this.$slots.b.length).toBe(1)360            expect(this.$slots.b[0].tag).toBe('p')361            expect(this.$slots.b[0].children.length).toBe(1)362            expect(this.$slots.b[0].children[0].text).toBe('B')363364            expect(this.$slots.default.length).toBe(1)365            expect(this.$slots.default[0].tag).toBe('div')366            expect(this.$slots.default[0].children.length).toBe(1)367            expect(this.$slots.default[0].children[0].text).toBe('C')368369            return this.$slots.default[0]370          }371        }372      }373    }).$mount()374    expect(vm.$el.tagName).toBe('DIV')375    expect(vm.$el.textContent).toBe('C')376  })377378  it('warn if user directly returns array', () => {379    new Vue({380      template: '<test><div slot="foo"></div><div slot="foo"></div></test>',381      components: {382        test: {383          render() {384            return this.$slots.foo385          }386        }387      }388    }).$mount()389    expect(390      'Render function should return a single root node'391    ).toHaveBeenWarned()392  })393394  // #3254395  it('should not keep slot name when passed further down', () => {396    const vm = new Vue({397      template: '<test><span slot="foo">foo</span></test>',398      components: {399        test: {400          template: '<child><slot name="foo"></slot></child>',401          components: {402            child: {403              template: `404                <div>405                  <div class="default"><slot></slot></div>406                  <div class="named"><slot name="foo"></slot></div>407                </div>408              `409            }410          }411        }412      }413    }).$mount()414    expect(vm.$el.querySelector('.default').textContent).toBe('foo')415    expect(vm.$el.querySelector('.named').textContent).toBe('')416  })417418  it('should not keep slot name when passed further down (nested)', () => {419    const vm = new Vue({420      template: '<wrap><test><span slot="foo">foo</span></test></wrap>',421      components: {422        wrap: {423          template: '<div><slot></slot></div>'424        },425        test: {426          template: '<child><slot name="foo"></slot></child>',427          components: {428            child: {429              template: `430                <div>431                  <div class="default"><slot></slot></div>432                  <div class="named"><slot name="foo"></slot></div>433                </div>434              `435            }436          }437        }438      }439    }).$mount()440    expect(vm.$el.querySelector('.default').textContent).toBe('foo')441    expect(vm.$el.querySelector('.named').textContent).toBe('')442  })443444  it('should not keep slot name when passed further down (functional)', () => {445    const child = {446      template: `447        <div>448          <div class="default"><slot></slot></div>449          <div class="named"><slot name="foo"></slot></div>450        </div>451      `452    }453454    const vm = new Vue({455      template: '<test><span slot="foo">foo</span></test>',456      components: {457        test: {458          functional: true,459          render(h, ctx) {460            const slots = ctx.slots()461            return h(child, slots.foo)462          }463        }464      }465    }).$mount()466    expect(vm.$el.querySelector('.default').textContent).toBe('foo')467    expect(vm.$el.querySelector('.named').textContent).toBe('')468  })469470  // #3400471  it('named slots should be consistent across re-renders', done => {472    const vm = new Vue({473      template: `474        <comp>475          <div slot="foo">foo</div>476        </comp>477      `,478      components: {479        comp: {480          data() {481            return { a: 1 }482          },483          template: `<div><slot name="foo"></slot>{{ a }}</div>`484        }485      }486    }).$mount()487    expect(vm.$el.textContent).toBe('foo1')488    vm.$children[0].a = 2489    waitForUpdate(() => {490      expect(vm.$el.textContent).toBe('foo2')491    }).then(done)492  })493494  // #3437495  it('should correctly re-create components in slot', done => {496    const calls: any[] = []497    const vm = new Vue({498      template: `499        <comp ref="child">500          <div slot="foo">501            <child></child>502          </div>503        </comp>504      `,505      components: {506        comp: {507          data() {508            return { ok: true }509          },510          template: `<div><slot name="foo" v-if="ok"></slot></div>`511        },512        child: {513          template: '<div>child</div>',514          created() {515            calls.push(1)516          },517          destroyed() {518            calls.push(2)519          }520        }521      }522    }).$mount()523524    expect(calls).toEqual([1])525    vm.$refs.child.ok = false526    waitForUpdate(() => {527      expect(calls).toEqual([1, 2])528      vm.$refs.child.ok = true529    })530      .then(() => {531        expect(calls).toEqual([1, 2, 1])532        vm.$refs.child.ok = false533      })534      .then(() => {535        expect(calls).toEqual([1, 2, 1, 2])536      })537      .then(done)538  })539540  it('should support duplicate slots', done => {541    const vm = new Vue({542      template: `543        <foo ref="foo">544          <div slot="a">{{ n }}</div>545        </foo>546      `,547      data: {548        n: 1549      },550      components: {551        foo: {552          data() {553            return { ok: true }554          },555          template: `556            <div>557              <slot name="a" />558              <slot v-if="ok" name="a" />559              <pre><slot name="a" /></pre>560            </div>561          `562        }563      }564    }).$mount()565    expect(vm.$el.innerHTML).toBe(566      `<div>1</div> <div>1</div> <pre><div>1</div></pre>`567    )568    vm.n++569    waitForUpdate(() => {570      expect(vm.$el.innerHTML).toBe(571        `<div>2</div> <div>2</div> <pre><div>2</div></pre>`572      )573      vm.n++574    })575      .then(() => {576        expect(vm.$el.innerHTML).toBe(577          `<div>3</div> <div>3</div> <pre><div>3</div></pre>`578        )579        vm.$refs.foo.ok = false580      })581      .then(() => {582        expect(vm.$el.innerHTML).toBe(583          `<div>3</div> <!----> <pre><div>3</div></pre>`584        )585        vm.n++586        vm.$refs.foo.ok = true587      })588      .then(() => {589        expect(vm.$el.innerHTML).toBe(590          `<div>4</div> <div>4</div> <pre><div>4</div></pre>`591        )592      })593      .then(done)594  })595596  // #3518597  it('events should not break when slot is toggled by v-if', done => {598    const spy = vi.fn()599    const vm = new Vue({600      template: `<test><div class="click" @click="test">hi</div></test>`,601      methods: {602        test: spy603      },604      components: {605        test: {606          data: () => ({607            toggle: true608          }),609          template: `<div v-if="toggle"><slot></slot></div>`610        }611      }612    }).$mount()613614    document.body.appendChild(vm.$el)615    expect(vm.$el.textContent).toBe('hi')616    vm.$children[0].toggle = false617    waitForUpdate(() => {618      vm.$children[0].toggle = true619    })620      .then(() => {621        global.triggerEvent(vm.$el.querySelector('.click'), 'click')622        expect(spy).toHaveBeenCalled()623      })624      .then(() => {625        document.body.removeChild(vm.$el)626      })627      .then(done)628  })629630  it('renders static tree with text', () => {631    const vm = new Vue({632      template: `<div><test><template><div></div>Hello<div></div></template></test></div>`,633      components: {634        test: {635          template: '<div><slot></slot></div>'636        }637      }638    })639    vm.$mount()640    expect('Error when rendering root').not.toHaveBeenWarned()641  })642643  // #3872644  it('functional component as slot', () => {645    const vm = new Vue({646      template: `647        <parent>648          <child>one</child>649          <child slot="a">two</child>650        </parent>651      `,652      components: {653        parent: {654          template: `<div><slot name="a"></slot><slot></slot></div>`655        },656        child: {657          functional: true,658          render(h, { slots }) {659            return h('div', slots().default)660          }661        }662      }663    }).$mount()664    expect(vm.$el.innerHTML.trim()).toBe('<div>two</div><div>one</div>')665  })666667  // #4209668  it('slot of multiple text nodes should not be infinitely merged', done => {669    const wrap = {670      template: `<inner ref="inner">foo<slot></slot></inner>`,671      components: {672        inner: {673          data: () => ({ a: 1 }),674          template: `<div>{{a}}<slot></slot></div>`675        }676      }677    }678    const vm = new Vue({679      template: `<wrap ref="wrap">bar</wrap>`,680      components: { wrap }681    }).$mount()682683    expect(vm.$el.textContent).toBe('1foobar')684    vm.$refs.wrap.$refs.inner.a++685    waitForUpdate(() => {686      expect(vm.$el.textContent).toBe('2foobar')687    }).then(done)688  })689690  // #4315691  it('functional component passing slot content to stateful child component', done => {692    const ComponentWithSlots = {693      render(h) {694        return h('div', this.$slots.slot1)695      }696    }697698    const FunctionalComp = {699      functional: true,700      render(h) {701        return h(ComponentWithSlots, [h('span', { slot: 'slot1' }, 'foo')])702      }703    }704705    const vm = new Vue({706      data: { n: 1 },707      render(h) {708        return h('div', [this.n, h(FunctionalComp)])709      }710    }).$mount()711712    expect(vm.$el.textContent).toBe('1foo')713    vm.n++714    waitForUpdate(() => {715      // should not lose named slot716      expect(vm.$el.textContent).toBe('2foo')717    }).then(done)718  })719720  it('the elements of slot should be updated correctly', done => {721    const vm = new Vue({722      data: { n: 1 },723      template:724        '<div><test><span v-for="i in n" :key="i">{{ i }}</span><input value="a"/></test></div>',725      components: {726        test: {727          template: '<div><slot></slot></div>'728        }729      }730    }).$mount()731    expect(vm.$el.innerHTML).toBe('<div><span>1</span><input value="a"></div>')732    const input = vm.$el.querySelector('input')733    input.value = 'b'734    vm.n++735    waitForUpdate(() => {736      expect(vm.$el.innerHTML).toBe(737        '<div><span>1</span><span>2</span><input value="a"></div>'738      )739      expect(vm.$el.querySelector('input')).toBe(input)740      expect(vm.$el.querySelector('input').value).toBe('b')741    }).then(done)742  })743744  // GitHub issue #5888745  it('should resolve correctly slot with keep-alive', () => {746    const vm = new Vue({747      template: `748      <div>749        <container>750          <keep-alive slot="foo">751            <child></child>752          </keep-alive>753        </container>754      </div>755      `,756      components: {757        container: {758          template:759            '<div><slot>default</slot><slot name="foo">named</slot></div>'760        },761        child: {762          template: '<span>foo</span>'763        }764      }765    }).$mount()766    expect(vm.$el.innerHTML).toBe('<div>default<span>foo</span></div>')767  })768769  // #6372, #6915770  it('should handle nested components in slots properly', done => {771    const TestComponent = {772      template: `773        <component :is="toggleEl ? 'b' : 'i'">774          <slot />775        </component>776      `,777      data() {778        return {779          toggleEl: true780        }781      }782    }783784    const vm = new Vue({785      template: `786        <div>787          <test-component ref="test">788            <div>789              <foo/>790            </div>791            <bar>792              <foo/>793            </bar>794          </test-component>795        </div>796      `,797      components: {798        TestComponent,799        foo: {800          template: `<div>foo</div>`801        },802        bar: {803          template: `<div>bar<slot/></div>`804        }805      }806    }).$mount()807808    expect(vm.$el.innerHTML).toBe(809      `<b><div><div>foo</div></div> <div>bar<div>foo</div></div></b>`810    )811812    vm.$refs.test.toggleEl = false813    waitForUpdate(() => {814      expect(vm.$el.innerHTML).toBe(815        `<i><div><div>foo</div></div> <div>bar<div>foo</div></div></i>`816      )817    }).then(done)818  })819820  it('should preserve slot attribute if not absorbed by a Vue component', () => {821    const vm = new Vue({822      template: `823        <div>824          <div slot="foo"></div>825        </div>826      `827    }).$mount()828    expect(vm.$el.children[0].getAttribute('slot')).toBe('foo')829  })830831  it('passing a slot down as named slot', () => {832    const Bar = {833      template: `<div class="bar"><slot name="foo"/></div>`834    }835836    const Foo = {837      components: { Bar },838      template: `<div class="foo"><bar><slot slot="foo"/></bar></div>`839    }840841    const vm = new Vue({842      components: { Foo },843      template: `<div><foo>hello</foo></div>`844    }).$mount()845846    expect(vm.$el.innerHTML).toBe(847      '<div class="foo"><div class="bar">hello</div></div>'848    )849  })850851  it('fallback content for named template slot', () => {852    const Bar = {853      template: `<div class="bar"><slot name="foo">fallback</slot></div>`854    }855856    const Foo = {857      components: { Bar },858      template: `<div class="foo"><bar><template slot="foo"/><slot/></template></bar></div>`859    }860861    const vm = new Vue({862      components: { Foo },863      template: `<div><foo></foo></div>`864    }).$mount()865866    expect(vm.$el.innerHTML).toBe(867      '<div class="foo"><div class="bar">fallback</div></div>'868    )869  })870871  // #7106872  it('should not lose functional slot across renders', done => {873    const One = {874      data: () => ({875        foo: true876      }),877      render(h) {878        this.foo879        return h('div', this.$slots.slot)880      }881    }882883    const Two = {884      render(h) {885        return h('span', this.$slots.slot)886      }887    }888889    const Three = {890      functional: true,891      render: (h, { children }) => h('span', children)892    }893894    const vm = new Vue({895      template: `896        <div>897          <one ref="one">898            <two slot="slot">899              <three slot="slot">hello</three>900            </two>901          </one>902        </div>903      `,904      components: { One, Two, Three }905    }).$mount()906907    expect(vm.$el.textContent).toBe('hello')908    // trigger re-render of <one>909    vm.$refs.one.foo = false910    waitForUpdate(() => {911      // should still be there912      expect(vm.$el.textContent).toBe('hello')913    }).then(done)914  })915916  it('should allow passing named slots as raw children down multiple layers of functional component', () => {917    const CompB = {918      functional: true,919      render(h, { slots }) {920        return slots().foo921      }922    }923924    const CompA = {925      functional: true,926      render(h, { children }) {927        return h(CompB, children)928      }929    }930931    const vm = new Vue({932      components: {933        CompA934      },935      template: `936        <div>937          <comp-a>938            <span slot="foo">foo</span>939          </comp-a>940        </div>941      `942    }).$mount()943944    expect(vm.$el.textContent).toBe('foo')945  })946947  // #7817948  it('should not match wrong named slot in functional component on re-render', done => {949    const Functional = {950      functional: true,951      render: (h, ctx) => ctx.slots().default952    }953954    const Stateful = {955      data() {956        return { ok: true }957      },958      render(h) {959        this.ok // register dep960        return h('div', [h(Functional, this.$slots.named)])961      }962    }963964    const vm = new Vue({965      template: `<stateful ref="stateful"><div slot="named">foo</div></stateful>`,966      components: { Stateful }967    }).$mount()968969    expect(vm.$el.textContent).toBe('foo')970    vm.$refs.stateful.ok = false971    waitForUpdate(() => {972      expect(vm.$el.textContent).toBe('foo')973    }).then(done)974  })975976  // #7975977  it('should update named slot correctly when its position in the tree changed', done => {978    const ChildComponent = {979      template: '<b>{{ message }}</b>',980      props: ['message']981    }982    let parentVm983    const ParentComponent = {984      template: `985        <div>986          <span v-if="alter">987            <span><slot name="foo" /></span>988          </span>989          <span v-else>990            <slot name="foo" />991          </span>992        </div>993      `,994      data() {995        return {996          alter: true997        }998      },999      mounted() {1000        parentVm = this1001      }1002    }1003    const vm = new Vue({1004      template: `1005        <parent-component>1006          <span slot="foo">1007            <child-component :message="message" />1008          </span>1009        </parent-component>1010      `,1011      components: {1012        ChildComponent,1013        ParentComponent1014      },1015      data() {1016        return {1017          message: 11018        }1019      }1020    }).$mount()1021    expect(vm.$el.firstChild.innerHTML).toBe(1022      '<span><span><b>1</b></span></span>'1023    )1024    parentVm.alter = false1025    waitForUpdate(() => {1026      vm.message = 21027    })1028      .then(() => {1029        expect(vm.$el.firstChild.innerHTML).toBe('<span><b>2</b></span>')1030      })1031      .then(done)1032  })10331034  // #121021035  it('v-if inside scoped slot', () => {1036    const vm = new Vue({1037      template: `<test><template #custom><span v-if="false">a</span><span>b</span></template></test>`,1038      components: {1039        test: {1040          template: `<div><slot name="custom"/></div>`1041        }1042      }1043    }).$mount()10441045    expect(vm.$el.innerHTML).toBe(`<!----><span>b</span>`)1046  })10471048  // regression 2.7.0-alpha.41049  it('passing scoped slots through nested parent chain', () => {1050    const Foo = {1051      template: `1052        <div><slot>foo default</slot></div>1053      `1054    }10551056    const Bar = {1057      components: { Foo },1058      template: `<Foo><slot name="bar"/></Foo>`1059    }10601061    const App = {1062      components: { Bar },1063      template: `<Bar>1064        <template #bar>1065          <span>App content for Bar#bar</span>1066        </template>1067      </Bar>`1068    }10691070    const vm = new Vue({1071      render: h => h(App)1072    }).$mount()10731074    expect(vm.$el.innerHTML).toMatch(`App content for Bar#bar`)1075  })1076})

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.