Skip to content

Commit 1573f1d

Browse files
committed
Add tests for puter.ai.txt2speech
1 parent 71f298e commit 1573f1d

File tree

2 files changed

+248
-3
lines changed

2 files changed

+248
-3
lines changed

src/puter-js/test/run.html

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<script src="./kv.test.js"></script>
66
<script src="./fs.test.js"></script>
77
<script src="./ai.test.js"></script>
8+
<script src="./txt2speech.test.js"></script>
89
<style>
910
body {
1011
font-family: Arial, sans-serif;
@@ -430,6 +431,21 @@
430431
</div>`);
431432
}
432433

434+
$('#tests').append('<h2><label><input type="checkbox" id="txt2speechTests-group" checked> Text-to-Speech</label></h2>');
435+
for (let i = 0; i < txt2speechTests.length; i++) {
436+
const testInfo = getTestInfo(txt2speechTests[i]);
437+
$('#tests').append(`<div class="test-container" id="txt2speechTests-container-${i}">
438+
<div class="test-checkbox-container">
439+
<input type="checkbox" class="test-checkbox txt2speechTests-checkbox" id="txt2speechTests${i}" checked>
440+
<label for="txt2speechTests${i}">
441+
<div class="test-name">${testInfo.name}</div>
442+
<div class="test-description">${testInfo.description}</div>
443+
</label><br>
444+
<button class="test-run-button" onclick="runSingleTest('txt2speech', ${i})">Run Test</button>
445+
</div>
446+
</div>`);
447+
}
448+
433449
// Add event listeners for group checkboxes
434450
$('#fsTests-group').change(function() {
435451
const isChecked = $(this).prop('checked');
@@ -446,6 +462,11 @@
446462
$('.aiTests-checkbox').prop('checked', isChecked);
447463
});
448464

465+
$('#txt2speechTests-group').change(function() {
466+
const isChecked = $(this).prop('checked');
467+
$('.txt2speechTests-checkbox').prop('checked', isChecked);
468+
});
469+
449470
// Add event listeners for individual checkboxes to update group checkbox state
450471
$(document).on('change', '.fsTests-checkbox', function() {
451472
const totalFsTests = $('.fsTests-checkbox').length;
@@ -486,6 +507,19 @@
486507
}
487508
});
488509

510+
$(document).on('change', '.txt2speechTests-checkbox', function() {
511+
const totalTxt2speechTests = $('.txt2speechTests-checkbox').length;
512+
const checkedTxt2speechTests = $('.txt2speechTests-checkbox:checked').length;
513+
514+
if (checkedTxt2speechTests === 0) {
515+
$('#txt2speechTests-group').prop('checked', false).prop('indeterminate', false);
516+
} else if (checkedTxt2speechTests === totalTxt2speechTests) {
517+
$('#txt2speechTests-group').prop('checked', true).prop('indeterminate', false);
518+
} else {
519+
$('#txt2speechTests-group').prop('checked', false).prop('indeterminate', true);
520+
}
521+
});
522+
489523
window.assert = function(condition, message) {
490524
if (!condition) {
491525
throw new Error(message || "Assertion failed");
@@ -496,7 +530,8 @@
496530
const testSuites = {
497531
'fs': fsTests,
498532
'kv': kvTests,
499-
'ai': aiTests
533+
'ai': aiTests,
534+
'txt2speech': txt2speechTests
500535
};
501536

502537
const tests = testSuites[testType];
@@ -642,6 +677,38 @@
642677
await delay(100);
643678
}
644679
}
680+
681+
for (let i = 0; i < txt2speechTests.length; i++) {
682+
if (document.getElementById(`txt2speechTests${i}`).checked) {
683+
const testInfo = getTestInfo(txt2speechTests[i]);
684+
testProgress.currentTest = `Text-to-Speech: ${testInfo.name}`;
685+
updateProgressPanel();
686+
687+
try{
688+
await executeTest(txt2speechTests[i]);
689+
// make this test's container green
690+
$(`#txt2speechTests-container-${i}`).css('background-color', '#85e085');
691+
testProgress.passed++;
692+
} catch (e) {
693+
console.error('Txt2Speech Test failed:', testInfo.name, e);
694+
// make this test's container red
695+
$(`#txt2speechTests-container-${i}`).css('background-color', '#ff8484');
696+
// message - show full error information including JSON details
697+
let errorMessage = e.message || e.toString();
698+
if (e.originalError) {
699+
errorMessage += '\n\nOriginal Error:\n' + JSON.stringify(e.originalError, null, 2);
700+
}
701+
$(`#txt2speechTests-container-${i}`).append(`<pre style="color:red; white-space: pre-wrap; font-size: 12px; margin: 5px 0; padding: 10px; background-color: #f8f8f8; border-radius: 3px;">${errorMessage}</pre>`);
702+
testProgress.failed++;
703+
}
704+
705+
testProgress.completed++;
706+
updateProgressPanel();
707+
708+
// Small delay to make progress visible
709+
await delay(100);
710+
}
711+
}
645712

