Better image support
This commit is contained in:
parent
9dd4d706fa
commit
f4b9af1572
8 changed files with 1557 additions and 197 deletions
|
|
@ -53,8 +53,10 @@ global.window = {
|
|||
})
|
||||
};
|
||||
|
||||
// Mock html2canvas
|
||||
global.html2canvas = jest.fn();
|
||||
// Mock html-to-image
|
||||
global.htmlToImage = {
|
||||
toCanvas: jest.fn(),
|
||||
};
|
||||
|
||||
describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
||||
let screenshotSelector;
|
||||
|
|
@ -63,7 +65,7 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
||||
// Reset clipboard mock for each test
|
||||
if (!global.navigator) {
|
||||
global.navigator = {};
|
||||
|
|
@ -75,7 +77,7 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
return { data, type: 'image/png' };
|
||||
});
|
||||
global.window.isSecureContext = true;
|
||||
|
||||
|
||||
// Mock element to capture
|
||||
mockElement = {
|
||||
classList: {
|
||||
|
|
@ -102,7 +104,7 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
toDataURL: jest.fn(() => 'data:image/png;base64,mockdata')
|
||||
};
|
||||
|
||||
global.html2canvas = jest.fn().mockResolvedValue(mockCanvas);
|
||||
global.htmlToImage.toCanvas = jest.fn().mockResolvedValue(mockCanvas);
|
||||
|
||||
|
||||
|
||||
|
|
@ -183,11 +185,17 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
async captureElement(element) {
|
||||
try {
|
||||
// Generate canvas with background-specific settings
|
||||
const canvas = await global.html2canvas(element, {
|
||||
backgroundColor: this.background === 'transparent' ? null :
|
||||
this.background === 'white' ? '#ffffff' : '#000000',
|
||||
useCORS: true,
|
||||
allowTaint: false
|
||||
const backgroundColor =
|
||||
this.background === 'transparent'
|
||||
? undefined
|
||||
: this.background === 'white'
|
||||
? '#ffffff'
|
||||
: '#000000';
|
||||
|
||||
const canvas = await global.htmlToImage.toCanvas(element, {
|
||||
backgroundColor,
|
||||
pixelRatio: global.window.devicePixelRatio || 1,
|
||||
cacheBust: false
|
||||
});
|
||||
|
||||
// Always download first
|
||||
|
|
@ -205,7 +213,7 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
// Update UI based on results (matching new message format)
|
||||
let successMessage = 'Screenshot captured!';
|
||||
let messageIcon = '✅';
|
||||
|
||||
|
||||
if (this.saveToPc && this.copyToClipboard) {
|
||||
// Both operations enabled
|
||||
if (clipboardResult && clipboardResult.success) {
|
||||
|
|
@ -235,7 +243,7 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
}
|
||||
|
||||
this.overlay.innerHTML = `<div>${successMessage}</div>`;
|
||||
|
||||
|
||||
return {
|
||||
success: true,
|
||||
downloadSuccess: true,
|
||||
|
|
@ -258,13 +266,11 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
|
||||
test('should capture with transparent background and copy to clipboard', async () => {
|
||||
await screenshotSelector.init('transparent', true);
|
||||
|
||||
|
||||
const result = await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
expect(global.html2canvas).toHaveBeenCalledWith(mockElement, expect.objectContaining({
|
||||
backgroundColor: null, // Transparent background
|
||||
useCORS: true,
|
||||
allowTaint: false
|
||||
expect(global.htmlToImage.toCanvas).toHaveBeenCalledWith(mockElement, expect.objectContaining({
|
||||
backgroundColor: undefined, // Transparent background
|
||||
}));
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -275,13 +281,11 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
|
||||
test('should capture with black background and copy to clipboard', async () => {
|
||||
await screenshotSelector.init('black', true);
|
||||
|
||||
|
||||
const result = await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
expect(global.html2canvas).toHaveBeenCalledWith(mockElement, expect.objectContaining({
|
||||
expect(global.htmlToImage.toCanvas).toHaveBeenCalledWith(mockElement, expect.objectContaining({
|
||||
backgroundColor: '#000000', // Black background
|
||||
useCORS: true,
|
||||
allowTaint: false
|
||||
}));
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -291,13 +295,11 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
|
||||
test('should capture with white background and copy to clipboard', async () => {
|
||||
await screenshotSelector.init('white', true);
|
||||
|
||||
|
||||
const result = await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
expect(global.html2canvas).toHaveBeenCalledWith(mockElement, expect.objectContaining({
|
||||
expect(global.htmlToImage.toCanvas).toHaveBeenCalledWith(mockElement, expect.objectContaining({
|
||||
backgroundColor: '#ffffff', // White background
|
||||
useCORS: true,
|
||||
allowTaint: false
|
||||
}));
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -307,7 +309,7 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
|
||||
test('should capture without clipboard when disabled', async () => {
|
||||
await screenshotSelector.init('black', false, true); // saveToPc = true, copyToClipboard = false
|
||||
|
||||
|
||||
const result = await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -324,9 +326,9 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
global.navigator.clipboard = {
|
||||
write: jest.fn().mockRejectedValue(new DOMException('Permission denied', 'NotAllowedError'))
|
||||
};
|
||||
|
||||
|
||||
await screenshotSelector.init('black', true);
|
||||
|
||||
|
||||
const result = await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -340,9 +342,9 @@ describe('Integration Scenarios - Clipboard with Different Backgrounds', () => {
|
|||
test('should handle clipboard API unavailable scenario', async () => {
|
||||
// Mock clipboard API not available
|
||||
global.navigator.clipboard = undefined;
|
||||
|
||||
|
||||
await screenshotSelector.init('transparent', true);
|
||||
|
||||
|
||||
const result = await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
|
|
@ -359,7 +361,7 @@ describe('Integration Scenarios - Complete Workflow', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
||||
// Mock popup elements
|
||||
mockPopupElements = {
|
||||
clipboardToggle: { checked: true, addEventListener: jest.fn() },
|
||||
|
|
@ -399,18 +401,18 @@ describe('Integration Scenarios - Complete Workflow', () => {
|
|||
const backgroundSelect = document.getElementById('background-select');
|
||||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
const startBtn = document.getElementById('start-selector');
|
||||
|
||||
|
||||
// Load preferences
|
||||
const saved = await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard']);
|
||||
if (saved.backgroundPreference) {
|
||||
backgroundSelect.value = saved.backgroundPreference;
|
||||
}
|
||||
clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;
|
||||
|
||||
|
||||
// Start selector
|
||||
startBtn.addEventListener('click', async () => {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
|
||||
|
||||
await chrome.tabs.sendMessage(tab.id, {
|
||||
action: 'startSelector',
|
||||
background: backgroundSelect.value,
|
||||
|
|
@ -466,12 +468,12 @@ describe('Integration Scenarios - Complete Workflow', () => {
|
|||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const popupScript = `
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const backgroundSelect = document.getElementById('background-select');
|
||||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
|
||||
|
||||
backgroundSelect.addEventListener('change', () => {
|
||||
chrome.storage.sync.set({ backgroundPreference: backgroundSelect.value });
|
||||
});
|
||||
|
|
@ -499,9 +501,9 @@ describe('Integration Scenarios - Complete Workflow', () => {
|
|||
|
||||
test('should handle incompatible pages gracefully', async () => {
|
||||
// Mock incompatible page
|
||||
global.chrome.tabs.query.mockResolvedValue([{
|
||||
id: 123,
|
||||
url: 'chrome://settings/'
|
||||
global.chrome.tabs.query.mockResolvedValue([{
|
||||
id: 123,
|
||||
url: 'chrome://settings/'
|
||||
}]);
|
||||
|
||||
let startButtonCallback;
|
||||
|
|
@ -514,7 +516,7 @@ describe('Integration Scenarios - Complete Workflow', () => {
|
|||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const startBtn = document.getElementById('start-selector');
|
||||
const status = document.getElementById('status');
|
||||
|
||||
|
||||
startBtn.addEventListener('click', async () => {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
|
||||
|
|
@ -527,7 +529,7 @@ describe('Integration Scenarios - Complete Workflow', () => {
|
|||
status.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Normal flow would continue here
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -53,8 +53,10 @@ global.window = {
|
|||
CSS: { escape: jest.fn(str => str) }
|
||||
};
|
||||
|
||||
// Mock html2canvas
|
||||
global.html2canvas = jest.fn();
|
||||
// Mock html-to-image
|
||||
global.htmlToImage = {
|
||||
toCanvas: jest.fn(),
|
||||
};
|
||||
|
||||
// Mock ScreenshotSelector class for testing
|
||||
class MockScreenshotSelector {
|
||||
|
|
@ -126,10 +128,18 @@ class MockScreenshotSelector {
|
|||
toDataURL: jest.fn(() => 'data:image/png;base64,mockdata')
|
||||
};
|
||||
|
||||
// Mock html2canvas
|
||||
global.html2canvas.mockResolvedValue(mockCanvas);
|
||||
// Mock html-to-image
|
||||
global.htmlToImage.toCanvas.mockResolvedValue(mockCanvas);
|
||||
|
||||
const canvas = await global.html2canvas(element);
|
||||
const canvas = await global.htmlToImage.toCanvas(element, {
|
||||
backgroundColor: this.background === 'transparent'
|
||||
? undefined
|
||||
: this.background === 'white'
|
||||
? '#ffffff'
|
||||
: '#000000',
|
||||
pixelRatio: global.window.devicePixelRatio || 1,
|
||||
cacheBust: false
|
||||
});
|
||||
|
||||
// Conditionally download based on saveToPc setting
|
||||
if (this.saveToPc) {
|
||||
|
|
@ -159,7 +169,7 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
||||
// Reset mocks
|
||||
mockCreateElement.mockClear();
|
||||
mockCreateElement.mockReturnValue(mockLink);
|
||||
|
|
@ -168,7 +178,7 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
global.document.createElement = mockCreateElement;
|
||||
}
|
||||
mockLink.click.mockClear();
|
||||
|
||||
|
||||
// Setup clipboard API mocks
|
||||
global.navigator = {
|
||||
clipboard: {
|
||||
|
|
@ -207,7 +217,7 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
// Verify download was triggered
|
||||
expect(mockCreateElement).toHaveBeenCalledWith('a');
|
||||
expect(mockLink.click).toHaveBeenCalled();
|
||||
|
||||
|
||||
// Verify clipboard operation was attempted
|
||||
expect(global.navigator.clipboard.write).toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -256,7 +266,7 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
// Verify download was triggered
|
||||
expect(mockCreateElement).toHaveBeenCalledWith('a');
|
||||
expect(mockLink.click).toHaveBeenCalled();
|
||||
|
||||
|
||||
// Verify clipboard operation was NOT attempted
|
||||
expect(global.navigator.clipboard.write).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -287,7 +297,7 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
|
||||
// Verify download was NOT triggered
|
||||
expect(mockCreateElement).not.toHaveBeenCalledWith('a');
|
||||
|
||||
|
||||
// Verify clipboard operation was attempted
|
||||
expect(global.navigator.clipboard.write).toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -317,7 +327,7 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
|
||||
// Verify download was NOT triggered
|
||||
expect(mockCreateElement).not.toHaveBeenCalledWith('a');
|
||||
|
||||
|
||||
// Verify clipboard operation was NOT attempted
|
||||
expect(global.navigator.clipboard.write).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
@ -334,8 +344,11 @@ describe('Save to PC and Clipboard Combinations', () => {
|
|||
test('should still create canvas even when both outputs are disabled', async () => {
|
||||
await screenshotSelector.captureElement(mockElement);
|
||||
|
||||
// html2canvas should still be called (needed for potential future operations)
|
||||
expect(global.html2canvas).toHaveBeenCalledWith(mockElement);
|
||||
// html-to-image should still be called (needed for potential future operations)
|
||||
expect(global.htmlToImage.toCanvas).toHaveBeenCalledWith(
|
||||
mockElement,
|
||||
expect.any(Object)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -349,24 +362,24 @@ describe('Popup Validation Logic for All Combinations', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
||||
// Mock DOM elements
|
||||
clipboardToggle = {
|
||||
checked: true,
|
||||
addEventListener: jest.fn()
|
||||
};
|
||||
|
||||
|
||||
saveToPcToggle = {
|
||||
checked: true,
|
||||
addEventListener: jest.fn()
|
||||
};
|
||||
|
||||
|
||||
startBtn = {
|
||||
disabled: false,
|
||||
setAttribute: jest.fn(),
|
||||
addEventListener: jest.fn()
|
||||
};
|
||||
|
||||
|
||||
validationWarning = {
|
||||
style: { display: 'none' }
|
||||
};
|
||||
|
|
@ -384,7 +397,7 @@ describe('Popup Validation Logic for All Combinations', () => {
|
|||
// Define validation function
|
||||
validateOutputMethods = function() {
|
||||
const hasValidOutput = clipboardToggle.checked || saveToPcToggle.checked;
|
||||
|
||||
|
||||
if (hasValidOutput) {
|
||||
validationWarning.style.display = 'none';
|
||||
startBtn.disabled = false;
|
||||
|
|
@ -394,7 +407,7 @@ describe('Popup Validation Logic for All Combinations', () => {
|
|||
startBtn.disabled = true;
|
||||
startBtn.setAttribute('aria-describedby', 'validation-warning');
|
||||
}
|
||||
|
||||
|
||||
return hasValidOutput;
|
||||
};
|
||||
});
|
||||
|
|
@ -454,13 +467,13 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
||||
// Mock DOM elements
|
||||
mockClipboardToggle = {
|
||||
checked: false,
|
||||
addEventListener: jest.fn()
|
||||
};
|
||||
|
||||
|
||||
mockSaveToPcToggle = {
|
||||
checked: false,
|
||||
addEventListener: jest.fn()
|
||||
|
|
@ -481,13 +494,13 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
test('should default to both enabled for new installations', async () => {
|
||||
// Mock no saved preferences (new installation)
|
||||
global.chrome.storage.sync.get.mockResolvedValueOnce({});
|
||||
|
||||
|
||||
const popupScript = `
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
const saveToPcToggle = document.getElementById('save-to-pc-toggle');
|
||||
const saved = await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard', 'saveToPc']);
|
||||
|
||||
|
||||
clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;
|
||||
saveToPcToggle.checked = saved.saveToPc !== undefined ? saved.saveToPc : true;
|
||||
});
|
||||
|
|
@ -513,13 +526,13 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
copyToClipboard: false,
|
||||
saveToPc: true
|
||||
});
|
||||
|
||||
|
||||
const popupScript = `
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
const saveToPcToggle = document.getElementById('save-to-pc-toggle');
|
||||
const saved = await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard', 'saveToPc']);
|
||||
|
||||
|
||||
clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;
|
||||
saveToPcToggle.checked = saved.saveToPc !== undefined ? saved.saveToPc : true;
|
||||
});
|
||||
|
|
@ -545,13 +558,13 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
copyToClipboard: true,
|
||||
saveToPc: false
|
||||
});
|
||||
|
||||
|
||||
const popupScript = `
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
const saveToPcToggle = document.getElementById('save-to-pc-toggle');
|
||||
const saved = await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard', 'saveToPc']);
|
||||
|
||||
|
||||
clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;
|
||||
saveToPcToggle.checked = saved.saveToPc !== undefined ? saved.saveToPc : true;
|
||||
});
|
||||
|
|
@ -583,7 +596,7 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
const saveToPcToggle = document.getElementById('save-to-pc-toggle');
|
||||
const saved = await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard', 'saveToPc']);
|
||||
|
||||
|
||||
clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;
|
||||
saveToPcToggle.checked = saved.saveToPc !== undefined ? saved.saveToPc : true;
|
||||
});
|
||||
|
|
@ -601,7 +614,7 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
|
||||
expect(mockClipboardToggle.checked).toBe(false);
|
||||
expect(mockSaveToPcToggle.checked).toBe(false);
|
||||
|
||||
|
||||
// Validation should fail with both disabled
|
||||
const isValid = mockClipboardToggle.checked || mockSaveToPcToggle.checked;
|
||||
expect(isValid).toBe(false);
|
||||
|
|
@ -613,13 +626,13 @@ describe('Preference Persistence Across Browser Sessions', () => {
|
|||
copyToClipboard: true
|
||||
// saveToPc is undefined (not set in previous version)
|
||||
});
|
||||
|
||||
|
||||
const popupScript = `
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const clipboardToggle = document.getElementById('clipboard-toggle');
|
||||
const saveToPcToggle = document.getElementById('save-to-pc-toggle');
|
||||
const saved = await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard', 'saveToPc']);
|
||||
|
||||
|
||||
clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;
|
||||
saveToPcToggle.checked = saved.saveToPc !== undefined ? saved.saveToPc : true;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -233,13 +233,15 @@ global.mockClipboardAPI = (scenario = 'supported') => {
|
|||
beforeEach(() => {
|
||||
// Clear all mocks first
|
||||
jest.clearAllMocks();
|
||||
|
||||
|
||||
global.mockChromeAPIs();
|
||||
global.mockDOMAPIs();
|
||||
global.mockClipboardAPI('supported');
|
||||
|
||||
// Mock html2canvas
|
||||
global.html2canvas = jest.fn().mockResolvedValue(global.createMockCanvas());
|
||||
|
||||
// Mock html-to-image
|
||||
global.htmlToImage = {
|
||||
toCanvas: jest.fn().mockResolvedValue(global.createMockCanvas()),
|
||||
};
|
||||
});
|
||||
|
||||
// Cleanup after each test
|
||||
|
|
@ -251,13 +253,13 @@ afterEach(() => {
|
|||
expect.extend({
|
||||
toHaveBeenCalledWithClipboardMessage(received, expectedBackground, expectedClipboard) {
|
||||
const calls = received.mock.calls;
|
||||
const matchingCall = calls.find(call =>
|
||||
call[1] &&
|
||||
const matchingCall = calls.find(call =>
|
||||
call[1] &&
|
||||
call[1].action === 'startSelector' &&
|
||||
call[1].background === expectedBackground &&
|
||||
call[1].copyToClipboard === expectedClipboard
|
||||
);
|
||||
|
||||
|
||||
if (matchingCall) {
|
||||
return {
|
||||
message: () => `Expected not to be called with clipboard message`,
|
||||
|
|
@ -270,7 +272,7 @@ expect.extend({
|
|||
};
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
toHaveClipboardResult(received, expectedSuccess, expectedErrorType) {
|
||||
if (!received.clipboardResult) {
|
||||
return {
|
||||
|
|
@ -278,10 +280,10 @@ expect.extend({
|
|||
pass: false
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const success = received.clipboardResult.success === expectedSuccess;
|
||||
const errorType = !expectedErrorType || received.clipboardResult.errorType === expectedErrorType;
|
||||
|
||||
|
||||
if (success && errorType) {
|
||||
return {
|
||||
message: () => `Expected clipboard result not to match`,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue