-
-
Notifications
You must be signed in to change notification settings - Fork 159
/
activityRelatedArtifact.ts
126 lines (111 loc) · 4.77 KB
/
activityRelatedArtifact.ts
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
124
125
126
import { AssertionReportDiffer } from '@serenity-js/core/lib/io';
import { Artifact, AssertionReport, CorrelationId, HTTPRequestResponse, JSONData, LogEntry, Name, RequestAndResponse, TextData, Timestamp } from '@serenity-js/core/lib/model';
import { createHash } from 'crypto';
import { match } from 'tiny-types';
import { inspect } from 'util';
import { SerenityBDDReportContext } from '../SerenityBDDReportContext';
/**
* @package
*/
export function activityRelatedArtifact<Context extends SerenityBDDReportContext>(activityId: CorrelationId, name: Name, artifact: Artifact, timestamp: Timestamp): (context: Context) => Context {
const differ = new AssertionReportDiffer({
expected: line => `+ ${ line }`,
actual: line => `- ${ line }`,
matching: line => ` ${ line }`,
});
return (report: Context): Context =>
match<Artifact, Context>(artifact)
.when(HTTPRequestResponse, _ =>
report.with(httpRequestResponse(
activityId,
artifact.map(data => data),
timestamp
))
)
.when(TextData, _ =>
report.with(arbitraryData(
activityId,
name,
artifact.map(artifactContents => artifactContents.data),
timestamp
))
)
.when(LogEntry, _ =>
report.with(arbitraryData(
activityId,
name,
artifact.map(artifactContents => artifactContents.data),
timestamp
))
)
.when(AssertionReport, _ =>
report.with(arbitraryData(
activityId,
name,
artifact.map(value => differ.diff(value.expected, value.actual)),
timestamp
))
)
.when(JSONData, _ =>
report.with(arbitraryData(
activityId,
name,
artifact.map(value => JSON.stringify(value, undefined, 4)),
timestamp
))
)
.else(_ => report)
}
function mapToString(dictionary: Record<string, string | number | boolean>) {
return Object.keys(dictionary).map(key => `${key}: ${dictionary[key]}`).join('\n');
}
function bodyToString(data: any): string {
if (data === null || data === undefined) {
return '';
}
if (typeof data === 'string') {
return data;
}
if (typeof data === 'object') {
return JSON.stringify(data, undefined, 4);
}
return inspect(data);
}
function httpRequestResponse<Context extends SerenityBDDReportContext>(activityId: CorrelationId, requestResponse: RequestAndResponse, timestamp: Timestamp) {
return (context: Context): Context => {
if (context.steps.has(activityId.value)) {
context.steps.get(activityId.value).step.restQuery = {
method: requestResponse.request.method.toUpperCase(),
path: requestResponse.request.url,
content: bodyToString(requestResponse.request.data),
contentType: String(requestResponse.request.headers['Content-Type'] || ''), // todo: add a case insensitive proxy around this RFC 2616: 4.2
requestHeaders: mapToString(requestResponse.request.headers || {}) || '',
requestCookies: String(requestResponse.request.headers.Cookie || ''), // todo: add a case insensitive proxy around this RFC 2616: 4.2
statusCode: requestResponse.response.status,
responseHeaders: mapToString(requestResponse.response.headers) || '',
responseCookies: requestResponse.response.headers.Cookie || '', // todo: add a case insensitive proxy around this RFC 2616: 4.2
responseBody: bodyToString(requestResponse.response.data),
};
}
return context;
}
}
function arbitraryData<Context extends SerenityBDDReportContext>(activityId: CorrelationId, name: Name, contents: string, timestamp: Timestamp) {
return (context: Context): Context => {
if (context.steps.has(activityId.value)) {
const id = createHash('sha1')
.update(name.value)
.update(contents)
.update(`${ timestamp.toMillisecondTimestamp() }`)
.digest('hex');
context.steps.get(activityId.value).step.reportData.push({
id: `report-data-${ id }`,
isEvidence: false,
path: '',
title: name.value,
contents,
});
}
return context;
}
}