UNPKG

qa-shadow-report

Version:

npm package that prints formatted test reports into a google sheet or csv file

577 lines (506 loc) 17.4 kB
import { buildFormulas, constructHeaderRegex, createMergeQueries, determineSubjectColumn, generatePlaceholders, generateReport, generateReportEntry, generateStateReports, generateTeamReport, generateTypeReport, getKeysPattern, } from './reportGenerationHelpers.js'; import { numberToLetter } from '../../sharedMethods/dataHandler.js'; import { initializeReportColumnMetrics } from '../../sharedMethods/summaryHandler.js'; import { PAYLOAD_TEST_DATA, TEST_OBJECTS, TEST_TYPES, TEST_CATEGORIES, } from '../../../__tests__/data/testData'; import { jest } from '@jest/globals'; describe('report generation helpers', () => { // Test Data Setup const createTestParams = (params) => ({ ...params, }); // generatePlaceholders Tests describe('generatePlaceholders', () => { it('should generate the correct number of placeholders', () => { const count = 3; const placeholders = generatePlaceholders(count); expect(placeholders).toEqual([ ['', ''], ['', ''], ['', ''], ]); }); it('should handle zero count', () => { const placeholders = generatePlaceholders(0); expect(placeholders).toEqual([]); }); it('should handle large count', () => { const count = 1000; const placeholders = generatePlaceholders(count); expect(placeholders.length).toBe(count); expect(placeholders[0]).toEqual(['', '']); }); it('should throw a TypeError if count is not a number', () => { expect(() => generatePlaceholders('3')).toThrow( 'The count must be a number.' ); }); it('should throw a TypeError if count is not an integer', () => { expect(() => generatePlaceholders(3.5)).toThrow( 'The count must be an integer.' ); }); it('should throw a TypeError if count is a negative number', () => { expect(() => generatePlaceholders(-1)).toThrow( 'The count must be a non-negative integer.' ); }); }); // generateReportEntry Tests describe('generateReportEntry', () => { it('should create a report entry with valid inputs', () => { const title = 'Test Title'; const formula = 'SUM(A1:A10)'; const reportEntry = generateReportEntry(title, formula); expect(reportEntry).toEqual([title, formula]); }); it('should handle long titles and formulas', () => { const title = 'A'.repeat(100); const formula = 'SUM(A1:A1000)'; const reportEntry = generateReportEntry(title, formula); expect(reportEntry).toEqual([title, formula]); }); it('should throw a TypeError if title is not a string', () => { expect(() => generateReportEntry(123, 'SUM(A1:A10)')).toThrow( 'Title must be a string.' ); }); it('should throw an Error if title is an empty string', () => { expect(() => generateReportEntry('', 'SUM(A1:A10)')).toThrow( 'Title cannot be an empty string.' ); }); it('should throw a TypeError if formula is not a string', () => { expect(() => generateReportEntry('Test Title', 123)).toThrow( 'Formula must be a string.' ); }); it('should throw an Error if formula is an empty string', () => { expect(() => generateReportEntry('Test Title', '')).toThrow( 'Formula cannot be an empty string.' ); }); }); // generateStateReports Tests describe('generateStateReports', () => { it('should generate report entries with valid inputs', () => { const defaultHeaderMetrics = [ '# Total tests', '# Passed tests', '# Failed tests', ]; const index = 0; const reports = generateStateReports(defaultHeaderMetrics, index); expect(reports).toEqual([ ['# Total tests', 'Total formula base'], ['# Passed tests', 'Total formula base'], ['# Failed tests', 'Total formula base'], ]); }); it('should handle different metric types', () => { const defaultHeaderMetrics = ['# Skipped tests', '# Pending tests']; const index = 0; const reports = generateStateReports(defaultHeaderMetrics, index); expect(reports).toEqual([ ['# Skipped tests', 'Skipped formula base'], ['# Pending tests', 'Skipped formula base'], ]); }); it('should throw a TypeError if defaultHeaderMetrics is not an array', () => { expect(() => generateStateReports('not an array', 0)).toThrow( 'defaultHeaderMetrics must be an array of strings.' ); }); it('should throw a TypeError if defaultHeaderMetrics contains non-string elements', () => { expect(() => generateStateReports([1, 2, 3], 0)).toThrow( 'Each item in defaultHeaderMetrics must be a string.' ); }); it('should throw a TypeError if index is not a number', () => { expect(() => generateStateReports(['# Total tests'], 'not a number') ).toThrow('index must be an integer.'); }); it('should throw a RangeError if index is out of bounds', () => { expect(() => generateStateReports(['# Total tests'], 1)).toThrow( 'index is out of bounds for defaultHeaderMetrics.' ); }); it('should throw a TypeError if the extracted type is not a string', () => { expect(() => generateStateReports(['# tests'], 0)).toThrow( 'The extracted type must be a non-empty string.' ); }); }); // generateTeamReport Tests describe('generateTeamReport', () => { it('should generate a report entry with a valid type', () => { const type = 'Team Alpha'; const reportEntry = generateTeamReport(type); expect(reportEntry).toEqual([ '# Team Alpha tests passed', 'Team Alpha formula tests passed', ]); }); it('should handle team names with special characters', () => { const type = 'Team-123_Alpha'; const reportEntry = generateTeamReport(type); expect(reportEntry).toEqual([ '# Team-123_Alpha tests passed', 'Team-123_Alpha formula tests passed', ]); }); it('should throw a TypeError if type is not a string', () => { expect(() => generateTeamReport(123)).toThrow( 'Type must be a non-empty string.' ); }); it('should throw a TypeError if type is an empty string', () => { expect(() => generateTeamReport('')).toThrow( 'Type must be a non-empty string.' ); }); it('should throw a TypeError if type is a string with only whitespace', () => { expect(() => generateTeamReport(' ')).toThrow( 'Type must be a non-empty string.' ); }); }); // generateTypeReport Tests describe('generateTypeReport', () => { it('should generate report entries with a valid type', () => { const type = 'Unit'; const reportEntries = generateTypeReport(type); expect(reportEntries).toEqual([ ['# Unit tests passed', 'Unit formula tests passed'], ]); }); it('should handle test types with special characters', () => { const type = 'E2E-Test'; const reportEntries = generateTypeReport(type); expect(reportEntries).toEqual([ ['# E2E-Test tests passed', 'E2E-Test formula tests passed'], ]); }); it('should throw a TypeError if type is not a string', () => { expect(() => generateTypeReport(123)).toThrow( 'Type must be a non-empty string.' ); }); it('should throw a TypeError if type is an empty string', () => { expect(() => generateTypeReport('')).toThrow( 'Type must be a non-empty string.' ); }); it('should throw a TypeError if type is a string with only whitespace', () => { expect(() => generateTypeReport(' ')).toThrow( 'Type must be a non-empty string.' ); }); }); // generateReport Tests describe('generateReport', () => { it('should generate a report with valid inputs', () => { const types = ['Unit', 'Integration']; const payload = [ ['Unit', 'Test 1', 'Passed'], ['Integration', 'Test 2', 'Failed'], ['Unit', 'Test 3', 'Passed'], ]; const searchIndex = 0; const isTeam = false; const report = generateReport(types, payload, searchIndex, isTeam); expect(report).toEqual([ ['# Unit tests passed', 'Unit formula tests passed'], ['# Integration tests passed', 'Integration formula tests passed'], ]); }); it('should handle team reports', () => { const types = ['Team Alpha', 'Team Beta']; const payload = [ ['Team Alpha', 'Test 1', 'Passed'], ['Team Beta', 'Test 2', 'Failed'], ]; const searchIndex = 0; const isTeam = true; const report = generateReport(types, payload, searchIndex, isTeam); expect(report).toEqual([ ['# Team Alpha tests passed', 'Team Alpha formula tests passed'], ['# Team Beta tests passed', 'Team Beta formula tests passed'], ]); }); it('should handle empty types array gracefully', () => { const report = generateReport([], [['Unit', 'Test 1']], 0); expect(report).toEqual([]); }); it('should handle empty payload gracefully', () => { const report = generateReport(['Unit'], [], 0); expect(report).toEqual([]); }); it('should throw an error if types is not an array', () => { expect(() => generateReport('not an array', [], 0)).toThrow( 'Types must be an array.' ); }); it('should throw an error if types contains non-string elements', () => { expect(() => generateReport([123], [], 0)).toThrow( 'All types must be strings.' ); }); it('should throw an error if payload is not an array', () => { expect(() => generateReport([], 'not an array', 0)).toThrow( 'Payload must be an array.' ); }); it('should throw an error if searchIndex is not a non-negative integer', () => { expect(() => generateReport([], [], -1)).toThrow( 'SearchIndex must be a non-negative integer.' ); }); it('should throw an error if isTeam is not a boolean', () => { expect(() => generateReport([], [], 0, 'not a boolean')).toThrow( 'isTeam must be a boolean.' ); }); }); // buildFormulas Tests describe('buildFormulas', () => { it('should build formulas with valid inputs', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 1, totalNumberOfRows: 10, bodyRowCount: 8, subjectColumn: 'A', stateColumn: 'B', }); const formulas = buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ); expect(formulas).toBeDefined(); expect(typeof formulas).toBe('object'); }); it('should handle different column combinations', () => { const params = createTestParams({ type: 'Integration', headerRowIndex: 1, totalNumberOfRows: 10, bodyRowCount: 8, subjectColumn: 'C', stateColumn: 'D', }); const formulas = buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ); expect(formulas).toBeDefined(); expect(typeof formulas).toBe('object'); }); it('should throw an error if type is not a string', () => { const params = createTestParams({ type: 123, headerRowIndex: 1, totalNumberOfRows: 10, bodyRowCount: 8, subjectColumn: 'A', stateColumn: 'B', }); expect(() => buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ) ).toThrow('Type must be a string.'); }); it('should throw an error if headerRowIndex is not a positive integer', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 0, totalNumberOfRows: 10, bodyRowCount: 8, subjectColumn: 'A', stateColumn: 'B', }); expect(() => buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ) ).toThrow('Header row index must be a positive integer.'); }); it('should throw an error if totalNumberOfRows is not greater than headerRowIndex', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 5, totalNumberOfRows: 5, bodyRowCount: 8, subjectColumn: 'A', stateColumn: 'B', }); expect(() => buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ) ).toThrow( 'Total number of rows must be an integer greater than header row index.' ); }); it('should throw an error if bodyRowCount is not a positive integer', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 1, totalNumberOfRows: 10, bodyRowCount: 0, subjectColumn: 'A', stateColumn: 'B', }); expect(() => buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ) ).toThrow('Body row count must be a positive integer.'); }); it('should throw an error if subjectColumn is not a non-empty string', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 1, totalNumberOfRows: 10, bodyRowCount: 8, subjectColumn: '', stateColumn: 'B', }); expect(() => buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ) ).toThrow('Subject column must be a non-empty string.'); }); it('should throw an error if stateColumn is not a non-empty string', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 1, totalNumberOfRows: 10, bodyRowCount: 8, subjectColumn: 'A', stateColumn: '', }); expect(() => buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ) ).toThrow('State column must be a non-empty string.'); }); }); // Performance Tests describe('Performance', () => { it('should generate reports efficiently for large datasets', () => { const types = Array(100).fill('Unit'); const payload = Array(1000).fill(['Unit', 'Test', 'Passed']); const searchIndex = 0; const isTeam = false; const startTime = performance.now(); const report = generateReport(types, payload, searchIndex, isTeam); const endTime = performance.now(); expect(report).toBeDefined(); expect(Array.isArray(report)).toBe(true); expect(endTime - startTime).toBeLessThan(100); // Should complete within 100ms }); it('should build formulas efficiently for large datasets', () => { const params = createTestParams({ type: 'Unit', headerRowIndex: 1, totalNumberOfRows: 1000, bodyRowCount: 998, subjectColumn: 'A', stateColumn: 'B', }); const startTime = performance.now(); const formulas = buildFormulas( params.type, params.headerRowIndex, params.totalNumberOfRows, params.bodyRowCount, params.subjectColumn, params.stateColumn ); const endTime = performance.now(); expect(formulas).toBeDefined(); expect(typeof formulas).toBe('object'); expect(endTime - startTime).toBeLessThan(100); // Should complete within 100ms }); }); describe('initializeReportColumnMetrics', () => { it('should initialize column metrics', () => { const headerIndicatorsLength = 3; const result = initializeReportColumnMetrics(headerIndicatorsLength); expect(result).toEqual({ nextAvailableColumn: 0, defaultHeaderMetricsDestinationColumn: 0, longestHeaderEnd: 0, defaultHeaderMetricsDestinationColumnEnd: 3, }); }); it('should handle zero length', () => { const result = initializeReportColumnMetrics(0); expect(result).toEqual({ nextAvailableColumn: 0, defaultHeaderMetricsDestinationColumn: 0, longestHeaderEnd: 0, defaultHeaderMetricsDestinationColumnEnd: 0, }); }); }); });