diff --git a/.kokoro/build.sh b/.kokoro/build.sh index 9a453242c9..ffa0d7e83c 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -41,7 +41,6 @@ export SENDGRID_API_KEY=$(cat $KOKORO_GFILE_DIR/secrets-sendgrid-api-key.txt) # Configure GCF variables export FUNCTIONS_TOPIC=integration-tests-instance export FUNCTIONS_BUCKET=$GCLOUD_PROJECT -export BASE_URL="http://localhost:8010/${GCLOUD_PROJECT}/${GCF_REGION}" # Configure IoT variables export NODEJS_IOT_EC_PUBLIC_KEY=${KOKORO_GFILE_DIR}/ec_public.pem @@ -58,8 +57,12 @@ export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/secrets-key.json gcloud auth activate-service-account --key-file "$GOOGLE_APPLICATION_CREDENTIALS" gcloud config set project $GCLOUD_PROJECT +npm install -g @google-cloud/functions-framework + # Start functions emulator, if appropriate -if [[ $PROJECT == functions/* ]]; then +if [[ $PROJECT == functions/* ]] && grep --quiet functions-emulator package.json; then + export BASE_URL="http://localhost:8010/${GCLOUD_PROJECT}/${GCF_REGION}" + export FUNCTIONS_LOG_PATH=$(pwd)/logs/cloud-functions-emulator.log npm install -g @google-cloud/functions-emulator touch "$FUNCTIONS_LOG_PATH" diff --git a/functions/background/index.js b/functions/background/index.js index e149e55895..2d7ac6070d 100644 --- a/functions/background/index.js +++ b/functions/background/index.js @@ -22,13 +22,13 @@ const requestPromiseNative = require('request-promise-native'); * Background Cloud Function that returns a Promise. Note that we don't pass * a "callback" argument to the function. * - * @param {object} event The Cloud Functions event. - * @param {object} event.data The event data. + * @param {object} data The event data + * @param {object} data.endpoint The URL to send the request to. * @returns {Promise} */ -exports.helloPromise = event => { +exports.helloPromise = data => { return requestPromiseNative({ - uri: event.data.endpoint, + uri: data.endpoint, }); }; // [END functions_background_promise] @@ -38,12 +38,11 @@ exports.helloPromise = event => { * Background Cloud Function that returns synchronously. Note that we don't pass * a "callback" argument to the function. * - * @param {object} event The Cloud Functions event. - * @param {object} event.data The event data. + * @param {object} data The event data */ -exports.helloSynchronous = event => { +exports.helloSynchronous = data => { // This function returns synchronously - if (event.data.something === true) { + if (data.something === true) { return 'Something is true!'; } else { throw new Error('Something was not true!'); diff --git a/functions/background/package.json b/functions/background/package.json index 5dfbdbb94f..6dea6943ca 100644 --- a/functions/background/package.json +++ b/functions/background/package.json @@ -19,10 +19,10 @@ "request-promise-native": "^1.0.5" }, "devDependencies": { - "@google-cloud/nodejs-repo-tools": "^3.3.0", + "@google-cloud/functions-framework": "^1.1.1", + "child-process-promise": "^2.2.1", "mocha": "^6.0.0", - "proxyquire": "^2.1.0", - "sinon": "^7.2.7" + "requestretry": "^4.0.0" }, "cloud-repo-tools": { "requiresKeyFile": true, diff --git a/functions/background/test/index.test.js b/functions/background/test/index.test.js index 6812c81982..2ac797cfaa 100644 --- a/functions/background/test/index.test.js +++ b/functions/background/test/index.test.js @@ -15,49 +15,62 @@ 'use strict'; -const proxyquire = require('proxyquire').noCallThru(); -const sinon = require('sinon'); const assert = require('assert'); -const tools = require('@google-cloud/nodejs-repo-tools'); +const requestRetry = require('requestretry'); +const execPromise = require('child-process-promise').exec; +const path = require('path'); -function getSample() { - const requestPromiseNative = sinon.stub().returns(Promise.resolve('test')); +const program = require('..'); - return { - program: proxyquire('../', { - 'request-promise-native': requestPromiseNative, - }), - mocks: { - requestPromiseNative: requestPromiseNative, - }, - }; -} +const BASE_URL = process.env.BASE_URL || 'http://localhost:8080'; -beforeEach(tools.stubConsole); -afterEach(tools.restoreConsole); +const cwd = path.join(__dirname, '..'); -it('should make a promise request', () => { - const sample = getSample(); +let ffProc; + +before(() => { + ffProc = execPromise( + `functions-framework --target=helloPromise --signature-type=event`, + {timeout: 2000, shell: true, cwd} + ); +}); + +after(async () => { + try { + await ffProc; + } catch (err) { + // Timeouts always cause errors on Linux, so catch them + if (err.name && err.name === 'ChildProcessError') { + return; + } + + throw err; + } +}); + +it('should make a promise request', async () => { const event = { data: { - endpoint: 'foo.com', + endpoint: 'https://example.com', }, }; - return sample.program.helloPromise(event).then(result => { - assert.deepStrictEqual(sample.mocks.requestPromiseNative.firstCall.args, [ - {uri: 'foo.com'}, - ]); - assert.strictEqual(result, 'test'); + const response = await requestRetry({ + url: `${BASE_URL}/`, + method: 'POST', + body: event, + retryDelay: 200, + json: true, }); + + assert.strictEqual(response.statusCode, 200); + assert.ok(response.body.includes(`Example Domain`)); }); it('should return synchronously', () => { assert.strictEqual( - getSample().program.helloSynchronous({ - data: { - something: true, - }, + program.helloSynchronous({ + something: true, }), 'Something is true!' ); @@ -66,10 +79,8 @@ it('should return synchronously', () => { it('should throw an error', () => { assert.throws( () => { - getSample().program.helloSynchronous({ - data: { - something: false, - }, + program.helloSynchronous({ + something: false, }); }, Error,