From f438af1b2f481d360088ecb302aa133d10b9d980 Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Fri, 29 May 2020 15:50:03 -0400 Subject: [PATCH 1/3] Enforce 100% code coverage --- .gitignore | 2 ++ lib/airtable.js | 1 + lib/airtable_error.js | 1 + lib/base.js | 1 + lib/callback_to_promise.js | 1 + lib/deprecate.js | 1 + lib/http_headers.js | 1 + lib/object_to_query_param_string.js | 1 + lib/promise.js | 1 + lib/query.js | 1 + lib/record.js | 1 + lib/run_action.js | 1 + lib/table.js | 1 + lib/typecheck.js | 1 + package.json | 14 +++++++++++++- test/test_helpers.js | 1 + 16 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3c3629e6..e80e0df2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules +/.nyc_output/ +/coverage/ diff --git a/lib/airtable.js b/lib/airtable.js index cd1e6901..dba32b1f 100644 --- a/lib/airtable.js +++ b/lib/airtable.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var Base = require('./base'); diff --git a/lib/airtable_error.js b/lib/airtable_error.js index ad5b3db2..09311f0d 100644 --- a/lib/airtable_error.js +++ b/lib/airtable_error.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; function AirtableError(error, message, statusCode) { diff --git a/lib/base.js b/lib/base.js index f9d9cae6..77b980d2 100644 --- a/lib/base.js +++ b/lib/base.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var forEach = require('lodash/forEach'); diff --git a/lib/callback_to_promise.js b/lib/callback_to_promise.js index 843667f1..755102c4 100644 --- a/lib/callback_to_promise.js +++ b/lib/callback_to_promise.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var Promise = require('./promise'); diff --git a/lib/deprecate.js b/lib/deprecate.js index a8f29934..e7d3c9a0 100644 --- a/lib/deprecate.js +++ b/lib/deprecate.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var didWarnForDeprecation = {}; diff --git a/lib/http_headers.js b/lib/http_headers.js index 20299cd3..bb1373b6 100644 --- a/lib/http_headers.js +++ b/lib/http_headers.js @@ -1,3 +1,4 @@ +// istanbul ignore file var forEach = require('lodash/forEach'); var isBrowser = typeof window !== 'undefined'; diff --git a/lib/object_to_query_param_string.js b/lib/object_to_query_param_string.js index b10b8889..445abce7 100644 --- a/lib/object_to_query_param_string.js +++ b/lib/object_to_query_param_string.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var isArray = require('lodash/isArray'); diff --git a/lib/promise.js b/lib/promise.js index 91fdcb68..a8a88a0a 100644 --- a/lib/promise.js +++ b/lib/promise.js @@ -1,3 +1,4 @@ +// istanbul ignore file /* global Promise */ var polyfill = require('es6-promise'); diff --git a/lib/query.js b/lib/query.js index 26a2fca8..3a14b518 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var isPlainObject = require('lodash/isPlainObject'); diff --git a/lib/record.js b/lib/record.js index 2de5a2d9..4dacd93b 100644 --- a/lib/record.js +++ b/lib/record.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var assign = require('lodash/assign'); diff --git a/lib/run_action.js b/lib/run_action.js index 0f459e5d..c1248629 100644 --- a/lib/run_action.js +++ b/lib/run_action.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var exponentialBackoffWithJitter = require('./exponential_backoff_with_jitter'); diff --git a/lib/table.js b/lib/table.js index be3505e9..5a114686 100644 --- a/lib/table.js +++ b/lib/table.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var isArray = require('lodash/isArray'); diff --git a/lib/typecheck.js b/lib/typecheck.js index 1ff63c72..f2655659 100644 --- a/lib/typecheck.js +++ b/lib/typecheck.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var includes = require('lodash/includes'); diff --git a/package.json b/package.json index 0c797901..4c88931e 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,12 @@ "repository": "git://github.com/airtable/airtable.js.git", "private": false, "scripts": { + "coverage": "jest --env node --coverage", "pretest": "npm run lint", "lint": "eslint .", "format": "prettier --write '**/*.js'", - "test": "jest --env node" + "test": "npm run coverage && npm run test-unit", + "test-unit": "jest --env node" }, "dependencies": { "es6-promise": "4.2.8", @@ -29,6 +31,16 @@ "/build/airtable.browser.js", "/lib/" ], + "jest": { + "coverageThreshold": { + "global": { + "branches": 100, + "functions": 100, + "lines": 100, + "statements": 100 + } + } + }, "devDependencies": { "body-parser": "^1.19.0", "envify": "^4.1.0", diff --git a/test/test_helpers.js b/test/test_helpers.js index 983aeaf1..f0cc97e9 100644 --- a/test/test_helpers.js +++ b/test/test_helpers.js @@ -1,3 +1,4 @@ +// istanbul ignore file 'use strict'; var Airtable = require('../lib/airtable'); From 6252e563324ebda0b04945a68dbc49e0f68dff7a Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Fri, 29 May 2020 15:51:41 -0400 Subject: [PATCH 2/3] Enable test coverage verification for test helper Some code paths which are intended to improve error reports for test failures. They are not expected to be used when all tests are passing. Tolerate coverage gaps for these specific code paths. --- test/test_helpers.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_helpers.js b/test/test_helpers.js index f0cc97e9..8933b3e6 100644 --- a/test/test_helpers.js +++ b/test/test_helpers.js @@ -1,4 +1,3 @@ -// istanbul ignore file 'use strict'; var Airtable = require('../lib/airtable'); @@ -112,6 +111,7 @@ function getMockEnvironmentAsync(options) { res.json({error: 'NOT_FOUND'}); }); + // istanbul ignore next // eslint-disable-next-line no-unused-vars app.use(function(err, req, res, next) { console.error(err); @@ -135,6 +135,7 @@ function getMockEnvironmentAsync(options) { } testServer.listen(testServerPort, function(err) { + // istanbul ignore if if (err) { reject(err); } else { @@ -157,6 +158,7 @@ function _checkParamsMiddleware(req, res, next) { req.get('authorization') === 'Bearer key123' && req.params.baseId === 'app123' && req.params.tableIdOrName === 'Table'; + // istanbul ignore else if (areParamsValid) { next(); } else { From 35232225b14c2aeb7c50c3a8d405c480b6858efb Mon Sep 17 00:00:00 2001 From: Mike Pennisi Date: Fri, 29 May 2020 16:42:42 -0400 Subject: [PATCH 3/3] Improve coverage for `Airtable` interface --- lib/airtable.js | 1 - test/airtable.test.js | 69 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/lib/airtable.js b/lib/airtable.js index dba32b1f..cd1e6901 100644 --- a/lib/airtable.js +++ b/lib/airtable.js @@ -1,4 +1,3 @@ -// istanbul ignore file 'use strict'; var Base = require('./base'); diff --git a/test/airtable.test.js b/test/airtable.test.js index c622be7b..e17f4bd7 100644 --- a/test/airtable.test.js +++ b/test/airtable.test.js @@ -10,4 +10,73 @@ describe('Airtable', function() { expect(value).not.toEqual('keyXyz'); }); }); + + it('recognizes API key as a property of the constructor', function() { + try { + Airtable.apiKey = 'keyAbc'; + new Airtable({}); + new Airtable(); + } finally { + delete Airtable.apiKey; + } + }); + + it('recognizes API key as an environment variable', function() { + try { + process.env.AIRTABLE_API_KEY = 'keyDef'; + new Airtable({}); + new Airtable(); + } finally { + delete process.env.AIRTABLE_API_KEY; + } + }); + + it('throws when API key is not provided', function() { + expect(function() { + new Airtable({}); + }).toThrow(); + + expect(function() { + new Airtable(); + }).toThrow(); + }); + + describe('configure static method', function() { + it('sets the apiKey', function() { + Airtable.configure({apiKey: 'keyGhi'}); + + try { + expect(Airtable.apiKey).toEqual('keyGhi'); + } finally { + delete Airtable.apiKey; + } + }); + }); + + describe('base static method', function() { + it('throws in the absense of an API key', function() { + expect(function() { + Airtable.base('abaseid'); + }); + }); + + it('returns a Base instance configured with the given ID', function() { + try { + Airtable.apiKey = 'keyJkl'; + var base = Airtable.base('abaseid'); + + expect(base.getId()).toBe('abaseid'); + } finally { + delete Airtable.apiKey; + } + }); + }); + + describe('base instance method', function() { + it('returns a Base instance configured with the given ID', function() { + var base = new Airtable({apiKey: 'keyMno'}).base('anotherbaseid'); + + expect(base.getId()).toBe('anotherbaseid'); + }); + }); });