# speechkit/7.2.0/src/editor/components/settings-fields/classic-metabox.test.js

BeyondWords – AI audio for publishers, version 7.2.0. 152 lines.

- Page: https://pluginprobe.com/plugins/speechkit/7.2.0/code/src/editor/components/settings-fields/classic-metabox.test.js
- Raw: https://pluginprobe.com/plugins/speechkit/7.2.0/raw/src/editor/components/settings-fields/classic-metabox.test.js
- Modified: 2026-09-25T15:14:58+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/speechkit/7.2.0/code/src/editor/components/settings-fields/classic-metabox.test.js#L10-L20`.

```javascript
/* global describe, it, expect, beforeEach, jest */

/*
 * The module is a bare IIFE, so each test rebuilds the markup PHP emits, re-runs
 * the module against it, and drives it with real `change` events.
 */

const SOURCE_VALUES = [ 'post', 'script', 'post_and_script' ];
const OUTPUT_VALUES = [ 'audio', 'video', 'audio_and_video' ];

const renderSelect = ( id, values, selected ) =>
	`<select id="${ id }" name="${ id }">${ values
		.map(
			( value ) =>
				`<option value="${ value }"${
					value === selected ? ' selected' : ''
				}>${ value }</option>`
		)
		.join( '' ) }</select>`;

const boot = ( {
	source = 'post',
	output = 'audio',
	embedOptions = [ 'none', 'audio_post' ],
	embed = 'audio_post',
	withTouched = true,
} = {} ) => {
	document.body.innerHTML = [
		renderSelect( 'beyondwords_source', SOURCE_VALUES, source ),
		renderSelect( 'beyondwords_output', OUTPUT_VALUES, output ),
		renderSelect( 'beyondwords_embed', embedOptions, embed ),
		withTouched
			? '<input type="hidden" id="beyondwords_embed_touched" name="beyondwords_embed_touched" value="" />'
			: '',
		// The wrappers the Source/Output handlers show and hide.
		'<div id="beyondwords-metabox-settings--beyondwords-script-template-id"></div>',
		'<div id="beyondwords-metabox-settings--beyondwords-video-template-id"></div>',
		'<div id="beyondwords-metabox-settings--beyondwords-video-size"></div>',
	].join( '' );

	require( './classic-metabox' );

	return {
		source: document.getElementById( 'beyondwords_source' ),
		output: document.getElementById( 'beyondwords_output' ),
		embed: document.getElementById( 'beyondwords_embed' ),
		touched: document.getElementById( 'beyondwords_embed_touched' ),
	};
};

const change = ( element, value ) => {
	element.value = value;
	element.dispatchEvent( new Event( 'change', { bubbles: true } ) );
};

const optionValues = ( select ) =>
	Array.from( select.options ).map( ( option ) => option.value );

describe( 'classic-metabox recomputeEmbed', () => {
	beforeEach( () => {
		jest.resetModules();
	} );

	it( 'selects the first produced asset when the stored value is invalid', () => {
		const { output, embed } = boot( { embed: 'audio_post' } );

		change( output, 'video' );

		// Post × Video cannot produce audio_post, so the post keeps a player.
		expect( optionValues( embed ) ).toEqual( [ 'none', 'video_post' ] );
		expect( embed.value ).toBe( 'video_post' );
	} );

	it( 'keeps a value the new Source × Output can still produce', () => {
		const { source, embed } = boot( {
			output: 'audio_and_video',
			embedOptions: [ 'none', 'audio_post', 'video_post' ],
			embed: 'video_post',
		} );

		change( source, 'post_and_script' );

		expect( embed.value ).toBe( 'video_post' );
	} );

	it( 'keeps an explicit None, which every Source × Output offers', () => {
		const { output, embed } = boot( { embed: 'none' } );

		change( output, 'video' );

		expect( embed.value ).toBe( 'none' );
	} );

	it( 'falls back to None when no asset can be produced', () => {
		// Defensive: the rendered list always has an asset, but must not break if not.
		const { output, embed } = boot( {
			embedOptions: [ 'none' ],
			embed: 'none',
		} );

		change( output, 'audio' );

		expect( embed.value ).toBe( 'none' );
	} );
} );

describe( 'classic-metabox embed touched flag', () => {
	beforeEach( () => {
		jest.resetModules();
	} );

	it( 'is set when the user picks an Embed', () => {
		const { embed, touched } = boot();

		expect( touched.value ).toBe( '' );

		change( embed, 'none' );

		expect( touched.value ).toBe( '1' );
	} );

	it( 'stays empty when an Output change rebuilds the Embed', () => {
		const { output, embed, touched } = boot( { embed: 'audio_post' } );

		change( output, 'video' );

		// The rebuild picked video_post, but the user never chose it.
		expect( embed.value ).toBe( 'video_post' );
		expect( touched.value ).toBe( '' );
	} );

	it( 'stays empty when a Source change rebuilds the Embed', () => {
		const { source, touched } = boot( {
			source: 'post',
			embedOptions: [ 'none', 'audio_post' ],
			embed: 'audio_post',
		} );

		change( source, 'script' );

		expect( touched.value ).toBe( '' );
	} );

	it( 'is not required for the Embed to be recomputed', () => {
		const { output, embed } = boot( { withTouched: false } );

		change( output, 'video' );

		expect( embed.value ).toBe( 'video_post' );
	} );
} );

```
