Add copy to clipboard and save to pc toggle.
* escaped node modules from vcs * feat: added copy to clipboard feature * feat: added tests * feat: added feature spec * feat: added toggle for save to pc * feat: added tests * refactor: change toggle from '?' button to the 'switch' component * Fix failing tests * Update gitignore and remove unnecessary files * Remove tooltips because they are unnecessary --------- Co-authored-by: Joey Yakimowich-Payne <jyapayne@gmail.com>
This commit is contained in:
parent
feba59bb8d
commit
9dd4d706fa
12 changed files with 7780 additions and 22 deletions
209
tests/validation-logic.test.js
Normal file
209
tests/validation-logic.test.js
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/**
|
||||
* Tests for output method validation logic
|
||||
*/
|
||||
|
||||
// Mock DOM elements and Chrome APIs
|
||||
const mockChrome = {
|
||||
storage: {
|
||||
sync: {
|
||||
get: jest.fn(),
|
||||
set: jest.fn()
|
||||
}
|
||||
},
|
||||
tabs: {
|
||||
query: jest.fn(),
|
||||
sendMessage: jest.fn()
|
||||
},
|
||||
runtime: {
|
||||
onMessage: {
|
||||
addListener: jest.fn()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
global.chrome = mockChrome;
|
||||
|
||||
describe('Output Method Validation', () => {
|
||||
let mockDocument;
|
||||
let clipboardToggle;
|
||||
let saveToPcToggle;
|
||||
let startBtn;
|
||||
let validationWarning;
|
||||
let validateOutputMethods;
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset mocks
|
||||
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' }
|
||||
};
|
||||
|
||||
// Mock document.getElementById
|
||||
const mockGetElementById = jest.fn((id) => {
|
||||
switch (id) {
|
||||
case 'clipboard-toggle': return clipboardToggle;
|
||||
case 'save-to-pc-toggle': return saveToPcToggle;
|
||||
case 'start-selector': return startBtn;
|
||||
case 'validation-warning': return validationWarning;
|
||||
default: return null;
|
||||
}
|
||||
});
|
||||
|
||||
mockDocument = {
|
||||
getElementById: mockGetElementById,
|
||||
addEventListener: jest.fn()
|
||||
};
|
||||
|
||||
global.document = mockDocument;
|
||||
|
||||
// Define validation function (extracted from popup.js logic)
|
||||
validateOutputMethods = function() {
|
||||
const hasValidOutput = clipboardToggle.checked || saveToPcToggle.checked;
|
||||
|
||||
if (hasValidOutput) {
|
||||
validationWarning.style.display = 'none';
|
||||
startBtn.disabled = false;
|
||||
startBtn.setAttribute('aria-describedby', '');
|
||||
} else {
|
||||
validationWarning.style.display = 'block';
|
||||
startBtn.disabled = true;
|
||||
startBtn.setAttribute('aria-describedby', 'validation-warning');
|
||||
}
|
||||
|
||||
return hasValidOutput;
|
||||
};
|
||||
});
|
||||
|
||||
describe('Validation Logic', () => {
|
||||
test('should return true when both save to PC and clipboard are enabled', () => {
|
||||
clipboardToggle.checked = true;
|
||||
saveToPcToggle.checked = true;
|
||||
|
||||
const result = validateOutputMethods();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(validationWarning.style.display).toBe('none');
|
||||
expect(startBtn.disabled).toBe(false);
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', '');
|
||||
});
|
||||
|
||||
test('should return true when only save to PC is enabled', () => {
|
||||
clipboardToggle.checked = false;
|
||||
saveToPcToggle.checked = true;
|
||||
|
||||
const result = validateOutputMethods();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(validationWarning.style.display).toBe('none');
|
||||
expect(startBtn.disabled).toBe(false);
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', '');
|
||||
});
|
||||
|
||||
test('should return true when only clipboard is enabled', () => {
|
||||
clipboardToggle.checked = true;
|
||||
saveToPcToggle.checked = false;
|
||||
|
||||
const result = validateOutputMethods();
|
||||
|
||||
expect(result).toBe(true);
|
||||
expect(validationWarning.style.display).toBe('none');
|
||||
expect(startBtn.disabled).toBe(false);
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', '');
|
||||
});
|
||||
|
||||
test('should return false when both save to PC and clipboard are disabled', () => {
|
||||
clipboardToggle.checked = false;
|
||||
saveToPcToggle.checked = false;
|
||||
|
||||
const result = validateOutputMethods();
|
||||
|
||||
expect(result).toBe(false);
|
||||
expect(validationWarning.style.display).toBe('block');
|
||||
expect(startBtn.disabled).toBe(true);
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', 'validation-warning');
|
||||
});
|
||||
});
|
||||
|
||||
describe('UI State Management', () => {
|
||||
test('should hide warning and enable button when validation passes', () => {
|
||||
clipboardToggle.checked = true;
|
||||
saveToPcToggle.checked = false;
|
||||
|
||||
validateOutputMethods();
|
||||
|
||||
expect(validationWarning.style.display).toBe('none');
|
||||
expect(startBtn.disabled).toBe(false);
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', '');
|
||||
});
|
||||
|
||||
test('should show warning and disable button when validation fails', () => {
|
||||
clipboardToggle.checked = false;
|
||||
saveToPcToggle.checked = false;
|
||||
|
||||
validateOutputMethods();
|
||||
|
||||
expect(validationWarning.style.display).toBe('block');
|
||||
expect(startBtn.disabled).toBe(true);
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', 'validation-warning');
|
||||
});
|
||||
|
||||
test('should update accessibility attributes correctly', () => {
|
||||
// Test valid state
|
||||
clipboardToggle.checked = true;
|
||||
saveToPcToggle.checked = true;
|
||||
validateOutputMethods();
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', '');
|
||||
|
||||
// Reset mock
|
||||
startBtn.setAttribute.mockClear();
|
||||
|
||||
// Test invalid state
|
||||
clipboardToggle.checked = false;
|
||||
saveToPcToggle.checked = false;
|
||||
validateOutputMethods();
|
||||
expect(startBtn.setAttribute).toHaveBeenCalledWith('aria-describedby', 'validation-warning');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
test('should handle undefined checkbox states gracefully', () => {
|
||||
clipboardToggle.checked = undefined;
|
||||
saveToPcToggle.checked = true;
|
||||
|
||||
const result = validateOutputMethods();
|
||||
|
||||
// undefined should be falsy, so only saveToPc (true) should make it valid
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle null checkbox states gracefully', () => {
|
||||
clipboardToggle.checked = null;
|
||||
saveToPcToggle.checked = null;
|
||||
|
||||
const result = validateOutputMethods();
|
||||
|
||||
// Both null should be falsy, so validation should fail
|
||||
expect(result).toBeFalsy(); // Use toBeFalsy to handle null/false/undefined
|
||||
expect(validationWarning.style.display).toBe('block');
|
||||
expect(startBtn.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue