@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.
Files changed (48) hide show
  1. package/index.esm.d.ts +1 -0
  2. package/index.esm.js +7174 -0
  3. package/package.json +10 -6
  4. package/src/lib/components/{DotExperimentHandlingComponent.tsx → DotExperimentHandlingComponent.d.ts} +3 -20
  5. package/src/lib/components/{DotExperimentsProvider.tsx → DotExperimentsProvider.d.ts} +3 -41
  6. package/src/lib/components/withExperiments.d.ts +20 -0
  7. package/src/lib/contexts/{DotExperimentsContext.tsx → DotExperimentsContext.d.ts} +2 -5
  8. package/src/lib/dot-experiments.d.ts +289 -0
  9. package/src/lib/hooks/useExperimentVariant.d.ts +21 -0
  10. package/src/lib/hooks/useExperiments.d.ts +14 -0
  11. package/src/lib/shared/{constants.ts → constants.d.ts} +18 -35
  12. package/src/lib/shared/mocks/mock.d.ts +43 -0
  13. package/src/lib/shared/{models.ts → models.d.ts} +2 -35
  14. package/src/lib/shared/parser/parser.d.ts +54 -0
  15. package/src/lib/shared/persistence/index-db-database-handler.d.ts +87 -0
  16. package/src/lib/shared/utils/DotLogger.d.ts +15 -0
  17. package/src/lib/shared/utils/memoize.d.ts +7 -0
  18. package/src/lib/shared/utils/utils.d.ts +73 -0
  19. package/src/lib/standalone.d.ts +7 -0
  20. package/.babelrc +0 -12
  21. package/.eslintrc.json +0 -26
  22. package/jest.config.ts +0 -11
  23. package/project.json +0 -55
  24. package/src/lib/components/DotExperimentsProvider.spec.tsx +0 -62
  25. package/src/lib/components/withExperiments.tsx +0 -52
  26. package/src/lib/contexts/DotExperimentsContext.spec.tsx +0 -42
  27. package/src/lib/dot-experiments.spec.ts +0 -285
  28. package/src/lib/dot-experiments.ts +0 -716
  29. package/src/lib/hooks/useExperimentVariant.spec.tsx +0 -111
  30. package/src/lib/hooks/useExperimentVariant.ts +0 -55
  31. package/src/lib/hooks/useExperiments.ts +0 -90
  32. package/src/lib/shared/mocks/mock.ts +0 -209
  33. package/src/lib/shared/parser/parse.spec.ts +0 -187
  34. package/src/lib/shared/parser/parser.ts +0 -171
  35. package/src/lib/shared/persistence/index-db-database-handler.spec.ts +0 -100
  36. package/src/lib/shared/persistence/index-db-database-handler.ts +0 -218
  37. package/src/lib/shared/utils/DotLogger.ts +0 -57
  38. package/src/lib/shared/utils/memoize.spec.ts +0 -49
  39. package/src/lib/shared/utils/memoize.ts +0 -49
  40. package/src/lib/shared/utils/utils.spec.ts +0 -142
  41. package/src/lib/shared/utils/utils.ts +0 -203
  42. package/src/lib/standalone.spec.ts +0 -36
  43. package/src/lib/standalone.ts +0 -28
  44. package/tsconfig.json +0 -20
  45. package/tsconfig.lib.json +0 -20
  46. package/tsconfig.spec.json +0 -9
  47. package/vite.config.ts +0 -41
  48. /package/src/{index.ts → index.d.ts} +0 -0
