@newrelic/browser-agent 1.242.0 → 1.243.1

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 (111) hide show
  1. package/CHANGELOG.md +1472 -0
  2. package/dist/cjs/common/constants/env.cdn.js +1 -1
  3. package/dist/cjs/common/constants/env.npm.js +1 -1
  4. package/dist/cjs/common/session/session-entity.js +20 -2
  5. package/dist/cjs/common/wrap/wrap-function.js +1 -1
  6. package/dist/cjs/features/ajax/aggregate/index.js +1 -1
  7. package/dist/cjs/features/session_replay/aggregate/index.js +89 -53
  8. package/dist/cjs/features/utils/feature-base.js +1 -2
  9. package/dist/cjs/loaders/api/api.js +2 -2
  10. package/dist/cjs/loaders/api/apiAsync.js +0 -37
  11. package/dist/cjs/loaders/configure/configure.js +1 -1
  12. package/dist/cjs/loaders/configure/public-path.js +6 -3
  13. package/dist/esm/common/constants/env.cdn.js +1 -1
  14. package/dist/esm/common/constants/env.npm.js +1 -1
  15. package/dist/esm/common/session/session-entity.js +18 -1
  16. package/dist/esm/common/wrap/wrap-function.js +1 -1
  17. package/dist/esm/features/ajax/aggregate/index.js +1 -1
  18. package/dist/esm/features/session_replay/aggregate/index.js +88 -53
  19. package/dist/esm/features/utils/feature-base.js +1 -2
  20. package/dist/esm/loaders/api/api.js +2 -2
  21. package/dist/esm/loaders/api/apiAsync.js +1 -36
  22. package/dist/esm/loaders/configure/configure.js +1 -1
  23. package/dist/esm/loaders/configure/public-path.js +6 -3
  24. package/dist/types/common/session/session-entity.d.ts +5 -0
  25. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  26. package/dist/types/features/session_replay/aggregate/index.d.ts +11 -14
  27. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  28. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  29. package/dist/types/loaders/api/api.d.ts.map +1 -1
  30. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  31. package/dist/types/loaders/configure/public-path.d.ts +1 -1
  32. package/dist/types/loaders/configure/public-path.d.ts.map +1 -1
  33. package/package.json +2 -2
  34. package/src/common/session/session-entity.js +20 -1
  35. package/src/common/wrap/wrap-function.js +1 -1
  36. package/src/features/ajax/aggregate/index.js +2 -2
  37. package/src/features/session_replay/aggregate/index.js +86 -36
  38. package/src/features/utils/feature-base.js +1 -2
  39. package/src/loaders/api/api.js +1 -2
  40. package/src/loaders/api/apiAsync.js +1 -39
  41. package/src/loaders/configure/configure.js +1 -1
  42. package/src/loaders/configure/public-path.js +6 -3
  43. package/src/common/aggregate/aggregator.test.js +0 -107
  44. package/src/common/config/state/configurable.test.js +0 -73
  45. package/src/common/config/state/info.test.js +0 -31
  46. package/src/common/config/state/init.test.js +0 -68
  47. package/src/common/config/state/loader-config.test.js +0 -21
  48. package/src/common/config/state/runtime.test.js +0 -21
  49. package/src/common/constants/env.cdn.test.js +0 -7
  50. package/src/common/constants/env.npm.test.js +0 -7
  51. package/src/common/constants/env.test.js +0 -7
  52. package/src/common/constants/runtime.test.js +0 -176
  53. package/src/common/deny-list/deny-list.test.js +0 -104
  54. package/src/common/dom/query-selector.test.js +0 -24
  55. package/src/common/drain/drain.test.js +0 -74
  56. package/src/common/event-emitter/contextual-ee.component-test.js +0 -293
  57. package/src/common/event-emitter/handle.test.js +0 -56
  58. package/src/common/event-emitter/register-handler.test.js +0 -61
  59. package/src/common/harvest/harvest-scheduler.test.js +0 -492
  60. package/src/common/harvest/harvest.test.js +0 -813
  61. package/src/common/ids/id.test.js +0 -92
  62. package/src/common/ids/unique-id.test.js +0 -58
  63. package/src/common/session/session-entity.component-test.js +0 -346
  64. package/src/common/storage/local-storage.test.js +0 -17
  65. package/src/common/timer/interaction-timer.component-test.js +0 -212
  66. package/src/common/timer/timer.test.js +0 -99
  67. package/src/common/timing/nav-timing.test.js +0 -161
  68. package/src/common/url/canonicalize-url.test.js +0 -45
  69. package/src/common/url/clean-url.test.js +0 -25
  70. package/src/common/url/encode.test.js +0 -81
  71. package/src/common/url/location.test.js +0 -15
  72. package/src/common/url/parse-url.test.js +0 -110
  73. package/src/common/url/protocol.test.js +0 -17
  74. package/src/common/util/console.test.js +0 -34
  75. package/src/common/util/data-size.test.js +0 -56
  76. package/src/common/util/feature-flags.test.js +0 -94
  77. package/src/common/util/get-or-set.test.js +0 -58
  78. package/src/common/util/invoke.test.js +0 -65
  79. package/src/common/util/map-own.test.js +0 -52
  80. package/src/common/util/obfuscate.component-test.js +0 -173
  81. package/src/common/util/stringify.test.js +0 -49
  82. package/src/common/util/submit-data.test.js +0 -183
  83. package/src/common/util/traverse.test.js +0 -50
  84. package/src/common/vitals/cumulative-layout-shift.test.js +0 -71
  85. package/src/common/vitals/first-contentful-paint.test.js +0 -124
  86. package/src/common/vitals/first-input-delay.test.js +0 -88
  87. package/src/common/vitals/first-paint.test.js +0 -127
  88. package/src/common/vitals/interaction-to-next-paint.test.js +0 -74
  89. package/src/common/vitals/largest-contentful-paint.test.js +0 -94
  90. package/src/common/vitals/long-task.test.js +0 -122
  91. package/src/common/vitals/time-to-first-byte.test.js +0 -147
  92. package/src/common/vitals/vital-metric.test.js +0 -171
  93. package/src/common/wrap/wrap-promise.component-test.js +0 -110
  94. package/src/features/ajax/instrument/distributed-tracing.test.js +0 -375
  95. package/src/features/jserrors/aggregate/canonical-function-name.test.js +0 -13
  96. package/src/features/jserrors/aggregate/compute-stack-trace.test.js +0 -414
  97. package/src/features/jserrors/aggregate/format-stack-trace.test.js +0 -39
  98. package/src/features/jserrors/aggregate/string-hash-code.test.js +0 -12
  99. package/src/features/metrics/aggregate/framework-detection.test.js +0 -332
  100. package/src/features/page_view_timing/aggregate/index.component-test.js +0 -86
  101. package/src/features/session_replay/aggregate/index.component-test.js +0 -317
  102. package/src/features/spa/aggregate/interaction-node.test.js +0 -17
  103. package/src/features/utils/agent-session.test.js +0 -194
  104. package/src/features/utils/aggregate-base.test.js +0 -123
  105. package/src/features/utils/feature-base.test.js +0 -45
  106. package/src/features/utils/handler-cache.test.js +0 -72
  107. package/src/features/utils/instrument-base.test.js +0 -216
  108. package/src/features/utils/lazy-feature-loader.test.js +0 -37
  109. package/src/loaders/api/api.component-test.js +0 -45
  110. package/src/loaders/api/api.test.js +0 -85
  111. package/src/loaders/api/apiAsync.test.js +0 -17
