From e7e38a18e0158ed9c47f5256f8c0dd1a97d54995 Mon Sep 17 00:00:00 2001 From: Beto Muniz Date: Thu, 15 Apr 2021 00:59:47 -0300 Subject: [PATCH] Migrate clipboard-action-default to functional approach. Update tests. Add tests --- dist/clipboard.js | 227 +++++++++---------------------- dist/clipboard.min.js | 2 +- src/clipboard-action-default.js | 159 ++++++---------------- src/clipboard.js | 27 ++-- test/clipboard-action-copy.js | 2 +- test/clipboard-action-cut.js | 2 +- test/clipboard-action-default.js | 125 ++--------------- test/clipboard.js | 58 ++++++-- test/common/command.js | 32 +++-- 9 files changed, 198 insertions(+), 436 deletions(-) diff --git a/dist/clipboard.js b/dist/clipboard.js index 0223e77..e98e221 100644 --- a/dist/clipboard.js +++ b/dist/clipboard.js @@ -125,170 +125,66 @@ var ClipboardActionCopy = function ClipboardActionCopy(target) { ;// CONCATENATED MODULE: ./src/clipboard-action-default.js function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } - -function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } - /** - * Inner class which performs selection from either `text` or `target` + * Inner function which performs selection from either `text` or `target` * properties and then executes copy or cut operations. + * @param {Object} options */ -var ClipboardActionDefault = /*#__PURE__*/function () { - /** - * @param {Object} options - */ - function ClipboardActionDefault(options) { - _classCallCheck(this, ClipboardActionDefault); +var ClipboardActionDefault = function ClipboardActionDefault() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + // Defines base properties passed from constructor. + var _options$action = options.action, + action = _options$action === void 0 ? 'copy' : _options$action, + container = options.container, + target = options.target, + text = options.text; // Sets the `action` to be performed which can be either 'copy' or 'cut'. - this.resolveOptions(options); - this.initSelection(); + if (action !== 'copy' && action !== 'cut') { + throw new Error('Invalid "action" value, use either "copy" or "cut"'); + } // Sets the `target` property using an element that will be have its content copied. + + + if (target !== undefined) { + if (target && _typeof(target) === 'object' && target.nodeType === 1) { + if (action === 'copy' && target.hasAttribute('disabled')) { + throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); + } + + if (action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) { + throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); + } + } else { + throw new Error('Invalid "target" value, use a valid Element'); + } + } // Define selection strategy based on `text` property. + + + if (text) { + return clipboard_action_copy(text, { + container: container + }); + } // Defines which selection strategy based on `target` property. + + + if (target) { + return action === 'cut' ? clipboard_action_cut(target) : clipboard_action_copy(target, { + container: container + }); } - /** - * Defines base properties passed from constructor. - * @param {Object} options - */ - - - _createClass(ClipboardActionDefault, [{ - key: "resolveOptions", - value: function resolveOptions() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - this.action = options.action; - this.container = options.container; - this.emitter = options.emitter; - this.target = options.target; - this.text = options.text; - this.trigger = options.trigger; - this.selectedText = ''; - } - /** - * Decides which selection strategy is going to be applied based - * on the existence of `text` and `target` properties. - */ - - }, { - key: "initSelection", - value: function initSelection() { - if (this.text) { - this.selectedText = clipboard_action_copy(this.text, { - container: this.container - }); - } else if (this.target) { - if (this.action === 'cut') { - this.selectedText = clipboard_action_cut(this.target); - } else if (this.action === 'copy') { - this.selectedText = clipboard_action_copy(this.target, { - container: this.container - }); - } - } - - this.handleResult(Boolean(this.selectedText)); - } - /** - * Fires an event based on the copy operation result. - * @param {Boolean} succeeded - */ - - }, { - key: "handleResult", - value: function handleResult(succeeded) { - this.emitter.emit(succeeded ? 'success' : 'error', { - action: this.action, - text: this.selectedText, - trigger: this.trigger, - clearSelection: this.clearSelection.bind(this) - }); - } - /** - * Moves focus away from `target` and back to the trigger, removes current selection. - */ - - }, { - key: "clearSelection", - value: function clearSelection() { - if (this.trigger) { - this.trigger.focus(); - } - - document.activeElement.blur(); - window.getSelection().removeAllRanges(); - } - /** - * Sets the `action` to be performed which can be either 'copy' or 'cut'. - * @param {String} action - */ - - }, { - key: "action", - set: function set() { - var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy'; - this._action = action; - - if (this._action !== 'copy' && this._action !== 'cut') { - throw new Error('Invalid "action" value, use either "copy" or "cut"'); - } - } - /** - * Gets the `action` property. - * @return {String} - */ - , - get: function get() { - return this._action; - } - /** - * Sets the `target` property using an element - * that will be have its content copied. - * @param {Element} target - */ - - }, { - key: "target", - set: function set(target) { - if (target !== undefined) { - if (target && _typeof(target) === 'object' && target.nodeType === 1) { - if (this.action === 'copy' && target.hasAttribute('disabled')) { - throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute'); - } - - if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) { - throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes'); - } - - this._target = target; - } else { - throw new Error('Invalid "target" value, use a valid Element'); - } - } - } - /** - * Gets the `target` property. - * @return {String|HTMLElement} - */ - , - get: function get() { - return this._target; - } - }]); - - return ClipboardActionDefault; -}(); +}; /* harmony default export */ var clipboard_action_default = (ClipboardActionDefault); ;// CONCATENATED MODULE: ./src/clipboard.js function clipboard_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { clipboard_typeof = function _typeof(obj) { return typeof obj; }; } else { clipboard_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return clipboard_typeof(obj); } -function clipboard_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function clipboard_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } -function clipboard_createClass(Constructor, protoProps, staticProps) { if (protoProps) clipboard_defineProperties(Constructor.prototype, protoProps); if (staticProps) clipboard_defineProperties(Constructor, staticProps); return Constructor; } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } @@ -342,7 +238,7 @@ var Clipboard = /*#__PURE__*/function (_Emitter) { function Clipboard(trigger, options) { var _this; - clipboard_classCallCheck(this, Clipboard); + _classCallCheck(this, Clipboard); _this = _super.call(this); _this.ClipboardActionCut = clipboard_action_cut.bind(_assertThisInitialized(_this)); @@ -361,7 +257,7 @@ var Clipboard = /*#__PURE__*/function (_Emitter) { */ - clipboard_createClass(Clipboard, [{ + _createClass(Clipboard, [{ key: "resolveOptions", value: function resolveOptions() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; @@ -393,18 +289,25 @@ var Clipboard = /*#__PURE__*/function (_Emitter) { key: "onClick", value: function onClick(e) { var trigger = e.delegateTarget || e.currentTarget; - - if (this.clipboardActionDefault) { - this.clipboardActionDefault = null; - } - - this.clipboardActionDefault = new clipboard_action_default({ + var selectedText = clipboard_action_default({ action: this.action(trigger), - target: this.target(trigger), - text: this.text(trigger), container: this.container, + target: this.target(trigger), + text: this.text(trigger) + }); // Fires an event based on the copy operation result. + + this.emit(selectedText ? 'success' : 'error', { + action: this.action, + text: selectedText, trigger: trigger, - emitter: this + clearSelection: function clearSelection() { + if (trigger) { + trigger.focus(); + } + + document.activeElement.blur(); + window.getSelection().removeAllRanges(); + } }); } /** @@ -449,10 +352,6 @@ var Clipboard = /*#__PURE__*/function (_Emitter) { key: "destroy", value: function destroy() { this.listener.destroy(); - - if (this.clipboardActionDefault) { - this.clipboardActionDefault = null; - } } }], [{ key: "copy", diff --git a/dist/clipboard.min.js b/dist/clipboard.min.js index f7a4306..7800920 100644 --- a/dist/clipboard.min.js +++ b/dist/clipboard.min.js @@ -4,4 +4,4 @@ * * Licensed MIT © Zeno Rocha */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={747:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),c=n.n(e),e=n(817),u=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var l=function(t){t=u()(t);return a("cut"),t};var s=function(t){var e,n,o,r=1 { + // Defines base properties passed from constructor. + const { action = 'copy', container, target, text } = options; + + // Sets the `action` to be performed which can be either 'copy' or 'cut'. + if (action !== 'copy' && action !== 'cut') { + throw new Error('Invalid "action" value, use either "copy" or "cut"'); } - /** - * Defines base properties passed from constructor. - * @param {Object} options - */ - resolveOptions(options = {}) { - this.action = options.action; - this.container = options.container; - this.emitter = options.emitter; - this.target = options.target; - this.text = options.text; - this.trigger = options.trigger; - - this.selectedText = ''; - } - - /** - * Decides which selection strategy is going to be applied based - * on the existence of `text` and `target` properties. - */ - initSelection() { - if (this.text) { - this.selectedText = ClipboardActionCopy(this.text, { - container: this.container, - }); - } else if (this.target) { - this.selectedText = - this.action === 'cut' - ? ClipboardActionCut(this.target) - : ClipboardActionCopy(this.target, { - container: this.container, - }); - } - - this.handleResult(Boolean(this.selectedText)); - } - - /** - * Fires an event based on the copy operation result. - * @param {Boolean} succeeded - */ - handleResult(succeeded) { - this.emitter.emit(succeeded ? 'success' : 'error', { - action: this.action, - text: this.selectedText, - trigger: this.trigger, - clearSelection: this.clearSelection.bind(this), - }); - } - - /** - * Moves focus away from `target` and back to the trigger, removes current selection. - */ - clearSelection() { - if (this.trigger) { - this.trigger.focus(); - } - document.activeElement.blur(); - window.getSelection().removeAllRanges(); - } - - /** - * Sets the `action` to be performed which can be either 'copy' or 'cut'. - * @param {String} action - */ - set action(action = 'copy') { - this._action = action; - - if (this._action !== 'copy' && this._action !== 'cut') { - throw new Error('Invalid "action" value, use either "copy" or "cut"'); - } - } - - /** - * Gets the `action` property. - * @return {String} - */ - get action() { - return this._action; - } - - /** - * Sets the `target` property using an element - * that will be have its content copied. - * @param {Element} target - */ - set target(target) { - if (target !== undefined) { - if (target && typeof target === 'object' && target.nodeType === 1) { - if (this.action === 'copy' && target.hasAttribute('disabled')) { - throw new Error( - 'Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute' - ); - } - - if ( - this.action === 'cut' && - (target.hasAttribute('readonly') || target.hasAttribute('disabled')) - ) { - throw new Error( - 'Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes' - ); - } - - this._target = target; - } else { - throw new Error('Invalid "target" value, use a valid Element'); + // Sets the `target` property using an element that will be have its content copied. + if (target !== undefined) { + if (target && typeof target === 'object' && target.nodeType === 1) { + if (action === 'copy' && target.hasAttribute('disabled')) { + throw new Error( + 'Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute' + ); } + + if ( + action === 'cut' && + (target.hasAttribute('readonly') || target.hasAttribute('disabled')) + ) { + throw new Error( + 'Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes' + ); + } + } else { + throw new Error('Invalid "target" value, use a valid Element'); } } - /** - * Gets the `target` property. - * @return {String|HTMLElement} - */ - get target() { - return this._target; + // Define selection strategy based on `text` property. + if (text) { + return ClipboardActionCopy(text, { container }); } -} + + // Defines which selection strategy based on `target` property. + if (target) { + return action === 'cut' + ? ClipboardActionCut(target) + : ClipboardActionCopy(target, { container }); + } +}; export default ClipboardActionDefault; diff --git a/src/clipboard.js b/src/clipboard.js index f1eec87..c282b29 100644 --- a/src/clipboard.js +++ b/src/clipboard.js @@ -71,18 +71,25 @@ class Clipboard extends Emitter { */ onClick(e) { const trigger = e.delegateTarget || e.currentTarget; - - if (this.clipboardActionDefault) { - this.clipboardActionDefault = null; - } - - this.clipboardActionDefault = new ClipboardActionDefault({ + const selectedText = ClipboardActionDefault({ action: this.action(trigger), + container: this.container, target: this.target(trigger), text: this.text(trigger), - container: this.container, + }); + + // Fires an event based on the copy operation result. + this.emit(selectedText ? 'success' : 'error', { + action: this.action, + text: selectedText, trigger, - emitter: this, + clearSelection() { + if (trigger) { + trigger.focus(); + } + document.activeElement.blur(); + window.getSelection().removeAllRanges(); + }, }); } @@ -143,10 +150,6 @@ class Clipboard extends Emitter { */ destroy() { this.listener.destroy(); - - if (this.clipboardActionDefault) { - this.clipboardActionDefault = null; - } } } diff --git a/test/clipboard-action-copy.js b/test/clipboard-action-copy.js index c676736..c84948b 100644 --- a/test/clipboard-action-copy.js +++ b/test/clipboard-action-copy.js @@ -17,7 +17,7 @@ describe('ClipboardActionCopy', () => { document.body.innerHTML = ''; }); - describe.only('#selectText', () => { + describe('#selectText', () => { it('should select its value based on input target', () => { const selectedText = ClipboardActionCopy( document.querySelector('#input'), diff --git a/test/clipboard-action-cut.js b/test/clipboard-action-cut.js index 08c2de6..a7678e0 100644 --- a/test/clipboard-action-cut.js +++ b/test/clipboard-action-cut.js @@ -17,7 +17,7 @@ describe('ClipboardActionCut', () => { document.body.innerHTML = ''; }); - describe.only('#selectText', () => { + describe('#selectText', () => { it('should select its value', () => { const selectedText = ClipboardActionCut( document.querySelector('#input'), diff --git a/test/clipboard-action-default.js b/test/clipboard-action-default.js index 90227b6..f2c7ddb 100644 --- a/test/clipboard-action-default.js +++ b/test/clipboard-action-default.js @@ -1,4 +1,3 @@ -import Emitter from 'tiny-emitter'; import ClipboardActionDefault from '../src/clipboard-action-default'; describe('ClipboardActionDefault', () => { @@ -20,26 +19,19 @@ describe('ClipboardActionDefault', () => { describe('#resolveOptions', () => { it('should set base properties', () => { - let clip = new ClipboardActionDefault({ - emitter: new Emitter(), + const selectedText = ClipboardActionDefault({ container: document.body, text: 'foo', }); - assert.property(clip, 'action'); - assert.property(clip, 'container'); - assert.property(clip, 'emitter'); - assert.property(clip, 'target'); - assert.property(clip, 'text'); - assert.property(clip, 'trigger'); - assert.property(clip, 'selectedText'); + assert.equal(selectedText, 'foo'); }); }); describe('#set action', () => { it('should throw an error since "action" is invalid', (done) => { try { - let clip = new ClipboardActionDefault({ + let clip = ClipboardActionDefault({ text: 'foo', action: 'paste', }); @@ -56,7 +48,7 @@ describe('ClipboardActionDefault', () => { describe('#set target', () => { it('should throw an error since "target" do not match any element', (done) => { try { - let clip = new ClipboardActionDefault({ + let clip = ClipboardActionDefault({ target: document.querySelector('#foo'), }); } catch (e) { @@ -66,122 +58,23 @@ describe('ClipboardActionDefault', () => { }); }); - describe('#selectTarget', () => { + describe('#selectedText', () => { it('should select text from editable element', () => { - let clip = new ClipboardActionDefault({ - emitter: new Emitter(), + const selectedText = ClipboardActionDefault({ container: document.body, target: document.querySelector('#input'), }); - assert.equal(clip.selectedText, clip.target.value); + assert.equal(selectedText, 'abc'); }); it('should select text from non-editable element', () => { - let clip = new ClipboardActionDefault({ - emitter: new Emitter(), + const selectedText = ClipboardActionDefault({ container: document.body, target: document.querySelector('#paragraph'), }); - assert.equal(clip.selectedText, clip.target.textContent); - }); - }); - - describe('#copyText', () => { - before(() => { - global.stub = sinon.stub(document, 'execCommand'); - }); - - after(() => { - global.stub.restore(); - }); - - it('should fire a success event on browsers that support copy command', (done) => { - global.stub.returns(true); - - let emitter = new Emitter(); - - emitter.on('success', () => { - done(); - }); - - let clip = new ClipboardActionDefault({ - emitter, - target: document.querySelector('#input'), - }); - }); - - it('should fire an error event on browsers that support cut command', (done) => { - let emitter = new Emitter(); - - emitter.on('error', () => { - done(); - }); - - let clip = new ClipboardActionDefault({ - emitter, - target: document.querySelector('#input'), - }); - - clip.handleResult(false); - }); - }); - - describe('#handleResult', () => { - it('should fire a success event with certain properties', (done) => { - let clip = new ClipboardActionDefault({ - emitter: new Emitter(), - container: document.body, - target: document.querySelector('#input'), - }); - - clip.emitter.on('success', (e) => { - assert.property(e, 'action'); - assert.property(e, 'text'); - assert.property(e, 'trigger'); - assert.property(e, 'clearSelection'); - - done(); - }); - - clip.handleResult(true); - }); - - it('should fire a error event with certain properties', (done) => { - let clip = new ClipboardActionDefault({ - emitter: new Emitter(), - container: document.body, - target: document.querySelector('#input'), - }); - - clip.emitter.on('error', (e) => { - assert.property(e, 'action'); - assert.property(e, 'trigger'); - assert.property(e, 'clearSelection'); - - done(); - }); - - clip.handleResult(false); - }); - }); - - describe('#clearSelection', () => { - it('should remove focus from target and text selection', () => { - let clip = new ClipboardActionDefault({ - emitter: new Emitter(), - container: document.body, - target: document.querySelector('#input'), - }); - - clip.clearSelection(); - - let selectedElem = document.activeElement; - let selectedText = window.getSelection().toString(); - - assert.equal(selectedElem, document.body); - assert.equal(selectedText, ''); + assert.equal(selectedText, 'abc'); }); }); }); diff --git a/test/clipboard.js b/test/clipboard.js index 5c928a4..3f31c1d 100644 --- a/test/clipboard.js +++ b/test/clipboard.js @@ -1,5 +1,4 @@ import Clipboard from '../src/clipboard'; -import ClipboardActionDefault from '../src/clipboard-action-default'; describe('Clipboard', () => { before(() => { @@ -75,28 +74,28 @@ describe('Clipboard', () => { }); describe('#onClick', () => { - it('should create a new instance of ClipboardActionDefault', () => { + it('should create a new instance of ClipboardActionDefault', (done) => { let clipboard = new Clipboard('.btn'); + clipboard.on('success', () => { + done(); + }); + clipboard.onClick(global.event); - assert.instanceOf( - clipboard.clipboardActionDefault, - ClipboardActionDefault - ); }); - it("should use an event's currentTarget when not equal to target", () => { + it("should use an event's currentTarget when not equal to target", (done) => { let clipboard = new Clipboard('.btn'); let bubbledEvent = { target: global.span, currentTarget: global.button, }; + clipboard.on('success', () => { + done(); + }); + clipboard.onClick(bubbledEvent); - assert.instanceOf( - clipboard.clipboardActionDefault, - ClipboardActionDefault - ); }); it('should throw an exception when target is invalid', (done) => { @@ -152,4 +151,41 @@ describe('Clipboard', () => { assert.equal(clipboard.clipboardAction, null); }); }); + + describe('#events', () => { + it('should fire a success event with certain properties', (done) => { + let clipboard = new Clipboard('.btn'); + + clipboard.on('success', (e) => { + assert.property(e, 'action'); + assert.property(e, 'text'); + assert.property(e, 'trigger'); + assert.property(e, 'clearSelection'); + + done(); + }); + + clipboard.onClick(global.event); + }); + }); + + describe('#clearSelection', () => { + it('should remove focus from target and text selection', (done) => { + let clipboard = new Clipboard('.btn'); + + clipboard.on('success', (e) => { + let selectedElem = document.activeElement; + let selectedText = window.getSelection().toString(); + + e.clearSelection(); + + assert.equal(selectedElem, document.body); + assert.equal(selectedText, ''); + + done(); + }); + + clipboard.onClick(global.event); + }); + }); }); diff --git a/test/common/command.js b/test/common/command.js index 7d1e3c9..474d7c1 100644 --- a/test/common/command.js +++ b/test/common/command.js @@ -1,8 +1,9 @@ import select from 'select'; import command from '../../src/common/command'; -describe('command', () => { +describe('#command', () => { before(() => { + global.stub = sinon.stub(document, 'execCommand'); global.input = document.createElement('input'); global.input.setAttribute('id', 'input'); global.input.setAttribute('value', 'abc'); @@ -10,26 +11,39 @@ describe('command', () => { }); after(() => { + global.stub.restore(); document.body.innerHTML = ''; }); - it('should execute cut command', (done) => { - // Set document direction - document.documentElement.setAttribute('dir', 'rtl'); - + it('should execute cut', (done) => { + global.stub.returns(true); select(document.querySelector('#input')); assert.isTrue(command('cut')); done(); }); - it('should execute copy command', (done) => { - // Set document direction - document.documentElement.setAttribute('dir', 'rtl'); - + it('should execute copy', (done) => { + global.stub.returns(true); select(document.querySelector('#input')); assert.isTrue(command('copy')); done(); }); + + it('should not execute copy', (done) => { + global.stub.returns(false); + select(document.querySelector('#input')); + + assert.isFalse(command('copy')); + done(); + }); + + it('should not execute cut', (done) => { + global.stub.returns(false); + select(document.querySelector('#input')); + + assert.isFalse(command('cut')); + done(); + }); });