Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add test helper for stubbing services #12

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 22 additions & 23 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
)
}
]
};
7 changes: 1 addition & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ language: node_js
node_js:
# we recommend testing addons with the same minimum supported node version as Ember CLI
# so that your addon works for all apps
- "4"
- "6"

sudo: false
dist: trusty
Expand Down Expand Up @@ -35,11 +35,6 @@ matrix:
allow_failures:
- env: EMBER_TRY_SCENARIO=ember-canary

before_install:
- npm config set spin false
- npm install -g npm@4
- npm --version

script:
- npm run lint:js
# Usually, it's ok to finish the test scenario without reverting
Expand Down
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,28 @@ 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() {
// `stubService` returns a reference to the servive
let someStubbedService = stubService("some-service");

// Do something that would call `method()` on the service

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
1 change: 1 addition & 0 deletions addon-test-support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as stubService } from "./stub-service";
42 changes: 42 additions & 0 deletions addon-test-support/stub-service.js
Original file line number Diff line number Diff line change
@@ -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();

return replace(owner, name);
} else {
throw new Error("Unexpected number of arguments");
}
}
39 changes: 20 additions & 19 deletions config/ember-try.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,66 @@
'use strict';
"use strict";

const getChannelURL = require('ember-source-channel-url');
const getChannelURL = require("ember-source-channel-url");

module.exports = function() {
return Promise.all([
getChannelURL('release'),
getChannelURL('beta'),
getChannelURL('canary'),
]).then((urls) => {
getChannelURL("release"),
getChannelURL("beta"),
getChannelURL("canary")
]).then(urls => {
return {
useYarn: true,
scenarios: [
{
name: 'ember-lts-2.12',
name: "ember-lts-2.12",
npm: {
devDependencies: {
'ember-source': '~2.12.0'
"ember-source": "~2.12.0"
}
}
},
{
name: 'ember-lts-2.16',
name: "ember-lts-2.16",
npm: {
devDependencies: {
'ember-source': '~2.16.0'
"ember-source": "~2.16.0"
}
}
},
{
name: 'ember-lts-2.18',
name: "ember-lts-2.18",
npm: {
devDependencies: {
'ember-source': '~2.18.0'
"ember-source": "~2.18.0"
}
}
},
{
name: 'ember-release',
name: "ember-release",
npm: {
devDependencies: {
'ember-source': urls[0]
"ember-source": urls[0]
}
}
},
{
name: 'ember-beta',
name: "ember-beta",
npm: {
devDependencies: {
'ember-source': urls[1]
"ember-source": urls[1]
}
}
},
{
name: 'ember-canary',
name: "ember-canary",
npm: {
devDependencies: {
'ember-source': urls[2]
"ember-source": urls[2]
}
}
},
{
name: 'ember-default',
name: "ember-default",
npm: {
devDependencies: {}
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
7 changes: 7 additions & 0 deletions tests/dummy/app/services/to-stub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Service from "@ember/service";

export default Service.extend({
method() {
// This will be stubbed in a test
}
});
10 changes: 6 additions & 4 deletions tests/test-helper.js
Original file line number Diff line number Diff line change
@@ -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";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created this addon and the library it wraps, testdouble-qunit, which just adds the assert.verify method used below, which mirror td.verify but reports more nicely into the QUnit test results and doesn't blow up the whole test on a single failure. Also removes the need to use assert.expect(0).


setApplication(Application.create(config.APP));

Expand Down
36 changes: 36 additions & 0 deletions tests/unit/test-support/stub-service-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
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() {
this.service = 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());
assert.equal(
service,
this.service,
"Returns a references to the stubbed service"
);
});
});
});
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -5896,6 +5904,10 @@ [email protected]:
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"
Expand Down