From 13bb1b84d23bc11ea755bc6a9b77c99756eceaa7 Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Mon, 25 May 2015 15:44:34 -0400 Subject: [PATCH 1/2] add doc examples to test suite --- lib/bigquery/dataset.js | 2 + lib/bigquery/index.js | 2 +- lib/bigquery/job.js | 4 +- lib/bigquery/table.js | 17 ++++-- lib/datastore/dataset.js | 10 +++- lib/datastore/entity.js | 2 +- lib/datastore/index.js | 8 +-- lib/datastore/query.js | 8 +-- lib/datastore/request.js | 41 +++++++------- lib/datastore/transaction.js | 50 +++++++++-------- lib/pubsub/index.js | 1 - lib/pubsub/subscription.js | 2 +- lib/storage/acl.js | 4 +- lib/storage/bucket.js | 20 +++---- lib/storage/file.js | 2 +- lib/storage/index.js | 8 +-- package.json | 4 +- scripts/build.sh | 1 + scripts/docs.sh | 2 - test/common/docs.js | 102 ++++++++++++++++++++++++++++++++++ test/datastore/dataset.js | 10 ++-- test/datastore/request.js | 19 +++++++ test/datastore/transaction.js | 26 ++++----- test/testdata/testfile.json | 0 24 files changed, 240 insertions(+), 105 deletions(-) create mode 100644 test/common/docs.js create mode 100644 test/testdata/testfile.json diff --git a/lib/bigquery/dataset.js b/lib/bigquery/dataset.js index f6d2f936833..f6ce3918700 100644 --- a/lib/bigquery/dataset.js +++ b/lib/bigquery/dataset.js @@ -73,6 +73,8 @@ function Dataset(bigQuery, id) { * schema: 'UNITID,INSTNM,ADDR,CITY,STABBR,ZIP,FIPS,OBEREG,CHFNM,...' * }; * + * var bigquery = gcloud.bigquery(); + * var dataset = bigquery.dataset(); * dataset.createTable(tableConfig, function(err, table, apiResponse) {}); */ Dataset.prototype.createTable = function(options, callback) { diff --git a/lib/bigquery/index.js b/lib/bigquery/index.js index 67a3c25d85b..dd4c3d57372 100644 --- a/lib/bigquery/index.js +++ b/lib/bigquery/index.js @@ -77,7 +77,7 @@ var SCOPES = ['https://www.googleapis.com/auth/bigquery']; * projectId: 'my-project' * }); * - * var bigquery = myProject.bigquery(); + * var bigquery = gcloud.bigquery(); * * //- * // In the following examples from this page and the other modules (Dataset, diff --git a/lib/bigquery/job.js b/lib/bigquery/job.js index 6de6a218a8c..8b063f0a580 100644 --- a/lib/bigquery/job.js +++ b/lib/bigquery/job.js @@ -62,6 +62,7 @@ function Job(bigQuery, id) { * @param {function} callback - The callback function. * * @example + * var job = bigquery.job('id'); * job.getMetadata(function(err, metadata, apiResponse) {}); */ Job.prototype.getMetadata = function(callback) { @@ -117,12 +118,13 @@ Job.prototype.getMetadata = function(callback) { * // Consume the results from the query as a readable stream. * //- * var through2 = require('through2'); + * var fs = require('fs'); * * job.getQueryResults(options) * .pipe(through2.obj(function (row, enc, next) { * this.push(JSON.stringify(row) + '\n'); * })) - * .pipe(fs.createWriteStream('./backup.json')); + * .pipe(fs.createWriteStream('./test/testdata/testfile.json')); */ Job.prototype.getQueryResults = function(options, callback) { if (util.is(options, 'function')) { diff --git a/lib/bigquery/table.js b/lib/bigquery/table.js index 21ea4ad1493..0bb04877cd0 100644 --- a/lib/bigquery/table.js +++ b/lib/bigquery/table.js @@ -52,6 +52,9 @@ var util = require('../common/util'); * * @alias module:bigquery/table * @constructor + * + * @example + * var table = dataset.table('my-table'); */ function Table(dataset, id) { this.bigQuery = dataset.bigQuery; @@ -124,7 +127,8 @@ Table.mergeSchemaWithRows_ = function(schema, rows) { * @throws {Error} If a destination other than a Table object is provided. * * @example - * table.copy(dataset.table('my-table'), function(err, job, apiResponse) {}); + * var yourTable = dataset.table('your-table'); + * table.copy(yourTable, function(err, job, apiResponse) {}); * * //- * // See the [`configuration.copy`](http://goo.gl/dKWIyS) object for all @@ -135,7 +139,7 @@ Table.mergeSchemaWithRows_ = function(schema, rows) { * writeDisposition: 'WRITE_TRUNCATE' * }; * - * table.copy(options, metadata, function(err, job, apiResponse) {}); + * table.copy(yourTable, metadata, function(err, job, apiResponse) {}); */ Table.prototype.copy = function(destination, metadata, callback) { var that = this; @@ -191,7 +195,7 @@ Table.prototype.copy = function(destination, metadata, callback) { * .pipe(through2.obj(function(row, enc, next) { * this.push(JSON.stringify(row) + '\n'); * })) - * .pipe(fs.createWriteStream('./institutions.json')); + * .pipe(fs.createWriteStream('./test/testdata/testfile.json')); */ Table.prototype.createReadStream = function() { var that = this; @@ -261,7 +265,7 @@ Table.prototype.createReadStream = function() { * //- * var fs = require('fs'); * - * fs.createReadStream('./institutions.json') + * fs.createReadStream('./test/testdata/testfile.json') * .pipe(table.createWriteStream('json')) * .on('complete', function(job) {}); */ @@ -357,6 +361,7 @@ Table.prototype.delete = function(callback) { * @throws {Error} If destination format isn't recongized. * * @example + * var storage = gcloud.storage(); * var exportedFile = storage.bucket('institutions').file('2014.csv'); * * //- @@ -499,7 +504,7 @@ Table.prototype.getMetadata = function(callback) { * if (nextQuery) { * table.getRows(nextQuery, function(err, rows, nextQuery, apiResponse) {}); * } - * });` + * }); */ Table.prototype.getRows = function(options, callback) { var that = this; @@ -585,7 +590,7 @@ Table.prototype.getRows = function(options, callback) { * //- * var metadata = { * encoding: 'ISO-8859-1', - * sourceFormat: 'JSON' + * sourceFormat: 'NEWLINE_DELIMITED_JSON' * }; * * table.import('./my-data.csv', metadata, function(err, job, apiResponse) {}); diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index 2a1a94682ec..9b6b7e02359 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -77,6 +77,7 @@ var SCOPES = [ * @param {string} options.namespace - Namespace to isolate transactions to. * * @example + * var datastore = gcloud.datastore; * var dataset = datastore.dataset({ * projectId: 'my-project', * keyFilename: '/path/to/keyfile.json' @@ -208,7 +209,10 @@ Dataset.prototype.createQuery = function(namespace, kind) { /** * Run a function in the context of a new transaction. Transactions allow you to - * perform multiple operations, committing your changes atomically. + * perform multiple operations, committing your changes atomically. When you are + * finished making your changes within the transaction, run the done() function + * provided in the callback function to commit your changes. See an example + * below for more information. * * @borrows {module:datastore/transaction#begin} as runInTransaction * @@ -232,13 +236,13 @@ Dataset.prototype.createQuery = function(namespace, kind) { Dataset.prototype.runInTransaction = function(fn, callback) { var newTransaction = this.createTransaction_(); - newTransaction.begin(function(err) { + newTransaction.begin_(function(err) { if (err) { callback(err); return; } - fn(newTransaction, newTransaction.commit.bind(newTransaction, callback)); + fn(newTransaction, newTransaction.commit_.bind(newTransaction, callback)); }); }; diff --git a/lib/datastore/entity.js b/lib/datastore/entity.js index adfe1186987..57418778d12 100644 --- a/lib/datastore/entity.js +++ b/lib/datastore/entity.js @@ -411,7 +411,7 @@ function valueToProperty(v) { p.blob_value = v; return p; } - if (v instanceof Array) { + if (Array.isArray(v)) { p.list_value = v.map(function(item) { return valueToProperty(item); }); diff --git a/lib/datastore/index.js b/lib/datastore/index.js index 6adf1db19c7..994c24daa73 100644 --- a/lib/datastore/index.js +++ b/lib/datastore/index.js @@ -41,13 +41,11 @@ var Dataset = require('./dataset'); /*! Developer Documentation * * Invoking the Datastore class allows you to provide configuration up-front. - * This configuration will be used for future invokations of the returned + * This configuration will be used for future invocations of the returned * `dataset` method. * * @example - * var datastore = require('gcloud/lib/datastore')({ - * keyFilename: '/path/to/keyfile.json' - * }); + * var datastore = gcloud.datastore; * * var dataset = datastore.dataset(); * // equal to: @@ -82,7 +80,7 @@ function Datastore(options) { * options. * * @example - * var datastore = require('gcloud/lib/datastore'); + * var datastore = gcloud.datastore; * * // Create a Dataset object. * var dataset = datastore.dataset({ diff --git a/lib/datastore/query.js b/lib/datastore/query.js index d6389a4b543..aa24d7f1dbe 100644 --- a/lib/datastore/query.js +++ b/lib/datastore/query.js @@ -46,13 +46,13 @@ var util = require('../common/util.js'); * @example * // If your dataset was scoped to a namespace at initialization, your query * // will likewise be scoped to that namespace. - * dataset.createQuery('Lion'); + * var query = dataset.createQuery('Lion'); * * // However, you may override the namespace per query. - * dataset.createQuery('AnimalNamespace', 'Lion'); + * var query = dataset.createQuery('AnimalNamespace', 'Lion'); * * // You may also remove the namespace altogether. - * dataset.createQuery(null, 'Lion'); + * var query = dataset.createQuery(null, 'Lion'); */ function Query(namespace, kinds) { if (!kinds) { @@ -91,7 +91,7 @@ function Query(namespace, kinds) { * @example * // List all companies named Google that have less than 400 employees. * var companyQuery = query - * .filter('name =', 'Google'); + * .filter('name =', 'Google') * .filter('size <', 400); * * // To filter by key, use `__key__` for the property name. Filter on keys diff --git a/lib/datastore/request.js b/lib/datastore/request.js index 656aeaaa2ba..9f8257f8147 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -64,11 +64,6 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; * * Creates requests to the Dataset endpoint. Designed to be inherited by * datastore.Dataset and datastore.Transaction objects. - * - * @example - * // Inherit in Dataset and Transaction - * require('util').inherits(Dataset, DatastoreRequest); - * require('util').inherits(Transaction, DatastoreRequest); */ /* * Handle logic for Datastore API operations. @@ -95,10 +90,10 @@ function DatastoreRequest() {} * * // Get a single entity. * var key = dataset.key(['Company', 123]); - * transaction.get(key, function(err, entity, apiResponse) {}); + * dataset.get(key, function(err, entity, apiResponse) {}); * * // Get multiple entities at once. - * transaction.get([ + * dataset.get([ * dataset.key(['Company', 123]), * dataset.key(['Product', 'Computer']) * ], function(err, entities, apiResponse) {}); @@ -258,13 +253,13 @@ DatastoreRequest.prototype.insert = function(entities, callback) { * key: key, * data: { * name: 'DonutShack', // strings - * rating: datastore.int(8), // ints - * worth: datastore.double(123456.78), // doubles + * rating: gcloud.datastore.int(8), // ints + * worth: gcloud.datastore.double(123456.78), // doubles * numDonutsServed: 45, // detect number type (int or double) * founded: new Date('Tue May 12 2015 15:30:00 GMT-0400 (EDT)'), // dates * isStartup: true, // booleans * donutEmoji: new Buffer('\uD83C\uDF69'), // buffers - * keywords: ['donut', 'coffee', 'yum'] // lists of objects + * keywords: [ 'donut', 'coffee', 'yum' ] // lists of objects * } * }, function(err) {}); * @@ -465,17 +460,13 @@ DatastoreRequest.prototype.delete = function(keys, callback) { * stream instance is returned. * * @example - * //- - * // Where you see `transaction`, assume this is the context that's relevant to - * // your use, whether that be a Dataset or a Transaction object. - * //- * * // Retrieve 5 companies. - * transaction.runQuery(query, function(err, entities, endCursor, apiResponse) { + * dataset.runQuery(query, function(err, entities, endCursor, apiResponse) { * // Use `endCursor` as the starting cursor for your next query. * var nextQuery = query.start(endCursor); * var callback = function(err, entities, endCursor, apiResponse) {}; - * transaction.runQuery(nextQuery, callback); + * dataset.runQuery(nextQuery, callback); * }); * * //- @@ -483,7 +474,7 @@ DatastoreRequest.prototype.delete = function(keys, callback) { * // queries until no results remain. Entity objects will be pushed as they are * // found. * //- - * transaction.runQuery(queryObject) + * dataset.runQuery(query) * .on('data', function (entity) {}); */ DatastoreRequest.prototype.runQuery = function(q, callback) { @@ -565,13 +556,15 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * * @example * //- - * // Where you see `transaction`, assume this is the context that's relevant to + * // Where you see `dataset`, assume this is the context that's relevant to * // your use, whether that be a Dataset or a Transaction object. * //- * + * var incompleteKey = dataset.key(['Company']); + * * // The following call will create 100 new IDs from the Company kind, which * // exists under the default namespace. - * transaction.allocateIds(incompleteKey, 100, function(err, keys) {}); + * dataset.allocateIds(incompleteKey, 100, function(err, keys) {}); * * // You may prefer to create IDs from a non-default namespace by providing an * // incomplete key with a namespace. Similar to the previous example, the call @@ -582,7 +575,7 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * path: ['Company'] * }); * var callback = function(err, keys, apiResponse) {}; - * transaction.allocateIds(incompleteKey, 100, callback); + * dataset.allocateIds(incompleteKey, 100, callback); */ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { if (entity.isKeyComplete(incompleteKey)) { @@ -643,7 +636,9 @@ DatastoreRequest.prototype.upsert = function(entities, callback) { * } * }; * var callback = function(err, result, apiResponse) {}; - * transaction.makeReq('commit', deleteRequest, callback); + * var Transaction = require('gcloud/lib/datastore/transaction'); + * var transaction = new Transaction(dataset, 'my-project-id'); + * transaction.makeReq_('commit', deleteRequest, callback); */ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { // TODO: Handle non-HTTP 200 cases. @@ -664,6 +659,10 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { } } + if (method === 'rollback') { + body.transaction = this.id; + } + if (method === 'lookup' && this.id) { body.read_options = body.read_options || {}; body.read_options.transaction = this.id; diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index 888bad2772d..ab4a982218d 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -42,6 +42,14 @@ var extend = require('extend'); * connection to Google Cloud Datastore. * @param {string} projectId - Dataset ID. This is your project ID from the * Google Developers Console. + * + * @example + * // This is how to create a transaction object directly using this Transaction + * // class. The following transaction object is created for use in the examples + * // in this file below. + * var Transaction = require('gcloud/lib/datastore/transaction'); + * var transaction = new Transaction(dataset, 'my-project-id'); + * transaction.id = '1234'; // Give the transaction an ID. */ /** * Build a Transaction object. Transactions will be created for you by @@ -57,7 +65,7 @@ var extend = require('extend'); * @example * dataset.runInTransaction(function(transaction, done) { * // `transaction` is a Transaction object. - * }); + * }, function(err) {}); */ function Transaction(dataset, projectId) { this.id = null; @@ -84,19 +92,14 @@ nodeutil.inherits(Transaction, DatastoreRequest); * @param {function} callback - The function to execute within the context of * a transaction. * + * @private + * * @example - * transaction.begin(function(err) { + * transaction.begin_(function(err) { * // Perform Datastore operations as usual. - * transaction.get(dataset.key(['Company', 123]), function(err, entity) { - * // Commit the transaction. - * transaction.finalize(function(err, apiResponse) {}); - * - * // Rollback the transaction. - * transaction.rollback(function(err, apiResponse) {}); - * }); * }); */ -Transaction.prototype.begin = function(callback) { +Transaction.prototype.begin_ = function(callback) { var that = this; callback = callback || util.noop; @@ -119,12 +122,10 @@ Transaction.prototype.begin = function(callback) { * @param {function} callback - The callback function. * * @example - * transaction.begin(function(err) { - * transaction.rollback(function(err) { - * if (err) { - * // Transaction could not be rolled back. - * } - * }); + * transaction.rollback(function(err) { + * if (err) { + * // Transaction could not be rolled back. + * } * }); */ Transaction.prototype.rollback = function(callback) { @@ -141,19 +142,21 @@ Transaction.prototype.rollback = function(callback) { /** * Commit the remote transaction and finalize the current transaction instance. + * This function is provided as the `done` function in the callback of + * `dataset.runInTransaction(function(transaction, done) {});` * * @param {function} callback - The callback function. * + * @private + * * @example - * transaction.begin(function(err) { - * transaction.commit(function(err, apiResponse) { - * if (err) { - * // Transaction could not be committed. - * } - * }); + * transaction.commit_(function(err, apiResponse) { + * if (err) { + * // Transaction could not be committed. + * } * }); */ -Transaction.prototype.commit = function(callback) { +Transaction.prototype.commit_ = function(callback) { var that = this; callback = callback || util.noop; @@ -341,7 +344,6 @@ Transaction.prototype.delete = function(entities) { * //- * var companyKey = dataset.key(['Company', 123]); * var productKey = dataset.key(['Product', 'Computer']); - * * transaction.save([ * { * key: companyKey, diff --git a/lib/pubsub/index.js b/lib/pubsub/index.js index 0f15df8e8e5..44d332ab957 100644 --- a/lib/pubsub/index.js +++ b/lib/pubsub/index.js @@ -177,7 +177,6 @@ PubSub.prototype.createTopic = function(name, callback) { * @example * var topic = pubsub.topic('my-existing-topic'); * var topic = pubsub.topic('topic-that-maybe-exists', { autoCreate: true }); - * topic.publish('New message!'); */ PubSub.prototype.topic = function(name, options) { if (!name) { diff --git a/lib/pubsub/subscription.js b/lib/pubsub/subscription.js index 0c91730a584..67958e3b893 100644 --- a/lib/pubsub/subscription.js +++ b/lib/pubsub/subscription.js @@ -182,7 +182,7 @@ Subscription.formatMessage_ = function(msg) { * @private * * @example - * this.listenForEvents_(); + * subscription.listenForEvents_(); */ Subscription.prototype.listenForEvents_ = function() { var self = this; diff --git a/lib/storage/acl.js b/lib/storage/acl.js index b2ea0de0ba1..b332eba11c4 100644 --- a/lib/storage/acl.js +++ b/lib/storage/acl.js @@ -102,6 +102,8 @@ function Acl(options) { * //- * // Add a user as an owner of a file. * //- + * var myBucket = storage.bucket('my-bucket'); + * var myFile = myBucket.file('my-file'); * myFile.acl.owners.addUser('email@example.com', function(err, aclObject) {}); * * //- @@ -325,7 +327,7 @@ Acl.prototype.delete = function(options, callback) { * myFile.acl.get({ * entity: 'user-useremail@example.com', * generation: 1 - * } function(err, aclObject, apiResponse) {}); + * }, function(err, aclObject, apiResponse) {}); */ Acl.prototype.get = function(options, callback) { var that = this; diff --git a/lib/storage/bucket.js b/lib/storage/bucket.js index df27542ce94..6dd1508c9be 100644 --- a/lib/storage/bucket.js +++ b/lib/storage/bucket.js @@ -65,7 +65,7 @@ var RESUMABLE_THRESHOLD = 5000000; * @constructor * @alias module:storage/bucket * - * @throws if a bucket name isn't provided. + * @throws {Error} if a bucket name isn't provided. * * @param {object} options - Configuration options. * @param {string} options.bucketName - Name of the bucket. @@ -128,7 +128,7 @@ function Bucket(storage, name) { * //- * myBucket.acl.add({ * scope: 'allUsers', - * permission: storage.acl.READER_ROLE + * role: storage.acl.READER_ROLE * }, function(err, aclObject) {}); */ this.acl = new Acl({ @@ -206,10 +206,10 @@ function Bucket(storage, name) { /** * Combine mutliple files into one new file. * - * @throws if a non-array is provided as sources argument. - * @throws if less than two sources are provided. - * @throws if no destination is provided. - * @throws if a content type cannot be determined for the destination file. + * @throws {Error} if a non-array is provided as sources argument. + * @throws {Error} if less than two sources are provided. + * @throws {Error} if no destination is provided. + * @throws {Error} if content type can't be determined for the destination file. * * @param {string[]|module:storage/file} sources - The source files that will be * combined. @@ -218,14 +218,14 @@ function Bucket(storage, name) { * @param {function=} callback - The callback function. * * @example - * var 2013logs = bucket.file('2013-logs.txt'); - * var 2014logs = bucket.file('2014-logs.txt'); + * var logs2013 = bucket.file('2013-logs.txt'); + * var logs2014 = bucket.file('2014-logs.txt'); * * var allLogs = bucket.file('all-logs.txt'); * * bucket.combine([ - * 2013logs, - * 2014logs + * logs2013, + * logs2014 * ], allLogs, function(err, newFile, apiResponse) { * // newFile === allLogs * }); diff --git a/lib/storage/file.js b/lib/storage/file.js index ba0d74a34c0..5bb55ff7f3a 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -109,7 +109,7 @@ function File(bucket, name, options) { * //- * myFile.acl.add({ * scope: 'allUsers', - * permission: storage.acl.READER_ROLE + * role: storage.acl.READER_ROLE * }, function(err, aclObject) {}); */ this.acl = new Acl({ diff --git a/lib/storage/index.js b/lib/storage/index.js index 80e36bccd83..d4c55d7d2a6 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -74,7 +74,7 @@ var STORAGE_BASE_URL = 'https://www.googleapis.com/storage/v1/b'; * projectId: 'my-project' * }); * - * var storage = myProject.storage(); + * var storage = gcloud.storage(); */ function Storage(options) { if (!(this instanceof Storage)) { @@ -119,7 +119,7 @@ function Storage(options) { * //- * albums.acl.add({ * scope: 'allUsers', - * permission: storage.acl.READER_ROLE + * role: storage.acl.READER_ROLE * }, function(err, aclObject) {}); * * //- @@ -127,7 +127,7 @@ function Storage(options) { * //- * albums.acl.default.add({ * scope: 'allUsers', - * permission: storage.acl.READER_ROLE + * role: storage.acl.READER_ROLE * }, function(err, aclObject) {}); * * //- @@ -136,7 +136,7 @@ function Storage(options) { * * albums.acl.add({ * scope: 'user-useremail@example.com', - * permission: storage.acl.OWNER_ROLE + * role: storage.acl.OWNER_ROLE * }, function(err, aclObject) {}); */ Storage.acl = { diff --git a/package.json b/package.json index 29b193af078..5c2e039d7ed 100644 --- a/package.json +++ b/package.json @@ -67,8 +67,10 @@ "bytebuffer": "^3.5.4", "coveralls": "^2.11.2", "dox": "^0.7.0", + "glob": "^5.0.9", "istanbul": "^0.3.5", "jshint": "^2.6.0", + "mitm": "^1.1.0", "mocha": "^2.1.0", "mockery": "^1.4.0", "tmp": "0.0.24" @@ -76,7 +78,7 @@ "scripts": { "docs": "./scripts/docs.sh", "lint": "jshint lib/ system-test/ test/", - "test": "mocha test/*", + "test": "npm run docs && mocha test/*", "system-test": "mocha system-test/* --timeout 30000", "cover": "istanbul cover -x 'system-test/*' _mocha -- --timeout 30000 test/* system-test/*", "coveralls": "istanbul cover -x 'system-test/*' _mocha --report lcovonly -- --timeout 30000 test/* system-test/* -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage" diff --git a/scripts/build.sh b/scripts/build.sh index 5f6b1b9423f..31f22fd9989 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -17,6 +17,7 @@ set -ev npm run lint +npm run docs npm run test # if merging to master and not a pull request, execute system tests, create coverage report and update docs diff --git a/scripts/docs.sh b/scripts/docs.sh index 7c58f85cb95..b797fa86140 100755 --- a/scripts/docs.sh +++ b/scripts/docs.sh @@ -34,6 +34,4 @@ ./node_modules/.bin/dox < lib/storage/acl.js > docs/json/master/storage/acl.json & ./node_modules/.bin/dox < lib/storage/bucket.js > docs/json/master/storage/bucket.json & ./node_modules/.bin/dox < lib/storage/file.js > docs/json/master/storage/file.json & -./node_modules/.bin/dox < lib/storage/index.js > docs/json/master/storage/index.json & - ./node_modules/.bin/dox < lib/storage/index.js > docs/json/master/storage/index.json diff --git a/test/common/docs.js b/test/common/docs.js new file mode 100644 index 00000000000..8dab7bb9488 --- /dev/null +++ b/test/common/docs.js @@ -0,0 +1,102 @@ +/** + * Copyright 2014 Google Inc. All Rights Reserved. + * + * 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. + */ + +/*global describe, it */ + +'use strict'; + +var vm = require('vm'); +var assert = require('assert'); +var gcloud = require('../../'); +var glob = require('glob'); +var mitm = require('mitm'); +var fs = require('fs'); + +var sandbox = { + gcloud: gcloud, + require: require, + process: process, + Buffer: Buffer, + Date: Date, + Array: Array +}; + +function runCodeInSandbox(code) { + vm.createContext(sandbox); + try { + vm.runInNewContext(code, sandbox, { + filename: 'assert-code.vm', + timeout: 1000 + }); + } catch(err) { + // rethrow the error with code for context and resolving issues faster. + throw new Error('\n' + code + '\n\n' + err.message); + } +} + +describe('documentation', function() { + var MITM; + var FILES; + + before(function(done) { + // Turn off the network so that API calls aren't actually made. + MITM = mitm(); + glob('docs/json/**/*.json', {}, function(err, files) { + assert.ifError(err); + FILES = files; + done(); + }); + }); + + after(function() { + // Re-enable the network. + MITM.disable(); + }); + + it('should run docs examples without errors', function() { + for (var f in FILES) { + var fileDocBlocks = []; + var fileContents = fs.readFileSync(FILES[f], { + encoding: 'utf8' + }); + + try { + fileDocBlocks = JSON.parse(fileContents); + } catch(e) { + throw new Error('Failed to parse one of the doc files (' + e.message + + ')\n\nFilename: ' + FILES[f] + '\n\nFile contents: \'' + + fileContents + '\''); + } + + for (var i in fileDocBlocks) { + var tags = fileDocBlocks[i].tags; + for (var j in tags) { + var tag = tags[j]; + + // Only blocks under @example are tested. + if (tag.type === 'example') { + // Replace all references to require('gcloud') with a relative + // version so that the code can be passed into the VM directly. + var code = tag.string + .replace('require(\'gcloud\')', 'require(\'..\/..\/\')') + .replace('require(\'gcloud', 'require(\'..\/..'); + assert.doesNotThrow(runCodeInSandbox.bind(null, code)); + } + } + } + } + }); +}); diff --git a/test/datastore/dataset.js b/test/datastore/dataset.js index 30b49a3715d..07cc2f2278d 100644 --- a/test/datastore/dataset.js +++ b/test/datastore/dataset.js @@ -91,7 +91,7 @@ describe('Dataset', function() { it('should begin transaction', function(done) { ds.createTransaction_ = function() { return { - begin: function() { + begin_: function() { done(); } }; @@ -101,10 +101,10 @@ describe('Dataset', function() { it('should return transaction object to the callback', function(done) { var transaction = { - begin: function(callback) { + begin_: function(callback) { callback(); }, - commit: util.noop + commit_: util.noop }; ds.createTransaction_ = function() { return transaction; @@ -118,10 +118,10 @@ describe('Dataset', function() { it('should return correct done function to the callback', function(done) { ds.createTransaction_ = function() { return { - begin: function(callback) { + begin_: function(callback) { callback(); }, - commit: function() { + commit_: function() { done(); } }; diff --git a/test/datastore/request.js b/test/datastore/request.js index 2e623ceac4a..9cbb54298d3 100644 --- a/test/datastore/request.js +++ b/test/datastore/request.js @@ -748,6 +748,25 @@ describe('Request', function() { }; }); + describe('rollback', function() { + it('should attach transacational properties', function(done) { + request.id = 'EeMXCSGvwcSWGkkABRmGMTWdbi_pa66VflNhQAGblQFMXf9HrmNGa' + + 'GugEsO1M2_2x7wZvLencG51uwaDOTZCjTkkRh7bw_oyKUgTmtJ0iWJwath7'; + var expected = new pb.RollbackRequest({ + transaction: request.id + }).toBuffer(); + request_Override = function() { + var stream = { on: util.noop, end: util.noop }; + stream.end = function(data) { + assert.deepEqual(data, expected); + done(); + }; + return stream; + }; + request.makeReq_('rollback', util.noop); + }); + }); + describe('commit', function() { it('should attach transactional properties', function(done) { request.id = 'EeMXCSGvwcSWGkkABRmGMTWdbi_pa66VflNhQAGblQFMXf9HrmNGa' + diff --git a/test/datastore/transaction.js b/test/datastore/transaction.js index 42ec46e4a5e..72e26e9df14 100644 --- a/test/datastore/transaction.js +++ b/test/datastore/transaction.js @@ -98,14 +98,14 @@ describe('Transaction', function() { }); }); - describe('begin', function() { + describe('begin_', function() { it('should begin', function(done) { transaction.makeReq_ = function(method, req, callback) { callback = callback || req; assert.equal(method, 'beginTransaction'); done(); }; - transaction.begin(); + transaction.begin_(); }); it('should set transaction id', function(done) { @@ -113,7 +113,7 @@ describe('Transaction', function() { callback = callback || req; callback(null, { transaction: TRANSACTION_ID }); }; - transaction.begin(function(err) { + transaction.begin_(function(err) { assert.ifError(err); assert.equal(transaction.id, TRANSACTION_ID); done(); @@ -126,7 +126,7 @@ describe('Transaction', function() { callback = callback || req; callback(error); }; - transaction.begin(function(err) { + transaction.begin_(function(err) { assert.deepEqual(err, error); done(); }); @@ -138,7 +138,7 @@ describe('Transaction', function() { callback = callback || req; callback(null, resp); }; - transaction.begin(function(err, apiResponse) { + transaction.begin_(function(err, apiResponse) { assert.ifError(err); assert.deepEqual(resp, apiResponse); done(); @@ -207,7 +207,7 @@ describe('Transaction', function() { }); }); - describe('commit', function() { + describe('commit_', function() { beforeEach(function() { transaction.id = TRANSACTION_ID; }); @@ -217,7 +217,7 @@ describe('Transaction', function() { assert.equal(method, 'commit'); done(); }; - transaction.commit(); + transaction.commit_(); }); it('should pass error to callback', function(done) { @@ -226,7 +226,7 @@ describe('Transaction', function() { callback = callback || req; callback(error); }; - transaction.commit(function(err) { + transaction.commit_(function(err) { assert.deepEqual(err, error); done(); }); @@ -238,7 +238,7 @@ describe('Transaction', function() { callback = callback || req; callback(null, resp); }; - transaction.commit(function(err, apiResponse) { + transaction.commit_(function(err, apiResponse) { assert.ifError(err); assert.deepEqual(resp, apiResponse); done(); @@ -274,7 +274,7 @@ describe('Transaction', function() { transaction.makeReq_ = util.noop; - transaction.commit(); + transaction.commit_(); assert.equal(deleteCalled, 1); assert.equal(saveCalled, 1); @@ -303,7 +303,7 @@ describe('Transaction', function() { transaction.makeReq_ = util.noop; - transaction.commit(); + transaction.commit_(); assert.equal(deleteCalled, 0); assert.equal(saveCalled, 1); }); @@ -321,7 +321,7 @@ describe('Transaction', function() { done(); }; - transaction.commit(); + transaction.commit_(); }); it('should execute the queued callbacks', function() { @@ -337,7 +337,7 @@ describe('Transaction', function() { cb(); }; - transaction.commit(); + transaction.commit_(); assert(cb1Called); assert(cb2Called); diff --git a/test/testdata/testfile.json b/test/testdata/testfile.json new file mode 100644 index 00000000000..e69de29bb2d From f11cf79abcabd7c5f708f9337b25762fd18f4e98 Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Wed, 27 May 2015 14:56:31 -0400 Subject: [PATCH 2/2] examples in each file now tested in own sandbox --- lib/bigquery/job.js | 7 ++++- lib/bigquery/table.js | 8 ++++++ lib/datastore/dataset.js | 1 + lib/datastore/query.js | 2 ++ lib/datastore/request.js | 41 +++++++++++++++++++++------- lib/datastore/transaction.js | 5 ++-- lib/pubsub/subscription.js | 2 ++ lib/pubsub/topic.js | 2 ++ lib/storage/acl.js | 2 ++ lib/storage/bucket.js | 12 ++++++--- lib/storage/file.js | 3 +++ scripts/build.sh | 5 ++-- test/common/docs.js | 52 +++++++++++++++++------------------- 13 files changed, 95 insertions(+), 47 deletions(-) diff --git a/lib/bigquery/job.js b/lib/bigquery/job.js index 8b063f0a580..54b3bd16a7d 100644 --- a/lib/bigquery/job.js +++ b/lib/bigquery/job.js @@ -29,7 +29,12 @@ var util = require('../common/util'); /*! Developer Documentation * * @param {module:bigquery} bigQuery - BigQuery instance. - * @param {string} id - The ID of the table. + * @param {string} id - The ID of the job. + * + * @example + * var bigquery = gcloud.bigquery(); + * var Job = require('gcloud/lib/bigquery/job'); + * var job = new Job(bigquery, 'job-id'); */ /** * Job objects are returned from various places in the BigQuery API: diff --git a/lib/bigquery/table.js b/lib/bigquery/table.js index 0bb04877cd0..e580f0d76e6 100644 --- a/lib/bigquery/table.js +++ b/lib/bigquery/table.js @@ -44,6 +44,13 @@ var util = require('../common/util'); * * @param {module:bigquery/dataset} dataset - Dataset instance. * @param {string} id - The ID of the table. + * + * @example + * var bigquery = gcloud.bigquery(); + * var Dataset = require('gcloud/lib/bigquery/dataset'); + * var dataset = new Dataset(bigquery, 'dataset-id'); + * var Table = require('gcloud/lib/bigquery/table'); + * var table = new Table(dataset, 'table-id'); */ /** * Table objects are returned by methods such as @@ -190,6 +197,7 @@ Table.prototype.copy = function(destination, metadata, callback) { * * @example * var through2 = require('through2'); + * var fs = require('fs'); * * table.createReadStream() * .pipe(through2.obj(function(row, enc, next) { diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index 9b6b7e02359..2b15fee4b1d 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -78,6 +78,7 @@ var SCOPES = [ * * @example * var datastore = gcloud.datastore; + * * var dataset = datastore.dataset({ * projectId: 'my-project', * keyFilename: '/path/to/keyfile.json' diff --git a/lib/datastore/query.js b/lib/datastore/query.js index aa24d7f1dbe..607b0996119 100644 --- a/lib/datastore/query.js +++ b/lib/datastore/query.js @@ -44,6 +44,8 @@ var util = require('../common/util.js'); * @param {string} kind - Kind to query. * * @example + * var dataset = gcloud.datastore.dataset(); + * * // If your dataset was scoped to a namespace at initialization, your query * // will likewise be scoped to that namespace. * var query = dataset.createQuery('Lion'); diff --git a/lib/datastore/request.js b/lib/datastore/request.js index 9f8257f8147..ad6e06b2ce2 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -64,6 +64,15 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; * * Creates requests to the Dataset endpoint. Designed to be inherited by * datastore.Dataset and datastore.Transaction objects. + * + * @example + * // This is how to create a transaction object directly using this Transaction + * // class. The following transaction object is created for use in the examples + * // in this file below. + * var dataset = gcloud.datastore.dataset(); + * var Transaction = require('gcloud/lib/datastore/transaction'); + * var transaction = new Transaction(dataset, 'my-project-id'); + * transaction.id = '1234'; // Give the transaction an ID. */ /* * Handle logic for Datastore API operations. @@ -90,10 +99,10 @@ function DatastoreRequest() {} * * // Get a single entity. * var key = dataset.key(['Company', 123]); - * dataset.get(key, function(err, entity, apiResponse) {}); + * transaction.get(key, function(err, entity, apiResponse) {}); * * // Get multiple entities at once. - * dataset.get([ + * transaction.get([ * dataset.key(['Company', 123]), * dataset.key(['Product', 'Computer']) * ], function(err, entities, apiResponse) {}); @@ -415,11 +424,16 @@ DatastoreRequest.prototype.save = function(entities, callback) { * @param {function} callback - The callback function. * * @example + * //- + * // Where you see `transaction`, assume this is the context that's relevant to + * // your use case, whether that be a Dataset or a Transaction object. + * //- + * * // Delete a single entity. - * dataset.delete(dataset.key(['Company', 123]), function(err) {}); + * transaction.delete(dataset.key(['Company', 123]), function(err, apiResp) {}); * * // Delete multiple entities at once. - * dataset.delete([ + * transaction.delete([ * dataset.key(['Company', 123]), * dataset.key(['Product', 'Computer']) * ], function(err, apiResponse) {}); @@ -460,13 +474,18 @@ DatastoreRequest.prototype.delete = function(keys, callback) { * stream instance is returned. * * @example + * //- + * // Where you see `transaction`, assume this is the context that's relevant to + * // your use, whether that be a Dataset or a Transaction object. + * //- + * var query = dataset.createQuery('Lion'); * * // Retrieve 5 companies. - * dataset.runQuery(query, function(err, entities, endCursor, apiResponse) { + * transaction.runQuery(query, function(err, entities, endCursor, apiResponse) { * // Use `endCursor` as the starting cursor for your next query. * var nextQuery = query.start(endCursor); * var callback = function(err, entities, endCursor, apiResponse) {}; - * dataset.runQuery(nextQuery, callback); + * transaction.runQuery(nextQuery, callback); * }); * * //- @@ -474,7 +493,7 @@ DatastoreRequest.prototype.delete = function(keys, callback) { * // queries until no results remain. Entity objects will be pushed as they are * // found. * //- - * dataset.runQuery(query) + * transaction.runQuery(query) * .on('data', function (entity) {}); */ DatastoreRequest.prototype.runQuery = function(q, callback) { @@ -556,7 +575,7 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * * @example * //- - * // Where you see `dataset`, assume this is the context that's relevant to + * // Where you see `transaction`, assume this is the context that's relevant to * // your use, whether that be a Dataset or a Transaction object. * //- * @@ -564,7 +583,7 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * * // The following call will create 100 new IDs from the Company kind, which * // exists under the default namespace. - * dataset.allocateIds(incompleteKey, 100, function(err, keys) {}); + * transaction.allocateIds(incompleteKey, 100, function(err, keys) {}); * * // You may prefer to create IDs from a non-default namespace by providing an * // incomplete key with a namespace. Similar to the previous example, the call @@ -575,7 +594,7 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * path: ['Company'] * }); * var callback = function(err, keys, apiResponse) {}; - * dataset.allocateIds(incompleteKey, 100, callback); + * transaction.allocateIds(incompleteKey, 100, callback); */ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { if (entity.isKeyComplete(incompleteKey)) { @@ -635,6 +654,8 @@ DatastoreRequest.prototype.upsert = function(entities, callback) { * delete: [] // datastore key objects. * } * }; + * + * var dataset = gcloud.datastore.dataset(); * var callback = function(err, result, apiResponse) {}; * var Transaction = require('gcloud/lib/datastore/transaction'); * var transaction = new Transaction(dataset, 'my-project-id'); diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index ab4a982218d..dc5609e9c58 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -47,6 +47,7 @@ var extend = require('extend'); * // This is how to create a transaction object directly using this Transaction * // class. The following transaction object is created for use in the examples * // in this file below. + * var dataset = gcloud.datastore.dataset(); * var Transaction = require('gcloud/lib/datastore/transaction'); * var transaction = new Transaction(dataset, 'my-project-id'); * transaction.id = '1234'; // Give the transaction an ID. @@ -263,13 +264,13 @@ Transaction.prototype.commit_ = function(callback) { * * @example * // Delete a single entity. - * transaction.delete(dataset.key(['Company', 123]), function(err) {}); + * transaction.delete(dataset.key(['Company', 123])); * * // Delete multiple entities at once. * transaction.delete([ * dataset.key(['Company', 123]), * dataset.key(['Product', 'Computer']) - * ], function(err) {}); + * ]); */ Transaction.prototype.delete = function(entities) { var that = this; diff --git a/lib/pubsub/subscription.js b/lib/pubsub/subscription.js index 67958e3b893..1740c1c468f 100644 --- a/lib/pubsub/subscription.js +++ b/lib/pubsub/subscription.js @@ -62,6 +62,8 @@ var util = require('../common/util.js'); * @constructor * * @example + * var pubsub = gcloud.pubsub(); + * * //- * // From {@linkcode module:pubsub#getSubscriptions}: * //- diff --git a/lib/pubsub/topic.js b/lib/pubsub/topic.js index ee913b23b4d..9789dd70f07 100644 --- a/lib/pubsub/topic.js +++ b/lib/pubsub/topic.js @@ -47,6 +47,8 @@ var Subscription = require('./subscription.js'); * @alias module:pubsub/topic * * @example + * var pubsub = gcloud.pubsub(); + * * // From pubsub.topic: * var topic = pubsub.topic('my-existing-topic'); * diff --git a/lib/storage/acl.js b/lib/storage/acl.js index b332eba11c4..f557fce6c43 100644 --- a/lib/storage/acl.js +++ b/lib/storage/acl.js @@ -99,6 +99,8 @@ function Acl(options) { * @return {object} * * @example + * var storage = gcloud.storage(); + * * //- * // Add a user as an owner of a file. * //- diff --git a/lib/storage/bucket.js b/lib/storage/bucket.js index 6dd1508c9be..bc1d48fbf01 100644 --- a/lib/storage/bucket.js +++ b/lib/storage/bucket.js @@ -126,6 +126,7 @@ function Bucket(storage, name) { * //- * // Make a bucket's contents publicly readable. * //- + * var myBucket = storage.bucket('my-bucket'); * myBucket.acl.add({ * scope: 'allUsers', * role: storage.acl.READER_ROLE @@ -218,12 +219,14 @@ function Bucket(storage, name) { * @param {function=} callback - The callback function. * * @example - * var logs2013 = bucket.file('2013-logs.txt'); - * var logs2014 = bucket.file('2014-logs.txt'); + * var logBucket = storage.bucket('log-bucket'); * - * var allLogs = bucket.file('all-logs.txt'); + * var logs2013 = logBucket.file('2013-logs.txt'); + * var logs2014 = logBucket.file('2014-logs.txt'); * - * bucket.combine([ + * var allLogs = logBucket.file('all-logs.txt'); + * + * logBucket.combine([ * logs2013, * logs2014 * ], allLogs, function(err, newFile, apiResponse) { @@ -303,6 +306,7 @@ Bucket.prototype.combine = function(sources, destination, callback) { * @param {function=} callback - The callback function. * * @example + * var bucket = storage.bucket('delete-me'); * bucket.delete(function(err, apiResponse) {}); */ Bucket.prototype.delete = function(callback) { diff --git a/lib/storage/file.js b/lib/storage/file.js index 5bb55ff7f3a..f166aa3a7a5 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -107,6 +107,8 @@ function File(bucket, name, options) { * //- * // Make a file publicly readable. * //- + * var storage = gcloud.storage(); + * var myFile = storage.bucket('my-bucket').file('my-file'); * myFile.acl.add({ * scope: 'allUsers', * role: storage.acl.READER_ROLE @@ -367,6 +369,7 @@ File.prototype.move = function(destination, callback) { * // backup of your remote data. * //- * var fs = require('fs'); + * var myBucket = storage.bucket('my-bucket'); * var image = myBucket.file('image.png'); * * image.createReadStream() diff --git a/scripts/build.sh b/scripts/build.sh index 31f22fd9989..6841843566b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -17,7 +17,7 @@ set -ev npm run lint -npm run docs +# generates docs and runs tests npm run test # if merging to master and not a pull request, execute system tests, create coverage report and update docs @@ -26,8 +26,7 @@ if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ] # create new coverage report (executes system tests) npm run coveralls - # generate new set of json files in docs/json/master - npm run docs + # add new docs to the gh-pages branch git submodule add -b gh-pages https://${GH_OAUTH_TOKEN}@github.com/${GH_OWNER}/${GH_PROJECT_NAME} ghpages # copy all the docs file that might have changed, excluding versions.txt (to avoid overriding it) cd docs diff --git a/test/common/docs.js b/test/common/docs.js index 8dab7bb9488..ab4d9a30be2 100644 --- a/test/common/docs.js +++ b/test/common/docs.js @@ -25,16 +25,7 @@ var glob = require('glob'); var mitm = require('mitm'); var fs = require('fs'); -var sandbox = { - gcloud: gcloud, - require: require, - process: process, - Buffer: Buffer, - Date: Date, - Array: Array -}; - -function runCodeInSandbox(code) { +function runCodeInSandbox(code, sandbox) { vm.createContext(sandbox); try { vm.runInNewContext(code, sandbox, { @@ -54,7 +45,7 @@ describe('documentation', function() { before(function(done) { // Turn off the network so that API calls aren't actually made. MITM = mitm(); - glob('docs/json/**/*.json', {}, function(err, files) { + glob('docs/json/master/**/*.json', function(err, files) { assert.ifError(err); FILES = files; done(); @@ -67,36 +58,43 @@ describe('documentation', function() { }); it('should run docs examples without errors', function() { - for (var f in FILES) { + FILES.forEach(function(filename) { var fileDocBlocks = []; - var fileContents = fs.readFileSync(FILES[f], { + var fileContents = fs.readFileSync(filename, { encoding: 'utf8' }); try { fileDocBlocks = JSON.parse(fileContents); } catch(e) { - throw new Error('Failed to parse one of the doc files (' + e.message + - ')\n\nFilename: ' + FILES[f] + '\n\nFile contents: \'' + - fileContents + '\''); + throw new Error([ + 'Failed to parse one of the doc files (' + e.message + ')', + 'Filename: ' + filename, + 'File contents: "' + fileContents + '"' + ].join('\n')); } - for (var i in fileDocBlocks) { - var tags = fileDocBlocks[i].tags; - for (var j in tags) { - var tag = tags[j]; + var sandbox = { + gcloud: gcloud, + require: require, + process: process, + Buffer: Buffer, + Date: Date, + Array: Array + }; - // Only blocks under @example are tested. + fileDocBlocks.forEach(function(block) { + block.tags.forEach(function(tag) { if (tag.type === 'example') { // Replace all references to require('gcloud') with a relative // version so that the code can be passed into the VM directly. var code = tag.string - .replace('require(\'gcloud\')', 'require(\'..\/..\/\')') - .replace('require(\'gcloud', 'require(\'..\/..'); - assert.doesNotThrow(runCodeInSandbox.bind(null, code)); + .replace(/require\(\'gcloud\'\)/g, 'require(\'..\/..\/\')') + .replace(/require\(\'gcloud/g, 'require(\'..\/..'); + assert.doesNotThrow(runCodeInSandbox.bind(null, code, sandbox)); } - } - } - } + }); + }); + }); }); });