Comparing version 0.0.1 to 0.0.2
@@ -1,4 +0,5 @@ | ||
module.exports = {}; | ||
const { TestEngine, readTestUnits } = require('./src/lib'); | ||
module.exports = { TestEngine, readTestUnits }; | ||
module.exports = Object.assign({}, module.exports, require('./src/jest')); | ||
module.exports = Object.assign({}, module.exports, require('./src/results')); | ||
module.exports.setup = require('./setup') | ||
module.exports.setup = require('./setup'); |
{ | ||
"name": "jest-csl", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"main": "index.js", | ||
@@ -8,3 +8,9 @@ "repository": "https://github.com/cormacrelf/jest-csl", | ||
"author": "Cormac Relf <web@cormacrelf.net>", | ||
"tags": ["csl", "csl-m", "citation-style-language", "testing", "jest"], | ||
"tags": [ | ||
"csl", | ||
"csl-m", | ||
"citation-style-language", | ||
"testing", | ||
"jest" | ||
], | ||
"bin": { | ||
@@ -30,2 +36,3 @@ "jest-csl": "./src/cli.js" | ||
"osenv": "^0.1.5", | ||
"slugify": "^1.3.3", | ||
"uuid": "^3.3.2", | ||
@@ -32,0 +39,0 @@ "xdg-basedir": "^3.0.0" |
# `jest-csl` | ||
![npm](https://img.shields.io/npm/v/jest-csl.svg) | ||
![build](https://img.shields.io/travis/com/cormacrelf/jest-csl.svg) | ||
This is a library to make testing [Citation Style Language][csl] definitions | ||
@@ -101,6 +104,4 @@ easier using [`Jest`][jest]. It includes: | ||
if (typeof jest !== 'undefined') { | ||
const { jestCSL } = require('jest-csl'); | ||
jestCSL(module.exports); | ||
} | ||
const { jestCSL } = require('jest-csl'); | ||
jestCSL(module.exports); | ||
``` | ||
@@ -162,3 +163,3 @@ | ||
for more complex combined citations, use 'sequence' to test the | ||
For more complex combined citations, use 'sequence' to test the | ||
in-texts/footnotes generated for a sequence of clusters of cites. | ||
@@ -174,7 +175,5 @@ | ||
sequence: | ||
- cluster: | ||
- { id: "doe2001", locator: "5", label: "page" } | ||
- { id: "doe2001", locator: "5", label: "page", prefix: "see also", suffix: "etc" } | ||
- cluster: | ||
- { id: "doe2001", locator: "5", label: "page" } | ||
- [ { id: "doe2001", locator: "5", label: "page" }, | ||
{ id: "doe2001", locator: "5", label: "page", prefix: "see also", suffix: "etc" } ] | ||
- [{ id: "doe2001", locator: "5", label: "page" }] | ||
expect: | ||
@@ -185,2 +184,21 @@ - Doe, <i>Miscellaneous Writings</i>, 2001, p. 5; see also <i>ibid</i> etc. | ||
To test the abbreviations found in the Abbreviation Filter: | ||
```yaml | ||
- describe: "a" | ||
tests: | ||
- it: "should x" | ||
... | ||
abbreviations: | ||
- jurisdiction: default | ||
hereinafter: | ||
doe2001: Misc | ||
container-title: | ||
American Something Journal: ASJ | ||
``` | ||
See this command's output for a list of allowed categories. | ||
node -e 'var c=require('citeproc');console.log(Object.keys(new c.AbbreviationSegments()))' | ||
### Combining test suites | ||
@@ -230,2 +248,17 @@ | ||
### Further splitting of test suites | ||
For convenience, you can split a large test suite into multiple files, and | ||
combine them all with a glob. Use a level of directories or a naming scheme to | ||
separate groups that should be strictly before or after one another. | ||
```javascript | ||
{ | ||
// ... | ||
suites: ["./test/core/*.yaml", "./test/extended/*.yaml"] | ||
} | ||
``` | ||
The same works for `jurisdictionDirs` and `libraries`. | ||
#### Skipping or isolating tests | ||
@@ -247,17 +280,2 @@ | ||
### Further splitting of test suites | ||
For convenience, you can split a large test suite into multiple files, and | ||
combine them all with a glob. Use a level of directories or a naming scheme to | ||
separate groups that should be strictly before or after one another. | ||
```javascript | ||
{ | ||
// ... | ||
suites: ["./test/core/*.yaml", "./test/extended/*.yaml"] | ||
} | ||
``` | ||
The same works for `jurisdictionDirs` and `libraries`. | ||
### Running your tests | ||
@@ -264,0 +282,0 @@ |
@@ -1,2 +0,2 @@ | ||
const { getProcessor, produceSingle, produceSequence, readInputFiles } = require('./lib'); | ||
const { TestEngine, readTestUnits, normalizeItalics } = require('./lib'); | ||
@@ -8,2 +8,3 @@ // these functions are to be run from within the jest context | ||
// csl: string path to a CSL file, | ||
// jurisdictionDirs: array of string paths to jurisdiction directories | ||
// libraries: array of string paths to exported CSL-JSON libraries, | ||
@@ -13,4 +14,7 @@ // suites: array of string paths to YAML test suites | ||
function jestCSL(args) { | ||
let { style, library, units, jurisdictionDirs } = readInputFiles(args); | ||
let engine = getProcessor(style, library, jurisdictionDirs); | ||
if (typeof jest === 'undefined') { | ||
return; | ||
} | ||
let units = readTestUnits(args.suites); | ||
let engine = new TestEngine(args); | ||
@@ -24,3 +28,3 @@ units.forEach(unit => { | ||
} | ||
// mode: skip | only | ||
// mode: skip | only (not doc) | ||
if (test.mode && it[test.mode]) { | ||
@@ -43,7 +47,7 @@ it[test.mode](test.it, run); | ||
if (test.single && test.expect) { | ||
let out = produceSingle(engine, test.single); | ||
expect(out).toBe(test.expect); | ||
let out = engine.produceSingle(test.single, test.format, test.abbreviations); | ||
expect(normalizeItalics(out)).toBe(normalizeItalics(test.expect)); | ||
} else if (test.sequence && test.expect) { | ||
let out = produceSequence(engine, test.sequence); | ||
expect(out).toMatchObject(test.expect); | ||
let out = engine.produceSequence(test.sequence, test.format, test.abbreviations); | ||
expect(out.map(normalizeItalics)).toMatchObject(test.expect.map(normalizeItalics)); | ||
} | ||
@@ -50,0 +54,0 @@ } |
175
src/lib.js
@@ -18,2 +18,4 @@ Array.prototype.flatMap = function(lambda) { | ||
const { normalizeKey, lookupKey, makeGetAbbreviation } = require('./getAbbreviation'); | ||
function cloneOrPull(url, repoDir, branch, shouldPull) { | ||
@@ -58,10 +60,3 @@ let repo; | ||
// function _fallback(repo, file) { | ||
// var xhr = new XMLHttpRequest(); | ||
// xhr.open('GET', `https://raw.githubusercontent.com/${repo}/master/${file}`, false); | ||
// xhr.send(null); | ||
// return xhr.status === 200 && xhr.responseText; | ||
// } | ||
const citeprocSys = (citations, jurisdictionDirs) => ({ | ||
const citeprocSys = (citations, jurisdictionDirs, myAbbreviations, gotAbbreviationCache) => ({ | ||
retrieveLocale: function (lang) { | ||
@@ -74,7 +69,9 @@ // console.log('language:', lang); | ||
retrieveItem: function(id){ | ||
retrieveItem(id){ | ||
return citations[id]; | ||
}, | ||
retrieveStyleModule: function(jurisdiction, preference) { | ||
getAbbreviation: makeGetAbbreviation(myAbbreviations, gotAbbreviationCache), | ||
retrieveStyleModule(jurisdiction, preference) { | ||
jurisdiction = jurisdiction.replace(/\:/g, "+"); | ||
@@ -110,3 +107,3 @@ var id = preference | ||
// @param library Array of CSL-JSON item objects. | ||
function _readLibrary(library) { | ||
function readLibrary(library) { | ||
let citations = {}; | ||
@@ -123,17 +120,2 @@ let itemIDs = new Set(); | ||
function getProcessor(styleStr, library, jurisdictionDirs = []) { | ||
let [citations, itemIDs] = _readLibrary(library); | ||
var proc = new CSL.Engine(citeprocSys(citations, jurisdictionDirs), styleStr); | ||
proc.updateItems(itemIDs); | ||
return proc; | ||
}; | ||
function produceSingle(engine, single) { | ||
// engine.makeCitationCluster([single], 'html') is broken, but it's meant to be faster. | ||
// (it tries to access 'disambig of undefined'... not helpful) | ||
// (node_modules/citeproc/citeproc_commonjs.js +10874) | ||
let out = produceSequence(engine, [{ cluster: [single]}]) | ||
return out[0]; | ||
} | ||
function _atIndex(c, i) { | ||
@@ -143,12 +125,6 @@ return { | ||
properties: { noteIndex: i }, | ||
citationItems: c.cluster | ||
citationItems: c | ||
} | ||
} | ||
function produceSequence(engine, clusters) { | ||
let citations = clusters.map((c, i) => _atIndex(c, i+1)) | ||
let out = engine.rebuildProcessorState(citations, 'html') | ||
return out.map(o => o[2]); | ||
} | ||
function _addTestsToMap(m, u) { | ||
@@ -213,3 +189,39 @@ for (let t of u.tests) { | ||
function readInputFiles(args) { | ||
function insertMissingPageLabels(test) { | ||
let immut = (single) => { | ||
return (single.locator && !single.label) | ||
? { ... single, label: single.label || 'page' } | ||
: single; | ||
}; | ||
if (test.single && test.single.locator && !test.single.label) { | ||
return { ...test, single: immut(test.single) }; | ||
} | ||
if (test.sequence) { | ||
return { | ||
...test, | ||
sequence: test.sequence.map(s => s.map(immut)) | ||
} | ||
} | ||
return test; | ||
} | ||
function stripWhitespace(test) { | ||
let expect = ''; | ||
if (Array.isArray(test.expect)) { | ||
expect = test.expect.map(e => e.trim()); | ||
} else { | ||
expect = test.expect && test.expect.trim(); | ||
} | ||
return { | ||
...test, | ||
expect: test.expect && expect | ||
} | ||
} | ||
function normalizeItalics(testString) { | ||
return testString.replace(new RegExp("</i>(\\s*)<i>"), "$1") | ||
} | ||
function readConfigFiles(args) { | ||
let style = fs.readFileSync(args.csl, 'utf8'); | ||
@@ -237,5 +249,13 @@ if (!style) { | ||
} | ||
let jurisdictionDirs = expandGlobs(args.jurisdictionDirs); | ||
let out = { style, library, jurisdictionDirs }; | ||
return out; | ||
} | ||
function readTestUnits(suites) { | ||
let units = []; | ||
let suites = expandGlobs(args.suites); | ||
for (let suite of suites) { | ||
let _suites = expandGlobs(suites); | ||
for (let suite of _suites) { | ||
let unitsStr = fs.readFileSync(suite, 'utf8'); | ||
@@ -245,7 +265,76 @@ let nxtUnits = yaml.safeLoad(unitsStr); | ||
} | ||
units = units.map(unit => { | ||
return { | ||
...unit, | ||
tests: unit.tests.map(stripWhitespace).map(insertMissingPageLabels) | ||
} | ||
}); | ||
return units; | ||
} | ||
let jurisdictionDirs = expandGlobs(args.jurisdictionDirs); | ||
class TestEngine { | ||
constructor(args) { | ||
let { style, library, jurisdictionDirs } = readConfigFiles(args); | ||
let [citations, itemIDs] = readLibrary(library); | ||
let out = { style, library, units, jurisdictionDirs }; | ||
return out; | ||
this.abbreviations = {}; | ||
this.sysAbbreviationCache = null; | ||
const sys = citeprocSys( | ||
citations, | ||
jurisdictionDirs, | ||
() => this.abbreviations, | ||
cache => { this.sysAbbreviationCache = cache; } | ||
); | ||
this.engine = new CSL.Engine(sys, style); | ||
this.engine.updateItems(itemIDs); | ||
} | ||
retrieveItem(item) { | ||
return this.engine.retrieveItem(item); | ||
} | ||
setAbbreviations(sets) { | ||
this.abbreviations = { | ||
default: new CSL.AbbreviationSegments() | ||
}; | ||
if (this.sysAbbreviationCache) { | ||
Object.keys(this.sysAbbreviationCache).forEach(k => delete this.sysAbbreviationCache[k]); | ||
this.sysAbbreviationCache['default'] = new CSL.AbbreviationSegments(); | ||
} | ||
if (!sets) return; | ||
sets.forEach(set => { | ||
let jurisdiction = set.jurisdiction || 'default'; | ||
let categories = Object.keys(new CSL.AbbreviationSegments()); | ||
categories.forEach(cat => { | ||
let kvs = set[cat] || {}; | ||
Object.entries(kvs).forEach(e => { | ||
this.addAbbreviation(jurisdiction, cat, e[0], e[1]); | ||
}) | ||
}); | ||
}) | ||
} | ||
produceSingle(single, format, abbreviations) { | ||
// engine.makeCitationCluster([single], 'html') is broken, but it's meant to be faster. | ||
// (it tries to access 'disambig of undefined'... not helpful) | ||
// (node_modules/citeproc/citeproc_commonjs.js +10874) | ||
let out = this.produceSequence([[single]], format || 'html', abbreviations) | ||
return out[0]; | ||
} | ||
produceSequence(clusters, format, abbreviations) { | ||
this.setAbbreviations(abbreviations); | ||
let citations = clusters.map((c, i) => _atIndex(c, i+1)) | ||
let out = this.engine.rebuildProcessorState(citations, format || 'html') | ||
return out.map(o => o[2]); | ||
} | ||
addAbbreviation(jurisdiction, category, key, value) { | ||
this.abbreviations[jurisdiction] = this.abbreviations[jurisdiction] || new CSL.AbbreviationSegments(); | ||
let k = lookupKey(normalizeKey(key)); | ||
this.abbreviations[jurisdiction][category][k] = value; | ||
// console.log('added:', key, '->', value); | ||
} | ||
} | ||
@@ -255,8 +344,8 @@ | ||
mergeUnits, | ||
getProcessor, | ||
produceSingle, | ||
produceSequence, | ||
ensureCachedRepos, | ||
readInputFiles, | ||
normalizeItalics, | ||
insertMissingPageLabels, | ||
TestEngine, | ||
readTestUnits, | ||
} | ||
@@ -1,2 +0,2 @@ | ||
const { getProcessor, produceSingle, produceSequence, readInputFiles } = require('./lib'); | ||
const { TestEngine, readTestUnits, normalizeItalics } = require('./lib'); | ||
@@ -14,4 +14,5 @@ // This generates a JS array of each of the test units, with each test | ||
function cslTestResults(args) { | ||
let { style, library, units, jurisdictionDirs } = readInputFiles(args); | ||
let engine = getProcessor(style, library, jurisdictionDirs); | ||
let units = readTestUnits(args.suites); | ||
let engine = new TestEngine(args); | ||
// console.log(engine.locale['en-GB'].terms.page); | ||
return { | ||
@@ -26,15 +27,24 @@ engine: engine, | ||
units.forEach((unit) => { | ||
let _tests = []; | ||
if (unit.tests) { | ||
unit.tests.forEach(test => { | ||
// TODO: handle skipped tests | ||
if (test.single && test.expect) { | ||
let res = produceSingle(engine, test.single); | ||
results.push({ ...test, result: res, passed: res === test.expect }); | ||
if (test.mode === 'skip') { | ||
// do nothing | ||
} else if (test.mode === 'doc') { | ||
_tests.push({ ...test, type: 'doc', passed: false }) | ||
} else if (!test.expect) { | ||
_tests.push({ ...test, type: 'stub', passed: false }) | ||
} else if (test.single && test.expect) { | ||
let res = engine.produceSingle(test.single, test.format, test.abbreviations); | ||
_tests.push({ ...test, type: 'single', result: res, passed: normalizeItalics(res) === normalizeItalics(test.expect) }); | ||
} else if (test.sequence && test.expect) { | ||
let res = engine.produceSequence(test.sequence, test.format, test.abbreviations); | ||
_tests.push({ ...test, type: 'sequence', result: res, passed: sequenceMatches(test.expect, res) }); | ||
} | ||
if (test.sequence && test.expect) { | ||
let res = produceSequence(engine, test.sequence); | ||
results.push({ ...test, result: res, passed: sequenceMatches(test.expect, res) }); | ||
} | ||
}) | ||
} | ||
let _u = { ...unit, tests: _tests }; | ||
results.push(_u); | ||
}); | ||
@@ -47,3 +57,3 @@ return results; | ||
for (let i = 0; i < expected.length; i++) { | ||
if (expected[i] !== actual[i]) return false; | ||
if (normalizeItalics(expected[i]) !== normalizeItalics(actual[i])) return false; | ||
} | ||
@@ -50,0 +60,0 @@ return true; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
29607
11
555
308
11
+ Addedslugify@^1.3.3
+ Addedslugify@1.6.6(transitive)