-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathrules.ts
More file actions
103 lines (89 loc) · 3.02 KB
/
rules.ts
File metadata and controls
103 lines (89 loc) · 3.02 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
import { produce } from 'immer'
import { ProxyData, RequestSnippetSchema } from '@/types'
import { TestRule } from '@/types/rules'
import { exhaustive } from '../utils/typescript'
import { createCorrelationRuleInstance } from './correlation'
import { createCustomCodeRuleInstance } from './customCode'
import { createParameterizationRuleInstance } from './parameterization'
import { generateSequentialInt, urlToQueryParams } from './utils'
import { createVerificationRuleInstance } from './verification'
function createSequentialIdPool() {
const currentId: Record<
TestRule['type'],
Generator<number, number, number>
> = {
correlation: generateSequentialInt(),
parameterization: generateSequentialInt(),
verification: generateSequentialInt(),
customCode: generateSequentialInt(),
}
return (type: TestRule['type']) => currentId[type]
}
export function applyRules(recording: ProxyData[], rules: TestRule[]) {
const idGenerator = createSequentialIdPool()
const ruleInstances = rules
.filter((rule) => rule.enabled)
.map((rule) => createRuleInstance(rule, idGenerator(rule.type)))
const requestSnippetSchemas = recording
.map((data) =>
ruleInstances.reduce<RequestSnippetSchema>(
(acc, rule) => rule.apply(acc),
{
data,
before: [],
after: [],
checks: [],
}
)
)
// Update query params after all rules have been applied,
// since some rules may change the URL
.map(updateQueryParams)
// Collect affected requests to exclude from redirect merging.
// All rule types that modify request snippets must be included here,
// otherwise their modifications (before/after/checks) can be silently
// dropped when redirect chains are merged.
const affectedRequestIds = new Set(
ruleInstances.flatMap((instance) => {
if (
['parameterization', 'customCode', 'verification'].includes(
instance.type
)
) {
return instance.state.matchedRequestIds
}
if (instance.type === 'correlation') {
return [
...instance.state.matchedRequestIds,
...instance.state.responsesExtracted.map((extracted) => extracted.id),
]
}
return []
})
)
return { requestSnippetSchemas, ruleInstances, affectedRequestIds }
}
function createRuleInstance<T extends TestRule>(
rule: T,
idGenerator: Generator<number, number, number>
) {
switch (rule.type) {
case 'correlation':
return createCorrelationRuleInstance(rule, idGenerator)
case 'parameterization':
return createParameterizationRuleInstance(rule, idGenerator)
case 'verification':
return createVerificationRuleInstance(rule)
case 'customCode':
return createCustomCodeRuleInstance(rule)
default:
return exhaustive(rule)
}
}
function updateQueryParams(
requestSnippet: RequestSnippetSchema
): RequestSnippetSchema {
return produce(requestSnippet, (draft) => {
draft.data.request.query = urlToQueryParams(draft.data.request.url)
})
}