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