Skip to content

Commit

Permalink
chore(EMS-3539): improve xlsx styled column functions (#3251)
Browse files Browse the repository at this point in the history
* chore(EMS-3539): improve xlsx styled column functions

* chore(EMS-3539): improve xlsx styled column functions

* chore(EMS-3539): improve xlsx generation functions

* chore(EMS-3539): add missing unit test

* chore(EMS-3539): improve documentation

* chore(EMS-3539): fix/update unit test

* chore(EMS-3539): fix typo

* chore(tests): fix date related unit test
  • Loading branch information
ttbarnes authored Dec 6, 2024
1 parent 11bfc41 commit e3c458c
Show file tree
Hide file tree
Showing 15 changed files with 409 additions and 127 deletions.
82 changes: 55 additions & 27 deletions src/api/.keystone/config.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import APPLICATION_INFORMATION_INDEXES from '.';

describe('api/constants/XLSX-CONFIG/INDEXES/APPLICATION_INFORMATION', () => {
it('should return an object with indexes', () => {
const expected = {
EXPORTER_CONTACT_DETAILS: 8,
KEY_INFORMATION: 13,
};

expect(APPLICATION_INFORMATION_INDEXES).toEqual(expected);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* APPLICATION_INFORMATION
* Default indexes for the "Application information" XLSX worksheet.
*/
const APPLICATION_INFORMATION_INDEXES = {
EXPORTER_CONTACT_DETAILS: 8,
KEY_INFORMATION: 13,
};

export default APPLICATION_INFORMATION_INDEXES;
7 changes: 7 additions & 0 deletions src/api/constants/XLSX-CONFIG/INDEXES/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ const { EXPORTER_BUSINESS, POLICY, BUYER, EXPORT_CONTRACT } = SECTION_NAMES;
/**
* XLSX_ROW_INDEXES
* Generate row indexes for each worksheet in the XLSX.
* If a row requires some additional row height - for example, for a multi-line address field,
* The row's index should be listed in the relevant section below.
* No other indexes need to be listed.
* NOTE: The APPLICATION_INFORMATION section indexes are intentionally excluded from here,
* because it does NOT require additional heights.
* - The APPLICATION_INFORMATION indexes are consumed in another area for other, non-height styling purposes.
* - The APPLICATION_INFORMATION has some unique requirements unlike all other sections.
* @returns {Object}
*/
const XLSX_ROW_INDEXES = {
Expand Down
70 changes: 30 additions & 40 deletions src/api/generate-xlsx/styled-columns/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,46 @@
import ExcelJS from 'exceljs';
import styledColumns, { worksheetRowHeights } from '.';
import { XLSX_CONFIG } from '../../constants';
import styledColumns, { getAdditionalRowHeightIndexes } from '.';
import XLSX_ROW_INDEXES from '../../constants/XLSX-CONFIG/INDEXES';
import modifyRowStyles from './modify-row-styles';
import modifyRowHeights from './modify-row-heights';
import { mockApplicationMinimalBrokerBuyerAndCompany as mockApplication } from '../../test-mocks';

const { LARGE_ADDITIONAL_COLUMN_HEIGHT, ADDITIONAL_TITLE_COLUMN_HEIGHT, FONT_SIZE } = XLSX_CONFIG;
import createMockWorksheet from '../../test-mocks/create-mock-worksheet';

describe('api/generate-xlsx/styled-columns/index', () => {
const mockSheetName = 'mock sheet name';
const { mockWorksheet, mockSheetName } = createMockWorksheet();

const workbook = new ExcelJS.Workbook();
describe('getAdditionalRowHeightIndexes', () => {
describe('when a provided sheetName is in XLSX_ROW_INDEXES', () => {
it('should return index values', () => {
const result = getAdditionalRowHeightIndexes(mockApplication, mockSheetName);

const worksheet = workbook.addWorksheet(mockSheetName);
const sheetIndexes = XLSX_ROW_INDEXES[mockSheetName](mockApplication);

describe('worksheetRowHeights', () => {
it('should add column heights to particular columns', async () => {
const mockIndexes = [5, 6];
const expected = Object.values(sheetIndexes);

const result = worksheetRowHeights(mockIndexes, worksheet);
expect(result).toEqual(expected);
});
});

result.eachRow((row, rowNumber) => {
if (rowNumber === 1) {
expect(row.height).toEqual(ADDITIONAL_TITLE_COLUMN_HEIGHT);
} else if (mockIndexes.includes(rowNumber)) {
expect(row.height).toEqual(LARGE_ADDITIONAL_COLUMN_HEIGHT);
}
describe('when a provided sheetName is NOT in XLSX_ROW_INDEXES', () => {
it('should return an empty array', () => {
const result = getAdditionalRowHeightIndexes(mockApplication, 'invalid sheet name');

expect(result).toEqual([]);
});
});
});

describe('styledColumns', () => {
it('should add custom `alignment` and font size properties to each column', async () => {
const result = styledColumns(mockApplication, worksheet, mockSheetName);

result.eachRow((row, rowNumber) => {
const isHeaderRow = rowNumber === 1;

if (isHeaderRow) {
row.eachCell((cell, colNumber) => {
const cellData = row.getCell(colNumber);

expect(cellData.font.bold).toEqual(true);
expect(cellData.font.size).toEqual(FONT_SIZE.TITLE);
});
} else {
row.eachCell((cell, colNumber) => {
const cellData = row.getCell(colNumber);

expect(cellData.font.bold).toEqual(false);
expect(cellData.font.size).toEqual(FONT_SIZE.DEFAULT);
});
}
});
it('should return a modified worksheet', async () => {
const result = styledColumns(mockApplication, mockWorksheet, mockSheetName);

const modifiedRowStyles = modifyRowStyles(mockWorksheet, mockSheetName);

const indexes = getAdditionalRowHeightIndexes(mockApplication, mockSheetName);

const expected = modifyRowHeights(indexes, modifiedRowStyles, mockSheetName);

expect(result).toEqual(expected);
});
});
});
79 changes: 20 additions & 59 deletions src/api/generate-xlsx/styled-columns/index.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,29 @@
import { Row, Worksheet } from 'exceljs';
import { XLSX_CONFIG } from '../../constants';
import { Worksheet } from 'exceljs';
import XLSX_ROW_INDEXES from '../../constants/XLSX-CONFIG/INDEXES';
import SECTION_NAMES from '../../constants/XLSX-CONFIG/SECTION_NAMES';
import modifyRowStyles from './modify-row-styles';
import modifyRowHeights from './modify-row-heights';
import { Application } from '../../types';

const { LARGE_ADDITIONAL_COLUMN_HEIGHT, ADDITIONAL_TITLE_COLUMN_HEIGHT, FONT_SIZE } = XLSX_CONFIG;

const { APPLICATION_INFORMATION } = SECTION_NAMES;
// TODO: unit test for getAdditionalRowHeightIndexes

/**
* worksheetRowHeights
* Add custom heights to certain worksheet cells
* @param {Array<number>} rowIndexes: Row indexes
* @param {ExcelJS.Worksheet} worksheet: ExcelJS worksheet
* @param {String} ExcelJS sheetName: worksheet name
* @returns {ExcelJS.Worksheet} ExcelJS worksheet
* getAdditionalRowHeightIndexes
* Get some specific row indexes for the XLSX.
* These indexes are then used for styling purposes.
* @param {Application} application
* @param {String} sheetName: ExcelJS worksheet name
* @returns {Array<number>} Row indexes
*/
export const worksheetRowHeights = (rowIndexes: Array<number>, worksheet: Worksheet, sheetName: string) => {
const modifiedWorksheet = worksheet;

modifiedWorksheet.getRow(1).height = ADDITIONAL_TITLE_COLUMN_HEIGHT;
export const getAdditionalRowHeightIndexes = (application: Application, sheetName: string) => {
let INDEXES = [] as Array<number>;

const isInformationSheet = sheetName === APPLICATION_INFORMATION;
if (XLSX_ROW_INDEXES[sheetName]) {
const sheetIndexes = XLSX_ROW_INDEXES[sheetName](application);

if (isInformationSheet) {
modifiedWorksheet.getRow(8).height = ADDITIONAL_TITLE_COLUMN_HEIGHT;
modifiedWorksheet.getRow(13).height = ADDITIONAL_TITLE_COLUMN_HEIGHT;
INDEXES = Object.values(sheetIndexes);
}

rowIndexes.forEach((rowIndex) => {
modifiedWorksheet.getRow(rowIndex).height = LARGE_ADDITIONAL_COLUMN_HEIGHT;
});

return modifiedWorksheet;
return INDEXES;
};

/**
Expand All @@ -44,43 +35,13 @@ export const worksheetRowHeights = (rowIndexes: Array<number>, worksheet: Worksh
* @returns {ExcelJS.Worksheet} ExcelJS worksheet
*/
const styledColumns = (application: Application, worksheet: Worksheet, sheetName: string) => {
let modifiedWorksheet = worksheet;

modifiedWorksheet.eachRow((row: Row, rowNumber: number) => {
row.eachCell((cell, colNumber) => {
const modifiedRow = row;
const withRowStyles = modifyRowStyles(worksheet, sheetName);

modifiedRow.getCell(colNumber).alignment = {
vertical: 'top',
wrapText: true,
};

const isInformationSheet = sheetName === APPLICATION_INFORMATION;
const isInformationTitleOne = isInformationSheet && rowNumber === 8;
const isInformationTitleTwo = isInformationSheet && rowNumber === 13;

const isInformationTitle = isInformationTitleOne || isInformationTitleTwo;

const isTitleRow = rowNumber === 1 || isInformationTitle;

modifiedRow.getCell(colNumber).font = {
bold: Boolean(isTitleRow),
size: isTitleRow ? FONT_SIZE.TITLE : FONT_SIZE.DEFAULT,
};
});
});

let INDEXES = [] as Array<number>;

if (XLSX_ROW_INDEXES[sheetName]) {
const sheetIndexes = XLSX_ROW_INDEXES[sheetName](application);

INDEXES = Object.values(sheetIndexes);
}
const indexes = getAdditionalRowHeightIndexes(application, sheetName);

modifiedWorksheet = worksheetRowHeights(INDEXES, modifiedWorksheet, sheetName);
const withRowHeights = modifyRowHeights(indexes, withRowStyles, sheetName);

return modifiedWorksheet;
return withRowHeights;
};

export default styledColumns;
56 changes: 56 additions & 0 deletions src/api/generate-xlsx/styled-columns/is-title-row/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import isTitleRow from '.';
import SECTION_NAMES from '../../../constants/XLSX-CONFIG/SECTION_NAMES';
import APPLICATION_INFORMATION_INDEXES from '../../../constants/XLSX-CONFIG/INDEXES/APPLICATION_INFORMATION';

const { APPLICATION_INFORMATION } = SECTION_NAMES;
const { EXPORTER_CONTACT_DETAILS, KEY_INFORMATION } = APPLICATION_INFORMATION_INDEXES;

describe('api/generate-xlsx/styled-columns/is-title-row', () => {
describe(`when the sheetName is ${APPLICATION_INFORMATION}`, () => {
const mockSheetName = APPLICATION_INFORMATION;

describe(`when rowNumber=${EXPORTER_CONTACT_DETAILS}`, () => {
it('should return true', () => {
const result = isTitleRow(mockSheetName, EXPORTER_CONTACT_DETAILS);

expect(result).toEqual(true);
});
});

describe(`when rowNumber=${KEY_INFORMATION}`, () => {
it('should return true', () => {
const result = isTitleRow(mockSheetName, KEY_INFORMATION);

expect(result).toEqual(true);
});
});

describe('when rowNumber is NOT 8 or 13', () => {
it('should return false', () => {
const result = isTitleRow(mockSheetName, 5);

expect(result).toEqual(false);
});
});
});

describe(`when the sheetName is NOT ${APPLICATION_INFORMATION}`, () => {
const mockSheetName = 'Mock sheet name';

describe('when rowNumber=1', () => {
it('should return true', () => {
const result = isTitleRow(mockSheetName, 1);

expect(result).toEqual(true);
});
});

describe('when rowNumber is NOT 1', () => {
it('should return false', () => {
const result = isTitleRow(mockSheetName, 5);

expect(result).toEqual(false);
});
});
});
});
Loading

0 comments on commit e3c458c

Please sign in to comment.