Skip to content

Commit

Permalink
fix: various bugs in the report builder
Browse files Browse the repository at this point in the history
- adding data to a report didn't properly override existing data
- the report builders are much more permissive in what they accept
- add unit tests for the report builder (other builders TBD)
- fix "Unexpected Error: this.json.data.images.forEach is not a function"

Closes #53
  • Loading branch information
rdeltour committed Oct 5, 2017
1 parent 564f695 commit 4db2bd2
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 9 deletions.
28 changes: 19 additions & 9 deletions src/report/report-builders.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function calculateResult(assertions) {
// add an assertion and recalc the top-level result
function withAssertions(obj, assertions) {
if (!('assertions' in obj)) obj.assertions = [];
obj.assertions.push(assertions);
obj.assertions = obj.assertions.concat(assertions);
obj['earl:result'] = calculateResult(obj.assertions);
return obj;
}
Expand Down Expand Up @@ -90,8 +90,8 @@ class ReportBuilder {
this._json = {
'@type': 'earl:report',
'@context': 'http://ace.daisy.org/ns/ace-report._jsonld',
'dct:title': title,
'dct:description': description,
'dct:title': (title == null) ? '' : title.toString(),
'dct:description': (title == null) ? '' : description.toString(),
'dct:date': new Date().toLocaleString(),
'earl:assertedBy': ACE_DESCRIPTION,
outlines: {},
Expand All @@ -103,37 +103,47 @@ class ReportBuilder {
return this._json;
}
withA11yMeta(metadata) {
if (!metadata) return this;
this._json['a11y-metadata'] = metadata;
return this;
}
withAssertions(assertions) {
if (!assertions) return this;
withAssertions(this._json, assertions);
return this;
}
withData(data) {
if (!data) return this;
Object.getOwnPropertyNames(data).forEach((key) => {
this._json.data[key] = (Array.isArray(this._json.data[key]))
? this._json.data[key].push(data[key])
: data[key];
if (Array.isArray(this._json.data[key])) {
this._json.data[key] = this._json.data[key].concat(data[key]);
} else {
this._json.data[key] = data[key];
}
});
return this;
}
withEPUBOutline(outline) {
if (!outline) return this;
this._json.outlines.toc = outline;
return this;
}
withHeadingsOutline(outline) {
if (!outline) return this;
this._json.outlines.headings = outline;
return this;
}
withHTMLOutline(outline) {
if (!outline) return this;
this._json.outlines.html = outline;
return this;
}
withProperties(properties) {
if (!properties) return this;
Object.getOwnPropertyNames(properties).forEach((key) => {
this._json.properties[key] = (key in properties)
? this._json.properties[key] || properties[key]
: properties[key];
this._json.properties[key] = (key in this._json.properties)
? this._json.properties[key] || Boolean(properties[key])
: Boolean(properties[key]);
});
return this;
}
Expand Down
192 changes: 192 additions & 0 deletions src/report/report-builders.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
'use strict';

const builders = require('./report-builders');
const pkg = require('../../package');

describe('report builder', () => {
let report;

beforeEach(() => {
report = new builders.ReportBuilder();
});

describe('creating a new report', () => {
test('new report is well formed', () => {
expect(report).toBeDefined();
expect(report.build()).toBeDefined();
expect(report.build()).toMatchObject({
'@type': 'earl:report',
'@context': 'http://ace.daisy.org/ns/ace-report.jsonld',
'dct:title': 'Ace Report',
'dct:description': 'Report on automated accessibility checks for EPUB',
'earl:assertedBy': {
'@type': 'earl:software',
'doap:name': 'DAISY Ace',
'doap:description': 'DAISY Accessibility Checker for EPUB',
'doap:homepage': 'http://ace.daisy.org',
'doap:created': '2017-07-01',
'doap:release': { 'doap:revision': pkg.version },
},
});
expect(report.build().data).toBeDefined();
expect(report.build().outlines).toBeDefined();
expect(report.build().properties).toBeDefined();
expect(report.build().assertions).toBeUndefined();
});
test('new report args are used', () => {
report = new builders.ReportBuilder('Title', 'Desc');
expect(report).toBeDefined();
expect(report.build()).toBeDefined();
expect(report.build()).toMatchObject({
'dct:title': 'Title',
'dct:description': 'Desc',
});
});
test('new report undefined args are ignored', () => {
report = new builders.ReportBuilder(undefined, undefined);
expect(report).toBeDefined();
expect(report.build()).toBeDefined();
expect(report.build()).toMatchObject({
'dct:title': 'Ace Report',
'dct:description': 'Report on automated accessibility checks for EPUB',
});
});
test('new report null args contains empty string values', () => {
report = new builders.ReportBuilder(null, null);
expect(report).toBeDefined();
expect(report.build()).toBeDefined();
expect(report.build()).toMatchObject({
'dct:title': '',
'dct:description': '',
});
});
test('new report with object args contains toString values', () => {
report = new builders.ReportBuilder({}, {});
expect(report).toBeDefined();
expect(report.build()).toBeDefined();
expect(report.build()).toMatchObject({
'dct:title': '[object Object]',
'dct:description': '[object Object]',
});
});
});
describe('adding assertions', () => {
let assertions;
test('adding null assertion is ignored', () => {
expect(report.withAssertions(null)).toBeDefined();
expect(report.build().assertions).toBeUndefined();
});
test('adding undefined assertion is ignored', () => {
expect(report.withAssertions(undefined)).toBeDefined();
expect(report.build().assertions).toBeUndefined();
});
test('adding single assertion to empty report creates a new array', () => {
expect(report.withAssertions({ foo: 'foo' })).toBeDefined();
assertions = report.build().assertions;
expect(assertions).toBeDefined();
expect(Array.isArray(assertions)).toBe(true);
expect(assertions.length).toBe(1);
expect(assertions[0]).toEqual({ foo: 'foo' });
});
test('adding single assertion adds to existing assertions', () => {
expect(report.withAssertions({ foo: 'foo' })).toBeDefined();
assertions = report.build().assertions;
expect(assertions).toBeDefined();
expect(Array.isArray(assertions)).toBe(true);
expect(assertions.length).toBe(1);
expect(assertions[0]).toEqual({ foo: 'foo' });
});
test('adding assertions array to empty report copies it to the report', () => {
expect(report.withAssertions([
{ foo: 'foo' }, { foo: 'foo' },
])).toBeDefined();
assertions = report.build().assertions;
expect(assertions).toBeDefined();
expect(Array.isArray(assertions)).toBe(true);
expect(assertions.length).toBe(2);
expect(assertions[0]).toEqual({ foo: 'foo' });
});
test('adding assertions array concatenates to existing array', () => {
expect(report.withAssertions({ bar: 'bar' })).toBeDefined();
expect(report.withAssertions([
{ foo: 'foo' }, { foo: 'foo' },
])).toBeDefined();
assertions = report.build().assertions;
expect(assertions).toBeDefined();
expect(Array.isArray(assertions)).toBe(true);
expect(assertions.length).toBe(3);
expect(assertions[0]).toEqual({ bar: 'bar' });
expect(assertions[1]).toEqual({ foo: 'foo' });
});
});
describe('adding data', () => {
let data;
beforeEach(() => {
data = report.build().data;
});
test('adding null data` is ignored', () => {
expect(report.withData(null)).toBeDefined();
expect(data).toEqual({});
});
test('adding undefined data is ignored', () => {
expect(report.withData(undefined)).toBeDefined();
expect(data).toEqual({});
});
test('adding data to new report populates the data section', () => {
expect(report.withData({ foo: 'foo' })).toBeDefined();
expect(data).toEqual({ foo: 'foo' });
});
test('adding data is merged in existing data', () => {
expect(report.withData({ foo: 'foo' })).toBeDefined();
expect(report.withData({ bar: 'bar' })).toBeDefined();
expect(data).toEqual({ foo: 'foo', bar: 'bar' });
});
test('adding data overrides existing scalar data', () => {
expect(report.withData({ foo: 'foo' })).toBeDefined();
expect(report.withData({ foo: 'bar' })).toBeDefined();
expect(data).toEqual({ foo: 'bar' });
});
test('adding data adds to existing array data', () => {
expect(report.withData({ foo: ['foo'] })).toBeDefined();
expect(report.withData({ foo: ['bar'] })).toBeDefined();
expect(data).toEqual({ foo: ['foo', 'bar'] });
});
});
describe('adding properties', () => {
let properties;
beforeEach(() => {
properties = report.build().properties;
});
test('adding null properties` is ignored', () => {
expect(report.withProperties(null)).toBeDefined();
expect(properties).toEqual({});
});
test('adding undefined properties is ignored', () => {
expect(report.withProperties(undefined)).toBeDefined();
expect(properties).toEqual({});
});
test('adding properties to new report populates the properties section', () => {
expect(report.withProperties({ foo: true })).toBeDefined();
expect(properties).toEqual({ foo: true });
});
test('adding properties augments existing properties', () => {
expect(report.withProperties({ foo: true })).toBeDefined();
expect(report.withProperties({ bar: true })).toBeDefined();
expect(properties).toEqual({ foo: true, bar: true });
});
test('adding properties keeps existing true properties', () => {
expect(report.withProperties({ foo: true })).toBeDefined();
expect(report.withProperties({ foo: false })).toBeDefined();
expect(properties).toEqual({ foo: true });
});
test('adding properties booleanizes values', () => {
expect(report.withProperties({ foo: 'hello', bar: null })).toBeDefined();
expect(properties).toEqual({ foo: true, bar: false });
});
test('adding properties booleanizes values when overrinding too', () => {
expect(report.withProperties({ foo: false })).toBeDefined();
expect(report.withProperties({ foo: [] })).toBeDefined();
expect(properties).toEqual({ foo: true });
});
});
});
5 changes: 5 additions & 0 deletions tests/__tests__/parsing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@ test('issue #49: multiple \'dc:title\' elements', async () => {
const report = await ace('../data/issue49');
expect(report['earl:result']['earl:outcome']).toEqual('pass');
});

test.only('issue #53: XXX', async () => {
const report = await ace('../data/issue53');
expect(report['earl:result']['earl:outcome']).toEqual('pass');
});
10 changes: 10 additions & 0 deletions tests/data/issue53/EPUB/content_001.xhtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en">
<head>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
<img src="image_001.jpg" alt="dummy"/>
</body>
</html>
10 changes: 10 additions & 0 deletions tests/data/issue53/EPUB/content_002.xhtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en">
<head>
<title>Minimal EPUB</title>
</head>
<body>
<h1>Loomings</h1>
<p>Call me Ishmael.</p>
<img src="image_001.jpg" alt="dummy"/>
</body>
</html>
1 change: 1 addition & 0 deletions tests/data/issue53/EPUB/image_001.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions tests/data/issue53/EPUB/nav.xhtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops" xml:lang="en">
<head>
<title>Minimal Nav</title>
</head>
<body>
<nav epub:type="toc">
<ol>
<li><a href="content_001.xhtml">content 001</a></li>
</ol>
</nav>
</body>
</html>
27 changes: 27 additions & 0 deletions tests/data/issue53/EPUB/package.opf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="en" unique-identifier="uid">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:title id="title">Minimal EPUB 3.0</dc:title>
<dc:language>en</dc:language>
<dc:identifier id="uid">NOID</dc:identifier>
<meta property="dcterms:modified">2017-01-01T00:00:01Z</meta>
<meta property="dcterms:modified">2017-01-01T00:00:01Z</meta>
<meta property="schema:accessibilityFeature">structuralNavigation</meta>
<meta property="schema:accessibilitySummary">everything OK!</meta>
<meta property="schema:accessibilityHazard">noFlashingHazard</meta>
<meta property="schema:accessibilityHazard">noSoundHazard</meta>
<meta property="schema:accessibilityHazard">noMotionSimulationHazard</meta>
<meta property="schema:accessMode">textual</meta>
<meta property="schema:accessModeSufficient">textual</meta>
</metadata>
<manifest>
<item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="content_001" href="content_001.xhtml" media-type="application/xhtml+xml"/>
<item id="content_002" href="content_002.xhtml" media-type="application/xhtml+xml"/>
<item id="image_001" href="image_001.jpg" media-type="image/jpeg"/>
</manifest>
<spine>
<itemref idref="content_001" />
<itemref idref="content_002" />
</spine>
</package>
6 changes: 6 additions & 0 deletions tests/data/issue53/META-INF/container.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
1 change: 1 addition & 0 deletions tests/data/issue53/mimetype
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
application/epub+zip

0 comments on commit 4db2bd2

Please sign in to comment.