Initial commit. \n 1. Screen capture plugin. \n 2. PNG annotation plugin
This commit is contained in:
573
DEPRECATED/test_plugin_capture_screen_Mocha_async.js
Normal file
573
DEPRECATED/test_plugin_capture_screen_Mocha_async.js
Normal file
@@ -0,0 +1,573 @@
|
||||
// Note: This code assumes you have Mocha, Chai, and Sinon loaded in your test environment
|
||||
// along with jQuery and html2canvas. You'll also need to include your screen capture plugin.
|
||||
|
||||
describe('Screen Capture Plugin', function() {
|
||||
var $button, sandbox, originalBodyHTML;
|
||||
|
||||
beforeEach(function() {
|
||||
originalBodyHTML = document.body.innerHTML;
|
||||
// Create a test element and initialize the plugin
|
||||
$button = $('.' + flagCaptureScreen);
|
||||
$button.screenshotButton();
|
||||
// $button = $button.find('button');
|
||||
|
||||
// Create a sinon sandbox for mocking
|
||||
sandbox = sinon.createSandbox();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
// Clean up
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
after(function() {
|
||||
document.body.innerHTML = originalBodyHTML;
|
||||
});
|
||||
|
||||
// 1. Initialization and Setup
|
||||
describe('1. Initialization and Setup', function() {
|
||||
it('a. should initialize correctly on a given DOM element', function() {
|
||||
expect($button).to.exist;
|
||||
});
|
||||
|
||||
it('b. should create the button with correct text', function() {
|
||||
expect($button.text()).to.equal('Capture Screen');
|
||||
});
|
||||
|
||||
it('c. should make the button visible on the page', function() {
|
||||
expect($button.is(':visible')).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
// 2. Button Functionality
|
||||
describe('2. Button Functionality', function() {
|
||||
it('a. should trigger screenshot process on click', function(done) {
|
||||
// const canvasStub = sinon.stub(document.createElement('canvas'));
|
||||
sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
// await waitForClick($button);
|
||||
$button.click();
|
||||
setTimeout(() => {
|
||||
expect(html2canvas.called).to.be.true;
|
||||
expect(html2canvas.callCount).to.equal(1);
|
||||
html2canvas.restore();
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
it('b. should hide button during screenshot process',
|
||||
/*
|
||||
async function() {
|
||||
sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
let resolve;
|
||||
const promise = new Promise((r) => resolve = r);
|
||||
function handleButtonClick() {
|
||||
resolve();
|
||||
$button.off('click', handleButtonClick);
|
||||
}
|
||||
$button.on("click", function() {
|
||||
handleButtonClick();
|
||||
});
|
||||
$button.click();
|
||||
expect($button.hasClass(flagIsHidden)).to.be.true;
|
||||
html2canvas.restore();
|
||||
}
|
||||
*/
|
||||
function(done) {
|
||||
sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
$button.click();
|
||||
expect($button.hasClass(flagIsHidden)).to.be.true;
|
||||
html2canvas.restore();
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
it('c. should show button after screenshot is taken', function(done) {
|
||||
sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
/*
|
||||
await waitForClick($button).then(() => {
|
||||
setTimeout(() => {
|
||||
expect($button.hasClass(flagIsHidden)).to.be.false;
|
||||
// html2canvas.restore();
|
||||
}, 100); // delay for screenshot and callback process
|
||||
})
|
||||
.catch((err) => {
|
||||
html2canvas.restore();
|
||||
throw err;
|
||||
});
|
||||
*/
|
||||
$button.click();
|
||||
setTimeout(() => {
|
||||
expect($button.hasClass(flagIsHidden)).to.be.false;
|
||||
html2canvas.restore();
|
||||
done();
|
||||
}, 1000); // delay for screenshot and callback process
|
||||
});
|
||||
});
|
||||
|
||||
// 3. Input Handling
|
||||
describe('3. Input Handling', function() {
|
||||
let $input, $textarea;
|
||||
|
||||
beforeEach(function() {
|
||||
$input = $('<input type="text" value="test">').appendTo('body');
|
||||
$textarea = $('<textarea>test</textarea>').appendTo('body');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$input.remove();
|
||||
$textarea.remove();
|
||||
});
|
||||
|
||||
it('a. should clear input and textarea values during screenshot', function(done) {
|
||||
sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
$button.click();
|
||||
expect($input.val()).to.equal('');
|
||||
expect($textarea.val()).to.equal('');
|
||||
html2canvas.restore();
|
||||
done();
|
||||
});
|
||||
|
||||
it('b. should restore input and textarea values after screenshot', function(done) {
|
||||
sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
/*
|
||||
await waitForClick($button).then(() => {
|
||||
setTimeout(() => {
|
||||
expect($input.val()).to.equal('test');
|
||||
expect($textarea.val()).to.equal('test');
|
||||
}, 1000); // delay for screenshot and callback process
|
||||
})
|
||||
/*
|
||||
.catch((err) => {
|
||||
html2canvas.restore();
|
||||
throw err;
|
||||
})*
|
||||
;
|
||||
*/
|
||||
$button.click();
|
||||
setTimeout(() => {
|
||||
expect($input.val()).to.equal('test');
|
||||
expect($textarea.val()).to.equal('test');
|
||||
done();
|
||||
}, 1000);
|
||||
html2canvas.restore();
|
||||
});
|
||||
});
|
||||
|
||||
// 4. Modal and Floating Element Handling
|
||||
describe('4. Modal and Floating Element Handling', function() {
|
||||
let $modal;
|
||||
|
||||
beforeEach(function() {
|
||||
$modal = $('<div class="modal">Modal Content</div>').appendTo('body');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
$modal.remove();
|
||||
});
|
||||
|
||||
it('a. should capture visible modals', async function() {
|
||||
sinon.stub(window, 'html2canvas').callsFake(function(element) {
|
||||
expect($(element).find('.modal').length).to.equal(5);
|
||||
return Promise.resolve(document.createElement('canvas'));
|
||||
});
|
||||
await waitForClick($button);
|
||||
html2canvas.restore();
|
||||
});
|
||||
});
|
||||
|
||||
// 5. HTML2Canvas Integration
|
||||
describe('5. HTML2Canvas Integration', function() {
|
||||
it('a. should call html2canvas with correct parameters', async function() {
|
||||
const html2canvasStub = sinon.stub(window, 'html2canvas').resolves(document.createElement('canvas'));
|
||||
await waitForClick($button);
|
||||
html2canvas.restore();
|
||||
expect(html2canvasStub.calledWith(document.body)).to.be.true;
|
||||
});
|
||||
|
||||
it('b. should handle html2canvas errors gracefully', async function() {
|
||||
sinon.stub(window, 'html2canvas').rejects(new Error('Test error'));
|
||||
sinon.stub(console, 'error');
|
||||
await waitForClick($button);
|
||||
html2canvas.restore();
|
||||
expect(console.error.called).to.be.true;
|
||||
console.error.restore();
|
||||
});
|
||||
});
|
||||
|
||||
// 6. Screenshot Generation
|
||||
describe('6. Screenshot Generation', function() {
|
||||
/* Base64 string used instead of Blob
|
||||
it('a. should create a blob from the canvas', async function() {
|
||||
const canvas = document.createElement('canvas');
|
||||
sinon.stub(window, 'html2canvas').resolves(canvas);
|
||||
sinon.stub(canvas, 'toBlob').callsArgWith(0, new Blob());
|
||||
await waitForClick($button);
|
||||
html2canvas.restore();
|
||||
expect(canvas.toBlob.called).to.be.true;
|
||||
canvas.toBlob.restore();
|
||||
});
|
||||
*/
|
||||
|
||||
it('b. should generate a Base64 PNG string when saving is confirmed', async function() {
|
||||
const consoleStub = sinon.stub(console, 'log');
|
||||
await waitForClick($button).then(() => {
|
||||
setTimeout(() => {
|
||||
expect(consoleStub.callCount).to.equal(2);
|
||||
const base64String = consoleStub.getCall(0).args[1];
|
||||
expect(base64String).to.be.a('string');
|
||||
expect(base64String).to.match(/^data:image\/png;base64,/);
|
||||
consoleStub.restore();
|
||||
}, 1000); // delay for screenshot and callback process
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// 7. Download Functionality
|
||||
describe('7. Download Functionality', function() {
|
||||
it('a. should create a temporary anchor element for download', async function() {
|
||||
// Stub document.createElement
|
||||
createElementStub = sinon.stub(document, 'createElement').callsFake(function(tagName) {
|
||||
if (tagName === 'a') {
|
||||
return {
|
||||
style: {},
|
||||
href: '',
|
||||
download: '',
|
||||
click: sinon.spy()
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Stub document.body.appendChild and removeChild
|
||||
appendChildStub = sinon.stub(document.body, 'appendChild');
|
||||
removeChildStub = sinon.stub(document.body, 'removeChild');
|
||||
|
||||
// Mock blob and URL
|
||||
blobMock = new Blob(['test'], { type: 'text/plain' });
|
||||
urlMock = 'blob:http://example.com/test';
|
||||
sinon.stub(URL, 'createObjectURL').returns(urlMock);
|
||||
sinon.stub(URL, 'revokeObjectURL');
|
||||
|
||||
await waitForClick($button).then(() => {
|
||||
setTimeout(() => {
|
||||
// Assertions
|
||||
expect(createElementStub.calledWith('a')).to.be.true;
|
||||
expect(appendChildStub.calledOnce).to.be.true;
|
||||
expect(removeChildStub.calledOnce).to.be.true;
|
||||
|
||||
const aElement = appendChildStub.getCall(0).args[0];
|
||||
expect(aElement.href).to.equal(urlMock);
|
||||
expect(aElement.download).to.equal('screenshot.png'); // Assuming settings.fileName is 'screenshot.png'
|
||||
}, 1000);
|
||||
});
|
||||
/*
|
||||
const appendChildStub = sandbox.stub(document.body, 'appendChild').callsFake((element) => {
|
||||
console.log("attempting to append element: ", element);
|
||||
if (element.tagName === 'IFRAME') {
|
||||
// Allow iframe to be appended normally
|
||||
document.body.appendChild.wrappedMethod.call(document.body, element);
|
||||
}
|
||||
});
|
||||
sandbox.stub(document.body, 'removeChild');
|
||||
sandbox.stub(URL, 'createObjectURL').returns('blob:test');
|
||||
sandbox.stub(URL, 'revokeObjectURL');
|
||||
|
||||
await waitForClick($button).then(() => {
|
||||
setTimeout(() => {
|
||||
expect(document.body.appendChild.calledOnce).to.be.true;
|
||||
expect(document.body.appendChild.args[0][0].tagName).to.equal('A');
|
||||
}, 1000); // delay for screenshot and callback process
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
it('b. should click the temporary anchor element programmatically', async function() {
|
||||
const fakeAnchor = {
|
||||
style: {},
|
||||
click: sinon.spy()
|
||||
};
|
||||
sandbox.stub(document, 'createElement').returns(fakeAnchor);
|
||||
|
||||
await waitForClick($button);
|
||||
expect(fakeAnchor.click.calledOnce).to.be.true;
|
||||
});
|
||||
|
||||
it('c. should remove the temporary anchor after download', async function() {
|
||||
sandbox.stub(document.body, 'removeChild');
|
||||
|
||||
await waitForClick($button);
|
||||
expect(document.body.removeChild.calledOnce).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
// 8. Cross-browser Compatibility
|
||||
describe('8. Cross-browser Compatibility', function() {
|
||||
it('a. should work in Chrome-like environments', function() {
|
||||
// Assuming we're running tests in a Chrome-like environment
|
||||
expect(() => $button.screenshotButton()).to.not.throw();
|
||||
});
|
||||
|
||||
// Additional browser-specific tests would go here
|
||||
// These might need to be run in different environments or with browser mocks
|
||||
});
|
||||
|
||||
// 9. Performance
|
||||
describe('9. Performance', function() {
|
||||
it('a. should capture and generate screenshot within acceptable time', async function() {
|
||||
this.timeout(5000); // Adjust timeout as needed
|
||||
|
||||
const startTime = performance.now();
|
||||
|
||||
await waitForClick($button);
|
||||
|
||||
const endTime = performance.now();
|
||||
const duration = endTime - startTime;
|
||||
expect(duration).to.be.below(1000); // Adjust threshold as needed
|
||||
});
|
||||
|
||||
// Additional performance tests with different page complexities would go here
|
||||
});
|
||||
|
||||
// 10. Error Handling
|
||||
describe('10. Error Handling', function() {
|
||||
it('a. should log error when html2canvas is not loaded', async function() {
|
||||
const consoleErrorStub = sandbox.stub(console, 'error');
|
||||
const originalHtml2Canvas = window.html2canvas;
|
||||
delete window.html2canvas;
|
||||
|
||||
await waitForClick($button);
|
||||
|
||||
expect(consoleErrorStub.calledOnce).to.be.true;
|
||||
expect(consoleErrorStub.args[0][0]).to.include('html2canvas is not loaded');
|
||||
|
||||
// Restore html2canvas
|
||||
window.html2canvas = originalHtml2Canvas;
|
||||
});
|
||||
|
||||
it('a. should handle errors during capture process', async function() {
|
||||
sandbox.stub(window, 'html2canvas').rejects(new Error('Capture failed'));
|
||||
const consoleErrorStub = sandbox.stub(console, 'error');
|
||||
|
||||
await waitForClick($button);
|
||||
|
||||
expect(consoleErrorStub.calledOnce).to.be.true;
|
||||
expect(consoleErrorStub.args[0][0]).to.include('Capture failed');
|
||||
});
|
||||
});
|
||||
|
||||
// Configuration Options
|
||||
describe('11. Configuration Options', function() {
|
||||
it('11.1 should apply custom button text correctly', function() {
|
||||
const customText = 'Capture Screen';
|
||||
$button.screenshotButton({ buttonText: customText });
|
||||
expect($button.text()).to.equal(customText);
|
||||
});
|
||||
|
||||
it('11.2 should use custom filename for the downloaded image', async function() {
|
||||
const customFileName = 'custom-screenshot.png';
|
||||
$button.screenshotButton({ fileName: customFileName });
|
||||
|
||||
// Mock html2canvas and URL.createObjectURL
|
||||
global.html2canvas = sinon.stub().resolves({ toBlob: (callback) => callback(new Blob()) });
|
||||
global.URL.createObjectURL = sinon.stub().returns('blob:url');
|
||||
|
||||
// Mock anchor creation and click
|
||||
const anchorMock = {
|
||||
style: {},
|
||||
click: sinon.spy(),
|
||||
remove: sinon.spy()
|
||||
};
|
||||
sinon.stub(document, 'createElement').returns(anchorMock);
|
||||
|
||||
await waitForClick($button);
|
||||
|
||||
expect(anchorMock.download).to.equal(customFileName);
|
||||
document.createElement.restore();
|
||||
});
|
||||
|
||||
it('11.3 should respect custom modal selectors during capture', async function() {
|
||||
const customSelector = '.custom-modal';
|
||||
$button.screenshotButton({ modalsSelector: customSelector });
|
||||
|
||||
// Create a custom modal element
|
||||
$('<div class="custom-modal">Custom Modal</div>').appendTo('body');
|
||||
|
||||
// Mock html2canvas
|
||||
global.html2canvas = sinon.spy((element, options) => {
|
||||
expect(options.ignoreElements).to.be.a('function');
|
||||
const customModal = document.querySelector(customSelector);
|
||||
expect(options.ignoreElements(customModal)).to.be.false;
|
||||
done();
|
||||
return Promise.resolve({ toBlob: () => {} });
|
||||
});
|
||||
|
||||
await waitForClick($button);
|
||||
});
|
||||
});
|
||||
|
||||
// Accessibility
|
||||
describe('12. Accessibility', function() {
|
||||
it('12.1 should have appropriate ARIA attributes', function() {
|
||||
$button.screenshotButton(defaultOptions);
|
||||
expect($button.attr('role')).to.equal('button');
|
||||
expect($button.attr('aria-label')).to.equal(defaultOptions.buttonText);
|
||||
});
|
||||
|
||||
it('12.2 should be keyboard accessible', async function() {
|
||||
$button.screenshotButton(defaultOptions);
|
||||
$button.on('keydown', function(e) {
|
||||
if (e.which === 13) { // Enter key
|
||||
done();
|
||||
}
|
||||
});
|
||||
const event = new KeyboardEvent('keydown', { 'keyCode': 13 });
|
||||
$button[0].dispatchEvent(event);
|
||||
});
|
||||
});
|
||||
|
||||
// Security
|
||||
describe('13. Security', function() {
|
||||
it('13.1 should not capture sensitive information in inputs and textareas', async function() {
|
||||
$button.screenshotButton(defaultOptions);
|
||||
|
||||
// Create test input and textarea with sensitive information
|
||||
$('<input type="text" value="sensitive-info">').appendTo('body');
|
||||
$('<textarea>confidential-data</textarea>').appendTo('body');
|
||||
|
||||
// Mock html2canvas
|
||||
global.html2canvas = sinon.spy(() => {
|
||||
const inputs = document.querySelectorAll('input, textarea');
|
||||
inputs.forEach(input => {
|
||||
expect(input.value).to.be.empty;
|
||||
});
|
||||
done();
|
||||
return Promise.resolve({ toBlob: () => {} });
|
||||
});
|
||||
|
||||
await waitForClick($button);
|
||||
});
|
||||
|
||||
it('13.2 should restore input and textarea values after capture', async function() {
|
||||
$button.screenshotButton(defaultOptions);
|
||||
|
||||
const inputValue = 'sensitive-info';
|
||||
const textareaValue = 'confidential-data';
|
||||
|
||||
// Create test input and textarea with sensitive information
|
||||
$('<input type="text" value="' + inputValue + '">').appendTo('body');
|
||||
$('<textarea>' + textareaValue + '</textarea>').appendTo('body');
|
||||
|
||||
// Mock html2canvas and URL.createObjectURL
|
||||
global.html2canvas = sinon.stub().resolves({ toBlob: (callback) => callback(new Blob()) });
|
||||
global.URL.createObjectURL = sinon.stub().returns('blob:url');
|
||||
|
||||
await waitForClick($button);
|
||||
|
||||
setTimeout(() => {
|
||||
const inputs = document.querySelectorAll('input, textarea');
|
||||
inputs.forEach(input => {
|
||||
if (input.tagName === 'INPUT') {
|
||||
expect(input.value).to.equal(inputValue);
|
||||
} else if (input.tagName === 'TEXTAREA') {
|
||||
expect(input.value).to.equal(textareaValue);
|
||||
}
|
||||
});
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
// CSS Interaction
|
||||
describe('14. CSS Interaction', function() {
|
||||
it('14.1 should not break existing page styles', function() {
|
||||
const originalStyles = getComputedStyle(document.body);
|
||||
$button.screenshotButton();
|
||||
const newStyles = getComputedStyle(document.body);
|
||||
expect(originalStyles.cssText).to.equal(newStyles.cssText);
|
||||
});
|
||||
|
||||
it('14.2 should apply correct button styling', function() {
|
||||
$button.screenshotButton();
|
||||
const $button = $button.find('button');
|
||||
const buttonStyles = getComputedStyle($button[0]);
|
||||
expect(buttonStyles.display).to.not.equal('none');
|
||||
// Add more specific style checks as per your plugin's CSS
|
||||
});
|
||||
});
|
||||
|
||||
// jQuery Plugin Standards
|
||||
describe('15. jQuery Plugin Standards', function() {
|
||||
it('15.1 should return jQuery object for chaining', function() {
|
||||
const result = $button.screenshotButton();
|
||||
expect(result).to.equal($button);
|
||||
});
|
||||
|
||||
it('15.2 should initialize plugin on multiple elements', function() {
|
||||
$('body').append('<div class="test-class"></div><div class="test-class"></div>');
|
||||
$('.test-class').screenshotButton();
|
||||
expect($('.test-class').find('button').length).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
||||
// Memory Management
|
||||
describe('16. Memory Management', function() {
|
||||
it('16.1 should not leak memory on repeated initialization and destruction', function() {
|
||||
const initialMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;
|
||||
for (let i = 0; i < 100; i++) {
|
||||
$button.screenshotButton();
|
||||
$button.empty();
|
||||
}
|
||||
const finalMemory = performance.memory ? performance.memory.usedJSHeapSize : 0;
|
||||
expect(finalMemory - initialMemory).to.be.below(1000000); // Less than 1MB increase
|
||||
});
|
||||
|
||||
it('16.2 should remove all created DOM elements after use', function() {
|
||||
$button.screenshotButton();
|
||||
const initialChildCount = $button[0].childElementCount;
|
||||
$button.find('button').click();
|
||||
// Assuming the screenshot process is synchronous for this test
|
||||
expect($button[0].childElementCount).to.equal(initialChildCount);
|
||||
});
|
||||
});
|
||||
|
||||
// Responsiveness
|
||||
describe('17. Responsiveness', function() {
|
||||
it('17.1 should behave correctly on different screen sizes', function() {
|
||||
const viewports = [
|
||||
{width: 320, height: 568}, // iPhone 5
|
||||
{width: 1024, height: 768}, // iPad
|
||||
{width: 1920, height: 1080} // Full HD
|
||||
];
|
||||
|
||||
viewports.forEach(size => {
|
||||
$button.width(size.width).height(size.height);
|
||||
$button.screenshotButton();
|
||||
const $button = $button.find('button');
|
||||
expect($button.is(':visible')).to.be.true;
|
||||
expect($button.width()).to.be.at.most(size.width);
|
||||
});
|
||||
});
|
||||
|
||||
it('17.2 should capture accurate viewport in screenshot', async function() {
|
||||
$button.width(800).height(600);
|
||||
$button.html('<div id="content" style="width: 100%; height: 100%; background-color: red;"></div>');
|
||||
$button.screenshotButton();
|
||||
|
||||
const $button = $button.find('button');
|
||||
await waitForClick($button);
|
||||
|
||||
// Mock html2canvas to check if it's called with correct dimensions
|
||||
sinon.replace(window, 'html2canvas', sinon.fake.returns(Promise.resolve({
|
||||
toBlob: (callback) => callback(new Blob(['fakepngdata'], {type: 'image/png'}))
|
||||
})));
|
||||
|
||||
setTimeout(() => {
|
||||
expect(html2canvas.calledOnce).to.be.true;
|
||||
const args = html2canvas.firstCall.args[1];
|
||||
expect(args.width).to.equal(800);
|
||||
expect(args.height).to.equal(600);
|
||||
sinon.restore();
|
||||
done();
|
||||
}, 100);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user