@ministryofjustice/hmpps-digital-prison-reporting-frontend
Version:
The Digital Prison Reporting Frontend contains templates and code to help display data effectively in UI applications.
598 lines (555 loc) • 15 kB
text/typescript
import Dict = NodeJS.Dict
import ReportQuery from '../../types/ReportQuery'
import { components } from '../../types/api'
import DataTableBuilder from './DataTableBuilder'
import { AsyncSummary } from '../../types/UserReports'
import { Template } from '../../types/Templates'
const defaultField: components['schemas']['FieldDefinition'] = {
name: 'date',
display: 'Date',
sortable: true,
defaultsort: false,
type: 'date',
mandatory: false,
visible: true,
calculated: false,
}
const defaultSpec: components['schemas']['Specification'] = {
fields: [defaultField],
template: 'list',
sections: [],
}
describe('mapData', () => {
it('Dates with values less than 10 mapped with leading 0', () => {
const data: Dict<string> = {
date: '2000-01-02T03:04:05.006Z',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'date',
display: 'Date',
sortable: true,
defaultsort: false,
type: 'date',
mandatory: false,
visible: true,
calculated: false,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['date']).buildTable([data])
expect(mapped).toEqual({
colCount: 1,
head: [
{
text: 'Date',
classes: null,
},
],
rowCount: 1,
rows: [
[
{
text: '02/01/00 03:04',
fieldName: 'date',
format: 'string',
classes: '',
},
],
],
})
})
it('Dates with null values mapped to an empty string', () => {
const data: Dict<string> = {
date: '',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'date',
display: 'Date',
sortable: true,
defaultsort: false,
type: 'date',
mandatory: false,
visible: true,
calculated: false,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['date']).buildTable([data])
expect(mapped).toEqual({
colCount: 1,
head: [
{
text: 'Date',
classes: null,
},
],
rowCount: 1,
rows: [
[
{
text: '',
fieldName: 'date',
format: 'string',
classes: '',
},
],
],
})
})
it('Dates with values greater than 10 mapped without leading 0', () => {
const data: Dict<string> = {
date: '2010-11-12T13:14:15.016Z',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'date',
display: 'Date',
sortable: true,
defaultsort: false,
type: 'date',
mandatory: false,
visible: true,
calculated: false,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['date']).buildTable([data])
expect(mapped.rows).toEqual([
[
{
text: '12/11/10 13:14',
fieldName: 'date',
format: 'string',
classes: '',
},
],
])
})
it('Numbers mapped correctly', () => {
const data: Dict<string> = {
number: '1234.05',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'number',
display: 'Number',
sortable: true,
defaultsort: false,
type: 'long',
mandatory: false,
visible: true,
calculated: false,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['number']).buildTable([data])
expect(mapped.rows).toEqual([
[
{
text: '1234.05',
fieldName: 'number',
format: 'numeric',
classes: '',
},
],
])
})
it('Calculated dates mapped correctly', () => {
const data: Dict<string> = {
date: '12/11/10',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'date',
display: 'Date',
sortable: true,
defaultsort: false,
type: 'date',
mandatory: false,
visible: true,
calculated: true,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['date']).buildTable([data])
expect(mapped.rows).toEqual([
[
{
text: '12/11/10',
fieldName: 'date',
format: 'string',
classes: '',
},
],
])
})
it('Strings mapped correctly', () => {
const data: Dict<string> = {
string: '1234.05',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'string',
display: 'String',
sortable: true,
defaultsort: false,
type: 'string',
mandatory: false,
visible: true,
calculated: false,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['string']).buildTable([data])
expect(mapped.rows).toEqual([
[
{
text: '1234.05',
fieldName: 'string',
format: 'string',
classes: '',
},
],
])
})
it('Strings with word wrapping configured are mapped correctly', () => {
const data: Dict<string> = {
string: '1234.05',
}
const field: components['schemas']['FieldDefinition'] = {
name: 'string',
display: 'String',
sortable: true,
defaultsort: false,
type: 'string',
wordWrap: 'none',
mandatory: false,
visible: true,
calculated: false,
}
const mapped = new DataTableBuilder([field]).withNoHeaderOptions(['string']).buildTable([data])
expect(mapped.rows).toEqual([
[
{
text: '1234.05',
fieldName: 'string',
format: 'string',
classes: 'data-table-cell-wrap-none',
},
],
])
})
})
describe('mapHeader', () => {
const defaultQueryParams = {
columns: 'date',
}
const filtersPrefix = 'f.'
const reqArgs = {
fields: defaultSpec.fields,
template: defaultSpec.template as Template,
queryParams: defaultQueryParams,
definitionsPath: 'one',
filtersPrefix,
}
const defaultListRequest: ReportQuery = new ReportQuery(reqArgs)
it('Unsortable field', () => {
const field = {
...defaultField,
sortable: false,
}
const mapped = new DataTableBuilder([field]).withHeaderSortOptions(defaultListRequest).buildTable([])
expect(mapped.head).toEqual([
{
text: 'Date',
classes: null,
},
])
})
it('Sortable unsorted field', () => {
const mapped = new DataTableBuilder([defaultField]).withHeaderSortOptions(defaultListRequest).buildTable([])
expect(mapped).toEqual({
colCount: 1,
head: [
{
html:
'<a ' +
'data-column="date" ' +
'class="data-table-header-button data-table-header-button-sort-ascending" ' +
'href="?selectedPage=1&pageSize=20&sortColumn=date&sortedAsc=false&columns=date&dataProductDefinitionsPath=one">' +
'Date' +
'</a>',
classes: null,
},
],
rowCount: 0,
rows: [],
})
})
it('Sortable field sorted ascending', () => {
const reportQuery: ReportQuery = new ReportQuery({
fields: defaultSpec.fields,
template: defaultSpec.template as Template,
queryParams: {
...defaultQueryParams,
sortColumn: 'date',
},
definitionsPath: defaultField.name,
filtersPrefix,
})
const mapped = new DataTableBuilder([defaultField]).withHeaderSortOptions(reportQuery).buildTable([])
expect(mapped).toEqual({
colCount: 1,
head: [
{
html:
'<a ' +
'data-column="date" ' +
'class="data-table-header-button data-table-header-button-sort-ascending" ' +
'href="?selectedPage=1&pageSize=20&sortColumn=date&sortedAsc=false&columns=date&dataProductDefinitionsPath=date">' +
'Date' +
'</a>',
classes: null,
},
],
rowCount: 0,
rows: [],
})
})
it('Sortable field sorted descending', () => {
const reportQuery: ReportQuery = new ReportQuery({
fields: defaultSpec.fields,
template: defaultSpec.template as Template,
queryParams: {
...defaultQueryParams,
sortColumn: 'date',
sortedAsc: 'false',
},
definitionsPath: defaultField.name,
filtersPrefix,
})
const mapped = new DataTableBuilder([defaultField]).withHeaderSortOptions(reportQuery).buildTable([])
expect(mapped).toEqual({
colCount: 1,
head: [
{
html:
'<a ' +
'data-column="date" ' +
'class="data-table-header-button data-table-header-button-sort-descending" ' +
'href="?selectedPage=1&pageSize=20&sortColumn=date&sortedAsc=true&columns=date&dataProductDefinitionsPath=date">' +
'Date' +
'</a>',
classes: null,
},
],
rowCount: 0,
rows: [],
})
})
})
describe('withSummary', () => {
const field: components['schemas']['FieldDefinition'] = {
name: 'mainField',
display: 'Main Field',
sortable: true,
defaultsort: false,
type: 'string',
mandatory: false,
visible: true,
calculated: false,
}
const headerSummary: Dict<Array<AsyncSummary>> = {
'table-header': [
{
id: 'test-header-summary',
template: 'table-header',
fields: [],
data: [
{
mainField: 'Header',
},
],
},
],
}
const footerSummary: Dict<Array<AsyncSummary>> = {
'table-footer': [
{
id: 'test-footer-summary',
template: 'table-header',
fields: [],
data: [
{
mainField: 'Footer',
},
],
},
],
}
it('Valid header summary', () => {
const mapped = new DataTableBuilder([field])
.withNoHeaderOptions([field.name])
.withSummaries(headerSummary)
.buildTable([{ mainField: 'Body' }])
expect(mapped.rows.length).toEqual(2)
expect(mapped.rows[0][0]).toEqual({
text: 'Header',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-header',
})
expect(mapped.rows[1][0]).toEqual({
text: 'Body',
fieldName: 'mainField',
format: 'string',
classes: '',
})
})
it('Valid footer summary', () => {
const mapped = new DataTableBuilder([field])
.withNoHeaderOptions([field.name])
.withSummaries(footerSummary)
.buildTable([{ mainField: 'Body' }])
expect(mapped.rows.length).toEqual(2)
expect(mapped.rows[0][0]).toEqual({
text: 'Body',
fieldName: 'mainField',
format: 'string',
classes: '',
})
expect(mapped.rows[1][0]).toEqual({
text: 'Footer',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-footer',
})
})
it('Valid header and footer summary', () => {
const mapped = new DataTableBuilder([field])
.withNoHeaderOptions([field.name])
.withSummaries({
...headerSummary,
...footerSummary,
})
.buildTable([{ mainField: 'Body' }])
expect(mapped.rows.length).toEqual(3)
expect(mapped.rows[0][0]).toEqual({
text: 'Header',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-header',
})
expect(mapped.rows[1][0]).toEqual({
text: 'Body',
fieldName: 'mainField',
format: 'string',
classes: '',
})
expect(mapped.rows[2][0]).toEqual({
text: 'Footer',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-footer',
})
})
it('Multiple valid header and footer summaries', () => {
const summaries: Dict<Array<AsyncSummary>> = {
'table-header': [
{
id: 'test-header-summary-1',
template: 'table-header',
fields: [],
data: [
{
mainField: 'Header 1',
},
],
},
{
id: 'test-header-summary-2',
template: 'table-header',
fields: [],
data: [
{
mainField: 'Header 2',
},
],
},
],
'table-footer': [
{
id: 'test-footer-summary-1',
template: 'table-header',
fields: [],
data: [
{
mainField: 'Footer 1',
},
],
},
{
id: 'test-footer-summary-2',
template: 'table-header',
fields: [],
data: [
{
mainField: 'Footer 2',
},
],
},
],
}
const mapped = new DataTableBuilder([field])
.withNoHeaderOptions([field.name])
.withSummaries(summaries)
.buildTable([{ mainField: 'Body' }])
expect(mapped.rows.length).toEqual(5)
expect(mapped.rows[0][0]).toEqual({
text: 'Header 1',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-header',
})
expect(mapped.rows[1][0]).toEqual({
text: 'Header 2',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-header',
})
expect(mapped.rows[2][0]).toEqual({
text: 'Body',
fieldName: 'mainField',
format: 'string',
classes: '',
})
expect(mapped.rows[3][0]).toEqual({
text: 'Footer 1',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-footer',
})
expect(mapped.rows[4][0]).toEqual({
text: 'Footer 2',
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-footer',
})
})
it('Invalid header summary', () => {
const invalidHeaderSummary: Dict<Array<AsyncSummary>> = {
'table-header': [
{
id: 'test-header-summary',
template: 'table-header',
fields: [],
data: [
{
invalidField: 'Header',
},
],
},
],
}
const mapped = new DataTableBuilder([field])
.withNoHeaderOptions([field.name])
.withSummaries(invalidHeaderSummary)
.buildTable([{ mainField: 'Body' }])
expect(mapped.rows.length).toEqual(2)
expect(mapped.rows[0][0]).toEqual({
fieldName: 'mainField',
format: 'string',
classes: 'dpr-report-summary-cell dpr-report-summary-cell-table-header',
})
expect(mapped.rows[1][0]).toEqual({
text: 'Body',
fieldName: 'mainField',
format: 'string',
classes: '',
})
})
})