1
+ <template >
2
+ <div class =" converter-container" >
3
+ <div class =" input-section" >
4
+ <label for =" curlInput" >Curl Command</label >
5
+ <textarea
6
+ id =" curlInput"
7
+ v-model =" curlInput"
8
+ placeholder =" Enter your curl command here..."
9
+ rows =" 5"
10
+ ></textarea >
11
+
12
+ <div class =" test-runner-select" >
13
+ <label for =" testRunner" >Test Runner</label >
14
+ <select id =" testRunner" v-model =" selectedRunner" >
15
+ <option value =" mocha" >Mocha</option >
16
+ <option value =" jest" >Jest</option >
17
+ <option value =" cucumber" >Cucumber.js</option >
18
+ </select >
19
+ </div >
20
+
21
+ <button class =" convert-button" @click =" convertCurl" >
22
+ Convert
23
+ </button >
24
+ <button class =" convert-button clear" @click =" clearOutput" >
25
+ Clear
26
+ </button >
27
+ </div >
28
+
29
+ <div class =" output-section" v-if =" generatedCode" >
30
+ <div class =" output-header" >
31
+ <h3 >Generated Test Code</h3 >
32
+ <button class =" copy-button" @click =" copyToClipboard" >
33
+ Copy Code
34
+ </button >
35
+ </div >
36
+ <pre ><code >{{ generatedCode }}</code ></pre >
37
+ </div >
38
+ </div >
39
+ </template >
40
+
41
+ <script setup>
42
+ import { ref } from ' vue'
43
+
44
+ const curlInput = ref (' ' )
45
+ const selectedRunner = ref (' mocha' )
46
+ const generatedCode = ref (' ' )
47
+
48
+ const clearOutput = () => {
49
+ generatedCode .value = ' '
50
+ }
51
+
52
+ const parseCurl = (curlCommand ) => {
53
+ if (! curlCommand) {
54
+ clearOutput ()
55
+ return " "
56
+ }
57
+ const urlMatch = curlCommand .match (/ https? :\/\/ [^ \s "'] + / );
58
+ const methodMatch = curlCommand .match (/ -X\s + (\w + )/ );
59
+ const headerMatches = curlCommand .match (/ -H\s + ['"] ([^ '"] + )['"] / g );
60
+ const dataMatch = curlCommand .match (/ --data\s + (['"] )(. *? )\1 / );
61
+
62
+ const headers = {};
63
+ if (headerMatches) {
64
+ headerMatches .forEach (header => {
65
+ const [key , value ] = header .match (/ -H\s + ['"] ([^ '"] + )['"] / )[1 ].split (' : ' );
66
+ headers[key] = value;
67
+ });
68
+ }
69
+ return {
70
+ url: urlMatch? .[0 ] || ' ' ,
71
+ method: methodMatch? .[1 ] || ' GET' ,
72
+ headers,
73
+ data: dataMatch? .[2 ] || null
74
+ };
75
+ }
76
+
77
+ const generateMochaTest = (curlData ) => {
78
+ return ` const { spec } = require('pactum');
79
+
80
+ describe('API Test', () => {
81
+ it('should make the API call successfully', async () => {
82
+ await spec()
83
+ .${ curlData .method .toLowerCase ()} ('${ curlData .url } ')
84
+ ${ Object .keys (curlData .headers ).length > 0 ?
85
+ ` .withHeaders(${ JSON .stringify (curlData .headers , null , 8 )} )` : ' ' }
86
+ ${ curlData .data ? ` .withJson(${ curlData .data } )` : ' ' }
87
+ .expectStatus(200);
88
+ });
89
+ });`
90
+ }
91
+
92
+ const generateJestTest = (curlData ) => {
93
+ return ` const { spec } = require('pactum');
94
+
95
+ describe('API Test', () => {
96
+ test('should make the API call successfully', async () => {
97
+ await spec()
98
+ .${ curlData .method .toLowerCase ()} ('${ curlData .url } ')
99
+ ${ Object .keys (curlData .headers ).length > 0 ?
100
+ ` .withHeaders(${ JSON .stringify (curlData .headers , null , 8 )} )` : ' ' }
101
+ ${ curlData .data ? ` .withJson(${ curlData .data } )` : ' ' }
102
+ .expectStatus(200);
103
+ });
104
+ });`
105
+ }
106
+
107
+ const generateCucumberTest = (curlData ) => {
108
+ return ` // features/api.feature
109
+ Feature: API Testing
110
+ Scenario: Make API call
111
+ When I make an API call
112
+ Then I should receive a successful response
113
+
114
+ // step_definitions/api_steps.js
115
+ const { spec } = require('pactum');
116
+
117
+ When('I make an API call', async function () {
118
+ this.response = await spec()
119
+ .${ curlData .method .toLowerCase ()} ('${ curlData .url } ')
120
+ ${ Object .keys (curlData .headers ).length > 0 ?
121
+ ` .withHeaders(${ JSON .stringify (curlData .headers , null , 8 )} )` : ' ' }
122
+ ${ curlData .data ? ` .withJson(${ curlData .data } )` : ' ' }
123
+ });
124
+
125
+ Then('I should receive a successful response', async function () {
126
+ await this.response.expectStatus(200);
127
+ });`
128
+ }
129
+
130
+ const convertCurl = () => {
131
+ try {
132
+ const curlData = parseCurl (curlInput .value )
133
+ if (! curlData .url ) {
134
+ return
135
+ }
136
+ let code = ' '
137
+
138
+ switch (selectedRunner .value ) {
139
+ case ' mocha' :
140
+ code = generateMochaTest (curlData)
141
+ break
142
+ case ' jest' :
143
+ code = generateJestTest (curlData)
144
+ break
145
+ case ' cucumber' :
146
+ code = generateCucumberTest (curlData)
147
+ break
148
+ }
149
+
150
+ generatedCode .value = code
151
+ } catch (error) {
152
+ generatedCode .value = ` Error parsing curl command: ${ error .message } `
153
+ }
154
+ }
155
+
156
+ const copyToClipboard = async () => {
157
+ try {
158
+ await navigator .clipboard .writeText (generatedCode .value )
159
+ alert (' Code copied to clipboard!' )
160
+ } catch (err) {
161
+ alert (' Failed to copy code to clipboard' )
162
+ }
163
+ }
164
+ < / script>
165
+
166
+ < style scoped>
167
+ .converter - container {
168
+ max- width: 800px ;
169
+ margin: 0 auto;
170
+ padding: 20px ;
171
+ }
172
+
173
+ .input - section {
174
+ margin- bottom: 20px ;
175
+ }
176
+
177
+ label {
178
+ display: block;
179
+ margin- bottom: 8px ;
180
+ font- weight: 500 ;
181
+ }
182
+
183
+ textarea {
184
+ width: 100 % ;
185
+ padding: 12px ;
186
+ border: 1px solid var (-- vp- c- divider);
187
+ border- radius: 8px ;
188
+ font- family: monospace;
189
+ margin- bottom: 16px ;
190
+ }
191
+
192
+ .test - runner- select {
193
+ margin- bottom: 16px ;
194
+ }
195
+
196
+ select {
197
+ width: 200px ;
198
+ padding: 8px ;
199
+ border: 1px solid var (-- vp- c- divider);
200
+ border- radius: 6px ;
201
+ background- color: var (-- vp- c- bg);
202
+ }
203
+
204
+ .convert - button {
205
+ background- color: var (-- vp- c- brand);
206
+ color: white;
207
+ padding: 8px 16px ;
208
+ border: none;
209
+ border- radius: 6px ;
210
+ cursor: pointer;
211
+ font- weight: 500 ;
212
+ }
213
+
214
+ .convert - button: hover {
215
+ background- color: var (-- vp- c- brand- dark);
216
+ }
217
+
218
+ .convert - button .clear {
219
+ background- color: var (-- vp- c- bg- mute);
220
+ }
221
+
222
+
223
+ .output - section {
224
+ background- color: var (-- vp- c- bg- soft);
225
+ border- radius: 8px ;
226
+ padding: 16px ;
227
+ }
228
+
229
+ .output - header {
230
+ display: flex;
231
+ justify- content: space- between;
232
+ align- items: center;
233
+ margin- bottom: 12px ;
234
+ }
235
+
236
+ .copy - button {
237
+ background- color: var (-- vp- c- brand- soft);
238
+ color: var (-- vp- c- brand);
239
+ padding: 4px 12px ;
240
+ border: none;
241
+ border- radius: 4px ;
242
+ cursor: pointer;
243
+ font- size: 14px ;
244
+ }
245
+
246
+ .copy - button: hover {
247
+ background- color: var (-- vp- c- brand- soft- hover);
248
+ }
249
+
250
+ pre {
251
+ margin: 0 ;
252
+ padding: 16px ;
253
+ background- color: var (-- vp- c- bg- alt);
254
+ border- radius: 6px ;
255
+ overflow- x: auto;
256
+ }
257
+
258
+ code {
259
+ font- family: monospace;
260
+ font- size: 14px ;
261
+ line- height: 1.5 ;
262
+ }
263
+ < / style>
0 commit comments