Skip to content

Commit

Permalink
Split copy function into single file (#143)
Browse files Browse the repository at this point in the history
  • Loading branch information
asamuzaK committed Apr 5, 2023
1 parent 0bfca00 commit 086fffd
Show file tree
Hide file tree
Showing 4 changed files with 279 additions and 68 deletions.
24 changes: 24 additions & 0 deletions src/mjs/exec-copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* exec-copy.js
*/

/* shared */
import { Clip } from './clipboard.js';
import { notifyOnCopy } from './notify.js';
import { MIME_HTML, MIME_PLAIN } from './constant.js';

/**
* execute copy
*
* @param {object} opt - options
* @returns {void}
*/
export const execCopy = async (opt = {}) => {
const { formatTitle, mimeType, notify, text } = opt;
if (mimeType === MIME_HTML || mimeType === MIME_PLAIN) {
await new Clip(text, mimeType).copy();
if (notify) {
await notifyOnCopy(formatTitle);
}
}
};
14 changes: 8 additions & 6 deletions src/mjs/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

/* shared */
import { sanitizeURL } from '../lib/url/url-sanitizer-wo-dompurify.min.js';
import { Clip } from './clipboard.js';
import { getType, isObjectNotEmpty, isString, logErr } from './common.js';
import {
execScriptToTab, execScriptsToTabInOrder, executeScriptToTab, getActiveTab,
getActiveTabId, getAllStorage, getAllTabsInWindow, getHighlightedTab,
getStorage, isScriptingAvailable, isTab, queryTabs, removeStorage, sendMessage
} from './browser.js';
import { getType, isObjectNotEmpty, isString, logErr } from './common.js';
import { editContent } from './edit-content.js';
import { execCopy } from './exec-copy.js';
import {
createLinkText, createTabsLinkText, enabledFormats, getFormat, getFormatId,
getFormatsKeys, getFormatTitle, hasFormat, setFormat, setFormatData,
Expand Down Expand Up @@ -499,10 +499,12 @@ export const extractClickedData = async (info, tab) => {
}
}
if (isString(text)) {
await new Clip(text, mimeType).copy();
if (userOpts.get(NOTIFY_COPY)) {
func.push(notifyOnCopy(formatTitle));
}
func.push(execCopy({
formatTitle,
mimeType,
text,
notify: userOpts.get(NOTIFY_COPY)
}));
}
}
}
Expand Down
185 changes: 185 additions & 0 deletions test/exec-copy.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/**
* exec-copy.test.js
*/
/* eslint-disable import/order */

/* api */
import sinon from 'sinon';
import { assert } from 'chai';
import { afterEach, beforeEach, describe, it } from 'mocha';
import { browser, createJsdom } from './mocha/setup.js';

/* test */
import { ICON, MIME_PLAIN } from '../src/mjs/constant.js';
import * as mjs from '../src/mjs/exec-copy.js';

describe('exec-copy', () => {
const globalKeys = [
'Blob',
'ClipboardItem',
'DOMParser',
'HTMLUnknownElement',
'Node',
'XMLSerializer'
];
let window, document, navigator;
beforeEach(() => {
const dom = createJsdom();
window = dom && dom.window;
document = window.document;
if (document.execCommand) {
sinon.stub(document, 'execCommand');
} else {
document.execCommand = sinon.fake();
}
navigator = window.navigator;
if (navigator.clipboard) {
sinon.stub(navigator.clipboard, 'write');
sinon.stub(navigator.clipboard, 'writeText');
} else {
navigator.clipboard = {
write: sinon.stub(),
writeText: sinon.stub()
};
}
browser._sandbox.reset();
browser.i18n.getMessage.callsFake((...args) => args.toString());
browser.permissions.contains.resolves(true);
browser.storage.local.get.resolves({});
global.browser = browser;
global.window = window;
global.document = document;
global.navigator = navigator;
for (const key of globalKeys) {
// Not implemented in jsdom
if (!window[key]) {
if (key === 'ClipboardItem') {
window[key] = class ClipboardItem {
constructor(obj) {
this._items = new Map();
this._mimetypes = [
'application/json',
'application/xhtml+xml',
'application/xml',
'image/gif',
'image/jpeg',
'image/jpg',
'image/png',
'image/svg+xml',
'text/css',
'text/csv',
'text/html',
'text/plain',
'text/uri-list',
'text/xml'
];
this._setItems(obj);
}

get types() {
return Array.from(this._items.keys());
}

_setItems(obj) {
const items = Object.entries(obj);
for (const [mime, blob] of items) {
if (this._mimetypes.includes(mime) && blob instanceof Blob) {
this._items.set(mime, blob);
} else {
this._items.remove(mime);
}
}
}

async getType(mime) {
const blob = this._items.get(mime);
if (!blob) {
throw new Error(`MIME type ${mime} is not found.`);
}
return blob;
}
};
}
}
global[key] = window[key];
}
});
afterEach(() => {
window = null;
document = null;
navigator = null;
delete global.browser;
delete global.window;
delete global.document;
delete global.navigator;
for (const key of globalKeys) {
delete global[key];
}
browser._sandbox.reset();
});

it('should get browser object', () => {
assert.isObject(browser, 'browser');
});

describe('execute copy', () => {
const func = mjs.execCopy;

it('should not call function', async () => {
browser.runtime.getURL.withArgs(ICON).returns('foo/bar');
browser.i18n.getMessage.withArgs('notifyOnCopyMsg_format').returns('foo');
browser.i18n.getMessage.withArgs('extensionName').returns('bar');
const i = navigator.clipboard.writeText.callCount;
const j = browser.notifications.create.callCount;
const opt = {
formatTitle: 'Text & URL',
mimeType: 'text/foo',
notify: false,
text: 'foo https://example.com'
};
await func(opt);
assert.strictEqual(navigator.clipboard.writeText.callCount, i,
'not called');
assert.strictEqual(browser.notifications.create.callCount, j,
'not called');
});

it('should call function', async () => {
browser.runtime.getURL.withArgs(ICON).returns('foo/bar');
browser.i18n.getMessage.withArgs('notifyOnCopyMsg_format').returns('foo');
browser.i18n.getMessage.withArgs('extensionName').returns('bar');
const i = navigator.clipboard.writeText.callCount;
const j = browser.notifications.create.callCount;
const opt = {
formatTitle: 'Text & URL',
mimeType: MIME_PLAIN,
notify: false,
text: 'foo https://example.com'
};
await func(opt);
assert.strictEqual(navigator.clipboard.writeText.callCount, i + 1,
'called');
assert.strictEqual(browser.notifications.create.callCount, j,
'not called');
});

it('should call function', async () => {
browser.runtime.getURL.withArgs(ICON).returns('foo/bar');
browser.i18n.getMessage.withArgs('notifyOnCopyMsg_format').returns('foo');
browser.i18n.getMessage.withArgs('extensionName').returns('bar');
const i = navigator.clipboard.writeText.callCount;
const j = browser.notifications.create.callCount;
const opt = {
formatTitle: 'Text & URL',
mimeType: MIME_PLAIN,
notify: true,
text: 'foo https://example.com'
};
await func(opt);
assert.strictEqual(navigator.clipboard.writeText.callCount, i + 1,
'called');
assert.strictEqual(browser.notifications.create.callCount, j + 1,
'called');
});
});
});
Loading

0 comments on commit 086fffd

Please sign in to comment.