@wordpress/block-library
Version:
Block library for the WordPress editor.
329 lines (271 loc) • 8.87 kB
JavaScript
/**
* @jest-environment jsdom
*/
/**
* External dependencies
*/
import '@testing-library/jest-dom';
/**
* Internal dependencies
*/
import {
createWaveformContainer,
styleSvgIcons,
setupPlayButtonAccessibility,
logPlayError,
} from '../waveform-utils';
// Base player data used across tests
const basePlayerData = {
url: 'https://example.com/song.mp3',
waveformColor: 'rgba(0, 0, 0, 0.3)',
progressColor: 'rgba(0, 0, 0, 0.6)',
buttonColor: '#000000',
};
describe( 'Waveform utilities', () => {
describe( 'createWaveformContainer', () => {
it( 'should create a container with required data attributes', () => {
const container = createWaveformContainer( basePlayerData );
expect( container.tagName ).toBe( 'DIV' );
expect( container ).toHaveAttribute( 'data-waveform-player', '' );
expect( container ).toHaveAttribute(
'data-url',
'https://example.com/song.mp3'
);
expect( container ).toHaveAttribute( 'data-height', '100' );
expect( container ).toHaveAttribute(
'data-waveform-style',
'bars'
);
expect( container ).toHaveAttribute(
'data-waveform-color',
'rgba(0, 0, 0, 0.3)'
);
expect( container ).toHaveAttribute(
'data-progress-color',
'rgba(0, 0, 0, 0.6)'
);
expect( container ).toHaveAttribute(
'data-button-color',
'#000000'
);
} );
it( 'should set optional attributes when provided', () => {
const container = createWaveformContainer( {
...basePlayerData,
title: 'My Song',
artist: 'The Artist',
artwork: 'https://example.com/cover.jpg',
} );
expect( container ).toHaveAttribute( 'data-title', 'My Song' );
expect( container ).toHaveAttribute(
'data-subtitle',
'The Artist'
);
expect( container ).toHaveAttribute(
'data-artwork',
'https://example.com/cover.jpg'
);
} );
it( 'should not set optional attributes when not provided', () => {
const container = createWaveformContainer( basePlayerData );
expect( container ).not.toHaveAttribute( 'data-title' );
expect( container ).not.toHaveAttribute( 'data-subtitle' );
expect( container ).not.toHaveAttribute( 'data-artwork' );
} );
it( 'should use custom height when provided', () => {
const container = createWaveformContainer( {
...basePlayerData,
height: 150,
} );
expect( container ).toHaveAttribute( 'data-height', '150' );
} );
} );
describe( 'styleSvgIcons', () => {
it( 'should set white fill for dark button colors', () => {
const container = document.createElement( 'div' );
const svg = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg'
);
const path = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
svg.appendChild( path );
container.appendChild( svg );
styleSvgIcons( container, '#000000' );
expect( path ).toHaveStyle( { fill: '#ffffff' } );
} );
it( 'should set black fill for light button colors', () => {
const container = document.createElement( 'div' );
const svg = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg'
);
const path = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
svg.appendChild( path );
container.appendChild( svg );
styleSvgIcons( container, '#ffffff' );
expect( path ).toHaveStyle( { fill: '#000000' } );
} );
it( 'should style multiple SVG paths', () => {
const container = document.createElement( 'div' );
const svg = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg'
);
const path1 = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
const path2 = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
svg.appendChild( path1 );
svg.appendChild( path2 );
container.appendChild( svg );
styleSvgIcons( container, '#000000' );
expect( path1 ).toHaveStyle( { fill: '#ffffff' } );
expect( path2 ).toHaveStyle( { fill: '#ffffff' } );
} );
it( 'should handle container with no SVG paths', () => {
const container = document.createElement( 'div' );
// Should not throw.
expect( () => {
styleSvgIcons( container, '#000000' );
} ).not.toThrow();
} );
it( 'should use white for dark colors', () => {
const container = document.createElement( 'div' );
const svg = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg'
);
const path = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
svg.appendChild( path );
container.appendChild( svg );
// A dark blue color.
styleSvgIcons( container, '#000080' );
expect( path ).toHaveStyle( { fill: '#ffffff' } );
} );
it( 'should use black for mid-light colors', () => {
const container = document.createElement( 'div' );
const svg = document.createElementNS(
'http://www.w3.org/2000/svg',
'svg'
);
const path = document.createElementNS(
'http://www.w3.org/2000/svg',
'path'
);
svg.appendChild( path );
container.appendChild( svg );
// A light yellow color.
styleSvgIcons( container, '#ffff00' );
expect( path ).toHaveStyle( { fill: '#000000' } );
} );
} );
describe( 'setupPlayButtonAccessibility', () => {
it( 'should set aria-label to Play initially', () => {
const container = document.createElement( 'div' );
const playBtn = document.createElement( 'button' );
playBtn.className = 'waveform-btn';
container.appendChild( playBtn );
setupPlayButtonAccessibility( container );
expect( playBtn ).toHaveAttribute( 'aria-label', 'Play' );
} );
it( 'should change aria-label to Pause on play event', () => {
const container = document.createElement( 'div' );
const playBtn = document.createElement( 'button' );
playBtn.className = 'waveform-btn';
container.appendChild( playBtn );
setupPlayButtonAccessibility( container );
container.dispatchEvent( new CustomEvent( 'waveformplayer:play' ) );
expect( playBtn ).toHaveAttribute( 'aria-label', 'Pause' );
} );
it( 'should change aria-label back to Play on pause event', () => {
const container = document.createElement( 'div' );
const playBtn = document.createElement( 'button' );
playBtn.className = 'waveform-btn';
container.appendChild( playBtn );
setupPlayButtonAccessibility( container );
container.dispatchEvent( new CustomEvent( 'waveformplayer:play' ) );
container.dispatchEvent(
new CustomEvent( 'waveformplayer:pause' )
);
expect( playBtn ).toHaveAttribute( 'aria-label', 'Play' );
} );
it( 'should change aria-label back to Play on ended event', () => {
const container = document.createElement( 'div' );
const playBtn = document.createElement( 'button' );
playBtn.className = 'waveform-btn';
container.appendChild( playBtn );
setupPlayButtonAccessibility( container );
container.dispatchEvent( new CustomEvent( 'waveformplayer:play' ) );
container.dispatchEvent(
new CustomEvent( 'waveformplayer:ended' )
);
expect( playBtn ).toHaveAttribute( 'aria-label', 'Play' );
} );
it( 'should return cleanup function that removes listeners', () => {
const container = document.createElement( 'div' );
const playBtn = document.createElement( 'button' );
playBtn.className = 'waveform-btn';
container.appendChild( playBtn );
const cleanup = setupPlayButtonAccessibility( container );
cleanup();
// After cleanup, events should not change the label.
container.dispatchEvent( new CustomEvent( 'waveformplayer:play' ) );
expect( playBtn ).toHaveAttribute( 'aria-label', 'Play' );
} );
it( 'should do nothing when play button not found', () => {
const container = document.createElement( 'div' );
// Should not throw.
expect( () =>
setupPlayButtonAccessibility( container )
).not.toThrow();
} );
} );
describe( 'logPlayError', () => {
let consoleErrorSpy;
beforeEach( () => {
consoleErrorSpy = jest
.spyOn( console, 'error' )
.mockImplementation( () => {} );
} );
afterEach( () => {
consoleErrorSpy.mockRestore();
} );
it( 'should not log AbortError', () => {
const abortError = new DOMException( 'Aborted', 'AbortError' );
logPlayError( abortError );
expect( consoleErrorSpy ).not.toHaveBeenCalled();
} );
it( 'should log other errors', () => {
const otherError = new Error( 'Some other error' );
logPlayError( otherError );
expect( consoleErrorSpy ).toHaveBeenCalledWith(
'Playlist play error:',
otherError
);
} );
it( 'should log NotAllowedError', () => {
const notAllowedError = new DOMException(
'Not allowed',
'NotAllowedError'
);
logPlayError( notAllowedError );
expect( consoleErrorSpy ).toHaveBeenCalledWith(
'Playlist play error:',
notAllowedError
);
} );
} );
} );