-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathmockReportingObserver.ts
More file actions
123 lines (108 loc) · 3.37 KB
/
Copy pathmockReportingObserver.ts
File metadata and controls
123 lines (108 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import type {
DocumentPolicyViolationReport,
InterventionReport,
ReportType,
} from '../../src/domain/report/browser.types'
import { noop } from '../../src/tools/utils/functionUtils'
import { registerCleanupTask } from '../registerCleanupTask'
import { createNewEvent } from './createNewEvent'
export type MockReportingObserver = ReturnType<typeof mockReportingObserver>
export function mockReportingObserver() {
const originalReportingObserver = window.ReportingObserver
let callbacks: { [k: string]: ReportingObserverCallback[] } = {}
let reportingObserver: ReportingObserver
window.ReportingObserver = function (callback: ReportingObserverCallback, { types }: ReportingObserverOptions) {
types?.forEach((type) => {
if (!callbacks[type]) {
callbacks[type] = []
}
callbacks[type]?.push(callback)
})
reportingObserver = {
disconnect() {
noop()
},
observe() {
noop()
},
takeRecords() {
return []
},
}
return reportingObserver
} as unknown as typeof originalReportingObserver
registerCleanupTask(() => {
window.ReportingObserver = originalReportingObserver
callbacks = {}
})
return {
raiseReport(type: ReportType, overrides?: Partial<DocumentPolicyViolationReport>) {
if (callbacks[type]) {
const report =
type === 'document-policy-violation'
? { ...FAKE_DOCUMENT_POLICY_VIOLATION_REPORT, ...overrides }
: { ...FAKE_REPORT, type }
callbacks[type].forEach((callback) => callback([report], reportingObserver))
}
},
}
}
export type MockCspEventListener = ReturnType<typeof mockCspEventListener>
export function mockCspEventListener() {
// eslint-disable-next-line @typescript-eslint/unbound-method
const originalAddEventListener = EventTarget.prototype.addEventListener
EventTarget.prototype.addEventListener = jasmine
.createSpy()
.and.callFake((_type: string, listener: EventListener) => {
listeners.push(listener)
})
registerCleanupTask(() => {
EventTarget.prototype.addEventListener = originalAddEventListener
})
const listeners: EventListener[] = []
return {
dispatchEvent() {
listeners.forEach((listener) => listener(FAKE_CSP_VIOLATION_EVENT))
},
}
}
export const FAKE_CSP_VIOLATION_EVENT = createNewEvent('securitypolicyviolation', {
blockedURI: 'blob',
columnNumber: 8,
disposition: 'enforce',
documentURI: 'blob',
effectiveDirective: 'worker-src',
lineNumber: 17,
originalPolicy: "worker-src 'none'",
referrer: '',
sourceFile: 'http://foo.bar/index.js',
statusCode: 200,
violatedDirective: 'worker-src',
})
export const FAKE_DOCUMENT_POLICY_VIOLATION_REPORT: DocumentPolicyViolationReport = {
type: 'document-policy-violation',
url: 'http://foo.bar',
body: {
featureId: 'network-efficiency-guardrails',
message: 'Document policy violation: resource compression is required.',
disposition: 'report',
lineNumber: null,
columnNumber: null,
sourceFile: 'https://foo.bar/large-uncompressed.js',
toJSON: noop,
},
toJSON: noop,
}
export const FAKE_REPORT: InterventionReport = {
type: 'intervention',
url: 'http://foo.bar',
body: {
id: 'NavigatorVibrate',
columnNumber: 10,
lineNumber: 20,
message: 'foo bar',
sourceFile: 'http://foo.bar/index.js',
toJSON: noop,
},
toJSON: noop,
}