Why does customElements.upgrade appear to not upgrade this custom element?

I have a situation similar to the example below: from a template element, I clone a node tree containing custom elements. One custom element is passed data during initialization, represented here by the line infobox.setData(getData()). The function I use to pass the data (setData) is added by my custom class, so I make sure the custom element is upgraded before calling it, by passing the node tree to customElements.upgrade. (I have also tried passing infobox itself.)

Unfortunately, when I try running my code or the example below I receive the error infobox.setData is not a function. I have confirmed infobox instanceof InfoBox is false and the element has no custom properties or methods prior to being connected to the document, so it seems customElements.upgrade is not upgrading the elements in the tree. What might be preventing it from doing so?

document.getElementById('addWidget').onclick = addWidget

class InfoBox extends HTMLElement {
  _data = ""

  connectedCallback() {
    this.render()
  }

  setData(val) {
    this._data = val
    this.render()
  }

  render() {
    if (!this?.isConnected) {
      return
    }

    this.replaceChildren(...this._data.split(' ').map(datum => {
      const el = document.createElement('span')
      el.innerText = datum
      return el
    }))
  }
}
customElements.define('info-box', InfoBox)

function addWidget() {
  const widget = document.getElementById('widgetTemplate').content.cloneNode(true)
  const infobox = widget.querySelector('info-box')

  customElements.upgrade(widget)

  console.assert(!(infobox instanceof InfoBox))
  console.assert(!('setData' in infobox))
  try {
    // TypeError: infobox.setData is not a function
    infobox.setData(getData())
  } catch {}

  document.getElementById('container').append(widget)

  // works because infobox was upgraded after being added to the document
  infobox.setData(getData())
}

function getData() {
  return ('lorem ipsum dolor sit amet consectetur adipiscing elit proin at ' +
    'vestibulum enim vestibulum ante ipsum primis in faucibus orci luctus')
}
#container {
  background: lightgrey;
  padding: 2em;
}

info-box {
  display: flex;
  flex-flow: row wrap;
  gap: .5em;
  padding: .5em;
  background: darkgrey;
}

info-box>span {
  background: lightblue;
  border-radius: .5em;
  padding: .5em;
}
<template id="widgetTemplate">
    <details>
        <info-box></info-box>
    </details>
</template>

<button id="addWidget">Add</button>
<div id="container"></div>