@@ -1,42 +0,0 @@
1
- import { renderHook } from '@testing-library/react-hooks';
2
- import { ReactNode, useContext } from 'react';
3
-
4
- import DotExperimentsContext from './DotExperimentsContext';
5
-
6
- import { DotExperiments } from '../dot-experiments';
7
-
8
- jest.mock('../dot-experiments', () => {
9
- return jest.fn().mockImplementation(() => {
10
- return {};
11
- });
12
- });
13
-
14
- describe('useDotExperimentsContext', () => {
15
- it('returns the context value null', () => {
16
- const mockContextValue = null;
17
-
18
- const { result } = renderHook(() => useContext(DotExperimentsContext), {
19
- wrapper: ({ children }: { children: ReactNode }) => (
20
- <DotExperimentsContext.Provider value={mockContextValue}>
21
- {children}
22
- </DotExperimentsContext.Provider>
23
- )
24
- });
25
-
26
- expect(result.current).toEqual(mockContextValue);
27
- });
28
-
29
- it('returns the context value DotExperiment', () => {
30
- const mockContextValue = {} as DotExperiments;
31
-
32
- const { result } = renderHook(() => useContext(DotExperimentsContext), {
33
- wrapper: ({ children }: { children: ReactNode }) => (
34
- <DotExperimentsContext.Provider value={mockContextValue}>
35
- {children}
36
- </DotExperimentsContext.Provider>
37
- )
38
- });
39
-
40
- expect(result.current).toEqual(mockContextValue);
41
- });
42
- });
@@ -1,285 +0,0 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
2
- import fakeIndexedDB from 'fake-indexeddb';
3
- import fetchMock from 'fetch-mock';
4
-
5
- import { DotExperiments } from './dot-experiments';
6
- import { API_EXPERIMENTS_URL, EXPERIMENT_QUERY_PARAM_KEY } from './shared/constants';
7
- import {
8
- After15DaysIsUserIncludedResponse,
9
- IsUserIncludedResponse,
10
- LocationMock,
11
- MOCK_CURRENT_TIMESTAMP,
12
- MockDataStoredIndexDB,
13
- MockDataStoredIndexDBWithNew,
14
- MockDataStoredIndexDBWithNew15DaysLater,
15
- NewIsUserIncludedResponse,
16
- NoExperimentsIsUserIncludedResponse,
17
- sessionStorageMock,
18
- TIME_15_DAYS_MILLISECONDS,
19
- TIME_5_DAYS_MILLISECONDS
20
- } from './shared/mocks/mock';
21
- import { DotExperimentConfig } from './shared/models';
22
-
23
- jest.spyOn(Date, 'now').mockImplementation(() => MOCK_CURRENT_TIMESTAMP);
24
-
25
- // Jitsu SDK Mock
26
- jest.mock('@jitsu/sdk-js', () => ({
27
- jitsuClient: jest.fn(() => ({
28
- set: jest.fn(),
29
- track: jest.fn().mockResolvedValue(true)
30
- }))
31
- }));
32
-
33
- // SessionStorage mock
34
- global.sessionStorage = sessionStorageMock;
35
-
36
- // IndexDB Mock
37
- Object.defineProperty(window, 'indexedDB', {
38
- writable: true,
39
- value: fakeIndexedDB
40
- });
41
-
42
- if (!globalThis.structuredClone) {
43
- globalThis.structuredClone = function (obj) {
44
- return JSON.parse(JSON.stringify(obj));
45
- };
46
- }
47
-
48
- // Windows Mock
49
- global.window = Object.create(window);
50
- Object.defineProperty(window, 'location', {
51
- value: {
52
- href: 'http://localhost:8080/',
53
- origin: 'http://localhost:8080'
54
- }
55
- });
56
-
57
- describe('DotExperiments', () => {
58
- const configMock: DotExperimentConfig = {
59
- apiKey: 'yourApiKey',
60
- server: 'http://localhost:8080/',
61
- debug: false,
62
- trackPageView: true
63
- };
64
-
65
- describe('DotExperiments Instance and Initialization', () => {
66
- beforeEach(() => {
67
- // destroy the instance of the singleton
68
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
- (DotExperiments as any).instance = null;
70
- });
71
- it('should throw an error if config is not provided', () => {
72
- expect(() => DotExperiments.getInstance()).toThrow(
73
- 'Configuration is required to create a new instance.'
74
- );
75
- });
76
-
77
- it('should instantiate the class when getInstance is called with config', () => {
78
- const dotExperimentsInstance = DotExperiments.getInstance(configMock);
79
-
80
- expect(dotExperimentsInstance).toBeInstanceOf(DotExperiments);
81
- });
82
-
83
- it('should throw an error if server is not provided in config', () => {
84
- expect(() =>
85
- // @ts-ignore
86
- DotExperiments.getInstance({ 'api-key': 'api-key-test', debug: true })
87
- ).toThrow('`server` must be provided and should not be empty!');
88
- });
89
-
90
- it('should throw an error if api-key is not provided in config', () => {
91
- expect(() =>
92
- // @ts-ignore
93
- DotExperiments.getInstance({ server: 'http://server-test.com', debug: true })
94
- ).toThrow('`apiKey` must be provided and should not be empty!');
95
- });
96
-
97
- it('should return false if the debug inactive', async () => {
98
- const instance = DotExperiments.getInstance(configMock);
99
-
100
- expect(instance.getIsDebugActive()).toBe(false);
101
- });
102
-
103
- it('should not call to trackPageView if you send the flag', async () => {
104
- const config: DotExperimentConfig = { ...configMock, trackPageView: false };
105
-
106
- fetchMock.post(`${configMock.server}/${API_EXPERIMENTS_URL}`, {
107
- status: 200,
108
- body: IsUserIncludedResponse,
109
- headers: {
110
- Accept: 'application/json',
111
- 'Content-Type': 'application/json'
112
- }
113
- });
114
-
115
- const instance = DotExperiments.getInstance(config);
116
-
117
- const spyTrackPageView = jest.spyOn(instance, 'trackPageView');
118
-
119
- expect(spyTrackPageView).not.toHaveBeenCalled();
120
-
121
- await instance.locationChanged(LocationMock).then(() => {
122
- expect(spyTrackPageView).not.toHaveBeenCalled();
123
- });
124
- });
125
-
126
- it('should not call to trackPageView if you dont have experiment to track', async () => {
127
- const config: DotExperimentConfig = { ...configMock, trackPageView: false };
128
-
129
- fetchMock.post(
130
- `${configMock.server}/${API_EXPERIMENTS_URL}`,
131
- {
132
- status: 200,
133
- body: NoExperimentsIsUserIncludedResponse,
134
- headers: {
135
- Accept: 'application/json',
136
- 'Content-Type': 'application/json'
137
- }
138
- },
139
- { overwriteRoutes: true }
140
- );
141
-
142
- const instance = DotExperiments.getInstance(config);
143
-
144
- const spyTrackPageView = jest.spyOn(instance, 'trackPageView');
145
-
146
- expect(spyTrackPageView).not.toHaveBeenCalled();
147
-
148
- await instance.locationChanged(LocationMock).then(() => {
149
- expect(spyTrackPageView).not.toHaveBeenCalled();
150
- });
151
- });
152
-
153
- it('should return a a string with the query params of variant by the url given', async () => {
154
- const config: DotExperimentConfig = { ...configMock, trackPageView: false };
155
-
156
- fetchMock.post(
157
- `${configMock.server}/${API_EXPERIMENTS_URL}`,
158
- {
159
- status: 200,
160
- body: IsUserIncludedResponse,
161
- headers: {
162
- Accept: 'application/json',
163
- 'Content-Type': 'application/json'
164
- }
165
- },
166
- { overwriteRoutes: true }
167
- );
168
-
169
- const instance = DotExperiments.getInstance(config);
170
-
171
- await instance.ready();
172
-
173
- const EMPTY_URL = '';
174
-
175
- const expected1 = new URLSearchParams({});
176
-
177
- expect(instance.getVariantAsQueryParam(EMPTY_URL)).toStrictEqual(expected1);
178
-
179
- const URL_WITH_EXPERIMENT = '/blog';
180
-
181
- const expected2 = new URLSearchParams({
182
- [EXPERIMENT_QUERY_PARAM_KEY]:
183
- IsUserIncludedResponse.entity.experiments[0].variant.name
184
- });
185
-
186
- expect(instance.getVariantAsQueryParam(URL_WITH_EXPERIMENT)).toStrictEqual(expected2);
187
-
188
- const URL_NO_EXPERIMENT = '/destinations';
189
-
190
- const expected3 = new URLSearchParams({});
191
-
192
- expect(instance.getVariantAsQueryParam(URL_NO_EXPERIMENT)).toStrictEqual(expected3);
193
- });
194
- });
195
-
196
- describe('Class interactions', () => {
197
- beforeEach(() => {
198
- fetchMock.restore();
199
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
200
- (DotExperiments as any).instance = null;
201
- });
202
-
203
- it('should simulate the changes of the data in first run, after 5 days and 15 days.', async () => {
204
- // First time the user enter to the page
205
-
206
- fetchMock.post(`${configMock.server}/${API_EXPERIMENTS_URL}`, {
207
- status: 200,
208
- body: IsUserIncludedResponse,
209
- headers: {
210
- Accept: 'application/json',
211
- 'Content-Type': 'application/json'
212
- }
213
- });
214
-
215
- const instance = DotExperiments.getInstance(configMock);
216
-
217
- const spyTrackPageView = jest.spyOn(instance, 'trackPageView');
218
-
219
- await instance.ready().then(() => {
220
- const experiments = instance.experiments;
221
-
222
- expect(experiments.length).toBe(1);
223
- expect(experiments).toEqual(MockDataStoredIndexDB);
224
-
225
- expect(spyTrackPageView).toBeCalledTimes(1);
226
- });
227
-
228
- // Second time the user enter to the page
229
- // change the time 5 days later
230
- jest.spyOn(Date, 'now').mockImplementation(
231
- () => MOCK_CURRENT_TIMESTAMP + TIME_5_DAYS_MILLISECONDS
232
- );
233
-
234
- fetchMock.post(
235
- `${configMock.server}/${API_EXPERIMENTS_URL}`,
236
- {
237
- status: 200,
238
- body: NewIsUserIncludedResponse,
239
- headers: {
240
- Accept: 'application/json',
241
- 'Content-Type': 'application/json'
242
- }
243
- },
244
- { overwriteRoutes: true }
245
- );
246
-
247
- await instance.locationChanged(LocationMock).then(() => {
248
- // get the experiments stored in the indexDB
249
- const experiments = instance.experiments;
250
-
251
- expect(experiments.length).toBe(1);
252
- expect(experiments).toEqual(MockDataStoredIndexDBWithNew);
253
- expect(spyTrackPageView).toBeCalledTimes(2);
254
- });
255
-
256
- fetchMock.post(
257
- `${configMock.server}/${API_EXPERIMENTS_URL}`,
258
- {
259
- status: 200,
260
- body: After15DaysIsUserIncludedResponse,
261
- headers: {
262
- Accept: 'application/json',
263
- 'Content-Type': 'application/json'
264
- }
265
- },
266
- { overwriteRoutes: true }
267
- );
268
-
269
- // Third try, after 15 days
270
- const location = { ...LocationMock, href: 'http://localhost/destinations' };
271
-
272
- jest.spyOn(Date, 'now').mockImplementation(
273
- () => MOCK_CURRENT_TIMESTAMP + TIME_15_DAYS_MILLISECONDS
274
- );
275
- await instance.locationChanged(location).then(() => {
276
- // get the experiments stored in the indexDB
277
- const experiments = instance.experiments;
278
-
279
- expect(experiments.length).toBe(1);
280
- expect(experiments).toEqual(MockDataStoredIndexDBWithNew15DaysLater);
281
- expect(spyTrackPageView).toBeCalledTimes(3);
282
- });
283
- });
284
- });
285
- });