1package cloudflare
2
3import (
4	"fmt"
5	"net/http"
6	"testing"
7	"time"
8
9	"github.com/stretchr/testify/assert"
10)
11
12const (
13	deleteWorkerResponseData = `{
14    "result": null,
15    "success": true,
16    "errors": [],
17    "messages": []
18}`
19	uploadWorkerResponseData = `{
20    "result": {
21        "script": "addEventListener('fetch', event => {\n    event.passThroughOnException()\nevent.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n    return fetch(request)\n}",
22        "etag": "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
23        "size": 191,
24        "modified_on": "2018-06-09T15:17:01.989141Z"
25    },
26    "success": true,
27    "errors": [],
28    "messages": []
29}`
30	updateWorkerRouteResponse = `{
31    "result": {
32        "id": "e7a57d8746e74ae49c25994dadb421b1",
33        "pattern": "app3.example.com/*",
34        "enabled": true
35    },
36    "success": true,
37    "errors": [],
38    "messages": []
39}`
40	updateWorkerRouteEntResponse = `{
41    "result": {
42        "id": "e7a57d8746e74ae49c25994dadb421b1",
43        "pattern": "app3.example.com/*",
44        "script": "test_script_1"
45    },
46    "success": true,
47    "errors": [],
48    "messages": []
49}`
50	createWorkerRouteResponse = `{
51    "result": {
52        "id": "e7a57d8746e74ae49c25994dadb421b1"
53    },
54    "success": true,
55    "errors": [],
56    "messages": []
57}`
58	listRouteResponseData = `{
59    "result": [
60        {
61            "id": "e7a57d8746e74ae49c25994dadb421b1",
62            "pattern": "app1.example.com/*",
63            "enabled": true
64        },
65        {
66            "id": "f8b68e9857f85bf59c25994dadb421b1",
67            "pattern": "app2.example.com/*",
68            "enabled": false
69        }
70    ],
71    "success": true,
72    "errors": [],
73    "messages": []
74}`
75	listRouteEntResponseData = `{
76    "result": [
77        {
78            "id": "e7a57d8746e74ae49c25994dadb421b1",
79            "pattern": "app1.example.com/*",
80            "script": "test_script_1"
81        },
82        {
83            "id": "f8b68e9857f85bf59c25994dadb421b1",
84            "pattern": "app2.example.com/*",
85            "script": "test_script_2"
86        },
87        {
88            "id": "2b5bf4240cd34c77852fac70b1bf745a",
89            "pattern": "app3.example.com/*"
90        }
91    ],
92    "success": true,
93    "errors": [],
94    "messages": []
95}`
96	listWorkersResponseData = `{
97  "result": [
98    {
99      "id": "bar",
100      "created_on": "2018-04-22T17:10:48.938097Z",
101      "modified_on": "2018-04-22T17:10:48.938097Z",
102      "etag": "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a"
103    },
104    {
105      "id": "baz",
106      "created_on": "2018-04-22T17:10:48.938097Z",
107      "modified_on": "2018-04-22T17:10:48.938097Z",
108      "etag": "380dg51e97e80b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43088b"
109    }
110  ],
111  "success": true,
112  "errors": [],
113  "messages": []
114}`
115)
116
117var (
118	successResponse               = Response{Success: true, Errors: []ResponseInfo{}, Messages: []ResponseInfo{}}
119	workerScript                  = "addEventListener('fetch', event => {\n    event.passThroughOnException()\nevent.respondWith(handleRequest(event.request))\n})\n\nasync function handleRequest(request) {\n    return fetch(request)\n}"
120	deleteWorkerRouteResponseData = createWorkerRouteResponse
121)
122
123func TestWorkers_DeleteWorker(t *testing.T) {
124	setup()
125	defer teardown()
126
127	mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) {
128		assert.Equal(t, "DELETE", r.Method, "Expected method 'DELETE', got %s", r.Method)
129		w.Header().Set("content-type", "application/javascript")
130		fmt.Fprintf(w, deleteWorkerResponseData)
131	})
132	res, err := client.DeleteWorker(&WorkerRequestParams{ZoneID: "foo"})
133	want := WorkerScriptResponse{
134		successResponse,
135		WorkerScript{}}
136	if assert.NoError(t, err) {
137		assert.Equal(t, want.Response, res.Response)
138	}
139}
140
141func TestWorkers_DeleteWorkerWithName(t *testing.T) {
142	setup(UsingAccount("foo"))
143	defer teardown()
144
145	mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) {
146		assert.Equal(t, "DELETE", r.Method, "Expected method 'DELETE', got %s", r.Method)
147		w.Header().Set("content-type", "application/javascript")
148		fmt.Fprintf(w, deleteWorkerResponseData)
149	})
150	res, err := client.DeleteWorker(&WorkerRequestParams{ScriptName: "bar"})
151	want := WorkerScriptResponse{
152		successResponse,
153		WorkerScript{}}
154	if assert.NoError(t, err) {
155		assert.Equal(t, want.Response, res.Response)
156	}
157}
158
159func TestWorkers_DeleteWorkerWithNameErrorsWithoutAccountId(t *testing.T) {
160	setup()
161	defer teardown()
162
163	_, err := client.DeleteWorker(&WorkerRequestParams{ScriptName: "bar"})
164	assert.Error(t, err)
165}
166
167func TestWorkers_DownloadWorker(t *testing.T) {
168	setup()
169	defer teardown()
170
171	mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) {
172		assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
173		w.Header().Set("content-type", "application/javascript")
174		fmt.Fprintf(w, workerScript)
175	})
176	res, err := client.DownloadWorker(&WorkerRequestParams{ZoneID: "foo"})
177	want := WorkerScriptResponse{
178		successResponse,
179		WorkerScript{
180			Script: workerScript,
181		}}
182	if assert.NoError(t, err) {
183		assert.Equal(t, want.Script, res.Script)
184	}
185}
186
187func TestWorkers_DownloadWorkerWithName(t *testing.T) {
188	setup(UsingAccount("foo"))
189	defer teardown()
190
191	mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) {
192		assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
193		w.Header().Set("content-type", "application/javascript")
194		fmt.Fprintf(w, workerScript)
195	})
196	res, err := client.DownloadWorker(&WorkerRequestParams{ScriptName: "bar"})
197	want := WorkerScriptResponse{
198		successResponse,
199		WorkerScript{
200			Script: workerScript,
201		}}
202	if assert.NoError(t, err) {
203		assert.Equal(t, want.Script, res.Script)
204	}
205}
206
207func TestWorkers_DownloadWorkerWithNameErrorsWithoutAccountId(t *testing.T) {
208	setup()
209	defer teardown()
210
211	_, err := client.DownloadWorker(&WorkerRequestParams{ScriptName: "bar"})
212	assert.Error(t, err)
213}
214
215func TestWorkers_ListWorkerScripts(t *testing.T) {
216	setup(UsingAccount("foo"))
217	defer teardown()
218
219	mux.HandleFunc("/accounts/foo/workers/scripts", func(w http.ResponseWriter, r *http.Request) {
220		assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
221		w.Header().Set("content-type", "application-json")
222		fmt.Fprintf(w, listWorkersResponseData)
223	})
224
225	res, err := client.ListWorkerScripts()
226	sampleDate, _ := time.Parse(time.RFC3339Nano, "2018-04-22T17:10:48.938097Z")
227	want := []WorkerMetaData{
228		{
229			ID:         "bar",
230			ETAG:       "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
231			CreatedOn:  sampleDate,
232			ModifiedOn: sampleDate,
233		},
234		{
235			ID:         "baz",
236			ETAG:       "380dg51e97e80b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43088b",
237			CreatedOn:  sampleDate,
238			ModifiedOn: sampleDate,
239		},
240	}
241	if assert.NoError(t, err) {
242		assert.Equal(t, want, res.WorkerList)
243	}
244
245}
246
247func TestWorkers_UploadWorker(t *testing.T) {
248	setup()
249	defer teardown()
250
251	mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) {
252		assert.Equal(t, "PUT", r.Method, "Expected method 'PUT', got %s", r.Method)
253		contentTypeHeader := r.Header.Get("content-type")
254		assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader)
255		w.Header().Set("content-type", "application/javascript")
256		fmt.Fprintf(w, uploadWorkerResponseData)
257	})
258	res, err := client.UploadWorker(&WorkerRequestParams{ZoneID: "foo"}, workerScript)
259	formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z")
260	want := WorkerScriptResponse{
261		successResponse,
262		WorkerScript{
263			Script: workerScript,
264			WorkerMetaData: WorkerMetaData{
265				ETAG:       "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
266				Size:       191,
267				ModifiedOn: formattedTime,
268			},
269		}}
270	if assert.NoError(t, err) {
271		assert.Equal(t, want, res)
272	}
273
274}
275
276func TestWorkers_UploadWorkerWithName(t *testing.T) {
277	setup(UsingAccount("foo"))
278	defer teardown()
279
280	mux.HandleFunc("/accounts/foo/workers/scripts/bar", func(w http.ResponseWriter, r *http.Request) {
281		assert.Equal(t, "PUT", r.Method, "Expected method 'PUT', got %s", r.Method)
282		contentTypeHeader := r.Header.Get("content-type")
283		assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader)
284		w.Header().Set("content-type", "application/javascript")
285		fmt.Fprintf(w, uploadWorkerResponseData)
286	})
287	res, err := client.UploadWorker(&WorkerRequestParams{ScriptName: "bar"}, workerScript)
288	formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z")
289	want := WorkerScriptResponse{
290		successResponse,
291		WorkerScript{
292			Script: workerScript,
293			WorkerMetaData: WorkerMetaData{
294				ETAG:       "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
295				Size:       191,
296				ModifiedOn: formattedTime,
297			},
298		}}
299	if assert.NoError(t, err) {
300		assert.Equal(t, want, res)
301	}
302}
303
304func TestWorkers_UploadWorkerSingleScriptWithAccount(t *testing.T) {
305	setup(UsingAccount("foo"))
306	defer teardown()
307
308	mux.HandleFunc("/zones/foo/workers/script", func(w http.ResponseWriter, r *http.Request) {
309		assert.Equal(t, "PUT", r.Method, "Expected method 'PUT', got %s", r.Method)
310		contentTypeHeader := r.Header.Get("content-type")
311		assert.Equal(t, "application/javascript", contentTypeHeader, "Expected content-type request header to be 'application/javascript', got %s", contentTypeHeader)
312		w.Header().Set("content-type", "application/javascript")
313		fmt.Fprintf(w, uploadWorkerResponseData)
314	})
315	res, err := client.UploadWorker(&WorkerRequestParams{ZoneID: "foo"}, workerScript)
316	formattedTime, _ := time.Parse(time.RFC3339Nano, "2018-06-09T15:17:01.989141Z")
317	want := WorkerScriptResponse{
318		successResponse,
319		WorkerScript{
320			Script: workerScript,
321			WorkerMetaData: WorkerMetaData{
322				ETAG:       "279cf40d86d70b82f6cd3ba90a646b3ad995912da446836d7371c21c6a43977a",
323				Size:       191,
324				ModifiedOn: formattedTime,
325			},
326		}}
327	if assert.NoError(t, err) {
328		assert.Equal(t, want, res)
329	}
330}
331
332func TestWorkers_UploadWorkerWithNameErrorsWithoutAccountId(t *testing.T) {
333	setup()
334	defer teardown()
335
336	_, err := client.UploadWorker(&WorkerRequestParams{ScriptName: "bar"}, workerScript)
337	assert.Error(t, err)
338}
339
340func TestWorkers_CreateWorkerRoute(t *testing.T) {
341	setup()
342	defer teardown()
343
344	mux.HandleFunc("/zones/foo/workers/filters", func(w http.ResponseWriter, r *http.Request) {
345		assert.Equal(t, "POST", r.Method, "Expected method 'POST', got %s", r.Method)
346		w.Header().Set("content-type", "application-json")
347		fmt.Fprintf(w, createWorkerRouteResponse)
348	})
349	route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true}
350	res, err := client.CreateWorkerRoute("foo", route)
351	want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}}
352	if assert.NoError(t, err) {
353		assert.Equal(t, want, res)
354	}
355
356}
357
358func TestWorkers_CreateWorkerRouteEnt(t *testing.T) {
359	setup(UsingAccount("foo"))
360	defer teardown()
361
362	mux.HandleFunc("/zones/foo/workers/routes", func(w http.ResponseWriter, r *http.Request) {
363		assert.Equal(t, "POST", r.Method, "Expected method 'POST', got %s", r.Method)
364		w.Header().Set("content-type", "application-json")
365		fmt.Fprintf(w, createWorkerRouteResponse)
366	})
367	route := WorkerRoute{Pattern: "app1.example.com/*", Script: "test_script"}
368	res, err := client.CreateWorkerRoute("foo", route)
369	want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}}
370	if assert.NoError(t, err) {
371		assert.Equal(t, want, res)
372	}
373
374}
375
376func TestWorkers_CreateWorkerRouteSingleScriptWithAccount(t *testing.T) {
377	setup(UsingAccount("foo"))
378	defer teardown()
379
380	mux.HandleFunc("/zones/foo/workers/filters", func(w http.ResponseWriter, r *http.Request) {
381		assert.Equal(t, "POST", r.Method, "Expected method 'POST', got %s", r.Method)
382		w.Header().Set("content-type", "application-json")
383		fmt.Fprintf(w, createWorkerRouteResponse)
384	})
385	route := WorkerRoute{Pattern: "app1.example.com/*", Enabled: true}
386	res, err := client.CreateWorkerRoute("foo", route)
387	want := WorkerRouteResponse{successResponse, WorkerRoute{ID: "e7a57d8746e74ae49c25994dadb421b1"}}
388	if assert.NoError(t, err) {
389		assert.Equal(t, want, res)
390	}
391
392}
393
394func TestWorkers_DeleteWorkerRoute(t *testing.T) {
395	setup()
396	defer teardown()
397
398	mux.HandleFunc("/zones/foo/workers/filters/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) {
399		assert.Equal(t, "DELETE", r.Method, "Expected method 'DELETE', got %s", r.Method)
400		w.Header().Set("content-type", "application-json")
401		fmt.Fprintf(w, deleteWorkerRouteResponseData)
402	})
403	res, err := client.DeleteWorkerRoute("foo", "e7a57d8746e74ae49c25994dadb421b1")
404	want := WorkerRouteResponse{successResponse,
405		WorkerRoute{
406			ID: "e7a57d8746e74ae49c25994dadb421b1",
407		}}
408	if assert.NoError(t, err) {
409		assert.Equal(t, want, res)
410	}
411
412}
413
414func TestWorkers_DeleteWorkerRouteEnt(t *testing.T) {
415	setup(UsingAccount("foo"))
416	defer teardown()
417
418	mux.HandleFunc("/zones/foo/workers/filters/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) {
419		assert.Equal(t, "DELETE", r.Method, "Expected method 'DELETE', got %s", r.Method)
420		w.Header().Set("content-type", "application-json")
421		fmt.Fprintf(w, deleteWorkerRouteResponseData)
422	})
423	res, err := client.DeleteWorkerRoute("foo", "e7a57d8746e74ae49c25994dadb421b1")
424	want := WorkerRouteResponse{successResponse,
425		WorkerRoute{
426			ID: "e7a57d8746e74ae49c25994dadb421b1",
427		}}
428	if assert.NoError(t, err) {
429		assert.Equal(t, want, res)
430	}
431
432}
433
434func TestWorkers_ListWorkerRoutes(t *testing.T) {
435	setup()
436	defer teardown()
437
438	mux.HandleFunc("/zones/foo/workers/filters", func(w http.ResponseWriter, r *http.Request) {
439		assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
440		w.Header().Set("content-type", "application-json")
441		fmt.Fprintf(w, listRouteResponseData)
442	})
443
444	res, err := client.ListWorkerRoutes("foo")
445	want := WorkerRoutesResponse{successResponse,
446		[]WorkerRoute{
447			{ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Enabled: true},
448			{ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Enabled: false},
449		},
450	}
451	if assert.NoError(t, err) {
452		assert.Equal(t, want, res)
453	}
454}
455
456func TestWorkers_ListWorkerRoutesEnt(t *testing.T) {
457	setup(UsingAccount("foo"))
458	defer teardown()
459
460	mux.HandleFunc("/zones/foo/workers/routes", func(w http.ResponseWriter, r *http.Request) {
461		assert.Equal(t, "GET", r.Method, "Expected method 'GET', got %s", r.Method)
462		w.Header().Set("content-type", "application-json")
463		fmt.Fprintf(w, listRouteEntResponseData)
464	})
465
466	res, err := client.ListWorkerRoutes("foo")
467	want := WorkerRoutesResponse{successResponse,
468		[]WorkerRoute{
469			{ID: "e7a57d8746e74ae49c25994dadb421b1", Pattern: "app1.example.com/*", Script: "test_script_1", Enabled: true},
470			{ID: "f8b68e9857f85bf59c25994dadb421b1", Pattern: "app2.example.com/*", Script: "test_script_2", Enabled: true},
471			{ID: "2b5bf4240cd34c77852fac70b1bf745a", Pattern: "app3.example.com/*", Script: "", Enabled: false},
472		},
473	}
474	if assert.NoError(t, err) {
475		assert.Equal(t, want, res)
476	}
477}
478
479func TestWorkers_UpdateWorkerRoute(t *testing.T) {
480	setup()
481	defer teardown()
482
483	mux.HandleFunc("/zones/foo/workers/filters/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) {
484		assert.Equal(t, "PUT", r.Method, "Expected method 'PUT', got %s", r.Method)
485		w.Header().Set("content-type", "application-json")
486		fmt.Fprintf(w, updateWorkerRouteResponse)
487	})
488	route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true}
489	res, err := client.UpdateWorkerRoute("foo", "e7a57d8746e74ae49c25994dadb421b1", route)
490	want := WorkerRouteResponse{successResponse,
491		WorkerRoute{
492			ID:      "e7a57d8746e74ae49c25994dadb421b1",
493			Pattern: "app3.example.com/*",
494			Enabled: true,
495		}}
496	if assert.NoError(t, err) {
497		assert.Equal(t, want, res)
498	}
499
500}
501
502func TestWorkers_UpdateWorkerRouteEnt(t *testing.T) {
503	setup(UsingAccount("foo"))
504	defer teardown()
505
506	mux.HandleFunc("/zones/foo/workers/routes/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) {
507		assert.Equal(t, "PUT", r.Method, "Expected method 'PUT', got %s", r.Method)
508		w.Header().Set("content-type", "application-json")
509		fmt.Fprintf(w, updateWorkerRouteEntResponse)
510	})
511	route := WorkerRoute{Pattern: "app3.example.com/*", Script: "test_script_1"}
512	res, err := client.UpdateWorkerRoute("foo", "e7a57d8746e74ae49c25994dadb421b1", route)
513	want := WorkerRouteResponse{successResponse,
514		WorkerRoute{
515			ID:      "e7a57d8746e74ae49c25994dadb421b1",
516			Pattern: "app3.example.com/*",
517			Script:  "test_script_1",
518		}}
519	if assert.NoError(t, err) {
520		assert.Equal(t, want, res)
521	}
522
523}
524
525func TestWorkers_UpdateWorkerRouteSingleScriptWithAccount(t *testing.T) {
526	setup(UsingAccount("foo"))
527	defer teardown()
528
529	mux.HandleFunc("/zones/foo/workers/filters/e7a57d8746e74ae49c25994dadb421b1", func(w http.ResponseWriter, r *http.Request) {
530		assert.Equal(t, "PUT", r.Method, "Expected method 'PUT', got %s", r.Method)
531		w.Header().Set("content-type", "application-json")
532		fmt.Fprintf(w, updateWorkerRouteEntResponse)
533	})
534	route := WorkerRoute{Pattern: "app3.example.com/*", Enabled: true}
535	res, err := client.UpdateWorkerRoute("foo", "e7a57d8746e74ae49c25994dadb421b1", route)
536	want := WorkerRouteResponse{successResponse,
537		WorkerRoute{
538			ID:      "e7a57d8746e74ae49c25994dadb421b1",
539			Pattern: "app3.example.com/*",
540			Script:  "test_script_1",
541		}}
542	if assert.NoError(t, err) {
543		assert.Equal(t, want, res)
544	}
545
546}
547