3752b2ece416b914ba17e1c74d20efabb4d2063a
[bottlenecks.git] / testing-scheduler / ui / src / components / testsuite.vue
1 <template>\r
2   <div class="wrapper wrapper-content animated fadeIn">\r
3     <div class="row" style="margin-bottom: 20px;">\r
4       <div class="col-md-8">\r
5         <ol class="breadcrumb" style="padding-left: 20px; font-size: 17px;">\r
6           <li>\r
7             <router-link to="/" >root</router-link>\r
8           </li>\r
9         </ol>\r
10       </div>\r
11     </div>\r
12     <div id="page-content" class="row">\r
13       <div class="col-lg-8">\r
14         <div class="ibox">\r
15             <div class="ibox-title">\r
16                 <h5 style="font-size:26px;margin-top: -3px;">Test Suite</h5>\r
17                 <div class="ibox-tools">\r
18                     <button class="btn btn-info btn-sm my-button-sm" type="button" v-on:click="runTestsuites()">Run</button>\r
19                     <button class="btn btn-success btn-sm my-button-sm" type="button" v-on:click="createSuite()">Create</button>\r
20                     <button class="btn btn-danger btn-sm my-button-sm" v-on:click="deleteSuites()" type="button">Delete</button>\r
21                     <a class="collapse-link">\r
22                         <i class="fa fa-chevron-up"></i>\r
23                     </a>\r
24                     <a class="fullscreen-link">\r
25                         <i class="fa fa-expand"></i>\r
26                     </a>\r
27                 </div>\r
28             </div>\r
29             <div class="ibox-content" style="text-align:center;">\r
30               <table class="my-table table table-bordered" cellspacing="0" cellpadding="0" style="text-align: center;">\r
31                 <thead>\r
32                   <tr>\r
33                     <td style="width:20px"><input type="checkbox" v-model="selectAll"> All</td>\r
34                     <td class="smallbox" style="with:250px;">TestSuite Name</td>\r
35                   </tr>\r
36                 </thead>\r
37                 <tbody>\r
38                     <tr v-for="testsuite in testsuites">\r
39                       <td><input style="width:20px" type="checkbox" v-model="selected" :value="testsuite.testsuite"> </td>\r
40                       <td class="smallbox" style="with:250px;"><router-link :to="{ path: '/testcase', query: { name: testsuite.testsuite }}" >{{testsuite.testsuite}}</router-link></td>\r
41                     </tr>\r
42                 </tbody>\r
43                 <tfoot id="create-box" style="display: none">\r
44                     <tr>\r
45                       <td style="width:20px"><input type="checkbox"> </td>\r
46                       <td class="smallbox" style="with:250px;"><input type="text" v-model="newSuite" @keydown.enter="addItem" ></td>\r
47                     </tr>\r
48                 </tfoot>\r
49               </table>\r
50             </div>\r
51         </div>\r
52       </div>\r
53     </div>\r
54     <hr />\r
55     <div class="row">\r
56       <div class="col-lg-12">\r
57           <div class="ibox">\r
58               <div class="ibox-title">\r
59                   <h5 style="font-size:26px;margin-top: -3px;">Workflow</h5>\r
60                   <div class="ibox-tools">\r
61                       <a class="collapse-link">\r
62                           <i class="fa fa-chevron-up"></i>\r
63                       </a>\r
64                       <a class="fullscreen-link">\r
65                           <i class="fa fa-expand"></i>\r
66                       </a>\r
67                   </div>\r
68               </div>\r
69               <div class="ibox-content" style="padding-top: 30px;">\r
70                 <div id="executing" class="row" style="padding: 0 30px 60px;">\r
71                   <div class="col-md-offset-2 col-md-8">\r
72                       <div class="table-responsive">\r
73                         <table class="table text-center" style="margin-top: 30px;">\r
74                           <thead>\r
75                             <tr>\r
76                               <th class="text-center">#</th>\r
77                               <th class="text-center">testcase</th>\r
78                               <th class="text-center">status</th>\r
79                               <th class="text-center">operation</th>\r
80                             </tr>\r
81                           </thead>\r
82                           <tbody>\r
83                             <tr v-for="testcase in casesInSuite">\r
84                               <td>{{ testcase.id }}</td>\r
85                               <td>{{ testcase.testcase }}</td>\r
86                               <td><span class="badge" v-bind:class="'badge-' + statusClass(testcase.status)">{{ testcase.status }}</span></td>\r
87                               <td>\r
88                               <div style="display: inline-block;min-width: 130px;">\r
89                                 <button class="btn btn-primary btn-outline btn-xs fadeIn" v-on:click="runTestcase()" v-show="testcase.status == 'failed'">rerun</button>\r
90                                 <button class="btn btn-primary btn-outline btn-xs fadeIn" v-on:click="runNextCase($event.target)" v-show="testcase.status == 'failed'">run next one</button>\r
91                               </div>\r
92                               </td>\r
93                             </tr>\r
94                           </tbody>\r
95                         </table>\r
96                       </div>\r
97                   </div>\r
98                 </div>\r
99                 <hr class="hr-line-solid">\r
100                 <div class="row" style="margin-top: 60px;">\r
101                   <wfresult v-bind:workflowId="workflowId" v-bind:wfloading='wfloading' v-bind:wfJson='wfJson' v-on:wfComplete="wfComplete = $event"></wfresult>\r
102                 </div>\r
103               </div>\r
104           </div>\r
105       </div>\r
106     </div>\r
107   </div>\r
108 </template>\r
109 <script>\r
110 import wfresult from './workflow_graph/wfresult.vue'\r
111 import showMessage from './message/showMessage.js'\r
112 export default {\r
113   name: 'testsuite',\r
114   data () {\r
115     return {\r
116       newSuite : '',\r
117       testsuites : '',\r
118       service_selected : '',\r
119       workflowId: '',\r
120       wfloading: false,\r
121       wfJson: '',\r
122       selected: [],\r
123       casesInSuite: [],\r
124       running: {\r
125         suiteName: "",\r
126         caseName: ""\r
127       },\r
128       curRunningId: 0,\r
129       wfComplete: false\r
130     }\r
131   },\r
132   created: function() {\r
133     var self = this;\r
134     var msgTitle = "GET -- TESTSUITES";\r
135     var errorInfo = "Failed to get testsuite list.";\r
136     $.ajax({\r
137       url: this.global.SERVER_ADDR + "testsuite/list",\r
138       method:"GET",\r
139       data:{},\r
140       success:function (data) {\r
141         if(data['code'] == 200) {\r
142           self.testsuites = data['result'];\r
143         } else {\r
144           showMessage(data['code'], msgTitle, errorInfo, data['error']);\r
145         }\r
146       },\r
147       error: function(obj, status, msg) {\r
148         showMessage(status, msgTitle, errorInfo, msg);\r
149       }\r
150     });\r
151   },\r
152   computed: {\r
153     selectAll: {\r
154       get: function () {\r
155         return this.testsuites ? this.selected.length == this.testsuites.length : false;\r
156       },\r
157       set: function (value) {\r
158         var selected = [];\r
159         if (value) {\r
160           this.testsuites.forEach(function (story) {\r
161             selected.push(story.testsuite);\r
162           });\r
163         }\r
164         this.selected = selected;\r
165       }\r
166     }\r
167 },\r
168   methods:{\r
169     createSuite: function () {\r
170       var cbox = document.getElementById("create-box");\r
171       cbox.style.display = "table-footer-group";\r
172     },\r
173     addItem: function () {\r
174       var self = this;\r
175       const suiteName = self.newSuite.trim();\r
176       if(suiteName)\r
177       {\r
178         var msgTitle = "CREATE -- TESTSUITE";\r
179         $.ajax({\r
180           url: this.global.SERVER_ADDR + "testsuite/new",\r
181           method:"POST",\r
182           data:{\r
183             suiteName:suiteName\r
184           },\r
185           success:function(data){\r
186             if(data['code'] == 200){\r
187               self.testsuites.push({\r
188                 id: self.testsuites.length + 1 ,\r
189                 testsuite: suiteName,\r
190               });\r
191               showMessage(data['code'], msgTitle, "Create <strong>" + suiteName + "</strong> succesfully!");\r
192             } else {\r
193               showMessage(data['code'], msgTitle, "Failed to create <strong>" + suiteName + "</strong>!", data['error']);\r
194             }\r
195           },\r
196           error: function(obj, status, msg) {\r
197             showMessage(status, msgTitle, "Failed to create <strong>" + suiteName + "</strong>!", msg);\r
198           }\r
199         })\r
200       }\r
201       var cbox = document.getElementById("create-box");\r
202       cbox.style.display = "none";\r
203       this.newSuite = '';\r
204     },\r
205     deleteSuites:function () {\r
206       var self = this;\r
207       var msgTitle = "DELETE -- TESTSUITE";\r
208       var deleteArr = self.selected.slice(0);\r
209       self.testsuites = self.testsuites.filter(item => {\r
210           for(var i in deleteArr) {\r
211             if(item.testsuite == deleteArr[i]) {\r
212               return false;\r
213             }\r
214           }\r
215           return true;\r
216       });\r
217       self.selected = [];\r
218       for(var i in deleteArr)\r
219       {\r
220         $.ajax({\r
221           url: this.global.SERVER_ADDR + "testsuite/delete",\r
222           method:"POST",\r
223           data:{\r
224             suiteName: deleteArr[i]\r
225           },\r
226           success:function (data) {\r
227             if(data['code'] == 200){\r
228               showMessage(data['code'], msgTitle, "Delete <strong>" + deleteArr[i] + "</strong> succesfully!");\r
229             } else {\r
230               showMessage(data['code'], msgTitle, "Failed to delete <strong>" + deleteArr[i] + "</strong>!", data['error']);\r
231             }\r
232           },\r
233           error: function(obj, status, msg) {\r
234             showMessage(status, msgTitle, "Failed to delete <strong>" + deleteArr[i] + "</strong>!", msg);\r
235           }\r
236         });\r
237       }\r
238     },\r
239     runTestsuites: function() {\r
240       var self = this;\r
241       var msgTitle = "RUN -- TESTSUITE";\r
242       if(self.selected.length == 0) {\r
243         showMessage("warning", msgTitle, "please select one!");\r
244         return;\r
245       } else if(self.selected.length != 1) {\r
246         showMessage("warning", msgTitle, "sorry, one suite at a time!");\r
247         return;\r
248       }\r
249       self.running.suiteName = self.selected[0];\r
250       $.ajax({\r
251         url: this.global.SERVER_ADDR + "testsuite/content",\r
252         method: "GET",\r
253         data: {\r
254           "suiteName": self.running.suiteName\r
255         },\r
256         success: function(data) {\r
257           if (data['code'] == 200) {\r
258             var caseList = data['result'];\r
259             if(caseList.length == 0) {\r
260               showMessage("info", msgTitle, "<strong>" + self.running.suiteName + "</strong> is empty!");\r
261               return;\r
262             }\r
263             for(var i=0; i < caseList.length; i++) {\r
264               caseList[i]['status'] = "waiting";\r
265             }\r
266             self.casesInSuite = caseList;\r
267             showMessage(data['code'], msgTitle, "Start to run <strong>" + self.running.suiteName + "</strong>");\r
268             self.runTestcase();\r
269           } else {\r
270             showMessage(data['code'], msgTitle, "Failed to run <strong>" + self.running.suiteName + "</strong>", data['error']);\r
271           }\r
272         },\r
273         error: function(obj, status, msg) {\r
274           showMessage(status, msgTitle, "Failed to run <strong>" + self.running.suiteName + "</strong>", msg);\r
275         }\r
276       });\r
277     },\r
278     runTestcase: function() {\r
279         var self = this;\r
280         var msgTitle = "RUN -- TESTCASE";\r
281         if (self.curRunningId == self.casesInSuite.length) {\r
282           self.curRunningId = 0;\r
283           return;\r
284         }\r
285         self.wfComplete = false;\r
286         var i = self.curRunningId;\r
287         self.casesInSuite[i]['status'] = "running";\r
288         self.running.caseName = self.casesInSuite[i]['testcase'];\r
289         $.ajax({\r
290           url: self.global.SERVER_ADDR + "execute/testcase",\r
291           method: "POST",\r
292           data: {\r
293               "suiteName": self.running.suiteName,\r
294               "caseName": self.running.caseName\r
295           },\r
296           beforeSend: function(XHR) {\r
297               self.wfloading = true;\r
298           },\r
299           success: function(data) {\r
300               if(data['code'] == 200) {\r
301                 self.workflowId = data['result']['workflowId'];\r
302                 $.ajax({\r
303                     url: self.global.SERVER_ADDR + "story-content",\r
304                     method: "GET",\r
305                     data: {\r
306                         "service":  self.running.suiteName,\r
307                         "story": self.running.caseName\r
308                     },\r
309                     success: function(data) {\r
310                         if(data['code'] == 200) {\r
311                             self.wfJson = data['result']['content'];\r
312                         } else {\r
313                             showMessage(data['code'], msgTitle, "workflow.json get failed!");\r
314                         }\r
315                     },\r
316                     error: function(obj, status, msg) {\r
317                       showMessage(status, msgTitle, msg);\r
318                     }\r
319                 });\r
320               } else {\r
321                 var i = self.curRunningId;\r
322                 self.casesInSuite[i]['status'] = "failed";\r
323                 self.wfloading = false;\r
324                 showMessage(data['code'], msgTitle, "Failed to run <strong>" + self.running.caseName + "</strong>", data['error']);\r
325               }\r
326           },\r
327           error: function(obj, status, msg) {\r
328             var i = self.curRunningId;\r
329             self.casesInSuite[i]['status'] = "failed";\r
330             self.wfloading = false;\r
331             showMessage(status, msgTitle, "Failed to run <strong>" + self.running.caseName + "</strong>", msg);\r
332           }\r
333         });\r
334     },\r
335     statusClass: function(status) {\r
336       if(status == "waiting") {\r
337         return "success";\r
338       }\r
339       if(status == "running") {\r
340         return "warning";\r
341       }\r
342       if(status == "pass") {\r
343         return "primary";\r
344       }\r
345       if(status == "failed") {\r
346         return "danger";\r
347       }\r
348     },\r
349     runNextCase: function(obj) {\r
350       $(obj).parent().css({"display": "none"});\r
351       var i = this.curRunningId++;\r
352       this.runTestcase();\r
353     }\r
354   },\r
355   watch: {\r
356     wfComplete: function(val) {\r
357       if(val == false) return;\r
358       this.wfloading = false;\r
359       var i = this.curRunningId++;\r
360       this.casesInSuite[i]['status'] = "pass";\r
361       // run the next testcase.\r
362       this.runTestcase();\r
363     }\r
364   },\r
365   components: {\r
366     wfresult\r
367   }\r
368 }\r
369 </script>