From 7ed4291dc688165be19fee00b6651ea75ae329d3 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 4 Apr 2017 13:05:09 -0700 Subject: [PATCH] Require languageCode to be explicitly specified. (#2186) --- package.json | 4 +-- packages/speech/src/index.js | 46 +++++++++++++++++++------ packages/speech/system-test/speech.js | 6 ++-- packages/speech/test/index.js | 48 ++++++++++++++++++++++----- 4 files changed, 80 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 2f3f9383aa7..85a616e2e57 100644 --- a/package.json +++ b/package.json @@ -40,8 +40,8 @@ "unit-test": "mocha --timeout 5000 --bail packages/*/test/*.js", "snippet-test": "mocha --timeout 5000 --bail test/docs.js", "system-test": "mocha packages/*/system-test/*.js --no-timeouts --bail", - "cover": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -x 'packages/*/src/*{/*,/**/*}.js' -- --no-timeouts --bail packages/*/test/*.js -R spec", - "cover-html": "istanbul cover node_modules/mocha/bin/_mocha --report html -x 'packages/*/src/*{/*,/**/*}.js' -- --no-timeouts --bail packages/*/test/*.js -R spec", + "cover": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -x 'packages/*/src/*{/*,/**/*}.js' -- --no-timeouts packages/*/test/*.js -R spec", + "cover-html": "istanbul cover node_modules/mocha/bin/_mocha --report html -x 'packages/*/src/*{/*,/**/*}.js' -- --no-timeouts packages/*/test/*.js -R spec", "coveralls": "npm run cover && cat ./.coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" }, "license": "Apache-2.0", diff --git a/packages/speech/src/index.js b/packages/speech/src/index.js index feabc3095d5..99e33cfbc76 100644 --- a/packages/speech/src/index.js +++ b/packages/speech/src/index.js @@ -372,6 +372,8 @@ Speech.formatResults_ = function(resultSets, verboseMode) { * * @param {object} config - A `StreamingRecognitionConfig` object. See * [`StreamingRecognitionConfig`](https://cloud.google.com/speech/reference/rpc/google.cloud.speech.v1beta1#google.cloud.speech.v1beta1.StreamingRecognitionConfig). + * @param {string} config.languageCode - The language of the supplied audio as +* [BCP-47 language tag](http://bit.ly/1ZHeENX). Example: 'en-US'. * @param {number=} config.timeout - In seconds, the amount of time before the * underlying API request times out. The default value, `190`, is sufficient * for audio input of 60 seconds or less. If your input is longer, consider @@ -390,6 +392,7 @@ Speech.formatResults_ = function(resultSets, verboseMode) { * var request = { * config: { * encoding: 'LINEAR16', + * languageCode: 'en-US', * sampleRateHertz: 16000 * }, * singleUtterance: false, @@ -410,6 +413,7 @@ Speech.formatResults_ = function(resultSets, verboseMode) { * var request = { * config: { * encoding: 'LINEAR16', + * languageCode: 'en-US', * sampleRateHertz: 16000 * }, * singleUtterance: false, @@ -432,11 +436,19 @@ Speech.prototype.createRecognizeStream = function(config) { throw new Error('A recognize request requires a configuration object.'); } - config = extend(true, { - config: { - languageCode: 'en-US' - } - }, config); + // As of Speech v1, a language code is required; throw an exception if we + // did not receive one. + // + // This is expected within a nested config, but in the interest of user + // sanity, accept it in the outer config object. + config.config = config.config || {}; + if (config.languageCode) { + config.config.languageCode = config.languageCode; + delete config.languageCode; + } + if (is.undefined(config.config.languageCode)) { + throw new Error('A `languageCode` is required in the config object.'); + } var verboseMode = config.verbose === true; delete config.verbose; @@ -524,6 +536,8 @@ Speech.prototype.operation = function(name) { * object. * @param {object} config - A `RecognitionConfig` object. See * [`RecognitionConfig`](https://cloud.google.com/speech/reference/rpc/google.cloud.speech.v1beta1#google.cloud.speech.v1beta1.RecognitionConfig). + * @param {string} config.languageCode - The language of the supplied audio as + * [BCP-47 language tag](http://bit.ly/1ZHeENX). Example: 'en-US'. * @param {boolean=} config.verbose - Enable verbose mode for a more detailed * response. See the examples below. Default: `false`. * @param {function} callback - The callback function. @@ -540,6 +554,7 @@ Speech.prototype.operation = function(name) { * @example * var config = { * encoding: 'LINEAR16', + * languageCode: 'en-US', * sampleRateHertz: 16000 * }; * @@ -582,6 +597,7 @@ Speech.prototype.operation = function(name) { * //- * var config = { * encoding: 'LINEAR16', + * languageCode: 'en-US', * sampleRateHertz: 16000, * verbose: true * }; @@ -620,9 +636,11 @@ Speech.prototype.recognize = function(file, config, callback) { throw new Error('A recognize request requires a configuration object.'); } - config = extend({ - languageCode: 'en-US' - }, config); + // As of Speech v1, a language code is required; throw an exception if we + // did not receive one. + if (is.undefined(config.languageCode)) { + throw new Error('A `languageCode` is required in the config object.'); + } if (!config.encoding) { config.encoding = Speech.detectEncoding_(file); @@ -674,6 +692,8 @@ Speech.prototype.recognize = function(file, config, callback) { * [`RecognitionConfig`](https://cloud.google.com/speech/reference/rpc/google.cloud.speech.v1beta1#google.cloud.speech.v1beta1.RecognitionConfig). * @param {boolean=} config.verbose - Enable verbose mode for a more detailed * response. See the examples below. Default: `false`. + * @param {string} config.languageCode - The language of the supplied audio as + * [BCP-47 language tag](http://bit.ly/1ZHeENX). Example: 'en-US'. * @param {function} callback - The callback function. * @param {?error} callback.err - An error returned while making this request. * @param {module:speech/operation} callback.operation - An operation object @@ -683,6 +703,7 @@ Speech.prototype.recognize = function(file, config, callback) { * @example * var config = { * encoding: 'LINEAR16', + * languageCode: 'en-US', * sampleRateHertz: 16000 * }; * @@ -732,6 +753,7 @@ Speech.prototype.recognize = function(file, config, callback) { * //- * var config = { * encoding: 'LINEAR16', + * languageCode: 'en-US', * sampleRateHertz: 16000, * verbose: true * }; @@ -764,9 +786,11 @@ Speech.prototype.recognize = function(file, config, callback) { Speech.prototype.startRecognition = function(file, config, callback) { var self = this; - config = extend({ - languageCode: 'en-US' - }, config); + // As of Speech v1, a language code is required; throw an exception if we + // did not receive one. + if (is.undefined(config.languageCode)) { + throw new Error('A `languageCode` is required in the config object.'); + } if (!config.encoding) { config.encoding = Speech.detectEncoding_(file); diff --git a/packages/speech/system-test/speech.js b/packages/speech/system-test/speech.js index 597cb879156..1c7f049939d 100644 --- a/packages/speech/system-test/speech.js +++ b/packages/speech/system-test/speech.js @@ -49,6 +49,7 @@ describe('Speech', function() { var OPTIONS = { encoding: 'LINEAR16', + languageCode: 'en-US', sampleRateHertz: 16000 }; @@ -109,7 +110,7 @@ describe('Speech', function() { assert.ifError(err); speech.recognize({ - content: audioFile + content: audioFile, }, OPTIONS, assertSimplifiedResponse(done)); }); }); @@ -119,7 +120,7 @@ describe('Speech', function() { assert.ifError(err); speech.recognize({ - content: audioFile + content: audioFile, }, OPTIONS_VERBOSE, assertVerboseResponse(done)); }); }); @@ -127,6 +128,7 @@ describe('Speech', function() { it('recognizes speech from local file', function(done) { speech.recognize(AUDIO_FILES.bridge.path, { // encoding should be automatically detected + languageCode: 'en-US', sampleRateHertz: 16000 }, assertSimplifiedResponse(done)); }); diff --git a/packages/speech/test/index.js b/packages/speech/test/index.js index d7c81c90b90..bd9921f690e 100644 --- a/packages/speech/test/index.js +++ b/packages/speech/test/index.js @@ -451,7 +451,7 @@ describe('Speech', function() { }); describe('createRecognizeStream', function() { - var CONFIG = {}; + var CONFIG = {languageCode: 'en-US'}; var stream; var requestStream; @@ -474,6 +474,12 @@ describe('Speech', function() { }, /A recognize request requires a configuration object\./); }); + it('should throw if a language code is not provided', function() { + assert.throws(function() { + speech.createRecognizeStream({}); + }, /languageCode/); + }); + it('should make the correct request once writing started', function(done) { speech.api.Speech = { streamingRecognize: function() { @@ -603,6 +609,7 @@ describe('Speech', function() { it('should format results from the API in verbose mode', function(done) { var stream = speech.createRecognizeStream({ + languageCode: 'en-US', verbose: true }); @@ -626,6 +633,7 @@ describe('Speech', function() { it('should delete verbose option from request object', function(done) { var stream = speech.createRecognizeStream({ + languageCode: 'en-US', verbose: true }); @@ -662,6 +670,7 @@ describe('Speech', function() { }; var stream = speech.createRecognizeStream({ + languageCode: 'en-US', timeout: timeout }); @@ -683,6 +692,7 @@ describe('Speech', function() { }; var stream = speech.createRecognizeStream({ + languageCode: 'en-US', timeout: 90 }); @@ -738,7 +748,10 @@ describe('Speech', function() { describe('recognize', function() { var FILE = {}; var FOUND_FILE = {}; - var CONFIG = { a: 'b' }; + var CONFIG = { + a: 'b', + languageCode: 'en-US', + }; var DETECTED_ENCODING = 'LINEAR16'; beforeEach(function() { @@ -788,8 +801,14 @@ describe('Speech', function() { speech.recognize(FILE, CONFIG, assert.ifError); }); + it('should fail if no language code is set', function() { + assert.throws(function() { + speech.recognize(FILE, {}); + }, /languageCode/); + }); + it('should allow setting a languageCode', function(done) { - var languageCode = 'uk'; + var languageCode = 'en-GB'; var config = { languageCode: languageCode @@ -807,7 +826,8 @@ describe('Speech', function() { it('should respect the provided encoding', function(done) { var config = { - encoding: 'LINEAR32' + encoding: 'LINEAR32', + languageCode: 'en-US' }; Speech.detectEncoding_ = function() { @@ -839,7 +859,7 @@ describe('Speech', function() { } }; - speech.recognize(FILE, {}, assert.ifError); + speech.recognize(FILE, {languageCode: 'en-US'}, assert.ifError); }); it('should return an error from findFile_', function(done) { @@ -956,7 +976,10 @@ describe('Speech', function() { describe('startRecognition', function() { var FILE = {}; var FOUND_FILE = {}; - var CONFIG = { a: 'b' }; + var CONFIG = { + a: 'b', + languageCode: 'en-US' + }; var DETECTED_ENCODING = 'LINEAR16'; beforeEach(function() { @@ -1000,8 +1023,14 @@ describe('Speech', function() { speech.startRecognition(FILE, CONFIG, assert.ifError); }); + it('should error if no language code is given', function() { + assert.throws(function() { + speech.startRecognition(FILE, {}); + }, /languageCode/); + }); + it('should respect the provided language code', function(done) { - var languageCode = 'uk'; + var languageCode = 'en-GB'; var config = { languageCode: languageCode @@ -1019,7 +1048,8 @@ describe('Speech', function() { it('should respect the provided encoding', function(done) { var config = { - encoding: 'LINEAR32' + encoding: 'LINEAR32', + languageCode: 'en-US' }; Speech.detectEncoding_ = function() { @@ -1051,7 +1081,7 @@ describe('Speech', function() { } }; - speech.startRecognition(FILE, {}, assert.ifError); + speech.startRecognition(FILE, {languageCode: 'en-US'}, assert.ifError); }); it('should return an error from findFile_', function(done) {