From d40e0e8d8b4740ec49d781e04c13fbaa30841fbc Mon Sep 17 00:00:00 2001
From: Tristan Cavelier <tristan.cavelier@tiolive.com>
Date: Thu, 5 Dec 2013 13:51:08 +0100
Subject: [PATCH] revisionstorage.tests.js post method done

---
 test/jio.storage/revisionstorage.tests.js | 2712 +++++++++++----------
 1 file changed, 1394 insertions(+), 1318 deletions(-)

diff --git a/test/jio.storage/revisionstorage.tests.js b/test/jio.storage/revisionstorage.tests.js
index 5e805c7..1b9bd05 100644
--- a/test/jio.storage/revisionstorage.tests.js
+++ b/test/jio.storage/revisionstorage.tests.js
@@ -1,6 +1,6 @@
 /*jslint indent: 2, maxlen: 80, nomen: true */
-/*global define, jIO, jio_tests, hex_sha256, window, test, ok, deepEqual, sinon,
-  expect */
+/*global define, jIO, test_util, hex_sha256, RSVP, test, ok, deepEqual, start,
+  stop, module */
 
 // define([module_name], [dependencies], module);
 (function (dependencies, module) {
@@ -8,56 +8,23 @@
   if (typeof define === 'function' && define.amd) {
     return define(dependencies, module);
   }
-  module(jIO, jio_tests, {hex_sha256: hex_sha256});
-}(['jio', 'jio_tests', 'sha256', 'localstorage', 'revisionstorage'], function (
-  jIO,
-  util,
-  sha256
-) {
+  module(jIO, test_util, {hex_sha256: hex_sha256}, RSVP);
+}([
+  'jio',
+  'test_util',
+  'sha256',
+  'rsvp',
+  'localstorage',
+  'revisionstorage'
+], function (jIO, util, sha256, RSVP) {
   "use strict";
 
   //////////////////////////////////////////////////////////////////////////////
   // Tools
 
-  /**
-   * Clones all native object in deep. Managed types: Object, Array, String,
-   * Number, Boolean, Function, null.
-   *
-   * @param  {A} object The object to clone
-   * @return {A} The cloned object
-   */
-  function deepClone(object) {
-    var i, cloned;
-    if (Array.isArray(object)) {
-      cloned = [];
-      for (i = 0; i < object.length; i += 1) {
-        cloned[i] = deepClone(object[i]);
-      }
-      return cloned;
-    }
-    if (typeof object === "object") {
-      cloned = {};
-      for (i in object) {
-        if (object.hasOwnProperty(i)) {
-          cloned[i] = deepClone(object[i]);
-        }
-      }
-      return cloned;
-    }
-    return object;
-  }
-
-  function generateTools() {
-    return {
-      clock: sinon.useFakeTimers(),
-      spy: util.ospy,
-      tick: util.otick
-    };
-  }
-
   function generateRevisionHash(doc, revisions, deleted_flag) {
     var string;
-    doc = deepClone(doc);
+    doc = jIO.util.deepClone(doc);
     delete doc._rev;
     delete doc._revs;
     delete doc._revs_info;
@@ -66,6 +33,30 @@
     return sha256.hex_sha256(string);
   }
 
+  function isRevision(revision) {
+    return (/^[0-9]+-[0-9a-zA-Z]+$/).test(revision);
+  }
+
+  function success(promise) {
+    return new RSVP.Promise(function (resolve, reject, notify) {
+      /*jslint unparam: true*/
+      promise.then(resolve, resolve, notify);
+    }, function () {
+      promise.cancel();
+    });
+  }
+
+  function unexpectedError(error) {
+    if (error instanceof Error) {
+      deepEqual([
+        error.name + ": " + error.message,
+        error
+      ], "UNEXPECTED ERROR", "Unexpected error");
+    } else {
+      deepEqual(error, "UNEXPECTED ERROR", "Unexpected error");
+    }
+  }
+
   //////////////////////////////////////////////////////////////////////////////
   // Tests
 
@@ -73,1318 +64,1403 @@
 
   test("Post", function () {
 
-    var o = generateTools();
+    var shared = {}, jio, jio_local;
+
+    shared.workspace = {};
+    shared.local_storage_description = {
+      "type": "local",
+      "username": "revision post",
+      "mode": "memory"
+      //"mode": "localStorage"
+    };
 
-    o.jio = jIO.newJio({
+    jio = jIO.createJIO({
       "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "urevpost",
-        "application_name": "arevpost"
-      }
+      "sub_storage": shared.local_storage_description
+    }, {"workspace": shared.workspace});
+
+    jio_local = jIO.createJIO(shared.local_storage_description, {
+      "workspace": shared.workspace
     });
-    o.localpath = "jio/localstorage/urevpost/arevpost";
+
+    stop();
 
     // post without id
-    o.revisions = {"start": 0, "ids": []};
-    o.spy(o, "status", undefined, "Post without id");
-    o.jio.post({}, function (err, response) {
-      o.f.apply(arguments);
-      o.uuid = (err || response).id;
-      ok(util.isUuid(o.uuid), "Uuid should look like " +
-         "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + o.uuid);
-    });
-    o.tick(o);
-    o.rev = "1-" + generateRevisionHash({"_id": o.uuid}, o.revisions);
-
-    // check document
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/" + o.uuid + "." + o.rev),
-      {"_id": o.uuid + "." + o.rev},
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree = {
-      "_id": o.uuid + ".revision_tree.json",
-      "children": [{
-        "rev": o.rev,
-        "status": "available",
-        "children": []
-      }]
-    };
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/" + o.uuid + ".revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // post non empty document
-    o.doc = {"_id": "post1", "title": "myPost1"};
-    o.rev = "1-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"ok": true, "id": "post1", "rev": o.rev}, "Post");
-    o.jio.post(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "post1." + o.rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/post1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree._id = "post1.revision_tree.json";
-    o.doc_tree.children[0] = {
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    };
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/post1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // post and document already exists
-    o.doc = {"_id": "post1", "title": "myPost2"};
-    o.rev = "1-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {
-      "ok": true,
-      "id": "post1",
-      "rev": o.rev
-    }, "Post and document already exists");
-    o.jio.post(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "post1." + o.rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/post1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree._id = "post1.revision_tree.json";
-    o.doc_tree.children.unshift({
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/post1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // post + revision
-    o.doc = {"_id": "post1", "_rev": o.rev, "title": "myPost2"};
-    o.revisions = {"start": 1, "ids": [o.rev.split('-')[1]]};
-    o.rev = "2-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"ok": true, "id": "post1", "rev": o.rev},
-           "Post + revision");
-    o.jio.post(o.doc, o.f);
-    o.tick(o);
-
-    // // keep_revision_history
-    // ok (false, "keep_revision_history Option Not Implemented");
-
-    // check document
-    o.doc._id = "post1." + o.rev;
-    delete o.doc._rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/post1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree._id = "post1.revision_tree.json";
-    o.doc_tree.children[0].children.unshift({
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/post1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // add attachment
-    o.doc._attachments = {
-      "attachment_test": {
-        "length": 35,
-        "digest": "A",
-        "content_type": "oh/yeah"
-      }
-    };
-    util.jsonlocalstorage.setItem(o.localpath + "/post1." + o.rev, o.doc);
-    util.jsonlocalstorage.setItem(
-      o.localpath + "/post1." + o.rev + "/attachment_test",
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-    );
-
-    // post + attachment copy
-    o.doc = {"_id": "post1", "_rev": o.rev, "title": "myPost2"};
-    o.revisions = {
-      "start": 2,
-      "ids": [o.rev.split('-')[1], o.revisions.ids[0]]
-    };
-    o.rev = "3-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"ok": true, "id": "post1", "rev": o.rev},
-           "Post + attachment copy");
-    o.jio.post(o.doc, o.f);
-    o.tick(o);
-
-    // check attachment
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/post1." + o.rev +
-                                    "/attachment_test"),
-      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
-      "Check Attachment"
-    );
-
-    // check document tree
-    o.doc_tree._id = "post1.revision_tree.json";
-    o.doc_tree.children[0].children[0].children.unshift({
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/post1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // post + wrong revision
-    o.doc = {"_id": "post1", "_rev": "3-wr3", "title": "myPost3"};
-    o.revisions = {"start": 3, "ids": ["wr3"]};
-    o.rev = "4-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"id": "post1", "ok": true, "rev": o.rev},
-          "Post + wrong revision");
-    o.jio.post(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/post1.3-wr3"),
-      null,
-      "Check document"
-    );
-
-    // check document
-    o.doc._id = "post1." + o.rev;
-    delete o.doc._rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/post1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree._id = "post1.revision_tree.json";
-    o.doc_tree.children.unshift({
-      "rev": "3-wr3",
-      "status": "missing",
-      "children": [{
-        "rev": o.rev,
+    shared.revisions = {"start": 0, "ids": []};
+    jio.post({}).then(function (response) {
+
+      shared.uuid = response.id;
+      response.id = "<uuid>";
+      shared.rev = response.rev;
+      response.rev = "<rev>";
+      ok(util.isUuid(shared.uuid), "Uuid should look like " +
+         "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + shared.uuid);
+      ok(isRevision(shared.rev), "Revision should look like " +
+         "x-xxxxxxxxxxxxxxxxxxxxxxxxx... : " + shared.rev);
+      deepEqual(
+        shared.rev,
+        "1-" + generateRevisionHash({"_id": shared.uuid}, shared.revisions),
+        "Check revision value"
+      );
+      deepEqual(response, {
+        "id": "<uuid>",
+        "rev": "<rev>",
+        "method": "post",
+        "result": "success",
+        "status": 201,
+        "statusText": "Created"
+      }, "Post without id");
+
+      return jio_local.get({"_id": shared.uuid + "." + shared.rev});
+
+    }).then(function (answer) {
+
+      deepEqual(answer.data, {
+        "_id": shared.uuid + "." + shared.rev
+      }, "Check document");
+
+      return jio_local.get({"_id": shared.uuid + ".revision_tree.json"});
+
+    }).then(function (answer) {
+
+      shared.doc_tree = {
+        "_id": shared.uuid + ".revision_tree.json",
+        "children": JSON.stringify([{
+          "rev": shared.rev,
+          "status": "available",
+          "children": []
+        }])
+      };
+      deepEqual(answer.data, shared.doc_tree, "Check document tree");
+
+      // post non empty document
+      shared.doc = {"_id": "post1", "title": "myPost1"};
+      shared.rev = "1-" + generateRevisionHash(shared.doc, shared.revisions);
+      return jio.post(shared.doc);
+
+    }).then(function (answer) {
+
+      deepEqual(answer, {
+        "id": "post1",
+        "method": "post",
+        "result": "success",
+        "rev": "1-eedaf5235af91978a06d0b0e68b1c16adbc539" +
+          "5bb9bd4a0cfd632fe03f9d8ef3",
+        "status": 201,
+        "statusText": "Created"
+      }, "Post");
+
+      // check document
+      shared.doc._id = "post1." + shared.rev;
+      return jio_local.get(shared.doc);
+
+    }).then(function (answer) {
+
+      deepEqual(answer.data, {
+        "_id": shared.doc._id,
+        "title": "myPost1"
+      }, "Check document");
+
+      // check document tree
+      shared.doc_tree._id = "post1.revision_tree.json";
+      shared.doc_tree.children = JSON.parse(shared.doc_tree.children);
+      shared.doc_tree.children[0] = {
+        "rev": shared.rev,
         "status": "available",
         "children": []
-      }]
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/post1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    util.closeAndcleanUpJio(o.jio);
-  });
+      };
+      shared.doc_tree.children = JSON.stringify(shared.doc_tree.children);
 
-  test("Put", function () {
+      return jio_local.get(shared.doc_tree);
 
-    var o = generateTools();
+    }).then(function (answer) {
 
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "urevput",
-        "application_name": "arevput"
-      }
-    });
-    o.localpath = "jio/localstorage/urevput/arevput";
-
-    // put without id
-    // error 20 -> document id required
-    o.spy(o, "status", 20, "Put without id");
-    o.jio.put({}, o.f);
-    o.tick(o);
-
-    // put non empty document
-    o.doc = {"_id": "put1", "title": "myPut1"};
-    o.revisions = {"start": 0, "ids": []};
-    o.rev = "1-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"ok": true, "id": "put1", "rev": o.rev},
-           "Creates a document");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "put1." + o.rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree = {
-      "_id": "put1.revision_tree.json",
-      "children": [{
-        "rev": o.rev,
-        "status": "available",
-        "children": []
-      }]
-    };
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/put1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // put without rev and document already exists
-    o.doc = {"_id": "put1", "title": "myPut2"};
-    o.rev = "1-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"ok": true, "id": "put1", "rev": o.rev},
-           "Put same document without revision");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    o.doc_tree.children.unshift({
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    });
+      deepEqual(answer.data, shared.doc_tree, "Check document tree");
 
-    // put + revision
-    o.doc = {"_id": "put1", "_rev": o.rev, "title": "myPut2"};
-    o.revisions = {"start": 1, "ids": [o.rev.split('-')[1]]};
-    o.rev = "2-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"id": "put1", "ok": true, "rev": o.rev},
-           "Put + revision");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "put1." + o.rev;
-    delete o.doc._rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree.children[0].children.unshift({
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/put1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // put + wrong revision
-    o.doc = {"_id": "put1", "_rev": "3-wr3", "title": "myPut3"};
-    o.revisions = {"start": 3, "ids": ["wr3"]};
-    o.rev = "4-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"id": "put1", "ok": true, "rev": o.rev},
-           "Put + wrong revision");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "put1." + o.rev;
-    delete o.doc._rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree.children.unshift({
-      "rev": "3-wr3",
-      "status": "missing",
-      "children": [{
-        "rev": o.rev,
-        "status": "available",
-        "children": []
-      }]
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/put1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // put + revision history
-    o.doc = {
-      "_id": "put1",
-      //"_revs": ["3-rh3", "2-rh2", "1-rh1"], // same as below
-      "_revs": {"start": 3, "ids": ["rh3", "rh2", "rh1"]},
-      "title": "myPut3"
-    };
-    o.spy(o, "value", {"id": "put1", "ok": true, "rev": "3-rh3"},
-           "Put + revision history");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "put1.3-rh3";
-    delete o.doc._revs;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1.3-rh3"),
-      o.doc,
-      "Check document"
-    );
-
-    // check document tree
-    o.doc_tree.children.unshift({
-      "rev": "1-rh1",
-      "status": "missing",
-      "children": [{
-        "rev": "2-rh2",
-        "status": "missing",
-        "children": [{
-          "rev": "3-rh3",
-          "status": "available",
-          "children": []
-        }]
-      }]
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/put1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
-
-    // add attachment
-    o.doc._attachments = {
-      "att1": {
-        "length": 1,
-        "content_type": "text/plain",
-        "digest": "md5-0cc175b9c0f1b6a831c399e269772661"
-      },
-      "att2": {
-        "length": 2,
-        "content_type": "dont/care",
-        "digest": "md5-5360af35bde9ebd8f01f492dc059593c"
-      }
-    };
-    util.jsonlocalstorage.setItem(o.localpath + "/put1.3-rh3", o.doc);
-    util.jsonlocalstorage.setItem(o.localpath + "/put1.3-rh3/att1", "a");
-    util.jsonlocalstorage.setItem(o.localpath + "/put1.3-rh3/att2", "bc");
-
-    // put + revision with attachment
-    o.attachments = o.doc._attachments;
-    o.doc = {"_id": "put1", "_rev": "3-rh3", "title": "myPut4"};
-    o.revisions = {"start": 3, "ids": ["rh3", "rh2", "rh1"]};
-    o.rev = "4-" + generateRevisionHash(o.doc, o.revisions);
-    o.spy(o, "value", {"id": "put1", "ok": true, "rev": o.rev},
-           "Put + revision (document contains attachments)");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    // check document
-    o.doc._id = "put1." + o.rev;
-    o.doc._attachments = o.attachments;
-    delete o.doc._rev;
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
-      o.doc,
-      "Check document"
-    );
-
-    // check attachments
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev + "/att1"),
-      "a",
-      "Check Attachment"
-    );
-    deepEqual(
-      util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev + "/att2"),
-      "bc",
-      "Check Attachment"
-    );
-
-    // check document tree
-    o.doc_tree.children[0].children[0].children[0].children.unshift({
-      "rev": o.rev,
-      "status": "available",
-      "children": []
-    });
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        o.localpath + "/put1.revision_tree.json"
-      ),
-      o.doc_tree,
-      "Check document tree"
-    );
+      // post and document already exists
+      shared.doc = {"_id": "post1", "title": "myPost2"};
+      shared.rev = "1-" + generateRevisionHash(shared.doc, shared.revisions);
+      return jio.post(shared.doc);
 
-    util.closeAndcleanUpJio(o.jio);
+    }).then(function (answer) {
 
-  });
+      deepEqual(answer, {
+        "id": "post1",
+        "method": "post",
+        "result": "success",
+        "rev": shared.rev,
+        "status": 201,
+        "statusText": "Created"
+      }, "Post and document already exists");
 
-  test("Put Attachment", function () {
+      // check document
+      shared.doc._id = "post1." + shared.rev;
+      return jio_local.get(shared.doc);
 
-    var o = generateTools();
+    }).then(function (answer) {
 
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "urevputattmt",
-        "application_name": "arevputattmt"
-      }
-    });
+      deepEqual(answer.data, shared.doc, "Check document");
 
-    // putAttachment without doc id
-    // error 20 -> document id required
-    o.spy(o, "status", 20, "PutAttachment without doc id" +
-          " -> 20 document id required");
-    o.jio.putAttachment({}, o.f);
-    o.tick(o);
-
-    // putAttachment without attachment id
-    // erorr 22 -> attachment id required
-    o.spy(o, "status", 22, "PutAttachment without attachment id" +
-          " -> 22 attachment id required");
-    o.jio.putAttachment({"_id": "putattmt1"}, o.f);
-    o.tick(o);
-
-    // putAttachment without document
-    o.revisions = {"start": 0, "ids": []};
-    o.rev_hash = generateRevisionHash({"_id": "doc1", "_attachment": "attmt1"},
-                                      o.revisions);
-    o.rev = "1-" + o.rev_hash;
-    o.spy(o, "value",
-          {"ok": true, "id": "doc1", "attachment": "attmt1", "rev": o.rev},
-          "PutAttachment without document, without data");
-    o.jio.putAttachment({"_id": "doc1", "_attachment": "attmt1"}, o.f);
-    o.tick(o);
-
-    // check document
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
-      ),
-      {
-        "_id": "doc1." + o.rev,
-        "_attachments": {
-          "attmt1": {
-            "length": 0,
-            // md5("")
-            "digest": "md5-d41d8cd98f00b204e9800998ecf8427e"
-          }
-        }
-      },
-      "Check document"
-    );
-
-    // check attachment
-    deepEqual(util.jsonlocalstorage.getItem(
-      "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
-        + "/attmt1"
-    ), "", "Check attachment");
-    // adding a metadata to the document
-    o.doc = util.jsonlocalstorage.getItem(
-      "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
-    );
-    o.doc.title = "My Title";
-    util.jsonlocalstorage.setItem(
-      "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev,
-      o.doc
-    );
-
-    // update attachment
-    o.prev_rev = o.rev;
-    o.revisions = {"start": 1, "ids": [o.rev_hash]};
-    o.rev_hash = generateRevisionHash({
-      "_id": "doc1",
-      "_data": "abc",
-      "_attachment": "attmt1",
-    }, o.revisions);
-    o.rev = "2-" + o.rev_hash;
-    o.spy(o, "value",
-          {"ok": true, "id": "doc1", "attachment": "attmt1", "rev": o.rev},
-          "Update Attachment, with data");
-    o.jio.putAttachment({
-      "_id": "doc1",
-      "_data": "abc",
-      "_attachment": "attmt1",
-      "_rev": o.prev_rev
-    }, o.f);
-    o.tick(o);
-
-    // check document
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
-      ),
-      {
-        "_id": "doc1." + o.rev,
-        "title": "My Title",
-        "_attachments": {
-          "attmt1": {
-            "length": 3,
-            // md5("abc")
-            "digest": "md5-900150983cd24fb0d6963f7d28e17f72"
-          }
-        }
-      },
-      "Check document"
-    );
-
-    // check attachment
-    deepEqual(util.jsonlocalstorage.getItem(
-      "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev +
-        "/attmt1"
-    ), "abc", "Check attachment");
-
-    // putAttachment new attachment
-    o.prev_rev = o.rev;
-    o.revisions = {"start": 2, "ids": [o.rev_hash, o.revisions.ids[0]]};
-    o.rev_hash = generateRevisionHash({
-      "_id": "doc1",
-      "_data": "def",
-      "_attachment": "attmt2",
-    }, o.revisions);
-    o.rev = "3-" + o.rev_hash;
-    o.spy(o, "value",
-          {"ok": true, "id": "doc1", "attachment": "attmt2", "rev": o.rev},
-          "PutAttachment without document, without data");
-    o.jio.putAttachment({
-      "_id": "doc1",
-      "_data": "def",
-      "_attachment": "attmt2",
-      "_rev": o.prev_rev
-    }, o.f);
-    o.tick(o);
-
-    // check document
-    deepEqual(
-      util.jsonlocalstorage.getItem(
-        "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
-      ),
-      {
-        "_id": "doc1." + o.rev,
-        "title": "My Title",
-        "_attachments": {
-          "attmt1": {
-            "length": 3,
-            "digest": "md5-900150983cd24fb0d6963f7d28e17f72"
-          },
-          "attmt2": {
-            "length": 3,
-            // md5("def")
-            "digest": "md5-4ed9407630eb1000c0f6b63842defa7d"
-          }
-        }
-      },
-      "Check document"
-    );
-
-    // check attachment
-    deepEqual(util.jsonlocalstorage.getItem(
-      "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev +
-        "/attmt2"
-    ), "def", "Check attachment");
-
-    util.closeAndcleanUpJio(o.jio);
+      // check document tree
+      shared.doc_tree._id = "post1.revision_tree.json";
+      shared.doc_tree.children = JSON.parse(shared.doc_tree.children);
+      shared.doc_tree.children.unshift({
+        "rev": shared.rev,
+        "status": "available",
+        "children": []
+      });
+      shared.doc_tree.children = JSON.stringify(shared.doc_tree.children);
 
