add testsuite and testcase list pages in frontend of testing-scheduler
[bottlenecks.git] / testing-scheduler / ui / src / components / testcase.vue
diff --git a/testing-scheduler/ui/src/components/testcase.vue b/testing-scheduler/ui/src/components/testcase.vue
new file mode 100644 (file)
index 0000000..4d15dc7
--- /dev/null
@@ -0,0 +1,349 @@
+<template>\r
+  <div class="wrapper wrapper-content animated fadeIn">\r
+    <div class="row" style="margin-bottom: 20px;">\r
+      <div class="col-md-8">\r
+        <ol class="breadcrumb" style="padding-left: 20px; font-size: 17px;">\r
+          <li>\r
+            <router-link to="/" >root</router-link>\r
+          </li>\r
+          <li>\r
+            <router-link :to="{ path: '/testcase', query: { name: sname }}"><b>{{this.$route.query.name}}</b></router-link>\r
+          </li>\r
+        </ol>\r
+      </div>\r
+    </div>\r
+    <div id="page-content" style="" class="row">\r
+        <div class="col-lg-8">\r
+            <div class="ibox">\r
+                <div class="ibox-title">\r
+                    <h5 style="font-size:26px;margin-top: -3px;">Test Case</h5>\r
+                    <div class="ibox-tools">\r
+                    <button class="btn btn-info btn-sm my-button-sm" type="button" v-on:click="runMultiTestcase()">Run</button>\r
+                    <button class="btn btn-success btn-sm my-button-sm" type="button" v-on:click="create()">Create</button>\r
+                    <button class="btn btn-danger btn-sm my-button-sm" v-on:click="deleteCases()" type="button">Delete</button>\r
+                    <a class="collapse-link">\r
+                        <i class="fa fa-chevron-up"></i>\r
+                    </a>\r
+                    <a class="fullscreen-link">\r
+                        <i class="fa fa-expand"></i>\r
+                    </a>\r
+                    </div>\r
+                </div>\r
+                <div class="ibox-content" style="text-align:center;">\r
+                <table class="my-table table table-bordered" cellspacing="0" cellpadding="0" style="text-align: center;">\r
+                    <thead>\r
+                        <tr>\r
+                              <td class="checkbox1" style="width:20px"><input type="checkbox" v-model="selectAll"> All</td>\r
+                              <td class="smallbox" style="with:250px;">TestCase Name</td>\r
+                        </tr>\r
+                    </thead>\r
+                    <tbody>\r
+                        <tr v-for="testcase in testcases">\r
+                          <td><input class="checkbox1" style="width:20px" type="checkbox" v-model="selected" :value="testcase.testcase"> </td>\r
+                          <td class="smallbox" style="with:250px;"><router-link :to="{ path: '/content', query: { suiteName: sname, caseName: testcase.testcase } }">{{testcase.testcase}}</router-link></td>\r
+                        </tr>\r
+                    </tbody>\r
+                    <tfoot id="create-box" style="display: none">\r
+                        <tr>\r
+                            <td class="checkbox1" style="width:20px"><input type="checkbox"> </td>\r
+                            <td class="smallbox" style="with:250px;"><input type="text" v-model="newCase" @keydown.enter="additem" ></td>\r
+                        </tr>\r
+                    </tfoot>\r
+                  </table>\r
+                </div>\r
+            </div>\r
+        </div>\r
+    </div>\r
+    <hr />\r
+    <div class="row">\r
+      <div class="col-lg-12">\r
+          <div class="ibox">\r
+              <div class="ibox-title">\r
+                  <h5 style="font-size:26px;margin-top: -3px;">Workflow</h5>\r
+                  <div class="ibox-tools">\r
+                      <a class="collapse-link">\r
+                          <i class="fa fa-chevron-up"></i>\r
+                      </a>\r
+                      <a class="fullscreen-link">\r
+                          <i class="fa fa-expand"></i>\r
+                      </a>\r
+                  </div>\r
+              </div>\r
+              <div class="ibox-content" style="padding-top: 30px;">\r
+                <div id="executing" class="row" style="padding: 0 30px 60px;">\r
+                    <div class="col-md-offset-2 col-md-8">\r
+                      <div class="table-responsive">\r
+                        <table class="table text-center" style="margin-top: 30px;">\r
+                          <thead>\r
+                            <tr>\r
+                              <th class="text-center">#</th>\r
+                              <th class="text-center">testcase</th>\r
+                              <th class="text-center">status</th>\r
+                              <th class="text-center">operation</th>\r
+                            </tr>\r
+                          </thead>\r
+                          <tbody>\r
+                            <tr v-for="testcase in runTestcases">\r
+                              <td>{{ testcase.id }}</td>\r
+                              <td>{{ testcase.testcase }}</td>\r
+                              <td><span class="badge" v-bind:class="'badge-' + statusClass(testcase.status)">{{ testcase.status }}</span></td>\r
+                              <td>\r
+                                <div style="display: inline-block;min-width: 130px;">\r
+                                  <button class="btn btn-primary btn-outline btn-xs fadeIn" v-on:click="runTestcase()" v-show="testcase.status == 'failed'">rerun</button>\r
+                                  <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
+                                </div>\r
+                              </td>\r
+                            </tr>\r
+                          </tbody>\r
+                        </table>\r
+                      </div>\r
+                    </div>\r
+                </div>\r
+                <hr class="hr-line-solid">\r
+                <div class="row" style="margin-top: 60px;">\r
+                  <wfresult v-bind:workflowId="workflowId" v-bind:wfloading='wfloading' v-bind:wfJson='wfJson' v-on:wfComplete="wfComplete = $event"></wfresult>\r
+                </div>\r
+              </div>\r
+          </div>\r
+      </div>\r
+    </div>\r
+  </div>\r
+</template>\r
+<script>\r
+import wfresult from './workflow_graph/wfresult.vue'\r
+import showMessage from './message/showMessage.js'\r
+export default {\r
+  name: 'testcase',\r
+  data () {\r
+    return {\r
+      testcases: [],\r
+      sname: this.$route.query.name,\r
+      newCase:'',\r
+      addstory:'',\r
+      workflowId: '',\r
+      wfloading: false,\r
+      wfJson: '',\r
+      selected: [],\r
+      curRunningId: 0,\r
+      runTestcases: [],\r
+      wfComplete: false\r
+    }\r
+  },\r
+  created: function() {\r
+    var self = this;\r
+    var msgTitle = "GET -- TESTCASES";\r
+    var errorInfo = "Failed to get testcase list.";\r
+    $.ajax({\r
+      url: this.global.SERVER_ADDR + "testsuite/content",\r
+      method:"GET",\r
+      data:{\r
+        suiteName:  this.$route.query.name\r
+      },\r
+      success:function (data) {\r
+        if(data['code'] == 200) {\r
+          self.testcases = data['result'];\r
+        } else {\r
+          showMessage(data['code'], msgTitle, errorInfo, data['error']);\r
+        }\r
+      },\r
+      error: function(obj, status, msg) {\r
+        showMessage(status, msgTitle, errorInfo, msg);\r
+      }\r
+    });\r
+  },\r
+  computed: {\r
+    selectAll: {\r
+      get: function () {\r
+        return this.testcases ? this.selected.length == this.testcases.length : false;\r
+      },\r
+      set: function (value) {\r
+        var selected = [];\r
+        if (value) {\r
+          this.testcases.forEach(function (testcase) {\r
+            selected.push(testcase.testcase);\r
+          });\r
+        }\r
+        this.selected = selected;\r
+      }\r
+    }\r
+  },\r
+  methods:{\r
+    create: function () {\r
+      var cbox = document.getElementById("create-box");\r
+      cbox.style.display = "table-footer-group";\r
+    },\r
+    additem: function () {\r
+      var self = this;\r
+      var msgTitle = "CREATE -- TESTCASE";\r
+      const caseName = self.newCase.trim();\r
+      if(caseName)\r
+      {\r
+        $.ajax({\r
+          url: this.global.SERVER_ADDR + "testcase/new",\r
+          method:"POST",\r
+          data:{\r
+            suiteName: self.sname,\r
+            caseName: caseName\r
+          },\r
+          success:function (data) {\r
+            if(data['code'] == 200){\r
+              self.testcases.push({\r
+                id: self.testcases.length + 1 ,\r
+                testcase: caseName,\r
+              });\r
+              showMessage(data['code'], msgTitle, "Create <strong>" + caseName + "</strong> succesfully!");\r
+            } else {\r
+              showMessage(data['code'], msgTitle, "Failed to create <strong>" + caseName + "</strong>!", data['error']);\r
+            }\r
+          },\r
+          error: function(obj, status, msg) {\r
+            showMessage(status, msgTitle, "Failed to create <strong>" + caseName + "</strong>!", msg);\r
+          }\r
+        });\r
+      }\r
+      var cbox = document.getElementById("create-box");\r
+      cbox.style.display = "none";\r
+      this.newCase = '';\r
+    },\r
+    deleteCases:function () {\r
+      var self = this;\r
+      var msgTitle = "DELETE -- TESTCASE";\r
+      var deleteArr = self.selected.slice(0);\r
+      self.testcases = self.testcases.filter(item => {\r
+          for(var i in deleteArr) {\r
+            if(item.testcase == deleteArr[i]) {\r
+              return false;\r
+            }\r
+          }\r
+          return true;\r
+      });\r
+      self.selected = [];\r
+      for(var i in deleteArr)\r
+      {\r
+        $.ajax({\r
+          url: this.global.SERVER_ADDR + "testcase/delete",\r
+          method: "POST",\r
+          data: {\r
+            suiteName: self.sname,\r
+            caseName: deleteArr[i]\r
+          },\r
+          success: function(data) {\r
+            if(data['code'] == 200){\r
+              showMessage(data['code'], msgTitle, "Delete <strong>" + deleteArr[i] + "</strong> succesfully!");\r
+            } else {\r
+              showMessage(data['code'], msgTitle, "Failed to delete <strong>" + deleteArr[i] + "</strong>!", data['error']);\r
+            }\r
+          },\r
+          error: function(obj, status, msg) {\r
+            showMessage(status, msgTitle, "Failed to delete <strong>" + deleteArr[i] + "</strong>!", msg);\r
+          }\r
+        });\r
+      }\r
+    },\r
+    runMultiTestcase: function() {\r
+      var self = this;\r
+      var msgTitle = "RUN -- TESTCASES";\r
+      self.runTestcases = [];\r
+      if(self.selected.length == 0) {\r
+        showMessage("warning", msgTitle, "please select one!");\r
+        return;\r
+      }\r
+      for(var i=0; i < self.selected.length; i++) {\r
+        var testcaseItem = {'id': i, 'testcase': '', 'status': "waiting"};\r
+        testcaseItem['testcase'] = self.selected[i];\r
+        self.runTestcases.push(testcaseItem);\r
+      }\r
+      self.curRunningId = 0;\r
+      showMessage("info", msgTitle, "start to run <strong>testcases</strong>");\r
+      self.runOneTestcase();\r
+    },\r
+    runOneTestcase: function() {\r
+      var self = this;\r
+      var msgTitle = "RUN -- TESTCASE";\r
+      if (self.curRunningId == self.runTestcases.length) {\r
+        self.curRunningId = 0;\r
+        return;\r
+      }\r
+      self.wfComplete = false;\r
+      var i = self.curRunningId;\r
+      self.runTestcases[i]['status'] = "running";\r
+      $.ajax({\r
+          url: self.global.SERVER_ADDR + "execute/testcase",\r
+          method: "POST",\r
+          data: {\r
+              "suiteName": self.sname,\r
+              "caseName": self.runTestcases[self.curRunningId]['testcase']\r
+          },\r
+          beforeSend: function(XHR) {\r
+              self.wfloading = true;\r
+          },\r
+          success: function(data) {\r
+              if(data['code'] == 200) {\r
+                  self.workflowId = data['result']['workflowId'];\r
+                  $.ajax({\r
+                      url: self.global.SERVER_ADDR + "story-content",\r
+                      method: "GET",\r
+                      data: {\r
+                          "service":  self.sname,\r
+                          "story": self.runTestcases[self.curRunningId]['testcase']\r
+                      },\r
+                      success: function(data) {\r
+                          if(data['code'] == 200) {\r
+                              self.wfJson = data['result']['content'];\r
+                          } else {\r
+                            showMessage(data['code'], msgTitle, "workflow.json get failed!");\r
+                          }\r
+                      },\r
+                      error: function(obj, status, msg) {\r
+                        showMessage(status, msgTitle, msg);\r
+                      }\r
+                  });\r
+              } else {\r
+                var i = self.curRunningId;\r
+                self.runTestcases[i]['status'] = "failed";\r
+                self.wfloading = false;\r
+                showMessage(data['code'], msgTitle, "Failed to run <strong>" + self.runTestcases[i]['testcase'] + "</strong>", data['error']);\r
+              }\r
+          },\r
+          error: function(obj, status, msg) {\r
+            var i = self.curRunningId;\r
+            self.runTestcases[i]['status'] = "failed";\r
+            self.wfloading = false;\r
+            showMessage(status, msgTitle, "Failed to run <strong>" + self.runTestcases[i]['testcase'] + "</strong>", msg);\r
+          }\r
+      });\r
+    },\r
+    statusClass: function(status) {\r
+      if(status == "waiting") {\r
+        return "success";\r
+      }\r
+      if(status == "running") {\r
+        return "warning";\r
+      }\r
+      if(status == "pass") {\r
+        return "primary";\r
+      }\r
+      if(status == "failed") {\r
+        return "danger";\r
+      }\r
+    },\r
+    runNextCase: function(obj) {\r
+      $(obj).parent().css({"display": "none"});\r
+      var i = this.curRunningId++;\r
+      this.runOneTestcase();\r
+    }\r
+  },\r
+  watch: {\r
+    wfComplete: function(val) {\r
+      if(val == false) return;\r
+      this.wfloading = false;\r
+      var i = this.curRunningId++;\r
+      this.runTestcases[i]['status'] = "pass";\r
+      this.runOneTestcase();\r
+    }\r
+  },\r
+  components: {\r
+    wfresult\r
+  }\r
+}\r
+</script>
\ No newline at end of file