@dotcms/experiments 0.0.1-alpha.39 → 0.0.1-alpha.41
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/index.esm.d.ts +1 -0
- package/index.esm.js +7174 -0
- package/package.json +10 -6
- package/src/lib/components/{DotExperimentHandlingComponent.tsx → DotExperimentHandlingComponent.d.ts} +3 -20
- package/src/lib/components/{DotExperimentsProvider.tsx → DotExperimentsProvider.d.ts} +3 -41
- package/src/lib/components/withExperiments.d.ts +20 -0
- package/src/lib/contexts/{DotExperimentsContext.tsx → DotExperimentsContext.d.ts} +2 -5
- package/src/lib/dot-experiments.d.ts +289 -0
- package/src/lib/hooks/useExperimentVariant.d.ts +21 -0
- package/src/lib/hooks/useExperiments.d.ts +14 -0
- package/src/lib/shared/{constants.ts → constants.d.ts} +18 -35
- package/src/lib/shared/mocks/mock.d.ts +43 -0
- package/src/lib/shared/{models.ts → models.d.ts} +2 -35
- package/src/lib/shared/parser/parser.d.ts +54 -0
- package/src/lib/shared/persistence/index-db-database-handler.d.ts +87 -0
- package/src/lib/shared/utils/DotLogger.d.ts +15 -0
- package/src/lib/shared/utils/memoize.d.ts +7 -0
- package/src/lib/shared/utils/utils.d.ts +73 -0
- package/src/lib/standalone.d.ts +7 -0
- package/.babelrc +0 -12
- package/.eslintrc.json +0 -26
- package/jest.config.ts +0 -11
- package/project.json +0 -55
- package/src/lib/components/DotExperimentsProvider.spec.tsx +0 -62
- package/src/lib/components/withExperiments.tsx +0 -52
- package/src/lib/contexts/DotExperimentsContext.spec.tsx +0 -42
- package/src/lib/dot-experiments.spec.ts +0 -285
- package/src/lib/dot-experiments.ts +0 -716
- package/src/lib/hooks/useExperimentVariant.spec.tsx +0 -111
- package/src/lib/hooks/useExperimentVariant.ts +0 -55
- package/src/lib/hooks/useExperiments.ts +0 -90
- package/src/lib/shared/mocks/mock.ts +0 -209
- package/src/lib/shared/parser/parse.spec.ts +0 -187
- package/src/lib/shared/parser/parser.ts +0 -171
- package/src/lib/shared/persistence/index-db-database-handler.spec.ts +0 -100
- package/src/lib/shared/persistence/index-db-database-handler.ts +0 -218
- package/src/lib/shared/utils/DotLogger.ts +0 -57
- package/src/lib/shared/utils/memoize.spec.ts +0 -49
- package/src/lib/shared/utils/memoize.ts +0 -49
- package/src/lib/shared/utils/utils.spec.ts +0 -142
- package/src/lib/shared/utils/utils.ts +0 -203
- package/src/lib/standalone.spec.ts +0 -36
- package/src/lib/standalone.ts +0 -28
- package/tsconfig.json +0 -20
- package/tsconfig.lib.json +0 -20
- package/tsconfig.spec.json +0 -9
- package/vite.config.ts +0 -41
- /package/src/{index.ts → index.d.ts} +0 -0
|
@@ -26,7 +26,6 @@ export interface DotExperimentConfig {
|
|
|
26
26
|
*/
|
|
27
27
|
redirectFn?: (url: string) => void;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
29
|
/**
|
|
31
30
|
* Represents the configuration for the LookBackWindow.
|
|
32
31
|
*
|
|
@@ -37,18 +36,15 @@ export interface LookBackWindow {
|
|
|
37
36
|
* Defines the time period in milliseconds when the LookBackWindow should expire.
|
|
38
37
|
*/
|
|
39
38
|
expireMillis: number;
|
|
40
|
-
|
|
41
39
|
/**
|
|
42
40
|
* A value indicating the expiration timestamp of the experiment.
|
|
43
41
|
*/
|
|
44
42
|
expireTime?: number;
|
|
45
|
-
|
|
46
43
|
/**
|
|
47
44
|
* Represents the associated value with the LookBackWindow.
|
|
48
45
|
*/
|
|
49
46
|
value: string;
|
|
50
47
|
}
|
|
51
|
-
|
|
52
48
|
/**
|
|
53
49
|
* Represents the configurations for checking whether the current page is an Experiment page, or a target.
|
|
54
50
|
*
|
|
@@ -59,13 +55,11 @@ interface Regexs {
|
|
|
59
55
|
* A regular expression for validating if the page is an Experiment page.
|
|
60
56
|
*/
|
|
61
57
|
isExperimentPage: string;
|
|
62
|
-
|
|
63
58
|
/**
|
|
64
59
|
* A regular expression for validating if the page is the target page. This can be null.
|
|
65
60
|
*/
|
|
66
61
|
isTargetPage: string | null;
|
|
67
62
|
}
|
|
68
|
-
|
|
69
63
|
/**
|
|
70
64
|
* Represents a variant that is applied when a request is made.
|
|
71
65
|
*
|
|
@@ -76,13 +70,11 @@ export interface Variant {
|
|
|
76
70
|
* The name of the variant.
|
|
77
71
|
*/
|
|
78
72
|
name: string;
|
|
79
|
-
|
|
80
73
|
/**
|
|
81
74
|
* The fully qualified URL where the variant is being applied, with query parameters already set.
|
|
82
75
|
*/
|
|
83
76
|
url: string;
|
|
84
77
|
}
|
|
85
|
-
|
|
86
78
|
/**
|
|
87
79
|
* Represents an experiment with all its configurations.
|
|
88
80
|
*
|
|
@@ -93,38 +85,31 @@ export interface Experiment {
|
|
|
93
85
|
* The unique identifier for the experiment.
|
|
94
86
|
*/
|
|
95
87
|
id: string;
|
|
96
|
-
|
|
97
88
|
/**
|
|
98
89
|
* The lookback window object for the experiment.
|
|
99
90
|
*/
|
|
100
91
|
lookBackWindow: LookBackWindow;
|
|
101
|
-
|
|
102
92
|
/**
|
|
103
93
|
* The name of the experiment.
|
|
104
94
|
*/
|
|
105
95
|
name: string;
|
|
106
|
-
|
|
107
96
|
/**
|
|
108
97
|
* The URL of the page where the experiment is applied.
|
|
109
98
|
*/
|
|
110
99
|
pageUrl: string;
|
|
111
|
-
|
|
112
100
|
/**
|
|
113
101
|
* The object containing regular expressions for validating pages.
|
|
114
102
|
*/
|
|
115
103
|
regexs: Regexs;
|
|
116
|
-
|
|
117
104
|
/**
|
|
118
105
|
* The unique running identifier for the experiment.
|
|
119
106
|
*/
|
|
120
107
|
runningId: string;
|
|
121
|
-
|
|
122
108
|
/**
|
|
123
109
|
* The variant applied to the user making the request.
|
|
124
110
|
*/
|
|
125
111
|
variant: Variant;
|
|
126
112
|
}
|
|
127
|
-
|
|
128
113
|
/**
|
|
129
114
|
* Represents the experiments assigned and their details.
|
|
130
115
|
*
|
|
@@ -135,31 +120,23 @@ export interface AssignedExperiments {
|
|
|
135
120
|
* The ids of the experiments that are excluded in the assignment.
|
|
136
121
|
*/
|
|
137
122
|
excludedExperimentIds: string[];
|
|
138
|
-
|
|
139
123
|
/**
|
|
140
124
|
* An array representing the assigned experiments.
|
|
141
125
|
*/
|
|
142
126
|
experiments: Experiment[];
|
|
143
|
-
|
|
144
127
|
/**
|
|
145
128
|
* The ids of the experiments included in the assignment.
|
|
146
129
|
*/
|
|
147
130
|
includedExperimentIds: string[];
|
|
148
|
-
|
|
149
131
|
/**
|
|
150
132
|
* The ids of the experiments that are excluded in the request and have ended.
|
|
151
133
|
*/
|
|
152
134
|
excludedExperimentIdsEnded: string[];
|
|
153
135
|
}
|
|
154
|
-
|
|
155
136
|
/**
|
|
156
137
|
* Represents the response from the backend when fetching an experiment and the excludedExperimentIdsEnded.
|
|
157
138
|
*/
|
|
158
|
-
export type FetchExperiments = Pick<
|
|
159
|
-
AssignedExperiments,
|
|
160
|
-
'excludedExperimentIdsEnded' | 'experiments'
|
|
161
|
-
>;
|
|
162
|
-
|
|
139
|
+
export type FetchExperiments = Pick<AssignedExperiments, 'excludedExperimentIdsEnded' | 'experiments'>;
|
|
163
140
|
/**
|
|
164
141
|
* Represents the response from backend holding information about running experiments and variant assignment.
|
|
165
142
|
*
|
|
@@ -170,23 +147,19 @@ export interface IsUserIncludedApiResponse {
|
|
|
170
147
|
* The object holding all experiment-related information.
|
|
171
148
|
*/
|
|
172
149
|
entity: AssignedExperiments;
|
|
173
|
-
|
|
174
150
|
/**
|
|
175
151
|
* An array holding possible error messages.
|
|
176
152
|
*/
|
|
177
153
|
errors: string[];
|
|
178
|
-
|
|
179
154
|
/**
|
|
180
155
|
* A map that holds internationalization (i18n) messages.
|
|
181
156
|
*/
|
|
182
157
|
i18nMessagesMap: Record<string, string>;
|
|
183
|
-
|
|
184
158
|
/**
|
|
185
159
|
* An array of generic messages.
|
|
186
160
|
*/
|
|
187
161
|
messages: string[];
|
|
188
162
|
}
|
|
189
|
-
|
|
190
163
|
/**
|
|
191
164
|
* Represents a single experiment event.
|
|
192
165
|
*
|
|
@@ -197,33 +170,27 @@ export interface ExperimentEvent {
|
|
|
197
170
|
* The name or identifier of the experiment.
|
|
198
171
|
*/
|
|
199
172
|
experiment: string;
|
|
200
|
-
|
|
201
173
|
/**
|
|
202
174
|
* The unique running identifier of the experiment.
|
|
203
175
|
*/
|
|
204
176
|
runningId: string;
|
|
205
|
-
|
|
206
177
|
/**
|
|
207
178
|
* A flag that determines if the current page is the one where the experiment is conducted.
|
|
208
179
|
*/
|
|
209
180
|
isExperimentPage: boolean;
|
|
210
|
-
|
|
211
181
|
/**
|
|
212
182
|
* A flag that determines if the current page is the target page of the experiment.
|
|
213
183
|
*/
|
|
214
184
|
isTargetPage: boolean;
|
|
215
|
-
|
|
216
185
|
/**
|
|
217
186
|
* Represents the time period for which the experiment is valid or should be considered.
|
|
218
187
|
*/
|
|
219
188
|
lookBackWindow: string;
|
|
220
|
-
|
|
221
189
|
/**
|
|
222
190
|
* Represents the variant of the experiment to specify different versions of an experiment.
|
|
223
191
|
*/
|
|
224
192
|
variant: string;
|
|
225
193
|
}
|
|
226
|
-
|
|
227
194
|
/**
|
|
228
195
|
* Represents parsed data of an experiment that is ready to be sent to Analytics.
|
|
229
196
|
*
|
|
@@ -234,9 +201,9 @@ export interface ExperimentParsed {
|
|
|
234
201
|
* The URL of the experiment. It helps track the location or origin of the experiment.
|
|
235
202
|
*/
|
|
236
203
|
href: string;
|
|
237
|
-
|
|
238
204
|
/**
|
|
239
205
|
* An array holding details of individual experiments being conducted.
|
|
240
206
|
*/
|
|
241
207
|
experiments: ExperimentEvent[];
|
|
242
208
|
}
|
|
209
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Experiment, ExperimentParsed, FetchExperiments } from '../models';
|
|
2
|
+
/**
|
|
3
|
+
* This arrow function parses a given set of assigned experiments for analytics.
|
|
4
|
+
*
|
|
5
|
+
* This process involves iterating over the experiments, which are currently in the "Running" state as received from the DotCMS endpoint,
|
|
6
|
+
* analyzing each experiment's relevant data such as running ID, variant name, and look back window value.
|
|
7
|
+
* It also performs regular expression verification for both 'isExperimentPage' and 'isTargetPage' against the current URL.
|
|
8
|
+
*
|
|
9
|
+
* The parsed data is useful for tracking and understanding the user's interaction with the experiment-targeted components during their visit.
|
|
10
|
+
*
|
|
11
|
+
* Contains an object with experiments information.
|
|
12
|
+
*
|
|
13
|
+
* @param experiments
|
|
14
|
+
* @param {Location} location - This parameter is the object representing the current location (URL) of the user.
|
|
15
|
+
* Mostly employed for matching the regular expressions to detect whether the current page is an 'ExperimentPage' or a 'TargetPage'.
|
|
16
|
+
*
|
|
17
|
+
* @returns {ExperimentParsed} - The function returns an object with the original URL and an array of each experiment's comprehensive detail.
|
|
18
|
+
* The return object is suitable for further analytical operations. Each experiment's detail includes the experiment ID, running ID, variant name,
|
|
19
|
+
* look back window value, and booleans that represent whether current URL is 'isExperimentPage' or 'isTargetPage' for the respective experiment.
|
|
20
|
+
*/
|
|
21
|
+
export declare const parseDataForAnalytics: (experiments: Experiment[], location: Location) => ExperimentParsed;
|
|
22
|
+
/**
|
|
23
|
+
* This utility function performs regular expression (regex) matching on a supplied URL.
|
|
24
|
+
*
|
|
25
|
+
* @param {string | null} regexToCheck - The regular expression to match against the URL.
|
|
26
|
+
* @param {string} href - This is the target URL, which is aimed to be matched against the provided regular expression.
|
|
27
|
+
* @returns {boolean} -The function returns a Boolean value.
|
|
28
|
+
*/
|
|
29
|
+
export declare const verifyRegex: (regexToCheck: string | null, href: string) => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* This function merges newly fetched data with the data stored from IndexedDB, preparing it for re-storage in IndexedDB.
|
|
32
|
+
*
|
|
33
|
+
* @param { AssignedExperiments | null } fetchExperiments - The experiment data fetched from the API.
|
|
34
|
+
* @param { AssignedExperiments | null } storedExperiments - The experiment data currently stored in IndexedDB.
|
|
35
|
+
*
|
|
36
|
+
* @returns { AssignedExperiments } - The parsed experiment data ready for storing.
|
|
37
|
+
*
|
|
38
|
+
* Following cases are handled -
|
|
39
|
+
* 1) When new Data is received without Old data. This is assumed to be the first time data is received.
|
|
40
|
+
* 2) When only old data is received, implying that the timestamp hasn't expired and the data is available in IndexedDB.
|
|
41
|
+
* The data is verified and any expired experiment is removed before being assigned to dataToStorage.
|
|
42
|
+
* 3) When both old data and new data is present. This implies that the record existed in IndexedDB but was fetched because the flag had expired.
|
|
43
|
+
* Additional operations are performed to add expiry time to experiments, merging all experiments, and storing them.
|
|
44
|
+
*
|
|
45
|
+
* There could be scenarios where none of these conditions are met, in that case, dataToStorage will be the default empty object.
|
|
46
|
+
*/
|
|
47
|
+
export declare const parseData: (fetchExperiments: FetchExperiments, storedExperiments: Experiment[] | undefined) => Experiment[];
|
|
48
|
+
/**
|
|
49
|
+
* Retrieves the array of experiment IDs from the given AssignedExperiments..
|
|
50
|
+
*
|
|
51
|
+
* @returns {string[]} Returns an array of experiment IDs if available, otherwise an empty array.
|
|
52
|
+
* @param experiments
|
|
53
|
+
*/
|
|
54
|
+
export declare const getExperimentsIds: (experiments: Experiment[]) => string[];
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents the configuration for a database connection.
|
|
3
|
+
* @interface
|
|
4
|
+
*/
|
|
5
|
+
interface DbConfig {
|
|
6
|
+
db_name: string;
|
|
7
|
+
db_store: string;
|
|
8
|
+
db_key_path: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The `DatabaseHandler` class offers specific methods to store and get data
|
|
12
|
+
* from IndexedDB.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // To fetch data from the IndexedDB
|
|
16
|
+
* const data = await DatabaseHandler.getData();
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // To store an object of type AssignedExperiments to IndexedDB
|
|
20
|
+
* await DatabaseHandler.persistData(anAssignedExperiment);
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // To get an object of type AssignedExperiments to IndexedDB
|
|
24
|
+
* await DatabaseHandler.persistData(anAssignedExperiment);
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
export declare class IndexDBDatabaseHandler {
|
|
28
|
+
private config;
|
|
29
|
+
constructor(config: DbConfig);
|
|
30
|
+
/**
|
|
31
|
+
* Saves the provided data to indexDB.
|
|
32
|
+
*
|
|
33
|
+
* @async
|
|
34
|
+
* @param {AssignedExperiments} data - The data to be saved.
|
|
35
|
+
* @returns {Promise<any>} - The result of the save operation.
|
|
36
|
+
*/
|
|
37
|
+
persistData<T>(data: T): Promise<IDBValidKey>;
|
|
38
|
+
/**
|
|
39
|
+
* Retrieves data from the database using a specific key.
|
|
40
|
+
*
|
|
41
|
+
* @async
|
|
42
|
+
* @returns {Promise<any>} A promise that resolves with the data retrieved from the database.
|
|
43
|
+
*/
|
|
44
|
+
getData<T>(): Promise<T>;
|
|
45
|
+
/**
|
|
46
|
+
* Deletes all the data from the IndexedDB store.
|
|
47
|
+
*
|
|
48
|
+
* @async
|
|
49
|
+
* @returns {Promise<void>} - The result of the delete operation.
|
|
50
|
+
*/
|
|
51
|
+
clearData(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Sets the flag indicating that the experiment has already been checked.
|
|
54
|
+
*
|
|
55
|
+
* @function setFlagExperimentAlreadyChecked
|
|
56
|
+
* @returns {void}
|
|
57
|
+
*/
|
|
58
|
+
setFlagExperimentAlreadyChecked(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Sets the fetch expired time in the local storage.
|
|
61
|
+
*
|
|
62
|
+
* @return {void}
|
|
63
|
+
*/
|
|
64
|
+
setFetchExpiredTime(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Builds an error message based on the provided error object.
|
|
67
|
+
* @param {DOMException | null} error - The error object to build the message from.
|
|
68
|
+
* @returns {string} The constructed error message.
|
|
69
|
+
*/
|
|
70
|
+
private getOnErrorMessage;
|
|
71
|
+
/**
|
|
72
|
+
* Creates or opens a IndexedDB database with the specified version.
|
|
73
|
+
*
|
|
74
|
+
*
|
|
75
|
+
* @returns {Promise<IDBDatabase>} A promise that resolves to the opened database.
|
|
76
|
+
* The promise will be rejected with an error message if there was a database error.
|
|
77
|
+
*/
|
|
78
|
+
private openDB;
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves the result of a database request from an Event object.
|
|
81
|
+
*
|
|
82
|
+
* @param {Event} event - The Event object containing the database request.
|
|
83
|
+
* @returns {IDBDatabase} - The result of the database request, casted as an IDBDatabase object.
|
|
84
|
+
*/
|
|
85
|
+
private getRequestResult;
|
|
86
|
+
}
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger for the dotCMS SDK
|
|
3
|
+
*/
|
|
4
|
+
export declare class DotLogger {
|
|
5
|
+
private readonly isDebug;
|
|
6
|
+
private readonly packageName;
|
|
7
|
+
constructor(isDebug: boolean, packageName: string);
|
|
8
|
+
group(label: string): void;
|
|
9
|
+
groupEnd(): void;
|
|
10
|
+
time(label: string): void;
|
|
11
|
+
timeEnd(label: string): void;
|
|
12
|
+
log(message: string): void;
|
|
13
|
+
warn(message: string): void;
|
|
14
|
+
error(message: string): void;
|
|
15
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memoizes an object and returns the memoized object.
|
|
3
|
+
* Mantaing the same reference if the object is the same independently if is called inside any component.
|
|
4
|
+
* @param object
|
|
5
|
+
* @returns
|
|
6
|
+
*/
|
|
7
|
+
export declare function useMemoizedObject<T extends object>(object: T): T;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { DotExperimentConfig, Experiment, Variant } from '../models';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the first script element that includes the experiment script identifier.
|
|
4
|
+
*
|
|
5
|
+
* @return {HTMLScriptElement|undefined} - The found script element or undefined if none is found.
|
|
6
|
+
*/
|
|
7
|
+
export declare const getExperimentScriptTag: () => HTMLScriptElement;
|
|
8
|
+
/**
|
|
9
|
+
* Retrieves experiment attributes from a given script element.
|
|
10
|
+
*
|
|
11
|
+
*
|
|
12
|
+
* @return {DotExperimentConfig | null} - The experiment attributes or null if there are no valid attributes present.
|
|
13
|
+
*/
|
|
14
|
+
export declare const getDataExperimentAttributes: (location: Location) => DotExperimentConfig | null;
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves the data attributes from the experiment script tag.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* Given the custom script tag in your HTML:
|
|
20
|
+
* <script src="/dot-experiments.iife.js"
|
|
21
|
+
* defer=""
|
|
22
|
+
* data-experiment-api-key="api-token"
|
|
23
|
+
* data-experiment-server="http://localhost:8080/"
|
|
24
|
+
* data-experiment-debug>
|
|
25
|
+
* </script>
|
|
26
|
+
*
|
|
27
|
+
* @returns {DotExperimentConfig | null} The data attributes of the experiment script tag, or null if no experiment script is found.
|
|
28
|
+
*/
|
|
29
|
+
export declare const getScriptDataAttributes: (location: Location) => DotExperimentConfig | null;
|
|
30
|
+
/**
|
|
31
|
+
* Checks the flag indicating whether the experiment has already been checked.
|
|
32
|
+
*
|
|
33
|
+
* @function checkFlagExperimentAlreadyChecked
|
|
34
|
+
* @returns {boolean} - returns true if experiment has already been checked, otherwise false.
|
|
35
|
+
*/
|
|
36
|
+
export declare const checkFlagExperimentAlreadyChecked: () => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the data needs to be invalidated based on the creation date.
|
|
39
|
+
*
|
|
40
|
+
* @returns {boolean} - True if the data needs to be invalidated, false otherwise.
|
|
41
|
+
*/
|
|
42
|
+
export declare const isDataCreateValid: () => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Ad to an absolute path the baseUrl depending on the location.
|
|
45
|
+
*
|
|
46
|
+
* @param {string | null} absolutePath - The absolute path of the URL.
|
|
47
|
+
* @param {Location} location - The location object representing the current URL.
|
|
48
|
+
* @returns {string | null} - The full URL or null if absolutePath is null.
|
|
49
|
+
*/
|
|
50
|
+
export declare const getFullUrl: (location: Location, absolutePath: string | null) => string | null;
|
|
51
|
+
/**
|
|
52
|
+
* Updates the URL with the queryParam with the experiment variant name.
|
|
53
|
+
*
|
|
54
|
+
* @param {Location|string} location - The current location object or the URL string.
|
|
55
|
+
* @param {Variant} variant - The experiment variant to update the URL with.
|
|
56
|
+
* @returns {string} The updated URL string.
|
|
57
|
+
*/
|
|
58
|
+
export declare const updateUrlWithExperimentVariant: (location: Location | string, variant: Variant | null) => string;
|
|
59
|
+
/**
|
|
60
|
+
* Check if two arrays of Experiment objects are equal.
|
|
61
|
+
*
|
|
62
|
+
* @param {Experiment[]} obj1 - The first array of Experiment objects.
|
|
63
|
+
* @param {Experiment[]} obj2 - The second array of Experiment objects.
|
|
64
|
+
* @return {boolean} - True if the arrays are equal, false otherwise.
|
|
65
|
+
*/
|
|
66
|
+
export declare const objectsAreEqual: (obj1: Experiment[], obj2: Experiment[]) => boolean;
|
|
67
|
+
/**
|
|
68
|
+
* A function to redirect the user to a new URL.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} href - The URL to redirect to.
|
|
71
|
+
* @returns {void}
|
|
72
|
+
*/
|
|
73
|
+
export declare const defaultRedirectFn: (href: string) => string;
|
package/.babelrc
DELETED
package/.eslintrc.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": ["plugin:@nrwl/nx/react", "../../../.eslintrc.base.json"],
|
|
3
|
-
"ignorePatterns": ["!**/*"],
|
|
4
|
-
"overrides": [
|
|
5
|
-
{
|
|
6
|
-
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
|
7
|
-
"rules": {
|
|
8
|
-
"padding-line-between-statements": [
|
|
9
|
-
"error",
|
|
10
|
-
{ "blankLine": "always", "prev": "const", "next": "*" },
|
|
11
|
-
{ "blankLine": "always", "prev": "*", "next": "if" },
|
|
12
|
-
{ "blankLine": "always", "prev": "if", "next": "*" },
|
|
13
|
-
{ "blankLine": "always", "prev": "*", "next": "const" }
|
|
14
|
-
]
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"files": ["*.ts", "*.tsx"],
|
|
19
|
-
"rules": {}
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"files": ["*.js", "*.jsx"],
|
|
23
|
-
"rules": {}
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
}
|
package/jest.config.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
export default {
|
|
3
|
-
displayName: 'sdk-experiments',
|
|
4
|
-
preset: '../../../jest.preset.js',
|
|
5
|
-
transform: {
|
|
6
|
-
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
|
|
7
|
-
'^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nrwl/react/babel'] }]
|
|
8
|
-
},
|
|
9
|
-
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
|
10
|
-
coverageDirectory: '../../../coverage/libs/sdk/experiments'
|
|
11
|
-
};
|
package/project.json
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "sdk-experiments",
|
|
3
|
-
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "libs/sdk/experiments/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"targets": {
|
|
7
|
-
"build": {
|
|
8
|
-
"executor": "@nrwl/rollup:rollup",
|
|
9
|
-
"outputs": ["{options.outputPath}"],
|
|
10
|
-
"options": {
|
|
11
|
-
"outputPath": "dist/libs/sdk/experiments",
|
|
12
|
-
"tsConfig": "libs/sdk/experiments/tsconfig.lib.json",
|
|
13
|
-
"project": "libs/sdk/experiments/package.json",
|
|
14
|
-
"entryFile": "libs/sdk/experiments/src/index.ts",
|
|
15
|
-
"external": ["react/jsx-runtime"],
|
|
16
|
-
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
|
|
17
|
-
"compiler": "babel",
|
|
18
|
-
"assets": [
|
|
19
|
-
{
|
|
20
|
-
"glob": "libs/sdk/experiments/README.md",
|
|
21
|
-
"input": ".",
|
|
22
|
-
"output": "."
|
|
23
|
-
}
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"build:iife": {
|
|
28
|
-
"executor": "@nx/vite:build",
|
|
29
|
-
"outputs": ["{options.outputPath}"],
|
|
30
|
-
"options": {
|
|
31
|
-
"outputPath": "dist/libs/sdk/experiments/iife",
|
|
32
|
-
"main": "libs/sdk/experiments/src/lib/standalone.ts",
|
|
33
|
-
"tsConfig": "libs/sdk/experiments/tsconfig.lib.json"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"publish": {
|
|
37
|
-
"command": "node tools/scripts/publish.mjs sdk-experiments {args.ver} {args.tag}",
|
|
38
|
-
"outputPath": "dist/libs/sdk/experiments",
|
|
39
|
-
"dependsOn": ["build", "test"]
|
|
40
|
-
},
|
|
41
|
-
"nx-release-publish": {
|
|
42
|
-
"options": {
|
|
43
|
-
"packageRoot": "dist/libs/sdk/experiments"
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
"test": {
|
|
47
|
-
"executor": "@nx/jest:jest",
|
|
48
|
-
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
|
49
|
-
"options": {
|
|
50
|
-
"jestConfig": "libs/sdk/experiments/jest.config.ts"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
"tags": []
|
|
55
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { render, waitFor } from '@testing-library/react';
|
|
2
|
-
|
|
3
|
-
import * as dotcmsClient from '@dotcms/client';
|
|
4
|
-
|
|
5
|
-
import { DotExperimentsProvider } from './DotExperimentsProvider';
|
|
6
|
-
|
|
7
|
-
import { DotExperiments } from '../dot-experiments';
|
|
8
|
-
|
|
9
|
-
jest.mock('../dot-experiments');
|
|
10
|
-
jest.mock('@dotcms/client');
|
|
11
|
-
|
|
12
|
-
const mockDotExperimentsInstance = {
|
|
13
|
-
getInstance: jest.fn().mockResolvedValue(true),
|
|
14
|
-
ready: jest.fn().mockResolvedValue(true),
|
|
15
|
-
locationChanged: jest.fn().mockResolvedValue(true)
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
describe('DotExperimentsProvider', () => {
|
|
19
|
-
beforeEach(() => {
|
|
20
|
-
DotExperiments.getInstance = jest.fn().mockReturnValue(mockDotExperimentsInstance);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('initializes DotExperiments instance when not inside the editor', async () => {
|
|
24
|
-
const config = { apiKey: 'key', server: 'server', debug: true };
|
|
25
|
-
|
|
26
|
-
jest.spyOn(dotcmsClient, 'isInsideEditor').mockReturnValue(true);
|
|
27
|
-
|
|
28
|
-
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
|
|
29
|
-
|
|
30
|
-
render(
|
|
31
|
-
<DotExperimentsProvider config={config}>
|
|
32
|
-
<div>Test</div>
|
|
33
|
-
</DotExperimentsProvider>
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
await waitFor(() => expect(DotExperiments.getInstance).not.toHaveBeenCalled());
|
|
37
|
-
|
|
38
|
-
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
39
|
-
'DotExperimentsProvider: DotExperiments instance not initialized because it is inside the editor.'
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
consoleWarnSpy.mockRestore();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('initializes DotExperiments instance when is inside the editor', async () => {
|
|
46
|
-
const config = { apiKey: 'key', server: 'server', debug: true };
|
|
47
|
-
|
|
48
|
-
jest.spyOn(dotcmsClient, 'isInsideEditor').mockReturnValue(false);
|
|
49
|
-
|
|
50
|
-
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
|
|
51
|
-
|
|
52
|
-
render(
|
|
53
|
-
<DotExperimentsProvider config={config}>
|
|
54
|
-
<div>Test</div>
|
|
55
|
-
</DotExperimentsProvider>
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
await waitFor(() => expect(DotExperiments.getInstance).toHaveBeenCalled());
|
|
59
|
-
|
|
60
|
-
consoleWarnSpy.mockRestore();
|
|
61
|
-
});
|
|
62
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
2
|
-
import React, { ReactNode, useCallback } from 'react';
|
|
3
|
-
|
|
4
|
-
import { DotcmsPageProps } from '@dotcms/react';
|
|
5
|
-
|
|
6
|
-
import { DotExperimentHandlingComponent } from './DotExperimentHandlingComponent';
|
|
7
|
-
import { DotExperimentsProvider } from './DotExperimentsProvider';
|
|
8
|
-
|
|
9
|
-
import { DotExperimentConfig } from '../shared/models';
|
|
10
|
-
import { useMemoizedObject } from '../shared/utils/memoize';
|
|
11
|
-
|
|
12
|
-
export interface PageProviderProps {
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
-
readonly entity: any;
|
|
15
|
-
readonly children: ReactNode;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Wraps a given component with experiment handling capabilities using the 'useExperimentVariant' hook.
|
|
20
|
-
* This HOC checks if the entity's assigned experiment variant differs from the currently displayed variant.
|
|
21
|
-
* If they differ, the content is hidden until the correct variant is displayed. Once the assigned variant
|
|
22
|
-
* matches the displayed variant, the content of the WrappedComponent is shown.
|
|
23
|
-
*
|
|
24
|
-
* @param {React.ComponentType<DotcmsPageProps>} WrappedComponent - The component to be enhanced.
|
|
25
|
-
* @param {DotExperimentConfig} config - Configuration for experiment handling, including any necessary
|
|
26
|
-
* redirection functions or other settings.
|
|
27
|
-
* @returns {React.FunctionComponent<DotcmsPageProps>} A component that wraps the original component,
|
|
28
|
-
* adding experiment handling based on the specified configuration.
|
|
29
|
-
*/
|
|
30
|
-
export const withExperiments = (
|
|
31
|
-
WrappedComponent: React.ComponentType<DotcmsPageProps>,
|
|
32
|
-
config: DotExperimentConfig
|
|
33
|
-
) => {
|
|
34
|
-
// We need to use a custom memoization hook
|
|
35
|
-
// because the useMemo or React.memo lose the reference of the object
|
|
36
|
-
// in each render, causing the experiment handling to be reinitialized.
|
|
37
|
-
const memoizedConfig = useMemoizedObject(config);
|
|
38
|
-
|
|
39
|
-
return useCallback(
|
|
40
|
-
(props: DotcmsPageProps) => {
|
|
41
|
-
return (
|
|
42
|
-
<DotExperimentsProvider config={memoizedConfig}>
|
|
43
|
-
<DotExperimentHandlingComponent
|
|
44
|
-
{...props}
|
|
45
|
-
WrappedComponent={WrappedComponent}
|
|
46
|
-
/>
|
|
47
|
-
</DotExperimentsProvider>
|
|
48
|
-
);
|
|
49
|
-
},
|
|
50
|
-
[WrappedComponent, memoizedConfig]
|
|
51
|
-
);
|
|
52
|
-
};
|