@usertour/helpers 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/attribute.test.cjs +1036 -0
- package/dist/__tests__/attribute.test.d.cts +2 -0
- package/dist/__tests__/attribute.test.d.ts +2 -0
- package/dist/__tests__/attribute.test.js +802 -0
- package/dist/__tests__/time.test.cjs +73 -0
- package/dist/__tests__/time.test.d.cts +2 -0
- package/dist/__tests__/time.test.d.ts +2 -0
- package/dist/__tests__/time.test.js +48 -0
- package/dist/__tests__/url.test.cjs +259 -0
- package/dist/__tests__/url.test.d.cts +2 -0
- package/dist/__tests__/url.test.d.ts +2 -0
- package/dist/__tests__/url.test.js +197 -0
- package/dist/{chunk-B4DTY6GN.js → chunk-4LLDSAHJ.js} +0 -12
- package/dist/chunk-7CC4WXB3.js +60 -0
- package/dist/chunk-7ODE2AIC.js +0 -0
- package/dist/{chunk-IZFZYGPU.js → chunk-BC7KXBMF.js} +5 -56
- package/dist/chunk-CEK3SCQO.js +31 -0
- package/dist/chunk-PBZSPV5R.js +239 -0
- package/dist/conditions/attribute.cjs +264 -0
- package/dist/conditions/attribute.d.cts +28 -0
- package/dist/conditions/attribute.d.ts +28 -0
- package/dist/conditions/attribute.js +9 -0
- package/dist/conditions/condition.cjs +95 -0
- package/dist/{conditions.d.ts → conditions/condition.d.cts} +1 -2
- package/dist/{conditions.d.cts → conditions/condition.d.ts} +1 -2
- package/dist/conditions/condition.js +9 -0
- package/dist/conditions/index.cjs +379 -0
- package/dist/conditions/index.d.cts +6 -0
- package/dist/conditions/index.d.ts +6 -0
- package/dist/conditions/index.js +24 -0
- package/dist/conditions/time.cjs +55 -0
- package/dist/conditions/time.d.cts +10 -0
- package/dist/conditions/time.d.ts +10 -0
- package/dist/conditions/time.js +7 -0
- package/dist/{conditions.cjs → conditions/url.cjs} +9 -71
- package/dist/conditions/url.d.cts +6 -0
- package/dist/conditions/url.d.ts +6 -0
- package/dist/conditions/url.js +9 -0
- package/dist/content.cjs +0 -13
- package/dist/content.d.cts +1 -2
- package/dist/content.d.ts +1 -2
- package/dist/content.js +1 -3
- package/dist/index.cjs +261 -54
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +19 -8
- package/package.json +15 -9
- package/dist/conditions.js +0 -11
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// src/conditions/time.ts
|
|
4
|
+
var import_date_fns = require("date-fns");
|
|
5
|
+
var evaluateTimeCondition = (rules) => {
|
|
6
|
+
try {
|
|
7
|
+
const { endDate, endDateHour, endDateMinute, startDate, startDateHour, startDateMinute } = rules.data || {};
|
|
8
|
+
if (!startDate || !startDateHour || !startDateMinute) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
const startTimeString = `${startDate}T${startDateHour.padStart(2, "0")}:${startDateMinute.padStart(2, "0")}:00`;
|
|
12
|
+
const startTime = (0, import_date_fns.parseISO)(startTimeString);
|
|
13
|
+
if (!(0, import_date_fns.isValid)(startTime)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
const now = /* @__PURE__ */ new Date();
|
|
17
|
+
if (!endDate || !endDateHour || !endDateMinute) {
|
|
18
|
+
return (0, import_date_fns.isAfter)(now, startTime);
|
|
19
|
+
}
|
|
20
|
+
const endTimeString = `${endDate}T${endDateHour.padStart(2, "0")}:${endDateMinute.padStart(2, "0")}:00`;
|
|
21
|
+
const endTime = (0, import_date_fns.parseISO)(endTimeString);
|
|
22
|
+
if (!(0, import_date_fns.isValid)(endTime)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return (0, import_date_fns.isAfter)(now, startTime) && (0, import_date_fns.isBefore)(now, endTime);
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// src/__tests__/time.test.ts
|
|
32
|
+
describe("Time Condition Evaluation", () => {
|
|
33
|
+
const mockNow = /* @__PURE__ */ new Date("2024-01-15T12:00:00Z");
|
|
34
|
+
beforeAll(() => {
|
|
35
|
+
jest.useFakeTimers();
|
|
36
|
+
jest.setSystemTime(mockNow);
|
|
37
|
+
});
|
|
38
|
+
afterAll(() => {
|
|
39
|
+
jest.useRealTimers();
|
|
40
|
+
});
|
|
41
|
+
test("should return true when current time is after start time and no end time", () => {
|
|
42
|
+
const rules = {
|
|
43
|
+
id: "condition-1",
|
|
44
|
+
type: "condition",
|
|
45
|
+
operators: "and",
|
|
46
|
+
data: {
|
|
47
|
+
startDate: "2024-01-15",
|
|
48
|
+
startDateHour: "10",
|
|
49
|
+
startDateMinute: "00",
|
|
50
|
+
endDate: "",
|
|
51
|
+
endDateHour: "",
|
|
52
|
+
endDateMinute: ""
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
expect(evaluateTimeCondition(rules)).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
test("should return true when current time is within start and end time range", () => {
|
|
58
|
+
const rules = {
|
|
59
|
+
id: "condition-2",
|
|
60
|
+
type: "condition",
|
|
61
|
+
operators: "and",
|
|
62
|
+
data: {
|
|
63
|
+
startDate: "2024-01-15",
|
|
64
|
+
startDateHour: "10",
|
|
65
|
+
startDateMinute: "00",
|
|
66
|
+
endDate: "2024-01-15",
|
|
67
|
+
endDateHour: "14",
|
|
68
|
+
endDateMinute: "00"
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
expect(evaluateTimeCondition(rules)).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
evaluateTimeCondition
|
|
3
|
+
} from "../chunk-CEK3SCQO.js";
|
|
4
|
+
import "../chunk-XEO3YXBM.js";
|
|
5
|
+
|
|
6
|
+
// src/__tests__/time.test.ts
|
|
7
|
+
describe("Time Condition Evaluation", () => {
|
|
8
|
+
const mockNow = /* @__PURE__ */ new Date("2024-01-15T12:00:00Z");
|
|
9
|
+
beforeAll(() => {
|
|
10
|
+
jest.useFakeTimers();
|
|
11
|
+
jest.setSystemTime(mockNow);
|
|
12
|
+
});
|
|
13
|
+
afterAll(() => {
|
|
14
|
+
jest.useRealTimers();
|
|
15
|
+
});
|
|
16
|
+
test("should return true when current time is after start time and no end time", () => {
|
|
17
|
+
const rules = {
|
|
18
|
+
id: "condition-1",
|
|
19
|
+
type: "condition",
|
|
20
|
+
operators: "and",
|
|
21
|
+
data: {
|
|
22
|
+
startDate: "2024-01-15",
|
|
23
|
+
startDateHour: "10",
|
|
24
|
+
startDateMinute: "00",
|
|
25
|
+
endDate: "",
|
|
26
|
+
endDateHour: "",
|
|
27
|
+
endDateMinute: ""
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
expect(evaluateTimeCondition(rules)).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
test("should return true when current time is within start and end time range", () => {
|
|
33
|
+
const rules = {
|
|
34
|
+
id: "condition-2",
|
|
35
|
+
type: "condition",
|
|
36
|
+
operators: "and",
|
|
37
|
+
data: {
|
|
38
|
+
startDate: "2024-01-15",
|
|
39
|
+
startDateHour: "10",
|
|
40
|
+
startDateMinute: "00",
|
|
41
|
+
endDate: "2024-01-15",
|
|
42
|
+
endDateHour: "14",
|
|
43
|
+
endDateMinute: "00"
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
expect(evaluateTimeCondition(rules)).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// src/conditions/url.ts
|
|
4
|
+
var parseUrl = (url) => {
|
|
5
|
+
const urlPatterns = url.match(/^(([a-z\d]+):\/\/)?([^/?#]+)?(\/[^?#]*)?(\?([^#]*))?(#.*)?$/i);
|
|
6
|
+
if (!urlPatterns) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const [, , scheme = "", domain = "", path = "", , query = "", fragment = ""] = urlPatterns;
|
|
10
|
+
return { scheme, domain, path, query, fragment };
|
|
11
|
+
};
|
|
12
|
+
var replaceWildcard = (input, s1, s2) => {
|
|
13
|
+
const withSpecialWords = replaceSpecialWords(input);
|
|
14
|
+
const withWildcard = withSpecialWords.replace(/\\\*/g, `${s1}*`);
|
|
15
|
+
if (!s2) {
|
|
16
|
+
return withWildcard;
|
|
17
|
+
}
|
|
18
|
+
return withWildcard.replace(/:[a-z0-9_]+/g, `[^${s2}]+`);
|
|
19
|
+
};
|
|
20
|
+
var replaceSpecialWords = (str) => {
|
|
21
|
+
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
22
|
+
};
|
|
23
|
+
var parsePattern = (pattern) => {
|
|
24
|
+
if (!pattern || !pattern.trim()) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const _pattern = parseUrl(pattern);
|
|
28
|
+
if (!_pattern) {
|
|
29
|
+
console.error("Invalid URL pattern:", pattern);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const { scheme, domain, path, query, fragment } = _pattern;
|
|
33
|
+
const _scheme = scheme ? replaceSpecialWords(scheme) : "[a-z\\d]+";
|
|
34
|
+
const _domain = domain ? replaceWildcard(domain, "[^/]", ".") : "[^/]*";
|
|
35
|
+
const _fragment = fragment ? replaceWildcard(fragment, ".", "/") : "(#.*)?";
|
|
36
|
+
const _path = path ? replaceWildcard(path, "[^?#]", "/") : "/[^?#]*";
|
|
37
|
+
let _query = "(\\?[^#]*)?";
|
|
38
|
+
if (query) {
|
|
39
|
+
new URLSearchParams(query).forEach((value, key) => {
|
|
40
|
+
const _str = value === "" ? "=?" : value === "*" ? "(=[^&#]*)?" : `=${replaceWildcard(value, "[^#]")}`;
|
|
41
|
+
_query += `(?=.*[?&]${replaceSpecialWords(key)}${_str}([&#]|$))`;
|
|
42
|
+
});
|
|
43
|
+
_query += "\\?[^#]*";
|
|
44
|
+
}
|
|
45
|
+
return new RegExp(`^${_scheme}://${_domain}(:\\d+)?${_path}${_query}${_fragment}$`);
|
|
46
|
+
};
|
|
47
|
+
var isMatchUrlPattern = (_url, includes, excludes) => {
|
|
48
|
+
const isMatchIncludesConditions = includes.length > 0 ? includes.some((_include) => {
|
|
49
|
+
const reg = parsePattern(_include);
|
|
50
|
+
if (reg) {
|
|
51
|
+
return reg.test(_url);
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}) : true;
|
|
55
|
+
const isMatchExcludesConditions = excludes.length > 0 ? excludes.some((_exclude) => {
|
|
56
|
+
const reg = parsePattern(_exclude);
|
|
57
|
+
if (reg) {
|
|
58
|
+
return reg.test(_url);
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}) : false;
|
|
62
|
+
return isMatchIncludesConditions && !isMatchExcludesConditions;
|
|
63
|
+
};
|
|
64
|
+
var evaluateUrlCondition = (rules, url) => {
|
|
65
|
+
const { excludes, includes } = rules.data;
|
|
66
|
+
return isMatchUrlPattern(url, includes, excludes);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/__tests__/url.test.ts
|
|
70
|
+
describe("URL Condition Evaluation", () => {
|
|
71
|
+
describe("evaluateUrlCondition", () => {
|
|
72
|
+
test("should return true when URL matches include pattern and no excludes", () => {
|
|
73
|
+
const rules = {
|
|
74
|
+
id: "condition-1",
|
|
75
|
+
type: "condition",
|
|
76
|
+
operators: "and",
|
|
77
|
+
data: {
|
|
78
|
+
includes: ["https://example.com/dashboard"],
|
|
79
|
+
excludes: []
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const url = "https://example.com/dashboard";
|
|
83
|
+
expect(evaluateUrlCondition(rules, url)).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
test("should return false when URL does not match include pattern", () => {
|
|
86
|
+
const rules = {
|
|
87
|
+
id: "condition-2",
|
|
88
|
+
type: "condition",
|
|
89
|
+
operators: "and",
|
|
90
|
+
data: {
|
|
91
|
+
includes: ["https://example.com/dashboard"],
|
|
92
|
+
excludes: []
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const url = "https://example.com/profile";
|
|
96
|
+
expect(evaluateUrlCondition(rules, url)).toBe(false);
|
|
97
|
+
});
|
|
98
|
+
test("should return false when URL matches exclude pattern", () => {
|
|
99
|
+
const rules = {
|
|
100
|
+
id: "condition-3",
|
|
101
|
+
type: "condition",
|
|
102
|
+
operators: "and",
|
|
103
|
+
data: {
|
|
104
|
+
includes: ["https://example.com/*"],
|
|
105
|
+
excludes: ["https://example.com/admin"]
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const url = "https://example.com/admin";
|
|
109
|
+
expect(evaluateUrlCondition(rules, url)).toBe(false);
|
|
110
|
+
});
|
|
111
|
+
test("should return true when URL matches include but not exclude", () => {
|
|
112
|
+
const rules = {
|
|
113
|
+
id: "condition-4",
|
|
114
|
+
type: "condition",
|
|
115
|
+
operators: "and",
|
|
116
|
+
data: {
|
|
117
|
+
includes: ["https://example.com/*"],
|
|
118
|
+
excludes: ["https://example.com/admin"]
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const url = "https://example.com/dashboard";
|
|
122
|
+
expect(evaluateUrlCondition(rules, url)).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
test("should return true when no includes specified (matches all)", () => {
|
|
125
|
+
const rules = {
|
|
126
|
+
id: "condition-5",
|
|
127
|
+
type: "condition",
|
|
128
|
+
operators: "and",
|
|
129
|
+
data: {
|
|
130
|
+
includes: [],
|
|
131
|
+
excludes: []
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
const url = "https://example.com/dashboard";
|
|
135
|
+
expect(evaluateUrlCondition(rules, url)).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
test("should return false when URL matches exclude even with no includes", () => {
|
|
138
|
+
const rules = {
|
|
139
|
+
id: "condition-6",
|
|
140
|
+
type: "condition",
|
|
141
|
+
operators: "and",
|
|
142
|
+
data: {
|
|
143
|
+
includes: [],
|
|
144
|
+
excludes: ["https://example.com/admin"]
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const url = "https://example.com/admin";
|
|
148
|
+
expect(evaluateUrlCondition(rules, url)).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
describe("isMatchUrlPattern", () => {
|
|
152
|
+
test("should match exact URL", () => {
|
|
153
|
+
const url = "https://example.com/dashboard";
|
|
154
|
+
const includes = ["https://example.com/dashboard"];
|
|
155
|
+
const excludes = [];
|
|
156
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
test("should match wildcard pattern", () => {
|
|
159
|
+
const url = "https://example.com/dashboard";
|
|
160
|
+
const includes = ["https://example.com/*"];
|
|
161
|
+
const excludes = [];
|
|
162
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
163
|
+
});
|
|
164
|
+
test("should match multiple include patterns", () => {
|
|
165
|
+
const url = "https://example.com/dashboard";
|
|
166
|
+
const includes = [
|
|
167
|
+
"https://example.com/profile",
|
|
168
|
+
"https://example.com/dashboard",
|
|
169
|
+
"https://example.com/settings"
|
|
170
|
+
];
|
|
171
|
+
const excludes = [];
|
|
172
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
test("should not match when no includes match", () => {
|
|
175
|
+
const url = "https://example.com/dashboard";
|
|
176
|
+
const includes = ["https://example.com/profile", "https://example.com/settings"];
|
|
177
|
+
const excludes = [];
|
|
178
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
test("should not match when URL is excluded", () => {
|
|
181
|
+
const url = "https://example.com/admin";
|
|
182
|
+
const includes = ["https://example.com/*"];
|
|
183
|
+
const excludes = ["https://example.com/admin"];
|
|
184
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
185
|
+
});
|
|
186
|
+
test("should match when URL matches include but not exclude", () => {
|
|
187
|
+
const url = "https://example.com/dashboard";
|
|
188
|
+
const includes = ["https://example.com/*"];
|
|
189
|
+
const excludes = ["https://example.com/admin"];
|
|
190
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
191
|
+
});
|
|
192
|
+
test("should handle empty includes (matches all)", () => {
|
|
193
|
+
const url = "https://example.com/dashboard";
|
|
194
|
+
const includes = [];
|
|
195
|
+
const excludes = [];
|
|
196
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
test("should handle empty excludes", () => {
|
|
199
|
+
const url = "https://example.com/dashboard";
|
|
200
|
+
const includes = ["https://example.com/*"];
|
|
201
|
+
const excludes = [];
|
|
202
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
203
|
+
});
|
|
204
|
+
test("should handle complex URL patterns with query parameters", () => {
|
|
205
|
+
const url = "https://example.com/dashboard?tab=overview&user=123";
|
|
206
|
+
const includes = ["https://example.com/dashboard?tab=*"];
|
|
207
|
+
const excludes = [];
|
|
208
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
test("should handle URL patterns with path parameters", () => {
|
|
211
|
+
const url = "https://example.com/users/123/profile";
|
|
212
|
+
const includes = ["https://example.com/users/*/profile"];
|
|
213
|
+
const excludes = [];
|
|
214
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
215
|
+
});
|
|
216
|
+
test("should handle URL patterns with fragments", () => {
|
|
217
|
+
const url = "https://example.com/dashboard#overview";
|
|
218
|
+
const includes = ["https://example.com/dashboard#*"];
|
|
219
|
+
const excludes = [];
|
|
220
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
test("should handle URLs without protocol", () => {
|
|
223
|
+
const url = "https://example.com/dashboard";
|
|
224
|
+
const includes = ["example.com/dashboard"];
|
|
225
|
+
const excludes = [];
|
|
226
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
227
|
+
});
|
|
228
|
+
test("should handle URLs with different protocols", () => {
|
|
229
|
+
const url = "http://example.com/dashboard";
|
|
230
|
+
const includes = ["https://example.com/dashboard"];
|
|
231
|
+
const excludes = [];
|
|
232
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
233
|
+
});
|
|
234
|
+
test("should handle invalid URL patterns gracefully", () => {
|
|
235
|
+
const url = "https://example.com/dashboard";
|
|
236
|
+
const includes = ["invalid-url-pattern"];
|
|
237
|
+
const excludes = [];
|
|
238
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
239
|
+
});
|
|
240
|
+
test("should handle empty URL", () => {
|
|
241
|
+
const url = "";
|
|
242
|
+
const includes = ["https://example.com/*"];
|
|
243
|
+
const excludes = [];
|
|
244
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
245
|
+
});
|
|
246
|
+
test("should handle multiple exclude patterns", () => {
|
|
247
|
+
const url = "https://example.com/admin";
|
|
248
|
+
const includes = ["https://example.com/*"];
|
|
249
|
+
const excludes = ["https://example.com/admin", "https://example.com/settings"];
|
|
250
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
251
|
+
});
|
|
252
|
+
test("should match when URL matches include but not any exclude", () => {
|
|
253
|
+
const url = "https://example.com/dashboard";
|
|
254
|
+
const includes = ["https://example.com/*"];
|
|
255
|
+
const excludes = ["https://example.com/admin", "https://example.com/settings"];
|
|
256
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import {
|
|
2
|
+
evaluateUrlCondition,
|
|
3
|
+
isMatchUrlPattern
|
|
4
|
+
} from "../chunk-BC7KXBMF.js";
|
|
5
|
+
import "../chunk-XEO3YXBM.js";
|
|
6
|
+
|
|
7
|
+
// src/__tests__/url.test.ts
|
|
8
|
+
describe("URL Condition Evaluation", () => {
|
|
9
|
+
describe("evaluateUrlCondition", () => {
|
|
10
|
+
test("should return true when URL matches include pattern and no excludes", () => {
|
|
11
|
+
const rules = {
|
|
12
|
+
id: "condition-1",
|
|
13
|
+
type: "condition",
|
|
14
|
+
operators: "and",
|
|
15
|
+
data: {
|
|
16
|
+
includes: ["https://example.com/dashboard"],
|
|
17
|
+
excludes: []
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const url = "https://example.com/dashboard";
|
|
21
|
+
expect(evaluateUrlCondition(rules, url)).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
test("should return false when URL does not match include pattern", () => {
|
|
24
|
+
const rules = {
|
|
25
|
+
id: "condition-2",
|
|
26
|
+
type: "condition",
|
|
27
|
+
operators: "and",
|
|
28
|
+
data: {
|
|
29
|
+
includes: ["https://example.com/dashboard"],
|
|
30
|
+
excludes: []
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const url = "https://example.com/profile";
|
|
34
|
+
expect(evaluateUrlCondition(rules, url)).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
test("should return false when URL matches exclude pattern", () => {
|
|
37
|
+
const rules = {
|
|
38
|
+
id: "condition-3",
|
|
39
|
+
type: "condition",
|
|
40
|
+
operators: "and",
|
|
41
|
+
data: {
|
|
42
|
+
includes: ["https://example.com/*"],
|
|
43
|
+
excludes: ["https://example.com/admin"]
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const url = "https://example.com/admin";
|
|
47
|
+
expect(evaluateUrlCondition(rules, url)).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
test("should return true when URL matches include but not exclude", () => {
|
|
50
|
+
const rules = {
|
|
51
|
+
id: "condition-4",
|
|
52
|
+
type: "condition",
|
|
53
|
+
operators: "and",
|
|
54
|
+
data: {
|
|
55
|
+
includes: ["https://example.com/*"],
|
|
56
|
+
excludes: ["https://example.com/admin"]
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const url = "https://example.com/dashboard";
|
|
60
|
+
expect(evaluateUrlCondition(rules, url)).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
test("should return true when no includes specified (matches all)", () => {
|
|
63
|
+
const rules = {
|
|
64
|
+
id: "condition-5",
|
|
65
|
+
type: "condition",
|
|
66
|
+
operators: "and",
|
|
67
|
+
data: {
|
|
68
|
+
includes: [],
|
|
69
|
+
excludes: []
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const url = "https://example.com/dashboard";
|
|
73
|
+
expect(evaluateUrlCondition(rules, url)).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
test("should return false when URL matches exclude even with no includes", () => {
|
|
76
|
+
const rules = {
|
|
77
|
+
id: "condition-6",
|
|
78
|
+
type: "condition",
|
|
79
|
+
operators: "and",
|
|
80
|
+
data: {
|
|
81
|
+
includes: [],
|
|
82
|
+
excludes: ["https://example.com/admin"]
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
const url = "https://example.com/admin";
|
|
86
|
+
expect(evaluateUrlCondition(rules, url)).toBe(false);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe("isMatchUrlPattern", () => {
|
|
90
|
+
test("should match exact URL", () => {
|
|
91
|
+
const url = "https://example.com/dashboard";
|
|
92
|
+
const includes = ["https://example.com/dashboard"];
|
|
93
|
+
const excludes = [];
|
|
94
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
test("should match wildcard pattern", () => {
|
|
97
|
+
const url = "https://example.com/dashboard";
|
|
98
|
+
const includes = ["https://example.com/*"];
|
|
99
|
+
const excludes = [];
|
|
100
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
test("should match multiple include patterns", () => {
|
|
103
|
+
const url = "https://example.com/dashboard";
|
|
104
|
+
const includes = [
|
|
105
|
+
"https://example.com/profile",
|
|
106
|
+
"https://example.com/dashboard",
|
|
107
|
+
"https://example.com/settings"
|
|
108
|
+
];
|
|
109
|
+
const excludes = [];
|
|
110
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
111
|
+
});
|
|
112
|
+
test("should not match when no includes match", () => {
|
|
113
|
+
const url = "https://example.com/dashboard";
|
|
114
|
+
const includes = ["https://example.com/profile", "https://example.com/settings"];
|
|
115
|
+
const excludes = [];
|
|
116
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
test("should not match when URL is excluded", () => {
|
|
119
|
+
const url = "https://example.com/admin";
|
|
120
|
+
const includes = ["https://example.com/*"];
|
|
121
|
+
const excludes = ["https://example.com/admin"];
|
|
122
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
123
|
+
});
|
|
124
|
+
test("should match when URL matches include but not exclude", () => {
|
|
125
|
+
const url = "https://example.com/dashboard";
|
|
126
|
+
const includes = ["https://example.com/*"];
|
|
127
|
+
const excludes = ["https://example.com/admin"];
|
|
128
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
129
|
+
});
|
|
130
|
+
test("should handle empty includes (matches all)", () => {
|
|
131
|
+
const url = "https://example.com/dashboard";
|
|
132
|
+
const includes = [];
|
|
133
|
+
const excludes = [];
|
|
134
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
test("should handle empty excludes", () => {
|
|
137
|
+
const url = "https://example.com/dashboard";
|
|
138
|
+
const includes = ["https://example.com/*"];
|
|
139
|
+
const excludes = [];
|
|
140
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
141
|
+
});
|
|
142
|
+
test("should handle complex URL patterns with query parameters", () => {
|
|
143
|
+
const url = "https://example.com/dashboard?tab=overview&user=123";
|
|
144
|
+
const includes = ["https://example.com/dashboard?tab=*"];
|
|
145
|
+
const excludes = [];
|
|
146
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
147
|
+
});
|
|
148
|
+
test("should handle URL patterns with path parameters", () => {
|
|
149
|
+
const url = "https://example.com/users/123/profile";
|
|
150
|
+
const includes = ["https://example.com/users/*/profile"];
|
|
151
|
+
const excludes = [];
|
|
152
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
test("should handle URL patterns with fragments", () => {
|
|
155
|
+
const url = "https://example.com/dashboard#overview";
|
|
156
|
+
const includes = ["https://example.com/dashboard#*"];
|
|
157
|
+
const excludes = [];
|
|
158
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
159
|
+
});
|
|
160
|
+
test("should handle URLs without protocol", () => {
|
|
161
|
+
const url = "https://example.com/dashboard";
|
|
162
|
+
const includes = ["example.com/dashboard"];
|
|
163
|
+
const excludes = [];
|
|
164
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
165
|
+
});
|
|
166
|
+
test("should handle URLs with different protocols", () => {
|
|
167
|
+
const url = "http://example.com/dashboard";
|
|
168
|
+
const includes = ["https://example.com/dashboard"];
|
|
169
|
+
const excludes = [];
|
|
170
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
171
|
+
});
|
|
172
|
+
test("should handle invalid URL patterns gracefully", () => {
|
|
173
|
+
const url = "https://example.com/dashboard";
|
|
174
|
+
const includes = ["invalid-url-pattern"];
|
|
175
|
+
const excludes = [];
|
|
176
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
177
|
+
});
|
|
178
|
+
test("should handle empty URL", () => {
|
|
179
|
+
const url = "";
|
|
180
|
+
const includes = ["https://example.com/*"];
|
|
181
|
+
const excludes = [];
|
|
182
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
183
|
+
});
|
|
184
|
+
test("should handle multiple exclude patterns", () => {
|
|
185
|
+
const url = "https://example.com/admin";
|
|
186
|
+
const includes = ["https://example.com/*"];
|
|
187
|
+
const excludes = ["https://example.com/admin", "https://example.com/settings"];
|
|
188
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(false);
|
|
189
|
+
});
|
|
190
|
+
test("should match when URL matches include but not any exclude", () => {
|
|
191
|
+
const url = "https://example.com/dashboard";
|
|
192
|
+
const includes = ["https://example.com/*"];
|
|
193
|
+
const excludes = ["https://example.com/admin", "https://example.com/settings"];
|
|
194
|
+
expect(isMatchUrlPattern(url, includes, excludes)).toBe(true);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
@@ -44,17 +44,6 @@ var defaultContentConfig = {
|
|
|
44
44
|
autoStartRulesSetting: rulesSetting,
|
|
45
45
|
hideRulesSetting
|
|
46
46
|
};
|
|
47
|
-
var autoStartConditions = {
|
|
48
|
-
...defaultContentConfig,
|
|
49
|
-
enabledAutoStartRules: true,
|
|
50
|
-
autoStartRules: [
|
|
51
|
-
{
|
|
52
|
-
data: { excludes: [], includes: ["/*"] },
|
|
53
|
-
type: "current-page",
|
|
54
|
-
operators: "and"
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
};
|
|
58
47
|
var buildConfig = (config) => {
|
|
59
48
|
return {
|
|
60
49
|
...defaultContentConfig,
|
|
@@ -71,6 +60,5 @@ export {
|
|
|
71
60
|
isPublishedInAllEnvironments,
|
|
72
61
|
isPublishedAtLeastOneEnvironment,
|
|
73
62
|
defaultContentConfig,
|
|
74
|
-
autoStartConditions,
|
|
75
63
|
buildConfig
|
|
76
64
|
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/conditions/condition.ts
|
|
2
|
+
import isEqual from "fast-deep-equal";
|
|
3
|
+
var compareConditionsItem = (item1, item2) => {
|
|
4
|
+
const { data = {}, ...others1 } = item1;
|
|
5
|
+
const { data: data2 = {}, ...others2 } = item2;
|
|
6
|
+
if (!isEqual(others2, others1)) {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
for (const key in data) {
|
|
10
|
+
if (!isEqual(data[key], data2[key])) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
};
|
|
16
|
+
var conditionsIsSame = (rr1, rr2) => {
|
|
17
|
+
const r1 = [...rr1];
|
|
18
|
+
const r2 = [...rr2];
|
|
19
|
+
if (r1.length === 0 && r2.length === 0) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
if (r1.length !== r2.length) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const group1 = r1.filter((item) => item.type === "group");
|
|
26
|
+
const group2 = r2.filter((item) => item.type === "group");
|
|
27
|
+
if (group1.length !== group2.length) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
for (let index = 0; index < r1.length; index++) {
|
|
31
|
+
const item1 = r1[index];
|
|
32
|
+
const item2 = r2[index];
|
|
33
|
+
if (!item1 || !item2) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (item1.type === "group") {
|
|
37
|
+
if (!item2.conditions) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const c1 = item1.conditions;
|
|
41
|
+
const c2 = item2.conditions;
|
|
42
|
+
if (item1.operators !== item2.operators) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (!conditionsIsSame(c1, c2)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
if (!compareConditionsItem(item1, item2)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
isEqual,
|
|
59
|
+
conditionsIsSame
|
|
60
|
+
};
|
|
File without changes
|