translator.optional.https.window.js (9280B)
1 // META: title=Optional Translator tests 2 // META: global=window 3 // META: timeout=long 4 // META: script=../resources/util.js 5 // META: script=/common/gc.js 6 // META: script=/resources/testdriver.js 7 // META: script=resources/util.js 8 // 9 // Setting `timeout=long` as this test may require downloading the translation 10 // library and the language models. 11 12 'use strict'; 13 14 // TODO(crbug.com/390246212): Support model state controls for WPTs. 15 promise_test(async t => { 16 // Create requires user activation when availability is 'downloadable'. 17 const languagePair = {sourceLanguage: 'en', targetLanguage: 'ja'}; 18 assert_implements_optional(await Translator.availability(languagePair) == 'downloadable'); 19 assert_false(navigator.userActivation.isActive); 20 await promise_rejects_dom(t, 'NotAllowedError', Translator.create(languagePair)); 21 await test_driver.bless('Translator.create', async () => { await Translator.create(languagePair); }); 22 23 // Create does not require user activation when availability is 'available'. 24 assert_equals(await Translator.availability(languagePair), 'available'); 25 assert_false(navigator.userActivation.isActive); 26 await Translator.create(languagePair); 27 }, 'Create requires user activation when availability is "downloadable"'); 28 29 promise_test(async t => { 30 const translator = 31 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 32 assert_equals(await translator.translate('hello'), 'こんにちは'); 33 }, 'Simple Translator.translate() call'); 34 35 promise_test(async () => { 36 const translator = 37 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 38 const streamingResponse = translator.translateStreaming('hello'); 39 assert_equals( 40 Object.prototype.toString.call(streamingResponse), 41 '[object ReadableStream]'); 42 let result = ''; 43 for await (const chunk of streamingResponse) { 44 result += chunk; 45 } 46 assert_equals(await translator.translate('hello'), 'こんにちは'); 47 }, 'Simple Translator.translateStreaming() call'); 48 49 promise_test(async () => { 50 const translator = 51 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 52 const streamingResponse = translator.translateStreaming('Welcome. Nice to meet you.'); 53 assert_equals( 54 Object.prototype.toString.call(streamingResponse), 55 '[object ReadableStream]'); 56 let result = ''; 57 for await (const chunk of streamingResponse) { 58 result += chunk; 59 } 60 assert_equals(result, 'ようこそ。 はじめまして。'); 61 }, 'Multiple sentence Translator.translateStreaming() call'); 62 63 promise_test(async () => { 64 const translator = 65 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 66 const streamingResponse = translator.translateStreaming('Hello, Dr. Sanders. Nice to meet you.'); 67 assert_equals( 68 Object.prototype.toString.call(streamingResponse), 69 '[object ReadableStream]'); 70 let result = ''; 71 for await (const chunk of streamingResponse) { 72 result += chunk; 73 } 74 assert_equals(result, 'こんにちは、サンダース博士です。 はじめまして。'); 75 }, 'Multiple sentence Translator.translateStreaming() call with honorific'); 76 77 promise_test(async () => { 78 const translator = 79 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 80 const streamingResponse = translator.translateStreaming('hello'); 81 garbageCollect(); 82 assert_equals(Object.prototype.toString.call(streamingResponse), 83 '[object ReadableStream]'); 84 let result = ''; 85 for await (const value of streamingResponse) { 86 result += value; 87 garbageCollect(); 88 } 89 assert_greater_than(result.length, 0, 'The result should not be empty.'); 90 }, 'Translate Streaming API must continue even after GC has been performed.'); 91 92 promise_test(async t => { 93 const translator = 94 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 95 assert_equals(translator.sourceLanguage, 'en'); 96 assert_equals(translator.targetLanguage, 'ja'); 97 }, 'Translator: sourceLanguage and targetLanguage are equal to their respective option passed in to Translator.create.'); 98 99 promise_test(async t => { 100 const controller = new AbortController(); 101 controller.abort(); 102 103 const createPromise = createTranslator( 104 {signal: controller.signal, sourceLanguage: 'en', targetLanguage: 'ja'}); 105 106 await promise_rejects_dom(t, 'AbortError', createPromise); 107 }, 'Translator.create() call with an aborted signal.'); 108 109 promise_test(async t => { 110 await testAbortPromise(t, signal => { 111 return createTranslator( 112 {signal, sourceLanguage: 'en', targetLanguage: 'ja'}); 113 }); 114 }, 'Aborting Translator.create().'); 115 116 promise_test(async t => { 117 const controller = new AbortController(); 118 controller.abort(); 119 120 const translator = 121 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 122 const translatePromise = 123 translator.translate('hello', {signal: controller.signal}); 124 125 await promise_rejects_dom(t, 'AbortError', translatePromise); 126 }, 'Translator.translate() call with an aborted signal.'); 127 128 promise_test(async t => { 129 const translator = 130 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 131 await testAbortPromise(t, signal => { 132 return translator.translate('hello', {signal}); 133 }); 134 }, 'Aborting Translator.translate().'); 135 136 promise_test(async t => { 137 await testDestroy( 138 t, createTranslator, { sourceLanguage: 'en', targetLanguage: 'ja' }, [ 139 translator => translator.translate(kTestPrompt), 140 translator => translator.measureInputUsage(kTestPrompt), 141 ]); 142 }, 'Calling Translator.destroy() aborts calls to write and measureInputUsage.'); 143 144 promise_test(async (t) => { 145 const translator = 146 await createTranslator({ sourceLanguage: 'en', targetLanguage: 'ja' }); 147 const stream = translator.translateStreaming(kTestPrompt); 148 149 translator.destroy(); 150 151 await promise_rejects_dom( 152 t, 'AbortError', stream.pipeTo(new WritableStream())); 153 }, 'Translator.translateStreaming() fails after destroyed'); 154 155 promise_test(async t => { 156 await testCreateAbort( 157 t, createTranslator, { sourceLanguage: 'en', targetLanguage: 'ja' }, [ 158 translator => translator.translate(kTestPrompt), 159 translator => translator.measureInputUsage(kTestPrompt), 160 ]); 161 }, 'Translator.create()\'s abort signal destroys its Translator after creation.'); 162 163 promise_test(async t => { 164 await testMonitor( 165 createTranslator, {sourceLanguage: 'en', targetLanguage: 'ja'}); 166 }, 'Translator.create() notifies its monitor on downloadprogress'); 167 168 promise_test(async t => { 169 await testCreateMonitorWithAbort( 170 t, createTranslator, {sourceLanguage: 'en', targetLanguage: 'ja'}); 171 }, 'Progress events are not emitted after aborted.'); 172 173 promise_test(async t => { 174 const translator = 175 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 176 177 // Strings containing only white space are not translatable. 178 const nonTranslatableStrings = ['', ' ', ' ', ' \r\n\t\f']; 179 180 // Strings containing only control characters are not translatable. 181 for (let c = 0; c < 0x1F; c++) { 182 nonTranslatableStrings.push(String.fromCharCode(c)); 183 } 184 185 const translatedNonTranslatableString = await Promise.all( 186 nonTranslatableStrings.map(str => translator.translate(str))); 187 188 // Non translatable strings should be echoed back 189 assert_array_equals(translatedNonTranslatableString, nonTranslatableStrings); 190 191 // Adding translatable text makes it translatable. 192 const translatableStrings = 193 nonTranslatableStrings.map(str => `Hello ${str} world`); 194 195 const translatedTranslatableString = await Promise.all( 196 translatableStrings.map(str => translator.translate(str))); 197 198 // All the strings should have been translated in some way. 199 for (let i = 0; i < translatableStrings.length; i++) { 200 assert_not_equals(translatedTranslatableString[i], translatableStrings[i]); 201 } 202 }, 'Translator.translate() echoes non-translatable content'); 203 204 promise_test(async t => { 205 const translator = 206 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 207 208 const text = 'hello'; 209 const inputUsage = await translator.measureInputUsage(text); 210 211 assert_greater_than_equal(translator.inputQuota, 0); 212 assert_greater_than_equal(inputUsage, 0); 213 214 if (inputUsage < translator.inputQuota) { 215 assert_equals(await translator.translate(text), 'こんにちは'); 216 } else { 217 await promise_rejects_quotaexceedederror(t, translator.translate(text), requested => requested !== null, translator.inputQuota); 218 } 219 }, 'Translator.measureInputUsage() and inputQuota basic usage.'); 220 221 promise_test(async t => { 222 const controller = new AbortController(); 223 controller.abort(); 224 225 const translator = 226 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 227 const measureInputUsagePromise = 228 translator.measureInputUsage('hello', {signal: controller.signal}); 229 230 await promise_rejects_dom(t, 'AbortError', measureInputUsagePromise); 231 }, 'Translator.measureInputUsage() call with an aborted signal.'); 232 233 promise_test(async t => { 234 const translator = 235 await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); 236 await testAbortPromise(t, signal => { 237 return translator.measureInputUsage('hello', {signal}); 238 }); 239 }, 'Aborting Translator.measureInputUsage().');