Skip to content

Commit dae9569

Browse files
add testcases
1 parent b767a4c commit dae9569

File tree

9 files changed

+1104
-132
lines changed

9 files changed

+1104
-132
lines changed

package-lock.json

Lines changed: 207 additions & 110 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"dev": "rollup --config --watch",
1919
"lint": "eslint src/ test/ --ignore-pattern test/browser/testcases.js",
2020
"fix-lint": "eslint src/ test/ --fix --ignore-pattern test/browser/testcases.js",
21-
"test": "mocha out/*.test.{js,cjs,mjs} --parallel",
21+
"test": "mocha out/test/*.test.{js,cjs,mjs} --parallel",
2222
"test-browser": "npx playwright install chromium && npx playwright test"
2323
},
2424
"repository": {
@@ -44,6 +44,7 @@
4444
"rimraf": "^5.0.5",
4545
"rollup": "^4.22.4",
4646
"rollup-plugin-dts": "^6.1.0",
47+
"sinon": "^18.0.0",
4748
"tslib": "^2.6.2",
4849
"typescript": "^5.3.3"
4950
},

src/filter/recurrence/validator.ts

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,18 @@ import { VALUE_OUT_OF_RANGE_ERROR_MESSAGE, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE, R
66
import { DayOfWeek, RecurrenceSpec, RecurrencePattern, RecurrenceRange, RecurrencePatternType, RecurrenceRangeType, DAYS_PER_WEEK, ONE_DAY_IN_MILLISECONDS } from "./model.js";
77
import { calculateWeeklyDayOffset, sortDaysOfWeek, getDayOfWeek } from "./utils.js";
88

9-
const START_NOT_MATCHED_ERROR_MESSAGE = "Start date is not a valid first occurrence.";
10-
const TIME_WINDOW_DURATION_OUT_OF_RANGE_ERROR_MESSAGE = "Time window duration cannot be longer than how frequently it occurs or be longer than 10 years.";
9+
export const START_NOT_MATCHED_ERROR_MESSAGE = "Start date is not a valid first occurrence.";
10+
export const TIME_WINDOW_DURATION_OUT_OF_RANGE_ERROR_MESSAGE = "Time window duration cannot be longer than how frequently it occurs or be longer than 10 years.";
11+
export const PATTERN = "Recurrence.Pattern";
12+
export const PATTERN_TYPE = "Recurrence.Pattern.Type";
13+
export const INTERVAL = "Recurrence.Pattern.Interval";
14+
export const DAYS_OF_WEEK = "Recurrence.Pattern.DaysOfWeek";
15+
export const FIRST_DAY_OF_WEEK = "Recurrence.Pattern.FirstDayOfWeek";
16+
export const RANGE = "Recurrence.Range";
17+
export const RANGE_TYPE = "Recurrence.Range.Type";
18+
export const END_DATE = "Recurrence.Range.EndDate";
19+
export const NUMBER_OF_OCCURRENCES = "Recurrence.Range.NumberOfOccurrences";
20+
1121

1222
/**
1323
* Parses @see RecurrenceParameter into a @see RecurrenceSpec object. If the parameter is invalid, an error will be thrown.
@@ -44,21 +54,21 @@ export function parseRecurrenceParameter(startTime: Date | undefined, endTime: D
4454
function parseRecurrencePattern(startTime: Date, endTime: Date, recurrenceParameter: RecurrenceParameter, timeZoneOffset: number): RecurrencePattern {
4555
const rawPattern = recurrenceParameter.Pattern;
4656
if (rawPattern === undefined) {
47-
throw new Error(buildInvalidParameterErrorMessage("Pattern", REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
57+
throw new Error(buildInvalidParameterErrorMessage(PATTERN, REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
4858
}
4959
if (rawPattern.Type === undefined) {
50-
throw new Error(buildInvalidParameterErrorMessage("Pattern.Type", REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
60+
throw new Error(buildInvalidParameterErrorMessage(PATTERN_TYPE, REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
5161
}
5262
const patternType = RecurrencePatternType[rawPattern.Type];
5363
if (patternType === undefined) {
54-
throw new Error(buildInvalidParameterErrorMessage("Pattern.Type", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
64+
throw new Error(buildInvalidParameterErrorMessage(PATTERN_TYPE, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
5565
}
5666
let interval = rawPattern.Interval;
5767
if (interval !== undefined) {
5868
if (typeof interval !== "number") {
59-
throw new Error(buildInvalidParameterErrorMessage("Pattern.Interval", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
69+
throw new Error(buildInvalidParameterErrorMessage(INTERVAL, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
6070
} else if (interval <= 0 || !Number.isInteger(interval)) {
61-
throw new Error(buildInvalidParameterErrorMessage("Pattern.Interval", VALUE_OUT_OF_RANGE_ERROR_MESSAGE));
71+
throw new Error(buildInvalidParameterErrorMessage(INTERVAL, VALUE_OUT_OF_RANGE_ERROR_MESSAGE));
6272
}
6373
} else {
6474
interval = 1;
@@ -77,7 +87,7 @@ function parseRecurrencePattern(startTime: Date, endTime: Date, recurrenceParame
7787
if (rawPattern.FirstDayOfWeek !== undefined) {
7888
firstDayOfWeek = DayOfWeek[rawPattern.FirstDayOfWeek];
7989
if (firstDayOfWeek === undefined) {
80-
throw new Error(buildInvalidParameterErrorMessage("Pattern.FirstDayOfWeek", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
90+
throw new Error(buildInvalidParameterErrorMessage(FIRST_DAY_OF_WEEK, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
8191
}
8292
}
8393
else {
@@ -86,11 +96,14 @@ function parseRecurrencePattern(startTime: Date, endTime: Date, recurrenceParame
8696
parsedPattern.firstDayOfWeek = firstDayOfWeek;
8797

8898
if (rawPattern.DaysOfWeek === undefined || rawPattern.DaysOfWeek.length === 0) {
89-
throw new Error(buildInvalidParameterErrorMessage("Pattern.DaysOfWeek", REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
99+
throw new Error(buildInvalidParameterErrorMessage(DAYS_OF_WEEK, REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
100+
}
101+
if (!Array.isArray(rawPattern.DaysOfWeek)) {
102+
throw new Error(buildInvalidParameterErrorMessage(DAYS_OF_WEEK, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
90103
}
91104
const daysOfWeek = [...new Set(rawPattern.DaysOfWeek.map(day => DayOfWeek[day]))]; // dedup array
92105
if (daysOfWeek.some(day => day === undefined)) {
93-
throw new Error(buildInvalidParameterErrorMessage("Pattern.DaysOfWeek", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
106+
throw new Error(buildInvalidParameterErrorMessage(DAYS_OF_WEEK, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
94107
}
95108
if (timeWindowDuration > interval * DAYS_PER_WEEK * ONE_DAY_IN_MILLISECONDS ||
96109
!IsDurationCompliantWithDaysOfWeek(timeWindowDuration, interval, daysOfWeek, firstDayOfWeek)) {
@@ -110,25 +123,25 @@ function parseRecurrencePattern(startTime: Date, endTime: Date, recurrenceParame
110123
function parseRecurrenceRange(startTime: Date, recurrenceParameter: RecurrenceParameter): RecurrenceRange {
111124
const rawRange = recurrenceParameter.Range;
112125
if (rawRange === undefined) {
113-
throw new Error(buildInvalidParameterErrorMessage("Range", REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
126+
throw new Error(buildInvalidParameterErrorMessage(RANGE, REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
114127
}
115128
if (rawRange.Type === undefined) {
116-
throw new Error(buildInvalidParameterErrorMessage("Range.Type", REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
129+
throw new Error(buildInvalidParameterErrorMessage(RANGE_TYPE, REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE));
117130
}
118131
const rangeType = RecurrenceRangeType[rawRange.Type];
119132
if (rangeType === undefined) {
120-
throw new Error(buildInvalidParameterErrorMessage("Range.Type", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
133+
throw new Error(buildInvalidParameterErrorMessage(RANGE_TYPE, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
121134
}
122135
const parsedRange: RecurrenceRange = { type: rangeType };
123136
if (rangeType === RecurrenceRangeType.EndDate) {
124137
let endDate: Date;
125138
if (rawRange.EndDate !== undefined) {
126139
endDate = new Date(rawRange.EndDate);
127140
if (isNaN(endDate.getTime())) {
128-
throw new Error(buildInvalidParameterErrorMessage("Range.EndDate", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
141+
throw new Error(buildInvalidParameterErrorMessage(END_DATE, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
129142
}
130143
if (endDate < startTime) {
131-
throw new Error(buildInvalidParameterErrorMessage("Range.EndDate", VALUE_OUT_OF_RANGE_ERROR_MESSAGE));
144+
throw new Error(buildInvalidParameterErrorMessage(END_DATE, VALUE_OUT_OF_RANGE_ERROR_MESSAGE));
132145
}
133146
} else {
134147
endDate = new Date(8.64e15); // the maximum date in ECMAScript: https://262.ecma-international.org/5.1/#sec-15.9.1.1
@@ -138,9 +151,9 @@ function parseRecurrenceRange(startTime: Date, recurrenceParameter: RecurrencePa
138151
let numberOfOccurrences = rawRange.NumberOfOccurrences;
139152
if (numberOfOccurrences !== undefined) {
140153
if (typeof numberOfOccurrences !== "number") {
141-
throw new Error(buildInvalidParameterErrorMessage("Range.NumberOfOccurrences", UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
154+
throw new Error(buildInvalidParameterErrorMessage(NUMBER_OF_OCCURRENCES, UNRECOGNIZABLE_VALUE_ERROR_MESSAGE));
142155
} else if (numberOfOccurrences <= 0 || !Number.isInteger(numberOfOccurrences)) {
143-
throw new Error(buildInvalidParameterErrorMessage("Range.NumberOfOccurrences", VALUE_OUT_OF_RANGE_ERROR_MESSAGE));
156+
throw new Error(buildInvalidParameterErrorMessage(NUMBER_OF_OCCURRENCES, VALUE_OUT_OF_RANGE_ERROR_MESSAGE));
144157
}
145158
} else {
146159
numberOfOccurrences = Number.MAX_SAFE_INTEGER;

src/filter/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ export const UNRECOGNIZABLE_VALUE_ERROR_MESSAGE = "The value is unrecognizable."
66
export const REQUIRED_PARAMETER_MISSING_ERROR_MESSAGE = "Value cannot be undefined or empty.";
77

88
export function buildInvalidParameterErrorMessage(parameterName: string, additionalInfo?: string): string {
9-
return `The ${parameterName} parameter is not valid.` + (additionalInfo ?? "");
9+
return `The ${parameterName} parameter is not valid. ` + (additionalInfo ?? "");
1010
}

test/featureManager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised";
66
chai.use(chaiAsPromised);
77
const expect = chai.expect;
88

9-
import { FeatureManager, ConfigurationObjectFeatureFlagProvider, ConfigurationMapFeatureFlagProvider } from "../";
9+
import { FeatureManager, ConfigurationObjectFeatureFlagProvider, ConfigurationMapFeatureFlagProvider } from "../src/index.js";
1010

1111
describe("feature manager", () => {
1212
it("should load from json string", () => {

test/noFilters.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as chaiAsPromised from "chai-as-promised";
66
chai.use(chaiAsPromised);
77
const expect = chai.expect;
88

9-
import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "../";
9+
import { FeatureManager, ConfigurationObjectFeatureFlagProvider } from "../src/index.js";
1010

1111
const featureFlagsDataObject = {
1212
"feature_management": {

0 commit comments

Comments
 (0)