From c18a2f9c6e7a0eba6ef703746408712606596c53 Mon Sep 17 00:00:00 2001 From: Alex LaFroscia Date: Mon, 16 Jul 2018 16:42:40 -0700 Subject: [PATCH] feat: add test helper for stubbing services --- .eslintrc.js | 45 ++++++++++---------- README.md | 27 +++++++++++- addon-test-support/index.js | 1 + addon-test-support/stub-service.js | 42 ++++++++++++++++++ package.json | 1 + tests/dummy/app/services/to-stub.js | 7 +++ tests/test-helper.js | 10 +++-- tests/unit/test-support/stub-service-test.js | 31 ++++++++++++++ yarn.lock | 12 ++++++ 9 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 addon-test-support/index.js create mode 100644 addon-test-support/stub-service.js create mode 100644 tests/dummy/app/services/to-stub.js create mode 100644 tests/unit/test-support/stub-service-test.js diff --git a/.eslintrc.js b/.eslintrc.js index 1dc3939..65cae79 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,47 +2,46 @@ module.exports = { root: true, parserOptions: { ecmaVersion: 2017, - sourceType: 'module' + sourceType: "module" }, - plugins: [ - 'ember' - ], - extends: [ - 'eslint:recommended', - 'plugin:ember/recommended' - ], + plugins: ["ember"], + extends: ["eslint:recommended", "plugin:ember/recommended"], env: { browser: true }, - rules: { - }, + rules: {}, overrides: [ // node files { files: [ - 'index.js', - 'testem.js', - 'ember-cli-build.js', - 'config/**/*.js', - 'tests/dummy/config/**/*.js' + "index.js", + "testem.js", + "ember-cli-build.js", + "config/**/*.js", + "tests/dummy/config/**/*.js" ], excludedFiles: [ - 'app/**', - 'addon/**', - 'tests/dummy/app/**' + "app/**", + "addon/**", + "tests/dummy/app/**", + "addon-test-support/**" ], parserOptions: { - sourceType: 'script', + sourceType: "script", ecmaVersion: 2015 }, env: { browser: false, node: true }, - plugins: ['node'], - rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, { - // add your custom rules and overrides for node files here - }) + plugins: ["node"], + rules: Object.assign( + {}, + require("eslint-plugin-node").configs.recommended.rules, + { + // add your custom rules and overrides for node files here + } + ) } ] }; diff --git a/README.md b/README.md index dd31b12..efff2f7 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,30 @@ Then import as follows: import td from 'testdouble'; ``` -License ------------------------------------------------------------------------------- +## Test Helpers + +### `stubService` + +Included is a function that can replace a service with one stubbed using [`td.object()`][td-object]. + +```js +import td from "testdouble"; +import { stubService } from "ember-cli-testdouble/test-support"; + +test("verifying a method invocation", function(assert) { + assert.expect(0); // Won't actually use `assert` in this test + + stubService("some-service"); + + let someService = this.owner.lookup("service:some-service"); + someService.method(); + + td.verify(someService.method()); // Passes! +}); +``` + +## License This project is licensed under the [MIT License](LICENSE.md). + +[td-object]: https://github.com/testdouble/testdouble.js/blob/master/docs/4-creating-test-doubles.md#tdobject diff --git a/addon-test-support/index.js b/addon-test-support/index.js new file mode 100644 index 0000000..6d261a0 --- /dev/null +++ b/addon-test-support/index.js @@ -0,0 +1 @@ +export { default as stubService } from "./stub-service"; diff --git a/addon-test-support/stub-service.js b/addon-test-support/stub-service.js new file mode 100644 index 0000000..8283547 --- /dev/null +++ b/addon-test-support/stub-service.js @@ -0,0 +1,42 @@ +import { getContext } from "@ember/test-helpers"; +import { run } from "@ember/runloop"; +import td from "testdouble"; + +function replace(owner, name) { + const serviceName = `service:${name}`; + const original = owner.lookup(serviceName); + const replacement = td.object(original); + + run(() => { + owner.unregister(serviceName); + owner.register(serviceName, replacement, { instantiate: false }); + }); + + return replacement; +} + +/** + * Replace a service with a stubbed version of itself + * + * Each method on the service will be replaced with a TestDouble function + */ +export default function stubService() { + if (arguments.length === 2) { + let [hooks, name] = arguments; + + hooks.beforeEach(function() { + replace(this.owner, name); + }); + + hooks.afterEach(function() { + td.reset(); + }); + } else if (arguments.length === 1) { + let [name] = arguments; + let { owner } = getContext(); + + replace(owner, name); + } else { + throw new Error("Unexpected number of arguments"); + } +} diff --git a/package.json b/package.json index 29e8925..95b82ce 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "ember-cli-qunit": "^4.1.1", "ember-cli-shims": "^1.2.0", "ember-cli-sri": "^2.1.0", + "ember-cli-testdouble-qunit": "^2.0.2", "ember-cli-uglify": "^2.0.0", "ember-disable-prototype-extensions": "^1.1.2", "ember-export-application-global": "^2.0.0", diff --git a/tests/dummy/app/services/to-stub.js b/tests/dummy/app/services/to-stub.js new file mode 100644 index 0000000..f00f2ce --- /dev/null +++ b/tests/dummy/app/services/to-stub.js @@ -0,0 +1,7 @@ +import Service from "@ember/service"; + +export default Service.extend({ + method() { + // This will be stubbed in a test + } +}); diff --git a/tests/test-helper.js b/tests/test-helper.js index 0382a84..b8a6fb0 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -1,7 +1,9 @@ -import Application from '../app'; -import config from '../config/environment'; -import { setApplication } from '@ember/test-helpers'; -import { start } from 'ember-qunit'; +import Application from "../app"; +import config from "../config/environment"; +import { setApplication } from "@ember/test-helpers"; +import { start } from "ember-qunit"; + +import "ember-cli-testdouble-qunit"; setApplication(Application.create(config.APP)); diff --git a/tests/unit/test-support/stub-service-test.js b/tests/unit/test-support/stub-service-test.js new file mode 100644 index 0000000..911b4ec --- /dev/null +++ b/tests/unit/test-support/stub-service-test.js @@ -0,0 +1,31 @@ +import { module, test } from "qunit"; +import { setupTest } from "ember-qunit"; +import { stubService } from "ember-cli-testdouble/test-support"; + +module("Test Helpers | stub-service", function(hooks) { + setupTest(hooks); + + module("as a `hooks` reciever", function(hooks) { + stubService(hooks, "to-stub"); + + test("it can replace a service", function(assert) { + let service = this.owner.lookup("service:to-stub"); + service.method(); + + assert.verify(service.method()); + }); + }); + + module("invoking without `hooks`", function(hooks) { + hooks.beforeEach(function() { + stubService("to-stub"); + }); + + test("it can replace a service", function(assert) { + let service = this.owner.lookup("service:to-stub"); + service.method(); + + assert.verify(service.method()); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index 3bed22b..29a0838 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2071,6 +2071,14 @@ ember-cli-test-loader@^2.2.0: dependencies: ember-cli-babel "^6.8.1" +ember-cli-testdouble-qunit@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ember-cli-testdouble-qunit/-/ember-cli-testdouble-qunit-2.0.2.tgz#4edbe71e71d1abff101cb36e780a24586e8ba829" + dependencies: + broccoli-funnel "^2.0.1" + ember-cli-babel "^6.6.0" + testdouble-qunit "^2.0.2" + ember-cli-uglify@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/ember-cli-uglify/-/ember-cli-uglify-2.0.2.tgz#12becdaf1a2e6f0cdbd386b1d5f5a2d0540347d3" @@ -5896,6 +5904,10 @@ temp@0.8.3: os-tmpdir "^1.0.0" rimraf "~2.2.6" +testdouble-qunit@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/testdouble-qunit/-/testdouble-qunit-2.0.2.tgz#740393c867901b9a814882b50f4c94a9e343fab9" + testdouble@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/testdouble/-/testdouble-3.5.2.tgz#7ac91d08be05bac3b2acba57c430f6c62d0ad8af"