UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

397 lines (324 loc) 15.4 kB
import Print from "../../../src/js/modules/Print/Print"; describe("Print module", () => { /** @type {Print} */ let print; let mockTable; let addEventListenerSpy; let removeEventListenerSpy; let originalWindowPrint; let originalScrollTo; beforeEach(() => { // Save original window methods originalWindowPrint = window.print; originalScrollTo = window.scrollTo; // Mock window methods window.print = jest.fn(); window.scrollTo = jest.fn(); window.scrollX = 100; window.scrollY = 100; // Spy on window event listeners addEventListenerSpy = jest.spyOn(window, 'addEventListener'); removeEventListenerSpy = jest.spyOn(window, 'removeEventListener'); // Mock document methods and elements document.createElement = jest.fn().mockImplementation((tagName) => { const element = { tagName: tagName.toUpperCase(), classList: { add: jest.fn() }, style: {}, appendChild: jest.fn(), parentNode: { insertBefore: jest.fn(), removeChild: jest.fn() }, innerHTML: "" }; return element; }); // Instead of replacing document.body, just spy on its methods if (document.body) { jest.spyOn(document.body.classList, 'add').mockImplementation(() => {}); jest.spyOn(document.body.classList, 'remove').mockImplementation(() => {}); jest.spyOn(document.body, 'appendChild').mockImplementation(() => {}); } // Create mock element const mockElement = { style: {}, parentNode: { insertBefore: jest.fn() } }; // Create mock export module const mockExportModule = { generateTable: jest.fn().mockReturnValue({ table: true }) }; // Create mock eventBus const mockEventBus = { subscribe: jest.fn() }; // Create mock optionsList const mockOptionsList = { register: jest.fn() }; // Create mock functionRegistry const mockFunctionRegistry = {}; // Create a simplified mock of the table mockTable = { element: mockElement, modules: { export: mockExportModule }, options: { printAsHtml: false, printFormatter: false, printHeader: false, printFooter: false, printStyled: true, printRowRange: "visible", printConfig: {} }, eventBus: mockEventBus, optionsList: mockOptionsList, functionRegistry: mockFunctionRegistry }; // Mock methods in the Print prototype jest.spyOn(Print.prototype, 'registerTableOption').mockImplementation(function(key, value) { this.table.options[key] = this.table.options[key] || value; }); jest.spyOn(Print.prototype, 'registerColumnOption').mockImplementation(function(key) { this.table.optionsList.register(key); }); jest.spyOn(Print.prototype, 'registerTableFunction').mockImplementation(function(key, callback) { this.table.functionRegistry[key] = callback; }); jest.spyOn(Print.prototype, 'subscribe').mockImplementation(function(key, callback) { return this.table.eventBus.subscribe(key, callback); }); // Create an instance of the Print module with the mock table print = new Print(mockTable); }); afterEach(() => { jest.clearAllMocks(); jest.restoreAllMocks(); // Restore original window methods window.print = originalWindowPrint; window.scrollTo = originalScrollTo; }); it("should register all table options during construction", () => { // Verify table options are registered expect(mockTable.options.printAsHtml).toBe(false); expect(mockTable.options.printFormatter).toBe(false); expect(mockTable.options.printHeader).toBe(false); expect(mockTable.options.printFooter).toBe(false); expect(mockTable.options.printStyled).toBe(true); expect(mockTable.options.printRowRange).toBe("visible"); expect(mockTable.options.printConfig).toEqual({}); }); it("should register column options during construction", () => { // Verify column options are registered expect(mockTable.optionsList.register).toHaveBeenCalledWith("print"); expect(mockTable.optionsList.register).toHaveBeenCalledWith("titlePrint"); }); it("should register table print function during initialization", () => { // Initialize print module print.initialize(); // Verify print function is registered expect(mockTable.functionRegistry.print).toBeDefined(); }); it("should not set up event listeners when printAsHtml is false", () => { // Initialize print module with printAsHtml = false mockTable.options.printAsHtml = false; print.initialize(); // Verify event listeners are not added expect(addEventListenerSpy).not.toHaveBeenCalledWith("beforeprint", expect.any(Function)); expect(addEventListenerSpy).not.toHaveBeenCalledWith("afterprint", expect.any(Function)); }); it("should set up event listeners when printAsHtml is true", () => { // Initialize print module with printAsHtml = true mockTable.options.printAsHtml = true; print.initialize(); // Verify event listeners are added expect(addEventListenerSpy).toHaveBeenCalledWith("beforeprint", expect.any(Function)); expect(addEventListenerSpy).toHaveBeenCalledWith("afterprint", expect.any(Function)); expect(mockTable.eventBus.subscribe).toHaveBeenCalledWith("table-destroy", expect.any(Function)); }); it("should clean up event listeners on destroy", () => { // Initialize print module with printAsHtml = true mockTable.options.printAsHtml = true; print.initialize(); // Destroy print module print.destroy(); // Verify event listeners are removed expect(removeEventListenerSpy).toHaveBeenCalledWith("beforeprint", expect.any(Function)); expect(removeEventListenerSpy).toHaveBeenCalledWith("afterprint", expect.any(Function)); }); it("should replace table with print version on beforeprint event", () => { // Initialize print module with printAsHtml = true mockTable.options.printAsHtml = true; print.initialize(); // Call replaceTable (this would be triggered by beforeprint event) print.replaceTable(); // Verify table is replaced expect(document.createElement).toHaveBeenCalledWith("div"); expect(print.element.classList.add).toHaveBeenCalledWith("tabulator-print-table"); expect(mockTable.modules.export.generateTable).toHaveBeenCalledWith( mockTable.options.printConfig, mockTable.options.printStyled, mockTable.options.printRowRange, "print" ); expect(mockTable.element.style.display).toBe("none"); expect(mockTable.element.parentNode.insertBefore).toHaveBeenCalledWith(print.element, mockTable.element); }); it("should clean up after printing", () => { // Set up element and call cleanup print.element = document.createElement("div"); mockTable.element.style.display = "none"; // Call cleanup (this would be triggered by afterprint event) print.cleanup(); // Verify cleanup expect(document.body.classList.remove).toHaveBeenCalledWith("tabulator-print-fullscreen-hide"); expect(print.element.parentNode.removeChild).toHaveBeenCalledWith(print.element); expect(mockTable.element.style.display).toBe(""); }); it("should print table in fullscreen mode", () => { // Initialize print module print.initialize(); // Call printFullscreen print.printFullscreen(); // Verify fullscreen print setup expect(document.createElement).toHaveBeenCalledWith("div"); expect(print.element.classList.add).toHaveBeenCalledWith("tabulator-print-fullscreen"); expect(mockTable.modules.export.generateTable).toHaveBeenCalledWith( mockTable.options.printConfig, mockTable.options.printStyled, mockTable.options.printRowRange, "print" ); expect(document.body.classList.add).toHaveBeenCalledWith("tabulator-print-fullscreen-hide"); expect(document.body.appendChild).toHaveBeenCalledWith(print.element); expect(window.print).toHaveBeenCalled(); expect(window.scrollTo).toHaveBeenCalledWith(100, 100); }); it("should print table with custom visible, style, and config parameters", () => { // Initialize print module print.initialize(); // Call printFullscreen with custom parameters print.printFullscreen(true, false, { custom: "config" }); // Verify parameters are passed to generateTable expect(mockTable.modules.export.generateTable).toHaveBeenCalledWith( { custom: "config" }, false, true, "print" ); }); it("should add header to print output if printHeader is provided as string", () => { // Set header option as string mockTable.options.printHeader = "Test Header"; // Initialize and print print.initialize(); print.printFullscreen(); // Verify header is created and added expect(document.createElement).toHaveBeenCalledWith("div"); expect(print.element.appendChild).toHaveBeenCalledTimes(2); // header and table // Get the header element (first created div) const headerEl = document.createElement.mock.results[0].value; // Verify header setup expect(headerEl.classList.add).toHaveBeenCalledWith("tabulator-print-header"); expect(headerEl.innerHTML).toBe("Test Header"); }); it("should add header to print output if printHeader is provided as function", () => { // Create header element const headerContent = document.createElement("h1"); // Spy on document.createElement to capture calls const createElementSpy = jest.spyOn(document, 'createElement'); // Set header option as function mockTable.options.printHeader = jest.fn().mockReturnValue(headerContent); // Initialize and print print.initialize(); print.printFullscreen(); // Verify header function is called expect(mockTable.options.printHeader).toHaveBeenCalled(); // Find the header element by looking at all created elements and finding the one // that had the tabulator-print-header class added to it let headerEl = null; createElementSpy.mock.results.forEach(result => { const el = result.value; if (el.classList.add.mock.calls.some(call => call[0] === "tabulator-print-header")) { headerEl = el; } }); // Verify header setup expect(headerEl).not.toBeNull(); expect(headerEl.classList.add).toHaveBeenCalledWith("tabulator-print-header"); expect(headerEl.appendChild).toHaveBeenCalledWith(headerContent); }); it("should add footer to print output if printFooter is provided as string", () => { // Set footer option as string mockTable.options.printFooter = "Test Footer"; // Initialize and print print.initialize(); print.printFullscreen(); // Verify footer is created and added expect(document.createElement).toHaveBeenCalledWith("div"); expect(print.element.appendChild).toHaveBeenCalledTimes(2); // table and footer // Get the footer element (second created div) const footerEl = document.createElement.mock.results[1].value; // Verify footer setup expect(footerEl.classList.add).toHaveBeenCalledWith("tabulator-print-footer"); expect(footerEl.innerHTML).toBe("Test Footer"); }); it("should add footer to print output if printFooter is provided as function", () => { // Create footer element const footerContent = document.createElement("div"); // Spy on document.createElement to capture calls const createElementSpy = jest.spyOn(document, 'createElement'); // Set footer option as function mockTable.options.printFooter = jest.fn().mockReturnValue(footerContent); // Initialize and print print.initialize(); print.printFullscreen(); // Verify footer function is called expect(mockTable.options.printFooter).toHaveBeenCalled(); // Find the footer element by looking at all created elements and finding the one // that had the tabulator-print-footer class added to it let footerEl = null; createElementSpy.mock.results.forEach(result => { const el = result.value; if (el.classList.add.mock.calls.some(call => call[0] === "tabulator-print-footer")) { footerEl = el; } }); // Verify footer setup expect(footerEl).not.toBeNull(); expect(footerEl.classList.add).toHaveBeenCalledWith("tabulator-print-footer"); expect(footerEl.appendChild).toHaveBeenCalledWith(footerContent); }); it("should call printFormatter if provided", () => { // Set formatter function mockTable.options.printFormatter = jest.fn(); // Initialize and print print.initialize(); print.printFullscreen(); // Verify formatter is called expect(mockTable.options.printFormatter).toHaveBeenCalledWith( print.element, { table: true } // mock table element returned by generateTable ); }); it("should not replace table during window.print if manual block is active", () => { // Initialize print module with printAsHtml = true mockTable.options.printAsHtml = true; print.initialize(); // Set manual block and call replaceTable print.manualBlock = true; print.replaceTable(); // Verify table is not replaced expect(document.createElement).not.toHaveBeenCalled(); expect(mockTable.modules.export.generateTable).not.toHaveBeenCalled(); }); });