PluginProbe
BeyondWords – AI audio for publishers / 7.0.0
BeyondWords – AI audio for publishers v7.0.0
7.1.0 trunk 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.7.0 All 43 releases
speechkit / src / editor / components / settings-fields / classic-metabox.test.js

classic-metabox.test.js in BeyondWords – AI audio for publishers 7.0.0, at src/editor/components/settings-fields/classic-metabox.test.js

152 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /* global describe, it, expect, beforeEach, jest */
2
3 /*
4 * The module is a bare IIFE, so each test rebuilds the markup PHP emits, re-runs
5 * the module against it, and drives it with real `change` events.
6 */
7
8 const SOURCE_VALUES = [ 'post', 'script', 'post_and_script' ];
9 const OUTPUT_VALUES = [ 'audio', 'video', 'audio_and_video' ];
10
11 const renderSelect = ( id, values, selected ) =>
12 `<select id="${ id }" name="${ id }">${ values
13 .map(
14 ( value ) =>
15 `<option value="${ value }"${
16 value === selected ? ' selected' : ''
17 }>${ value }</option>`
18 )
19 .join( '' ) }</select>`;
20
21 const boot = ( {
22 source = 'post',
23 output = 'audio',
24 embedOptions = [ 'none', 'audio_post' ],
25 embed = 'audio_post',
26 withTouched = true,
27 } = {} ) => {
28 document.body.innerHTML = [
29 renderSelect( 'beyondwords_source', SOURCE_VALUES, source ),
30 renderSelect( 'beyondwords_output', OUTPUT_VALUES, output ),
31 renderSelect( 'beyondwords_embed', embedOptions, embed ),
32 withTouched
33 ? '<input type="hidden" id="beyondwords_embed_touched" name="beyondwords_embed_touched" value="" />'
34 : '',
35 // The wrappers the Source/Output handlers show and hide.
36 '<div id="beyondwords-metabox-settings--beyondwords-script-template-id"></div>',
37 '<div id="beyondwords-metabox-settings--beyondwords-video-template-id"></div>',
38 '<div id="beyondwords-metabox-settings--beyondwords-video-size"></div>',
39 ].join( '' );
40
41 require( './classic-metabox' );
42
43 return {
44 source: document.getElementById( 'beyondwords_source' ),
45 output: document.getElementById( 'beyondwords_output' ),
46 embed: document.getElementById( 'beyondwords_embed' ),
47 touched: document.getElementById( 'beyondwords_embed_touched' ),
48 };
49 };
50
51 const change = ( element, value ) => {
52 element.value = value;
53 element.dispatchEvent( new Event( 'change', { bubbles: true } ) );
54 };
55
56 const optionValues = ( select ) =>
57 Array.from( select.options ).map( ( option ) => option.value );
58
59 describe( 'classic-metabox recomputeEmbed', () => {
60 beforeEach( () => {
61 jest.resetModules();
62 } );
63
64 it( 'selects the first produced asset when the stored value is invalid', () => {
65 const { output, embed } = boot( { embed: 'audio_post' } );
66
67 change( output, 'video' );
68
69 // Post × Video cannot produce audio_post, so the post keeps a player.
70 expect( optionValues( embed ) ).toEqual( [ 'none', 'video_post' ] );
71 expect( embed.value ).toBe( 'video_post' );
72 } );
73
74 it( 'keeps a value the new Source × Output can still produce', () => {
75 const { source, embed } = boot( {
76 output: 'audio_and_video',
77 embedOptions: [ 'none', 'audio_post', 'video_post' ],
78 embed: 'video_post',
79 } );
80
81 change( source, 'post_and_script' );
82
83 expect( embed.value ).toBe( 'video_post' );
84 } );
85
86 it( 'keeps an explicit None, which every Source × Output offers', () => {
87 const { output, embed } = boot( { embed: 'none' } );
88
89 change( output, 'video' );
90
91 expect( embed.value ).toBe( 'none' );
92 } );
93
94 it( 'falls back to None when no asset can be produced', () => {
95 // Defensive: the rendered list always has an asset, but must not break if not.
96 const { output, embed } = boot( {
97 embedOptions: [ 'none' ],
98 embed: 'none',
99 } );
100
101 change( output, 'audio' );
102
103 expect( embed.value ).toBe( 'none' );
104 } );
105 } );
106
107 describe( 'classic-metabox embed touched flag', () => {
108 beforeEach( () => {
109 jest.resetModules();
110 } );
111
112 it( 'is set when the user picks an Embed', () => {
113 const { embed, touched } = boot();
114
115 expect( touched.value ).toBe( '' );
116
117 change( embed, 'none' );
118
119 expect( touched.value ).toBe( '1' );
120 } );
121
122 it( 'stays empty when an Output change rebuilds the Embed', () => {
123 const { output, embed, touched } = boot( { embed: 'audio_post' } );
124
125 change( output, 'video' );
126
127 // The rebuild picked video_post, but the user never chose it.
128 expect( embed.value ).toBe( 'video_post' );
129 expect( touched.value ).toBe( '' );
130 } );
131
132 it( 'stays empty when a Source change rebuilds the Embed', () => {
133 const { source, touched } = boot( {
134 source: 'post',
135 embedOptions: [ 'none', 'audio_post' ],
136 embed: 'audio_post',
137 } );
138
139 change( source, 'script' );
140
141 expect( touched.value ).toBe( '' );
142 } );
143
144 it( 'is not required for the Embed to be recomputed', () => {
145 const { output, embed } = boot( { withTouched: false } );
146
147 change( output, 'video' );
148
149 expect( embed.value ).toBe( 'video_post' );
150 } );
151 } );
152