gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-backoffice] branch master updated (956e3e4 -> 82430f


From: gnunet
Subject: [GNUnet-SVN] [taler-backoffice] branch master updated (956e3e4 -> 82430fd)
Date: Fri, 12 Jan 2018 14:09:05 +0100

This is an automated email from the git hooks/post-receive script.

marcello pushed a change to branch master
in repository backoffice.

    from 956e3e4  non-working "/track/transfer" test case
     new 5af0b8e  better separation logic -vs- prsentation
     new 82430fd  Adjust tests after logic -vs- presentation separation

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 js/backoffice.js | 339 ++++++++++++++++++++++++++++++++++++-------------------
 js/test/main.js  |  81 ++-----------
 2 files changed, 238 insertions(+), 182 deletions(-)

diff --git a/js/backoffice.js b/js/backoffice.js
index c5524e1..fc00f77 100644
--- a/js/backoffice.js
+++ b/js/backoffice.js
@@ -28,7 +28,6 @@
 "use strict";
 
 var FRACTION = 100000000;
-var TIMESTAMP = 0;
 var START = 0;
 var DELTA = 5
 var LAST = 0;
@@ -40,10 +39,10 @@ var LAST = 0;
  * it wrong.
  */
 function amount_to_string(amount){
-  var number = Number(amount.value) + (Number(amount.fraction)/FRACTION);
+  var number = Number(amount.value) +
+              (Number(amount.fraction)/FRACTION);
   return `${number.toFixed(2)} ${amount.currency}`;
 }
-module.exports.amount_to_string = amount_to_string;
 
 function close_popup(){
 
@@ -57,7 +56,6 @@ function close_popup(){
 
   toggle_overlay(true);
 }
-module.exports.close_popup = close_popup;
 
 function amount_sum(a1, a2){
   if(a1.currency != a2.currency)
@@ -72,6 +70,9 @@ function amount_sum(a1, a2){
   return ret;
 }
 
+/**
+ * Parse Taler /Date(x)/ into human-friendly format.
+ */
 function parse_date(date){
 
   var split = date.match(/Date\(([0-9]+)\)/);
@@ -92,6 +93,10 @@ function parse_date(date){
   return `${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}, 
${hours}:${minutes}`;
 }
 
+/**
+ * Make screen-centerd box (which show a order's tracks)
+ * appear/disappear.
+ */
 function toggle_overlay(force_close){
   var overlay = document.getElementsByClassName("overlay")[0];
   if(overlay.style.visibility == "visible" || force_close){
@@ -106,6 +111,10 @@ function toggle_overlay(force_close){
 
 }
 
+/**
+ * Draws a line at the bottom of a orders list to indicate
+ * they have all being paid out by the same WTID.
+ */
 function make_marker(wtid){
   var tr = document.createElement("tr");
   var td = document.createElement("td");
@@ -118,10 +127,20 @@ function make_marker(wtid){
   return tr;
 }
 
-function track_transfer(exchange, wtid){
-  var loader = document.getElementsByClassName("loader")[0]; 
-  loader.style.visibility = "visible";
-  var qs = 
`/track/transfer?exchange=${exchange}&wtid=${wtid}&instance=${get_instance()}`;
+
+/**
+ * Use the /track/transfer API from the frontend.  Once data
+ * arrives, it calls a UI function which lists all the entries
+ * in the page.
+ *
+ * 'cb' is a UI transforming function.  Typically, it is set to
+ * 'fill_table()'.
+ */
+module.exports.track_transfer = function(exchange, wtid, cb){
+  var qs = `/track/transfer?` +
+           `exchange=${exchange}&` +
+           `wtid=${wtid}&` +
+           `instance=${get_instance()}`;
   var req = new XMLHttpRequest();
   req.open("GET", qs, true);
   req.onload = function(){
@@ -129,12 +148,7 @@ function track_transfer(exchange, wtid){
       switch(req.status){
       case 200:
         var tracks = JSON.parse(req.responseText);
-        clean_results();
-        /**
-         * close the popup which is now on the focus showing
-         * the tracks from one order. */
-        close_popup();
-        fill_table(tracks.deposits_sums, tracks.execution_time, wtid);
+        cb(true, tracks.deposits_sums, tracks.execution_time, wtid);
         break;
       case 400:
         console.log("Bad request, check submitted data!");
@@ -146,98 +160,160 @@ function track_transfer(exchange, wtid){
   }
   req.send();
 }
-module.exports.track_transfer = track_transfer;
 
-function track_order(order_id){
+
+/**
+ * Call /track/order API offered by the frontend.  Once data
+ * arrives it calls a UI routine which fills the "entries table"
+ * in the page.
+ */
+module.exports.track_order = function(order_id, cb){
   var req = new XMLHttpRequest();
-  req.open("GET", 
`/track/order?order_id=${order_id}&instance=${get_instance()}`, true);
+  var url = `/track/order?` +
+            `order_id=${order_id}&` +
+            `instance=${get_instance()}`
+  req.open("GET", url, true);
   req.onload = function(){
     if (4 == req.readyState){
-      if(200 == req.status){
-        var tracks = JSON.parse(req.responseText); 
-        if(!tracks)
-          console.log("Got invalid JSON");
-        if(0 == tracks.length || !tracks.length){
-          console.log("Got no tracks and status == 200.  Should not be here.");
-          return;
-        }
-        for(var i=0; i<tracks.length; i++){
-          var entry = tracks[i];
-          /**
-           * 'track_content' contains the tracks (WTID/Amount/Date) about
-           * *one* order.  It is contained in the 'overlay', which renders
-           * it in a "box" in the middle of the screen.  This "box" is then
-           * toggleable as visible/hidden.
-           */
-          var overlay = document.getElementsByClassName("overlay")[0];
-          var track_content = 
document.getElementsByClassName("track-content")[0];
-          var table = document.evaluate("table/tbody",
-                                        track_content,
-                                        null,
-                                        
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
-                                        null).snapshotItem(0);
-          var row = document.createElement("tr");
-          var subject = `${entry.wtid} ${entry.exchange_url}`;
-          console.log("Subject", subject);
-
-          row.innerHTML = `<td class="wtid">
-                             <a 
onclick="track_transfer(\'${entry.exchange_url}\', \'${entry.wtid}\')"
-                                href="#${i}">${subject.substring(0, 20)}...</a>
-                           </td> 
-                           <td 
class="amount">${amount_to_string(entry.amount)}</td>
-                           <td 
class="date">${parse_date(entry.execution_time)}</td>`;
-
-          table.appendChild(row);
-          toggle_overlay();
-        }
-      }
-      if (202 == req.status){
-        console.log("Pending order.");
-        var overlay = document.getElementsByClassName("overlay")[0];
-        var track_content = 
document.getElementsByClassName("track-content")[0];
-        track_content.innerHTML = "This order is still waiting to be paid 
back.";
-        toggle_overlay();
-      } 
-      if (404 == req.status)
-        alert("Order ID unknown");
+      cb(JSON.parse(req.responseText), req.status);
+      return;
     }
   }
   req.send();
 }
-module.exports.track_order = track_order;
 
+/**
+ * Fill the screen-centered box with data from /track/order.
+ */
+function fill_box(tracks, http_code)
+{
+
+  if (http_code == 404){
+    alert("No tracks for that order.");
+    return;
+  }
+
+  if (http_code == 202){
+    console.log("Pending order.");
+    var overlay = document.getElementsByClassName("overlay")[0];
+    var track_content = document
+      .getElementsByClassName("track-content")[0];
+    track_content.innerHTML = "This order is still" +
+      "waiting to be paid back.";
+    return;
+  }
+
+  if(!tracks)
+    console.log("Got invalid JSON");
+    if(0 == tracks.length || !tracks.length){
+      console.log(`Got no tracks and status == ${http_code}.  ` +
+                  `Should not be here.`);
+      return;
+    }
+
+
+  for(var i=0; i<tracks.length; i++){
+    var entry = tracks[i];
+    /**
+     * 'track_content' contains the tracks (WTID/Amount/Date)
+     * about *one* order.  It is contained in the 'overlay',
+     * which renders it in a "box" in the middle of the
+     * screen.  This "box" is then toggleable as visible/hidden.
+     */
+    var overlay = document.getElementsByClassName("overlay")[0];
+    var track_content = document.getElementsByClassName
+      ("track-content")[0];
+    var table = document.evaluate
+      ("table/tbody",
+       track_content,
+       null,
+       XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
+       null).snapshotItem(0);
+    var row = document.createElement("tr");
+    var subject = `${entry.wtid} ${entry.exchange_url}`;
+    console.log("Subject", subject);
+    row.innerHTML = `` +
+      `<td class="wtid">` +
+        `<a onclick="track_transfer(\'${entry.exchange_url}\', ` +
+                                   `\'${entry.wtid}\')"` +
+            `href="#${i}">${subject.substring(0, 20)}...` +
+        `</a>` +
+      `</td>`
+      `<td class="amount">` +
+        `${amount_to_string(entry.amount)}` +
+      `</td>` +
+      `<td class="date">` +
+        `${parse_date(entry.execution_time)}` +
+      `</td>`;
+    table.appendChild(row);
+    toggle_overlay();
+  }
+}
+
+/**
+ * Helper function which abstracts the hard-to-remember
+ * API offered by document.evaluate().
+ */
 function xpath_get(xpath, ctx){
-  var ret = document.evaluate(xpath,
-                              ctx,
-                              null,
-                              XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
-                              null);
+  var ret = document.evaluate
+    (xpath,
+     ctx,
+     null,
+     XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
+     null);
   return ret;
 }
 
 /**
- * Append results to the table showing results.
+ * Modify the table showing orders.  Those orders could be
+ * either from /history or /track/transfer.  If data is _not_
+ * to be appended to previous results in the table, this
+ * function will erase previous results and either show new
+ * data or make the "no results" message available.  Otherwise,
+ * it will just append data to what already exists in the table.
+ *
+ * Data is non-appending if (1) the page has been (re)loaded,
+ * (2) the user queried /track/transfer, (3) the user changed
+ * the instance being tracked.  Those 1-3 cases will all have
+ * the 'refresh' parameter set to true.
+ *
+ * 'wtid_marker' - set to <WTID> - serves to show a line at the
+ * bottom of the lines being added in the table which indicates
+ * that all those entries - orders - have been paid out by the
+ * same WTID.
+ *
+ * FIXME: 'execution_time' is a problematic field: when showing
+ * /history results, it shows the order timestamp.  When instead
+ * /track/tranfer results are being shown, it indicates the time
+ * the exchange wire transferred this order's amount.
  */
-function fill_table(history, execution_time, wtid_marker){
+function fill_table(refresh, data, execution_time, wtid_marker){
+  toggle_loader();
   var table = document.getElementById("history");
   var tbody = xpath_get("tbody", table).snapshotItem(0);
-  var nr = xpath_get("address@hidden'no-records']", tbody).snapshotItem(0)
-  if(0 == history.length){
-    nr.style.display = "block";
-    xpath_get("address@hidden'headers']", 
tbody).snapshotItem(0).style.visibility = "hidden";
-    window.setTimeout(remove_loader, 900);
-    console.log("Nothing gotten!");
-    return;
+  var nr = xpath_get("address@hidden'no-records']", tbody)
+  .snapshotItem(0)
+  if (refresh){
+    clean_results();
+    if(0 == data.length){
+      nr.style.display = "block";
+      xpath_get("address@hidden'headers']", tbody)
+        .snapshotItem(0).style.visibility = "hidden";
+      window.setTimeout(remove_loader, 900);
+      console.log("Nothing gotten!");
+      return;
+    }
   }
 
   /* hide "no records" message */
   nr.style.display = "none";
 
   /* Make table's header visible */
-  xpath_get("address@hidden'headers']", 
tbody).snapshotItem(0).style.visibility = "";
+  xpath_get("address@hidden'headers']", tbody)
+    .snapshotItem(0).style.visibility = "";
 
-  for (var i=0; i<history.length; i++){
-    var entry = history[i];
+  for (var i=0; i<data.length; i++){
+    var entry = data[i];
     var row = document.createElement("tr");
     row.className = "even";
     var row_summary = document.createElement("tr");
@@ -251,11 +327,15 @@ function fill_table(history, execution_time, wtid_marker){
     td_amount.className = "amount";
     var td_date = document.createElement("td");
     td_date.className = "date";
-    td_order_id.innerHTML = `<a href="#${i}" 
onclick='track_order("${entry.order_id}");'>${entry.order_id}</a>`;
+    td_order_id.innerHTML = `<a href="#${i}"
+      onclick='track_order("${entry.order_id}");'>
+      ${entry.order_id}</a>`;
     td_summary.className = "summary";
     td_summary.innerHTML = entry.summary;
-    td_amount.innerHTML = amount_to_string(entry.amount || 
entry.deposit_value);
-    td_date.innerHTML = parse_date(entry.timestamp || execution_time);
+    td_amount.innerHTML = amount_to_string
+      (entry.amount || entry.deposit_value);
+    td_date.innerHTML = parse_date
+      (entry.timestamp || execution_time);
     row.appendChild(td_order_id);
     row.appendChild(td_summary);
     row.appendChild(td_amount);
@@ -265,21 +345,35 @@ function fill_table(history, execution_time, wtid_marker){
     tbody.appendChild(row_summary);
     }
   if (wtid_marker){
+    // close popup showing wire transfer information
+    close_popup();
     // draw a line @ the bottom, mentioning the WTID.
     var marker = make_marker(wtid_marker);
     tbody.appendChild(marker);
   }
-  function remove_loader(){
-    var loader = document.getElementsByClassName("loader")[0]; 
+
+  window.setTimeout(function(){
+    toggle_loader();
+    table.style.visibility = ""; 
+  }, 900);
+}
+
+/**
+ * Make the spinning wheel appear if it is not shown,
+ * and viceversa.
+ */
+function toggle_loader(){
+  var loader = document.getElementsByClassName("loader")[0]; 
+  if (loader.style.visibility == "hidden")
+    loader.style.visibility = ""
+  else
     loader.style.visibility = "hidden";
-    table.style.visibility = "";
   }
-  window.setTimeout(remove_loader, 900);
-}
-module.exports.fill_table = fill_table;
 
 /**
- * Issue a direrct /track via Web form.
+ * Issue a /track/order (/track/transfer) depending on
+ * whether the user selected "order" ("transfer") on the
+ * given form.
  */
 function track_cherry_pick(form){
   var types = xpath_get("address@hidden'radio']", form);
@@ -288,25 +382,35 @@ function track_cherry_pick(form){
       continue;
     var type = types.snapshotItem(i).value;
     if ("order" == type){
-      var order_id = xpath_get("address@hidden'order']", form).snapshotItem(0);
+      var order_id = xpath_get("address@hidden'order']", form)
+        .snapshotItem(0);
       track_order(order_id.value);
     }
     else{
       var data = xpath_get("address@hidden'transfer']", form);
       var wtid = data.snapshotItem(0);
       var exchange = data.snapshotItem(1);
-      track_transfer(exchange.value, wtid.value);
+      track_transfer(exchange.value, wtid.value, fill_table);
     }  
   }
 }
 
 /**
- * Restore the cherry-pick form to the initial state.
- * In other words, it formats the form so that /track/order
- * can be called.
+ * The "cherry pick" form allows the user to track a particular
+ * order or wire transfer by entering its "id" in the input field.
+ *
+ * The UI is such that a radio button can switch the form "type"
+ * to query for a order or for a wire transfer;  the following two
+ * functions help to switch the form appearance according to this
+ * order/wire-transfer switch.
+ */
+
+/**
+ * Make the "cherry pick" form be suitable to query /track/order.
  */
 function cherry_pick_form_order(form){
-  var input_order = xpath_get("address@hidden'order']", form).snapshotItem(0);
+  var input_order = xpath_get("address@hidden'order']", form)
+    .snapshotItem(0);
   input_order.style.visibility = "";
   var input_transfer = xpath_get("address@hidden'transfer']", form);
   for(var i in [0, 1])
@@ -314,11 +418,11 @@ function cherry_pick_form_order(form){
 }
 
 /**
- * Change the cherry-pick form to the format useful for
- * tracking wire transfers.
+ * Make the "cherry pick" form be suitable to query /track/transfer.
  */
 function cherry_pick_form_transfer(form){
-  var input_order = xpath_get("address@hidden'order']", form).snapshotItem(0);
+  var input_order = xpath_get("address@hidden'order']", form)
+  .snapshotItem(0);
   input_order.style.visibility = "hidden";
   var input_transfer = xpath_get("address@hidden'transfer']", form);
   for(var i in [0, 1])
@@ -349,19 +453,21 @@ function clean_results(){
  * selected one.
  */
 function change_instance(){
-  clean_results();
-  get_history();
+  get_history(false, cb);
 }
 
 /**
- * scroll if true, the logic tries to retrieve the
+ * If 'scroll' is true, the logic tries to retrieve the
  * "next page" of all the proposals known to the merchant.
+ * Otherwise, it gets the merchant's history from the beginning
+ * of their business.
+ *
+ * 'cb' is a UI transforming function.  Typically, it is set
+ * to 'fill_table()'.
  */
-function get_history(scroll){
-  var loader = document.getElementsByClassName("loader")[0]; 
-  loader.style.visibility = "visible";
+function get_history(refresh, cb){
   var qs = `/history?instance=${get_instance()}&delta=${DELTA}`;
-  if(scroll){
+  if(!refresh){
     START = LAST;
     qs += `&start=${START}`;
   }
@@ -379,7 +485,7 @@ function get_history(scroll){
           console.log(history);
           LAST = history[history.length - 1].row_id;
         }
-        fill_table(history);
+        cb(refresh, history);
       }
       else{
         console.log("error: status != 200");
@@ -390,12 +496,19 @@ function get_history(scroll){
   req.send();
 }
 
-document.addEventListener("DOMContentLoaded", () => get_history(false));
+document.addEventListener
+  ("DOMContentLoaded",
+   function(){
+     toggle_loader();
+     get_history(true, fill_table);});
 document.addEventListener("scroll", function(){
   /* If page bottom is hit */
-  if(window.innerHeight + window.scrollY >= document.body.offsetHeight)
-    window.setTimeout(()=>get_history(true), 400);
-});
+  if(window.innerHeight + window.scrollY
+       >= document.body.offsetHeight)
+    window.setTimeout(function(){
+      toggle_loader();
+      get_history(false, fill_table);},
+      400);});
 
 /* Close dialog on ESC press */
 document.onkeydown = function(e) {
diff --git a/js/test/main.js b/js/test/main.js
index 66c715b..cda4c9f 100644
--- a/js/test/main.js
+++ b/js/test/main.js
@@ -28,9 +28,6 @@
 
 const ava = require("ava");
 const sinon = require("sinon");
-const swig = require("swig");
-const jsdom = require("jsdom");
-const xpath = require("xpath");
 const pd = require("pretty-data");
 
 ava.test.beforeEach(t => {
@@ -42,63 +39,39 @@ ava.test.beforeEach(t => {
       t.context.requests.push(xhr);};
     global.XMLHttpRequest = t.context.xhr;};
 
-  function document_mock() {
-    var template = swig.compileFile(
-      __dirname + "/" + "../../" +
-      "talerbackoffice/backoffice/" +
-      "templates/backoffice.html");
-    var html = template({instances: ["mock-instance"]});
-    var dom = new jsdom.JSDOM(html);
-    dom.window.document.addEventListener = function(){};
-    global.document = dom.window.document;};
-
   function minor_mocks() {
+    var document = {};
+    document.addEventListener = ()=>{};
+    document.getElementById = ()=>{return {value: "mock"}};
+    global.document = document;
     global.alert = console.log;
-    global.XPathResult = xpath.XPathResult;
     // disable logging for tests
     global.console.log = function(){};
   };
-
   xhr_mock();
-  document_mock();
   minor_mocks();
-
   t.context.bo = require("../backoffice");
 });
 
 ava.test.afterEach(t => {
   delete global.XMLHttpRequest;
-  delete global.document;
   delete global.alert;
   delete t.context.xhr;
   delete t.context.requests;
-  var bo_handle = require.resolve("../backoffice");
-  delete require.cache[bo_handle];
 });
 
 ava.test("Tracking a wire transfer", (t) => {
-  /**
-   * This test case checks whether the popup where
-   * the user clicked to track a wire transfer got
-   * closed; then it checks that the 'table' of the
-   * orders associated with this wire transfer got
-   * correctly filled.
-   */
-
   var mock_tracks = {
     deposits_sums: ["mock-tracks"],
     execution_time: "/Date(0)/"};
 
-  sinon.stub(t.context.bo, "close_popup"); 
-  sinon.stub(t.context.bo, "fill_table"); 
-  t.context.bo.track_transfer("http://exchange.mock/";, "mock-wtid");
+  var cb = sinon.spy();
+  t.context.bo.track_transfer("http://exchange.mock/";, "mock-wtid", cb);
   t.context.requests[0].respond(200, "application/json",
                                 JSON.stringify(mock_tracks));
-  sinon.assert.calledOnce(t.context.bo.close_popup);
-  sinon.assert.calledWith(t.context.bo.fill_table,
-                          ["mock-tracks"],
-                          "/Date(0)/",
-                          "mock-wtid");
+  sinon.assert.calledWith(cb, true, mock_tracks.deposits_sums,
+                          mock_tracks.execution_time, "mock-wtid");
+  t.pass();
 });
 
 ava.test("Tracking order id", t => {
@@ -108,7 +81,8 @@ ava.test("Tracking order id", t => {
    * page contains the expected tracks and it is made visible.
    */
 
-  t.context.bo.track_order(22);
+  var cb = sinon.spy();
+  t.context.bo.track_order(22, cb);
 
   // mocking a "/track/transaction" response from the backend
   var mock_tracks = [
@@ -121,37 +95,6 @@ ava.test("Tracking order id", t => {
     (200, "application/json",
      JSON.stringify(mock_tracks));
 
-  var overlay = document.getElementById("popup1");
-  t.true(overlay.style.visibility == "visible");
-
-  var rendered_tracks = document.evaluate
-    ("div/div/table/tbody/tr[2]",
-     overlay,
-     null,
-     XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
-     null).snapshotItem(0);
-  var expected_html =
-    "<tr>" +
-      "<td class=\"wtid\">" +
-        "<a onclick=\"track_transfer('http://exchange.mock/', " +
-                                    "'mock wtid')\" " +
-           "href=\"#0\">mock wtid http://exc...</a>" +
-      "</td>" +
-      "<td class=\"amount\">2.00 MOCK</td>" +
-      "<td class=\"date\">1 Jan 1970, 01:00</td>" +
-      "</tr>";
-
-  t.true(pd.pd.xmlmin(rendered_tracks.outerHTML) == expected_html);
-});
-
-ava.test("Order id not found", (t) => {
-  /**
-   * FIXME: improve the reaction to a order id not found.
-   * Alerting a message is not acceptable.
-   */
-  var alert = sinon.spy(global, "alert");
-  t.context.bo.track_order(22);
-  t.context.requests[0].respond(404);
-  sinon.assert.calledWith(alert, "Order ID unknown");
+  sinon.assert.calledWith(cb, mock_tracks, 200);
   t.pass();
 });

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]