From a5c16a1b609c3d0e2b9f16721cddde3681becc39 Mon Sep 17 00:00:00 2001 From: Daniel Kmak Date: Sat, 6 Aug 2016 15:15:04 +0200 Subject: [PATCH] Upgrade to CLI 2.8.0-beta.2. Add unit tests. SRP in Mixin. --- .editorconfig | 14 ---- .jshintrc | 2 +- .npmignore | 20 ++--- .travis.yml | 16 ++-- LICENSE.md | 2 +- addon/initializers/allow-link-action.js | 6 +- addon/mixins/link-action.js | 25 +++--- bower.json | 12 +-- config/ember-try.js | 51 ++++++++---- ember-cli-build.js | 2 +- package.json | 39 ++++----- testem.js | 13 +++ tests/.jshintrc | 2 +- tests/acceptance/link-action-test.js | 36 ++++----- tests/dummy/app/app.js | 4 +- tests/dummy/app/index.html | 16 ++-- tests/dummy/app/resolver.js | 3 + tests/dummy/app/router.js | 3 +- tests/dummy/config/environment.js | 3 +- tests/helpers/module-for-acceptance.js | 12 +-- tests/helpers/resolver.js | 2 +- tests/index.html | 33 ++++---- tests/unit/mixins/link-action-test.js | 102 ++++++++++++++++++++++++ 23 files changed, 269 insertions(+), 149 deletions(-) create mode 100644 testem.js create mode 100644 tests/dummy/app/resolver.js create mode 100644 tests/unit/mixins/link-action-test.js diff --git a/.editorconfig b/.editorconfig index 47c5438..219985c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,22 +13,8 @@ insert_final_newline = true indent_style = space indent_size = 2 -[*.js] -indent_style = space -indent_size = 2 - [*.hbs] insert_final_newline = false -indent_style = space -indent_size = 2 - -[*.css] -indent_style = space -indent_size = 2 - -[*.html] -indent_style = space -indent_size = 2 [*.{diff,md}] trim_trailing_whitespace = false diff --git a/.jshintrc b/.jshintrc index 08096ef..d421faa 100644 --- a/.jshintrc +++ b/.jshintrc @@ -27,6 +27,6 @@ "strict": false, "white": false, "eqnull": true, - "esnext": true, + "esversion": 6, "unused": true } diff --git a/.npmignore b/.npmignore index 49996f5..fa8b147 100644 --- a/.npmignore +++ b/.npmignore @@ -1,14 +1,16 @@ -bower_components/ -tests/ -tmp/ -dist/ - +/bower_components +/config/ember-try.js +/dist +/tests +/tmp +**/.gitkeep .bowerrc .editorconfig .ember-cli +.gitignore +.jshintrc +.watchmanconfig .travis.yml -.npmignore -**/.gitkeep bower.json -Brocfile.js -testem.json +ember-cli-build.js +testem.js diff --git a/.travis.yml b/.travis.yml index 8197d31..794f9c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ --- language: node_js node_js: - - "0.12" + - "4" sudo: false @@ -11,6 +11,7 @@ cache: env: - EMBER_TRY_SCENARIO=default + - EMBER_TRY_SCENARIO=ember-1.13 - EMBER_TRY_SCENARIO=ember-release - EMBER_TRY_SCENARIO=ember-beta - EMBER_TRY_SCENARIO=ember-canary @@ -21,14 +22,17 @@ matrix: - env: EMBER_TRY_SCENARIO=ember-canary before_install: - - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH - - "npm config set spin false" - - "npm install -g npm@^2" + - npm config set spin false + - npm install -g bower + - bower --version + - npm install phantomjs-prebuilt + - node_modules/phantomjs-prebuilt/bin/phantomjs --version install: - - npm install -g bower - npm install - bower install script: - - ember try $EMBER_TRY_SCENARIO test + # Usually, it's ok to finish the test scenario without reverting + # to the addon's original dependency state, skipping "cleanup". + - ember try:one $EMBER_TRY_SCENARIO test --skip-cleanup diff --git a/LICENSE.md b/LICENSE.md index 00e9fbb..02000b5 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 +Copyright (c) 2016 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/addon/initializers/allow-link-action.js b/addon/initializers/allow-link-action.js index 5af755f..32204a8 100644 --- a/addon/initializers/allow-link-action.js +++ b/addon/initializers/allow-link-action.js @@ -1,11 +1,13 @@ import Ember from 'ember'; import LinkActionMixin from '../mixins/link-action'; +const { LinkComponent } = Ember; + export function initialize() { - Ember.LinkComponent.reopen(LinkActionMixin); + LinkComponent.reopen(LinkActionMixin); } export default { name: 'allow-link-action', - initialize: initialize + initialize }; diff --git a/addon/mixins/link-action.js b/addon/mixins/link-action.js index b32a071..aed9b9f 100644 --- a/addon/mixins/link-action.js +++ b/addon/mixins/link-action.js @@ -1,25 +1,28 @@ import Ember from 'ember'; -export default Ember.Mixin.create({ - _sendInvokeAction() { - this.sendAction('invokeAction'); - }, +const { Mixin } = Ember; +export default Mixin.create({ init() { this._super(...arguments); - // Map desired event name to invoke function - const eventName = this.get('eventName'); - if (this.get('invokeAction')) { - this.on(eventName, this, this._sendInvokeAction); + this._attachActionEvent(); } - }, - willDestroyElement() { if (this.get('invokeAction')) { - this.off(this.get('eventName'), this, this._sendInvokeAction); + this._detachActionEvent(); } + }, + + _sendInvokeAction() { + this.sendAction('invokeAction'); + }, + _attachActionEvent() { + this.on(this.get('eventName'), this, this._sendInvokeAction); + }, + _detachActionEvent() { + this.off(this.get('eventName'), this, this._sendInvokeAction); } }); diff --git a/bower.json b/bower.json index 0d85be2..72da95f 100644 --- a/bower.json +++ b/bower.json @@ -1,15 +1,7 @@ { "name": "ember-link-action", "dependencies": { - "ember": "2.0.2", - "ember-cli-shims": "0.0.6", - "ember-cli-test-loader": "0.2.1", - "ember-load-initializers": "0.1.7", - "ember-qunit": "0.4.16", - "ember-qunit-notifications": "0.1.0", - "ember-resolver": "~0.1.20", - "jquery": "^1.11.3", - "loader.js": "ember-cli/loader.js#3.4.0", - "qunit": "~1.20.0" + "ember": "~2.8.0-beta.1", + "ember-cli-shims": "0.1.1" } } diff --git a/config/ember-try.js b/config/ember-try.js index 3e88bc6..014f603 100644 --- a/config/ember-try.js +++ b/config/ember-try.js @@ -3,33 +3,52 @@ module.exports = { scenarios: [ { name: 'default', - dependencies: { } + bower: { + dependencies: { } + } + }, + { + name: 'ember-1.13', + bower: { + dependencies: { + 'ember': '~1.13.0' + }, + resolutions: { + 'ember': '~1.13.0' + } + } }, { name: 'ember-release', - dependencies: { - 'ember': 'components/ember#release' - }, - resolutions: { - 'ember': 'release' + bower: { + dependencies: { + 'ember': 'components/ember#release' + }, + resolutions: { + 'ember': 'release' + } } }, { name: 'ember-beta', - dependencies: { - 'ember': 'components/ember#beta' - }, - resolutions: { - 'ember': 'beta' + bower: { + dependencies: { + 'ember': 'components/ember#beta' + }, + resolutions: { + 'ember': 'beta' + } } }, { name: 'ember-canary', - dependencies: { - 'ember': 'components/ember#canary' - }, - resolutions: { - 'ember': 'canary' + bower: { + dependencies: { + 'ember': 'components/ember#canary' + }, + resolutions: { + 'ember': 'canary' + } } } ] diff --git a/ember-cli-build.js b/ember-cli-build.js index c8c48f8..4ac3913 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -8,7 +8,7 @@ module.exports = function(defaults) { }); /* - This build file specifes the options for the dummy test app of this + This build file specifies the options for the dummy test app of this addon, located in `/tests/dummy` This build file does *not* influence how the addon or the app using it behave. You most likely want to be modifying `./index.js` or app's build file diff --git a/package.json b/package.json index 3ff6467..6512b31 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "build": "ember build", "start": "ember server", - "test": "ember try:testall" + "test": "ember try:each" }, "repository": { "type": "git", @@ -21,24 +21,28 @@ "author": "Daniel 'Kuzirashi' Kmak", "license": "MIT", "devDependencies": { - "broccoli-asset-rev": "^2.2.0", - "ember-cli": "1.13.13", + "broccoli-asset-rev": "^2.4.2", + "ember-cli": "2.8.0-beta.2", + "ember-ajax": "^2.0.1", "ember-cli-app-version": "^1.0.0", - "ember-cli-content-security-policy": "0.4.0", - "ember-cli-dependency-checker": "^1.1.0", - "ember-cli-htmlbars": "^1.0.1", + "ember-cli-dependency-checker": "^1.2.0", + "ember-cli-htmlbars": "^1.0.3", "ember-cli-htmlbars-inline-precompile": "^0.3.1", - "ember-cli-ic-ajax": "0.2.4", - "ember-cli-inject-live-reload": "^1.3.1", - "ember-cli-qunit": "^1.0.4", - "ember-cli-release": "0.2.8", - "ember-cli-sri": "^1.2.0", + "ember-cli-inject-live-reload": "^1.4.0", + "ember-cli-qunit": "^2.1.0", + "ember-cli-release": "^0.2.9", + "ember-cli-sri": "^2.1.0", + "ember-cli-test-loader": "^1.1.0", "ember-cli-uglify": "^1.2.0", - "ember-disable-prototype-extensions": "^1.0.0", - "ember-disable-proxy-controllers": "^1.0.1", - "ember-export-application-global": "^1.0.4", - "ember-try": "~0.0.8", - "handlebars": "^1.3.0" + "ember-export-application-global": "^1.0.5", + "ember-load-initializers": "^0.5.1", + "ember-resolver": "^2.0.3", + "ember-disable-prototype-extensions": "^1.1.0", + "ember-cli-jshint": "^1.0.0", + "loader.js": "^4.0.1" + }, + "dependencies": { + "ember-cli-babel": "^5.1.6" }, "keywords": [ "ember-addon", @@ -50,9 +54,6 @@ "action", "addon" ], - "dependencies": { - "ember-cli-babel": "^5.1.5" - }, "ember-addon": { "configPath": "tests/dummy/config" } diff --git a/testem.js b/testem.js new file mode 100644 index 0000000..26044b2 --- /dev/null +++ b/testem.js @@ -0,0 +1,13 @@ +/*jshint node:true*/ +module.exports = { + "framework": "qunit", + "test_page": "tests/index.html?hidepassed", + "disable_watching": true, + "launch_in_ci": [ + "PhantomJS" + ], + "launch_in_dev": [ + "PhantomJS", + "Chrome" + ] +}; diff --git a/tests/.jshintrc b/tests/.jshintrc index 6ec0b7c..d2bd113 100644 --- a/tests/.jshintrc +++ b/tests/.jshintrc @@ -47,6 +47,6 @@ "strict": false, "white": false, "eqnull": true, - "esnext": true, + "esversion": 6, "unused": true } diff --git a/tests/acceptance/link-action-test.js b/tests/acceptance/link-action-test.js index a973eb0..aee4f94 100644 --- a/tests/acceptance/link-action-test.js +++ b/tests/acceptance/link-action-test.js @@ -1,20 +1,18 @@ -/* global getRegistry */ - import Ember from 'ember'; import { test } from 'qunit'; import moduleForAcceptance from '../../tests/helpers/module-for-acceptance'; import hbs from 'htmlbars-inline-precompile'; -moduleForAcceptance('Acceptance | link action'); +const { Controller } = Ember; -Ember.Test.registerHelper('getRegistry', app => app.registry); +moduleForAcceptance('Acceptance | link action'); test('clicking {{link-to}} with closure action specified correctly transition to other route and triggers an action', function(assert) { assert.expect(3); - const registry = getRegistry(); + const { application } = this; - registry.register('controller:link-action', Ember.Controller.extend({ + application.register('controller:link-action', Controller.extend({ actions: { testAction() { assert.ok('test action fired'); @@ -22,7 +20,7 @@ test('clicking {{link-to}} with closure action specified correctly transition to } })); - registry.register('template:link-action', hbs` + application.register('template:link-action', hbs` {{#link-to 'other-route' invokeAction=(action 'testAction')}} Link to other route {{/link-to}} @@ -40,9 +38,9 @@ test('clicking {{link-to}} with closure action specified correctly transition to test('clicking {{link-to}} with action name specified correctly transition to other route and triggers an action', function(assert) { assert.expect(3); - const registry = getRegistry(); + const { application } = this; - registry.register('controller:link-action', Ember.Controller.extend({ + application.register('controller:link-action', Controller.extend({ actions: { testAction() { assert.ok('test action fired'); @@ -50,31 +48,27 @@ test('clicking {{link-to}} with action name specified correctly transition to ot } })); - registry.register('template:link-action', hbs` + application.register('template:link-action', hbs` {{#link-to 'other-route' invokeAction='testAction'}} Link to other route {{/link-to}} `); visit('/link-action'); - - andThen(() => { - assert.equal(currentURL(), '/link-action'); - }); + + andThen(() => assert.equal(currentURL(), '/link-action')); click('a'); - andThen(() => { - assert.equal(currentURL(), '/other-route'); - }); + andThen(() => assert.equal(currentURL(), '/other-route')); }); -test('action parameters can be passed to invoked action', assert => { +test('action parameters can be passed to invoked action', function(assert) { assert.expect(2); - const registry = getRegistry(); + const { application } = this; - registry.register('controller:link-action', Ember.Controller.extend({ + application.register('controller:link-action', Controller.extend({ actions: { testAction(param1, param2) { assert.equal(param1, 'value1', 'param1 has value of value1'); @@ -83,7 +77,7 @@ test('action parameters can be passed to invoked action', assert => { } })); - registry.register('template:link-action', hbs` + application.register('template:link-action', hbs` {{#link-to 'other-route' invokeAction=(action 'testAction' 'value1' 'value2')}} Link to other route {{/link-to}} diff --git a/tests/dummy/app/app.js b/tests/dummy/app/app.js index 8b234d6..831ad61 100644 --- a/tests/dummy/app/app.js +++ b/tests/dummy/app/app.js @@ -1,6 +1,6 @@ import Ember from 'ember'; -import Resolver from 'ember/resolver'; -import loadInitializers from 'ember/load-initializers'; +import Resolver from './resolver'; +import loadInitializers from 'ember-load-initializers'; import config from './config/environment'; let App; diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html index 1c49d36..5120bd7 100644 --- a/tests/dummy/app/index.html +++ b/tests/dummy/app/index.html @@ -7,19 +7,19 @@ - {{content-for 'head'}} + {{content-for "head"}} - - + + - {{content-for 'head-footer'}} + {{content-for "head-footer"}} - {{content-for 'body'}} + {{content-for "body"}} - - + + - {{content-for 'body-footer'}} + {{content-for "body-footer"}} diff --git a/tests/dummy/app/resolver.js b/tests/dummy/app/resolver.js new file mode 100644 index 0000000..2fb563d --- /dev/null +++ b/tests/dummy/app/resolver.js @@ -0,0 +1,3 @@ +import Resolver from 'ember-resolver'; + +export default Resolver; diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index a49d37e..8208002 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -2,7 +2,8 @@ import Ember from 'ember'; import config from './config/environment'; const Router = Ember.Router.extend({ - location: config.locationType + location: config.locationType, + rootURL: config.rootURL }); Router.map(function() { diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js index c59bcd5..2529939 100644 --- a/tests/dummy/config/environment.js +++ b/tests/dummy/config/environment.js @@ -4,7 +4,7 @@ module.exports = function(environment) { var ENV = { modulePrefix: 'dummy', environment: environment, - baseURL: '/', + rootURL: '/', locationType: 'auto', EmberENV: { FEATURES: { @@ -29,7 +29,6 @@ module.exports = function(environment) { if (environment === 'test') { // Testem prefers this... - ENV.baseURL = '/'; ENV.locationType = 'none'; // keep test console output quieter diff --git a/tests/helpers/module-for-acceptance.js b/tests/helpers/module-for-acceptance.js index ed23003..76996fd 100644 --- a/tests/helpers/module-for-acceptance.js +++ b/tests/helpers/module-for-acceptance.js @@ -1,23 +1,23 @@ import { module } from 'qunit'; +import Ember from 'ember'; import startApp from '../helpers/start-app'; import destroyApp from '../helpers/destroy-app'; +const { RSVP: { Promise } } = Ember; + export default function(name, options = {}) { module(name, { beforeEach() { this.application = startApp(); if (options.beforeEach) { - options.beforeEach.apply(this, arguments); + return options.beforeEach.apply(this, arguments); } }, afterEach() { - destroyApp(this.application); - - if (options.afterEach) { - options.afterEach.apply(this, arguments); - } + let afterEach = options.afterEach && options.afterEach.apply(this, arguments); + return Promise.resolve(afterEach).then(() => destroyApp(this.application)); } }); } diff --git a/tests/helpers/resolver.js b/tests/helpers/resolver.js index ebfb4e4..b208d38 100644 --- a/tests/helpers/resolver.js +++ b/tests/helpers/resolver.js @@ -1,4 +1,4 @@ -import Resolver from 'ember/resolver'; +import Resolver from '../../resolver'; import config from '../../config/environment'; const resolver = Resolver.create(); diff --git a/tests/index.html b/tests/index.html index 5e88e5e..f7ff652 100644 --- a/tests/index.html +++ b/tests/index.html @@ -7,28 +7,27 @@ - {{content-for 'head'}} - {{content-for 'test-head'}} + {{content-for "head"}} + {{content-for "test-head"}} - - - + + + - {{content-for 'head-footer'}} - {{content-for 'test-head-footer'}} + {{content-for "head-footer"}} + {{content-for "test-head-footer"}} - {{content-for 'body'}} - {{content-for 'test-body'}} + {{content-for "body"}} + {{content-for "test-body"}} - - - - - - + + + + + - {{content-for 'body-footer'}} - {{content-for 'test-body-footer'}} + {{content-for "body-footer"}} + {{content-for "test-body-footer"}} diff --git a/tests/unit/mixins/link-action-test.js b/tests/unit/mixins/link-action-test.js new file mode 100644 index 0000000..4e14ef5 --- /dev/null +++ b/tests/unit/mixins/link-action-test.js @@ -0,0 +1,102 @@ +import Ember from 'ember'; +import LinkActionMixin from 'ember-link-action/mixins/link-action'; +import { module, test } from 'qunit'; + +const { Evented } = Ember; + +module('Unit | Mixin | link action'); + +test('it exists', function(assert) { + assert.expect(1); + + const LinkActionObject = Ember.Object.extend(LinkActionMixin); + const subject = LinkActionObject.create(); + + assert.ok(subject); +}); + +test('_sendInvokeAction sends `invokeAction` action', function(assert) { + assert.expect(2); + + const EXPECTED_ACTION_NAME = 'invokeAction'; + + const LinkActionObject = Ember.Object.extend(LinkActionMixin); + const subject = LinkActionObject.create({ + sendAction(actionName) { + assert.ok(true, 'sendAction is called'); + assert.equal(actionName, EXPECTED_ACTION_NAME); + } + }); + + subject._sendInvokeAction(); +}); + +test('_attachActionEvent is called on initialization if invokeAction is specified', function(assert) { + assert.expect(1); + + const LinkActionObject = Ember.Object.extend(LinkActionMixin); + + LinkActionObject.create({ + invokeAction: 'someAction', + _attachActionEvent() { + assert.ok(true, 'sendAction is called'); + } + }); +}); + +test('_detachActionEvent is called when willDestroyElement is called and invokeAction is specified', function(assert) { + assert.expect(1); + + const LinkActionObject = Ember.Object.extend(LinkActionMixin); + const subject = LinkActionObject.create({ + invokeAction: 'someAction', + _attachActionEvent() {}, + _detachActionEvent() { + assert.ok(true); + } + }); + + subject.willDestroyElement(); +}); + +test('_attachActionEvent subscribes _sendInvokeAction to `eventName` event', function(assert) { + assert.expect(1); + + const EXAMPLE_EVENT_NAME = 'click'; + + const LinkActionObject = Ember.Object.extend(LinkActionMixin, Evented); + const subject = LinkActionObject.create({ + eventName: EXAMPLE_EVENT_NAME, + _sendInvokeAction() { + assert.ok(true); + } + }); + + subject.set('invokeAction', 'someAction'); + subject.trigger(EXAMPLE_EVENT_NAME); + + subject._attachActionEvent(); + subject.trigger(EXAMPLE_EVENT_NAME); +}); + +test('_detachActionEvent unsubscribes _sendInvokeAction from `eventName` event', function(assert) { + assert.expect(0); + + const EXAMPLE_EVENT_NAME = 'click'; + + const LinkActionObject = Ember.Object.extend(LinkActionMixin, Evented); + const subject = LinkActionObject.create({ + eventName: EXAMPLE_EVENT_NAME, + _sendInvokeAction() { + assert.ok(false); + } + }); + + subject.set('invokeAction', 'someAction'); + + subject._attachActionEvent(); + + subject._detachActionEvent(); + + subject.trigger(EXAMPLE_EVENT_NAME); +});