Make copy to clipboard work with prefixes

The prefix was being included in the selection
copied.
This commit is contained in:
Tom Byers
2020-09-15 12:53:58 +01:00
parent c2e737b323
commit 956f5d4c3e
3 changed files with 52 additions and 9 deletions

View File

@@ -27,11 +27,27 @@
`
};
this.getRangeFromElement = function (keyElement) {
const range = document.createRange();
let prefixIndex = -1;
Array.from(keyElement.childNodes).forEach((el, idx) => {
if ((el.nodeType === 1) && el.classList.contains('govuk-visually-hidden')) {
prefixIndex = idx;
}
});
range.selectNodeContents(keyElement);
if (prefixIndex !== -1) { range.setStart(keyElement, prefixIndex + 1); }
return range;
};
this.copyKey = function(keyElement, callback) {
var selection = window.getSelection ? window.getSelection() : document.selection,
range = document.createRange();
range = this.getRangeFromElement(keyElement);
selection.removeAllRanges();
range.selectNodeContents(keyElement);
selection.addRange(range);
document.execCommand('copy');
selection.removeAllRanges();

View File

@@ -33,16 +33,12 @@ describe('API key', () => {
};
beforeAll(() => {
beforeEach(() => {
// mock objects used to manipulate the page selection
selectionMock = new helpers.SelectionMock(jest);
rangeMock = new helpers.RangeMock(jest);
});
beforeEach(() => {
// plug gaps in JSDOM's API for manipulation of selections
window.getSelection = jest.fn(() => selectionMock);
document.createRange = jest.fn(() => rangeMock);
@@ -325,7 +321,7 @@ describe('API key', () => {
describe("If it's one of many in the page", () => {
test("the button should have a hidden suffix naming the id it is for", () => {
beforeEach(() => {
// If 'thing' (what the id is) and 'name' (its specific idenifier on the page) are
// different, it will be one of others called the same 'thing'.
@@ -338,12 +334,31 @@ describe('API key', () => {
helpers.triggerEvent(component.querySelector('button'), 'click');
});
test("the button should have a hidden suffix naming the id it is for", () => {
const buttonSuffix = component.querySelector('button .govuk-visually-hidden');
expect(buttonSuffix).not.toBeNull();
expect(buttonSuffix.textContent).toEqual(' for Default');
});
test("the copied selection shouldn't include the prefix of the id", () => {
// that selection (a range) should have a startOffset past the first two nodes:
// index 0: text node containing the whitespace before the prefix
// index 1: the prefix node
expect(rangeMock.setStart).toHaveBeenCalled();
expect(rangeMock.setStart.mock.calls[0][1]).toEqual(2);
// reset any methods in the global space
window.queryCommandSupported = undefined;
window.getSelection = undefined;
document.createRange = undefined;
});
});
describe("If it's the only one on the page", () => {
@@ -373,6 +388,18 @@ describe('API key', () => {
})
test("the copied selection should match the id", () => {
// that selection (a range) shouldn't call setStart to avoid the prefix:
expect(rangeMock.setStart).not.toHaveBeenCalled();
// reset any methods in the global space
window.queryCommandSupported = undefined;
window.getSelection = undefined;
document.createRange = undefined;
});
});
});

View File

@@ -30,7 +30,7 @@ class DOMInterfaceMock {
class RangeMock extends DOMInterfaceMock {
constructor (jest) {
super(jest, { props: [], methods: ['selectNodeContents'] });
super(jest, { props: [], methods: ['selectNodeContents', 'setStart'] });
}
}