-  });
+      return jio_local.get(shared.doc_tree);
 
-  test("Get", function () {
+    }).then(function (answer) {
 
-    var o = generateTools();
+      deepEqual(answer.data, shared.doc_tree, "Check document tree");
 
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "urevget",
-        "application_name": "arevget"
-      }
-    });
-    o.localpath = "jio/localstorage/urevget/arevget";
-
-    // get inexistent document
-    o.spy(o, "status", 404, "Get inexistent document (winner)" +
-          " -> 404 Not Found");
-    o.jio.get({"_id": "get1"}, o.f);
-    o.tick(o);
-
-    // get inexistent attachment
-    o.spy(o, "status", 404, "Get inexistent attachment (winner)" +
-          " -> 404 Not Found");
-    o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f);
-    o.tick(o);
-
-    // adding a document
-    o.doctree = {"children": [{
-      "rev": "1-rev1",
-      "status": "available",
-      "children": []
-    }]};
-    o.doc_myget1 = {"_id": "get1.1-rev1", "title": "myGet1"};
-    util.jsonlocalstorage.setItem(
-      o.localpath + "/get1.revision_tree.json",
-      o.doctree
-    );
-    util.jsonlocalstorage.setItem(o.localpath + "/get1.1-rev1", o.doc_myget1);
-
-    // get document
-    o.doc_myget1_cloned = deepClone(o.doc_myget1);
-    o.doc_myget1_cloned._id = "get1";
-    o.doc_myget1_cloned._rev = "1-rev1";
-    o.doc_myget1_cloned._revisions = {"start": 1, "ids": ["rev1"]};
-    o.doc_myget1_cloned._revs_info = [{
-      "rev": "1-rev1",
-      "status": "available"
-    }];
-    o.spy(o, "value", o.doc_myget1_cloned, "Get document (winner)");
-    o.jio.get({"_id": "get1"}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true
-    }, o.f);
-    o.tick(o);
-
-    // adding two documents
-    o.doctree = {"children": [{
-      "rev": "1-rev1",
-      "status": "available",
-      "children": []
-    }, {
-      "rev": "1-rev2",
-      "status": "available",
-      "children": [{
-        "rev": "2-rev3",
-        "status": "available",
-        "children": []
-      }]
-    }]};
-    o.doc_myget2 = {"_id": "get1.1-rev2", "title": "myGet2"};
-    o.doc_myget3 = {"_id": "get1.2-rev3", "title": "myGet3"};
-    util.jsonlocalstorage.setItem(
-      o.localpath + "/get1.revision_tree.json",
-      o.doctree
-    );
-    util.jsonlocalstorage.setItem(o.localpath + "/get1.1-rev2", o.doc_myget2);
-    util.jsonlocalstorage.setItem(o.localpath + "/get1.2-rev3", o.doc_myget3);
-
-    // get document
-    o.doc_myget3_cloned = deepClone(o.doc_myget3);
-    o.doc_myget3_cloned._id = "get1";
-    o.doc_myget3_cloned._rev = "2-rev3";
-    o.doc_myget3_cloned._revisions = {"start": 2, "ids": ["rev3", "rev2"]};
-    o.doc_myget3_cloned._revs_info = [{
-      "rev": "2-rev3",
-      "status": "available"
-    }, {
-      "rev": "1-rev2",
-      "status": "available"
-    }];
-    o.doc_myget3_cloned._conflicts = ["1-rev1"];
-    o.spy(o, "value", o.doc_myget3_cloned,
-          "Get document (winner, after posting another one)");
-    o.jio.get({"_id": "get1"},
-              {"revs_info": true, "revs": true, "conflicts": true},
-              o.f);
-    o.tick(o);
-
-    // get inexistent specific document
-    o.spy(o, "status", 404, "Get document (inexistent specific revision)" +
-          " -> 404 Not Found");
-    o.jio.get({"_id": "get1", "_rev": "1-rev0"}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true,
-    }, o.f);
-    o.tick(o);
-
-    // get specific document
-    o.doc_myget2_cloned = deepClone(o.doc_myget2);
-    o.doc_myget2_cloned._id = "get1";
-    o.doc_myget2_cloned._rev = "1-rev2";
-    o.doc_myget2_cloned._revisions = {"start": 1, "ids": ["rev2"]};
-    o.doc_myget2_cloned._revs_info = [{
-      "rev": "1-rev2",
-      "status": "available"
-    }];
-    o.doc_myget2_cloned._conflicts = ["1-rev1"];
-    o.spy(o, "value", o.doc_myget2_cloned, "Get document (specific revision)");
-    o.jio.get({"_id": "get1", "_rev": "1-rev2"}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true,
-    }, o.f);
-    o.tick(o);
-
-    // adding an attachment
-    o.attmt_myget3 = {
-      "get2": {
-        "length": 3,
-        "digest": "md5-dontcare",
-        "content_type": "oh/yeah"
-      }
-    };
-    o.doc_myget3._attachments = o.attmt_myget3;
-    util.jsonlocalstorage.setItem(o.localpath + "/get1.2-rev3", o.doc_myget3);
-    util.jsonlocalstorage.setItem(o.localpath + "/get1.2-rev3/get2", "abc");
-
-    // get attachment winner
-    o.spy(o, "value", "abc", "Get attachment (winner)");
-    o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f);
-    o.tick(o);
-
-    // get inexistent attachment specific rev
-    o.spy(o, "status", 404, "Get inexistent attachment (specific revision)" +
-          " -> 404 Not Found");
-    o.jio.getAttachment({
-      "_id": "get1",
-      "_attachment": "get2",
-      "_rev": "1-rev1"
-    }, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true,
-    }, o.f);
-    o.tick(o);
-
-    // get attachment specific rev
-    o.spy(o, "value", "abc", "Get attachment (specific revision)");
-    o.jio.getAttachment({
-      "_id": "get1",
-      "_attachment": "get2",
-      "_rev": "2-rev3"
-    }, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true,
-    }, o.f);
-    o.tick(o);
-
-    // get document with attachment (specific revision)
-    delete o.doc_myget2_cloned._attachments;
-    o.spy(o, "value", o.doc_myget2_cloned,
-          "Get document which have an attachment (specific revision)");
-    o.jio.get({"_id": "get1", "_rev": "1-rev2"}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true
-    }, o.f);
-    o.tick(o);
-
-    // get document with attachment (winner)
-    o.doc_myget3_cloned._attachments = o.attmt_myget3;
-    o.spy(o, "value", o.doc_myget3_cloned,
-          "Get document which have an attachment (winner)");
-    o.jio.get({"_id": "get1"},
-              {"revs_info": true, "revs": true, "conflicts": true},
-              o.f);
-    o.tick(o);
-
-    util.closeAndcleanUpJio(o.jio);
+      // post + revision
+      shared.doc = {"_id": "post1", "_rev": shared.rev, "title": "myPost2"};
+      shared.revisions = {"start": 1, "ids": [shared.rev.split('-')[1]]};
+      shared.rev = "2-" + generateRevisionHash(shared.doc, shared.revisions);
+      return jio.post(shared.doc);
 