646713
// Show completion message
647714
testProgress.currentTest = `Complete! ${testProgress.passed} passed, ${testProgress.failed} failed`;
@@ -674,7 +741,7 @@
674741
$('#master-checkbox').change(function() {
675742
const isChecked = $(this).prop('checked');
676743
$('.test-checkbox').prop('checked', isChecked);
677-
$('#fsTests-group, #kvTests-group, #aiTests-group').prop('checked', isChecked);
744+
$('#fsTests-group, #kvTests-group, #aiTests-group, #txt2speechTests-group').prop('checked', isChecked);
678745
// Update the counter display
679746
updateMasterCheckboxState();
680747
});
@@ -702,7 +769,7 @@
702769
});
703770

704771
// Update master checkbox state when group checkboxes change
705-
$('#fsTests-group, #kvTests-group, #aiTests-group').change(function() {
772+
$('#fsTests-group, #kvTests-group, #aiTests-group, #txt2speechTests-group').change(function() {
706773
updateMasterCheckboxState();
707774
});
708775

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/* eslint-disable */
2+
// TODO: Make these more compatible with eslint
3+
4+
// Core test functions for txt2speech functionality
5+
const testTxt2SpeechBasicCore = async function() {
6+
// Test basic text-to-speech with simple text
7+
const result = await puter.ai.txt2speech("Hello, this is a test message.");
8+
9+
// Check that result is an Audio object
10+
assert(result instanceof Audio, "txt2speech should return an Audio object");
11+
assert(result !== null, "txt2speech should not return null");
12+
13+
// Check that Audio object has proper methods
14+
assert(typeof result.play === 'function', "result should have play method");
15+
assert(typeof result.pause === 'function', "result should have pause method");
16+
assert(typeof result.toString === 'function', "result should have toString method");
17+
assert(typeof result.valueOf === 'function', "result should have valueOf method");
18+
19+
// Get the actual values to debug
20+
const toStringValue = result.toString();
21+
const valueOfValue = result.valueOf();
22+
const srcValue = result.src;
23+
24+
// Check that toString() and valueOf() return strings
25+
assert(typeof toStringValue === 'string', `toString() should return a string, got: ${typeof toStringValue} with value: ${toStringValue}`);
26+
assert(typeof valueOfValue === 'string', `valueOf() should return a string, got: ${typeof valueOfValue} with value: ${valueOfValue}`);
27+
28+
// Check that the URL is valid (could be blob: or data: or http:)
29+
assert(toStringValue.length > 0, "toString() should not return empty string");
30+
assert(valueOfValue.length > 0, "valueOf() should not return empty string");
31+
32+
// Check that it's a valid URL format (blob:, data:, http:, or https:)
33+
const isValidUrl = toStringValue.startsWith('blob:') ||
34+
toStringValue.startsWith('data:') ||
35+
toStringValue.startsWith('http:') ||
36+
toStringValue.startsWith('https:');
37+
assert(isValidUrl, `toString() should return a valid URL, got: ${toStringValue}`);
38+
39+
// Check that src is set and is a valid URL
40+
assert(typeof srcValue === 'string', "result should have src property as string");
41+
assert(srcValue.length > 0, "src should not be empty");
42+
43+
// Verify toString() and valueOf() return the same value as src
44+
assert(toStringValue === srcValue, `toString() should return the same as src. toString(): ${toStringValue}, src: ${srcValue}`);
45+
assert(valueOfValue === srcValue, `valueOf() should return the same as src. valueOf(): ${valueOfValue}, src: ${srcValue}`);
46+
};
47+
48+
const testTxt2SpeechWithParametersCore = async function() {
49+
// Test text-to-speech with language and voice parameters
50+
const result = await puter.ai.txt2speech("Hello, this is a test with parameters.", "en-US", "Brian");
51+
52+
// Check that result is an Audio object
53+
assert(result instanceof Audio, "txt2speech should return an Audio object");
54+
assert(result !== null, "txt2speech should not return null");
55+
56+
// Check that Audio object has proper methods
57+
assert(typeof result.play === 'function', "result should have play method");
58+
assert(typeof result.pause === 'function', "result should have pause method");
59+
assert(typeof result.toString === 'function', "result should have toString method");
60+
assert(typeof result.valueOf === 'function', "result should have valueOf method");
61+
62+
// Get the actual values to debug
63+
const toStringValue = result.toString();
64+
const valueOfValue = result.valueOf();
65+
const srcValue = result.src;
66+
67+
// Check that toString() and valueOf() return strings
68+
assert(typeof toStringValue === 'string', `toString() should return a string, got: ${typeof toStringValue} with value: ${toStringValue}`);
69+
assert(typeof valueOfValue === 'string', `valueOf() should return a string, got: ${typeof valueOfValue} with value: ${valueOfValue}`);
70+
71+
// Check that the URL is valid (could be blob: or data: or http:)
72+
assert(toStringValue.length > 0, "toString() should not return empty string");
73+
assert(valueOfValue.length > 0, "valueOf() should not return empty string");
74+
75+
// Check that it's a valid URL format
76+
const isValidUrl = toStringValue.startsWith('blob:') ||
77+
toStringValue.startsWith('data:') ||
78+
toStringValue.startsWith('http:') ||
79+
toStringValue.startsWith('https:');
80+
assert(isValidUrl, `toString() should return a valid URL, got: ${toStringValue}`);
81+
82+
// Check that src is set and is a valid URL
83+
assert(typeof srcValue === 'string', "result should have src property as string");
84+
assert(srcValue.length > 0, "src should not be empty");
85+
86+
// Verify toString() and valueOf() return the same value as src
87+
assert(toStringValue === srcValue, `toString() should return the same as src. toString(): ${toStringValue}, src: ${srcValue}`);
88+
assert(valueOfValue === srcValue, `valueOf() should return the same as src. valueOf(): ${valueOfValue}, src: ${srcValue}`);
89+
90+
// Verify that different parameters produce different audio (comparing with basic call)
91+
const basicResult = await puter.ai.txt2speech("Hello, this is a test with parameters.");
92+
assert(result.src !== basicResult.src, "different parameters should produce different audio URLs");
93+
};
94+
95+
const testTxt2SpeechWithTestModeCore = async function() {
96+
// Test text-to-speech with testMode enabled
97+
const result = await puter.ai.txt2speech("Hello, this is a test message.", "en-US", true);
98+
99+
// Check that result is an Audio object (same structure in test mode)
100+
assert(result instanceof Audio, "txt2speech should return an Audio object in test mode");
101+
assert(result !== null, "txt2speech should not return null in test mode");
102+
103+
// Check that Audio object has proper methods
104+
assert(typeof result.play === 'function', "result should have play method in test mode");
105+
assert(typeof result.pause === 'function', "result should have pause method in test mode");
106+
assert(typeof result.toString === 'function', "result should have toString method in test mode");
107+
assert(typeof result.valueOf === 'function', "result should have valueOf method in test mode");
108+
109+
// Get the actual values to debug
110+
const toStringValue = result.toString();
111+
const valueOfValue = result.valueOf();
112+
const srcValue = result.src;
113+
114+
// Check that toString() and valueOf() return strings
115+
assert(typeof toStringValue === 'string', `toString() should return a string in test mode, got: ${typeof toStringValue} with value: ${toStringValue}`);
116+
assert(typeof valueOfValue === 'string', `valueOf() should return a string in test mode, got: ${typeof valueOfValue} with value: ${valueOfValue}`);
117+
118+
// Check that the URL is valid (could be blob: or data: or http:)
119+
assert(toStringValue.length > 0, "toString() should not return empty string in test mode");
120+
assert(valueOfValue.length > 0, "valueOf() should not return empty string in test mode");
121+
122+
// Check that it's a valid URL format
123+
const isValidUrl = toStringValue.startsWith('blob:') ||
124+
toStringValue.startsWith('data:') ||
125+
toStringValue.startsWith('http:') ||
126+
toStringValue.startsWith('https:');
127+
assert(isValidUrl, `toString() should return a valid URL in test mode, got: ${toStringValue}`);
128+
129+
// Check that src is set and is a valid URL
130+
assert(typeof srcValue === 'string', "result should have src property as string in test mode");
131+
assert(srcValue.length > 0, "src should not be empty in test mode");
132+
133+
// Verify toString() and valueOf() return the same value as src
134+
assert(toStringValue === srcValue, `toString() should return the same as src in test mode. toString(): ${toStringValue}, src: ${srcValue}`);
135+
assert(valueOfValue === srcValue, `valueOf() should return the same as src in test mode. valueOf(): ${valueOfValue}, src: ${srcValue}`);
136+
};
137+
138+
// Export test functions
139+
window.txt2speechTests = [
140+
{
141+
name: "testTxt2SpeechBasic",
142+
description: "Test basic text-to-speech functionality and verify Audio object structure",
143+
test: async function() {
144+
try {
145+
await testTxt2SpeechBasicCore();
146+
pass("testTxt2SpeechBasic passed");
147+
} catch (error) {
148+
fail("testTxt2SpeechBasic failed:", error);
149+
}
150+
}
151+
},
152+
153+
{
154+
name: "testTxt2SpeechWithParameters",
155+
description: "Test text-to-speech with language and voice parameters (en-US, Brian)",
156+
test: async function() {
157+
try {
158+
await testTxt2SpeechWithParametersCore();
159+
pass("testTxt2SpeechWithParameters passed");
160+
} catch (error) {
161+
fail("testTxt2SpeechWithParameters failed:", error);
162+
}
163+
}
164+
},
165+
166+
{
167+
name: "testTxt2SpeechWithTestMode",
168+
description: "Test text-to-speech with testMode enabled to verify test functionality",
169+
test: async function() {
170+
try {
171+
await testTxt2SpeechWithTestModeCore();
172+
pass("testTxt2SpeechWithTestMode passed");
173+
} catch (error) {
174+
fail("testTxt2SpeechWithTestMode failed:", error);
175+
}
176+
}
177+
}
178+
];

0 commit comments

Comments
 (0)