Back to Repositories

Testing Custom Element Shadow DOM Integration in Video.js

This test suite validates the implementation of custom web components in Video.js, focusing on shadow DOM integration and custom element definitions. It tests the creation and functionality of custom video player elements with shadow root attachments.

Test Coverage Overview

The test coverage encompasses custom element initialization and shadow DOM integration for Video.js players. Key functionality includes:
  • Shadow root attachment with both open and closed modes
  • Custom element registration and definition
  • Video.js player instantiation within custom elements
  • Slot element implementation for content projection

Implementation Analysis

The testing approach utilizes ES6 class definitions for custom elements, extending HTMLElement base class. The implementation demonstrates modern web component patterns including:
  • Shadow DOM encapsulation techniques
  • Dynamic element creation and attribute setting
  • Video.js player initialization within custom elements
  • Browser compatibility checks for customElements API

Technical Details

Testing infrastructure includes:
  • ESLint configuration for browser environment
  • ES6 module import/export syntax
  • DOM API methods for element manipulation
  • Video.js core library integration
  • Browser compatibility detection for customElements API

Best Practices Demonstrated

The test suite exemplifies several web component best practices:
  • Proper encapsulation using shadow DOM
  • Separation of concerns between player and wrapper elements
  • Conditional feature detection for browser support
  • Clean inheritance patterns for custom elements
  • Structured attribute and style handling

videojs/videoJs

test/unit/utils/custom-element.test.js

            
/* eslint-env browser */
import videojs from '../../../src/js/video.js';

export class TestCustomElement extends HTMLElement {

  constructor() {
    super();

    const shadowRoot = this.attachShadow({ mode: 'closed' });

    const containerElem = document.createElement('div');

    containerElem.setAttribute('data-vjs-player', '');
    shadowRoot.appendChild(containerElem);

    const videoElem = document.createElement('video');

    videoElem.setAttribute('width', 640);
    videoElem.setAttribute('height', 260);
    containerElem.appendChild(videoElem);

    this.innerPlayer = videojs(videoElem);
  }
}

export class TestSlotElement extends HTMLElement {

  constructor() {
    super();
    const shadowRoot = this.attachShadow({ mode: 'open' });
    const wrapperEl = document.createElement('div');

    wrapperEl.style = this.dataset.style;
    const slot = document.createElement('slot');

    wrapperEl.appendChild(slot);
    shadowRoot.appendChild(wrapperEl);
  }
}

// Not supported on Chrome < 54
if ('customElements' in window) {
  window.customElements.define('test-custom-element', TestCustomElement);
  window.customElements.define('test-slot-element', TestSlotElement);
}