From d02a36485dab8e67b4da360e4d87185ef5fc917c Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 27 Jul 2023 18:56:30 +0200 Subject: [PATCH 1/6] Add integration tests --- .github/workflows/ci.yaml | 9 ++++++ integration/read-only.mjs | 61 +++++++++++++++++++++++++++++++++++++++ integration/write.mjs | 57 ++++++++++++++++++++++++++++++++++++ package.json | 6 +++- 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 integration/read-only.mjs create mode 100644 integration/write.mjs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a6c1d474..6765e1f7 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -45,3 +45,12 @@ jobs: - name: Run tests run: | npm run test:coverage + + - name: Run integration tests + env: + TUMBLR_OAUTH_CONSUMER_KEY: ${{ secrets.TUMBLR_OAUTH_CONSUMER_KEY }} + TUMBLR_OAUTH_CONSUMER_SECRET: ${{ secrets.TUMBLR_OAUTH_CONSUMER_SECRET }} + TUMBLR_OAUTH_TOKEN: ${{ secrets.TUMBLR_OAUTH_TOKEN }} + TUMBLR_OAUTH_TOKEN_SECRET: ${{ secrets.TUMBLR_OAUTH_TOKEN_SECRET }} + run: | + npm run test:integration diff --git a/integration/read-only.mjs b/integration/read-only.mjs new file mode 100644 index 00000000..c4a9009f --- /dev/null +++ b/integration/read-only.mjs @@ -0,0 +1,61 @@ +import { env } from 'node:process'; +import { Client } from 'tumblr.js'; +import { assert } from 'chai'; +import { test } from 'mocha'; + +if (!env.TUMBLR_OAUTH_CONSUMER_KEY) { + throw new Error('Must provide TUMBLR_OAUTH_CONSUMER_KEY environment variable'); +} + +describe('consumer_key (api_key) only requests', () => { + /** @type {Client} */ + let c; + before(() => { + c = new Client({ + consumer_key: env.TUMBLR_OAUTH_CONSUMER_KEY, + }); + c.returnPromises(); + }); + + test('fetches blogInfo("staff")', async () => { + const resp = await c.blogInfo('staff'); + assert.isOk(resp); + assert.equal(resp.blog.name, 'staff'); + assert.equal(resp.blog.uuid, 't:0aY0xL2Fi1OFJg4YxpmegQ'); + }); +}); + +const OAUTH1_ENV_VARS = [ + 'TUMBLR_OAUTH_CONSUMER_SECRET', + 'TUMBLR_OAUTH_TOKEN', + 'TUMBLR_OAUTH_CONSUMER_SECRET', +]; + +describe('oauth1 requests', () => { + /** @type {Client} */ + let client; + before(function () { + if (!OAUTH1_ENV_VARS.every((envVarName) => Boolean(env[envVarName]))) { + console.warn( + `To run full oauth1 tests provide environment vars ${OAUTH1_ENV_VARS.join(', ')}`, + ); + this.skip(); + } + + client = new Client({ + consumer_key: env.TUMBLR_OAUTH_CONSUMER_KEY, + consumer_secret: env.TUMBLR_OAUTH_CONSUMER_SECRET, + token: env.TUMBLR_OAUTH_TOKEN, + token_secret: env.TUMBLR_OAUTH_TOKEN_SECRET, + }); + client.returnPromises(); + }); + + test('fetches userInfo()', async () => { + const resp = await client.userInfo(); + assert.isOk(resp); + assert.typeOf(resp.user.name, 'string'); + assert.typeOf(resp.user.blogs, 'array'); + assert.typeOf(resp.user.blogs[0].uuid, 'string'); + }); +}); diff --git a/integration/write.mjs b/integration/write.mjs new file mode 100644 index 00000000..8213af53 --- /dev/null +++ b/integration/write.mjs @@ -0,0 +1,57 @@ +import { env } from 'node:process'; +import { Client } from 'tumblr.js'; +import { assert } from 'chai'; +import { test } from 'mocha'; + +if ( + !env.TUMBLR_OAUTH_CONSUMER_KEY || + !env.TUMBLR_OAUTH_CONSUMER_SECRET || + !env.TUMBLR_OAUTH_TOKEN || + !env.TUMBLR_OAUTH_TOKEN_SECRET +) { + throw new Error('Must provide all Oauth1 environment variables'); +} + +describe('oauth1 write requests', () => { + /** @type {Client} */ + let client; + before(function () { + if (!env.CI) { + console.warn( + 'This test suite uses the API to make changes. Modify the test suite to enabled it.', + ); + this.skip(); + } + + client = new Client({ + consumer_key: env.TUMBLR_OAUTH_CONSUMER_KEY, + consumer_secret: env.TUMBLR_OAUTH_CONSUMER_SECRET, + token: env.TUMBLR_OAUTH_TOKEN, + token_secret: env.TUMBLR_OAUTH_TOKEN_SECRET, + }); + }); + + test('creates a post', (done) => { + client.userInfo((err, userResp) => { + assert.isNull(err); + assert.isOk(userResp); + + const blogName = userResp.user.blogs[0].name; + + client.createPost( + blogName, + { + type: 'text', + format: 'markdown', + title: `Automated test post ${new Date().toISOString()}`, + body: 'This post was automatically generated by the tumblr.js tests.\n\n[The official JavaScript client library for the Tumblr API.](https://github.com/tumblr/tumblr.js)', + tags: `tumblr.js-test,tumblr.js-version-${client.version}`, + }, + (err) => { + assert.isNull(err); + done(); + }, + ); + }); + }); +}); diff --git a/package.json b/package.json index 880b95de..35e3cda4 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,10 @@ "version": "3.0.0", "description": "Official JavaScript client for the Tumblr API", "main": "./lib/tumblr", - "types": "./lib/tumblr.d.ts", + "type": "commonjs", + "exports": { + ".": "./lib/tumblr.js" + }, "scripts": { "autoformat": "prettier --write .", "format-check": "prettier --check .", @@ -11,6 +14,7 @@ "gh-pages": "git subtree push --prefix=gh-pages origin gh-pages", "test": "mocha", "test:coverage": "nyc mocha", + "test:integration": "mocha ./integration", "lint": "eslint --report-unused-disable-directives lib test" }, "engines": { From 5ad34648ac6d9e7fc29fc5c11d3442d1a74f51fb Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 27 Jul 2023 18:58:53 +0200 Subject: [PATCH 2/6] Add changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27269b51..88140201 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - **Breaking** Support Node.js versions `>=16` +### Added + +- Integration test suites using real API. + ## [3.0.0] - 2020-07-28 ## [2.0.0] - 2018-06-13 From ae6079ea4f057d8ad624826dca10215089ad175e Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 27 Jul 2023 18:59:14 +0200 Subject: [PATCH 3/6] Add CONTRIBUTING section about tests --- CONTRIBUTING.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 125652ae..82c08b45 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,3 +14,52 @@ problems, please open an issue. We also actively welcome pull requests. By contributing to tumblr.js you agree that your contributions will be licensed under its Apache 2.0 license. + +## Testing + +First install dependencies by running `npm ci`. + +### Unit tests + +Run unit tests as follows: + +```sh +npm run test +``` + +### Integration tests + +To run the integration tests which will actually call the API, you'll need to get OAuth1 application +credentials. To get valid credentials, visit the +[Tumblr OAuth Applications page](https://www.tumblr.com/oauth/apps). + +**Never share your credentials. They're secret!** + +Part of the suite can be run with just the `consumer_key`, which is required: + +```sh +TUMBLR_OAUTH_CONSUMER_KEY='--- valid consumer_key ---' \ +npm run test:integration +``` + +To run the full suite, you must provide complete OAuth1 credentials. These full credentials can be +found by visiting the [Tumblr API Console](https://api.tumblr.com/console/calls/user/info) and +entering your OAuth Application consumer credentials. _Note:_ You may need to set +`https://api.tumblr.com/console/calls/user/info` as the default callback URL for you application. +It's recommended to create a dedicated application for testing this library. + +Provide the full OAuth1 credentials as environment variables and run the integration test suite: + +```sh +TUMBLR_OAUTH_CONSUMER_KEY='--- valid consumer_key ---' \ +TUMBLR_OAUTH_CONSUMER_SECRET='--- valid consumer_secret ---' \ +TUMBLR_OAUTH_TOKEN='--- valid token ---' \ +TUMBLR_OAUTH_TOKEN_SECRET='--- valid token_key ---' \ +npm run test:integration +``` + +The above tests query the API to read data, they won't make any changes. + +There are additional tests that _will write or modify data_. Those tests are disabled by default and +need to be enabled by changes to the test file. Be careful when running those tests and be sure the +credentials are for a test account. From 7c543e4899bc02138f6d2810200181dce2b599c0 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 27 Jul 2023 19:06:40 +0200 Subject: [PATCH 4/6] use promises for integration --- integration/write.mjs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/integration/write.mjs b/integration/write.mjs index 8213af53..faa9c525 100644 --- a/integration/write.mjs +++ b/integration/write.mjs @@ -29,29 +29,23 @@ describe('oauth1 write requests', () => { token: env.TUMBLR_OAUTH_TOKEN, token_secret: env.TUMBLR_OAUTH_TOKEN_SECRET, }); + client.returnPromises(); }); - test('creates a post', (done) => { - client.userInfo((err, userResp) => { - assert.isNull(err); - assert.isOk(userResp); + test('creates a post', async () => { + const userResp = await client.userInfo(); - const blogName = userResp.user.blogs[0].name; + assert.isOk(userResp); + const blogName = userResp.user.blogs[0].name; - client.createPost( - blogName, - { - type: 'text', - format: 'markdown', - title: `Automated test post ${new Date().toISOString()}`, - body: 'This post was automatically generated by the tumblr.js tests.\n\n[The official JavaScript client library for the Tumblr API.](https://github.com/tumblr/tumblr.js)', - tags: `tumblr.js-test,tumblr.js-version-${client.version}`, - }, - (err) => { - assert.isNull(err); - done(); - }, - ); - }); + assert.isOk( + await client.createPost(blogName, { + type: 'text', + format: 'markdown', + title: `Automated test post ${new Date().toISOString()}`, + body: 'This post was automatically generated by the tumblr.js tests.\n\n[The official JavaScript client library for the Tumblr API.](https://github.com/tumblr/tumblr.js)', + tags: `tumblr.js-test,tumblr.js-version-${client.version}`, + }), + ); }); }); From ea40afdf15f6ae4970ee5eb51a19d0e9d0b21b3f Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 31 Jul 2023 08:41:24 +0200 Subject: [PATCH 5/6] cleanup --- CONTRIBUTING.md | 8 +++++--- integration/read-only.mjs | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 82c08b45..5ad70f70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ First install dependencies by running `npm ci`. ### Unit tests -Run unit tests as follows: +Unit tests can be found under the `test/` directory. Run them tests as follows: ```sh npm run test @@ -29,8 +29,10 @@ npm run test ### Integration tests -To run the integration tests which will actually call the API, you'll need to get OAuth1 application -credentials. To get valid credentials, visit the +There are integration tests that will query the API. They can be found under the `integration/` +directory. + +They require OAuth1 application credentials. To get valid credentials, visit the [Tumblr OAuth Applications page](https://www.tumblr.com/oauth/apps). **Never share your credentials. They're secret!** diff --git a/integration/read-only.mjs b/integration/read-only.mjs index c4a9009f..3afb7b99 100644 --- a/integration/read-only.mjs +++ b/integration/read-only.mjs @@ -9,16 +9,16 @@ if (!env.TUMBLR_OAUTH_CONSUMER_KEY) { describe('consumer_key (api_key) only requests', () => { /** @type {Client} */ - let c; + let client; before(() => { - c = new Client({ + client = new Client({ consumer_key: env.TUMBLR_OAUTH_CONSUMER_KEY, }); c.returnPromises(); }); test('fetches blogInfo("staff")', async () => { - const resp = await c.blogInfo('staff'); + const resp = await client.blogInfo('staff'); assert.isOk(resp); assert.equal(resp.blog.name, 'staff'); assert.equal(resp.blog.uuid, 't:0aY0xL2Fi1OFJg4YxpmegQ'); From 8c434780902a862659967ce28863b2a8cbb241e5 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 31 Jul 2023 08:42:44 +0200 Subject: [PATCH 6/6] fixup! cleanup --- integration/read-only.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/read-only.mjs b/integration/read-only.mjs index 3afb7b99..f052b4c3 100644 --- a/integration/read-only.mjs +++ b/integration/read-only.mjs @@ -14,7 +14,7 @@ describe('consumer_key (api_key) only requests', () => { client = new Client({ consumer_key: env.TUMBLR_OAUTH_CONSUMER_KEY, }); - c.returnPromises(); + client.returnPromises(); }); test('fetches blogInfo("staff")', async () => {