ui: Implements a testable clipboard {{copy-button}} (#5967)
1. Remove ember-cli-clipboard dependency 2. Provide a new copy-button component implementing the same interface as ^ but make the clipboard functionality injectable 3. Provide 2 implementations of a Clipboard. One using clipboard.js (as previously) and an additional local storage 'clipboard'. 4. add a BDD step to assert whats in the clipboard (the fake one) Main reason here is that `document.exec` must be called by a user interaction
This commit is contained in:
parent
490242b4b8
commit
e4e209b748
|
@ -0,0 +1,39 @@
|
|||
import Component from '@ember/component';
|
||||
import { get } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
import WithListeners from 'consul-ui/mixins/with-listeners';
|
||||
|
||||
export default Component.extend(WithListeners, {
|
||||
clipboard: service('clipboard/os'),
|
||||
tagName: 'button',
|
||||
classNames: ['copy-btn'],
|
||||
buttonType: 'button',
|
||||
disabled: false,
|
||||
error: function() {},
|
||||
success: function() {},
|
||||
attributeBindings: [
|
||||
'clipboardText:data-clipboard-text',
|
||||
'clipboardTarget:data-clipboard-target',
|
||||
'clipboardAction:data-clipboard-action',
|
||||
'buttonType:type',
|
||||
'disabled',
|
||||
'aria-label',
|
||||
'title',
|
||||
],
|
||||
delegateClickEvent: true,
|
||||
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
const clipboard = get(this, 'clipboard').execute(
|
||||
this.delegateClickEvent ? `#${this.elementId}` : this.element
|
||||
);
|
||||
['success', 'error'].map(event => {
|
||||
return this.listen(clipboard, event, () => {
|
||||
if (!this.disabled) {
|
||||
this[event](...arguments);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
import Service from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import Clipboard from 'npm:clipboard';
|
||||
|
||||
class ClipboardCallback extends Clipboard {
|
||||
constructor(trigger, cb) {
|
||||
super(trigger);
|
||||
this._cb = cb;
|
||||
}
|
||||
onClick(e) {
|
||||
this._cb(this.text(e.delegateTarget || e.currentTarget));
|
||||
// Clipboard uses/extends `tiny-emitter`
|
||||
// TODO: We should probably fill this out to match the obj passed from
|
||||
// os implementation
|
||||
this.emit('success', {});
|
||||
}
|
||||
}
|
||||
|
||||
export default Service.extend({
|
||||
storage: window.localStorage,
|
||||
key: 'clipboard',
|
||||
execute: function(trigger) {
|
||||
return new ClipboardCallback(trigger, val => {
|
||||
get(this, 'storage').setItem(get(this, 'key'), val);
|
||||
});
|
||||
},
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
import Service from '@ember/service';
|
||||
|
||||
import Clipboard from 'npm:clipboard';
|
||||
|
||||
export default Service.extend({
|
||||
execute: function(trigger) {
|
||||
return new Clipboard(trigger);
|
||||
},
|
||||
});
|
|
@ -58,7 +58,6 @@
|
|||
"ember-cli-autoprefixer": "^0.8.1",
|
||||
"ember-cli-babel": "^6.6.0",
|
||||
"ember-cli-cjs-transform": "^1.2.0",
|
||||
"ember-cli-clipboard": "^0.9.0",
|
||||
"ember-cli-code-coverage": "^1.0.0-beta.4",
|
||||
"ember-cli-dependency-checker": "^2.0.0",
|
||||
"ember-cli-eslint": "^4.2.1",
|
||||
|
@ -102,7 +101,8 @@
|
|||
"node-sass": "^4.9.3",
|
||||
"prettier": "^1.10.2",
|
||||
"svgo": "^1.0.5",
|
||||
"text-encoding": "^0.6.4"
|
||||
"text-encoding": "^0.6.4",
|
||||
"clipboard": "^2.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^4.5 || 6.* || >= 7.*"
|
||||
|
|
|
@ -70,6 +70,9 @@ export default function(assert, library, pages, utils) {
|
|||
}
|
||||
return obj;
|
||||
};
|
||||
const clipboard = function() {
|
||||
return window.localStorage.getItem('clipboard');
|
||||
};
|
||||
models(library, utils.create);
|
||||
http(library, utils.respondWith, utils.set);
|
||||
visit(library, pages, setCurrentPage);
|
||||
|
@ -79,7 +82,7 @@ export default function(assert, library, pages, utils) {
|
|||
assertHttp(library, assert, utils.lastNthRequest);
|
||||
assertModel(library, assert, find, getCurrentPage, pauseUntil, utils.pluralize);
|
||||
assertPage(library, assert, find, getCurrentPage);
|
||||
assertDom(library, assert, pauseUntil, utils.find, utils.currentURL);
|
||||
assertDom(library, assert, pauseUntil, utils.find, utils.currentURL, clipboard);
|
||||
assertForm(library, assert, find, getCurrentPage);
|
||||
|
||||
return library.given(["I'm using a legacy token"], function(number, model, data) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export default function(scenario, assert, pauseUntil, find, currentURL) {
|
||||
export default function(scenario, assert, pauseUntil, find, currentURL, clipboard) {
|
||||
scenario
|
||||
.then('pause until I see the text "$text" in "$selector"', function(text, selector) {
|
||||
return pauseUntil(function(resolve) {
|
||||
|
@ -18,6 +18,13 @@ export default function(scenario, assert, pauseUntil, find, currentURL) {
|
|||
`Expected to see "${text}" in "${selector}"`
|
||||
);
|
||||
})
|
||||
.then(['I copied "$text"'], function(text) {
|
||||
const copied = clipboard();
|
||||
assert.ok(
|
||||
copied.indexOf(text) !== -1,
|
||||
`Expected to see "${text}" in the clipboard, was "${copied}"`
|
||||
);
|
||||
})
|
||||
.then(['I see the exact text "$text" in "$selector"'], function(text, selector) {
|
||||
assert.ok(
|
||||
find(selector).textContent.trim() === text,
|
||||
|
|
|
@ -6,6 +6,8 @@ import './helpers/flash-message';
|
|||
import loadEmberExam from 'ember-exam/test-support/load';
|
||||
|
||||
loadEmberExam();
|
||||
setApplication(Application.create(config.APP));
|
||||
const application = Application.create(config.APP);
|
||||
application.inject('component:copy-button', 'clipboard', 'service:clipboard/local-storage');
|
||||
setApplication(application);
|
||||
|
||||
start();
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('service:clipboard/local-storage', 'Unit | Service | clipboard/local storage', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['service:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let service = this.subject();
|
||||
assert.ok(service);
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('service:clipboard/os', 'Unit | Service | clipboard/os', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['service:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let service = this.subject();
|
||||
assert.ok(service);
|
||||
});
|
|
@ -2600,7 +2600,7 @@ broccoli-middleware@^1.0.0:
|
|||
handlebars "^4.0.4"
|
||||
mime-types "^2.1.18"
|
||||
|
||||
broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.3:
|
||||
broccoli-persistent-filter@^1.1.6, broccoli-persistent-filter@^1.4.0, broccoli-persistent-filter@^1.4.3:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.3.tgz#3511bc52fc53740cda51621f58a28152d9911bc1"
|
||||
dependencies:
|
||||
|
@ -2710,7 +2710,7 @@ broccoli-sri-hash@^2.1.0:
|
|||
sri-toolbox "^0.2.0"
|
||||
symlink-or-copy "^1.0.1"
|
||||
|
||||
broccoli-stew@^1.2.0, broccoli-stew@^1.3.3, broccoli-stew@^1.5.0:
|
||||
broccoli-stew@^1.2.0, broccoli-stew@^1.3.3:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-1.5.0.tgz#d7af8c18511dce510e49d308a62e5977f461883c"
|
||||
dependencies:
|
||||
|
@ -3306,9 +3306,10 @@ cli-width@^2.0.0:
|
|||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639"
|
||||
|
||||
clipboard@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.1.tgz#a12481e1c13d8a50f5f036b0560fe5d16d74e46a"
|
||||
clipboard@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d"
|
||||
integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==
|
||||
dependencies:
|
||||
good-listener "^1.2.2"
|
||||
select "^1.1.2"
|
||||
|
@ -4194,7 +4195,7 @@ ember-cli-babel-plugin-helpers@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.0.tgz#de3baedd093163b6c2461f95964888c1676325ac"
|
||||
integrity sha512-Zr4my8Xn+CzO0gIuFNXji0eTRml5AxZUTDQz/wsNJ5AJAtyFWCY4QtKdoELNNbiCVGt1lq5yLiwTm4scGKu6xA==
|
||||
|
||||
ember-cli-babel@6.12.0, ember-cli-babel@^6.0.0, ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.10.0, ember-cli-babel@^6.11.0, ember-cli-babel@^6.12.0, ember-cli-babel@^6.3.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.7.2, ember-cli-babel@^6.8.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.9.0, ember-cli-babel@^6.9.2:
|
||||
ember-cli-babel@6.12.0, ember-cli-babel@^6.0.0, ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.10.0, ember-cli-babel@^6.11.0, ember-cli-babel@^6.12.0, ember-cli-babel@^6.3.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.7.2, ember-cli-babel@^6.8.1, ember-cli-babel@^6.9.0, ember-cli-babel@^6.9.2:
|
||||
version "6.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-6.12.0.tgz#3adcdbe1278da1fcd0b9038f1360cb4ac5d4414c"
|
||||
dependencies:
|
||||
|
@ -4343,16 +4344,6 @@ ember-cli-cjs-transform@^1.2.0:
|
|||
rollup-plugin-node-resolve "^3.3.0"
|
||||
username "^3.0.0"
|
||||
|
||||
ember-cli-clipboard@^0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-clipboard/-/ember-cli-clipboard-0.9.0.tgz#c0cfce1a8a81ba1646e54bff9d41249b8bc507f7"
|
||||
dependencies:
|
||||
broccoli-funnel "^1.1.0"
|
||||
clipboard "^2.0.0"
|
||||
ember-cli-babel "^6.8.0"
|
||||
ember-cli-htmlbars "^2.0.2"
|
||||
fastboot-transform "0.1.1"
|
||||
|
||||
ember-cli-code-coverage@^1.0.0-beta.4:
|
||||
version "1.0.0-beta.6"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-code-coverage/-/ember-cli-code-coverage-1.0.0-beta.6.tgz#7da5dc4e2eb7c207b827b6cbdf91a96d0cca0983"
|
||||
|
@ -4425,15 +4416,6 @@ ember-cli-htmlbars@^2.0.1, ember-cli-htmlbars@^2.0.3:
|
|||
json-stable-stringify "^1.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
ember-cli-htmlbars@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-2.0.3.tgz#e116e1500dba12f29c94b05b9ec90f52cb8bb042"
|
||||
dependencies:
|
||||
broccoli-persistent-filter "^1.0.3"
|
||||
hash-for-dep "^1.0.2"
|
||||
json-stable-stringify "^1.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
ember-cli-htmlbars@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-3.0.0.tgz#4977b9eddbc725f8da25090ecdbba64533b2eadc"
|
||||
|
@ -5716,12 +5698,6 @@ fast-sourcemap-concat@^1.0.1:
|
|||
source-map-url "^0.3.0"
|
||||
sourcemap-validator "^1.0.5"
|
||||
|
||||
fastboot-transform@0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fastboot-transform/-/fastboot-transform-0.1.1.tgz#de55550d85644ec94cb11264c2ba883e3ea3b255"
|
||||
dependencies:
|
||||
broccoli-stew "^1.5.0"
|
||||
|
||||
faye-websocket@~0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
|
||||
|
|
Loading…
Reference in New Issue