@fullstory/browser 2.0.6 → 2.0.8

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/index.d.ts CHANGED
@@ -11,6 +11,7 @@ import { FSApi } from '@fullstory/snippet';
11
11
  * - recordCrossDomainIFrames: FullStory can record cross-domain iFrames. Defaults to `false`. Certain limitations apply and can be found [here](https://help.fullstory.com/hc/en-us/articles/360020622514-Can-FullStory-capture-content-that-is-presented-in-iframes-#h_01F1G333PYKPGZ4B42WDBV3YKV).
12
12
  * - recordOnlyThisIFrame: FullStory can record the iFrame as its own unique session. Defaults to `false`. Additional conditions apply and can be found [here](https://help.fullstory.com/hc/en-us/articles/360020622514-Can-FullStory-capture-content-that-is-presented-in-iframes-#h_01F1G33B40Q2TPQA8MA7SF8Y5P).
13
13
  * - devMode: In dev mode FullStory won't record sessions. Any calls to SDK methods will `console.warn` that FullStory is in `devMode`. Defaults to `false`.
14
+ * - sessionUid (beta): Sets the session UID passed to the `FS('init', ...)` v2 operation.
14
15
  */
15
16
  export interface SnippetOptions {
16
17
  orgId: string;
@@ -23,6 +24,7 @@ export interface SnippetOptions {
23
24
  namespace?: string;
24
25
  recordCrossDomainIFrames?: boolean;
25
26
  recordOnlyThisIFrame?: boolean;
27
+ sessionUid?: string;
26
28
  script?: string;
27
29
  startCaptureManually?: boolean;
28
30
  }
@@ -53,7 +55,7 @@ declare global {
53
55
  _fs_script?: string;
54
56
  }
55
57
  }
56
- export declare const init: (inputOptions: SnippetOptions, readyCallback?: ReadyCallback) => void;
57
- export declare const isInitialized: () => boolean;
58
- export declare const FullStory: FSApi;
59
- export {};
58
+ declare const init: (inputOptions: SnippetOptions, readyCallback?: ReadyCallback) => void;
59
+ declare const isInitialized: () => boolean;
60
+ declare const FullStory: FSApi;
61
+ export { FullStory, init, isInitialized };
package/dist/index.esm.js CHANGED
@@ -83,6 +83,9 @@ var _init = function (inputOptions, readyCallback) {
83
83
  console.warn('Failed to initialize FS snippet');
84
84
  return;
85
85
  }
86
+ if (options.sessionUid) {
87
+ fs('init', { env: { sessionUid: options.sessionUid } });
88
+ }
86
89
  if (readyCallback) {
87
90
  fs('observe', { type: 'start', callback: readyCallback });
88
91
  }
package/dist/index.js CHANGED
@@ -85,6 +85,9 @@ var _init = function (inputOptions, readyCallback) {
85
85
  console.warn('Failed to initialize FS snippet');
86
86
  return;
87
87
  }
88
+ if (options.sessionUid) {
89
+ fs('init', { env: { sessionUid: options.sessionUid } });
90
+ }
88
91
  if (readyCallback) {
89
92
  fs('observe', { type: 'start', callback: readyCallback });
90
93
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fullstory/browser",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
4
  "description": "The official Fullstory browser SDK",
5
5
  "repository": "git://github.com/fullstorydev/fullstory-browser-sdk.git",
6
6
  "homepage": "https://github.com/fullstorydev/fullstory-browser-sdk",
@@ -11,8 +11,7 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "scripts": {
13
13
  "clean": "rimraf dist",
14
- "pretest": "tsc --project tsconfig.test.json",
15
- "test": "npm run lint && karma start --single-run --browsers ChromeHeadless karma.conf.js",
14
+ "test": "npm run lint && jest",
16
15
  "lint": "eslint src",
17
16
  "build": "rollup -c"
18
17
  },
@@ -26,7 +25,7 @@
26
25
  "sdk"
27
26
  ],
28
27
  "dependencies": {
29
- "@fullstory/snippet": "2.0.5"
28
+ "@fullstory/snippet": "2.0.6"
30
29
  },
31
30
  "devDependencies": {
32
31
  "@babel/core": "^7.8.7",
@@ -34,26 +33,20 @@
34
33
  "@babel/preset-env": "^7.10.4",
35
34
  "@babel/register": "^7.8.6",
36
35
  "@rollup/plugin-typescript": "^11.1.0",
37
- "@types/chai": "^4.3.4",
38
- "@types/mocha": "^10.0.1",
36
+ "@types/jest": "^29.5.0",
39
37
  "@types/node": "^18.15.11",
40
38
  "@typescript-eslint/eslint-plugin": "^5.58.0",
41
39
  "@typescript-eslint/parser": "^5.58.0",
42
- "chai": "^4.1.2",
43
40
  "eslint": "^8.6.0",
44
41
  "eslint-config-airbnb": "^19.0.4",
45
42
  "eslint-plugin-import": "^2.20.1",
46
43
  "eslint-plugin-jsx-a11y": "^6.5.1",
47
44
  "eslint-plugin-react": "^7.28.0",
48
- "karma": "^6.4.2",
49
- "karma-chai": "^0.1.0",
50
- "karma-chrome-launcher": "^3.1.0",
51
- "karma-mocha": "^2.0.1",
52
- "karma-spec-reporter": "0.0.32",
53
- "karma-webpack": "^5.0.0",
54
- "mocha": "^9.2.0",
45
+ "jest": "^29.7.0",
46
+ "jest-environment-jsdom": "^30.3.0",
55
47
  "rimraf": "^2.7.1",
56
48
  "rollup": "^3.21.0",
49
+ "ts-jest": "^29.1.0",
57
50
  "tslib": "^2.5.0",
58
51
  "typescript": "^4.2.4",
59
52
  "webpack": "^5.76.1"
package/src/index.test.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { assert, expect } from 'chai';
2
1
  import {
3
2
  FullStory as FS,
4
3
  init,
@@ -19,23 +18,23 @@ beforeEach(() => {
19
18
 
20
19
  describe('init', () => {
21
20
  it('should throw error if not initialized with an orgId', () => {
22
- expect(() => { init({} as SnippetOptions); }).to.throw();
21
+ expect(() => { init({} as SnippetOptions); }).toThrow();
23
22
  });
24
23
 
25
24
  it('should throw error if API called before init', () => {
26
25
  try {
27
26
  FS('log', { msg: 'my log' });
28
- expect(false).to.be('this should have thrown');
27
+ throw new Error('this should have thrown');
29
28
  } catch (error) {
30
- expect((error as Error).message).to.match(/FullStory is not loaded/);
29
+ expect((error as Error).message).toMatch(/FullStory is not loaded/);
31
30
  }
32
31
  init({ orgId: testOrg });
33
- expect(() => { FS('log', { msg: 'my log' }); }).to.not.throw();
32
+ expect(() => { FS('log', { msg: 'my log' }); }).not.toThrow();
34
33
  });
35
34
 
36
35
  it('should add _fs_org value to window object', () => {
37
36
  init({ orgId: testOrg });
38
- expect(window._fs_org).to.equal(testOrg);
37
+ expect(window._fs_org).toBe(testOrg);
39
38
  });
40
39
 
41
40
  it('should add _fs_run_in_iframe value to window object', () => {
@@ -43,7 +42,7 @@ describe('init', () => {
43
42
  orgId: testOrg,
44
43
  recordCrossDomainIFrames: true,
45
44
  });
46
- expect(window._fs_run_in_iframe).to.equal(true);
45
+ expect(window._fs_run_in_iframe).toBe(true);
47
46
  });
48
47
 
49
48
  it('should add _fs_is_outer_script value to window object', () => {
@@ -51,7 +50,7 @@ describe('init', () => {
51
50
  orgId: testOrg,
52
51
  recordOnlyThisIFrame: true,
53
52
  });
54
- expect(window._fs_is_outer_script).to.equal(true);
53
+ expect(window._fs_is_outer_script).toBe(true);
55
54
  });
56
55
 
57
56
  it('should add _fs_dev_mode value to window when initialized with devMode', () => {
@@ -60,19 +59,19 @@ describe('init', () => {
60
59
  devMode: true,
61
60
  });
62
61
 
63
- expect(window._fs_dev_mode).to.equal(true);
62
+ expect(window._fs_dev_mode).toBe(true);
64
63
  });
65
64
 
66
65
  it('should return whether initialized', () => {
67
66
  let isInit = isInitialized();
68
- expect(isInit).to.equal(false);
67
+ expect(isInit).toBe(false);
69
68
 
70
69
  init({
71
70
  orgId: testOrg,
72
71
  });
73
72
 
74
73
  isInit = isInitialized();
75
- expect(isInit).to.equal(true);
74
+ expect(isInit).toBe(true);
76
75
  });
77
76
 
78
77
  it('should load fs-debug.js when debug is set', () => {
@@ -81,7 +80,22 @@ describe('init', () => {
81
80
  debug: true,
82
81
  });
83
82
 
84
- expect(window._fs_script).to.match(/fs-debug.js$/);
83
+ expect(window._fs_script).toMatch(/fs-debug.js$/);
84
+ });
85
+
86
+ it('should pass sessionUid to FS init', () => {
87
+ const sessionUid = 'session-123';
88
+
89
+ init({
90
+ orgId: testOrg,
91
+ sessionUid,
92
+ });
93
+
94
+ const queue = (window[window._fs_namespace ?? 'FS'] as unknown as { q?: unknown[][] }).q;
95
+ const initCall = queue?.find((call) => call[0] === 'init');
96
+ const initOptions = initCall?.[1] as { env?: { sessionUid?: string } } | undefined;
97
+
98
+ expect(initOptions?.env?.sessionUid).toBe(sessionUid);
85
99
  });
86
100
  });
87
101
 
@@ -98,17 +112,17 @@ describe('devMode', () => {
98
112
  });
99
113
 
100
114
  it('should return a message for functions invoked when in devMode', () => {
101
- expect(consoleWarnedMessage).to.equal(undefined);
115
+ expect(consoleWarnedMessage).toBeUndefined();
102
116
  init({
103
117
  orgId: testOrg,
104
118
  devMode: true,
105
119
  });
106
120
 
107
- expect(consoleWarnedMessage).to.match(/FullStory was initialized in devMode/);
121
+ expect(consoleWarnedMessage).toMatch(/FullStory was initialized in devMode/);
108
122
 
109
123
  FS('log', { msg: 'hello world' });
110
124
 
111
- expect(consoleWarnedMessage).to.equal('FullStory is in dev mode and is not capturing: log not executed');
125
+ expect(consoleWarnedMessage).toBe('FullStory is in dev mode and is not capturing: log not executed');
112
126
  });
113
127
  });
114
128
 
@@ -118,11 +132,7 @@ describe('getCurrentSessionURL', () => {
118
132
  // in theory, this is a race condition - assuming that fs.js
119
133
  // can't load by the time the following statement is executed
120
134
  const url = FS('getSession');
121
- assert.equal(
122
- url,
123
- null,
124
- 'FullStory.getCurrentSessionURL() should return null if executed before fs.js is fully bootstrapped'
125
- );
135
+ expect(url).toBeNull();
126
136
  });
127
137
  });
128
138
 
@@ -177,7 +187,7 @@ describe('typescript safety', () => {
177
187
  FS.event(42, { product_id: 'asdf' });
178
188
 
179
189
  // Assertion for posterity's sake...
180
- expect(true).to.equal(true);
190
+ expect(true).toBe(true);
181
191
  });
182
192
 
183
193
  it('allows the optional "source" param', () => {
@@ -212,7 +222,7 @@ describe('typescript safety', () => {
212
222
  });
213
223
 
214
224
  // NOTE: don't run this test, it will hang since fs.js isn't really running. It's only for typescript safety checks.
215
- xit('provides type assistance for the async api', async () => {
225
+ it.skip('provides type assistance for the async api', async () => {
216
226
  init({ orgId: testOrg });
217
227
 
218
228
  const disconnector = await FS('observeAsync', { type: 'start', callback: () => console.log('STARTED') });
@@ -220,7 +230,6 @@ describe('typescript safety', () => {
220
230
  disconnector.disconnect();
221
231
 
222
232
  const url = await FS('getSessionAsync');
223
-
224
- console.log(url.trim());
233
+ expect(url === null || typeof url === 'string' || typeof url === 'object').toBe(true); // type-check only
225
234
  });
226
235
  });
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ import { initFS, FSApi } from '@fullstory/snippet';
12
12
  * - recordCrossDomainIFrames: FullStory can record cross-domain iFrames. Defaults to `false`. Certain limitations apply and can be found [here](https://help.fullstory.com/hc/en-us/articles/360020622514-Can-FullStory-capture-content-that-is-presented-in-iframes-#h_01F1G333PYKPGZ4B42WDBV3YKV).
13
13
  * - recordOnlyThisIFrame: FullStory can record the iFrame as its own unique session. Defaults to `false`. Additional conditions apply and can be found [here](https://help.fullstory.com/hc/en-us/articles/360020622514-Can-FullStory-capture-content-that-is-presented-in-iframes-#h_01F1G33B40Q2TPQA8MA7SF8Y5P).
14
14
  * - devMode: In dev mode FullStory won't record sessions. Any calls to SDK methods will `console.warn` that FullStory is in `devMode`. Defaults to `false`.
15
+ * - sessionUid (beta): Sets the session UID passed to the `FS('init', ...)` v2 operation.
15
16
  */
16
17
  export interface SnippetOptions {
17
18
  orgId: string;
@@ -24,6 +25,7 @@ export interface SnippetOptions {
24
25
  namespace?: string;
25
26
  recordCrossDomainIFrames?: boolean;
26
27
  recordOnlyThisIFrame?: boolean;
28
+ sessionUid?: string;
27
29
  script?: string;
28
30
  startCaptureManually?: boolean;
29
31
  }
@@ -124,6 +126,10 @@ const _init = (inputOptions: SnippetOptions, readyCallback?: ReadyCallback) => {
124
126
  return;
125
127
  }
126
128
 
129
+ if (options.sessionUid) {
130
+ fs('init', { env: { sessionUid: options.sessionUid } });
131
+ }
132
+
127
133
  if (readyCallback) {
128
134
  fs('observe', { type: 'start', callback: readyCallback });
129
135
  }
@@ -151,10 +157,10 @@ const initOnce = (message) => (inputOptions: SnippetOptions, readyCallback?: Rea
151
157
  window._fs_initialized = true;
152
158
  };
153
159
 
154
- export const init = initOnce('FullStory init has already been called once, additional invocations are ignored');
160
+ const init = initOnce('FullStory init has already been called once, additional invocations are ignored');
155
161
 
156
162
  // normalize undefined into boolean
157
- export const isInitialized = () => !!window._fs_initialized;
163
+ const isInitialized = () => !!window._fs_initialized;
158
164
 
159
165
  const hasFullStoryWithFunction = (...testNames) => {
160
166
  const fs = ensureSnippetLoaded();
@@ -201,7 +207,9 @@ const buildFullStoryShim = (): FSApi => {
201
207
  FS.setVars = guard('setVars');
202
208
  FS.shutdown = guard('shutdown');
203
209
 
204
- return FS;
210
+ return FS as FSApi;
205
211
  };
206
212
 
207
- export const FullStory: FSApi = buildFullStoryShim();
213
+ const FullStory: FSApi = buildFullStoryShim();
214
+
215
+ export { FullStory, init, isInitialized };