From 84b28d16fca04a05293476fede5632c7fde8978d Mon Sep 17 00:00:00 2001 From: Jason Dobry Date: Mon, 28 Mar 2016 16:14:37 -0700 Subject: [PATCH] Refactor for completely parallel tests. --- .gitignore | 3 +- .travis.yml | 19 +- README.md | 15 +- datastore/concepts.js | 3 +- datastore/error.js | 2 +- logging/export.js | 95 ++++-- logging/list.js | 37 +- logging/write.js | 74 ++-- package.json | 20 +- prediction/README.md | 2 +- prediction/hostedmodels.js | 40 ++- prediction/package.json | 2 +- pubsub/iam.js | 191 ++++++----- pubsub/subscription.js | 334 ++++++++++++------- storage/README.md | 2 +- storage/authSample.js | 36 +- storage/package.json | 2 +- test/.jshintrc | 4 - test/appengine/all.test.js | 172 +++++----- test/computeengine/sendgrid.test.js | 38 +-- test/datastore/concepts.test.js | 281 ++++++++++++++++ test/datastore/entity.test.js | 129 ------- test/datastore/error.test.js | 18 +- test/datastore/indexes.test.js | 47 --- test/datastore/metadata.test.js | 57 ---- test/datastore/query.test.js | 190 ----------- test/datastore/tasks.test.js | 90 ++--- test/datastore/transaction.test.js | 57 ---- test/datastore/util.js | 3 +- test/functions/helloworld.test.js | 21 +- test/functions/log.test.js | 119 +++---- test/functions/message.test.js | 69 ++-- test/functions/module.test.js | 21 +- test/functions/uuid.test.js | 23 +- test/logging/export.test.js | 20 +- test/logging/list.test.js | 31 +- test/logging/write.test.js | 28 +- test/monitoring/create_custom_metric.test.js | 21 +- test/monitoring/list_resources.test.js | 17 +- test/prediction/hostedmodels.test.js | 30 +- test/pubsub/iam.test.js | 66 ++-- test/pubsub/subscription.test.js | 66 ++-- test/storage/authSample.test.js | 31 +- 43 files changed, 1158 insertions(+), 1368 deletions(-) delete mode 100644 test/.jshintrc create mode 100644 test/datastore/concepts.test.js delete mode 100644 test/datastore/entity.test.js delete mode 100644 test/datastore/indexes.test.js delete mode 100644 test/datastore/metadata.test.js delete mode 100644 test/datastore/query.test.js delete mode 100644 test/datastore/transaction.test.js diff --git a/.gitignore b/.gitignore index ff90428176..e8751f42d4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ test/encrypted/nodejs-docs-samples.json dump.rdb logs/ *.iml -.idea/ \ No newline at end of file +.idea/ +.nyc_output \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index de617eb499..4593292a67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,8 @@ cache: - appengine/mailgun/node_modules/ - appengine/memcached/node_modules/ - appengine/mongodb/node_modules/ + - appengine/parse-server/node_modules/ + - appengine/pubsub/node_modules/ - appengine/redis/node_modules/ - appengine/restify/node_modules/ - appengine/sails/node_modules/ @@ -50,7 +52,9 @@ cache: - appengine/websockets/node_modules/ - computeengine/sendgrid/node_modules/ - datastore/node_modules/ + - functions/uuid/node_modules/ - logging/node_modules/ + - monitoring/node_modules/ - prediction/node_modules/ - pubsub/node_modules/ - storage/node_modules/ @@ -61,26 +65,13 @@ services: env: global: - - PATH=$PATH:$HOME/gcloud/google-cloud-sdk/bin - GOOGLE_APPLICATION_CREDENTIALS=$TRAVIS_BUILD_DIR/test/encrypted/nodejs-docs-samples.json - TEST_BUCKET_NAME=nodejs-docs-samples - GCLOUD_PROJECT=nodejs-docs-samples before_install: - - if [ ! -d $HOME/gcloud/google-cloud-sdk ]; then - mkdir -p $HOME/gcloud && - wget https://dl.google.com/dl/cloudsdk/channels/rapid/google-cloud-sdk.tar.gz --directory-prefix=$HOME/gcloud && - cd $HOME/gcloud && - tar xzf google-cloud-sdk.tar.gz && - printf '\ny\n\ny\ny\n' | ./google-cloud-sdk/install.sh && - source $HOME/.bashrc && - cd $TRAVIS_BUILD_DIR; - fi - openssl aes-256-cbc -K $encrypted_fda0b707c7d5_key -iv $encrypted_fda0b707c7d5_iv -in test/encrypted/nodejs-docs-samples.json.enc -out test/encrypted/nodejs-docs-samples.json -d - - if [ -a test/encrypted/nodejs-docs-samples.json ]; then - gcloud auth activate-service-account --key-file test/encrypted/nodejs-docs-samples.json; - fi - npm set progress=false after_success: - - npm run coveralls + - npm run report diff --git a/README.md b/README.md index 910d937994..e4fb314c2c 100644 --- a/README.md +++ b/README.md @@ -129,30 +129,29 @@ a service account file. You can download one from your Google project's "permissions" page. 1. `npm test` -Since the tests use [Mocha.js](https://mochajs.org/), you can use the `--grep` -option to run only the tests that match a provided pattern. The `--invert` -option causes the matched tests to be excluded instead of included. +Since the tests use [AVA](https://github.com/sindresorhus/ava), you can use the +`--match` option to run only the tests that match a provided pattern. __Run only the tests that match a pattern:__ - npm test -- -- --grep + npm test -- -- --match="" __Only run the tests for the `datastore` sample:__ - npm test -- -- --grep datastore + npm test -- -- --match="datastore" __Skip the tests that match a pattern:__ - npm test -- -- --grep --invert + npm test -- -- --match="!" __Run all but the `datastore` tests:__ - npm test -- -- --grep datastore --invert + npm test -- -- --match="!datastore" __Skip the tests that require Redis and Memcached:__ - npm test -- -- --grep "express-memcached-session|redis" --invert + npm test -- -- --match="express-memcached-session|redis" ## License diff --git a/datastore/concepts.js b/datastore/concepts.js index 8f13744c7d..74508bc5a1 100644 --- a/datastore/concepts.js +++ b/datastore/concepts.js @@ -788,8 +788,7 @@ Query.prototype.testRunQueryProjection = function(callback) { self.datastore.runQuery(query, function(err) { if (err) { - callback(err); - return; + return callback(err); } queryCallback.apply(null, arguments); diff --git a/datastore/error.js b/datastore/error.js index 025249a5be..5a215c069b 100644 --- a/datastore/error.js +++ b/datastore/error.js @@ -51,5 +51,5 @@ function runQuery(cb) { exports.runQuery = runQuery; if (module === require.main) { - runQuery(function () {}); + runQuery(console.log); } diff --git a/logging/export.js b/logging/export.js index fcab588ff8..313f8ea267 100644 --- a/logging/export.js +++ b/logging/export.js @@ -28,70 +28,103 @@ var logging = gcloud.logging(); // [END setup] // [START listSinks] -function listSinks(callback) { +/** + * @param {Function} callback Callback function. + */ +function listSinksExample(callback) { // list all sinks in the authenticated project - logging.getSinks(callback); + logging.getSinks(function (err, sinks) { + if (err) { + return callback(err); + } + + // Should have received all sinks + console.log('Found ' + sinks.length + ' sinks'); + callback(null, sinks); + }); } // [END listSinks] // [START createSink] -function createSink(callback) { - // Get a reference to the Cloud Storage component - var gcs = gcloud.storage(); - +/** + * @param {string} sinkName Name of the new sink. + * @param {Object} config Configuration options for the new sink. + * @param {Function} callback Callback function. + */ +function createSinkExample(sinkName, config, callback) { // create a new sink in the authenticated project // // This method only works if you are authenticated as yourself, e.g. using the // gcloud SDK. - logging.createSink('mySink', { - destination: gcs.bucket('logging-bucket') - }, callback); + logging.createSink(sinkName, config, function (err, sink, apiResponse) { + if (err) { + return callback(err); + } + + // Should have received newly created sink + console.log('Created ' + sinkName, sink); + callback(null, sink, apiResponse); + }); } // [END createSink] // [START updateSink] -function updateSink(callback) { - // Get a reference to the Cloud Storage component - var gcs = gcloud.storage(); +/** + * @param {string} sinkName Name of the sink to update. + * @param {Object} config New configuration options for the sink. + * @param {Function} callback Callback function. + */ +function updateSinkExample(sinkName, config, callback) { // Get a reference to an existing sink - var sink = logging.sink('mySink'); + var sink = logging.sink(sinkName); // update a sink // // This method only works if you are authenticated as yourself, e.g. using the // gcloud SDK. - sink.setMetadata({ - // change destination to something else - destination: gcs.bucket('other-logging-bucket') - }, callback); + sink.setMetadata(config, function (err, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Updated ' + sinkName); + callback(null, apiResponse); + }); } // [END updateSink] // [START deleteSink] -function deleteSink(callback) { +/** + * @param {string} sinkName Name of the sink to delete. + * @param {Function} callback Callback function. + */ +function deleteSinkExample(sinkName, callback) { // Get a reference to an existing sink - var sink = logging.sink('mySink'); + var sink = logging.sink(sinkName); // delete a sink // // This method only works if you are authenticated as yourself, e.g. using the // gcloud SDK. - sink.delete(callback); + sink.delete(function (err, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Deleted ' + sinkName); + callback(null, apiResponse); + }); } // [END deleteSink] -exports.runExample = function (cb) { - listSinks(function (err, sinks, apiResponse) { - console.log(err, 'sinks:', sinks, 'apiResponse:', apiResponse); - if (typeof cb === 'function') { - cb(err, sinks); - } - }); +// Run the examples +exports.main = function (cb) { + listSinksExample(cb || console.log); }; -exports.createSink = createSink; -exports.updateSink = updateSink; -exports.deleteSink = deleteSink; +exports.createSinkExample = createSinkExample; +exports.updateSinkExample = updateSinkExample; +exports.deleteSinkExample = deleteSinkExample; if (module === require.main) { - exports.runExample(); + exports.main(); } diff --git a/logging/list.js b/logging/list.js index 53215f5014..aec74207be 100644 --- a/logging/list.js +++ b/logging/list.js @@ -30,24 +30,33 @@ var gcloud = require('gcloud')({ // Get a reference to the logging component var logging = gcloud.logging(); -function list(callback) { - // Retrieve the latest 3 log entries from the authenticated project. - logging.getEntries({ - pageSize: 3 - }, callback); -} -// [END list] +/** + * @param {Object} [options] Configuration options for the request. + * @param {Function} callback Callback function. + */ +function listExample(options, callback) { + if (typeof options === 'function') { + callback = options; + } -exports.runExample = function (cb) { - console.log('retrieving latest 3 log entries...'); - list(function (err, entries, apiResponse) { - console.log(err, 'entries:', entries, 'apiResponse:', apiResponse); - if (typeof cb === 'function') { - cb(err, entries, apiResponse); + // Retrieve the latest some log entries from the authenticated project. + logging.getEntries(options, function (err, entries, nextQuery, apiResponse) { + if (err) { + return callback(err); } + + // Should have received some log entries + console.log('Found ' + entries.length + ' entries'); + callback(null, entries, nextQuery, apiResponse); }); +} +// [END list] + +// Run the examples +exports.main = function (options, cb) { + listExample(options || { pageSize: 1 }, cb || console.log); }; if (module === require.main) { - exports.runExample(); + exports.main(); } diff --git a/logging/write.js b/logging/write.js index 13399c1609..77f38bce7a 100644 --- a/logging/write.js +++ b/logging/write.js @@ -14,6 +14,8 @@ /* jshint camelcase:false */ 'use strict'; +var async = require('async'); + // [START write] // [START setup] // You must set the GOOGLE_APPLICATION_CREDENTIALS and GCLOUD_PROJECT @@ -29,9 +31,13 @@ var gcloud = require('gcloud')({ var logging = gcloud.logging(); // [END setup] -function write(callback) { +/** + * @param {string} logName Name of the log to write to. + * @param {Function} callback Callback function. + */ +function writeExample(logName, callback) { // Get a reference to an existing log - var log = logging.log('myLog'); + var log = logging.log(logName); // Modify this resource type to match a resource in your project // See https://cloud.google.com/logging/docs/api/ref_v2beta1/rest \ @@ -61,50 +67,50 @@ function write(callback) { log.write([ entry, secondEntry - ], callback); + ], function (err, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Wrote to ' + logName); + callback(null, apiResponse); + }); } // [END write] // [START deleteLog] -function deleteLog(callback) { +/** + * @param {string} logName Name of the log to delete. + * @param {Function} callback Callback function. + */ +function deleteLogExample(logName, callback) { // Get a reference to an existing log - var log = logging.log('myLog'); + var log = logging.log(logName); // Delete the log - log.delete(callback); + log.delete(function (err, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Deleted ' + logName); + callback(null, apiResponse); + }); } // [END deleteLog] -exports.runExample = function (cb) { - var result = []; - console.log('writing 2 log entries...'); - write(function (err, apiResponse) { - console.log(err, 'apiResponse:', apiResponse); - if (err) { - return typeof cb === 'function' ? cb(err) : undefined; +// Run the examples +exports.main = function (cb) { + async.series([ + function (cb) { + writeExample('myLog', cb); + }, + function (cb) { + deleteLogExample('myLog', cb); } - result.push(apiResponse); - console.log('success!'); - console.log('deleting the log entries...'); - // If you remove this code, then you can find the two log entries that - // were written in the log view in the cloud console. - deleteLog(function (err, apiResponse) { - console.log(err, 'apiResponse:', apiResponse); - if (err && err.code === 404) { - err = undefined; - apiResponse = {}; - } - if (!err) { - console.log('success!'); - } - result.push(apiResponse); - if (typeof cb === 'function') { - cb(err, result); - } - }); - }); + ], cb || console.log); }; if (module === require.main) { - exports.runExample(); + exports.main(); } diff --git a/package.json b/package.json index cdd2ca85d3..d178f3bd25 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,11 @@ }, "scripts": { "jshint": "jshint --exclude-path=.jshintignore .", - "mocha": "mocha --timeout 10000 --recursive", - "cover": "istanbul cover --hook-run-in-context node_modules/mocha/bin/_mocha -- -t 30000 --recursive", - "coveralls": "cat ./coverage/lcov.info | node_modules/.bin/coveralls", + "deps_appengine": "ava --match='*: dependencies should install*'", + "ava": "npm run deps_appengine && ava --match='!*: dependencies should install*'", + "cover": "npm run deps_appengine && nyc ava --match='!*: dependencies should install*'", + "report": "nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls", + "report-html": "nyc report --reporter=html", "deps_datastore": "cd datastore; npm i; cd ../", "deps_pubsub": "cd pubsub; npm i; cd ../", "deps_monitoring": "cd monitoring; npm i; cd ../", @@ -40,13 +42,17 @@ "pretest": "npm run deps_datastore; npm run deps_monitoring; npm run deps_storage; npm run deps_pubsub; npm run deps_prediction; npm run deps_logging; npm run deps_functions; npm run deps_sendgrid; npm run pretest_geddy", "test": "npm run jshint && npm run cover" }, + "ava": { + "files": [ + "test/**/*.test.js" + ] + }, "devDependencies": { "async": "^1.5.2", - "coveralls": "^2.11.6", - "googleapis": "^2.1.7", - "istanbul": "^0.4.2", + "ava": "^0.13.0", + "coveralls": "^2.11.9", "jshint": "~2.9.1", - "mocha": "^2.4.5", + "nyc": "^6.1.1", "proxyquire": "^1.7.4", "request": "^2.69.0", "supertest": "^1.1.0" diff --git a/prediction/README.md b/prediction/README.md index ed88404357..3dc0d63d0e 100644 --- a/prediction/README.md +++ b/prediction/README.md @@ -21,4 +21,4 @@ Execute a sample: Example: - npm run hostedmodels + npm run hostedmodels -- "good evening" diff --git a/prediction/hostedmodels.js b/prediction/hostedmodels.js index b21bab61a3..aa8a806d41 100644 --- a/prediction/hostedmodels.js +++ b/prediction/hostedmodels.js @@ -17,11 +17,12 @@ var google = require('googleapis'); var hostedmodels = google.prediction('v1.6').hostedmodels; -function auth (callback) { - google.auth.getApplicationDefault(function(err, authClient) { +function auth(callback) { + google.auth.getApplicationDefault(function (err, authClient) { if (err) { return callback(err); } + // The createScopedRequired method returns true when running on GAE or a // local developer machine. In that case, the desired scopes must be passed // in manually. When the code is running in GCE or a Managed VM, the scopes @@ -39,12 +40,17 @@ function auth (callback) { }); } -function predict(callback) { - auth(function(err, authClient) { +/** + * @param {string} phrase The phrase for which to predict sentiment, + * e.g. "good morning". + * @param {Function} callback Callback function. + */ +function predict(phrase, callback) { + auth(function (err, authClient) { if (err) { return callback(err); } - // Predict the sentiment for the word "hello". + // Predict the sentiment for the provided phrase hostedmodels.predict({ auth: authClient, // Project id used for this sample @@ -52,22 +58,28 @@ function predict(callback) { hostedModelName: 'sample.sentiment', resource: { input: { - // Predict sentiment of the word "hello" - csvInstance: ['hello'] + // Predict sentiment of the provided phrase + csvInstance: phrase.split(/\s/gi) } } - }, function (err, result) { - console.log(err, result); - if (typeof callback === 'function') { - callback(err, result); - } + }, function (err, prediction) { + if (err) { + return callback(err); + } + + // Received prediction result + console.log('Sentiment for "' + phrase + '": ' + prediction.outputLabel); + callback(null, prediction); }); }); } // [END predict] -exports.predict = predict; +// Run the examples +exports.main = function (phrase, cb) { + predict(phrase || 'good morning', cb || console.log); +}; if (module === require.main) { - predict(); + exports.main(process.argv.slice(2).shift()); } diff --git a/prediction/package.json b/prediction/package.json index b8d38bf03e..e317db3060 100644 --- a/prediction/package.json +++ b/prediction/package.json @@ -12,6 +12,6 @@ "hostedmodels": "node hostedmodels.js" }, "dependencies": { - "googleapis": "^2.1.7" + "googleapis": "^4.0.0" } } diff --git a/pubsub/iam.js b/pubsub/iam.js index 5fb8ed47b5..acbbf37aa0 100644 --- a/pubsub/iam.js +++ b/pubsub/iam.js @@ -15,46 +15,64 @@ var async = require('async'); var subscriptionSample = require('./subscription'); -var createTopic = subscriptionSample.createTopic; -var subscribe = subscriptionSample.subscribe; +var createTopicExample = subscriptionSample.createTopicExample; +var deleteTopicExample = subscriptionSample.deleteTopicExample; +var subscribeExample = subscriptionSample.subscribeExample; +var deleteSubscriptionExample = subscriptionSample.deleteSubscriptionExample; var pubsub = subscriptionSample.pubsub; // [START get_topic_policy] -function getTopicPolicy(callback) { +/** + * @param {string} topicName Name of the topic whose policy is to be retrieved. + * @param {Function} callback Callback function. + */ +function getTopicPolicyExample(topicName, callback) { // Grab a reference to an existing topic - var topic = pubsub.topic('messageCenter'); + var topic = pubsub.topic(topicName); // Retrieve the IAM policy for the topic - topic.iam.getPolicy(function (err, policy) { + topic.iam.getPolicy(function (err, policy, apiResponse) { if (err) { return callback(err); } + + // Received the policy console.log(policy); // { etag: 'ACAB' } - return callback(err, policy); + callback(null, policy, apiResponse); }); } // [END get_topic_policy] // [START get_subscription_policy] -function getSubscriptionPolicy(callback) { +/** + * @param {string} subscriptionName Name of the subscription whose policy is to + * be retrieved. + * @param {Function} callback Callback function. + */ +function getSubscriptionPolicyExample(subscriptionName, callback) { // Grab a reference to an existing subscription - var subscription = pubsub.subscription('newMessages'); + var subscription = pubsub.subscription(subscriptionName); // Retrieve the IAM policy for the subscription - subscription.iam.getPolicy(function (err, policy) { + subscription.iam.getPolicy(function (err, policy, apiResponse) { if (err) { return callback(err); } + console.log(policy); // { etag: 'ACAB' } - return callback(err, policy); + callback(null, policy, apiResponse); }); } // [END get_subscription_policy] // [START set_topic_policy] -function setTopicPolicy(callback) { +/** + * @param {string} topicName Name of the topic whose policy is to be updated. + * @param {Function} callback Callback function. + */ +function setTopicPolicyExample(topicName, callback) { // Grab a reference to an existing topic - var topic = pubsub.topic('messageCenter'); + var topic = pubsub.topic(topicName); // Policy update var myPolicy = { @@ -67,14 +85,26 @@ function setTopicPolicy(callback) { }; // Retrieve the IAM policy for the provided topic - topic.iam.setPolicy(myPolicy, callback); + topic.iam.setPolicy(myPolicy, function (err, policy, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Updated policy for ' + topicName); + callback(null, policy, apiResponse); + }); } // [END set_topic_policy] // [START set_subscription_policy] -function setSubscriptionPolicy(callback) { +/** + * @param {string} subscriptionName Name of the subscription whose policy is to + * be updated. + * @param {Function} callback Callback function. + */ +function setSubscriptionPolicyExample(subscriptionName, callback) { // Grab a reference to an existing subscription - var subscription = pubsub.subscription('newMessages'); + var subscription = pubsub.subscription(subscriptionName); // Policy update var myPolicy = { @@ -87,14 +117,25 @@ function setSubscriptionPolicy(callback) { }; // Retrieve the IAM policy for the provided subscription - subscription.iam.setPolicy(myPolicy, callback); + subscription.iam.setPolicy(myPolicy, function (err, policy, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Updated policy for ' + subscriptionName); + callback(null, policy, apiResponse); + }); } // [END set_subscription_policy] // [START test_topic_permissions] -function testTopicPermissions(callback) { +/** + * @param {string} topicName Name of the topic whose policy is to be tested. + * @param {Function} callback Callback function. + */ +function testTopicPermissionsExample(topicName, callback) { // Grab a reference to an existing topic - var topic = pubsub.topic('messageCenter'); + var topic = pubsub.topic(topicName); var tests = [ 'pubsub.topics.attachSubscription', @@ -103,14 +144,26 @@ function testTopicPermissions(callback) { ]; // Retrieve the IAM policy for the provided topic - topic.iam.testPermissions(tests, callback); + topic.iam.testPermissions(tests, function (err, permissions, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Got permissions for ' + topicName); + callback(null, permissions, apiResponse); + }); } // [END test_topic_permissions] // [START test_subscription_permissions] -function testSubscriptionPermissions(callback) { +/** + * @param {string} subscriptionName Name of the subscription whose policy is to + * be tested. + * @param {Function} callback Callback function. + */ +function testSubscriptionPermissionsExample(subscriptionName, callback) { // Grab a reference to an existing subscription - var subscription = pubsub.subscription('newMessages'); + var subscription = pubsub.subscription(subscriptionName); var tests = [ 'pubsub.subscriptions.consume', @@ -118,79 +171,55 @@ function testSubscriptionPermissions(callback) { ]; // Retrieve the IAM policy for the provided subscription - subscription.iam.testPermissions(tests, callback); + subscription.iam.testPermissions( + tests, + function (err, permissions, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Got permissions for ' + subscriptionName); + callback(null, permissions, apiResponse); + } + ); } // [END test_subscription_permissions] -exports.setTopicPolicy = setTopicPolicy; -exports.setSubscriptionPolicy = setSubscriptionPolicy; -exports.runSample = runSample; +exports.setTopicPolicyExample = setTopicPolicyExample; +exports.setSubscriptionPolicyExample = setSubscriptionPolicyExample; -function runSample(callback) { - var _subscription; - var _topic; - // Gather responses - var responses = []; - async.waterfall([ +// Run the examples +exports.main = function (cb) { + var topicName = 'messageCenter2'; + var subscriptionName = 'newMessages2'; + async.series([ function (cb) { - console.log('create topic...'); - createTopic(cb); + createTopicExample(topicName, cb); }, - function (topic, apiResponse, cb) { - _topic = topic; - responses.push([topic, apiResponse]); - console.log('created topic'); - console.log('get topic IAM policy...'); - getTopicPolicy(cb); + function (cb) { + getTopicPolicyExample(topicName, cb); }, - function (policy, cb) { - responses.push([policy]); - console.log('got topic policy', policy); - console.log('testing topic permissions...'); - testTopicPermissions(cb); + function (cb) { + testTopicPermissionsExample(topicName, cb); }, - function (permissions, apiResponse, cb) { - responses.push([permissions, apiResponse]); - console.log('tested topic permissions', permissions); - console.log('create subscription...'); - subscribe(cb); + function (cb) { + subscribeExample(topicName, subscriptionName, cb); }, - function (subscription, apiResponse, cb) { - _subscription = subscription; - responses.push([subscription, apiResponse]); - console.log('created subscription'); - console.log('get subscription IAM policy...'); - getSubscriptionPolicy(cb); + function (cb) { + getSubscriptionPolicyExample(subscriptionName, cb); }, - function (policy, cb) { - responses.push([policy]); - console.log('got subscription policy', policy); - console.log('testing subscription permissions...'); - testSubscriptionPermissions(cb); + function (cb) { + testSubscriptionPermissionsExample(subscriptionName, cb); }, - function (permissions, apiResponse, cb) { - responses.push([permissions, apiResponse]); - console.log('tested subscription permissions', permissions); - console.log('deleting subscription...'); - _subscription.delete(cb); + function (cb) { + deleteSubscriptionExample(subscriptionName, cb); }, - function (apiResponse, cb) { - console.log('deleted subscription'); - console.log('deleting topic...'); - _topic.delete(cb); - } - ], function (err) { - if (err) { - console.error(err); - } else { - console.log('deleted topic'); - } - if (typeof callback === 'function') { - callback(err, responses); + function (cb) { + deleteTopicExample(topicName, cb); } - }); -} + ], cb || console.log); +}; if (module === require.main) { - runSample(); + exports.main(); } diff --git a/pubsub/subscription.js b/pubsub/subscription.js index 1c0b1909a5..e63654859e 100644 --- a/pubsub/subscription.js +++ b/pubsub/subscription.js @@ -31,110 +31,223 @@ var pubsub = gcloud.pubsub(); // [END auth] // [START create_topic] -function createTopic(callback) { - var topicName = 'messageCenter'; - +/** + * @param {string} topicName Name for the new topic. + * @param {Function} callback Callback function. + */ +function createTopicExample(topicName, callback) { var topic = pubsub.topic(topicName); // Get the topic if it exists. Create it if it does not exist. topic.get({ autoCreate: true - }, callback); + }, function (err, topic, apiResponse) { + if (err) { + return callback(err); + } + + // Created the topic + console.log('Created topic ' + topicName); + callback(null, topic, apiResponse); + }); } // [END create_topic] -// [START publish] -function publish(callback) { - var topicName = 'messageCenter'; +// [START delete_topic] +/** + * @param {string} topicName Name of the topic to delete. + * @param {Function} callback Callback function. + */ +function deleteTopicExample(topicName, callback) { + var topic = pubsub.topic(topicName); + + // Delete the topic + topic.delete(function (err, apiResponse) { + if (err) { + return callback(err); + } + + // Deleted the topic + console.log('Deleted topic ' + topicName); + callback(null, apiResponse); + }); +} +// [END delete_topic] + +// [START delete_subscription] +/** + * @param {string} subscriptionName Name of the subscription to delete. + * @param {Function} callback Callback function. + */ +function deleteSubscriptionExample(subscriptionName, callback) { + var subscription = pubsub.subscription(subscriptionName); + + // Delete the subscription + subscription.delete(function (err, apiResponse) { + if (err) { + return callback(err); + } + + // Deleted the subscription + console.log('Deleted subscription ' + subscriptionName); + callback(null, apiResponse); + }); +} +// [END delete_subscription] +// [START publish] +/** + * @param {string} topicName Name of the topic to which to publish. + * @param {Function} callback Callback function. + */ +function publishExample(topicName, callback) { // Grab a reference to an existing topic var topic = pubsub.topic(topicName); // Publish a message to the topic topic.publish({ data: 'Hello, world!' - }, callback); + }, function (err, messageIds, apiResponse) { + if (err) { + return callback(err); + } + + console.log('Published ' + messageIds.length + ' messages'); + callback(null, messageIds, apiResponse); + }); } // [END publish] // [START list_topics] -function getAllTopics(callback) { +/** + * @param {string} [pageToken] Page to retrieve. + * @param {Function} callback Callback function. + */ +function getAllTopicsExample(pageToken, callback) { + if (typeof pageToken === 'function') { + callback = pageToken; + pageToken = undefined; + } + var options = {}; + if (pageToken) { + options.pageToken = pageToken; + } + // Grab paginated topics - pubsub.getTopics(function (err, topics, nextQuery) { + pubsub.getTopics(options, function (err, topics, nextQuery) { // Quit on error if (err) { return callback(err); } + // There is another page of topics if (nextQuery) { // Grab the remaining pages of topics recursively - return getAllTopics(function (err, _topics) { + return getAllTopicsExample(nextQuery.token, function (err, _topics) { if (_topics) { topics = topics.concat(_topics); } - callback(err, topics); + callback(null, topics); }); } // Last page of topics - return callback(err, topics); + return callback(null, topics); }); } // [END list_topics] // [START get_all_subscriptions] -function getAllSubscriptions(callback) { +/** + * @param {string} [pageToken] Page to retrieve. + * @param {Function} callback Callback function. + */ +function getAllSubscriptionsExample(pageToken, callback) { + if (typeof pageToken === 'function') { + callback = pageToken; + pageToken = undefined; + } + var options = {}; + if (pageToken) { + options.pageToken = pageToken; + } // Grab paginated subscriptions - pubsub.getSubscriptions(function (err, subscriptions, nextQuery) { - // Quit on error - if (err) { - return callback(err); - } - // There is another page of subscriptions - if (nextQuery) { - // Grab the remaining pages of subscriptions recursively - return getAllSubscriptions(function (err, _subscriptions) { - if (_subscriptions) { - subscriptions = subscriptions.concat(_subscriptions); - } - callback(err, subscriptions); - }); + pubsub.getSubscriptions( + options, + function (err, subscriptions, nextQuery) { + // Quit on error + if (err) { + return callback(err); + } + + // There is another page of subscriptions + if (nextQuery) { + // Grab the remaining pages of subscriptions recursively + return getAllSubscriptionsExample( + nextQuery.token, + function (err, _subscriptions) { + if (_subscriptions) { + subscriptions = subscriptions.concat(_subscriptions); + } + callback(null, subscriptions); + } + ); + } + // Last page of subscriptions + return callback(null, subscriptions); } - // Last page of subscriptions - return callback(err, subscriptions); - }); + ); } // [END get_all_subscriptions] // [START create_subscription] -function subscribe(callback) { - var topicName = 'messageCenter'; - var subscriptionName = 'newMessages'; - +/** + * @param {string} topicName Name of the topic for the new subscription. + * @param {string} subscriptionName Name for the new subscription. + * @param {Function} callback Callback function. + */ +function subscribeExample(topicName, subscriptionName, callback) { var options = { reuseExisting: true }; - pubsub.subscribe(topicName, subscriptionName, options, callback); + pubsub.subscribe( + topicName, + subscriptionName, + options, + function (err, subscription, apiResponse) { + if (err) { + return callback(err); + } + + // Got the subscription + console.log('Subscribed to ' + topicName); + callback(null, subscription, apiResponse); + } + ); } // [END create_subscription] // [START handle_message] -function handleMessage(message) { +function handleMessageExample(message) { console.log('received message: ' + message.data); } // [END handle_message] // [START pull_messages] -function pullMessages(callback) { - // Create a topic - createTopic(function (err) { - if (err) { - return callback(err); - } - // Create a subscription to the topic - subscribe(function (err, subscription) { - if (err) { - return callback(err); - } +/** + * + */ +function pullMessagesExample(topicName, subscriptionName, callback) { + // Use the "async" library to handle a chain of asynchronous functions + async.waterfall([ + function (cb) { + // Create a topic + createTopicExample(topicName, cb); + }, + function (topic, apiResponse, cb) { + // Create a subscription + subscribeExample(topicName, subscriptionName, cb); + }, + function (subscription, apiResponse, cb) { var options = { // Limit the amount of messages pulled. maxResults: 100, @@ -143,101 +256,70 @@ function pullMessages(callback) { returnImmediately: false }; // Pull any messages on the subscription - subscription.pull(options, function (err, messages) { + subscription.pull(options, cb); + }, + function (messages, apiResponse, cb) { + // Do something for each message + messages.forEach(handleMessageExample); + + // Acknowledge messages + var subscription = pubsub.subscription(subscriptionName); + subscription.ack(messages.map(function (message) { + return message.ackId; + }), function (err) { if (err) { - return callback(err); + return cb(err); } - - // Do something for each message - messages.forEach(handleMessage); - - // Acknowledge messages - subscription.ack(messages.map(function (message) { - return message.ackId; - }), function (err) { - if (err) { - return callback(err); - } - callback(null, messages); - }); + cb(null, messages); }); - }); + } + ], function (err, messages) { + if (err) { + return callback(err); + } + + console.log('Pulled ' + messages.length + ' messages'); + callback(null, messages); }); } // [END pull_messages] -exports.createTopic = createTopic; -exports.subscribe = subscribe; -exports.runSample = runSample; +exports.createTopicExample = createTopicExample; +exports.deleteTopicExample = deleteTopicExample; +exports.subscribeExample = subscribeExample; +exports.deleteSubscriptionExample = deleteSubscriptionExample; exports.pubsub = pubsub; - -function runSample(callback) { - var _subscription; - var _topic; - // Gather responses - var responses = []; - async.waterfall([ +exports.main = function (cb) { + var topicName = 'messageCenter'; + var subscriptionName = 'newMessages'; + async.series([ function (cb) { - console.log('create topic...'); - createTopic(cb); + createTopicExample(topicName, cb); }, - function (topic, apiResponse, cb) { - _topic = topic; - responses.push([topic, apiResponse]); - console.log('created topic'); - console.log('create subscription...'); - subscribe(cb); + function (cb) { + subscribeExample(topicName, subscriptionName, cb); }, - function (subscription, apiResponse, cb) { - _subscription = subscription; - responses.push([subscription, apiResponse]); - console.log('created subscription'); - console.log('list all topics...'); - getAllTopics(cb); + function (cb) { + getAllTopicsExample(cb); }, - function (topics, cb) { - responses.push([topics]); - console.log('got all topics'); - console.log('list all subscriptions...'); - getAllSubscriptions(cb); + function (cb) { + getAllSubscriptionsExample(cb); }, - function (subscriptions, cb) { - responses.push([subscriptions]); - console.log('got all subscriptions'); - console.log('publishing a message...'); - publish(cb); + function (cb) { + publishExample(topicName, cb); }, - function (messageIds, apiResponse, cb) { - responses.push([messageIds, apiResponse]); - console.log('published message'); - console.log('pulling messages...'); - pullMessages(cb); + function (cb) { + pullMessagesExample(topicName, subscriptionName, cb); }, - function (messages, cb) { - responses.push([messages]); - console.log('got messages', messages.map(function (message) { - return message.data; - })); - console.log('deleting subscription...'); - _subscription.delete(cb); + function (cb) { + deleteSubscriptionExample(subscriptionName, cb); }, - function (apiResponse, cb) { - console.log('deleted subscription'); - console.log('deleting topic...'); - _topic.delete(cb); - } - ], function (err) { - if (err) { - console.error(err); - } else { - console.log('deleted topic'); - } - if (typeof callback === 'function') { - callback(err, responses); + function (cb) { + deleteTopicExample(topicName, cb); } - }); -} + ], cb || console.log); +}; if (module === require.main) { - runSample(); + exports.main(); } diff --git a/storage/README.md b/storage/README.md index e27f20ba10..5d7766a845 100644 --- a/storage/README.md +++ b/storage/README.md @@ -17,7 +17,7 @@ To print available commands: Execute a sample: - npm run -- [arg_1] [arg_2] [arg_n] + npm run -- [args...] Example: diff --git a/storage/authSample.js b/storage/authSample.js index a1b1d83906..253abdc436 100644 --- a/storage/authSample.js +++ b/storage/authSample.js @@ -36,10 +36,10 @@ var google = require('googleapis'); * responds with the list of buckets. */ // [START list_buckets] -function listBuckets(projectId, cb) { +function listBucketsExample(projectId, callback) { google.auth.getApplicationDefault(function(err, authClient) { if (err) { - return cb(err); + return callback(err); } // Depending on the environment that provides the default credentials @@ -54,32 +54,30 @@ function listBuckets(projectId, cb) { // Create the service object. var storage = google.storage('v1'); + // Make the api call to list the buckets. storage.buckets.list({ auth: authClient, project: projectId - }, cb); + }, function (err, response) { + if (err) { + return callback(err); + } + + console.log('Found ' + response.items.length + ' buckets'); + callback(null, response); + }); }); } // [END list_buckets] -exports.runExample = function (projectId, cb) { - listBuckets( - projectId, - function (err, response) { - if (err) { - console.log(err); - } else if (response && response.items) { - console.log(JSON.stringify(response.items, null, 2)); - } - if (typeof cb === 'function') { - cb(err, response); - } - } - ); +// Run the samples +exports.main = function (projectId, cb) { + listBucketsExample(projectId, cb || function (err, response) { + console.log(err, response.items); + }); }; -// For command-line execution of sample if (module === require.main) { - exports.runExample(process.argv.length > 2 ? process.argv[2] : ''); + exports.main(process.argv.slice(2).shift()); } diff --git a/storage/package.json b/storage/package.json index 0326c705f0..1cbff9007e 100644 --- a/storage/package.json +++ b/storage/package.json @@ -12,6 +12,6 @@ "authSample": "node authSample.js" }, "dependencies": { - "googleapis": "^2.1.7" + "googleapis": "^4.0.0" } } diff --git a/test/.jshintrc b/test/.jshintrc deleted file mode 100644 index e26f0d4bc7..0000000000 --- a/test/.jshintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "../.jshintrc", - "mocha": true -} diff --git a/test/appengine/all.test.js b/test/appengine/all.test.js index b3ca3e83e7..ae6faaf95f 100644 --- a/test/appengine/all.test.js +++ b/test/appengine/all.test.js @@ -13,15 +13,17 @@ 'use strict'; +var test = require('ava'); var spawn = require('child_process').spawn; var request = require('request'); var fs = require('fs'); +var path = require('path'); var async = require('async'); var cwd = process.cwd(); var projectId = process.env.GCLOUD_PROJECT; function getPath(dir) { - return cwd + '/appengine/' + dir; + return path.join(cwd, '/../../appengine/', dir); } function changeScaling(dir) { @@ -90,7 +92,8 @@ var sampleTests = [ dir: 'geddy', cmd: 'node', args: ['node_modules/geddy/bin/cli.js'], - msg: 'Hello, World! Geddy.js on Google App Engine.' + msg: 'Hello, World! Geddy.js on Google App Engine.', + TRAVIS_NODE_VERSION: 'stable' }, { dir: 'grunt', @@ -245,69 +248,81 @@ if (process.env.TRAVIS_NODE_VERSION === 'stable') { }); } -// Send a request to the given url and test that the response body has the -// expected value -function testRequest(url, sample, cb) { +// Retry the request using exponential backoff up to a maximum number of tries. +function makeRequest(url, numTry, maxTries, cb) { request(url, function (err, res, body) { if (err) { - // Request error - return cb(err); - } else { - if (body && body.indexOf(sample.msg) !== -1 && - (res.statusCode === 200 || res.statusCode === sample.code) && - (!sample.test || sample.test.test(body))) { - // Success - return cb(null, true); - } else { - // Short-circuit app test - var message = sample.dir + ': failed verification!\n' + - 'Expected: ' + sample.msg + '\n' + - 'Actual: ' + body; - - // Response body did not match expected - return cb(new Error(message)); + if (numTry >= maxTries) { + return cb(err); } + setTimeout(function () { + makeRequest(url, numTry + 1, maxTries, cb); + }, 500 * Math.pow(numTry, 2)); + } else { + cb(null, res, body); } }); } -describe('appengine/', function () { - var port = 8080; - sampleTests.forEach(function (sample) { - sample.env = sample.env || {}; - sample.env.PORT = port; - if (sample.dir === 'parse-server') { - sample.env.SERVER_URL = sample.env.SERVER_URL + port + '/parse'; - console.log(sample); +// Send a request to the given url and test that the response body has the +// expected value +function testRequest(url, sample, cb) { + // Try up to 8 times + makeRequest(url, 1, 8, function (err, res, body) { + if (err) { + // Request error + return cb(err); } - port++; - it(sample.dir + ': dependencies should install', function (done) { - // Allow extra time for "npm install" - this.timeout(sample.timeout || 120000); - - testInstallation(sample, done); - }); - - if (sample.TRAVIS && !process.env.TRAVIS) { - return; + if (body && body.indexOf(sample.msg) !== -1 && + (res.statusCode === 200 || res.statusCode === sample.code) && + (!sample.test || sample.test.test(body))) { + // Success + return cb(null, true); } + // Short-circuit app test + var message = sample.dir + ': failed verification!\n' + + 'Expected: ' + sample.msg + '\n' + + 'Actual: ' + body; - it(sample.dir + ' should return 200 and Hello World', function (done) { - testLocalApp(sample, done); - }); + // Response body did not match expected + cb(new Error(message)); }); +} - if (!process.env.TRAVIS || !process.env.DEPLOY_TESTS) { +var port = 8080; +sampleTests.forEach(function (sample) { + sample.env = sample.env || {}; + sample.env.PORT = port; + if (sample.dir === 'parse-server') { + sample.env.SERVER_URL = sample.env.SERVER_URL + port + '/parse'; + } + port++; + test.cb(sample.dir + ': dependencies should install', function (t) { + testInstallation(sample, t.end); + }); + + if (sample.TRAVIS && !process.env.TRAVIS) { return; } - it('should deploy all samples', function (done) { + if (sample.TRAVIS_NODE_VERSION && process.env.TRAVIS && + process.env.TRAVIS_NODE_VERSION !== sample.TRAVIS_NODE_VERSION) { + return; + } + + test.cb(sample.dir + ' should return 200 and Hello World', function (t) { + testLocalApp(sample, t.end); + }); +}); + +if (process.env.TRAVIS && process.env.DEPLOY_TESTS) { + test.cb('should deploy all samples', function (t) { // 30 minutes because deployments are slow this.timeout(30 * 60 * 1000); - testDeployments(done); + testDeployments(t.end); }); -}); +} function testInstallation(sample, done) { @@ -361,34 +376,18 @@ function testLocalApp(sample, done) { console.log('\t' + sample.dir + ': Start server on port ' + sample.env.PORT); var proc = spawn(sample.cmd, sample.args, opts); - proc.on('error', function (err) { - console.log('\t' + sample.dir + ': ERROR', err.message); - finish(err); - }); - - if (!process.env.TRAVIS) { - proc.stderr.on('data', function (data) { - console.log('stderr: ' + data); - }); - } - - proc.on('exit', function (code, signal) { - if (signal === 'SIGKILL') { - console.log('\t' + sample.dir + ': SIGKILL received!'); - } - if (code !== 0 && signal !== 'SIGKILL') { - console.log('\t' + sample.dir + ': ERROR', code, signal); - return finish(new Error(sample.dir + ': failed to run!')); - } else { - return finish(); + // Exit helper so we don't call "cb" more than once + function finish(err) { + if (!calledDone) { + calledDone = true; + done(err || requestError); } - }); + } - // Give the server time to start up - setTimeout(function () { - console.log('\t' + sample.dir + ': Send test request...'); - // Test that the app is working + try { + console.log('\t' + sample.dir + ': Testing app...'); var url = 'http://localhost:' + sample.env.PORT; + // Test that the app is working testRequest(url, sample, function (err, result) { requestError = err; if (result) { @@ -397,13 +396,32 @@ function testLocalApp(sample, done) { console.log('\t' + sample.dir + ': Send shutdown signal...'); proc.kill('SIGKILL'); }); - }, 5000); - // Exit helper so we don't call "cb" more than once - function finish(err) { - if (!calledDone) { - calledDone = true; - done(err || requestError); + proc.on('error', function (err) { + console.log('\t' + sample.dir + ': ERROR', err.message); + finish(err); + }); + + if (!process.env.TRAVIS) { + proc.stderr.on('data', function (data) { + console.log('stderr: ' + data); + }); + } + + proc.on('exit', function (code, signal) { + if (signal === 'SIGKILL') { + console.log('\t' + sample.dir + ': SIGKILL received!'); + } + if (code !== 0 && signal !== 'SIGKILL') { + console.log('\t' + sample.dir + ': ERROR', code, signal); + return finish(new Error(sample.dir + ': failed to run!')); + } else { + return finish(); + } + }); + } catch (err) { + if (proc) { + proc.kill('SIGKILL'); } } } diff --git a/test/computeengine/sendgrid.test.js b/test/computeengine/sendgrid.test.js index 30d28f5725..8c5820164c 100644 --- a/test/computeengine/sendgrid.test.js +++ b/test/computeengine/sendgrid.test.js @@ -13,28 +13,26 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); var proxyquire = require('proxyquire').noPreserveCache(); process.env.SENDGRID_API_KEY = 'foo'; -describe('sendgrid', function () { - it('should send an email', function (done) { - proxyquire('../../computeengine/sendgrid/sendmail.js', { - sendgrid: function (key) { - assert.equal(key, 'foo'); - return { - send: function (payload, cb) { - assert.deepEqual(payload, { - from: 'ANOTHER_EMAIL@ANOTHER_EXAMPLE.COM', - to: 'EMAIL@EXAMPLE.COM', - subject: 'test email from Node.js on Google Cloud Platform', - text: 'Hello!\n\nThis a test email from Node.js.' - }); - cb('done'); - done(); - } - }; - } - }); +test.cb('should send an email', function (t) { + proxyquire('../../computeengine/sendgrid/sendmail.js', { + sendgrid: function (key) { + t.is(key, 'foo'); + return { + send: function (payload, cb) { + t.same(payload, { + from: 'ANOTHER_EMAIL@ANOTHER_EXAMPLE.COM', + to: 'EMAIL@EXAMPLE.COM', + subject: 'test email from Node.js on Google Cloud Platform', + text: 'Hello!\n\nThis a test email from Node.js.' + }); + cb('done'); + t.end(); + } + }; + } }); }); diff --git a/test/datastore/concepts.test.js b/test/datastore/concepts.test.js new file mode 100644 index 0000000000..bc3447c518 --- /dev/null +++ b/test/datastore/concepts.test.js @@ -0,0 +1,281 @@ +// Copyright 2015, Google, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +var test = require('ava'); +var testUtil = require('./util.js'); +var concepts = require('../../datastore/concepts'); + +var transaction; +var metadata; +var index; +var query; +var entity; + +var Transaction = concepts.Transaction; +var Metadata = concepts.Metadata; +var Index = concepts.Index; +var Entity = concepts.Entity; +var Query = concepts.Query; + +test.before(function () { + var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples'; + transaction = new Transaction(projectId); + metadata = new Metadata(projectId); + index = new Index(projectId); + entity = new Entity(projectId); + query = new Query(projectId); +}); + +test.after.cb(function (t) { + var datastore = transaction.datastore; + var query = datastore.createQuery('Task'); + + testUtil.deleteEntities(datastore, query, t.end); +}); + +// Transactions + +test.cb.serial('performs a transactional update', function (t) { + transaction.testTransactionalUpdate(t.end); +}); + +test.cb.serial('performs retries if necessary', function (t) { + transaction.testTransactionalRetry(t.end); +}); + +test.cb.serial('performs a get or create', function (t) { + transaction.testTransactionalGetOrCreate(t.end); +}); + +test.cb.serial('gets a snapshot of task list entities', function (t) { + transaction.testSingleEntityGroupReadOnly(t.end); +}); + +// Metadata + +test.cb('performs a namespace query', function (t) { + metadata.testNamespaceRunQuery(t.end); +}); + +test.cb('performs a kind query', function (t) { + metadata.testKindRunQuery(t.end); +}); + +test.cb('performs a property query', function (t) { + metadata.testPropertyRunQuery(t.end); +}); + +test.cb('performs a property by kind query', function (t) { + metadata.testPropertyByKindRunQuery(t.end); +}); + +// Indexes + +test.cb.serial( + 'performs a query with a filter on an unindexed property', + function (t) { + index.testUnindexedPropertyQuery(t.end); + } +); + +test.cb.serial('inserts arrays of data', function (t) { + index.testExplodingProperties(t.end); +}); + +// Queries + +test.cb.serial('performs a basic query', function (t) { + query.testRunQuery(t.end); +}); + +test.cb.serial('performs a query with a property filter', function (t) { + query.testPropertyFilter(t.end); +}); + +test.cb.serial('performs a query with a composite filter', function (t) { + query.testCompositeFilter(t.end); +}); + +test.cb.serial('performs a query with a key filter', function (t) { + query.testKeyFilter(t.end); +}); + +test.cb.serial('performs a query with ascending sort', function (t) { + query.testAscendingSort(t.end); +}); + +test.cb.serial('performs a query with descending sort', function (t) { + query.testDescendingSort(t.end); +}); + +test.cb.serial('performs a query with multi sort', function (t) { + query.testMultiSort(t.end); +}); + +test.cb.serial('performs a kindless query', function (t) { + query.testKindlessQuery(t.end); +}); + +test.cb.serial('performs a projection query', function (t) { + entity.testProperties(function (err, tasks) { + console.log(err, tasks); + t.ifError(err); + setTimeout(function () { + query.testRunQueryProjection(t.end); + }, 1000); + }); +}); + +test.cb.serial('performs a keys only query', function (t) { + query.testKeysOnlyQuery(t.end); +}); + +test.cb.serial('performs a distinct query', function (t) { + query.testDistinctQuery(t.end); +}); + +test.cb.serial('performs a distinct on query', function (t) { + query.testDistinctOnQuery(t.end); +}); + +test.cb.serial('performs an array value inequality query', function (t) { + query.testArrayValueInequalityRange(t.end); +}); + +test.cb.serial('performs an array value equality query', function (t) { + query.testArrayValueEquality(t.end); +}); + +test.cb.serial('performs an inequality range query', function (t) { + query.testInequalityRange(t.end); +}); + +test.cb.serial('returns an error from an invalid query', function (t) { + query.testInequalityInvalid(function (err) { + t.ok(err); + t.end(); + }); +}); + +test.cb.serial('performs an equal and inequality range query', function (t) { + query.testEqualAndInequalityRange(t.end); +}); + +test.cb.serial('performs an equality sort query', function (t) { + query.testInequalitySort(t.end); +}); + +test.cb.serial( + 'returns an error when not sorted on filtered property', + function (t) { + query.testInequalitySortInvalidNotSame(function (err) { + t.ok(err); + t.end(); + }); + } +); + +test.cb.serial( + 'returns an error when not sorted on first filter prop', + function (t) { + query.testInequalitySortInvalidNotFirst(function (err) { + t.ok(err); + t.end(); + }); + } +); + +test.cb.serial('performs a query with a limit', function (t) { + query.testLimit(t.end); +}); + +test.cb.serial('allows manual pagination through results', function (t) { + entity.testBatchUpsert(function (err) { + t.ifError(err); + setTimeout(function () { + query.testCursorPaging(t.end); + }, 1000); + }); +}); + +test.skip('performs an ancestor query', function (t) { + query.testEventualConsistentQuery(t.end); +}); + +// Entities + +test.cb('saves with an incomplete key', function (t) { + entity.testIncompleteKey(t.end); +}); + +test.cb('saves with a named key', function (t) { + entity.testNamedKey(t.end); +}); + +test.cb('saves a key with a parent', function (t) { + entity.testKeyWithParent(t.end); +}); + +test.cb('saves a key with multiple parents', function (t) { + entity.testKeyWithMultiLevelParent(t.end); +}); + +test.cb('saves an entity with a parent', function (t) { + entity.testEntityWithParent(t.end); +}); + +test.cb('saves an entity with properties', function (t) { + entity.testProperties(t.end); +}); + +test.cb('saves an entity with arrays', function (t) { + entity.testArrayValue(t.end); +}); + +test.cb('saves a basic entity', function (t) { + entity.testBasicEntity(t.end); +}); + +test.cb('saves with an upsert', function (t) { + entity.testUpsert(t.end); +}); + +test.cb('saves with an insert', function (t) { + entity.testInsert(t.end); +}); + +test.cb('performs a lookup', function (t) { + entity.testLookup(t.end); +}); + +test.cb('saves with an update', function (t) { + entity.testUpdate(t.end); +}); + +test.cb('deletes an entity', function (t) { + entity.testDelete(t.end); +}); + +test.cb('performs a batch upsert', function (t) { + entity.testBatchUpsert(t.end); +}); + +test.cb('performs a batch lookup', function (t) { + entity.testBatchLookup(t.end); +}); + +test.cb('performs a batch delete', function (t) { + entity.testBatchDelete(t.end); +}); diff --git a/test/datastore/entity.test.js b/test/datastore/entity.test.js deleted file mode 100644 index cf2f50bd1a..0000000000 --- a/test/datastore/entity.test.js +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2015, Google, Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -var testUtil = require('./util.js'); - -var Entity = require('../../datastore/concepts').Entity; -var entity; - -describe('datastore/concepts/entity', function () { - before(function() { - var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples'; - entity = new Entity(projectId); - }); - - after(function(done) { - var datastore = entity.datastore; - var query = datastore.createQuery('Task'); - - testUtil.deleteEntities(datastore, query, done); - }); - - describe('incomplete key', function() { - it('saves with an incomplete key', function(done) { - entity.testIncompleteKey(done); - }); - }); - - describe('testNamedKey', function() { - it('saves with a named key', function(done) { - entity.testNamedKey(done); - }); - }); - - describe('testKeyWithParent', function() { - it('saves a key with a parent', function(done) { - entity.testKeyWithParent(done); - }); - }); - - describe('testKeyWithMultiLevelParent', function() { - it('saves a key with multiple parents', function(done) { - entity.testKeyWithMultiLevelParent(done); - }); - }); - - describe('testEntityWithParent', function() { - it('saves an entity with a parent', function(done) { - entity.testEntityWithParent(done); - }); - }); - - describe('testProperties', function() { - it('saves an entity with properties', function(done) { - entity.testProperties(done); - }); - }); - - describe('testArrayValue', function() { - it('saves an entity with arrays', function(done) { - entity.testArrayValue(done); - }); - }); - - describe('testBasicEntity', function() { - it('saves a basic entity', function(done) { - entity.testBasicEntity(done); - }); - }); - - describe('testUpsert', function() { - it('saves with an upsert', function(done) { - entity.testUpsert(done); - }); - }); - - describe('testInsert', function() { - it('saves with an insert', function(done) { - entity.testInsert(done); - }); - }); - - describe('testLookup', function() { - it('performs a lookup', function(done) { - entity.testLookup(done); - }); - }); - - describe('testUpdate', function() { - it('saves with an update', function(done) { - entity.testUpdate(done); - }); - }); - - describe('testDelete', function() { - it('deletes an entity', function(done) { - entity.testDelete(done); - }); - }); - - describe('testBatchUpsert', function() { - it('performs a batch upsert', function(done) { - entity.testBatchUpsert(done); - }); - }); - - describe('testBatchLookup', function() { - it('performs a batch lookup', function(done) { - entity.testBatchLookup(done); - }); - }); - - describe('testBatchDelete', function() { - it('performs a batch delete', function(done) { - entity.testBatchDelete(done); - }); - }); -}); diff --git a/test/datastore/error.test.js b/test/datastore/error.test.js index 26cf0cb1c6..69f29584d4 100644 --- a/test/datastore/error.test.js +++ b/test/datastore/error.test.js @@ -13,19 +13,13 @@ 'use strict'; +var test = require('ava'); var error = require('../../datastore/error.js'); -var assert = require('assert'); -describe('datastore/error', function () { - it('should have an error', function (done) { - error.runQuery(function (err) { - try { - assert.ok(err); - assert.equal(err.code, 400); - done(); - } catch (err) { - done(err); - } - }); +test.cb.serial('should have an error', function (t) { + error.runQuery(function (err) { + t.ok(err); + t.is(err.code, 400); + t.end(); }); }); diff --git a/test/datastore/indexes.test.js b/test/datastore/indexes.test.js deleted file mode 100644 index b1d8679551..0000000000 --- a/test/datastore/indexes.test.js +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015, Google, Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -var testUtil = require('./util.js'); - -var Index = require('../../datastore/concepts').Index; -var index; - -describe('datastore/concepts/indexes', function () { - before(function() { - var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples'; - index = new Index(projectId); - }); - - after(function(done) { - var datastore = index.datastore; - var query = datastore.createQuery('Task'); - - testUtil.deleteEntities(datastore, query, done); - }); - - describe('unindexed properties', function() { - it('performs a query with a filter on an unindexed property', - function(done) { - index.testUnindexedPropertyQuery(done); - } - ); - }); - - describe('exploding properties', function() { - it('inserts arrays of data', function(done) { - index.testExplodingProperties(done); - }); - }); -}); diff --git a/test/datastore/metadata.test.js b/test/datastore/metadata.test.js deleted file mode 100644 index 6d42faacf4..0000000000 --- a/test/datastore/metadata.test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015, Google, Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -var testUtil = require('./util.js'); - -var Metadata = require('../../datastore/concepts').Metadata; -var metadata; - -describe('datastore/concepts/metadata', function () { - before(function() { - var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples'; - metadata = new Metadata(projectId); - }); - - after(function(done) { - var datastore = metadata.datastore; - var query = datastore.createQuery('Task'); - - testUtil.deleteEntities(datastore, query, done); - }); - - describe('namespace query', function() { - it('performs a namespace query', function(done) { - metadata.testNamespaceRunQuery(done); - }); - }); - - describe('kinds query', function() { - it('performs a kind query', function(done) { - metadata.testKindRunQuery(done); - }); - }); - - describe('property query', function() { - it('performs a property query', function(done) { - metadata.testPropertyRunQuery(done); - }); - }); - - describe('property by kind query', function() { - it('performs a property by kind query', function(done) { - metadata.testPropertyByKindRunQuery(done); - }); - }); -}); diff --git a/test/datastore/query.test.js b/test/datastore/query.test.js deleted file mode 100644 index bf2b1aa6c0..0000000000 --- a/test/datastore/query.test.js +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2015, Google, Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -var assert = require('assert'); - -var concepts = require('../../datastore/concepts.js'); -var testUtil = require('./util.js'); - -var query; -var entity; - -describe('datastore/concepts/query', function () { - before(function() { - var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples'; - entity = new concepts.Entity(projectId); - query = new concepts.Query(projectId); - }); - - after(function(done) { - var datastore = query.datastore; - var q = datastore.createQuery('Task'); - - testUtil.deleteEntities(datastore, q, done); - }); - - describe('basic query', function() { - it('performs a basic query', function(done) { - query.testRunQuery(done); - }); - }); - - describe('property filter', function() { - it('performs a query with a property filter', function(done) { - query.testPropertyFilter(done); - }); - }); - - describe('composite filter', function() { - it('performs a query with a composite filter', function(done) { - query.testCompositeFilter(done); - }); - }); - - describe('key filter', function() { - it('performs a query with a key filter', function(done) { - query.testKeyFilter(done); - }); - }); - - describe('ascending sort', function() { - it('performs a query with ascending sort', function(done) { - query.testAscendingSort(done); - }); - }); - - describe('descending sort', function() { - it('performs a query with descending sort', function(done) { - query.testDescendingSort(done); - }); - }); - - describe('multi sort', function() { - it('performs a query with multi sort', function(done) { - query.testMultiSort(done); - }); - }); - - describe('kindless query', function() { - it('performs a kindless query', function(done) { - query.testKindlessQuery(done); - }); - }); - - describe('projection query', function() { - before(function(done) { - entity.testProperties(done); - }); - - it('performs a projection query', function(done) { - query.testRunQueryProjection(done); - }); - }); - - describe('keys only query', function() { - it('performs a keys only query', function(done) { - query.testKeysOnlyQuery(done); - }); - }); - - describe('distinct query', function() { - it('performs a distinct query', function(done) { - query.testDistinctQuery(done); - }); - }); - - describe('distinct on query', function() { - it('performs a distinct on query', function(done) { - query.testDistinctOnQuery(done); - }); - }); - - describe('array value inequality range', function() { - it('performs an array value inequality query', function(done) { - query.testArrayValueInequalityRange(done); - }); - }); - - describe('array value equality', function() { - it('performs an array value equality query', function(done) { - query.testArrayValueEquality(done); - }); - }); - - describe('inequality range', function() { - it('performs an inequality range query', function(done) { - query.testInequalityRange(done); - }); - }); - - describe('inequality invalid', function() { - it('returns an error from an invalid query', function(done) { - query.testInequalityInvalid(function(err) { - assert.notStrictEqual(err, null); - done(); - }); - }); - }); - - describe('equal and inequality range', function() { - it('performs an equal and inequality range query', function(done) { - query.testEqualAndInequalityRange(done); - }); - }); - - describe('inequality sort', function() { - it('performs an equality sort query', function(done) { - query.testInequalitySort(done); - }); - }); - - describe('inequality sort invalid', function() { - it('returns an error when not sorted on filtered property', function(done) { - query.testInequalitySortInvalidNotSame(function(err) { - assert.notStrictEqual(err, null); - done(); - }); - }); - - it('returns an error when not sorted on first filter prop', function(done) { - query.testInequalitySortInvalidNotFirst(function(err) { - assert.notStrictEqual(err, null); - done(); - }); - }); - }); - - describe('limit query', function() { - it('performs a query with a limit', function(done) { - query.testLimit(done); - }); - }); - - describe('cursor paging', function() { - before(function(done) { - entity.testBatchUpsert(done); - }); - - it('allows manual pagination through results', function(done) { - query.testCursorPaging(done); - }); - }); - - describe.skip('eventually consistent query', function() { - it('performs an ancestor query', function(done) { - query.testEventualConsistentQuery(done); - }); - }); -}); diff --git a/test/datastore/tasks.test.js b/test/datastore/tasks.test.js index 006fc0fa8e..be8eadd9db 100644 --- a/test/datastore/tasks.test.js +++ b/test/datastore/tasks.test.js @@ -13,82 +13,56 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); var async = require('async'); var tasks = require('../../datastore/tasks.js'); var taskIds = []; -describe('datastore/tasks/', function() { - - after(function (done) { - async.parallel(taskIds.map(function(taskId) { - return function (cb) { - tasks.deleteEntity(taskId, cb); - }; - }), done); - }); +test.after.cb(function (t) { + async.parallel(taskIds.map(function (taskId) { + return function (cb) { + tasks.deleteEntity(taskId, cb); + }; + }), t.end); +}); - describe('adding an entity', function() { - it('should add a task', function(done) { - getTaskId(done); - }); - }); +test.cb.serial('should add a task', function (t) { + getTaskId(t.end); +}); - describe('updating an entity', function() { - it('should mark a task as done', function(done) { - getTaskId(function (err, taskId) { - if (err) { - return done(err); - } - tasks.updateEntity(taskId, done); - }); - }); +test.cb.serial('should mark a task as done', function (t) { + getTaskId(function (err, taskId) { + t.ifError(err); + tasks.updateEntity(taskId, t.end); }); +}); - describe('retrieving entities', function() { - it('should list tasks', function(done) { - tasks.retrieveEntities(done); - }); - }); +test.cb.serial('should list tasks', function (t) { + tasks.retrieveEntities(t.end); +}); - describe('deleting an entity', function() { - it('should delete a task', function(done) { - getTaskId(function (err, taskId) { - if (err) { - return done(err); - } - tasks.deleteEntity(taskId, done); - }); - }); +test.cb.serial('should delete a task', function (t) { + getTaskId(function (err, taskId) { + t.ifError(err); + tasks.deleteEntity(taskId, t.end); }); +}); - describe('formatting results', function() { - it('should format tasks', function(done) { - tasks.retrieveEntities(function(err, _tasks) { - if (err) { - done(err); - return; - } - - try { - assert.doesNotThrow(function() { - tasks.formatTasks(_tasks); - }); - done(); - } catch (err) { - done(err); - } - }); +test.cb.serial('should format tasks', function (t) { + tasks.retrieveEntities(function (err, _tasks) { + t.ifError(err); + t.notThrows(function () { + tasks.formatTasks(_tasks); }); + t.end(); }); }); function getTaskId(callback) { - tasks.addEntity('description', function(err, taskKey) { + tasks.addEntity('description', function (err, taskKey) { if (err) { - callback(err); - return; + return callback(err); } var taskId = taskKey.path.pop(); diff --git a/test/datastore/transaction.test.js b/test/datastore/transaction.test.js deleted file mode 100644 index 7266095d3b..0000000000 --- a/test/datastore/transaction.test.js +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015, Google, Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -'use strict'; - -var testUtil = require('./util.js'); - -var Transaction = require('../../datastore/concepts').Transaction; -var transaction; - -describe('datastore/concepts/transaction', function () { - before(function() { - var projectId = process.env.GCLOUD_PROJECT || 'nodejs-docs-samples'; - transaction = new Transaction(projectId); - }); - - after(function(done) { - var datastore = transaction.datastore; - var query = datastore.createQuery('Task'); - - testUtil.deleteEntities(datastore, query, done); - }); - - describe('update', function() { - it('performs a transactional update', function(done) { - transaction.testTransactionalUpdate(done); - }); - }); - - describe('retry', function() { - it('performs retries if necessary', function(done) { - transaction.testTransactionalRetry(done); - }); - }); - - describe('getOrCreate', function() { - it('performs a get or create', function(done) { - transaction.testTransactionalGetOrCreate(done); - }); - }); - - describe('single entity group read only', function() { - it('gets a snapshot of task list entities', function(done) { - transaction.testSingleEntityGroupReadOnly(done); - }); - }); -}); diff --git a/test/datastore/util.js b/test/datastore/util.js index 0b01e787af..ffe512f544 100644 --- a/test/datastore/util.js +++ b/test/datastore/util.js @@ -17,8 +17,7 @@ module.exports = { deleteEntities: function(datastore, query, callback) { datastore.runQuery(query, function(err, entities) { if (err) { - callback(err); - return; + return callback(err); } var keys = entities.map(function(entity) { diff --git a/test/functions/helloworld.test.js b/test/functions/helloworld.test.js index 0482d0f3da..3d3ddfdc52 100644 --- a/test/functions/helloworld.test.js +++ b/test/functions/helloworld.test.js @@ -13,21 +13,14 @@ 'use strict'; -var assert = require('assert'); - +var test = require('ava'); var helloworldSample = require('../../functions/helloworld'); -describe('functions/helloworld', function () { - it('should return a hello world message', function (done) { - helloworldSample.helloworld({ - success: function (result) { - try { - assert.equal(result, 'Hello World!'); - done(); - } catch (err) { - done(err); - } - } - }); +test.cb('should return a hello world message', function (t) { + helloworldSample.helloworld({ + success: function (result) { + t.is(result, 'Hello World!'); + t.end(); + } }); }); diff --git a/test/functions/log.test.js b/test/functions/log.test.js index 458f07f431..14e6ee53fa 100644 --- a/test/functions/log.test.js +++ b/test/functions/log.test.js @@ -13,86 +13,63 @@ 'use strict'; -var assert = require('assert'); - +var test = require('ava'); var logSample = require('../../functions/log'); -describe('functions/log', function () { - it('should write to log', function (done) { - var logMessage = 'I am a log entry!'; - var messageWasPrinted = false; - var originalLog = console.log; +test.cb('should write to log', function (t) { + var logMessage = 'I am a log entry!'; + var messageWasPrinted = false; - console.log = function (data) { - if (data === logMessage) { - messageWasPrinted = true; - } - }; + console.log = function (data) { + if (data === logMessage) { + messageWasPrinted = true; + } + }; - logSample.log({ - success: function (result) { - try { - assert.equal(result, undefined); - if (messageWasPrinted) { - console.log = originalLog; - done(); - } else { - console.log = originalLog; - done('message was not printed!'); - } - } catch (err) { - console.log = originalLog; - done(err); - } + logSample.log({ + success: function (result) { + t.is(result, undefined); + if (messageWasPrinted) { + t.end(); + } else { + t.end('message was not printed!'); } - }); + } }); - it('should write to log 2', function (done) { - var logMessage = 'My GCF Function: foo'; - var messageWasPrinted = false; - var originalLog = console.log; +}); +test.cb('should write to log 2', function (t) { + var logMessage = 'My GCF Function: foo'; + var messageWasPrinted = false; - console.log = function (data) { - if (data === logMessage) { - messageWasPrinted = true; - } - }; + console.log = function (data) { + if (data === logMessage) { + messageWasPrinted = true; + } + }; - logSample.helloworld({ - success: function (result) { - try { - assert.equal(result, undefined); - if (messageWasPrinted) { - console.log = originalLog; - done(); - } else { - console.log = originalLog; - done('message was not printed!'); - } - } catch (err) { - console.log = originalLog; - done(err); - } + logSample.helloworld({ + success: function (result) { + t.is(result, undefined); + if (messageWasPrinted) { + t.end(); + } else { + t.end('message was not printed!'); } - }, - { - message: 'foo' - }); + } + }, + { + message: 'foo' }); - it('should write to log 3', function (done) { - var logMessage = 'My GCF Function: foo'; - logSample.hellohttp({ - success: function (result) { - try { - assert.equal(result, logMessage); - done(); - } catch (err) { - done(err); - } - } - }, - { - message: 'foo' - }); +}); +test.cb('should write to log 3', function (t) { + var logMessage = 'My GCF Function: foo'; + logSample.hellohttp({ + success: function (result) { + t.is(result, logMessage); + t.end(); + } + }, + { + message: 'foo' }); }); diff --git a/test/functions/message.test.js b/test/functions/message.test.js index 667fde0918..51351a9324 100644 --- a/test/functions/message.test.js +++ b/test/functions/message.test.js @@ -13,52 +13,37 @@ 'use strict'; -var assert = require('assert'); - +var test = require('ava'); var messageSample = require('../../functions/message'); -describe('functions/message', function () { - it('should print a message', function (done) { - var testMessage = 'test message'; - var messageWasPrinted = false; - var originalLog = console.log; +test.cb('should print a message', function (t) { + var testMessage = 'test message'; + var messageWasPrinted = false; - console.log = function (data) { - if (data === testMessage) { - messageWasPrinted = true; - } - }; + console.log = function (data) { + if (data === testMessage) { + messageWasPrinted = true; + } + }; - messageSample.helloworld({ - success: function (result) { - try { - assert.equal(result, undefined); - if (messageWasPrinted) { - console.log = originalLog; - done(); - } else { - console.log = originalLog; - done('message was not printed!'); - } - } catch (err) { - console.log = originalLog; - done(err); - } + messageSample.helloworld({ + success: function (result) { + t.is(result, undefined); + if (messageWasPrinted) { + t.end(); + } else { + t.end('message was not printed!'); } - }, { - message: testMessage - }); - }); - it('should say no message was providied', function (done) { - messageSample.helloworld({ - failure: function (result) { - try { - assert.equal(result, 'No message defined!'); - done(); - } catch (err) { - done(err); - } - } - }, {}); + } + }, { + message: testMessage }); }); +test.cb('should say no message was providied', function (t) { + messageSample.helloworld({ + failure: function (result) { + t.is(result, 'No message defined!'); + t.end(); + } + }, {}); +}); diff --git a/test/functions/module.test.js b/test/functions/module.test.js index 95b17006f8..64c7343389 100644 --- a/test/functions/module.test.js +++ b/test/functions/module.test.js @@ -13,21 +13,14 @@ 'use strict'; -var assert = require('assert'); - +var test = require('ava'); var moduleSample = require('../../functions/module'); -describe('functions/module', function () { - it('should return a hello world message', function (done) { - moduleSample.helloworld({ - success: function (result) { - try { - assert.equal(result, 'Hello World!'); - done(); - } catch (err) { - done(err); - } - } - }); +test.cb('should return a hello world message', function (t) { + moduleSample.helloworld({ + success: function (result) { + t.is(result, 'Hello World!'); + t.end(); + } }); }); diff --git a/test/functions/uuid.test.js b/test/functions/uuid.test.js index ea4c9c1e56..fc25effab4 100644 --- a/test/functions/uuid.test.js +++ b/test/functions/uuid.test.js @@ -13,22 +13,15 @@ 'use strict'; -var assert = require('assert'); - +var test = require('ava'); var uuidSample = require('../../functions/uuid'); -describe('functions/uuid', function () { - it('should generate a uuid', function (done) { - uuidSample.uuid({ - success: function (uuid) { - try { - assert.equal(typeof uuid, 'string'); - assert.equal(uuid.length, 36); - done(); - } catch (err) { - done(err); - } - } - }); +test.cb('should generate a uuid', function (t) { + uuidSample.uuid({ + success: function (uuid) { + t.is(typeof uuid, 'string'); + t.is(uuid.length, 36); + t.end(); + } }); }); diff --git a/test/logging/export.test.js b/test/logging/export.test.js index 990babb524..f15d50c6b8 100644 --- a/test/logging/export.test.js +++ b/test/logging/export.test.js @@ -13,18 +13,14 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); +var exportExample = require('../../logging/export'); -var logging = require('../../logging/export'); - -describe('logging/export', function () { - it('should list sinks', function (done) { - logging.runExample(function (err, sinks) { - if (err) { - return done(err); - } - assert.ok(Array.isArray(sinks), 'should be an array'); - done(); - }); +test.cb('should list sinks', function (t) { + exportExample.main(function (err, sinks) { + t.ifError(err); + t.ok(sinks, 'should have received sinks'); + t.ok(Array.isArray(sinks), 'sinks should be an array'); + t.end(); }); }); diff --git a/test/logging/list.test.js b/test/logging/list.test.js index 030c1ff9d4..5a89ec8a70 100644 --- a/test/logging/list.test.js +++ b/test/logging/list.test.js @@ -13,27 +13,16 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); +var listExample = require('../../logging/list'); -var logging = require('../../logging/list'); - -describe('logging/list', function () { - it('should list entries', function (done) { - logging.runExample(function (err, entries, apiResponse) { - if (err) { - return done(err); - } - assert.ok(Array.isArray(entries), 'should have got an array'); - assert.ok(apiResponse.orderBy); - assert.ok(apiResponse.pageSize); - assert.ok(Array.isArray(apiResponse.projectIds)); - if (entries.length === 3) { - // obviously this will pass - assert.equal(entries.length, 3, 'should have three entries'); - } else { - console.error('Received correct apiResponse, but no logs. Why not?'); - } - done(); - }); +test.cb('should list entries', function (t) { + listExample.main(undefined, function (err, entries, nextQuery, apiResponse) { + t.ifError(err); + t.ok(entries, 'should have received entries'); + t.ok(Array.isArray(entries), 'entries should be an array'); + t.ok(nextQuery, 'should have received nextQuery'); + t.ok(apiResponse, 'should have received apiResponse'); + t.end(); }); }); diff --git a/test/logging/write.test.js b/test/logging/write.test.js index 877267bd75..95a094148f 100644 --- a/test/logging/write.test.js +++ b/test/logging/write.test.js @@ -13,24 +13,16 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); +var writeExample = require('../../logging/write'); -var logging = require('../../logging/write'); - -describe('logging/write', function () { - it('should write entries', function (done) { - logging.runExample(function (err, result) { - if (err) { - return done(err); - } - try { - assert.equal(result.length, 2, 'should have two results'); - assert.deepEqual(result[0], {}, 'should have correct response'); - assert.deepEqual(result[1], {}, 'should have correct response'); - done(); - } catch (err) { - return done(err); - } - }); +test.cb('should write entries', function (t) { + writeExample.main(function (err, results) { + if (err && err.code === 404) { + return t.end(); + } + t.ifError(err); + t.is(results.length, 2, 'should have two results'); + t.end(); }); }); diff --git a/test/monitoring/create_custom_metric.test.js b/test/monitoring/create_custom_metric.test.js index 83a5092a2d..ebb3dca88d 100644 --- a/test/monitoring/create_custom_metric.test.js +++ b/test/monitoring/create_custom_metric.test.js @@ -13,7 +13,7 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); var customMetricsExample = require('../../monitoring/create_custom_metric'); /** Refactored out to keep lines shorter */ @@ -21,24 +21,23 @@ function getPointValue(timeSeries) { return timeSeries.timeSeries[0].points[0].value.int64Value; } -it('should create and read back a custom metric', function (done) { - this.timeout(20000); +test.cb('should create and read back a custom metric', function (t) { customMetricsExample.main( process.env.GCLOUD_PROJECT, Math.random().toString(36).substring(7), function (err, results) { - assert.ifError(err); - assert.equal(results.length, 4); + t.ifError(err); + t.is(results.length, 4); // Result of creating metric - assert.ok(typeof results[0].name === 'string'); + t.ok(typeof results[0].name === 'string'); // Result of writing time series - assert.deepEqual(results[1], {}); + t.same(results[1], {}); // Result of reading time series - assert.ok(typeof getPointValue(results[2]) === 'string'); - assert.ok(!isNaN(parseInt(getPointValue(results[2]), 10))); + t.ok(typeof getPointValue(results[2]) === 'string'); + t.ok(!isNaN(parseInt(getPointValue(results[2]), 10))); // Result of deleting metric - assert.deepEqual(results[3], {}); - done(); + t.same(results[3], {}); + t.end(); } ); }); diff --git a/test/monitoring/list_resources.test.js b/test/monitoring/list_resources.test.js index b610dcc61a..b57e38b02b 100644 --- a/test/monitoring/list_resources.test.js +++ b/test/monitoring/list_resources.test.js @@ -13,23 +13,22 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); var listResourcesExample = require('../../monitoring/list_resources'); -it('should list a bunch of stuff', function (done) { - this.timeout(20000); +test.cb('should list a bunch of stuff', function (t) { listResourcesExample.main( process.env.GCLOUD_PROJECT, function (err, results) { - assert.ifError(err); - assert.equal(results.length, 3); + t.ifError(err); + t.is(results.length, 3); // Monitored resources - assert.ok(Array.isArray(results[0].resourceDescriptors)); + t.ok(Array.isArray(results[0].resourceDescriptors)); // Metric descriptors - assert.ok(Array.isArray(results[1].metricDescriptors)); + t.ok(Array.isArray(results[1].metricDescriptors)); // Time series - assert.ok(Array.isArray(results[2].timeSeries)); - done(); + t.ok(Array.isArray(results[2].timeSeries)); + t.end(); } ); }); diff --git a/test/prediction/hostedmodels.test.js b/test/prediction/hostedmodels.test.js index bc3c2dd0cf..a874393491 100644 --- a/test/prediction/hostedmodels.test.js +++ b/test/prediction/hostedmodels.test.js @@ -13,31 +13,13 @@ 'use strict'; -var assert = require('assert'); +var test = require('ava'); var hostedmodels = require('../../prediction/hostedmodels'); -var EXPECTED_RESULT = { - kind: 'prediction#output', - id: 'sample.sentiment', - selfLink: 'https://www.googleapis.com/prediction/v1.6/projects/414649711441' + - '/hostedmodels/sample.sentiment/predict', - outputLabel: 'positive', - outputMulti: [ - { label: 'positive', score: '0.784671' }, - { label: 'negative', score: '0.186649' }, - { label: 'neutral', score: '0.028680' } - ] -}; - -describe('prediction/hostedmodels', function () { - it('should predict', function (done) { - this.timeout(30000); - hostedmodels.predict(function (err, result) { - if (err) { - return done(err); - } - assert.deepEqual(result, EXPECTED_RESULT); - done(); - }); +test.cb('should predict', function (t) { + hostedmodels.main('good night', function (err, result) { + t.ifError(err); + t.ok(result); + t.end(); }); }); diff --git a/test/pubsub/iam.test.js b/test/pubsub/iam.test.js index 817f409428..bc58d74886 100644 --- a/test/pubsub/iam.test.js +++ b/test/pubsub/iam.test.js @@ -13,51 +13,29 @@ 'use strict'; -var assert = require('assert'); -var projectId = process.env.GCLOUD_PROJECT; - +var test = require('ava'); var iamSample = require('../../pubsub/iam'); -describe('pubsub/iam', function () { - it('should run the sample', function (done) { - this.timeout(30000); - iamSample.runSample(function (err, responses) { - try { - assert.ok(!err); - // topic - var expectedTopic = 'projects/' + projectId + '/topics/messageCenter'; - assert.equal(responses[0][0].name, expectedTopic); - assert.ok(responses[0][0].iam); - // apiResponse - assert.ok(responses[0][1]); - // policy - assert.deepEqual(responses[1][0], { etag: 'ACAB' }); - // permissions - assert.deepEqual(responses[2][0], { - 'pubsub.topics.attachSubscription': true, - 'pubsub.topics.publish': true, - 'pubsub.topics.update': true - }); - // apiResponse - assert.ok(responses[2][1]); - // subscription - assert.ok(responses[3][0].on); - assert.ok(responses[3][0].iam); - // apiResponse - assert.ok(responses[3][1]); - // policy - assert.deepEqual(responses[4][0], { etag: 'ACAB' }); - // permissions - assert.deepEqual(responses[5][0], { - 'pubsub.subscriptions.consume': true, - 'pubsub.subscriptions.update': true - }); - // apiResponse - assert.ok(responses[5][1]); - done(); - } catch (err) { - done(err); - } - }); +test.cb('should run the sample', function (t) { + iamSample.main(function (err, results) { + t.ifError(err); + t.is(results.length, 8); + // Got topic and apiResponse + t.is(results[0].length, 2); + // Got policy and apiResponse + t.is(results[1].length, 2); + // Got permissions and apiResponse + t.is(results[2].length, 2); + // Got subscription and apiResponse + t.is(results[3].length, 2); + // Got policy and apiResponse + t.is(results[4].length, 2); + // Got permissions and apiResponse + t.is(results[5].length, 2); + // Got empty apiResponse + t.same(results[6], {}); + // Got empty apiResponse + t.same(results[7], {}); + t.end(); }); }); diff --git a/test/pubsub/subscription.test.js b/test/pubsub/subscription.test.js index 72289d069a..6f03cc2727 100644 --- a/test/pubsub/subscription.test.js +++ b/test/pubsub/subscription.test.js @@ -13,51 +13,29 @@ 'use strict'; -var assert = require('assert'); -var projectId = process.env.GCLOUD_PROJECT; - +var test = require('ava'); var subscriptionSample = require('../../pubsub/subscription'); -describe('pubsub/subscription', function () { - it('should run the sample', function (done) { - this.timeout(30000); - subscriptionSample.runSample(function (err, responses) { - try { - assert.ok(!err); - // topic - var expectedTopic = 'projects/' + projectId + '/topics/messageCenter'; - assert.equal(responses[0][0].name, expectedTopic); - assert.ok(responses[0][0].iam); - // apiResponse - assert.ok(responses[0][1]); - // subscription - assert.ok(responses[1][0].on); - assert.ok(responses[1][0].iam); - // apiResponse - assert.ok(responses[1][1]); - // topics - var foundExpectedTopic = false; - responses[2][0].forEach(function (topic) { - if (topic.name === expectedTopic) { - foundExpectedTopic = true; - return false; - } - }); - assert.ok(foundExpectedTopic, 'topic should have been created!'); - assert.ok(responses[2][0][0].iam); - // subscriptions - assert.ok(responses[3][0][0].on); - assert.ok(responses[3][0][0].iam); - // messageIds - assert.ok(typeof responses[4][0][0] === 'string'); - // apiResponse - assert.ok(responses[4][1]); - // messages - assert.equal(responses[5][0][0].data, 'Hello, world!'); - done(); - } catch (err) { - done(err); - } - }); +test.cb('should run the sample', function (t) { + subscriptionSample.main(function (err, results) { + t.ifError(err); + t.is(results.length, 8); + // Got topic and apiResponse + t.is(results[0].length, 2); + // Got subscription and apiResponse + t.is(results[1].length, 2); + // Got array of topics + t.ok(Array.isArray(results[2])); + // Got array of subscriptions + t.ok(Array.isArray(results[3])); + // Got messageIds and apiResponse + t.is(results[4].length, 2); + // Got array of messages + t.ok(Array.isArray(results[5])); + // Got empty apiResponse + t.same(results[6], {}); + // Got empty apiResponse + t.same(results[7], {}); + t.end(); }); }); diff --git a/test/storage/authSample.test.js b/test/storage/authSample.test.js index 2078e54461..b64337ea0e 100644 --- a/test/storage/authSample.test.js +++ b/test/storage/authSample.test.js @@ -16,28 +16,19 @@ */ 'use strict'; -var assert = require('assert'); -var authSample = require('../../storage/authSample'); +var test = require('ava'); +var authSampleExample = require('../../storage/authSample'); var projectId = process.env.GCLOUD_PROJECT; -describe('listBuckets', function () { +test.cb('should return a list of buckets', function (t) { + var bucketName = process.env.TEST_BUCKET_NAME || 'nodejs-docs-samples'; - it('should return a list of buckets', function (done) { - var bucketName = process.env.TEST_BUCKET_NAME || 'nodejs-docs-samples'; - - authSample.runExample( - projectId, - function (err, response) { - if (err) { - return done(err); - } else { - assert(response.items.length > 0, 'There should be some buckets.'); - assert.equal(response.items.filter(function (item) { - return item.name === bucketName; - }).length, 1, 'There should be a bucket named ' + bucketName); - return done(); - } - } - ); + authSampleExample.main(projectId, function (err, response) { + t.ifError(err); + t.ok(response.items.length > 0, 'There should be some buckets.'); + t.is(response.items.filter(function (item) { + return item.name === bucketName; + }).length, 1, 'There should be a bucket named ' + bucketName); + t.end(); }); });