-  });
+    }).then(function (answer) {
 
-  test("Remove", function () {
+      deepEqual(answer, {
+        "id": "post1",
+        "method": "post",
+        "result": "success",
+        "rev": shared.rev,
+        "status": 201,
+        "statusText": "Created" // XXX should be 204 no content
+      }, "Post + revision");
 
-    var o = generateTools();
+      // // keep_revision_history
+      // ok (false, "keep_revision_history Option Not Implemented");
 
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "urevrem",
-        "application_name": "arevrem"
-      }
-    });
-    o.localpath = "jio/localstorage/urevrem/arevrem";
-
-    // 1. remove document without revision
-    o.spy(o, "status", 409, "Remove document without revision " +
-          "-> 409 Conflict");
-    o.jio.remove({"_id": "remove1"}, o.f);
-    o.tick(o);
-
-    // 2. remove attachment without revision
-    o.spy(o, "status", 409, "Remove attachment without revision " +
-          "-> 409 Conflict");
-    o.jio.removeAttachment({"_id": "remove1", "_attachment": "remove2"}, o.f);
-    o.tick(o);
-
-    // adding a document with attachments
-    o.doc_myremove1 = {
-      "_id": "remove1.1-veryoldrev",
-      "title": "myRemove1"
-    };
+      // check document
+      shared.doc._id = "post1." + shared.rev;
+      delete shared.doc._rev;
+      return jio_local.get(shared.doc);
 
-    util.jsonlocalstorage.setItem(o.localpath + "/remove1.1-veryoldrev",
-                         o.doc_myremove1);
+    }).then(function (answer) {
 
-    o.doc_myremove1._id = "remove1.2-oldrev";
-    o.attachment_remove2 = {
-      "length": 3,
-      "digest": "md5-dontcare",
-      "content_type": "oh/yeah"
-    };
-    o.attachment_remove3 = {
-      "length": 5,
-      "digest": "md5-865f5cc7fbd7854902eae9d8211f178a",
-      "content_type": "he/ho"
-    };
-    o.doc_myremove1._attachments = {
-      "remove2": o.attachment_remove2,
-      "remove3": o.attachment_remove3
-    };
+      deepEqual(answer.data, shared.doc, "Check document");
 
-    util.jsonlocalstorage.setItem(o.localpath + "/remove1.2-oldrev",
-                         o.doc_myremove1);
-    util.jsonlocalstorage.setItem(
-      o.localpath + "/remove1.2-oldrev/remove2",
-      "abc"
-    );
-    util.jsonlocalstorage.setItem(
-      o.localpath + "/remove1.2-oldrev/remove3",
-      "defgh"
-    );
-
-    // add document tree
-    o.doctree = {
-      "children": [{
-        "rev": "1-veryoldrev",
+      // check document tree
+      shared.doc_tree._id = "post1.revision_tree.json";
+      shared.doc_tree.children = JSON.parse(shared.doc_tree.children);
+      shared.doc_tree.children[0].children.unshift({
+        "rev": shared.rev,
         "status": "available",
+        "children": []
+      });
+      shared.doc_tree.children = JSON.stringify(shared.doc_tree.children);
+      return jio_local.get(shared.doc_tree);
+
+    }).then(function (answer) {
+
+      deepEqual(answer.data, shared.doc_tree, "Check document tree");
+
+      // add attachment
+      return jio_local.putAttachment({
+        "_id": "post1." + shared.rev,
+        "_attachment": "attachment_test",
+        "_data": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+        "_mimetype": "oh/yeah"
+      });
+
+    }).then(function () {
+
+      // post + attachment copy
+      shared.doc = {"_id": "post1", "_rev": shared.rev, "title": "myPost2"};
+      shared.revisions = {
+        "start": 2,
+        "ids": [shared.rev.split('-')[1], shared.revisions.ids[0]]
+      };
+      shared.rev = "3-" + generateRevisionHash(shared.doc, shared.revisions);
+      return jio.post(shared.doc);
+
+    }).then(function (answer) {
+
+      deepEqual(answer, {
+        "id": "post1",
+        "method": "post",
+        "result": "success",
+        "rev": shared.rev,
+        "status": 201,
+        "statusText": "Created"
+      }, "Post + attachment copy");
+
+      // check attachment
+      return jio_local.getAttachment({
+        "_id": "post1." + shared.rev,
+        "_attachment": "attachment_test"
+      });
+
+    }).then(function (answer) {
+
+      return jIO.util.readBlobAsBinaryString(answer.data);
+
+    }).then(function (event) {
+
+      deepEqual(event.target.result, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+                "Check Attachment");
+
+      // check document tree
+      shared.doc_tree._id = "post1.revision_tree.json";
+      shared.doc_tree.children = JSON.parse(shared.doc_tree.children);
+      shared.doc_tree.children[0].children[0].children.unshift({
+         "rev": shared.rev,
+         "status": "available",
+         "children": []
+      });
+      shared.doc_tree.children = JSON.stringify(shared.doc_tree.children);
+
+      return jio_local.get({"_id": shared.doc_tree._id});
+
+    }).then(function (answer) {
+
+      deepEqual(
+        answer.data,
+        shared.doc_tree,
+        "Check document tree"
+      );
+
+      // post + wrong revision
+      shared.doc = {"_id": "post1", "_rev": "3-wr3", "title": "myPost3"};
+      shared.revisions = {"start": 3, "ids": ["wr3"]};
+      shared.rev = "4-" + generateRevisionHash(shared.doc, shared.revisions);
+      return jio.post(shared.doc);
+
+    }).then(function (answer) {
+
+      deepEqual(answer, {
+        "id": "post1",
+        "method": "post",
+        "rev": shared.rev,
+        "result": "success",
+        "status": 201,
+        "statusText": "Created"
+      }, "Post + wrong revision");
+
+      return success(jio_local.get({"_id": "post1.3-wr3"}));
+
+    }).then(function (answer) {
+
+      // check document
+      deepEqual(answer, {
+        "error": "not_found",
+        "id": "post1.3-wr3",
+        "message": "Cannot find document",
+        "method": "get",
+        "reason": "missing",
+        "result": "error",
+        "status": 404,
+        "statusText": "Not Found"
+      }, "Check document");
+
+      // check document
+      shared.doc._id = "post1." + shared.rev;
+      delete shared.doc._rev;
+
+      return jio_local.get({"_id": shared.doc._id});
+
+    }).then(function (answer) {
+
+      deepEqual(answer.data, shared.doc, "Check document");
+
+      // check document tree
+      shared.doc_tree._id = "post1.revision_tree.json";
+      shared.doc_tree.children = JSON.parse(shared.doc_tree.children);
+      shared.doc_tree.children.unshift({
+        "rev": "3-wr3",
+        "status": "missing",
         "children": [{
-          "rev": "2-oldrev",
+          "rev": shared.rev,
           "status": "available",
           "children": []
         }]
-      }]
-    };
-    util.jsonlocalstorage.setItem(o.localpath + "/remove1.revision_tree.json",
-                         o.doctree);
-
-    // 3. remove inexistent attachment
-    o.spy(o, "status", 404, "Remove inexistent attachment -> 404 Not Found");
-    o.jio.removeAttachment({
-      "_id": "remove1",
-      "_attachment": "remove0",
-      "_rev": "2-oldrev"
-    }, o.f);
-    o.tick(o);
-
-    // 4. remove existing attachment
-    o.rev_hash = generateRevisionHash({
-      "_id": "remove1",
-      "_attachment": "remove2",
-    }, {"start": 2, "ids": ["oldrev", "veryoldrev"]});
-    o.spy(o, "value", {
-      "ok": true,
-      "id": "remove1",
-      "attachment": "remove2",
-      "rev": "3-" + o.rev_hash
-    }, "Remove existing attachment");
-    o.jio.removeAttachment({
-      "_id": "remove1",
-      "_attachment": "remove2",
-      "_rev": "2-oldrev"
-    }, o.f);
-    o.tick(o);
-
-    o.doctree = {
-      "_id": "remove1.revision_tree.json",
-      "children": [{
-        "rev": "1-veryoldrev",
-        "status": "available",
-        "children": [{
-          "rev": "2-oldrev",
-          "status": "available",
-          "children": [{
-            "rev": "3-" + o.rev_hash,
-            "status": "available",
-            "children": []
-          }]
-        }]
-      }]
-    };
+      });
+      shared.doc_tree.children = JSON.stringify(shared.doc_tree.children);
 
-    // 5. check if document tree has been updated correctly
-    deepEqual(util.jsonlocalstorage.getItem(
-      o.localpath + "/remove1.revision_tree.json"
-    ), o.doctree, "Check document tree");
-
-    // 6. check if the attachment still exists
-    deepEqual(util.jsonlocalstorage.getItem(
-      o.localpath + "/remove1.2-oldrev/remove2"
-    ), "abc", "Check attachment -> still exists");
-
-    // 7. check if document is updated
-    deepEqual(util.jsonlocalstorage.getItem(
-      o.localpath + "/remove1.3-" + o.rev_hash
-    ), {
-      "_id": "remove1.3-" + o.rev_hash,
-      "title": "myRemove1",
-      "_attachments": {"remove3": o.attachment_remove3}
-    }, "Check document");
-
-    // 8. remove document with wrong revision
-    o.spy(o, "status", 409, "Remove document with wrong revision " +
-          "-> 409 Conflict");
-    o.jio.remove({"_id": "remove1", "_rev": "1-a"}, o.f);
-    o.tick(o);
-
-    // 9. remove attachment wrong revision
-    o.spy(o, "status", 409, "Remove attachment with wrong revision " +
-          "-> 409 Conflict");
-    o.jio.removeAttachment({
-      "_id": "remove1",
-      "_attachment": "remove2",
-      "_rev": "1-a"
-    }, o.f);
-    o.tick(o);
-
-    // 10. remove document
-    o.last_rev = "3-" + o.rev_hash;
-    o.rev_hash = generateRevisionHash(
-      {"_id": "remove1"},
-      {"start": 3, "ids": [o.rev_hash, "oldrev", "veryoldrev"]},
-      true
-    );
-    o.spy(o, "value", {"ok": true, "id": "remove1", "rev": "4-" + o.rev_hash},
-          "Remove document");
-    o.jio.remove({"_id": "remove1", "_rev": o.last_rev}, o.f);
-    o.tick(o);
-
-    // 11. check document tree
-    o.doctree.children[0].children[0].children[0].children.unshift({
-      "rev": "4-" + o.rev_hash,
-      "status": "deleted",
-      "children": []
-    });
-    deepEqual(util.jsonlocalstorage.getItem(
-      o.localpath + "/remove1.revision_tree.json"
-    ), o.doctree, "Check document tree");
+      return jio_local.get({"_id": "post1.revision_tree.json"});
 
-    util.closeAndcleanUpJio(o.jio);
-  });
+    }).then(function (answer) {
 
-  test("allDocs", function () {
+      deepEqual(answer.data, shared.doc_tree, "Check document tree");
 
-    var o = generateTools();
+    }).fail(unexpectedError).always(start);
 
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "urevad1",
-        "application_name": "arevad1"
-      }
-    });
-    o.localpath = "jio/localstorage/urevad1/arevad1";
-
-    // adding 3 documents
-    o.jio.put({"_id": "yes"}, function (err, response) {
-      o.rev1 = (response || {}).rev;
-    });
-    o.jio.put({"_id": "no"}, function (err, response) {
-      o.rev2 = (response || {}).rev;
-    });
-    o.jio.put({"_id": "maybe"}, function (err, response) {
-      o.rev3 = (response || {}).rev;
-    });
-    o.clock.tick(1000);
-
-    // adding conflicts
-    o.jio.put({"_id": "maybe"});
-
-    // adding 2 attachments
-    o.jio.putAttachment({
-      "_id": "yes",
-      "_attachment": "blue",
-      "_mimetype": "text/plain",
-      "_rev": o.rev1,
-      "_data": "sky"
-    }, function (err, response) {
-      o.rev1 = (response || {}).rev;
-    });
-    o.jio.putAttachment({
-      "_id": "no",
-      "_attachment": "Heeeee!",
-      "_mimetype": "text/plain",
-      "_rev": o.rev2,
-      "_data": "Hooooo!"
-    }, function (err, response) {
-      o.rev2 = (response || {}).rev;
-    });
-    o.clock.tick(1000);
-
-    o.rows = {
-      "total_rows": 3,
-      "rows": [{
-        "id": "maybe",
-        "key": "maybe",
-        "value": {
-          "rev": o.rev3
-        }
-      }, {
-        "id": "no",
-        "key": "no",
-        "value": {
-          "rev": o.rev2
-        }
-      }, {
-        "id": "yes",
-        "key": "yes",
-        "value": {
-          "rev": o.rev1
-        }
-      }]
-    };
-    o.spy(o, "value", o.rows, "allDocs");
-    o.jio.allDocs(function (err, response) {
-      if (response && response.rows) {
-        response.rows.sort(function (a, b) {
-          return a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
-        });
-      }
-      o.f(err, response);
-    });
-    o.tick(o);
-
-    o.rows.rows[0].doc = {
-      "_id": "maybe",
-      "_rev": o.rev3
-    };
-    o.rows.rows[1].doc = {
-      "_id": "no",
-      "_rev": o.rev2,
-      "_attachments": {
-        "Heeeee!": {
-          "content_type": "text/plain",
-          "digest": "md5-2686969b0bc0fd9bc186146a1ecb09a7",
-          "length": 7
-        }
-      },
-    };
-    o.rows.rows[2].doc = {
-      "_id": "yes",
-      "_rev": o.rev1,
-      "_attachments": {
-        "blue": {
-          "content_type": "text/plain",
-          "digest": "md5-900bc885d7553375aec470198a9514f3",
-          "length":  3
-        }
-      },
-    };
-    o.spy(o, "value", o.rows, "allDocs + include docs");
-    o.jio.allDocs({"include_docs": true}, function (err, response) {
-      if (response && response.rows) {
-        response.rows.sort(function (a, b) {
-          return a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
-        });
-      }
-      o.f(err, response);
-    });
-    o.tick(o);
-
-    util.closeAndcleanUpJio(o.jio);
   });
 