@@ -1,74 +0,0 @@
1
- beforeEach(() => {
2
- jest.resetModules()
3
- jest.resetAllMocks()
4
- jest.clearAllMocks()
5
- })
6
-
7
- const getFreshINPImport = async (codeToRun) => {
8
- const { interactionToNextPaint } = await import('./interaction-to-next-paint')
9
- codeToRun(interactionToNextPaint)
10
- }
11
-
12
- describe('inp', () => {
13
- test('reports fcp from web-vitals', (done) => {
14
- getFreshINPImport(metric => metric.subscribe(({ value, attrs }) => {
15
- expect(value).toEqual(1)
16
- expect(attrs.metricId).toEqual('id')
17
- done()
18
- }))
19
- })
20
-
21
- test('does NOT report if not browser scoped', (done) => {
22
- jest.doMock('../constants/runtime', () => ({
23
- __esModule: true,
24
- isBrowserScope: false
25
- }))
26
-
27
- getFreshINPImport(metric => {
28
- metric.subscribe(() => {
29
- console.log('should not have reported...')
30
- expect(1).toEqual(2)
31
- })
32
- setTimeout(done, 1000)
33
- })
34
- })
35
-
36
- test('multiple subs get same value', done => {
37
- jest.doMock('../constants/runtime', () => ({
38
- __esModule: true,
39
- isBrowserScope: true
40
- }))
41
- let sub1, sub2
42
- getFreshINPImport(metric => {
43
- const remove1 = metric.subscribe(({ entries }) => {
44
- sub1 ??= entries[0].id
45
- if (sub1 === sub2) { remove1(); remove2(); done() }
46
- })
47
-
48
- const remove2 = metric.subscribe(({ entries }) => {
49
- sub2 ??= entries[0].id
50
- if (sub1 === sub2) { remove1(); remove2(); done() }
51
- })
52
- })
53
- })
54
-
55
- test('reports more than once', (done) => {
56
- jest.doMock('../constants/runtime', () => ({
57
- __esModule: true,
58
- isBrowserScope: true
59
- }))
60
- let triggered = 0
61
- getFreshINPImport(metric => {
62
- metric.subscribe(({ value }) => {
63
- triggered++
64
- expect(value).toEqual(1)
65
- expect(triggered).toEqual(1)
66
- })
67
- setTimeout(() => {
68
- // the metric emits every quarter second
69
- expect(triggered).toBeGreaterThanOrEqual(3)
70
- done()
71
- }, 1000)
72
- })
73
- })
74
- })
@@ -1,94 +0,0 @@
1
- beforeEach(() => {
2
- jest.resetModules()
3
- jest.resetAllMocks()
4
- jest.clearAllMocks()
5
- })
6
-
7
- const getFreshLCPImport = async (codeToRun) => {
8
- const { largestContentfulPaint } = await import('./largest-contentful-paint')
9
- codeToRun(largestContentfulPaint)
10
- }
11
-
12
- describe('lcp', () => {
13
- test('reports lcp from web-vitals', (done) => {
14
- getFreshLCPImport(metric => metric.subscribe(({ value, attrs }) => {
15
- expect(value).toEqual(1)
16
- expect(attrs).toMatchObject({
17
- size: expect.any(Number),
18
- eid: expect.any(String),
19
- elUrl: expect.any(String),
20
- elTag: expect.any(String)
21
- })
22
- done()
23
- }))
24
- })
25
-
26
- test('does NOT report if not browser scoped', (done) => {
27
- jest.doMock('../constants/runtime', () => ({
28
- __esModule: true,
29
- isBrowserScope: false
30
- }))
31
-
32
- getFreshLCPImport(metric => {
33
- metric.subscribe(() => {
34
- console.log('should not have reported...')
35
- expect(1).toEqual(2)
36
- })
37
- setTimeout(done, 1000)
38
- })
39
- })
40
-
41
- test('Does NOT report values if initiallyHidden', (done) => {
42
- jest.doMock('../constants/runtime', () => ({
43
- __esModule: true,
44
- initiallyHidden: true,
45
- isBrowserScope: true
46
- }))
47
-
48
- getFreshLCPImport(metric => {
49
- metric.subscribe(() => {
50
- console.log('should not have reported')
51
- expect(1).toEqual(2)
52
- })
53
- setTimeout(done, 1000)
54
- })
55
- })
56
-
57
- test('multiple subs get same value', done => {
58
- jest.doMock('../constants/runtime', () => ({
59
- __esModule: true,
60
- isBrowserScope: true
61
- }))
62
- let sub1, sub2
63
- getFreshLCPImport(metric => {
64
- const remove1 = metric.subscribe(({ entries }) => {
65
- sub1 ??= entries[0].id
66
- if (sub1 === sub2) { remove1(); remove2(); done() }
67
- })
68
-
69
- const remove2 = metric.subscribe(({ entries }) => {
70
- sub2 ??= entries[0].id
71
- if (sub1 === sub2) { remove1(); remove2(); done() }
72
- })
73
- })
74
- })
75
-
76
- test('reports only once', (done) => {
77
- jest.doMock('../constants/runtime', () => ({
78
- __esModule: true,
79
- initiallyHidden: false,
80
- isBrowserScope: true
81
- }))
82
- let triggered = 0
83
- getFreshLCPImport(metric => metric.subscribe(({ value }) => {
84
- triggered++
85
- expect(value).toEqual(1)
86
- expect(triggered).toEqual(1)
87
- setTimeout(() => {
88
- expect(triggered).toEqual(1)
89
- done()
90
- }, 1000)
91
- })
92
- )
93
- })
94
- })
@@ -1,122 +0,0 @@
1
- beforeEach(() => {
2
- jest.resetModules()
3
- jest.resetAllMocks()
4
- jest.clearAllMocks()
5
-
6
- const mockPerformanceObserver = jest.fn(cb => ({
7
- observe: () => {
8
- const callCb = () => {
9
- // eslint-disable-next-line
10
- cb({
11
- getEntries: () => ([{
12
- name: 'longtask',
13
- duration: 1,
14
- startTime: 1,
15
- attribution: [{
16
- containerType: 'object',
17
- containerSrc: 'src',
18
- containerId: 'id',
19
- containerName: 'name'
20
- }]
21
- }])
22
- })
23
- setTimeout(callCb, 250)
24
- }
25
- setTimeout(callCb, 250)
26
- },
27
- disconnect: jest.fn()
28
- }))
29
- global.PerformanceObserver = mockPerformanceObserver
30
- global.PerformanceObserver.supportedEntryTypes = ['longtask']
31
- })
32
-
33
- const getFreshLTImport = async (codeToRun) => {
34
- const { longTask } = await import('./long-task')
35
- codeToRun(longTask)
36
- }
37
-
38
- describe('lt', () => {
39
- test('reports lt', (done) => {
40
- getFreshLTImport(metric => metric.subscribe(({ value, attrs }) => {
41
- expect(value).toEqual(1)
42
- expect(attrs).toMatchObject({
43
- ltFrame: 'longtask',
44
- ltStart: 1,
45
- ltCtr: 'object',
46
- ltCtrSrc: 'src',
47
- ltCtrId: 'id',
48
- ltCtrName: 'name'
49
- })
50
- done()
51
- }))
52
- })
53
-
54
- test('does NOT report if not browser scoped', (done) => {
55
- jest.doMock('../constants/runtime', () => ({
56
- __esModule: true,
57
- isBrowserScope: false
58
- }))
59
-
60
- getFreshLTImport(metric => {
61
- metric.subscribe(() => {
62
- console.log('should not have reported...')
63
- expect(1).toEqual(2)
64
- })
65
- setTimeout(done, 1000)
66
- })
67
- })
68
-
69
- test('does NOT report if browser does not support longtask', (done) => {
70
- jest.doMock('../constants/runtime', () => ({
71
- __esModule: true,
72
- isBrowserScope: true
73
- }))
74
-
75
- global.PerformanceObserver.supportedEntryTypes = ['paint']
76
-
77
- getFreshLTImport(metric => {
78
- metric.subscribe(() => {
79
- console.log('should not have reported...')
80
- expect(1).toEqual(2)
81
- })
82
- setTimeout(done, 1000)
83
- })
84
- })
85
-
86
- test('multiple subs get same value', done => {
87
- jest.doMock('../constants/runtime', () => ({
88
- __esModule: true,
89
- isBrowserScope: true
90
- }))
91
- let sub1, sub2
92
- getFreshLTImport(metric => {
93
- const remove1 = metric.subscribe(({ entries }) => {
94
- sub1 ??= entries[0].id
95
- if (sub1 === sub2) { remove1(); remove2(); done() }
96
- })
97
-
98
- const remove2 = metric.subscribe(({ entries }) => {
99
- sub2 ??= entries[0].id
100
- if (sub1 === sub2) { remove1(); remove2(); done() }
101
- })
102
- })
103
- })
104
-
105
- test('reports more than once', (done) => {
106
- jest.doMock('../constants/runtime', () => ({
107
- __esModule: true,
108
- isBrowserScope: true
109
- }))
110
- let triggered = 0
111
- getFreshLTImport(metric => metric.subscribe(({ value }) => {
112
- triggered++
113
- expect(value).toEqual(1)
114
- expect(triggered).toEqual(1)
115
- setTimeout(() => {
116
- expect(triggered).toBeGreaterThanOrEqual(3)
117
- done()
118
- }, 1000)
119
- })
120
- )
121
- })
122
- })
@@ -1,147 +0,0 @@
1
- beforeEach(() => {
2
- jest.resetModules()
3
- jest.resetAllMocks()
4
- jest.clearAllMocks()
5
- })
6
-
7
- const getFreshTTFBImport = async (codeToRun) => {
8
- const { timeToFirstByte } = await import('./time-to-first-byte')
9
- codeToRun(timeToFirstByte)
10
- }
11
-
12
- describe('ttfb', () => {
13
- test('reports ttfb from web-vitals', (done) => {
14
- jest.doMock('../constants/runtime', () => ({
15
- __esModule: true,
16
- isiOS: false,
17
- isBrowserScope: true
18
- }))
19
- global.PerformanceNavigationTiming = jest.fn()
20
-
21
- getFreshTTFBImport(metric => metric.subscribe(({ value }) => {
22
- expect(value).toEqual(1)
23
- done()
24
- }))
25
- })
26
-
27
- test('does NOT report if not browser scoped', (done) => {
28
- jest.doMock('../constants/runtime', () => ({
29
- __esModule: true,
30
- isBrowserScope: false
31
- }))
32
-
33
- getFreshTTFBImport(metric => {
34
- metric.subscribe(() => {
35
- console.log('should not have reported...')
36
- expect(1).toEqual(2)
37
- })
38
- setTimeout(done, 1000)
39
- })
40
- })
41
-
42
- test('does NOT report ttfb from web-vitals if no PNT', (done) => {
43
- jest.doMock('../constants/runtime', () => ({
44
- __esModule: true,
45
- isiOS: false,
46
- isBrowserScope: true
47
- }))
48
- global.PerformanceNavigationTiming = undefined
49
-
50
- getFreshTTFBImport(metric => {
51
- metric.subscribe(() => {
52
- console.log('should not have reported...')
53
- expect(1).toEqual(2)
54
- })
55
- setTimeout(done, 1000)
56
- })
57
- })
58
-
59
- test('does NOT report ttfb from web-vitals if is iOS', (done) => {
60
- jest.doMock('../constants/runtime', () => ({
61
- __esModule: true,
62
- isiOS: true,
63
- isBrowserScope: true
64
- }))
65
- global.PerformanceNavigationTiming = jest.fn()
66
-
67
- getFreshTTFBImport(metric => {
68
- metric.subscribe(() => {
69
- console.log('should not have reported...')
70
- expect(1).toEqual(2)
71
- })
72
- setTimeout(done, 1000)
73
- })
74
- })
75
-
76
- test('reports from performance.timing if cant use web-vitals', (done) => {
77
- jest.doMock('../constants/runtime', () => ({
78
- __esModule: true,
79
- isiOS: true,
80
- globalScope: {
81
- performance: {
82
- timing: {
83
- responseStart: 2
84
- }
85
- }
86
- },
87
- offset: 1,
88
- isBrowserScope: true
89
- }))
90
- global.PerformanceNavigationTiming = undefined
91
-
92
- getFreshTTFBImport(metric => {
93
- metric.subscribe(({ value }) => {
94
- expect(value).toEqual(1) // responseStart (2) - offset (1) === 1
95
- done()
96
- })
97
- })
98
- })
99
-
100
- test('multiple subs get same value', done => {
101
- jest.doMock('../constants/runtime', () => ({
102
- __esModule: true,
103
- isBrowserScope: true,
104
- isiOS: false
105
- }))
106
- global.PerformanceNavigationTiming = jest.fn()
107
- let sub1, sub2
108
- getFreshTTFBImport(metric => {
109
- const remove1 = metric.subscribe(({ entries }) => {
110
- sub1 ??= entries[0].id
111
- if (sub1 === sub2) { remove1(); remove2(); done() }
112
- })
113
-
114
- const remove2 = metric.subscribe(({ entries }) => {
115
- sub2 ??= entries[0].id
116
- if (sub1 === sub2) { remove1(); remove2(); done() }
117
- })
118
- })
119
- })
120
-
121
- test('reports only once', (done) => {
122
- jest.doMock('../constants/runtime', () => ({
123
- __esModule: true,
124
- isiOS: true,
125
- globalScope: {
126
- performance: {
127
- timing: {
128
- responseStart: 2
129
- }
130
- }
131
- },
132
- offset: 1,
133
- isBrowserScope: true
134
- }))
135
- let triggered = 0
136
- getFreshTTFBImport(metric => metric.subscribe(({ value }) => {
137
- triggered++
138
- expect(value).toEqual(1)
139
- expect(triggered).toEqual(1)
140
- setTimeout(() => {
141
- expect(triggered).toEqual(1)
142
- done()
143
- }, 1000)
144
- })
145
- )
146
- })
147
- })
@@ -1,171 +0,0 @@
1
- import { VitalMetric } from './vital-metric'
2
-
3
- let vitalMetric
4
- beforeEach(() => {
5
- vitalMetric = new VitalMetric('test')
6
- })
7
-
8
- afterEach(() => {
9
- jest.resetAllMocks()
10
- })
11
-
12
- describe('vital-metric', () => {
13
- test('default values', () => {
14
- expect(vitalMetric).toMatchObject({
15
- name: 'test',
16
- history: []
17
- })
18
-
19
- expect(vitalMetric.current).toMatchObject({
20
- name: 'test',
21
- attrs: {},
22
- entries: [],
23
- value: undefined
24
- })
25
- })
26
-
27
- test('update', () => {
28
- let i = 0
29
- vitalMetric.update({ value: i, entries: [{ test: i + 1 }], attrs: { test: i + 2 }, shouldAddConnectionAttributes: true })
30
- expect(vitalMetric.current).toMatchObject({
31
- value: i,
32
- entries: [{ test: i + 1 }],
33
- attrs: { test: i + 2 }
34
- })
35
-
36
- i++
37
- vitalMetric.update({ value: i, entries: [{ test: i + 1 }], attrs: { test: i + 2 }, shouldAddConnectionAttributes: true })
38
- expect(vitalMetric.current).toMatchObject({
39
- value: i,
40
- entries: [{ test: i + 1 }],
41
- attrs: { test: i + 2 }
42
- })
43
- })
44
-
45
- test('rounding', () => {
46
- // default rounding
47
- vitalMetric.update({ value: 1.234 })
48
- expect(vitalMetric.current.value).toEqual(1)
49
- // custom rounding
50
- vitalMetric = new VitalMetric('test', (x) => x * 100)
51
- vitalMetric.update({ value: 5 })
52
- expect(vitalMetric.current.value).toEqual(500)
53
- })
54
-
55
- test('isValid', () => {
56
- expect(vitalMetric.isValid).toEqual(false)
57
-
58
- vitalMetric.update({ value: -1 })
59
- expect(vitalMetric.isValid).toEqual(false)
60
-
61
- vitalMetric.update({ value: 1 })
62
- expect(vitalMetric.isValid).toEqual(true)
63
- })
64
-
65
- test('subscribers get updates when valid', (done) => {
66
- vitalMetric.subscribe(({ value }) => {
67
- expect(value).toEqual(1)
68
- done()
69
- })
70
-
71
- vitalMetric.update({ value: 1 })
72
- })
73
-
74
- test('multiple subscribers get same update when valid', (done) => {
75
- let sub1, sub2
76
- let stop1 = vitalMetric.subscribe(({ entries }) => {
77
- sub1 ??= entries[0].id
78
- if (sub1 === sub2) { stop1(); stop2(); done() }
79
- })
80
-
81
- let stop2 = vitalMetric.subscribe(({ entries }) => {
82
- sub2 ??= entries[0].id
83
- if (sub1 === sub2) { stop1(); stop2(); done() }
84
- })
85
-
86
- vitalMetric.update({ value: 1, entries: [{ id: 'abcd' }] })
87
- })
88
-
89
- test('subscribers do not get updates when not valid', (done) => {
90
- vitalMetric.subscribe(({ value }) => {
91
- console.log(value)
92
- console.log('should not have reached subscriber')
93
- expect(1).toEqual(2)
94
- })
95
-
96
- vitalMetric.update({ value: -1 })
97
- setTimeout(done, 1000)
98
- })
99
-
100
- test('subscribers get latest value immediately if already valid', (done) => {
101
- vitalMetric.update({ value: 1 })
102
-
103
- vitalMetric.subscribe(({ value }) => {
104
- expect(value).toEqual(1)
105
- done()
106
- })
107
- })
108
-
109
- test('unsubscribe', (done) => {
110
- const unsubscribe = vitalMetric.subscribe(({ value }) => {
111
- console.log('should not have reached subscriber')
112
- expect(1).toEqual(2)
113
- })
114
-
115
- unsubscribe()
116
- vitalMetric.update({ value: 1 })
117
- setTimeout(done, 1000)
118
- })
119
-
120
- test('addConnectionAttributes', () => {
121
- global.navigator.connection = {}
122
- vitalMetric.update({ value: 1, shouldAddConnectionAttributes: true })
123
- expect(vitalMetric.current.attrs).toEqual(expect.objectContaining({}))
124
-
125
- global.navigator.connection.type = 'type'
126
- vitalMetric.update({ value: 1, shouldAddConnectionAttributes: true })
127
- expect(vitalMetric.current.attrs).toEqual(expect.objectContaining({
128
- 'net-type': 'type'
129
- }))
130
-
131
- global.navigator.connection.effectiveType = 'effectiveType'
132
- vitalMetric.update({ value: 1, shouldAddConnectionAttributes: true })
133
- expect(vitalMetric.current.attrs).toEqual(expect.objectContaining({
134
- 'net-type': 'type',
135
- 'net-etype': 'effectiveType'
136
- }))
137
-
138
- global.navigator.connection.rtt = 'rtt'
139
- vitalMetric.update({ value: 1, shouldAddConnectionAttributes: true })
140
- expect(vitalMetric.current.attrs).toEqual(expect.objectContaining({
141
- 'net-type': 'type',
142
- 'net-etype': 'effectiveType',
143
- 'net-rtt': 'rtt'
144
- }))
145
-
146
- global.navigator.connection.downlink = 'downlink'
147
- vitalMetric.update({ value: 1, shouldAddConnectionAttributes: true })
148
- expect(vitalMetric.current.attrs).toEqual(expect.objectContaining({
149
- 'net-type': 'type',
150
- 'net-etype': 'effectiveType',
151
- 'net-rtt': 'rtt',
152
- 'net-dlink': 'downlink'
153
- }))
154
-
155
- global.navigator.connection = {
156
- type: 'type',
157
- effectiveType: 'effectiveType',
158
- rtt: 'rtt',
159
- downlink: 'downlink'
160
- }
161
- vitalMetric.update({ value: 1, shouldAddConnectionAttributes: true })
162
-
163
- expect(vitalMetric.current.attrs).toEqual(expect.objectContaining({
164
- 'net-type': 'type',
165
- 'net-etype': 'effectiveType',
166
- 'net-rtt': 'rtt',
167
- 'net-dlink': 'downlink'
168
- }))
169
- global.navigator.connection = {}
170
- })
171
- })