/
MockingjayGenerator.js
138 lines (126 loc) · 4.58 KB
/
MockingjayGenerator.js
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
127
128
129
130
131
132
133
134
135
136
137
138
class StubGenerator {
constructor(request, httpExchange) {
this.request = request
this.httpExchange = httpExchange
this.setupLines = []
}
generateStub() {
const commentLine = `// Stub for "${this.request.name}"`
const stubLine = `stub(${this._generateMatcher()}, ${this._generateBuilder()})`
let lines = this.setupLines
lines.unshift(commentLine)
lines.push(stubLine)
return lines.join('\n')
}
_getRequestSlug() {
let slug = this.request.name.split(/[^a-z0-9]/i).map(s => s.substr(0,1).toUpperCase() + s.substr(1).toLowerCase()).join('')
return slug.substr(0,1).toLowerCase() + slug.substr(1)
}
_generateMatcher() {
const method = this.request.method.toUpperCase()
if (method === 'GET') {
return `uri("${this.request.urlBase}")`
}
else {
return `http(.${method}, "${this.request.urlBase}")`
}
}
_generateBuilder() {
const contentType = this.httpExchange.responseHeaders['Content-Type']
if (contentType.match(/^application\/json/)) {
if (this.httpExchange.responseBody.length > 8192) {
return this._generateLargeJsonBuilder()
}
return this._generateJsonBuilder()
}
else if (this.httpExchange.responseBody.length > 0) {
return this._generateDataBuilder()
}
return `http(${this.httpExchange.responseStatusCode})`
}
_generateDataBuilder() {
const responseHeaders = this.httpExchange.responseHeaders
const allowHeaders = ['Content-Type', 'Content-Language', 'Set-Cookie']
let headers = []
for (let headerName of Object.keys(responseHeaders)) {
if (allowHeaders.indexOf(headerName) >= 0) {
headers.push(`"${headerName}":"${responseHeaders[headerName]}"`)
}
}
const headerString = headers.length === 0 ? '[:]' : `[${headers.join(', ')}]`
const slug = this._getRequestSlug(this.request)
const dataVarName = `${slug}Data`
this.setupLines.push(`let ${dataVarName} = try! Data(contentsOf: Bundle.main.url(forResource: "${slug}", withExtension: "dat" /* set your file extension */)!)`)
return `http(${this.httpExchange.responseStatusCode}, headers: ${headerString}, download: Download.content(${dataVarName}))`
}
_generateLargeJsonBuilder() {
const slug = this._getRequestSlug(this.request)
const dataVarName = `${slug}JsonData`
const objectVarName = `${slug}JsonObject`
this.setupLines.push(`let ${dataVarName} = try! Data(contentsOf: Bundle.main.url(forResource: "${slug}", withExtension: "json")!)`)
this.setupLines.push(`let ${objectVarName} = try! JSONSerialization.jsonObject(with: ${dataVarName}, options: [])`)
return `json(${objectVarName}, status: ${this.httpExchange.responseStatusCode})`
}
_generateJsonBuilder() {
let jsonObject
let swiftJsonString
try {
jsonObject = JSON.parse(this.httpExchange.responseBody)
}
catch (e) {
console.error(`Invalid JSON response: ${e.toString()}`)
jsonObject = null
}
if (jsonObject !== null) {
swiftJsonString = this._generateJsonObject(jsonObject)
}
else {
swiftJsonString = '/* JSON response */'
}
return `json(${swiftJsonString}, status: ${this.httpExchange.responseStatusCode})`
}
_generateJsonObject(jsonObject, indent = 0) {
if (jsonObject === null) {
return 'NSNull.null()'
}
else if (typeof jsonObject === 'string') {
return `"${jsonObject}"`
}
else if (Array.isArray(jsonObject)) {
if (jsonObject.length === 0) {
return '[]'
}
const children = jsonObject.map(obj => {
return `${' '.repeat(indent + 1)}${this._generateJsonObject(obj, indent + 1)}`
})
return `[\n${children.join(',\n')}\n${' '.repeat(indent)}]`
}
else if (typeof jsonObject === 'object') {
if (jsonObject.length === 0) {
return '[:]'
}
const children = Object.keys(jsonObject).map(key => {
return `${' '.repeat(indent + 1)}"${key}": ${this._generateJsonObject(jsonObject[key], indent + 1)}`
})
return `[\n${children.join(',\n')}\n${' '.repeat(indent)}]`
}
else {
return jsonObject.toString()
}
}
}
@registerCodeGenerator
class MockingjayGenerator {
static identifier = 'com.luckymarmot.PawExtensions.MockingjayGenerator';
static title = 'Swift Mockingjay';
_generateStub(request) {
const lastExchange = request.getLastExchange()
let generator = new StubGenerator(request, lastExchange)
return generator.generateStub()
}
generate(context, requests, options) {
return requests.map(request => {
return this._generateStub(request)
}).join('\n\n') + '\n'
}
}