-  test("Scenario", function () {
-
-    var o = generateTools();
-
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "usam1",
-        "application_name": "asam1"
-      }
-    });
-    o.localpath = "jio/localstorage/usam1/asam1";
-
-    // new application
-    ok(o.jio, "I open my application with revision and localstorage");
-
-    // put non empty document A-1
-    o.doc = {"_id": "sample1", "title": "mySample1"};
-    o.revisions = {"start": 0, "ids": []};
-    o.hex = generateRevisionHash(o.doc, o.revisions);
-    o.rev = "1-" + o.hex;
-
-    o.spy(o, "value", {"ok": true, "id": "sample1", "rev": o.rev},
-          "Then, I create a new document (no attachment), my application " +
-          "keep the revision in memory");
-    o.jio.put(o.doc, o.f);
-    o.tick(o);
-
-    // open new tab (JIO)
-    o.jio2 = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "usam1",
-        "application_name": "asam1"
-      }
-    });
-    o.localpath = "jio/localstorage/usam1/asam1";
-
-    // Create a new JIO in a new tab
-    ok(o.jio2, "Now, I am opening a new tab, with the same application" +
-       " and the same storage tree");
-
-    // Get the document from the first storage
-    o.doc._rev = o.rev;
-    o.doc._revisions = {"ids": [o.hex], "start": 1};
-    o.doc._revs_info = [{"rev": o.rev, "status": "available"}];
-    o.spy(o, "value", o.doc, "And, on this new tab, I load the document," +
-          "and my application keep the revision in memory");
-    o.jio2.get({"_id": "sample1", "_rev": o.rev}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true,
-    }, o.f);
-    o.tick(o);
-
-    // MODIFY the 2nd version
-    o.doc_2 = {"_id": "sample1", "_rev": o.rev,
-               "title": "mySample2_modified"};
-    o.revisions_2 = {"start": 1, "ids": [o.hex]};
-    o.hex_2 = generateRevisionHash(o.doc_2, o.revisions_2);
-    o.rev_2 = "2-" + o.hex_2;
-    o.spy(o, "value", {"id": "sample1", "ok": true, "rev": o.rev_2},
-          "So, I can modify and update it");
-    o.jio2.put(o.doc_2, o.f);
-    o.tick(o);
-
-    // MODIFY first version
-    o.doc_1 = {
-      "_id": "sample1",
-      "_rev": o.rev,
-      "title": "mySample1_modified"
-    };
-    o.revisions_1 = {"start": 1, "ids": [o.rev.split('-')[1]]};
-    o.hex_1 = generateRevisionHash(o.doc_1, o.revisions_1);
-    o.rev_1 = "2-" + o.hex_1;
-    o.spy(o, "value", {"id": "sample1", "ok": true, "rev": o.rev_1},
-          "Back to the first tab, I update the document.");
-    o.jio.put(o.doc_1, o.f);
-    o.tick(o);
-
-    // Close 1st tab
-    o.jio.close();
-
-    // Close 2nd tab
-    o.jio2.close();
-    ok(o.jio2, "I close tab both tabs");
-
-    // Reopen JIO
-    o.jio = jIO.newJio({
-      "type": "revision",
-      "sub_storage": {
-        "type": "local",
-        "username": "usam1",
-        "application_name": "asam1"
-      }
-    });
-    o.localpath = "jio/localstorage/usam1/asam1";
-    ok(o.jio, "Later, I open my application again");
-
-    // GET document without revision = winner & conflict!
-    o.mydocSample3 = {"_id": "sample1", "title": "mySample1_modified",
-                      "_rev": o.rev_1};
-    o.mydocSample3._conflicts = [o.rev_2];
-    o.mydocSample3._revs_info = [{"rev": o.rev_1, "status": "available"}, {
-      "rev": o.rev,
-      "status": "available"
-    }];
-    o.mydocSample3._revisions = {"ids": [o.hex_1, o.hex], "start": 2};
-    o.spy(o, "value", o.mydocSample3, "I load the same document as before" +
-          ", and a popup shows that there is a conflict");
-    o.jio.get({"_id": "sample1"}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true
-    }, o.f);
-    o.tick(o);
-
-    // REMOVE one of the two conflicting versions
-    o.revisions = {"start": 2, "ids": [
-      o.rev_1.split('-')[1],
-      o.rev.split('-')[1]
-    ]};
-    o.doc_myremove3 = {"_id": "sample1", "_rev": o.rev_1};
-    o.rev_3 = "3-" + generateRevisionHash(o.doc_myremove3, o.revisions, true);
-
-    o.spy(o, "value", {"ok": true, "id": "sample1", "rev": o.rev_3},
-           "I choose one of the document and close the application.");
-    o.jio.remove({"_id": "sample1", "_rev": o.rev_1}, o.f);
-    o.tick(o);
-
-    // check to see if conflict still exists
-    o.mydocSample4 = {
-      "_id": "sample1",
-      "title": "mySample2_modified",
-      "_rev": o.rev_2
-    };
-    o.mydocSample4._revs_info = [{"rev": o.rev_2, "status": "available"}, {
-      "rev": o.rev,
-      "status": "available"
-    }];
-    o.mydocSample4._revisions = {"ids": [o.hex_2, o.hex], "start": 2};
-
-    o.spy(o, "value", o.mydocSample4, "Test if conflict still exists");
-    o.jio.get({"_id": "sample1"}, {
-      "revs_info": true,
-      "revs": true,
-      "conflicts": true
-    }, o.f);
-    o.tick(o);
-
-    // END
-    util.closeAndcleanUpJio(o.jio);
-  });
+  // test("Put", function () {
+
+  //   var o = generateTools();
+
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "urevput",
+  //       "application_name": "arevput"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/urevput/arevput";
+
+  //   // put without id
+  //   // error 20 -> document id required
+  //   o.spy(o, "status", 20, "Put without id");
+  //   o.jio.put({}, o.f);
+  //   o.tick(o);
+
+  //   // put non empty document
+  //   o.doc = {"_id": "put1", "title": "myPut1"};
+  //   o.revisions = {"start": 0, "ids": []};
+  //   o.rev = "1-" + generateRevisionHash(o.doc, o.revisions);
+  //   o.spy(o, "value", {"ok": true, "id": "put1", "rev": o.rev},
+  //          "Creates a document");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   o.doc._id = "put1." + o.rev;
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
+  //     o.doc,
+  //     "Check document"
+  //   );
+
+  //   // check document tree
+  //   o.doc_tree = {
+  //     "_id": "put1.revision_tree.json",
+  //     "children": [{
+  //       "rev": o.rev,
+  //       "status": "available",
+  //       "children": []
+  //     }]
+  //   };
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       o.localpath + "/put1.revision_tree.json"
+  //     ),
+  //     o.doc_tree,
+  //     "Check document tree"
+  //   );
+
+  //   // put without rev and document already exists
+  //   o.doc = {"_id": "put1", "title": "myPut2"};
+  //   o.rev = "1-" + generateRevisionHash(o.doc, o.revisions);
+  //   o.spy(o, "value", {"ok": true, "id": "put1", "rev": o.rev},
+  //          "Put same document without revision");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   o.doc_tree.children.unshift({
+  //     "rev": o.rev,
+  //     "status": "available",
+  //     "children": []
+  //   });
+
+  //   // put + revision
+  //   o.doc = {"_id": "put1", "_rev": o.rev, "title": "myPut2"};
+  //   o.revisions = {"start": 1, "ids": [o.rev.split('-')[1]]};
+  //   o.rev = "2-" + generateRevisionHash(o.doc, o.revisions);
+  //   o.spy(o, "value", {"id": "put1", "ok": true, "rev": o.rev},
+  //          "Put + revision");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   o.doc._id = "put1." + o.rev;
+  //   delete o.doc._rev;
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
+  //     o.doc,
+  //     "Check document"
+  //   );
+
+  //   // check document tree
+  //   o.doc_tree.children[0].children.unshift({
+  //     "rev": o.rev,
+  //     "status": "available",
+  //     "children": []
+  //   });
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       o.localpath + "/put1.revision_tree.json"
+  //     ),
+  //     o.doc_tree,
+  //     "Check document tree"
+  //   );
+
+  //   // put + wrong revision
+  //   o.doc = {"_id": "put1", "_rev": "3-wr3", "title": "myPut3"};
+  //   o.revisions = {"start": 3, "ids": ["wr3"]};
+  //   o.rev = "4-" + generateRevisionHash(o.doc, o.revisions);
+  //   o.spy(o, "value", {"id": "put1", "ok": true, "rev": o.rev},
+  //          "Put + wrong revision");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   o.doc._id = "put1." + o.rev;
+  //   delete o.doc._rev;
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
+  //     o.doc,
+  //     "Check document"
+  //   );
+
+  //   // check document tree
+  //   o.doc_tree.children.unshift({
+  //     "rev": "3-wr3",
+  //     "status": "missing",
+  //     "children": [{
+  //       "rev": o.rev,
+  //       "status": "available",
+  //       "children": []
+  //     }]
+  //   });
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       o.localpath + "/put1.revision_tree.json"
+  //     ),
+  //     o.doc_tree,
+  //     "Check document tree"
+  //   );
+
+  //   // put + revision history
+  //   o.doc = {
+  //     "_id": "put1",
+  //     //"_revs": ["3-rh3", "2-rh2", "1-rh1"], // same as below
+  //     "_revs": {"start": 3, "ids": ["rh3", "rh2", "rh1"]},
+  //     "title": "myPut3"
+  //   };
+  //   o.spy(o, "value", {"id": "put1", "ok": true, "rev": "3-rh3"},
+  //          "Put + revision history");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   o.doc._id = "put1.3-rh3";
+  //   delete o.doc._revs;
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(o.localpath + "/put1.3-rh3"),
+  //     o.doc,
+  //     "Check document"
+  //   );
+
+  //   // check document tree
+  //   o.doc_tree.children.unshift({
+  //     "rev": "1-rh1",
+  //     "status": "missing",
+  //     "children": [{
+  //       "rev": "2-rh2",
+  //       "status": "missing",
+  //       "children": [{
+  //         "rev": "3-rh3",
+  //         "status": "available",
+  //         "children": []
+  //       }]
+  //     }]
+  //   });
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       o.localpath + "/put1.revision_tree.json"
+  //     ),
+  //     o.doc_tree,
+  //     "Check document tree"
+  //   );
+
+  //   // add attachment
+  //   o.doc._attachments = {
+  //     "att1": {
+  //       "length": 1,
+  //       "content_type": "text/plain",
+  //       "digest": "md5-0cc175b9c0f1b6a831c399e269772661"
+  //     },
+  //     "att2": {
+  //       "length": 2,
+  //       "content_type": "dont/care",
+  //       "digest": "md5-5360af35bde9ebd8f01f492dc059593c"
+  //     }
+  //   };
+  //   util.jsonlocalstorage.setItem(o.localpath + "/put1.3-rh3", o.doc);
+  //   util.jsonlocalstorage.setItem(o.localpath + "/put1.3-rh3/att1", "a");
+  //   util.jsonlocalstorage.setItem(o.localpath + "/put1.3-rh3/att2", "bc");
+
+  //   // put + revision with attachment
+  //   o.attachments = o.doc._attachments;
+  //   o.doc = {"_id": "put1", "_rev": "3-rh3", "title": "myPut4"};
+  //   o.revisions = {"start": 3, "ids": ["rh3", "rh2", "rh1"]};
+  //   o.rev = "4-" + generateRevisionHash(o.doc, o.revisions);
+  //   o.spy(o, "value", {"id": "put1", "ok": true, "rev": o.rev},
+  //          "Put + revision (document contains attachments)");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   o.doc._id = "put1." + o.rev;
+  //   o.doc._attachments = o.attachments;
+  //   delete o.doc._rev;
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev),
+  //     o.doc,
+  //     "Check document"
+  //   );
+
+  //   // check attachments
+  //   deepEqual(
+  //    util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev + "/att1"),
+  //     "a",
+  //     "Check Attachment"
+  //   );
+  //   deepEqual(
+  //    util.jsonlocalstorage.getItem(o.localpath + "/put1." + o.rev + "/att2"),
+  //     "bc",
+  //     "Check Attachment"
+  //   );
+
+  //   // check document tree
+  //   o.doc_tree.children[0].children[0].children[0].children.unshift({
+  //     "rev": o.rev,
+  //     "status": "available",
+  //     "children": []
+  //   });
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       o.localpath + "/put1.revision_tree.json"
+  //     ),
+  //     o.doc_tree,
+  //     "Check document tree"
+  //   );
+
+  //   util.closeAndcleanUpJio(o.jio);
+
+  // });
+
+  // test("Put Attachment", function () {
+
+  //   var o = generateTools();
+
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "urevputattmt",
+  //       "application_name": "arevputattmt"
+  //     }
+  //   });
+
+  //   // putAttachment without doc id
+  //   // error 20 -> document id required
+  //   o.spy(o, "status", 20, "PutAttachment without doc id" +
+  //         " -> 20 document id required");
+  //   o.jio.putAttachment({}, o.f);
+  //   o.tick(o);
+
+  //   // putAttachment without attachment id
+  //   // erorr 22 -> attachment id required
+  //   o.spy(o, "status", 22, "PutAttachment without attachment id" +
+  //         " -> 22 attachment id required");
+  //   o.jio.putAttachment({"_id": "putattmt1"}, o.f);
+  //   o.tick(o);
+
+  //   // putAttachment without document
+  //   o.revisions = {"start": 0, "ids": []};
+  // o.rev_hash = generateRevisionHash({"_id": "doc1", "_attachment": "attmt1"},
+  //                                     o.revisions);
+  //   o.rev = "1-" + o.rev_hash;
+  //   o.spy(o, "value",
+  //         {"ok": true, "id": "doc1", "attachment": "attmt1", "rev": o.rev},
+  //         "PutAttachment without document, without data");
+  //   o.jio.putAttachment({"_id": "doc1", "_attachment": "attmt1"}, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
+  //     ),
+  //     {
+  //       "_id": "doc1." + o.rev,
+  //       "_attachments": {
+  //         "attmt1": {
+  //           "length": 0,
+  //           // md5("")
+  //           "digest": "md5-d41d8cd98f00b204e9800998ecf8427e"
+  //         }
+  //       }
+  //     },
+  //     "Check document"
+  //   );
+
+  //   // check attachment
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
+  //       + "/attmt1"
+  //   ), "", "Check attachment");
+  //   // adding a metadata to the document
+  //   o.doc = util.jsonlocalstorage.getItem(
+  //     "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
+  //   );
+  //   o.doc.title = "My Title";
+  //   util.jsonlocalstorage.setItem(
+  //     "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev,
+  //     o.doc
+  //   );
+
+  //   // update attachment
+  //   o.prev_rev = o.rev;
+  //   o.revisions = {"start": 1, "ids": [o.rev_hash]};
+  //   o.rev_hash = generateRevisionHash({
+  //     "_id": "doc1",
+  //     "_data": "abc",
+  //     "_attachment": "attmt1",
+  //   }, o.revisions);
+  //   o.rev = "2-" + o.rev_hash;
+  //   o.spy(o, "value",
+  //         {"ok": true, "id": "doc1", "attachment": "attmt1", "rev": o.rev},
+  //         "Update Attachment, with data");
+  //   o.jio.putAttachment({
+  //     "_id": "doc1",
+  //     "_data": "abc",
+  //     "_attachment": "attmt1",
+  //     "_rev": o.prev_rev
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
+  //     ),
+  //     {
+  //       "_id": "doc1." + o.rev,
+  //       "title": "My Title",
+  //       "_attachments": {
+  //         "attmt1": {
+  //           "length": 3,
+  //           // md5("abc")
+  //           "digest": "md5-900150983cd24fb0d6963f7d28e17f72"
+  //         }
+  //       }
+  //     },
+  //     "Check document"
+  //   );
+
+  //   // check attachment
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev +
+  //       "/attmt1"
+  //   ), "abc", "Check attachment");
+
+  //   // putAttachment new attachment
+  //   o.prev_rev = o.rev;
+  //   o.revisions = {"start": 2, "ids": [o.rev_hash, o.revisions.ids[0]]};
+  //   o.rev_hash = generateRevisionHash({
+  //     "_id": "doc1",
+  //     "_data": "def",
+  //     "_attachment": "attmt2",
+  //   }, o.revisions);
+  //   o.rev = "3-" + o.rev_hash;
+  //   o.spy(o, "value",
+  //         {"ok": true, "id": "doc1", "attachment": "attmt2", "rev": o.rev},
+  //         "PutAttachment without document, without data");
+  //   o.jio.putAttachment({
+  //     "_id": "doc1",
+  //     "_data": "def",
+  //     "_attachment": "attmt2",
+  //     "_rev": o.prev_rev
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // check document
+  //   deepEqual(
+  //     util.jsonlocalstorage.getItem(
+  //       "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev
+  //     ),
+  //     {
+  //       "_id": "doc1." + o.rev,
+  //       "title": "My Title",
+  //       "_attachments": {
+  //         "attmt1": {
+  //           "length": 3,
+  //           "digest": "md5-900150983cd24fb0d6963f7d28e17f72"
+  //         },
+  //         "attmt2": {
+  //           "length": 3,
+  //           // md5("def")
+  //           "digest": "md5-4ed9407630eb1000c0f6b63842defa7d"
+  //         }
+  //       }
+  //     },
+  //     "Check document"
+  //   );
+
+  //   // check attachment
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     "jio/localstorage/urevputattmt/arevputattmt/doc1." + o.rev +
+  //       "/attmt2"
+  //   ), "def", "Check attachment");
+
+  //   util.closeAndcleanUpJio(o.jio);
+
+  // });
+
+  // test("Get", function () {
+
+  //   var o = generateTools();
+
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "urevget",
+  //       "application_name": "arevget"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/urevget/arevget";
+
+  //   // get inexistent document
+  //   o.spy(o, "status", 404, "Get inexistent document (winner)" +
+  //         " -> 404 Not Found");
+  //   o.jio.get({"_id": "get1"}, o.f);
+  //   o.tick(o);
+
+  //   // get inexistent attachment
+  //   o.spy(o, "status", 404, "Get inexistent attachment (winner)" +
+  //         " -> 404 Not Found");
+  //   o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f);
+  //   o.tick(o);
+
+  //   // adding a document
+  //   o.doctree = {"children": [{
+  //     "rev": "1-rev1",
+  //     "status": "available",
+  //     "children": []
+  //   }]};
+  //   o.doc_myget1 = {"_id": "get1.1-rev1", "title": "myGet1"};
+  //   util.jsonlocalstorage.setItem(
+  //     o.localpath + "/get1.revision_tree.json",
+  //     o.doctree
+  //   );
+  //  util.jsonlocalstorage.setItem(o.localpath + "/get1.1-rev1", o.doc_myget1);
+
+  //   // get document
+  //   o.doc_myget1_cloned = deepClone(o.doc_myget1);
+  //   o.doc_myget1_cloned._id = "get1";
+  //   o.doc_myget1_cloned._rev = "1-rev1";
+  //   o.doc_myget1_cloned._revisions = {"start": 1, "ids": ["rev1"]};
+  //   o.doc_myget1_cloned._revs_info = [{
+  //     "rev": "1-rev1",
+  //     "status": "available"
+  //   }];
+  //   o.spy(o, "value", o.doc_myget1_cloned, "Get document (winner)");
+  //   o.jio.get({"_id": "get1"}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // adding two documents
+  //   o.doctree = {"children": [{
+  //     "rev": "1-rev1",
+  //     "status": "available",
+  //     "children": []
+  //   }, {
+  //     "rev": "1-rev2",
+  //     "status": "available",
+  //     "children": [{
+  //       "rev": "2-rev3",
+  //       "status": "available",
+  //       "children": []
+  //     }]
+  //   }]};
+  //   o.doc_myget2 = {"_id": "get1.1-rev2", "title": "myGet2"};
+  //   o.doc_myget3 = {"_id": "get1.2-rev3", "title": "myGet3"};
+  //   util.jsonlocalstorage.setItem(
+  //     o.localpath + "/get1.revision_tree.json",
+  //     o.doctree
+  //   );
+  //  util.jsonlocalstorage.setItem(o.localpath + "/get1.1-rev2", o.doc_myget2);
+  //  util.jsonlocalstorage.setItem(o.localpath + "/get1.2-rev3", o.doc_myget3);
+
+  //   // get document
+  //   o.doc_myget3_cloned = deepClone(o.doc_myget3);
+  //   o.doc_myget3_cloned._id = "get1";
+  //   o.doc_myget3_cloned._rev = "2-rev3";
+  //   o.doc_myget3_cloned._revisions = {"start": 2, "ids": ["rev3", "rev2"]};
+  //   o.doc_myget3_cloned._revs_info = [{
+  //     "rev": "2-rev3",
+  //     "status": "available"
+  //   }, {
+  //     "rev": "1-rev2",
+  //     "status": "available"
+  //   }];
+  //   o.doc_myget3_cloned._conflicts = ["1-rev1"];
+  //   o.spy(o, "value", o.doc_myget3_cloned,
+  //         "Get document (winner, after posting another one)");
+  //   o.jio.get({"_id": "get1"},
+  //             {"revs_info": true, "revs": true, "conflicts": true},
+  //             o.f);
+  //   o.tick(o);
+
+  //   // get inexistent specific document
+  //   o.spy(o, "status", 404, "Get document (inexistent specific revision)" +
+  //         " -> 404 Not Found");
+  //   o.jio.get({"_id": "get1", "_rev": "1-rev0"}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true,
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // get specific document
+  //   o.doc_myget2_cloned = deepClone(o.doc_myget2);
+  //   o.doc_myget2_cloned._id = "get1";
+  //   o.doc_myget2_cloned._rev = "1-rev2";
+  //   o.doc_myget2_cloned._revisions = {"start": 1, "ids": ["rev2"]};
+  //   o.doc_myget2_cloned._revs_info = [{
+  //     "rev": "1-rev2",
+  //     "status": "available"
+  //   }];
+  //   o.doc_myget2_cloned._conflicts = ["1-rev1"];
+  // o.spy(o, "value", o.doc_myget2_cloned, "Get document (specific revision)");
+  //   o.jio.get({"_id": "get1", "_rev": "1-rev2"}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true,
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // adding an attachment
+  //   o.attmt_myget3 = {
+  //     "get2": {
+  //       "length": 3,
+  //       "digest": "md5-dontcare",
+  //       "content_type": "oh/yeah"
+  //     }
+  //   };
+  //   o.doc_myget3._attachments = o.attmt_myget3;
+  //  util.jsonlocalstorage.setItem(o.localpath + "/get1.2-rev3", o.doc_myget3);
+  //   util.jsonlocalstorage.setItem(o.localpath + "/get1.2-rev3/get2", "abc");
+
+  //   // get attachment winner
+  //   o.spy(o, "value", "abc", "Get attachment (winner)");
+  //   o.jio.getAttachment({"_id": "get1", "_attachment": "get2"}, o.f);
+  //   o.tick(o);
+
+  //   // get inexistent attachment specific rev
+  //   o.spy(o, "status", 404, "Get inexistent attachment (specific revision)" +
+  //         " -> 404 Not Found");
+  //   o.jio.getAttachment({
+  //     "_id": "get1",
+  //     "_attachment": "get2",
+  //     "_rev": "1-rev1"
+  //   }, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true,
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // get attachment specific rev
+  //   o.spy(o, "value", "abc", "Get attachment (specific revision)");
+  //   o.jio.getAttachment({
+  //     "_id": "get1",
+  //     "_attachment": "get2",
+  //     "_rev": "2-rev3"
+  //   }, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true,
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // get document with attachment (specific revision)
+  //   delete o.doc_myget2_cloned._attachments;
+  //   o.spy(o, "value", o.doc_myget2_cloned,
+  //         "Get document which have an attachment (specific revision)");
+  //   o.jio.get({"_id": "get1", "_rev": "1-rev2"}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // get document with attachment (winner)
+  //   o.doc_myget3_cloned._attachments = o.attmt_myget3;
+  //   o.spy(o, "value", o.doc_myget3_cloned,
+  //         "Get document which have an attachment (winner)");
+  //   o.jio.get({"_id": "get1"},
+  //             {"revs_info": true, "revs": true, "conflicts": true},
+  //             o.f);
+  //   o.tick(o);
+
+  //   util.closeAndcleanUpJio(o.jio);
+
+  // });
+
+  // test("Remove", function () {
+
+  //   var o = generateTools();
+
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "urevrem",
+  //       "application_name": "arevrem"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/urevrem/arevrem";
+
+  //   // 1. remove document without revision
+  //   o.spy(o, "status", 409, "Remove document without revision " +
+  //         "-> 409 Conflict");
+  //   o.jio.remove({"_id": "remove1"}, o.f);
+  //   o.tick(o);
+
+  //   // 2. remove attachment without revision
+  //   o.spy(o, "status", 409, "Remove attachment without revision " +
+  //         "-> 409 Conflict");
+  //  o.jio.removeAttachment({"_id": "remove1", "_attachment": "remove2"}, o.f);
+  //   o.tick(o);
+
+  //   // adding a document with attachments
+  //   o.doc_myremove1 = {
+  //     "_id": "remove1.1-veryoldrev",
+  //     "title": "myRemove1"
+  //   };
+
+  //   util.jsonlocalstorage.setItem(o.localpath + "/remove1.1-veryoldrev",
+  //                        o.doc_myremove1);
+
+  //   o.doc_myremove1._id = "remove1.2-oldrev";
+  //   o.attachment_remove2 = {
+  //     "length": 3,
+  //     "digest": "md5-dontcare",
+  //     "content_type": "oh/yeah"
+  //   };
+  //   o.attachment_remove3 = {
+  //     "length": 5,
+  //     "digest": "md5-865f5cc7fbd7854902eae9d8211f178a",
+  //     "content_type": "he/ho"
+  //   };
+  //   o.doc_myremove1._attachments = {
+  //     "remove2": o.attachment_remove2,
+  //     "remove3": o.attachment_remove3
+  //   };
+
+  //   util.jsonlocalstorage.setItem(o.localpath + "/remove1.2-oldrev",
+  //                        o.doc_myremove1);
+  //   util.jsonlocalstorage.setItem(
+  //     o.localpath + "/remove1.2-oldrev/remove2",
+  //     "abc"
+  //   );
+  //   util.jsonlocalstorage.setItem(
+  //     o.localpath + "/remove1.2-oldrev/remove3",
+  //     "defgh"
+  //   );
+
+  //   // add document tree
+  //   o.doctree = {
+  //     "children": [{
+  //       "rev": "1-veryoldrev",
+  //       "status": "available",
+  //       "children": [{
+  //         "rev": "2-oldrev",
+  //         "status": "available",
+  //         "children": []
+  //       }]
+  //     }]
+  //   };
+  //  util.jsonlocalstorage.setItem(o.localpath + "/remove1.revision_tree.json",
+  //                        o.doctree);
+
+  //   // 3. remove inexistent attachment
+  //   o.spy(o, "status", 404, "Remove inexistent attachment -> 404 Not Found");
+  //   o.jio.removeAttachment({
+  //     "_id": "remove1",
+  //     "_attachment": "remove0",
+  //     "_rev": "2-oldrev"
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // 4. remove existing attachment
+  //   o.rev_hash = generateRevisionHash({
+  //     "_id": "remove1",
+  //     "_attachment": "remove2",
+  //   }, {"start": 2, "ids": ["oldrev", "veryoldrev"]});
+  //   o.spy(o, "value", {
+  //     "ok": true,
+  //     "id": "remove1",
+  //     "attachment": "remove2",
+  //     "rev": "3-" + o.rev_hash
+  //   }, "Remove existing attachment");
+  //   o.jio.removeAttachment({
+  //     "_id": "remove1",
+  //     "_attachment": "remove2",
+  //     "_rev": "2-oldrev"
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   o.doctree = {
+  //     "_id": "remove1.revision_tree.json",
+  //     "children": [{
+  //       "rev": "1-veryoldrev",
+  //       "status": "available",
+  //       "children": [{
+  //         "rev": "2-oldrev",
+  //         "status": "available",
+  //         "children": [{
+  //           "rev": "3-" + o.rev_hash,
+  //           "status": "available",
+  //           "children": []
+  //         }]
+  //       }]
+  //     }]
+  //   };
+
+  //   // 5. check if document tree has been updated correctly
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     o.localpath + "/remove1.revision_tree.json"
+  //   ), o.doctree, "Check document tree");
+
+  //   // 6. check if the attachment still exists
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     o.localpath + "/remove1.2-oldrev/remove2"
+  //   ), "abc", "Check attachment -> still exists");
+
+  //   // 7. check if document is updated
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     o.localpath + "/remove1.3-" + o.rev_hash
+  //   ), {
+  //     "_id": "remove1.3-" + o.rev_hash,
+  //     "title": "myRemove1",
+  //     "_attachments": {"remove3": o.attachment_remove3}
+  //   }, "Check document");
+
+  //   // 8. remove document with wrong revision
+  //   o.spy(o, "status", 409, "Remove document with wrong revision " +
+  //         "-> 409 Conflict");
+  //   o.jio.remove({"_id": "remove1", "_rev": "1-a"}, o.f);
+  //   o.tick(o);
+
+  //   // 9. remove attachment wrong revision
+  //   o.spy(o, "status", 409, "Remove attachment with wrong revision " +
+  //         "-> 409 Conflict");
+  //   o.jio.removeAttachment({
+  //     "_id": "remove1",
+  //     "_attachment": "remove2",
+  //     "_rev": "1-a"
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // 10. remove document
+  //   o.last_rev = "3-" + o.rev_hash;
+  //   o.rev_hash = generateRevisionHash(
+  //     {"_id": "remove1"},
+  //     {"start": 3, "ids": [o.rev_hash, "oldrev", "veryoldrev"]},
+  //     true
+  //   );
+  //  o.spy(o, "value", {"ok": true, "id": "remove1", "rev": "4-" + o.rev_hash},
+  //         "Remove document");
+  //   o.jio.remove({"_id": "remove1", "_rev": o.last_rev}, o.f);
+  //   o.tick(o);
+
+  //   // 11. check document tree
+  //   o.doctree.children[0].children[0].children[0].children.unshift({
+  //     "rev": "4-" + o.rev_hash,
+  //     "status": "deleted",
+  //     "children": []
+  //   });
+  //   deepEqual(util.jsonlocalstorage.getItem(
+  //     o.localpath + "/remove1.revision_tree.json"
+  //   ), o.doctree, "Check document tree");
+
+  //   util.closeAndcleanUpJio(o.jio);
+  // });
+
+  // test("allDocs", function () {
+
+  //   var o = generateTools();
+
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "urevad1",
+  //       "application_name": "arevad1"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/urevad1/arevad1";
+
+  //   // adding 3 documents
+  //   o.jio.put({"_id": "yes"}, function (err, response) {
+  //     o.rev1 = (response || {}).rev;
+  //   });
+  //   o.jio.put({"_id": "no"}, function (err, response) {
+  //     o.rev2 = (response || {}).rev;
+  //   });
+  //   o.jio.put({"_id": "maybe"}, function (err, response) {
+  //     o.rev3 = (response || {}).rev;
+  //   });
+  //   o.clock.tick(1000);
+
+  //   // adding conflicts
+  //   o.jio.put({"_id": "maybe"});
+
+  //   // adding 2 attachments
+  //   o.jio.putAttachment({
+  //     "_id": "yes",
+  //     "_attachment": "blue",
+  //     "_mimetype": "text/plain",
+  //     "_rev": o.rev1,
+  //     "_data": "sky"
+  //   }, function (err, response) {
+  //     o.rev1 = (response || {}).rev;
+  //   });
+  //   o.jio.putAttachment({
+  //     "_id": "no",
+  //     "_attachment": "Heeeee!",
+  //     "_mimetype": "text/plain",
+  //     "_rev": o.rev2,
+  //     "_data": "Hooooo!"
+  //   }, function (err, response) {
+  //     o.rev2 = (response || {}).rev;
+  //   });
+  //   o.clock.tick(1000);
+
+  //   o.rows = {
+  //     "total_rows": 3,
+  //     "rows": [{
+  //       "id": "maybe",
+  //       "key": "maybe",
+  //       "value": {
+  //         "rev": o.rev3
+  //       }
+  //     }, {
+  //       "id": "no",
+  //       "key": "no",
+  //       "value": {
+  //         "rev": o.rev2
+  //       }
+  //     }, {
+  //       "id": "yes",
+  //       "key": "yes",
+  //       "value": {
+  //         "rev": o.rev1
+  //       }
+  //     }]
+  //   };
+  //   o.spy(o, "value", o.rows, "allDocs");
+  //   o.jio.allDocs(function (err, response) {
+  //     if (response && response.rows) {
+  //       response.rows.sort(function (a, b) {
+  //         return a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
+  //       });
+  //     }
+  //     o.f(err, response);
+  //   });
+  //   o.tick(o);
+
+  //   o.rows.rows[0].doc = {
+  //     "_id": "maybe",
+  //     "_rev": o.rev3
+  //   };
+  //   o.rows.rows[1].doc = {
+  //     "_id": "no",
+  //     "_rev": o.rev2,
+  //     "_attachments": {
+  //       "Heeeee!": {
+  //         "content_type": "text/plain",
+  //         "digest": "md5-2686969b0bc0fd9bc186146a1ecb09a7",
+  //         "length": 7
+  //       }
+  //     },
+  //   };
+  //   o.rows.rows[2].doc = {
+  //     "_id": "yes",
+  //     "_rev": o.rev1,
+  //     "_attachments": {
+  //       "blue": {
+  //         "content_type": "text/plain",
+  //         "digest": "md5-900bc885d7553375aec470198a9514f3",
+  //         "length":  3
+  //       }
+  //     },
+  //   };
+  //   o.spy(o, "value", o.rows, "allDocs + include docs");
+  //   o.jio.allDocs({"include_docs": true}, function (err, response) {
+  //     if (response && response.rows) {
+  //       response.rows.sort(function (a, b) {
+  //         return a.id > b.id ? 1 : a.id < b.id ? -1 : 0;
+  //       });
+  //     }
+  //     o.f(err, response);
+  //   });
+  //   o.tick(o);
+
+  //   util.closeAndcleanUpJio(o.jio);
+  // });
+
+  // test("Scenario", function () {
+
+  //   var o = generateTools();
+
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "usam1",
+  //       "application_name": "asam1"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/usam1/asam1";
+
+  //   // new application
+  //   ok(o.jio, "I open my application with revision and localstorage");
+
+  //   // put non empty document A-1
+  //   o.doc = {"_id": "sample1", "title": "mySample1"};
+  //   o.revisions = {"start": 0, "ids": []};
+  //   o.hex = generateRevisionHash(o.doc, o.revisions);
+  //   o.rev = "1-" + o.hex;
+
+  //   o.spy(o, "value", {"ok": true, "id": "sample1", "rev": o.rev},
+  //         "Then, I create a new document (no attachment), my application " +
+  //         "keep the revision in memory");
+  //   o.jio.put(o.doc, o.f);
+  //   o.tick(o);
+
+  //   // open new tab (JIO)
+  //   o.jio2 = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "usam1",
+  //       "application_name": "asam1"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/usam1/asam1";
+
+  //   // Create a new JIO in a new tab
+  //   ok(o.jio2, "Now, I am opening a new tab, with the same application" +
+  //      " and the same storage tree");
+
+  //   // Get the document from the first storage
+  //   o.doc._rev = o.rev;
+  //   o.doc._revisions = {"ids": [o.hex], "start": 1};
+  //   o.doc._revs_info = [{"rev": o.rev, "status": "available"}];
+  //   o.spy(o, "value", o.doc, "And, on this new tab, I load the document," +
+  //         "and my application keep the revision in memory");
+  //   o.jio2.get({"_id": "sample1", "_rev": o.rev}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true,
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // MODIFY the 2nd version
+  //   o.doc_2 = {"_id": "sample1", "_rev": o.rev,
+  //              "title": "mySample2_modified"};
+  //   o.revisions_2 = {"start": 1, "ids": [o.hex]};
+  //   o.hex_2 = generateRevisionHash(o.doc_2, o.revisions_2);
+  //   o.rev_2 = "2-" + o.hex_2;
+  //   o.spy(o, "value", {"id": "sample1", "ok": true, "rev": o.rev_2},
+  //         "So, I can modify and update it");
+  //   o.jio2.put(o.doc_2, o.f);
+  //   o.tick(o);
+
+  //   // MODIFY first version
+  //   o.doc_1 = {
+  //     "_id": "sample1",
+  //     "_rev": o.rev,
+  //     "title": "mySample1_modified"
+  //   };
+  //   o.revisions_1 = {"start": 1, "ids": [o.rev.split('-')[1]]};
+  //   o.hex_1 = generateRevisionHash(o.doc_1, o.revisions_1);
+  //   o.rev_1 = "2-" + o.hex_1;
+  //   o.spy(o, "value", {"id": "sample1", "ok": true, "rev": o.rev_1},
+  //         "Back to the first tab, I update the document.");
+  //   o.jio.put(o.doc_1, o.f);
+  //   o.tick(o);
+
+  //   // Close 1st tab
+  //   o.jio.close();
+
+  //   // Close 2nd tab
+  //   o.jio2.close();
+  //   ok(o.jio2, "I close tab both tabs");
+
+  //   // Reopen JIO
+  //   o.jio = jIO.newJio({
+  //     "type": "revision",
+  //     "sub_storage": {
+  //       "type": "local",
+  //       "username": "usam1",
+  //       "application_name": "asam1"
+  //     }
+  //   });
+  //   o.localpath = "jio/localstorage/usam1/asam1";
+  //   ok(o.jio, "Later, I open my application again");
+
+  //   // GET document without revision = winner & conflict!
+  //   o.mydocSample3 = {"_id": "sample1", "title": "mySample1_modified",
+  //                     "_rev": o.rev_1};
+  //   o.mydocSample3._conflicts = [o.rev_2];
+  //   o.mydocSample3._revs_info = [{"rev": o.rev_1, "status": "available"}, {
+  //     "rev": o.rev,
+  //     "status": "available"
+  //   }];
+  //   o.mydocSample3._revisions = {"ids": [o.hex_1, o.hex], "start": 2};
+  //   o.spy(o, "value", o.mydocSample3, "I load the same document as before" +
+  //         ", and a popup shows that there is a conflict");
+  //   o.jio.get({"_id": "sample1"}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // REMOVE one of the two conflicting versions
+  //   o.revisions = {"start": 2, "ids": [
+  //     o.rev_1.split('-')[1],
+  //     o.rev.split('-')[1]
+  //   ]};
+  //   o.doc_myremove3 = {"_id": "sample1", "_rev": o.rev_1};
+  //  o.rev_3 = "3-" + generateRevisionHash(o.doc_myremove3, o.revisions, true);
+
+  //   o.spy(o, "value", {"ok": true, "id": "sample1", "rev": o.rev_3},
+  //          "I choose one of the document and close the application.");
+  //   o.jio.remove({"_id": "sample1", "_rev": o.rev_1}, o.f);
+  //   o.tick(o);
+
+  //   // check to see if conflict still exists
+  //   o.mydocSample4 = {
+  //     "_id": "sample1",
+  //     "title": "mySample2_modified",
+  //     "_rev": o.rev_2
+  //   };
+  //   o.mydocSample4._revs_info = [{"rev": o.rev_2, "status": "available"}, {
+  //     "rev": o.rev,
+  //     "status": "available"
+  //   }];
+  //   o.mydocSample4._revisions = {"ids": [o.hex_2, o.hex], "start": 2};
+
+  //   o.spy(o, "value", o.mydocSample4, "Test if conflict still exists");
+  //   o.jio.get({"_id": "sample1"}, {
+  //     "revs_info": true,
+  //     "revs": true,
+  //     "conflicts": true
+  //   }, o.f);
+  //   o.tick(o);
+
+  //   // END
+  //   util.closeAndcleanUpJio(o.jio);
+  // });
 
 }));
-- 
2.30.9