From 43cb78c469b1d7e3114b54fb81c9982ca50387f1 Mon Sep 17 00:00:00 2001 From: "F. Hinkelmann" Date: Fri, 7 Dec 2018 09:31:10 -0800 Subject: [PATCH] Use eslint in functions/ (#1009) Fixes https://github.com/GoogleCloudPlatform/nodejs-docs-samples/issues/992 --- .eslintignore | 1 - functions/background/index.js | 6 +- functions/background/package.json | 5 +- functions/background/test/index.test.js | 70 ++-- functions/billing/.eslintrc.yml | 4 + functions/billing/index.js | 44 +- functions/billing/package.json | 6 +- functions/billing/test/index.test.js | 66 +-- functions/composer-storage-trigger/index.js | 88 ++-- .../composer-storage-trigger/package.json | 4 +- .../test/index.test.js | 58 +-- functions/concepts/package.json | 5 +- functions/concepts/test/index.test.js | 8 +- functions/datastore/index.js | 31 +- functions/datastore/package.json | 8 +- functions/datastore/test/.eslintrc.yml | 4 + functions/datastore/test/index.test.js | 131 +++--- functions/env_vars/package.json | 5 +- functions/env_vars/test/index.test.js | 8 +- functions/errorreporting/.eslintrc.yml | 3 + functions/errorreporting/index.js | 12 +- functions/errorreporting/report.js | 28 +- functions/firebase/index.js | 16 +- functions/firebase/package.json | 4 +- functions/firebase/test/index.test.js | 59 +-- functions/gcs/index.js | 22 +- functions/gcs/package.json | 5 +- functions/gcs/test/index.test.js | 38 +- functions/headless-chrome/index.js | 6 +- functions/headless-chrome/package.json | 2 - functions/headless-chrome/test/index.test.js | 2 +- functions/helloworld/.eslintrc.yml | 5 + functions/helloworld/index.js | 4 +- functions/helloworld/package.json | 5 +- functions/helloworld/shim.js | 80 ++-- functions/helloworld/test/index.test.js | 126 +++--- .../test/sample.integration.http.test.js | 10 +- .../test/sample.integration.pubsub.test.js | 14 +- .../test/sample.integration.storage.test.js | 24 +- .../test/sample.system.http.test.js | 10 +- .../test/sample.system.pubsub.test.js | 14 +- .../test/sample.system.storage.test.js | 22 +- .../helloworld/test/sample.unit.http.test.js | 10 +- .../test/sample.unit.pubsub.test.js | 6 +- .../test/sample.unit.storage.test.js | 12 +- functions/helloworld/test/shim.test.js | 45 +- functions/http/.eslintrc.yml | 4 + functions/http/index.js | 29 +- functions/http/package.json | 5 +- functions/http/test/index.test.js | 85 ++-- functions/imagemagick/index.js | 53 ++- functions/imagemagick/package.json | 5 +- functions/imagemagick/test/index.test.js | 161 +++++--- functions/log/index.js | 39 +- functions/log/package.json | 5 +- functions/log/test/index.test.js | 57 ++- functions/node8/.eslintrc.yml | 3 + functions/node8/index.js | 20 +- functions/node8/package.json | 4 +- functions/node8/test/index.test.js | 129 +++--- .../node8/test/sample.unit.pubsub.test.js | 2 +- .../node8/test/sample.unit.storage.test.js | 6 +- functions/ocr/app/index.js | 59 ++- functions/ocr/app/package.json | 5 +- functions/ocr/app/test/index.test.js | 389 +++++++++++------- functions/pubsub/index.js | 25 +- functions/pubsub/package.json | 5 +- functions/pubsub/test/index.test.js | 50 +-- functions/scheduleinstance/index.js | 16 +- functions/scheduleinstance/package.json | 4 +- functions/scheduleinstance/test/index.test.js | 129 +++--- functions/sendgrid/index.js | 85 ++-- functions/sendgrid/package.json | 5 +- functions/sendgrid/test/index.test.js | 214 ++++++---- functions/slack/index.js | 51 ++- functions/slack/package.json | 5 +- functions/slack/test/index.test.js | 167 ++++---- functions/spanner/index.js | 23 +- functions/spanner/package.json | 5 +- functions/spanner/test/index.test.js | 44 +- functions/speech-to-speech/index.js | 170 ++++---- functions/speech-to-speech/package.json | 4 +- functions/speech-to-speech/test/index.test.js | 44 +- .../test/sample.integration.http.test.js | 103 +++-- functions/sql/index.js | 7 +- functions/sql/package.json | 5 +- functions/sql/test/index.test.js | 26 +- functions/tips/index.js | 35 +- functions/tips/package.json | 7 +- functions/tips/test/index.test.js | 28 +- functions/uuid/package.json | 5 +- functions/uuid/test/index.test.js | 4 +- 92 files changed, 1971 insertions(+), 1491 deletions(-) create mode 100644 functions/billing/.eslintrc.yml create mode 100644 functions/datastore/test/.eslintrc.yml create mode 100644 functions/errorreporting/.eslintrc.yml create mode 100644 functions/helloworld/.eslintrc.yml create mode 100644 functions/http/.eslintrc.yml create mode 100644 functions/node8/.eslintrc.yml diff --git a/.eslintignore b/.eslintignore index bc1afe5d69..6c3fc746d8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,2 @@ **/node_modules/* -functions/** appengine/parse-server/cloud/main.js diff --git a/functions/background/index.js b/functions/background/index.js index 2d195d8d6b..82ed3d2c8a 100644 --- a/functions/background/index.js +++ b/functions/background/index.js @@ -46,9 +46,9 @@ const requestPromiseNative = require('request-promise-native'); * @param {object} event.data The event data. * @returns {Promise} */ -exports.helloPromise = (event) => { +exports.helloPromise = event => { return requestPromiseNative({ - uri: event.data.endpoint + uri: event.data.endpoint, }); }; // [END functions_background_promise] @@ -61,7 +61,7 @@ exports.helloPromise = (event) => { * @param {object} event The Cloud Functions event. * @param {object} event.data The event data. */ -exports.helloSynchronous = (event) => { +exports.helloSynchronous = event => { // This function returns synchronously if (event.data.something === true) { return 'Something is true!'; diff --git a/functions/background/package.json b/functions/background/package.json index 535808ab24..4ae1d74fa8 100644 --- a/functions/background/package.json +++ b/functions/background/package.json @@ -9,11 +9,9 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "test": "ava -T 20s --verbose test/*.test.js" }, "dependencies": { @@ -24,7 +22,6 @@ "@google-cloud/nodejs-repo-tools": "^3.0.0", "ava": "0.25.0", "proxyquire": "2.1.0", - "semistandard": "^12.0.1", "sinon": "4.4.2" }, "cloud-repo-tools": { diff --git a/functions/background/test/index.test.js b/functions/background/test/index.test.js index a3654b4228..5c1810fdeb 100644 --- a/functions/background/test/index.test.js +++ b/functions/background/test/index.test.js @@ -20,27 +20,27 @@ const sinon = require(`sinon`); const test = require(`ava`); const tools = require(`@google-cloud/nodejs-repo-tools`); -function getSample () { +function getSample() { const requestPromiseNative = sinon.stub().returns(Promise.resolve(`test`)); return { program: proxyquire(`../`, { - 'request-promise-native': requestPromiseNative + 'request-promise-native': requestPromiseNative, }), mocks: { - requestPromiseNative: requestPromiseNative - } + requestPromiseNative: requestPromiseNative, + }, }; } test.beforeEach(tools.stubConsole); test.afterEach.always(tools.restoreConsole); -test.serial(`should echo message`, (t) => { +test.serial(`should echo message`, t => { const event = { data: { - myMessage: `hi` - } + myMessage: `hi`, + }, }; const sample = getSample(); const callback = sinon.stub(); @@ -53,45 +53,53 @@ test.serial(`should echo message`, (t) => { t.deepEqual(callback.firstCall.args, []); }); -test.serial(`should say no message was provided`, (t) => { +test.serial(`should say no message was provided`, t => { const error = new Error(`No message defined!`); const callback = sinon.stub(); const sample = getSample(); - sample.program.helloWorld({ data: {} }, callback); + sample.program.helloWorld({data: {}}, callback); t.is(callback.callCount, 1); t.deepEqual(callback.firstCall.args, [error]); }); -test.serial(`should make a promise request`, (t) => { +test.serial(`should make a promise request`, t => { const sample = getSample(); const event = { data: { - endpoint: `foo.com` - } + endpoint: `foo.com`, + }, }; - return sample.program.helloPromise(event) - .then((result) => { - t.deepEqual(sample.mocks.requestPromiseNative.firstCall.args, [{ uri: `foo.com` }]); - t.is(result, `test`); - }); + return sample.program.helloPromise(event).then(result => { + t.deepEqual(sample.mocks.requestPromiseNative.firstCall.args, [ + {uri: `foo.com`}, + ]); + t.is(result, `test`); + }); }); -test.serial(`should return synchronously`, (t) => { - t.is(getSample().program.helloSynchronous({ - data: { - something: true - } - }), `Something is true!`); -}); - -test.serial(`should throw an error`, (t) => { - t.throws(() => { +test.serial(`should return synchronously`, t => { + t.is( getSample().program.helloSynchronous({ data: { - something: false - } - }); - }, Error, `Something was not true!`); + something: true, + }, + }), + `Something is true!` + ); +}); + +test.serial(`should throw an error`, t => { + t.throws( + () => { + getSample().program.helloSynchronous({ + data: { + something: false, + }, + }); + }, + Error, + `Something was not true!` + ); }); diff --git a/functions/billing/.eslintrc.yml b/functions/billing/.eslintrc.yml new file mode 100644 index 0000000000..e8cc274761 --- /dev/null +++ b/functions/billing/.eslintrc.yml @@ -0,0 +1,4 @@ +--- +rules: + no-unused-vars: off + diff --git a/functions/billing/index.js b/functions/billing/index.js index 761a202bfc..7a081681e0 100644 --- a/functions/billing/index.js +++ b/functions/billing/index.js @@ -15,8 +15,8 @@ // [START functions_billing_limit] // [START functions_billing_stop] -const { google } = require('googleapis'); -const { auth } = require('google-auth-library'); +const {google} = require('googleapis'); +const {auth} = require('google-auth-library'); const PROJECT_ID = process.env.GCP_PROJECT; const PROJECT_NAME = `projects/${PROJECT_ID}`; @@ -38,7 +38,7 @@ exports.notifySlack = async (data, context) => { const res = await slack.chat.postMessage({ token: BOT_ACCESS_TOKEN, channel: CHANNEL, - text: budgetNotificationText + text: budgetNotificationText, }); console.log(res); }; @@ -71,13 +71,13 @@ const _setAuthCredential = async () => { if (client.hasScopes && !client.hasScopes()) { client = client.createScoped([ 'https://www.googleapis.com/auth/cloud-billing', - 'https://www.googleapis.com/auth/cloud-platform' + 'https://www.googleapis.com/auth/cloud-platform', ]); } // Set credential globally for all requests google.options({ - auth: client + auth: client, }); }; @@ -86,8 +86,8 @@ const _setAuthCredential = async () => { * @param {string} projectName Name of project to check if billing is enabled * @return {bool} Whether project has billing enabled or not */ -const _isBillingEnabled = async (projectName) => { - const res = await billing.getBillingInfo({ name: projectName }); +const _isBillingEnabled = async projectName => { + const res = await billing.getBillingInfo({name: projectName}); return res.data.billingEnabled; }; @@ -96,10 +96,10 @@ const _isBillingEnabled = async (projectName) => { * @param {string} projectName Name of project disable billing on * @return {string} Text containing response from disabling billing */ -const _disableBillingForProject = async (projectName) => { +const _disableBillingForProject = async projectName => { const res = await billing.updateBillingInfo({ name: projectName, - resource: { 'billingAccountName': '' } // Disable billing + resource: {billingAccountName: ''}, // Disable billing }); return `Billing disabled: ${JSON.stringify(res.data)}`; }; @@ -126,7 +126,7 @@ exports.limitUse = async (data, context) => { const _listRunningInstances = async (projectId, zone) => { const res = await compute.instances.list({ project: projectId, - zone: zone + zone: zone, }); const instances = res.data.items || []; @@ -142,15 +142,19 @@ const _stopInstances = async (projectId, zone, instanceNames) => { if (!instanceNames.length) { return 'No running instances were found.'; } - await Promise.all(instanceNames.map(instanceName => { - return compute.instances.stop({ - project: projectId, - zone: zone, - instance: instanceName - }).then((res) => { - console.log('Instance stopped successfully: ' + instanceName); - return res.data; - }); - })); + await Promise.all( + instanceNames.map(instanceName => { + return compute.instances + .stop({ + project: projectId, + zone: zone, + instance: instanceName, + }) + .then(res => { + console.log('Instance stopped successfully: ' + instanceName); + return res.data; + }); + }) + ); }; // [END functions_billing_limit] diff --git a/functions/billing/package.json b/functions/billing/package.json index 13422b2abb..1fafd30b51 100644 --- a/functions/billing/package.json +++ b/functions/billing/package.json @@ -3,9 +3,10 @@ "version": "0.0.1", "description": "Examples of integrating Cloud Functions with billing", "main": "index.js", + "engines": { + "node": ">=8" + }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "test": "ava test/*" }, "author": "Ace Nassri ", @@ -19,7 +20,6 @@ "@google-cloud/nodejs-repo-tools": "^2.2.5", "ava": "^0.25.0", "proxyquire": "^2.1.0", - "semistandard": "^13.0.0", "sinon": "^6.3.4" } } diff --git a/functions/billing/test/index.test.js b/functions/billing/test/index.test.js index 99f672f358..8a7bf1ace7 100644 --- a/functions/billing/test/index.test.js +++ b/functions/billing/test/index.test.js @@ -17,72 +17,72 @@ const proxyquire = require(`proxyquire`).noCallThru(); const sinon = require(`sinon`); const test = require(`ava`); -function getSample () { +function getSample() { const instanceListMock = [ - { name: 'test-instance-1', status: 'RUNNING' }, - { name: 'test-instance-2', status: 'RUNNING' } + {name: 'test-instance-1', status: 'RUNNING'}, + {name: 'test-instance-2', status: 'RUNNING'}, ]; const listInstancesResponseMock = { data: { - items: instanceListMock - } + items: instanceListMock, + }, }; const computeMock = { instances: { list: sinon.stub().returns(listInstancesResponseMock), - stop: sinon.stub().resolves({ data: {} }) - } + stop: sinon.stub().resolves({data: {}}), + }, }; const cloudbillingMock = { projects: { getBillingInfo: sinon.stub().resolves({ data: { - billingEnabled: true - } + billingEnabled: true, + }, }), updateBillingInfo: sinon.stub().returns({ - data: {} - }) - } + data: {}, + }), + }, }; const googleMock = { cloudbilling: sinon.stub().returns(cloudbillingMock), compute: sinon.stub().returns(computeMock), - options: sinon.stub() + options: sinon.stub(), }; const googleapisMock = { - google: googleMock + google: googleMock, }; const slackMock = { chat: { - postMessage: sinon.stub().returns({ data: {} }) - } + postMessage: sinon.stub().returns({data: {}}), + }, }; const credentialMock = { - hasScopes: sinon.stub().returns(false) + hasScopes: sinon.stub().returns(false), }; credentialMock.createScoped = sinon.stub().returns(credentialMock); const googleAuthMock = { auth: { getApplicationDefault: sinon.stub().resolves({ - credential: credentialMock - }) - } + credential: credentialMock, + }), + }, }; return { program: proxyquire(`../`, { 'google-auth-library': googleAuthMock, - 'googleapis': googleapisMock, - 'slack': slackMock + googleapis: googleapisMock, + slack: slackMock, }), mocks: { google: googleMock, @@ -92,18 +92,18 @@ function getSample () { cloudbilling: cloudbillingMock, credential: credentialMock, slack: slackMock, - instanceList: instanceListMock - } + instanceList: instanceListMock, + }, }; } test(`should notify Slack when budget is exceeded`, async t => { - const { program, mocks } = getSample(); + const {program, mocks} = getSample(); - const jsonData = { cost: 500, budget: 400 }; + const jsonData = {cost: 500, budget: 400}; const pubsubData = { data: Buffer.from(JSON.stringify(jsonData)).toString('base64'), - attributes: {} + attributes: {}, }; await program.notifySlack(pubsubData, null); @@ -112,12 +112,12 @@ test(`should notify Slack when budget is exceeded`, async t => { }); test(`should disable billing when budget is exceeded`, async t => { - const { program, mocks } = getSample(); + const {program, mocks} = getSample(); - const jsonData = { cost: 500, budget: 400 }; + const jsonData = {cost: 500, budget: 400}; const pubsubData = { data: Buffer.from(JSON.stringify(jsonData)).toString('base64'), - attributes: {} + attributes: {}, }; await program.stopBilling(pubsubData, null); @@ -128,12 +128,12 @@ test(`should disable billing when budget is exceeded`, async t => { }); test(`should shut down GCE instances when budget is exceeded`, async t => { - const { program, mocks } = getSample(); + const {program, mocks} = getSample(); - const jsonData = { cost: 500, budget: 400 }; + const jsonData = {cost: 500, budget: 400}; const pubsubData = { data: Buffer.from(JSON.stringify(jsonData)).toString('base64'), - attributes: {} + attributes: {}, }; await program.limitUse(pubsubData, null); diff --git a/functions/composer-storage-trigger/index.js b/functions/composer-storage-trigger/index.js index 8dbd6068b8..9143b09ba6 100644 --- a/functions/composer-storage-trigger/index.js +++ b/functions/composer-storage-trigger/index.js @@ -31,7 +31,7 @@ const FormData = require('form-data'); * @param {!Object} event The Cloud Functions event. * @returns {Promise} */ -exports.triggerDag = function triggerDag (event) { +exports.triggerDag = function triggerDag(event) { // Fill in your Composer environment information here. // The project that holds your function @@ -47,24 +47,32 @@ exports.triggerDag = function triggerDag (event) { // Other constants const WEBSERVER_URL = `https://${WEBSERVER_ID}.appspot.com/api/experimental/dags/${DAG_NAME}/dag_runs`; const USER_AGENT = 'gcf-event-trigger'; - const BODY = {'conf': JSON.stringify(event.data)}; + const BODY = {conf: JSON.stringify(event.data)}; // Make the request - return authorizeIap(CLIENT_ID, PROJECT_ID, USER_AGENT) - .then(function iapAuthorizationCallback (iap) { - return makeIapPostRequest(WEBSERVER_URL, BODY, iap.idToken, USER_AGENT, iap.jwt); - }); + return authorizeIap(CLIENT_ID, PROJECT_ID, USER_AGENT).then( + function iapAuthorizationCallback(iap) { + return makeIapPostRequest( + WEBSERVER_URL, + BODY, + iap.idToken, + USER_AGENT, + iap.jwt + ); + } + ); }; /** - * @param {string} clientId The client id associated with the Composer webserver application. - * @param {string} projectId The id for the project containing the Cloud Function. - * @param {string} userAgent The user agent string which will be provided with the webserver request. - */ -function authorizeIap (clientId, projectId, userAgent) { + * @param {string} clientId The client id associated with the Composer webserver application. + * @param {string} projectId The id for the project containing the Cloud Function. + * @param {string} userAgent The user agent string which will be provided with the webserver request. + */ +function authorizeIap(clientId, projectId, userAgent) { const SERVICE_ACCOUNT = `${projectId}@appspot.gserviceaccount.com`; - const JWT_HEADER = Buffer.from(JSON.stringify({alg: 'RS256', typ: 'JWT'})) - .toString('base64'); + const JWT_HEADER = Buffer.from( + JSON.stringify({alg: 'RS256', typ: 'JWT'}) + ).toString('base64'); var jwt = ''; var jwtClaimset = ''; @@ -73,10 +81,11 @@ function authorizeIap (clientId, projectId, userAgent) { return fetch( `http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/${SERVICE_ACCOUNT}/token`, { - headers: {'User-Agent': userAgent, 'Metadata-Flavor': 'Google'} - }) + headers: {'User-Agent': userAgent, 'Metadata-Flavor': 'Google'}, + } + ) .then(res => res.json()) - .then(function obtainAccessTokenCallback (tokenResponse) { + .then(function obtainAccessTokenCallback(tokenResponse) { if (tokenResponse.error) { return Promise.reject(tokenResponse.error); } @@ -87,7 +96,7 @@ function authorizeIap (clientId, projectId, userAgent) { aud: 'https://www.googleapis.com/oauth2/v4/token', iat: iat, exp: iat + 60, - target_audience: clientId + target_audience: clientId, }; jwtClaimset = Buffer.from(JSON.stringify(claims)).toString('base64'); var toSign = [JWT_HEADER, jwtClaimset].join('.'); @@ -96,15 +105,18 @@ function authorizeIap (clientId, projectId, userAgent) { `https://iam.googleapis.com/v1/projects/${projectId}/serviceAccounts/${SERVICE_ACCOUNT}:signBlob`, { method: 'POST', - body: JSON.stringify({'bytesToSign': Buffer.from(toSign).toString('base64')}), + body: JSON.stringify({ + bytesToSign: Buffer.from(toSign).toString('base64'), + }), headers: { 'User-Agent': userAgent, - 'Authorization': `Bearer ${accessToken}` - } - }); + Authorization: `Bearer ${accessToken}`, + }, + } + ); }) .then(res => res.json()) - .then(function signJsonClaimCallback (body) { + .then(function signJsonClaimCallback(body) { if (body.error) { return Promise.reject(body.error); } @@ -114,40 +126,38 @@ function authorizeIap (clientId, projectId, userAgent) { var form = new FormData(); form.append('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer'); form.append('assertion', jwt); - return fetch( - 'https://www.googleapis.com/oauth2/v4/token', { - method: 'POST', - body: form - }); + return fetch('https://www.googleapis.com/oauth2/v4/token', { + method: 'POST', + body: form, + }); }) .then(res => res.json()) - .then(function returnJwt (body) { + .then(function returnJwt(body) { if (body.error) { return Promise.reject(body.error); } return { jwt: jwt, - idToken: body.id_token + idToken: body.id_token, }; }); } /** - * @param {string} url The url that the post request targets. - * @param {string} body The body of the post request. - * @param {string} idToken Bearer token used to authorize the iap request. - * @param {string} userAgent The user agent to identify the requester. - * @param {string} jwt A Json web token used to authenticate the request. - */ -function makeIapPostRequest (url, body, idToken, userAgent, jwt) { + * @param {string} url The url that the post request targets. + * @param {string} body The body of the post request. + * @param {string} idToken Bearer token used to authorize the iap request. + * @param {string} userAgent The user agent to identify the requester. + */ +function makeIapPostRequest(url, body, idToken, userAgent) { return fetch(url, { method: 'POST', headers: { 'User-Agent': userAgent, - 'Authorization': `Bearer ${idToken}` + Authorization: `Bearer ${idToken}`, }, - body: JSON.stringify(body) - }).then(function checkIapRequestStatus (res) { + body: JSON.stringify(body), + }).then(function checkIapRequestStatus(res) { if (!res.ok) { return res.text().then(body => Promise.reject(body)); } diff --git a/functions/composer-storage-trigger/package.json b/functions/composer-storage-trigger/package.json index 07accc4300..2c0fa7a398 100644 --- a/functions/composer-storage-trigger/package.json +++ b/functions/composer-storage-trigger/package.json @@ -6,7 +6,7 @@ "node-fetch": "^2.2.0" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "private": true, "license": "Apache-2.0", @@ -19,11 +19,9 @@ "@google-cloud/nodejs-repo-tools": "^2.2.5", "ava": "0.25.0", "proxyquire": "2.1.0", - "semistandard": "^12.0.1", "sinon": "4.4.2" }, "scripts": { - "lint": "semistandard '**/*.js'", "test": "ava -T 20s --verbose test/*.test.js" } } diff --git a/functions/composer-storage-trigger/test/index.test.js b/functions/composer-storage-trigger/test/index.test.js index 3046ed3994..f8af3dcae7 100644 --- a/functions/composer-storage-trigger/test/index.test.js +++ b/functions/composer-storage-trigger/test/index.test.js @@ -19,58 +19,70 @@ const proxyquire = require(`proxyquire`).noCallThru(); const sinon = require(`sinon`); const test = require(`ava`); -function getSample (FetchStub) { +function getSample(FetchStub) { return { program: proxyquire(`../`, { - 'node-fetch': FetchStub + 'node-fetch': FetchStub, }), mocks: { - fetch: FetchStub - } + fetch: FetchStub, + }, }; } -test.cb(`Handles error in JSON body`, (t) => { +test.cb(`Handles error in JSON body`, t => { const event = { data: { - file: `some-file` - } + file: `some-file`, + }, }; const expectedMsg = `Something bad happened.`; - const bodyJson = {'error': expectedMsg}; + const bodyJson = {error: expectedMsg}; const body = { - json: sinon.stub().resolves(bodyJson) + json: sinon.stub().resolves(bodyJson), }; const sample = getSample(sinon.stub().resolves(body)); - sample.program.triggerDag(event).catch(function (err) { + sample.program.triggerDag(event).catch(function(err) { t.regex(err, /Something bad happened/); t.end(); }); }); -test.cb(`Handles error in IAP response.`, (t) => { +test.cb(`Handles error in IAP response.`, t => { const event = { data: { - file: `some-file` - } + file: `some-file`, + }, }; const expectedMsg = 'Default IAP Error Message.'; const serviceAccountAccessTokenRes = { - json: sinon.stub().resolves({'access_token': 'default-access-token'}) + json: sinon.stub().resolves({access_token: 'default-access-token'}), }; - const signJsonClaimRes = {json: sinon.stub().resolves({'signature': 'default-jwt-signature'})}; - const getTokenRes = {json: sinon.stub().resolves({'id_token': 'default-id-token'})}; - const makeIapPostRequestRes = {ok: false, text: sinon.stub().resolves(expectedMsg)}; - const FetchStub = sinon.stub() - .onCall(0).resolves(serviceAccountAccessTokenRes) - .onCall(1).resolves(signJsonClaimRes) - .onCall(2).resolves(getTokenRes) - .onCall(3).resolves(makeIapPostRequestRes); + const signJsonClaimRes = { + json: sinon.stub().resolves({signature: 'default-jwt-signature'}), + }; + const getTokenRes = { + json: sinon.stub().resolves({id_token: 'default-id-token'}), + }; + const makeIapPostRequestRes = { + ok: false, + text: sinon.stub().resolves(expectedMsg), + }; + const FetchStub = sinon + .stub() + .onCall(0) + .resolves(serviceAccountAccessTokenRes) + .onCall(1) + .resolves(signJsonClaimRes) + .onCall(2) + .resolves(getTokenRes) + .onCall(3) + .resolves(makeIapPostRequestRes); const sample = getSample(FetchStub); - sample.program.triggerDag(event).catch(function (err) { + sample.program.triggerDag(event).catch(function(err) { t.is(err, expectedMsg); t.end(); }); diff --git a/functions/concepts/package.json b/functions/concepts/package.json index 20baac26b0..42df653629 100644 --- a/functions/concepts/package.json +++ b/functions/concepts/package.json @@ -9,10 +9,7 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" - }, - "scripts": { - "lint": "semistandard '**/*.js'" + "node": ">=8" }, "dependencies": { "request": "^2.85.0" diff --git a/functions/concepts/test/index.test.js b/functions/concepts/test/index.test.js index f0ffaf4129..fd6a2fb249 100644 --- a/functions/concepts/test/index.test.js +++ b/functions/concepts/test/index.test.js @@ -24,14 +24,12 @@ const sample = require(`../`); test.beforeEach(tools.stubConsole); test.afterEach.always(tools.restoreConsole); -test(`should demonstrate error type behavior`, (t) => { +test(`should demonstrate error type behavior`, t => { const objError = new Error('Error object!'); const strError = new Error('Error string!'); - const req = { body: - { throwAsString: true } - }; - const res = { end: sinon.stub() }; + const req = {body: {throwAsString: true}}; + const res = {end: sinon.stub()}; // Test throwing both objects and strings sample.errorTypes(req, res); diff --git a/functions/datastore/index.js b/functions/datastore/index.js index 33561ae080..6516974576 100644 --- a/functions/datastore/index.js +++ b/functions/datastore/index.js @@ -28,13 +28,17 @@ const datastore = Datastore(); * @param {string} requestData.kind Datastore kind. * @returns {object} Datastore key object. */ -function getKeyFromRequestData (requestData) { +function getKeyFromRequestData(requestData) { if (!requestData.key) { - throw new Error('Key not provided. Make sure you have a "key" property in your request'); + throw new Error( + 'Key not provided. Make sure you have a "key" property in your request' + ); } if (!requestData.kind) { - throw new Error('Kind not provided. Make sure you have a "kind" property in your request'); + throw new Error( + 'Kind not provided. Make sure you have a "kind" property in your request' + ); } return datastore.key([requestData.kind, requestData.key]); @@ -56,18 +60,21 @@ function getKeyFromRequestData (requestData) { exports.set = (req, res) => { // The value contains a JSON document representing the entity we want to save if (!req.body.value) { - throw new Error('Value not provided. Make sure you have a "value" property in your request'); + throw new Error( + 'Value not provided. Make sure you have a "value" property in your request' + ); } const key = getKeyFromRequestData(req.body); const entity = { key: key, - data: req.body.value + data: req.body.value, }; - return datastore.save(entity) + return datastore + .save(entity) .then(() => res.status(200).send(`Entity ${key.path.join('/')} saved.`)) - .catch((err) => { + .catch(err => { console.error(err); res.status(500).send(err.message); return Promise.reject(err); @@ -89,7 +96,8 @@ exports.set = (req, res) => { exports.get = (req, res) => { const key = getKeyFromRequestData(req.body); - return datastore.get(key) + return datastore + .get(key) .then(([entity]) => { // The get operation will not fail for a non-existent entity, it just // returns an empty dictionary. @@ -99,7 +107,7 @@ exports.get = (req, res) => { res.status(200).send(entity); }) - .catch((err) => { + .catch(err => { console.error(err); res.status(500).send(err.message); return Promise.reject(err); @@ -124,9 +132,10 @@ exports.del = (req, res) => { // Deletes the entity // The delete operation will not fail for a non-existent entity, it just // doesn't delete anything - return datastore.delete(key) + return datastore + .delete(key) .then(() => res.status(200).send(`Entity ${key.path.join('/')} deleted.`)) - .catch((err) => { + .catch(err => { console.error(err); res.status(500).send(err); return Promise.reject(err.message); diff --git a/functions/datastore/package.json b/functions/datastore/package.json index 7ef57607e2..c3d2ab0bc4 100644 --- a/functions/datastore/package.json +++ b/functions/datastore/package.json @@ -9,11 +9,9 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "e2e-test": "export FUNCTIONS_CMD='gcloud functions' && sh test/updateFunctions.sh && BASE_URL=\"https://$GCF_REGION-$GCLOUD_PROJECT.cloudfunctions.net/\" ava -T 20s --verbose test/*.test.js", "system-test": "export FUNCTIONS_CMD='functions' && sh test/updateFunctions.sh && BASE_URL=\"http://localhost:8010/$GCLOUD_PROJECT/$GCF_REGION\" ava -T 20s --verbose test/*.test.js", "test": "npm run system-test" @@ -27,8 +25,8 @@ "@google-cloud/nodejs-repo-tools": "^3.0.0", "ava": "0.25.0", "proxyquire": "2.1.0", - "semistandard": "^12.0.1", - "sinon": "4.4.2" + "sinon": "4.4.2", + "uuid": "^3.3.2" }, "cloud-repo-tools": { "requiresKeyFile": true, diff --git a/functions/datastore/test/.eslintrc.yml b/functions/datastore/test/.eslintrc.yml new file mode 100644 index 0000000000..07583b99db --- /dev/null +++ b/functions/datastore/test/.eslintrc.yml @@ -0,0 +1,4 @@ +--- +rules: + no-warning-comments: off + diff --git a/functions/datastore/test/index.test.js b/functions/datastore/test/index.test.js index 48135a4253..7f14984c50 100644 --- a/functions/datastore/test/index.test.js +++ b/functions/datastore/test/index.test.js @@ -27,89 +27,105 @@ const request = supertest(process.env.BASE_URL); const NAME = `sampletask1`; const KIND = `Task-${uuid.v4()}`; const VALUE = { - description: `Buy milk` + description: `Buy milk`, }; -const errorMsg = msg => `${msg} not provided. Make sure you have a "${msg.toLowerCase()}" property in your request`; +const errorMsg = msg => + `${msg} not provided. Make sure you have a "${msg.toLowerCase()}" property in your request`; -test.serial(`set: Fails without a value`, (t) => { +test.serial(`set: Fails without a value`, t => { const req = { - body: {} + body: {}, }; t.throws(() => { program.set(req, null); }, errorMsg(`Value`)); }); -test.serial(`set: Fails without a key`, (t) => { +test.serial(`set: Fails without a key`, t => { const req = { body: { - value: VALUE - } + value: VALUE, + }, }; t.throws(() => { program.set(req, null); }, errorMsg(`Key`)); }); -test.serial(`set: Fails without a kind`, (t) => { +test.serial(`set: Fails without a kind`, t => { const req = { body: { key: NAME, - value: VALUE - } + value: VALUE, + }, }; - t.throws(() => { - program.set(req, null); - }, Error, errorMsg(`Kind`)); + t.throws( + () => { + program.set(req, null); + }, + Error, + errorMsg(`Kind`) + ); }); // TODO: @ace-n figure out why these tests started failing -test.skip.serial.cb(`set: Saves an entity`, (t) => { +test.skip.serial.cb(`set: Saves an entity`, t => { request .post(`/set`) .send({ kind: KIND, key: NAME, - value: VALUE + value: VALUE, }) .expect(200) - .expect((response) => { + .expect(response => { t.true(response.text.includes(`Entity ${KIND}/${NAME} saved`)); }) .end(t.end); }); -test.serial(`get: Fails without a key`, (t) => { +test.serial(`get: Fails without a key`, t => { const req = { - body: {} + body: {}, }; - t.throws(() => { - program.get(req, null); - }, Error, errorMsg(`Key`)); + t.throws( + () => { + program.get(req, null); + }, + Error, + errorMsg(`Key`) + ); }); -test.serial(`get: Fails without a kind`, (t) => { +test.serial(`get: Fails without a kind`, t => { const req = { body: { - key: NAME - } + key: NAME, + }, }; - t.throws(() => { - program.get(req, null); - }, Error, errorMsg(`Kind`)); + t.throws( + () => { + program.get(req, null); + }, + Error, + errorMsg(`Kind`) + ); }); -test.serial.cb(`get: Fails when entity does not exist`, (t) => { +test.serial.cb(`get: Fails when entity does not exist`, t => { request .post(`/get`) .send({ kind: KIND, - key: 'nonexistent' + key: 'nonexistent', }) .expect(500) - .expect((response) => { - t.regex(response.text, /(Missing or insufficient permissions.)|(No entity found for key)/); + .expect(response => { + t.regex( + response.text, + /(Missing or insufficient permissions.)|(No entity found for key)/ + ); }) .end(() => { setTimeout(t.end, 50); // Subsequent test is flaky without this timeout @@ -117,69 +133,74 @@ test.serial.cb(`get: Fails when entity does not exist`, (t) => { }); // TODO: ace-n Figure out why this test started failing, remove skip -test.skip.serial.cb(`get: Finds an entity`, (t) => { +test.skip.serial.cb(`get: Finds an entity`, t => { request .post(`/get`) .send({ kind: KIND, - key: NAME + key: NAME, }) .expect(200) - .expect((response) => { - t.deepEqual( - JSON.parse(response.text), - { description: 'Buy milk' } - ); + .expect(response => { + t.deepEqual(JSON.parse(response.text), {description: 'Buy milk'}); }) .end(t.end); }); -test.serial(`del: Fails without a key`, (t) => { +test.serial(`del: Fails without a key`, t => { const req = { - body: {} + body: {}, }; - t.throws(() => { - program.del(req, null); - }, Error, errorMsg(`Kind`)); + t.throws( + () => { + program.del(req, null); + }, + Error, + errorMsg(`Kind`) + ); }); -test.serial(`del: Fails without a kind`, (t) => { +test.serial(`del: Fails without a kind`, t => { const req = { body: { - key: NAME - } + key: NAME, + }, }; - t.throws(() => { - program.del(req, null); - }, Error, errorMsg(`Kind`)); + t.throws( + () => { + program.del(req, null); + }, + Error, + errorMsg(`Kind`) + ); }); // TODO: ace-n Figure out why this test started failing -test.skip.serial.cb(`del: Doesn't fail when entity does not exist`, (t) => { +test.skip.serial.cb(`del: Doesn't fail when entity does not exist`, t => { request .post(`/del`) .send({ kind: KIND, - key: 'nonexistent' + key: 'nonexistent', }) .expect(200) - .expect((response) => { + .expect(response => { t.is(response.text, `Entity ${KIND}/nonexistent deleted.`); }) .end(t.end); }); // TODO: ace-n Figure out why this test started failing -test.skip.serial(`del: Deletes an entity`, async (t) => { +test.skip.serial(`del: Deletes an entity`, async t => { await new Promise(resolve => { request .post(`/del`) .send({ kind: KIND, - key: NAME + key: NAME, }) .expect(200) - .expect((response) => { + .expect(response => { t.is(response.text, `Entity ${KIND}/${NAME} deleted.`); }) .end(resolve); diff --git a/functions/env_vars/package.json b/functions/env_vars/package.json index 8a94623b93..9e93df7fc1 100644 --- a/functions/env_vars/package.json +++ b/functions/env_vars/package.json @@ -9,18 +9,15 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "test": "ava -T 20s --verbose test/*.test.js" }, "dependencies": {}, "devDependencies": { "@google-cloud/nodejs-repo-tools": "^3.0.0", "ava": "0.25.0", - "semistandard": "^12.0.1", "sinon": "4.4.2" }, "cloud-repo-tools": { diff --git a/functions/env_vars/test/index.test.js b/functions/env_vars/test/index.test.js index 6953dc02cd..530b564978 100644 --- a/functions/env_vars/test/index.test.js +++ b/functions/env_vars/test/index.test.js @@ -19,19 +19,19 @@ const sinon = require(`sinon`); const test = require(`ava`); const functions = require(`../`); -function getMocks () { +function getMocks() { const req = {}; const res = { - send: sinon.stub().returnsThis() + send: sinon.stub().returnsThis(), }; return { req: req, - res: res + res: res, }; } -test.serial(`should read env vars`, (t) => { +test.serial(`should read env vars`, t => { const mocks = getMocks(); process.env['FOO'] = 'bar'; diff --git a/functions/errorreporting/.eslintrc.yml b/functions/errorreporting/.eslintrc.yml new file mode 100644 index 0000000000..8a2e3adc8d --- /dev/null +++ b/functions/errorreporting/.eslintrc.yml @@ -0,0 +1,3 @@ +--- +rules: + no-empty: off \ No newline at end of file diff --git a/functions/errorreporting/index.js b/functions/errorreporting/index.js index 5311d04b4d..5deb9dede1 100644 --- a/functions/errorreporting/index.js +++ b/functions/errorreporting/index.js @@ -32,7 +32,7 @@ const reportDetailedError = require('./report'); * @param {Error} err The Error object to report. * @param {Function} callback Callback function. */ -function reportError (err, callback) { +function reportError(err, callback) { // This is the name of the StackDriver log stream that will receive the log // entry. This name can be any valid log stream name, but must contain "err" // in order for the error to be picked up by StackDriver Error Reporting. @@ -44,9 +44,9 @@ function reportError (err, callback) { resource: { type: 'cloud_function', labels: { - function_name: process.env.FUNCTION_NAME - } - } + function_name: process.env.FUNCTION_NAME, + }, + }, }; // https://cloud.google.com/error-reporting/reference/rest/v1beta1/ErrorEvent @@ -54,8 +54,8 @@ function reportError (err, callback) { message: err.stack, serviceContext: { service: `cloud_function:${process.env.FUNCTION_NAME}`, - version: require('./package.json').version || 'unknown' - } + version: require('./package.json').version || 'unknown', + }, }; // Write the error log entry diff --git a/functions/errorreporting/report.js b/functions/errorreporting/report.js index 6bfbe6f154..866f9abe90 100644 --- a/functions/errorreporting/report.js +++ b/functions/errorreporting/report.js @@ -31,7 +31,7 @@ const logging = Logging(); * @param {object} [options] Additional context, if any. * @param {function} callback Callback function. */ -function reportDetailedError (err, req, res, options, callback) { +function reportDetailedError(err, req, res, options, callback) { if (typeof req === 'function') { callback = req; req = null; @@ -54,9 +54,9 @@ function reportDetailedError (err, req, res, options, callback) { type: 'cloud_function', // MonitoredResource.labels labels: { - function_name: FUNCTION_NAME - } - } + function_name: FUNCTION_NAME, + }, + }, }; if (typeof options.region === 'string') { @@ -76,9 +76,10 @@ function reportDetailedError (err, req, res, options, callback) { context.httpRequest = { method: req.method, url: req.originalUrl, - userAgent: typeof req.get === 'function' ? req.get('user-agent') : 'unknown', + userAgent: + typeof req.get === 'function' ? req.get('user-agent') : 'unknown', referrer: '', - remoteIp: req.ip + remoteIp: req.ip, }; if (typeof res.statusCode === 'number') { context.httpRequest.responseStatusCode = res.statusCode; @@ -87,9 +88,14 @@ function reportDetailedError (err, req, res, options, callback) { if (!(err instanceof Error) || typeof err.stack !== 'string') { // ErrorEvent.context.reportLocation context.reportLocation = { - filePath: typeof options.filePath === 'string' ? options.filePath : 'unknown', - lineNumber: typeof options.lineNumber === 'number' ? options.lineNumber : 0, - functionName: typeof options.functionName === 'string' ? options.functionName : 'unknown' + filePath: + typeof options.filePath === 'string' ? options.filePath : 'unknown', + lineNumber: + typeof options.lineNumber === 'number' ? options.lineNumber : 0, + functionName: + typeof options.functionName === 'string' + ? options.functionName + : 'unknown', }; } @@ -111,10 +117,10 @@ function reportDetailedError (err, req, res, options, callback) { // ErrorEvent.serviceContext.service service: `cloud_function:${FUNCTION_NAME}`, // ErrorEvent.serviceContext.version - version: `${options.version}` + version: `${options.version}`, }, // ErrorEvent.context - context: context + context: context, }; // ErrorEvent.message diff --git a/functions/firebase/index.js b/functions/firebase/index.js index 4c21d8c0bb..f9e779d6c7 100644 --- a/functions/firebase/index.js +++ b/functions/firebase/index.js @@ -19,7 +19,7 @@ * * @param {!Object} event The Cloud Functions event. */ -exports.helloRTDB = (event) => { +exports.helloRTDB = event => { const triggerResource = event.resource; console.log(`Function triggered by change to: ${triggerResource}`); @@ -35,7 +35,7 @@ exports.helloRTDB = (event) => { * * @param {!Object} event The Cloud Functions event. */ -exports.helloFirestore = (event) => { +exports.helloFirestore = event => { const triggerResource = event.resource; console.log(`Function triggered by event on: ${triggerResource}`); @@ -59,7 +59,7 @@ exports.helloFirestore = (event) => { * * @param {!Object} event The Cloud Functions event. */ -exports.helloAuth = (event) => { +exports.helloAuth = event => { try { const data = event.data; console.log(`Function triggered by change to user: ${data.uid}`); @@ -78,11 +78,11 @@ exports.helloAuth = (event) => { const Firestore = require('@google-cloud/firestore'); const firestore = new Firestore({ - projectId: process.env.GCP_PROJECT + projectId: process.env.GCP_PROJECT, }); // Converts strings added to /messages/{pushId}/original to uppercase -exports.makeUpperCase = (event) => { +exports.makeUpperCase = event => { const resource = event.resource; const affectedDoc = firestore.doc(resource.split('/documents/')[1]); @@ -91,7 +91,7 @@ exports.makeUpperCase = (event) => { console.log(`Replacing value: ${curValue} --> ${newValue}`); return affectedDoc.set({ - 'original': newValue + original: newValue, }); }; // [END functions_firebase_reactive] @@ -102,7 +102,7 @@ exports.makeUpperCase = (event) => { * * @param {!Object} event The Cloud Functions event. */ -exports.helloAnalytics = (event) => { +exports.helloAnalytics = event => { const resource = event.resource; console.log(`Function triggered by the following event: ${resource}`); @@ -122,7 +122,7 @@ exports.helloAnalytics = (event) => { * * @param {object} data The Cloud Functions event data. */ -exports.helloRemoteConfig = (event) => { +exports.helloRemoteConfig = event => { const data = event.data; console.log(`Update type: ${data.updateType}`); diff --git a/functions/firebase/package.json b/functions/firebase/package.json index 0bb349f02c..712ff4356e 100644 --- a/functions/firebase/package.json +++ b/functions/firebase/package.json @@ -9,17 +9,15 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "scripts": { - "pretest": "semistandard '**/*.js'", "test": "ava -T 30s test/*.test.js" }, "devDependencies": { "@google-cloud/nodejs-repo-tools": "^2.2.5", "ava": "0.25.0", "proxyquire": "2.1.0", - "semistandard": "^12.0.1", "sinon": "4.4.8", "supertest": "^3.0.0", "uuid": "^3.1.0" diff --git a/functions/firebase/test/index.test.js b/functions/firebase/test/index.test.js index e47ec0704f..6a4b199524 100644 --- a/functions/firebase/test/index.test.js +++ b/functions/firebase/test/index.test.js @@ -20,19 +20,19 @@ const sinon = require(`sinon`); const test = require(`ava`); const tools = require(`@google-cloud/nodejs-repo-tools`); -function getSample () { +function getSample() { const firestoreMock = { doc: sinon.stub().returnsThis(), - set: sinon.stub() + set: sinon.stub(), }; return { program: proxyquire(`../`, { - '@google-cloud/firestore': sinon.stub().returns(firestoreMock) + '@google-cloud/firestore': sinon.stub().returns(firestoreMock), }), mocks: { - firestore: firestoreMock - } + firestore: firestoreMock, + }, }; } @@ -43,14 +43,14 @@ test(`should listen to RTDB`, t => { const sample = getSample(); const delta = { - foo: 'bar' + foo: 'bar', }; const event = { resource: 'resource', auth: { - admin: true + admin: true, }, - delta: delta + delta: delta, }; sample.program.helloRTDB(event); @@ -64,18 +64,18 @@ test(`should listen to Firestore`, t => { const sample = getSample(); const oldValue = { - foo: 'bar' + foo: 'bar', }; const value = { - bar: 'baz' + bar: 'baz', }; const event = { resource: 'resource', eventType: 'type', data: { oldValue: oldValue, - value: value - } + value: value, + }, }; sample.program.helloFirestore(event); @@ -95,9 +95,9 @@ test(`should listen to Auth events`, t => { uid: 'me', email: 'me@example.com', metadata: { - createdAt: date - } - } + createdAt: date, + }, + }, }; sample.program.helloAuth(event); @@ -111,26 +111,31 @@ test.serial('should listen to Analytics events', t => { const date = new Date(); const event = { data: { - eventDim: [{ - name: 'my-event', - timestampMicros: `${date.valueOf()}000` - }], + eventDim: [ + { + name: 'my-event', + timestampMicros: `${date.valueOf()}000`, + }, + ], userDim: { deviceInfo: { - deviceModel: 'Pixel' + deviceModel: 'Pixel', }, geoInfo: { city: 'London', - country: 'UK' - } - } + country: 'UK', + }, + }, }, - resource: 'my-resource' + resource: 'my-resource', }; const sample = getSample(); sample.program.helloAnalytics(event); - t.is(console.log.args[0][0], `Function triggered by the following event: my-resource`); + t.is( + console.log.args[0][0], + `Function triggered by the following event: my-resource` + ); t.is(console.log.args[1][0], `Name: my-event`); t.is(console.log.args[2][0], `Timestamp: ${date}`); t.is(console.log.args[3][0], `Device Model: Pixel`); @@ -144,8 +149,8 @@ test(`should listen to Remote Config events`, t => { data: { updateOrigin: 'CONSOLE', updateType: 'INCREMENTAL_UPDATE', - versionNumber: '1' - } + versionNumber: '1', + }, }; sample.program.helloRemoteConfig(event); diff --git a/functions/gcs/index.js b/functions/gcs/index.js index e2424591f8..4c855d6563 100644 --- a/functions/gcs/index.js +++ b/functions/gcs/index.js @@ -23,15 +23,22 @@ const readline = require('readline'); const storage = Storage(); // [END functions_word_count_setup] -function getFileStream (file) { +function getFileStream(file) { if (!file.bucket) { - throw new Error('Bucket not provided. Make sure you have a "bucket" property in your request'); + throw new Error( + 'Bucket not provided. Make sure you have a "bucket" property in your request' + ); } if (!file.name) { - throw new Error('Filename not provided. Make sure you have a "name" property in your request'); + throw new Error( + 'Filename not provided. Make sure you have a "name" property in your request' + ); } - return storage.bucket(file.bucket).file(file.name).createReadStream(); + return storage + .bucket(file.bucket) + .file(file.name) + .createReadStream(); } // [START functions_word_count_read] @@ -58,12 +65,13 @@ exports.wordCount = (event, callback) => { let count = 0; const options = { - input: getFileStream(file) + input: getFileStream(file), }; // Use the readline module to read the stream line by line. - readline.createInterface(options) - .on('line', (line) => { + readline + .createInterface(options) + .on('line', line => { count += line.trim().split(/\s+/).length; }) .on('close', () => { diff --git a/functions/gcs/package.json b/functions/gcs/package.json index f3fb8adc05..7827205e79 100644 --- a/functions/gcs/package.json +++ b/functions/gcs/package.json @@ -9,11 +9,9 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "test": "ava -T 20s --verbose test/*.test.js" }, "dependencies": { @@ -24,7 +22,6 @@ "@google-cloud/nodejs-repo-tools": "^3.0.0", "ava": "0.25.0", "proxyquire": "2.1.0", - "semistandard": "^12.0.1", "sinon": "4.4.2" }, "cloud-repo-tools": { diff --git a/functions/gcs/test/index.test.js b/functions/gcs/test/index.test.js index 16ee43d934..10f3ad6631 100644 --- a/functions/gcs/test/index.test.js +++ b/functions/gcs/test/index.test.js @@ -23,57 +23,57 @@ const test = require(`ava`); const filename = `sample.txt`; -function getSample () { +function getSample() { const filePath = path.join(__dirname, `../${filename}`); const file = { - createReadStream: () => fs.createReadStream(filePath, { encoding: `utf8` }) + createReadStream: () => fs.createReadStream(filePath, {encoding: `utf8`}), }; const bucket = { - file: sinon.stub().returns(file) + file: sinon.stub().returns(file), }; const storage = { - bucket: sinon.stub().returns(bucket) + bucket: sinon.stub().returns(bucket), }; const StorageMock = sinon.stub().returns(storage); return { program: proxyquire(`../`, { - '@google-cloud/storage': StorageMock + '@google-cloud/storage': StorageMock, }), mocks: { Storage: StorageMock, storage: storage, bucket: bucket, - file: file - } + file: file, + }, }; } -test.serial(`Fails without a bucket`, (t) => { +test.serial(`Fails without a bucket`, t => { const expectedMsg = `Bucket not provided. Make sure you have a "bucket" property in your request`; t.throws( - () => getSample().program.wordCount({ data: { name: `file` } }), + () => getSample().program.wordCount({data: {name: `file`}}), Error, expectedMsg ); }); -test.serial(`Fails without a file`, (t) => { +test.serial(`Fails without a file`, t => { const expectedMsg = `Filename not provided. Make sure you have a "file" property in your request`; t.throws( - () => getSample().program.wordCount({ data: { bucket: `bucket` } }), + () => getSample().program.wordCount({data: {bucket: `bucket`}}), Error, expectedMsg ); }); -test.cb.serial(`Does nothing for deleted files`, (t) => { +test.cb.serial(`Does nothing for deleted files`, t => { const event = { data: { - resourceState: `not_exists` - } + resourceState: `not_exists`, + }, }; const sample = getSample(); @@ -86,13 +86,13 @@ test.cb.serial(`Does nothing for deleted files`, (t) => { }); }); -test.cb.serial(`Reads the file line by line`, (t) => { +test.cb.serial(`Reads the file line by line`, t => { const expectedMsg = `File ${filename} has 114 words`; const event = { data: { bucket: `bucket`, - name: `sample.txt` - } + name: `sample.txt`, + }, }; const sample = getSample(); @@ -100,7 +100,9 @@ test.cb.serial(`Reads the file line by line`, (t) => { t.ifError(err); t.deepEqual(message, expectedMsg); t.deepEqual(sample.mocks.storage.bucket.calledOnce, true); - t.deepEqual(sample.mocks.storage.bucket.firstCall.args, [event.data.bucket]); + t.deepEqual(sample.mocks.storage.bucket.firstCall.args, [ + event.data.bucket, + ]); t.deepEqual(sample.mocks.bucket.file.calledOnce, true); t.deepEqual(sample.mocks.bucket.file.firstCall.args, [event.data.name]); t.end(); diff --git a/functions/headless-chrome/index.js b/functions/headless-chrome/index.js index c78494fda9..1010258ec8 100644 --- a/functions/headless-chrome/index.js +++ b/functions/headless-chrome/index.js @@ -20,7 +20,7 @@ const puppeteer = require('puppeteer'); let page; -async function getBrowserPage () { +async function getBrowserPage() { // [START start_browser] const browser = await puppeteer.launch({args: ['--no-sandbox']}); // [END start_browser] @@ -31,7 +31,9 @@ exports.screenshot = async (req, res) => { const url = req.query.url; if (!url) { - return res.send('Please provide URL as GET parameter, for example: ?url=https://example.com'); + return res.send( + 'Please provide URL as GET parameter, for example: ?url=https://example.com' + ); } if (!page) { diff --git a/functions/headless-chrome/package.json b/functions/headless-chrome/package.json index e72d240c7c..3476378b93 100644 --- a/functions/headless-chrome/package.json +++ b/functions/headless-chrome/package.json @@ -12,8 +12,6 @@ "node": ">=8" }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "e2e-test": "export FUNCTIONS_CMD='gcloud beta functions' && sh test/updateFunctions.sh && BASE_URL=\"https://$GCF_REGION-$GCLOUD_PROJECT.cloudfunctions.net/\" ava -T 20s --verbose test/*.test.js" }, "dependencies": { diff --git a/functions/headless-chrome/test/index.test.js b/functions/headless-chrome/test/index.test.js index 1e24c38dd3..b276385453 100644 --- a/functions/headless-chrome/test/index.test.js +++ b/functions/headless-chrome/test/index.test.js @@ -25,7 +25,7 @@ test.before(`Must specify BASE_URL`, t => { test.before(tools.checkCredentials); -test.cb(`screenshot: should return a screenshot`, (t) => { +test.cb(`screenshot: should return a screenshot`, t => { supertest(BASE_URL) .get(`/screenshot?url=https://example.com`) .send() diff --git a/functions/helloworld/.eslintrc.yml b/functions/helloworld/.eslintrc.yml new file mode 100644 index 0000000000..913c1b13f9 --- /dev/null +++ b/functions/helloworld/.eslintrc.yml @@ -0,0 +1,5 @@ +--- +rules: + no-warning-comments: off + no-unused-vars: off + diff --git a/functions/helloworld/index.js b/functions/helloworld/index.js index 47efcd94d2..340dc8eb20 100644 --- a/functions/helloworld/index.js +++ b/functions/helloworld/index.js @@ -76,7 +76,9 @@ exports.helloBackground = (event, callback) => { */ exports.helloPubSub = (event, callback) => { const pubsubMessage = event.data; - const name = pubsubMessage.data ? Buffer.from(pubsubMessage.data, 'base64').toString() : 'World'; + const name = pubsubMessage.data + ? Buffer.from(pubsubMessage.data, 'base64').toString() + : 'World'; console.log(`Hello, ${name}!`); diff --git a/functions/helloworld/package.json b/functions/helloworld/package.json index 7c31835a02..2b4737e1b5 100644 --- a/functions/helloworld/package.json +++ b/functions/helloworld/package.json @@ -9,11 +9,9 @@ "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, "engines": { - "node": ">=4.3.2" + "node": ">=8" }, "scripts": { - "lint": "semistandard '**/*.js'", - "pretest": "npm run lint", "e2e-test": "export FUNCTIONS_CMD='gcloud functions' && sh test/updateFunctions.sh && BASE_URL=\"https://$GCP_REGION-$GCLOUD_PROJECT.cloudfunctions.net/\" ava -T 20s --verbose test/*.test.js", "test": "export FUNCTIONS_CMD='functions-emulator' && sh test/updateFunctions.sh && export BASE_URL=\"http://localhost:8010/$GCLOUD_PROJECT/$GCF_REGION\" && ava -T 20s --verbose -c 1 test/index.test.js", "system-test": "export FUNCTIONS_CMD='functions-emulator' && sh test/updateFunctions.sh && export BASE_URL=\"http://localhost:8010/$GCLOUD_PROJECT/$GCF_REGION\" && ava -T 20s --verbose test/*.test.js" @@ -31,7 +29,6 @@ "ava": "0.25.0", "express": "^4.16.3", "proxyquire": "2.1.0", - "semistandard": "^12.0.1", "sinon": "4.4.8", "supertest": "^3.0.0", "uuid": "^3.1.0", diff --git a/functions/helloworld/shim.js b/functions/helloworld/shim.js index 7c06d798bd..0b3862de3d 100644 --- a/functions/helloworld/shim.js +++ b/functions/helloworld/shim.js @@ -13,7 +13,7 @@ * limitations under the License. */ -const httpShim = (PORT) => { +const httpShim = PORT => { // [START functions_testing_shim_http] // Import dependencies const gcfCode = require('./index.js'); @@ -60,8 +60,8 @@ const pubsubShim = (gcfFn, topicName, subscriptionName) => { const subscription = pubsub.topic(topicName).subscription(subscriptionName); // Handle a single Pub/Sub message - const messageHandler = (msg) => { - gcfFn({ data: msg }, () => { + const messageHandler = msg => { + gcfFn({data: msg}, () => { msg.ack(); subscription.removeListener(`message`, messageHandler); }); @@ -92,25 +92,29 @@ const storageShim = (gcfFn, bucketName, topicName, subscriptionName) => { // Create notification on target bucket // Further info: https://cloud.google.com/storage/docs/reporting-changes const bucket = storage.bucket(bucketName); - return bucket.createNotification(topicName) + return bucket + .createNotification(topicName) .then(data => data[0]) - .then((notification) => new Promise(resolve => { - // Subscribe to Pub/Sub topic - const subscription = pubsub - .topic(topicName) - .subscription(subscriptionName); - - // Handle a single Pub/Sub message - const messageHandler = (msg) => { - const data = JSON.parse(Buffer.from(msg.data, 'base64').toString()); - gcfFn({ data: data }, () => { - msg.ack(); - subscription.removeListener(`message`, messageHandler); - resolve(notification); - }); - }; - subscription.on(`message`, messageHandler); - })) + .then( + notification => + new Promise(resolve => { + // Subscribe to Pub/Sub topic + const subscription = pubsub + .topic(topicName) + .subscription(subscriptionName); + + // Handle a single Pub/Sub message + const messageHandler = msg => { + const data = JSON.parse(Buffer.from(msg.data, 'base64').toString()); + gcfFn({data: data}, () => { + msg.ack(); + subscription.removeListener(`message`, messageHandler); + resolve(notification); + }); + }; + subscription.on(`message`, messageHandler); + }) + ) .then(notification => notification.delete()); // Delete notification // [END functions_testing_shim_storage] }; @@ -118,34 +122,32 @@ const storageShim = (gcfFn, bucketName, topicName, subscriptionName) => { const gcfCodeGlobal = require('./index.js'); require(`yargs`) // eslint-disable-line .demandCommand(1) - .command( - 'http ', - 'HTTP-triggered-function shim', - {}, - opts => httpShim(opts.port) + .command('http ', 'HTTP-triggered-function shim', {}, opts => + httpShim(opts.port) ) .command( 'pubsub ', 'PubSub-triggered-function shim', {}, - opts => pubsubShim( - gcfCodeGlobal[opts.functionName], - opts.topic, - opts.subscription - ) + opts => + pubsubShim( + gcfCodeGlobal[opts.functionName], + opts.topic, + opts.subscription + ) ) .command( 'storage ', 'Storage-triggered-function shim', {}, - opts => storageShim( - gcfCodeGlobal[opts.functionName], - opts.bucket, - opts.topic, - opts.subscription - ) + opts => + storageShim( + gcfCodeGlobal[opts.functionName], + opts.bucket, + opts.topic, + opts.subscription + ) ) .wrap(120) .help() - .strict() - .argv; + .strict().argv; diff --git a/functions/helloworld/test/index.test.js b/functions/helloworld/test/index.test.js index 29a253795d..6e1bb4fda4 100644 --- a/functions/helloworld/test/index.test.js +++ b/functions/helloworld/test/index.test.js @@ -41,72 +41,76 @@ test.before(`Must specify BASE_URL`, t => { test.before(tools.checkCredentials); -test.cb(`helloGET: should print hello world`, (t) => { +test.cb(`helloGET: should print hello world`, t => { supertest(BASE_URL) .get(`/helloGET`) .expect(200) - .expect((response) => { + .expect(response => { t.is(response.text, `Hello World!`); }) .end(t.end); }); -test.cb(`helloHttp: should print a name via GET`, (t) => { +test.cb(`helloHttp: should print a name via GET`, t => { supertest(BASE_URL) .get(`/helloHttp?name=John`) .expect(200) - .expect((response) => { + .expect(response => { t.is(response.text, 'Hello John!'); }) .end(t.end); }); -test.cb(`helloHttp: should print a name via POST`, (t) => { +test.cb(`helloHttp: should print a name via POST`, t => { supertest(BASE_URL) .post(`/helloHttp`) - .send({ name: 'John' }) + .send({name: 'John'}) .expect(200) - .expect((response) => { + .expect(response => { t.is(response.text, 'Hello John!'); }) .end(t.end); }); -test.cb(`helloHttp: should print hello world`, (t) => { +test.cb(`helloHttp: should print hello world`, t => { supertest(BASE_URL) .get(`/helloHttp`) .expect(200) - .expect((response) => { + .expect(response => { t.is(response.text, `Hello World!`); }) .end(t.end); }); -test.cb.serial(`helloHttp: should escape XSS`, (t) => { +test.cb.serial(`helloHttp: should escape XSS`, t => { supertest(BASE_URL) .post(`/helloHttp`) - .send({ name: '' }) + .send({name: ''}) .expect(200) - .expect((response) => { + .expect(response => { t.false(response.text.includes('` }; + mocks.req.body = {name: ``}; httpSample.sample.helloContent(mocks.req, mocks.res); t.true(mocks.res.status.calledOnce); @@ -180,7 +185,7 @@ test.serial(`http:helloContent: should escape XSS`, (t) => { t.false(mocks.res.send.firstCall.args[0].includes('