rdf-validate-datatype
Version:
Validate literal value of an RDF term based on its datatype.
413 lines (412 loc) • 19.3 kB
JavaScript
import assert from 'assert';
import $rdf from '@rdfjs/data-model';
import { csvw, xsd } from '@tpluscode/rdf-ns-builders';
import { validateTerm } from '../index.js';
describe('#validateTerm', () => {
it('returns true for terms without datatype', () => {
const term = $rdf.literal('test');
const isValid = validateTerm(term);
assert.strictEqual(isValid, true);
});
it('returns true for unkown datatype', () => {
const term = $rdf.literal('test%é*$_4', $rdf.namedNode('custom-datatype'));
const isValid = validateTerm(term);
assert.strictEqual(isValid, true);
});
it('throws on named nodes', () => {
const term = $rdf.namedNode('test');
assert.throws(() => validateTerm(term), Error);
});
it('throws on blank nodes', () => {
const term = $rdf.blankNode();
assert.throws(() => validateTerm(term), Error);
});
const testCases = [
['', xsd.anyAtomicType, true],
['test', xsd.anyAtomicType, true],
['', xsd.anySimpleType, true],
['test', xsd.anySimpleType, true],
['', xsd.string, true],
['test', xsd.string, true],
['', xsd.normalizedString, true],
['test', xsd.normalizedString, true],
['test\n', xsd.normalizedString, false],
['test\r', xsd.normalizedString, false],
['test\t', xsd.normalizedString, false],
['', xsd.token, true],
['test', xsd.token, true],
['test\n', xsd.token, false],
['test\r', xsd.token, false],
['test\t', xsd.token, false],
[' test', xsd.token, false],
['test ', xsd.token, false],
['test test', xsd.token, false],
['fr', xsd.language, true],
['de', xsd.language, true],
['en-US', xsd.language, true],
['foobar-Xs04', xsd.language, true],
['foobar-Xs04-48asd', xsd.language, true],
['', xsd.language, false],
['asdfasdfasdf-Xs04', xsd.language, false],
['&', xsd.language, false],
['fr+', xsd.language, false],
['thisisalongword', xsd.language, false],
['', xsd.anyURI, true],
['test', xsd.anyURI, true],
['example:test', xsd.anyURI, true],
['example.org:test', xsd.anyURI, true],
['example.org/test', xsd.anyURI, true],
['example.org/test#test', xsd.anyURI, true],
['http://example.org/test#test', xsd.anyURI, true],
['something://example.org/test#test', xsd.anyURI, true],
['\ufffe', xsd.anyURI, false],
['\uffff', xsd.anyURI, false],
['test\ufffetest', xsd.anyURI, false],
['test\ufffftest', xsd.anyURI, false],
['1', xsd.integer, true],
['-18', xsd.integer, true],
['+14', xsd.integer, true],
['389473984759384759384759387459384759834759384751231343123123', xsd.integer, true],
['-389473984759384759384759387459384759834759384751231343123123', xsd.integer, true],
['123x', xsd.integer, false, 'trailing string'],
['test', xsd.integer, false],
['1', xsd.nonNegativeInteger, true],
['0', xsd.nonNegativeInteger, true],
['-18', xsd.nonNegativeInteger, false],
['+14', xsd.nonNegativeInteger, true],
['389473984759384759384759387459384759834759384751231343123123', xsd.nonNegativeInteger, true],
['-389473984759384759384759387459384759834759384751231343123123', xsd.nonNegativeInteger, false],
['123x', xsd.nonNegativeInteger, false, 'trailing string'],
['test', xsd.nonNegativeInteger, false],
['1', xsd.positiveInteger, true],
['0', xsd.positiveInteger, false],
['-18', xsd.positiveInteger, false],
['+14', xsd.positiveInteger, true],
['389473984759384759384759387459384759834759384751231343123123', xsd.positiveInteger, true],
['-389473984759384759384759387459384759834759384751231343123123', xsd.positiveInteger, false],
['123x', xsd.positiveInteger, false, 'trailing string'],
['test', xsd.positiveInteger, false],
['1', xsd.nonPositiveInteger, false],
['0', xsd.nonPositiveInteger, true],
['-18', xsd.nonPositiveInteger, true],
['+14', xsd.nonPositiveInteger, false],
['389473984759384759384759387459384759834759384751231343123123', xsd.nonPositiveInteger, false],
['-389473984759384759384759387459384759834759384751231343123123', xsd.nonPositiveInteger, true],
['123x', xsd.nonPositiveInteger, false, 'trailing string'],
['test', xsd.nonPositiveInteger, false],
['1', xsd.negativeInteger, false],
['0', xsd.negativeInteger, false],
['-18', xsd.negativeInteger, true],
['+14', xsd.negativeInteger, false],
['389473984759384759384759387459384759834759384751231343123123', xsd.negativeInteger, false],
['-389473984759384759384759387459384759834759384751231343123123', xsd.negativeInteger, true],
['123x', xsd.negativeInteger, false, 'trailing string'],
['test', xsd.negativeInteger, false],
['1', xsd.int, true],
['-18', xsd.int, true],
['+14', xsd.int, true],
['123134312312', xsd.int, false, 'too large'],
['-2147483649', xsd.int, false, 'too small'],
['123x', xsd.int, false, 'trailing string'],
['test', xsd.int, false],
['1', xsd.unsignedInt, true],
['-18', xsd.unsignedInt, false],
['+14', xsd.unsignedInt, true],
['4294967299', xsd.unsignedInt, false, 'too large'],
['-4294967299', xsd.unsignedInt, false],
['123x', xsd.unsignedInt, false, 'trailing string'],
['test', xsd.unsignedInt, false],
['1', xsd.long, true],
['-18', xsd.long, true],
['+14', xsd.long, true],
['1231343123123', xsd.long, true],
['9223372036854775808', xsd.long, false, 'too large'],
['-9223372036854775810', xsd.long, false, 'too small'],
['123x', xsd.long, false, 'trailing string'],
['test', xsd.long, false],
['1', xsd.unsignedLong, true],
['-18', xsd.unsignedLong, false],
['+14', xsd.unsignedLong, true],
['1231343123123', xsd.unsignedLong, true],
['18446744073709551616', xsd.unsignedLong, false, 'too large'],
['-18446744073709551619', xsd.unsignedLong, false],
['123x', xsd.unsignedLong, false, 'trailing string'],
['test', xsd.unsignedLong, false],
['1', xsd.short, true],
['-18', xsd.short, true],
['+14', xsd.short, true],
['32790', xsd.short, false, 'too large'],
['-32770', xsd.short, false, 'too small'],
['123x', xsd.short, false, 'trailing string'],
['test', xsd.short, false],
['1', xsd.unsignedShort, true],
['-18', xsd.unsignedShort, false],
['+14', xsd.unsignedShort, true],
['65537', xsd.unsignedShort, false, 'too large'],
['-65537', xsd.unsignedShort, false],
['123x', xsd.unsignedShort, false, 'trailing string'],
['test', xsd.unsignedShort, false],
['1', xsd.byte, true],
['-18', xsd.byte, true],
['+14', xsd.byte, true],
['128', xsd.byte, false, 'too large'],
['-130', xsd.byte, false, 'too small'],
['12x', xsd.byte, false, 'trailing string'],
['test', xsd.byte, false],
['1', xsd.unsignedByte, true],
['-18', xsd.unsignedByte, false],
['+14', xsd.unsignedByte, true],
['257', xsd.unsignedByte, false, 'too large'],
['-257', xsd.unsignedByte, false],
['12x', xsd.unsignedByte, false, 'trailing string'],
['test', xsd.unsignedByte, false],
['true', xsd.boolean, true],
['false', xsd.boolean, true],
['test', xsd.boolean, false],
['0', xsd.decimal, true, 'zero'],
['0.4', xsd.decimal, true, 'decimal point'],
['244.14', xsd.decimal, true, 'with decimal digits'],
['244', xsd.decimal, true, 'without decimal digits'],
['-24.4', xsd.decimal, true, 'minus sign'],
['+24.4', xsd.decimal, true, 'plus sign'],
['test', xsd.decimal, false, 'non-numeric characters'],
['NaN', xsd.decimal, false, 'NaN'],
['.4', xsd.decimal, true, 'leading decimal point'],
['4.', xsd.decimal, true, 'trailing decimal point'],
['003.500', xsd.decimal, true, 'leading zeros'],
['-003.500', xsd.decimal, true, 'negative number with leading zeros'],
['+003.500', xsd.decimal, true, 'positive number with leading zeros'],
['3.0000', xsd.decimal, true, 'trailing zeros'],
['3,5', xsd.decimal, false, 'comma instead of decimal point'],
['24.4.4', xsd.decimal, false, 'two decimal points'],
['-1E4', xsd.float, true],
['1267.43233E12', xsd.float, true],
['12.78e-2', xsd.float, true],
['12', xsd.float, true],
['-0', xsd.float, true],
['0', xsd.float, true],
['INF', xsd.float, true],
['-INF', xsd.float, true],
['NaN', xsd.float, true],
['test', xsd.float, false],
['10e4.2', xsd.float, false],
['-1E4', xsd.double, true],
['1267.43233E12', xsd.double, true],
['12.78e-2', xsd.double, true],
['12', xsd.double, true],
['-0', xsd.double, true],
['0', xsd.double, true],
['INF', xsd.double, true],
['-INF', xsd.double, true],
['NaN', xsd.double, true],
['test', xsd.double, false],
['10e4.2', xsd.double, false],
['P1Y2M3DT10H30M', xsd.duration, true],
['-P120D', xsd.duration, true],
['P1347Y', xsd.duration, true],
['P1347M', xsd.duration, true],
['P1Y2MT2H', xsd.duration, true],
['P0Y1347M', xsd.duration, true],
['P0Y1347M0D', xsd.duration, true],
['-P1347M', xsd.duration, true],
['P120DT10H30M', xsd.duration, true],
['PT2H', xsd.duration, true],
['-PT2H30M', xsd.duration, true],
['P-1347M', xsd.duration, false],
['P1Y2MT', xsd.duration, false],
['test', xsd.duration, false],
['P', xsd.duration, false],
['P1Y2M3DT10H30M', xsd.dayTimeDuration, false],
['-P120D', xsd.dayTimeDuration, true],
['P1347Y', xsd.dayTimeDuration, false],
['P1347M', xsd.dayTimeDuration, false],
['P1Y2MT2H', xsd.dayTimeDuration, false],
['P0Y1347M', xsd.dayTimeDuration, false],
['P0Y1347M0D', xsd.dayTimeDuration, false],
['-P1347M', xsd.dayTimeDuration, false],
['P120DT10H30M', xsd.dayTimeDuration, true],
['PT2H', xsd.dayTimeDuration, true],
['-PT2H30M', xsd.dayTimeDuration, true],
['P-1347M', xsd.dayTimeDuration, false],
['P1Y2MT', xsd.dayTimeDuration, false],
['test', xsd.dayTimeDuration, false],
['P', xsd.dayTimeDuration, false],
['P1Y2M3DT10H30M', xsd.yearMonthDuration, false],
['-P120D', xsd.yearMonthDuration, false],
['P1347Y', xsd.yearMonthDuration, true],
['P1347M', xsd.yearMonthDuration, true],
['P1Y2MT2H', xsd.yearMonthDuration, false],
['P0Y1347M', xsd.yearMonthDuration, true],
['P0Y1347M0D', xsd.yearMonthDuration, false],
['-P1347M', xsd.yearMonthDuration, true],
['P120DT10H30M', xsd.yearMonthDuration, false],
['PT2H', xsd.yearMonthDuration, false],
['-PT2H30M', xsd.yearMonthDuration, false],
['P-1347M', xsd.yearMonthDuration, false],
['P1Y2MT', xsd.yearMonthDuration, false],
['test', xsd.yearMonthDuration, false],
['P', xsd.yearMonthDuration, false],
['2020-04-02', xsd.date, true],
['-2020-04-02', xsd.date, true],
['2020-04-02Z', xsd.date, true],
['2020-04-02+03:00', xsd.date, true],
['12004-04-02', xsd.date, true],
['-12004-04-02', xsd.date, true],
['0922-04-02', xsd.date, true],
['-0922-04-02', xsd.date, true],
['-922-04-02', xsd.date, false],
// ['2020-23-04', xsd.date, false, 'invalid month'],
// ['2020-11-31', xsd.date, false, 'invalid month day'],
['2020-04-02x', xsd.date, false],
['test', xsd.date, false],
['', xsd.date, false],
['2020-04-02T23:33:12.234Z', xsd.dateTime, true],
['2020-04-02T23:33:12.234+04:00', xsd.dateTime, true],
['2020-04-02T23:33:12+04:00', xsd.dateTime, true],
['2020-04-02T23:33:12', xsd.dateTime, true],
['2020-04-02T23:33:12x', xsd.dateTime, false],
// ['2020-24-02T23:33:12', xsd.dateTime, false, 'invalid month'],
// ['2020-04-32T23:33:12', xsd.dateTime, false, 'invalid month day'],
// ['2020-04-02T24:33:12', xsd.dateTime, false, 'invalid hour'],
// ['2020-04-02T20:83:12', xsd.dateTime, false, 'invalid minute'],
// ['2020-04-02T20:23:82', xsd.dateTime, false, 'invalid seconds'],
['12004-04-02T23:33:12.234Z', xsd.dateTime, true],
['-12004-04-02T23:33:12.234Z', xsd.dateTime, true],
['0922-04-02T23:33:12.234Z', xsd.dateTime, true],
['-0922-04-02T23:33:12.234Z', xsd.dateTime, true],
['-922-04-02T23:33:12.234Z', xsd.dateTime, false],
['2020-04-02T23:33', xsd.dateTime, false],
['test', xsd.dateTime, false],
['', xsd.dateTime, false],
['2020-04-02T23:33:12.234Z', xsd.dateTimeStamp, true],
['2020-04-02T23:33:12.234+04:00', xsd.dateTimeStamp, true],
['2020-04-02T23:33:12+04:00', xsd.dateTimeStamp, true],
['12004-04-02T23:33:12.234Z', xsd.dateTimeStamp, true],
['-12004-04-02T23:33:12.234Z', xsd.dateTimeStamp, true],
['0922-04-02T23:33:12.234Z', xsd.dateTimeStamp, true],
['-0922-04-02T23:33:12.234Z', xsd.dateTimeStamp, true],
['-922-04-02T23:33:12.234Z', xsd.dateTimeStamp, false],
['2020-04-02T23:33:12', xsd.dateTimeStamp, false],
['2020-04-02T23:33:12x', xsd.dateTimeStamp, false],
// ['2020-24-02T23:33:12Z', xsd.dateTimeStamp, false, 'invalid month'],
// ['2020-04-32T23:33:12Z', xsd.dateTimeStamp, false, 'invalid month day'],
// ['2020-04-02T24:33:12Z', xsd.dateTimeStamp, false, 'invalid hour'],
// ['2020-04-02T20:83:12Z', xsd.dateTimeStamp, false, 'invalid minute'],
// ['2020-04-02T20:23:82Z', xsd.dateTimeStamp, false, 'invalid seconds'],
['2020-04-02T23:33Z', xsd.dateTimeStamp, false],
['test', xsd.dateTimeStamp, false],
['', xsd.dateTimeStamp, false],
['23:33:12.234', xsd.time, true],
['03:43:12.234Z', xsd.time, true],
['23:33:12.134+04:00', xsd.time, true],
['17:33:12.23-01:00', xsd.time, true],
['13:20:00-05:00', xsd.time, true],
['23:33:12', xsd.time, true],
// ['27:33:12', xsd.time, false, 'invalid hour'],
// ['17:66:12', xsd.time, false, 'invalid minute'],
// ['17:06:92', xsd.time, false, 'invalid second'],
['23:33:12x', xsd.time, false],
['23:33', xsd.time, false],
['test', xsd.time, false],
['12', xsd.gDay, true],
['30Z', xsd.gDay, true],
['01+01:00', xsd.gDay, true],
['04-12:00', xsd.gDay, true],
['1', xsd.gDay, false],
// ['32', xsd.gDay, false, 'out of range'],
['-13', xsd.gDay, false],
['test', xsd.gDay, false],
['--12', xsd.gMonth, true],
['--01', xsd.gMonth, true],
['--03Z', xsd.gMonth, true],
['--01+01:00', xsd.gMonth, true],
['--04-12:00', xsd.gMonth, true],
['--1', xsd.gMonth, false],
['1', xsd.gMonth, false],
['12', xsd.gMonth, false],
['-12', xsd.gMonth, false],
['----12', xsd.gMonth, false],
['test', xsd.gMonth, false],
['04-02', xsd.gMonthDay, true],
['12-22', xsd.gMonthDay, true],
['12-22Z', xsd.gMonthDay, true],
['12-22+04:00', xsd.gMonthDay, true],
['12-22-04:00', xsd.gMonthDay, true],
['2020-12-22', xsd.gMonthDay, false],
['-12-22', xsd.gMonthDay, false],
['12-22X', xsd.gMonthDay, false],
['test', xsd.gMonthDay, false],
['2020', xsd.gYear, true],
['-2020', xsd.gYear, true],
['2020Z', xsd.gYear, true],
['2020+04:00', xsd.gYear, true],
['-2020-02:00', xsd.gYear, true],
['12004', xsd.gYear, true],
['-12004', xsd.gYear, true],
['0922', xsd.gYear, true],
['-0922', xsd.gYear, true],
['-922', xsd.gYear, false],
['2020-12-01', xsd.gYear, false],
['test', xsd.gYear, false],
['', xsd.gYear, false],
['2020-12', xsd.gYearMonth, true],
['-2020-04', xsd.gYearMonth, true],
['2020-04Z', xsd.gYearMonth, true],
['2020-11+04:00', xsd.gYearMonth, true],
['-2020-05-02:00', xsd.gYearMonth, true],
['2020-12-01', xsd.gYearMonth, false],
['2020-04X', xsd.gYearMonth, false],
['12004-01', xsd.gYearMonth, true],
['-12004-01', xsd.gYearMonth, true],
['0922-01', xsd.gYearMonth, true],
['-0922-01', xsd.gYearMonth, true],
['-922-01', xsd.gYearMonth, false],
['test', xsd.gYearMonth, false],
['', xsd.gYearMonth, false],
['', xsd.base64Binary, true],
['dGVzdAo=', xsd.base64Binary, true],
['test', xsd.base64Binary, true],
['test test', xsd.base64Binary, true],
['dkKz84Jdo+k4 kxi8', xsd.base64Binary, true],
['dkKz84Jdo+k4 kxi', xsd.base64Binary, false],
['dkKz84Jdo+k4 kxi=', xsd.base64Binary, false],
['dkKz84Jdo+k4 kx0=', xsd.base64Binary, true],
['dkKz84Jdo+k4 kx0 =', xsd.base64Binary, true],
['dkKz84Jdo+k4 kQ==', xsd.base64Binary, true],
['dkKz84Jdo+k4 kx==', xsd.base64Binary, false],
['dkKz84Jdo+k4 kx= =', xsd.base64Binary, false],
['dkKz84Jdo+k4 kx = =', xsd.base64Binary, false],
['a', xsd.base64Binary, false],
['tests', xsd.base64Binary, false],
['%%%%', xsd.base64Binary, false],
['%44=', xsd.base64Binary, false],
['', xsd.hexBinary, true],
['0FB7', xsd.hexBinary, true],
['0fb7', xsd.hexBinary, true],
['0fb', xsd.hexBinary, false],
['z', xsd.hexBinary, false],
['G1', xsd.hexBinary, false],
['test', xsd.hexBinary, false],
['', csvw.JSON, false],
['[', csvw.JSON, false],
['a', csvw.JSON, false],
['4', csvw.JSON, true],
['null', csvw.JSON, true],
['[]', csvw.JSON, true],
['{}', csvw.JSON, true],
['"test"', csvw.JSON, true],
['{"test": "test"}', csvw.JSON, true],
['{"test": "test",}', csvw.JSON, false],
['{"test": 2}', csvw.JSON, true],
['{4: 2}', csvw.JSON, false],
];
testCases.forEach(([input, datatype, expected, remark]) => {
const datatypeName = datatype.value.split('#').slice(-1)[0];
const titleRemark = remark ? ` (${remark})` : '';
it(`validates ${expected ? 'valid' : 'invalid'} ${datatypeName}${titleRemark}: "${input}"`, () => {
const term = $rdf.literal(input, datatype);
const isValid = validateTerm(term);
assert.strictEqual(isValid, expected);
});
});
});