Skip to content

Commit 33552c7

Browse files
author
Jared Parnell
committed
data-quality: Add rule to ensure timezone matches IANA list
scheduleTimezone rule: update message with link to IANA
1 parent d6508a0 commit 33552c7

6 files changed

+117
-2
lines changed

src/rules/data-quality/timezone-in-partial-schedule-spec.js renamed to src/rules/data-quality/scheduletimezone-in-partialschedule-rule-spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const TimezoneInPartialSchedule = require('./timezone-in-partial-schedule');
1+
const TimezoneInPartialSchedule = require('./scheduletimezone-in-partial-schedule-rule');
22
const Model = require('../../classes/model');
33
const ModelNode = require('../../classes/model-node');
44
const ValidationErrorType = require('../../errors/validation-error-type');

src/rules/data-quality/repeatcount-is-positive-integer-spec.js renamed to src/rules/format/repeatcount-format-rule-spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const RepeatCountIsPositiveInteger = require('./repeatcount-is-positive-integer');
1+
const RepeatCountIsPositiveInteger = require('./repeatcount-format-rule');
22
const Model = require('../../classes/model');
33
const ModelNode = require('../../classes/model-node');
44
const ValidationErrorType = require('../../errors/validation-error-type');
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
const ScheduleTimezoneMatchesIANAList = require('./scheduletimezone-format-rule');
2+
const Model = require('../../classes/model');
3+
const ModelNode = require('../../classes/model-node');
4+
const ValidationErrorType = require('../../errors/validation-error-type');
5+
const ValidationErrorSeverity = require('../../errors/validation-error-severity');
6+
7+
describe('ScheduleTimezoneMatchesIANAList', () => {
8+
const rule = new ScheduleTimezoneMatchesIANAList();
9+
const model = new Model({
10+
type: 'PartialSchedule',
11+
fields: {
12+
scheduleTimezone: {
13+
fieldName: 'scheduleTimezone',
14+
requiredType: 'https://schema.org/Text',
15+
},
16+
},
17+
}, 'latest');
18+
19+
it('should target PartialSchedule models', () => {
20+
const isTargeted = rule.isModelTargeted(model);
21+
expect(isTargeted).toBe(true);
22+
});
23+
24+
it('should not return errors when scheduleTimezone is in the IANA database list', async () => {
25+
const data = {
26+
'@type': 'PartialSchedule',
27+
scheduleTimezone: 'Europe/London',
28+
};
29+
30+
const nodeToTest = new ModelNode(
31+
'$',
32+
data,
33+
null,
34+
model,
35+
);
36+
37+
const errors = await rule.validate(nodeToTest);
38+
39+
expect(errors.length).toBe(0);
40+
});
41+
42+
it('should return errors when scheduleTimezone is not in the IANA database list', async () => {
43+
const data = {
44+
'@type': 'PartialSchedule',
45+
scheduleTimezone: 'Europe/Slough',
46+
};
47+
48+
const nodeToTest = new ModelNode(
49+
'$',
50+
data,
51+
null,
52+
model,
53+
);
54+
55+
const errors = await rule.validate(nodeToTest);
56+
57+
expect(errors.length).toBe(1);
58+
for (const error of errors) {
59+
expect(error.type).toBe(ValidationErrorType.MISSING_REQUIRED_FIELD);
60+
expect(error.severity).toBe(ValidationErrorSeverity.FAILURE);
61+
}
62+
});
63+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const momentTZ = require('moment-timezone');
2+
const Rule = require('../rule');
3+
const ValidationErrorType = require('../../errors/validation-error-type');
4+
const ValidationErrorCategory = require('../../errors/validation-error-category');
5+
const ValidationErrorSeverity = require('../../errors/validation-error-severity');
6+
7+
module.exports = class ScheduleTimezoneMatchesIANAList extends Rule {
8+
constructor(options) {
9+
super(options);
10+
this.targetModels = ['Schedule', 'PartialSchedule'];
11+
this.meta = {
12+
name: 'ScheduleTimezoneMatchesIANAList',
13+
description: 'Validates that scheduleTimezone matches an IANA Timezone.',
14+
tests: {
15+
default: {
16+
message: 'scheduleTimezone must be one of the timezones contained in the [IANA Timezone database](https://www.iana.org/time-zones)',
17+
sampleValues: {
18+
field: 'scheduleTimezone',
19+
allowedValues: 'Europe/London',
20+
},
21+
category: ValidationErrorCategory.CONFORMANCE,
22+
severity: ValidationErrorSeverity.FAILURE,
23+
type: ValidationErrorType.MISSING_REQUIRED_FIELD,
24+
},
25+
},
26+
};
27+
}
28+
29+
validateModel(node) {
30+
const timezoneList = momentTZ.tz.names();
31+
const scheduleTimezone = node.getValue('scheduleTimezone');
32+
33+
if (typeof scheduleTimezone === 'undefined') {
34+
return [];
35+
}
36+
const errors = [];
37+
38+
if (!timezoneList.includes(scheduleTimezone)) {
39+
errors.push(
40+
this.createError(
41+
'default',
42+
{
43+
scheduleTimezone,
44+
path: node.getPath('scheduleTimezone'),
45+
},
46+
),
47+
);
48+
}
49+
50+
return errors;
51+
}
52+
};

0 commit comments

Comments
 (0)