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