You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by mr...@apache.org on 2016/09/02 16:27:12 UTC
[08/13] usergrid-javascript git commit: Initial commit of Usergrid
Javascript SDK into its own repo
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/lib/modules/util/Ajax.js
----------------------------------------------------------------------
diff --git a/lib/modules/util/Ajax.js b/lib/modules/util/Ajax.js
new file mode 100644
index 0000000..4b8a381
--- /dev/null
+++ b/lib/modules/util/Ajax.js
@@ -0,0 +1,99 @@
+/*
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ *
+ * @author ryan bridges (rbridges@apigee.com)
+ */
+
+//Ajax
+(function() {
+ var name = 'Ajax', global = this, overwrittenName = global[name], exports;
+
+ function partial(){
+ var args = Array.prototype.slice.call(arguments);
+ var fn=args.shift();
+ return fn.bind(this, args);
+ }
+ function Ajax() {
+ this.logger=new global.Logger(name);
+ var self=this;
+ function encode(data) {
+ var result = "";
+ if (typeof data === "string") {
+ result = data;
+ } else {
+ var e = encodeURIComponent;
+ for (var i in data) {
+ if (data.hasOwnProperty(i)) {
+ result += '&' + e(i) + '=' + e(data[i]);
+ }
+ }
+ }
+ return result;
+ }
+ function request(m, u, d) {
+ var p = new Promise(), timeout;
+ self.logger.time(m + ' ' + u);
+ (function(xhr) {
+ xhr.onreadystatechange = function() {
+ if(this.readyState === 4){
+ self.logger.timeEnd(m + ' ' + u);
+ clearTimeout(timeout);
+ p.done(null, this);
+ }
+ };
+ xhr.onerror=function(response){
+ clearTimeout(timeout);
+ p.done(response, null);
+ };
+ xhr.oncomplete=function(response){
+ clearTimeout(timeout);
+ self.logger.timeEnd(m + ' ' + u);
+ self.info("%s request to %s returned %s", m, u, this.status );
+ };
+ xhr.open(m, u);
+ if (d) {
+ if("object"===typeof d){
+ d=JSON.stringify(d);
+ }
+ xhr.setRequestHeader("Content-Type", "application/json");
+ xhr.setRequestHeader("Accept", "application/json");
+ }
+ timeout = setTimeout(function() {
+ xhr.abort();
+ p.done("API Call timed out.", null);
+ }, 30000);
+ //TODO stick that timeout in a config variable
+ xhr.send(encode(d));
+ }(new XMLHttpRequest()));
+ return p;
+ }
+ this.request=request;
+ this.get = partial(request,'GET');
+ this.post = partial(request,'POST');
+ this.put = partial(request,'PUT');
+ this.delete = partial(request,'DELETE');
+ }
+ global[name] = new Ajax();
+ global[name].noConflict = function() {
+ if(overwrittenName){
+ global[name] = overwrittenName;
+ }
+ return exports;
+ };
+ return global[name];
+}());
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/lib/modules/util/Event.js
----------------------------------------------------------------------
diff --git a/lib/modules/util/Event.js b/lib/modules/util/Event.js
new file mode 100644
index 0000000..d826e04
--- /dev/null
+++ b/lib/modules/util/Event.js
@@ -0,0 +1,33 @@
+var UsergridEventable = function(){
+ throw Error("'UsergridEventable' is not intended to be invoked directly");
+};
+UsergridEventable.prototype = {
+ bind : function(event, fn){
+ this._events = this._events || {};
+ this._events[event] = this._events[event] || [];
+ this._events[event].push(fn);
+ },
+ unbind : function(event, fn){
+ this._events = this._events || {};
+ if( event in this._events === false ) return;
+ this._events[event].splice(this._events[event].indexOf(fn), 1);
+ },
+ trigger : function(event /* , args... */){
+ this._events = this._events || {};
+ if( event in this._events === false ) return;
+ for(var i = 0; i < this._events[event].length; i++){
+ this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
+ }
+ }
+};
+UsergridEventable.mixin = function(destObject){
+ var props = ['bind', 'unbind', 'trigger'];
+ for(var i = 0; i < props.length; i ++){
+ if(props[i] in destObject.prototype){
+ console.warn("overwriting '"+props[i]+"' on '"+destObject.name+"'.");
+ console.warn("the previous version can be found at '_"+props[i]+"' on '"+destObject.name+"'.");
+ destObject.prototype['_'+props[i]]=destObject.prototype[props[i]];
+ }
+ destObject.prototype[props[i]] = UsergridEventable.prototype[props[i]];
+ }
+};
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/lib/modules/util/Logger.js
----------------------------------------------------------------------
diff --git a/lib/modules/util/Logger.js b/lib/modules/util/Logger.js
new file mode 100644
index 0000000..c3cf579
--- /dev/null
+++ b/lib/modules/util/Logger.js
@@ -0,0 +1,89 @@
+/*
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ *
+ * @author ryan bridges (rbridges@apigee.com)
+ */
+
+//Logger
+(function() {
+ var name = 'Logger', global = this, overwrittenName = global[name], exports;
+ /* logging */
+ function Logger(name) {
+ this.logEnabled = true;
+ this.init(name, true);
+ }
+ Logger.METHODS=[
+ "log", "error", "warn", "info", "debug", "assert", "clear", "count",
+ "dir", "dirxml", "exception", "group", "groupCollapsed", "groupEnd",
+ "profile", "profileEnd", "table", "time", "timeEnd", "trace"
+ ];
+ Logger.prototype.init=function(name, logEnabled){
+ this.name=name||"UNKNOWN";
+ this.logEnabled=logEnabled||true;
+ var addMethod=function(method){this[method]=this.createLogMethod(method);}.bind(this);
+ Logger.METHODS.forEach(addMethod);
+ };
+ Logger.prototype.createLogMethod=function(method){
+ return Logger.prototype.log.bind(this, method);
+ };
+ Logger.prototype.prefix=function(method, args){
+ var prepend='['+method.toUpperCase()+']['+name+"]:\t";
+ if(['log', 'error', 'warn', 'info'].indexOf(method)!==-1){
+ if("string"===typeof args[0]){
+ args[0]=prepend+args[0];
+ }else{
+ args.unshift(prepend);
+ }
+ }
+ return args;
+ };
+ Logger.prototype.log=function(){
+ var args=[].slice.call(arguments);
+ method=args.shift();
+ if(Logger.METHODS.indexOf(method)===-1){
+ method="log";
+ }
+ if(!(this.logEnabled && console && console[method]))return;
+ args=this.prefix(method, args);
+ console[method].apply(console, args);
+ };
+ Logger.prototype.setLogEnabled=function(logEnabled){
+ this.logEnabled=logEnabled||true;
+ };
+
+ Logger.mixin = function(destObject){
+ destObject.__logger=new Logger(destObject.name||"UNKNOWN");
+ var addMethod=function(method){
+ if(method in destObject.prototype){
+ console.warn("overwriting '"+method+"' on '"+destObject.name+"'.");
+ console.warn("the previous version can be found at '_"+method+"' on '"+destObject.name+"'.");
+ destObject.prototype['_'+method]=destObject.prototype[method];
+ }
+ destObject.prototype[method]=destObject.__logger.createLogMethod(method);
+ };
+ Logger.METHODS.forEach(addMethod);
+ };
+ global[name] = Logger;
+ global[name].noConflict = function() {
+ if(overwrittenName){
+ global[name] = overwrittenName;
+ }
+ return Logger;
+ };
+ return global[name];
+}());
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/lib/modules/util/Promise.js
----------------------------------------------------------------------
diff --git a/lib/modules/util/Promise.js b/lib/modules/util/Promise.js
new file mode 100644
index 0000000..76d0d04
--- /dev/null
+++ b/lib/modules/util/Promise.js
@@ -0,0 +1,101 @@
+/*
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ *
+ * @author ryan bridges (rbridges@apigee.com)
+ */
+
+//Promise
+(function(global) {
+ var name = 'Promise', overwrittenName = global[name], exports;
+
+ function Promise() {
+ this.complete = false;
+ this.error = null;
+ this.result = null;
+ this.callbacks = [];
+ }
+ Promise.prototype.then = function(callback, context) {
+ var f = function() {
+ return callback.apply(context, arguments);
+ };
+ if (this.complete) {
+ f(this.error, this.result);
+ } else {
+ this.callbacks.push(f);
+ }
+ };
+ Promise.prototype.done = function(error, result) {
+ this.complete = true;
+ this.error = error;
+ this.result = result;
+ if(this.callbacks){
+ for (var i = 0; i < this.callbacks.length; i++) this.callbacks[i](error, result);
+ this.callbacks.length = 0;
+ }
+ };
+ Promise.join = function(promises) {
+ var p = new Promise(),
+ total = promises.length,
+ completed = 0,
+ errors = [],
+ results = [];
+
+ function notifier(i) {
+ return function(error, result) {
+ completed += 1;
+ errors[i] = error;
+ results[i] = result;
+ if (completed === total) {
+ p.done(errors, results);
+ }
+ };
+ }
+ for (var i = 0; i < total; i++) {
+ promises[i]().then(notifier(i));
+ }
+ return p;
+ };
+ Promise.chain = function(promises, error, result) {
+ var p = new Promise();
+ if (promises===null||promises.length === 0) {
+ p.done(error, result);
+ } else {
+ promises[0](error, result).then(function(res, err) {
+ promises.splice(0, 1);
+ //self.logger.info(promises.length)
+ if(promises){
+ Promise.chain(promises, res, err).then(function(r, e) {
+ p.done(r, e);
+ });
+ }else{
+ p.done(res, err);
+ }
+ });
+ }
+ return p;
+ };
+
+ global[name] = Promise;
+ global[name].noConflict = function() {
+ if(overwrittenName){
+ global[name] = overwrittenName;
+ }
+ return Promise;
+ };
+ return global[name];
+}(this));
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..72e2046
--- /dev/null
+++ b/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "usergrid",
+ "version": "0.11.0",
+ "description": "Detailed instructions follow but if you just want a quick example of how to get started with this SDK, here\u2019s a minimal HTML5 file that shows you how to include & initialize the SDK, as well as how to read & write data from Usergrid with it.",
+ "main": "usergrid.js",
+ "directories": {
+ "example": "examples"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "Apache 2.0",
+ "devDependencies": {
+ "grunt": "~0.4.2",
+ "grunt-contrib-clean": "~0.5.0",
+ "grunt-contrib-watch": "~0.5.3",
+ "grunt-contrib-uglify": "~0.2.7",
+ "grunt-blanket-mocha": "~0.3.3",
+ "grunt-contrib-connect": "~0.6.0"
+ }
+}
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/tests/mocha/index.html
----------------------------------------------------------------------
diff --git a/tests/mocha/index.html b/tests/mocha/index.html
new file mode 100644
index 0000000..da47564
--- /dev/null
+++ b/tests/mocha/index.html
@@ -0,0 +1,60 @@
+
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Mocha Tests</title>
+ <link rel="stylesheet" href="../resources/css/mocha.css" />
+ <script src="../resources/js/mocha.js"></script>
+ <script>mocha.setup('bdd')</script>
+ <script src="../resources/js/blanket_mocha.min.js"></script>
+ <script type="text/javascript" src="../../node_modules/grunt-blanket-mocha/support/mocha-blanket.js"></script>
+ <script>
+ function assert(expr, msg) {
+ if (!expr) throw new Error(msg || 'failed');
+ }
+ </script>
+
+ <script src="../../usergrid.js" data-cover></script>
+ <script src="test.js"></script>
+<!-- run mocha -->
+ <script type="text/javascript" charset="utf-8">
+ var _onload=onload||function(){};
+ onload = function(){
+ _onload.apply(this, arguments);
+ mocha.checkLeaks();
+ mocha.globals(['']);
+ var runner = mocha.run();
+ /*runner.on('test end', function(test){
+ console.log(test.fullTitle());
+ });*/
+ };
+ </script>
+
+ <script>
+ if (window.PHANTOMJS) {
+ blanket.options("reporter", "../../node_modules/grunt-blanket-mocha/support/grunt-reporter.js");
+ }
+ </script>
+
+</head>
+<body>
+ <div id="mocha"></div>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/tests/mocha/test.js
----------------------------------------------------------------------
diff --git a/tests/mocha/test.js b/tests/mocha/test.js
new file mode 100644
index 0000000..ef4ff54
--- /dev/null
+++ b/tests/mocha/test.js
@@ -0,0 +1,1078 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/*
+ Creates a generic usergrid client with logging and buildCurl disabled
+
+ */
+function getClient() {
+ return new Usergrid.Client({
+ orgName: 'yourorgname',
+ appName: 'sandbox',
+ logging: false, //optional - turn on logging, off by default
+ buildCurl: true //optional - turn on curl commands, off by default
+ });
+}
+/*
+ A convenience function that will test for the presence of an API error
+ and run any number of additional tests
+ */
+function usergridTestHarness(err, data, done, tests, ignoreError) {
+ if (!ignoreError) assert(!err, (err)?err.error_description:"unknown");
+ if (tests) {
+ if ("function" === typeof tests) {
+ tests(err, data);
+ } else if (tests.length) {
+ tests.forEach(function(test) {
+ if ("function" === typeof test) {
+ test(err, data);
+ }
+ })
+ }
+ }
+ done();
+}
+describe('Ajax', function() {
+ var dogName="dog"+Math.floor(Math.random()*10000);
+ var dogData=JSON.stringify({type:"dog",name:dogName});
+ var dogURI='https://api.usergrid.com/yourorgname/sandbox/dogs'
+ it('should POST to a URI',function(done){
+ Ajax.post(dogURI, dogData).then(function(err, data){
+ assert(!err, err);
+ done();
+ })
+ })
+ it('should GET a URI',function(done){
+ Ajax.get(dogURI+'/'+dogName).then(function(err, data){
+ assert(!err, err);
+ done();
+ })
+ })
+ it('should PUT to a URI',function(done){
+ Ajax.put(dogURI+'/'+dogName, {"favorite":true}).then(function(err, data){
+ assert(!err, err);
+ done();
+ })
+ })
+ it('should DELETE a URI',function(done){
+ Ajax.delete(dogURI+'/'+dogName, dogData).then(function(err, data){
+ assert(!err, err);
+ done();
+ })
+ })
+});
+describe('UsergridError', function() {
+ var errorResponse={
+ "error":"service_resource_not_found",
+ "timestamp":1392067967144,
+ "duration":0,
+ "exception":"org.usergrid.services.exceptions.ServiceResourceNotFoundException",
+ "error_description":"Service resource not found"
+ };
+ it('should unmarshal a response from Usergrid into a proper Javascript error',function(done){
+ var error = UsergridError.fromResponse(errorResponse);
+ assert(error.name===errorResponse.error, "Error name not set correctly");
+ assert(error.message===errorResponse.error_description, "Error message not set correctly");
+ done();
+ });
+});
+describe('Usergrid', function(){
+ describe('SDK Version', function(){
+ it('should contain a minimum SDK version',function(){
+ var parts=Usergrid.VERSION.split('.').map(function(i){return i.replace(/^0+/,'')}).map(function(i){return parseInt(i)});
+
+ assert(parts[1]>=10, "expected minor version >=10");
+ assert(parts[1]>10||parts[2]>=8, "expected minimum version >=8");
+ });
+ });
+ describe('Usergrid Request/Response', function() {
+ var dogName="dog"+Math.floor(Math.random()*10000);
+ var dogData=JSON.stringify({type:"dog",name:dogName});
+ var dogURI='https://api.usergrid.com/yourorgname/sandbox/dogs'
+ it('should POST to a URI',function(done){
+ var req=new Usergrid.Request("POST", dogURI, {}, dogData, function(err, response){
+ console.error(err, response);
+ assert(!err, err);
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ done();
+ })
+ })
+ it('should GET a URI',function(done){
+ var req=new Usergrid.Request("GET", dogURI+'/'+dogName, {}, null, function(err, response){
+ assert(!err, err);
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ done();
+ })
+ })
+ it('should GET an array of entity data from the Usergrid.Response object',function(done){
+ var req=new Usergrid.Request("GET", dogURI, {}, null, function(err, response){
+ assert(!err, err);
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ var entities=response.getEntities();
+ assert(entities && entities.length, "Nothing was returned")
+ done();
+ })
+ })
+ it('should GET entity data from the Usergrid.Response object',function(done){
+ var req=new Usergrid.Request("GET", dogURI+'/'+dogName, {}, null, function(err, response){
+ var entity=response.getEntity();
+ assert(!err, err);
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ assert(entity, "Nothing was returned")
+ done();
+ })
+ })
+ it('should PUT to a URI',function(done){
+ var req=new Usergrid.Request("PUT", dogURI+'/'+dogName, {}, {favorite:true}, function(err, response){
+ assert(!err, err);
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ done();
+ })
+ })
+ it('should DELETE a URI',function(done){
+ var req=new Usergrid.Request("DELETE", dogURI+'/'+dogName, {}, null, function(err, response){
+ assert(!err, err);
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ done();
+ })
+ })
+ it('should NOT allow an invalid method',function(done){
+ try{
+ var req=new Usergrid.Request("INVALID", dogURI+'/'+dogName, {}, null, function(err, response){
+ assert(true, "Should have thrown an UsergridInvalidHTTPMethodError");
+ done();
+ })
+ }catch(e){
+ assert(e instanceof UsergridInvalidHTTPMethodError, "Error is not and instance of UsergridInvalidHTTPMethodError");
+ done()
+ }
+ })
+ it('should NOT allow an invalid URI',function(done){
+ try{
+ var req=new Usergrid.Request("GET", "://apigee.com", {}, null, function(err, response){
+ assert(true, "Should have thrown an UsergridInvalidURIError");
+ done();
+ })
+ }catch(e){
+ assert(e instanceof UsergridInvalidURIError, "Error is not and instance of UsergridInvalidURIError");
+ done()
+ }
+ })
+ it('should return a UsergridError object on an invalid URI',function(done){
+ var req=new Usergrid.Request("GET", dogURI+'/'+dogName+'zzzzz', {}, null, function(err, response){
+ assert(err, "Should have returned an error");
+ assert(response instanceof Usergrid.Response, "Response is not and instance of Usergrid.Response");
+ assert(err instanceof UsergridError, "Error is not and instance of UsergridError");
+ done();
+ })
+ })
+ });
+ describe('Usergrid Client', function() {
+ var client = getClient();
+ describe('Usergrid CRUD request', function() {
+ before(function(done) {
+ this.timeout(10000);
+ //Make sure our dog doesn't already exist
+ client.request({
+ method: 'DELETE',
+ endpoint: 'users/fred'
+ }, function(err, data) {
+ done();
+ });
+ });
+ var options = {
+ method: 'GET',
+ endpoint: 'users'
+ };
+ it('should persist default query parameters', function(done) {
+ //create new client with default params
+ var client=new Usergrid.Client({
+ orgName: 'yourorgname',
+ appName: 'sandbox',
+ logging: false, //optional - turn on logging, off by default
+ buildCurl: true, //optional - turn on curl commands, off by default
+ qs:{
+ test1:'test1',
+ test2:'test2'
+ }
+ });
+ var default_qs=client.getObject('default_qs');
+ assert(default_qs.test1==='test1', "the default query parameters were not persisted");
+ assert(default_qs.test2==='test2', "the default query parameters were not persisted");
+ client.request({
+ method: 'GET',
+ endpoint: 'users'
+ }, function(err, data) {
+ assert(data.params.test2[0]==='test2', "the default query parameters were not sent to the backend");
+ assert(data.params.test1[0]==='test1', "the default query parameters were not sent to the backend");
+ done();
+ });
+ });
+ it('should CREATE a new user', function(done) {
+ client.request({
+ method: 'POST',
+ endpoint: 'users',
+ body: {
+ username: 'fred',
+ password: 'secret'
+ }
+ }, function(err, data) {
+ usergridTestHarness(err, data, done, [
+ function(err, data) {
+ assert(!err)
+ }
+ ]);
+ });
+ });
+ it('should RETRIEVE an existing user', function(done) {
+ client.request({
+ method: 'GET',
+ endpoint: 'users/fred',
+ body: {}
+ }, function(err, data) {
+ usergridTestHarness(err, data, done, [
+
+ function(err, data) {
+ assert(true)
+ }
+ ]);
+ });
+ });
+ it('should UPDATE an existing user', function(done) {
+ client.request({
+ method: 'PUT',
+ endpoint: 'users/fred',
+ body: {
+ newkey: 'newvalue'
+ }
+ }, function(err, data) {
+ usergridTestHarness(err, data, done, [
+
+ function(err, data) {
+ assert(true)
+ }
+ ]);
+ });
+ });
+ it('should DELETE the user from the database', function(done) {
+ client.request({
+ method: 'DELETE',
+ endpoint: 'users/fred'
+ }, function(err, data) {
+ usergridTestHarness(err, data, done, [
+
+ function(err, data) {
+ assert(true)
+ }
+ ]);
+ });
+ });
+ });
+ describe('Usergrid REST', function() {
+ it('should return a list of users', function(done) {
+ client.request({
+ method: 'GET',
+ endpoint: 'users'
+ }, function(err, data) {
+ usergridTestHarness(err, data, done, [
+ function(err, data) {
+ assert(data.entities.length>=0, "Request should return at least one user");
+ }
+ ]);
+ });
+ });
+ it('should return no entities when an endpoint does not exist', function(done) {
+ client.request({
+ method: 'GET',
+ endpoint: 'nonexistantendpoint'
+ }, function(err, data) {
+ usergridTestHarness(err, data, done, [
+
+ function(err, data) {
+ assert(data.entities.length===0, "Request should return no entities");
+ }
+ ]);
+ });
+ });
+ });
+ describe('Usergrid convenience methods', function(){
+ before(function(){ client.logout();});
+ it('createEntity',function(done){
+ client.createEntity({type:'dog',name:'createEntityTestDog'}, function(err, response, dog){
+ console.warn(err, response, dog);
+ assert(!err, "createEntity returned an error")
+ assert(dog, "createEntity did not return a dog")
+ assert(dog.get("name")==='createEntityTestDog', "The dog's name is not 'createEntityTestDog'")
+ done();
+ })
+ })
+ it('createEntity - existing entity',function(done){
+ client.createEntity({type:'dog',name:'createEntityTestDog'}, function(err, response, dog){
+ try{
+ assert(err, "createEntity should return an error")
+ }catch(e){
+ assert(true, "trying to create an entity that already exists throws an error");
+ }finally{
+ done();
+ }
+ });
+ })
+ var testGroup;
+ it('createGroup',function(done){
+ client.createGroup({path:'dogLovers'},function(err, response, group){
+ try{
+ assert(!err, "createGroup returned an error")
+ }catch(e){
+ assert(true, "trying to create a group that already exists throws an error");
+ }finally{
+ done();
+ }
+ /*assert(!err, "createGroup returned an error: "+err);
+ assert(group, "createGroup did not return a group");
+ assert(group instanceof Usergrid.Group, "createGroup did not return a Usergrid.Group");
+ testGroup=group;
+ done();*/
+ })
+ done();
+ })
+ it('buildAssetURL',function(done){
+ var assetURL='https://api.usergrid.com/yourorgname/sandbox/assets/00000000-0000-0000-000000000000/data';
+ assert(assetURL===client.buildAssetURL('00000000-0000-0000-000000000000'), "buildAssetURL doesn't work")
+ done();
+ })
+ var dogEntity;
+ it('getEntity',function(done){
+ client.getEntity({type:'dog',name:'createEntityTestDog'}, function(err, response, dog){
+ assert(!err, "createEntity returned an error")
+ assert(dog, "createEntity returned a dog")
+ assert(dog.get("uuid")!==null, "The dog's UUID was not returned")
+ dogEntity=dog;
+ done();
+ })
+ })
+ it('restoreEntity',function(done){
+ var serializedDog=dogEntity.serialize();
+ var dog=client.restoreEntity(serializedDog);
+ assert(dog, "restoreEntity did not return a dog")
+ assert(dog.get("uuid")===dogEntity.get("uuid"), "The dog's UUID was not the same as the serialized dog")
+ assert(dog.get("type")===dogEntity.get("type"), "The dog's type was not the same as the serialized dog")
+ assert(dog.get("name")===dogEntity.get("name"), "The dog's name was not the same as the serialized dog")
+
+ done();
+ })
+ var dogCollection;
+ it('createCollection',function(done){
+ client.createCollection({type:'dogs'},function(err, response, dogs){
+ assert(!err, "createCollection returned an error");
+ assert(dogs, "createCollection did not return a dogs collection");
+ dogCollection=dogs;
+ done();
+ })
+ })
+ it('restoreCollection',function(done){
+ var serializedDogs=dogCollection.serialize();
+ var dogs=client.restoreCollection(serializedDogs);
+ console.warn('restoreCollection',dogs, dogCollection);
+ assert(dogs._type===dogCollection._type, "The dog collection type was not the same as the serialized dog collection")
+ assert(dogs._qs==dogCollection._qs, "The query strings do not match")
+ assert(dogs._list.length===dogCollection._list.length, "The collections have a different number of entities")
+ done();
+ })
+ var activityUser;
+ before(function(done){
+ activityUser=new Usergrid.Entity({client:client,data:{"type":"user",'username':"testActivityUser"}});
+ console.warn(activityUser);
+ activityUser.fetch(function(err, data){
+ console.warn(err, data, activityUser);
+ if(err){
+ activityUser.save(function(err, data){
+ activityUser.set(data);
+ done();
+ });
+ }else{
+ activityUser.set(data);
+ done();
+ }
+ })
+ })
+ it('createUserActivity',function(done){
+ var options = {
+ "actor" : {
+ "displayName" :"Test Activity User",
+ "uuid" : activityUser.get("uuid"),
+ "username" : "testActivityUser",
+ "email" : "usergrid@apigee.com",
+ "image" : {
+ "height" : 80,
+ "url" : "http://placekitten.com/80/80",
+ "width" : 80
+ }
+ },
+ "verb" : "post",
+ "content" : "test post for createUserActivity",
+ "lat" : 48.856614,
+ "lon" : 2.352222
+ };
+ client.createUserActivity("testActivityUser", options, function(err, activity){
+ assert(!err, "createUserActivity returned an error");
+ assert(activity, "createUserActivity returned no activity object")
+ done();
+ })
+ })
+ it('createUserActivityWithEntity',function(done){
+ client.createUserActivityWithEntity(activityUser, "Another test activity with createUserActivityWithEntity", function(err, activity){
+ assert(!err, "createUserActivityWithEntity returned an error "+err);
+ assert(activity, "createUserActivityWithEntity returned no activity object")
+ done();
+ })
+ })
+ it('getFeedForUser',function(done){
+ client.getFeedForUser('testActivityUser', function(err, data, items){
+ assert(!err, "getFeedForUser returned an error");
+ assert(data, "getFeedForUser returned no data object")
+ assert(items, "getFeedForUser returned no items array")
+ done();
+ })
+ })
+ var testProperty="____test_item"+Math.floor(Math.random()*10000),
+ testPropertyValue="test"+Math.floor(Math.random()*10000),
+ testPropertyObjectValue={test:testPropertyValue};
+ it('set',function(done){
+ client.set(testProperty, testPropertyValue);
+ done();
+ })
+ it('get',function(done){
+ var retrievedValue=client.get(testProperty);
+ assert(retrievedValue===testPropertyValue, "Get is not working properly");
+ done();
+ })
+ it('setObject',function(done){
+ client.set(testProperty, testPropertyObjectValue);
+ done();
+ })
+ it('getObject',function(done){
+ var retrievedValue=client.get(testProperty);
+ assert(retrievedValue==testPropertyObjectValue, "getObject is not working properly");
+ done();
+ })
+ /*it('setToken',function(done){
+ client.setToken("dummytoken");
+ done();
+ })
+ it('getToken',function(done){
+ assert(client.getToken()==="dummytoken");
+ done();
+ })*/
+ it('remove property',function(done){
+ client.set(testProperty);
+ assert(client.get(testProperty)===null);
+ done();
+ })
+ var newUser;
+ it('signup',function(done){
+ client.signup("newUsergridUser", "Us3rgr1d15Aw3s0m3!", "usergrid@apigee.com", "Another Satisfied Developer", function(err, user){
+ assert(!err, "signup returned an error");
+ assert(user, "signup returned no user object")
+ newUser=user;
+ done();
+ })
+ })
+ it('login',function(done){
+ client.login("newUsergridUser", "Us3rgr1d15Aw3s0m3!", function(err, data, user){
+ assert(!err, "login returned an error");
+ assert(user, "login returned no user object")
+ done();
+ })
+ })
+ /*it('reAuthenticateLite',function(done){
+ client.reAuthenticateLite(function(err){
+ assert(!err, "reAuthenticateLite returned an error");
+ done();
+ })
+ })*/
+ /*it('reAuthenticate',function(done){
+ client.reAuthenticate("usergrid@apigee.com", function(err, data, user, organizations, applications){
+ assert(!err, "reAuthenticate returned an error");
+ done();
+ })
+ })*/
+ /*it('loginFacebook',function(done){
+ assert(true, "Not sure how feasible it is to test this with Mocha")
+ done();
+ })*/
+ it('isLoggedIn',function(done){
+ assert(client.isLoggedIn()===true, "isLoggedIn is not detecting that we have logged in.")
+ done();
+ })
+ it('getLoggedInUser',function(done){
+ setTimeout(function(){
+ client.getLoggedInUser(function(err, data, user){
+ assert(!err, "getLoggedInUser returned an error");
+ assert(user, "getLoggedInUser returned no user object")
+ done();
+ })
+ },1000);
+ })
+ before(function(done){
+ //please enjoy this musical interlude.
+ setTimeout(function(){done()},1000);
+ })
+ it('logout',function(done){
+ client.logout();
+ assert(null===client.getToken(), "we logged out, but the token still remains.")
+ done();
+ })
+ it('getLoggedInUser',function(done){
+ client.getLoggedInUser(function(err, data, user){
+ assert(err, "getLoggedInUser should return an error after logout");
+ assert(user, "getLoggedInUser should not return data after logout")
+ done();
+ })
+ })
+ it('isLoggedIn',function(done){
+ assert(client.isLoggedIn()===false, "isLoggedIn still returns true after logout.")
+ done();
+ })
+ after(function (done) {
+ client.request({
+ method: 'DELETE',
+ endpoint: 'users/newUsergridUser'
+ }, function (err, data) {
+ done();
+ });
+
+ })
+ it('buildCurlCall',function(done){
+ done();
+ })
+ it('getDisplayImage',function(done){
+ done();
+ })
+ after(function(done){
+ dogEntity.destroy();
+ //dogCollection.destroy();
+ //testGroup.destroy();
+ done();
+ })
+ });
+ });
+ describe('Usergrid Entity', function() {
+ var client = getClient();
+ var dog;
+ before(function(done) {
+ //Make sure our dog doesn't already exist
+ client.request({
+ method: 'DELETE',
+ endpoint: 'dogs/Rocky'
+ }, function(err, data) {
+ assert(true);
+ done();
+ });
+ });
+ it('should CREATE a new dog', function(done) {
+ var options = {
+ type: 'dogs',
+ name: 'Rocky'
+ }
+ dog=new Usergrid.Entity({client:client,data:options});
+ dog.save(function(err, entity) {
+ assert(!err, "dog not created");
+ done();
+ });
+ });
+ it('should RETRIEVE the dog', function(done) {
+ if (!dog) {
+ assert(false, "dog not created");
+ done();
+ return;
+ }
+ //once the dog is created, you can set single properties:
+ dog.fetch(function(err) {
+ assert(!err, "dog not fetched");
+ done();
+ });
+ });
+ it('should UPDATE the dog', function(done) {
+ if (!dog) {
+ assert(false, "dog not created");
+ done();
+ return;
+ }
+ //once the dog is created, you can set single properties:
+ dog.set('breed', 'Dinosaur');
+
+ //the set function can also take a JSON object:
+ var data = {
+ master: 'Fred',
+ state: 'hungry'
+ }
+ //set is additive, so previously set properties are not overwritten
+ dog.set(data);
+ //finally, call save on the object to save it back to the database
+ dog.save(function(err) {
+ assert(!err, "dog not saved");
+ done();
+ });
+ });
+ it('should DELETE the dog', function(done) {
+ if (!dog) {
+ assert(false, "dog not created");
+ done();
+ return;
+ }
+ //once the dog is created, you can set single properties:
+ dog.destroy(function(err) {
+ assert(!err, "dog not removed");
+ done();
+ });
+ });
+ });
+ describe('Usergrid Collections', function() {
+ var client = getClient();
+ var dog, dogs = {};
+
+ before(function(done) {
+ //Make sure our dog doesn't already exist
+ var options = {
+ type: 'dogs',
+ qs: {
+ limit: 50
+ } //limit statement set to 50
+ }
+
+ client.createCollection(options, function(err, response, dogs) {
+ if (!err) {
+ assert(!err, "could not retrieve list of dogs: " + dogs.error_description);
+ //we got 50 dogs, now display the Entities:
+ //do doggy cleanup
+ //if (dogs.hasNextEntity()) {
+ while (dogs.hasNextEntity()) {
+ //get a reference to the dog
+ var dog = dogs.getNextEntity();
+ console.warn(dog);
+ //notice('removing dog ' + dogname + ' from database');
+ if(dog === null) continue;
+ dog.destroy(function(err, data) {
+ assert(!err, dog.get('name') + " not removed: " + data.error_description);
+ if (!dogs.hasNextEntity()) {
+ done();
+ }
+ });
+ }
+ //} else {
+ done();
+ //}
+ }
+ });
+ });
+ it('should CREATE a new dogs collection', function(done) {
+ var options = {
+ client:client,
+ type: 'dogs',
+ qs: {
+ ql: 'order by index'
+ }
+ }
+ dogs=new Usergrid.Collection(options);
+ assert(dogs!==undefined&&dogs!==null, "could not create dogs collection");
+ done();
+ });
+ it('should CREATE dogs in the collection', function(done) {
+ this.timeout(10000);
+ var totalDogs = 30;
+ Array.apply(0, Array(totalDogs)).forEach(function(x, y) {
+ var dogNum = y + 1;
+ var options = {
+ type: 'dogs',
+ name: 'dog' + dogNum,
+ index: y
+ }
+ dogs.addEntity(options, function(err, dog) {
+ assert(!err, "dog not created");
+ if (dogNum === totalDogs) {
+ done();
+ }
+ });
+ })
+ });
+ it('should RETRIEVE dogs from the collection', function(done) {
+ while (dogs.hasNextEntity()) {
+ //get a reference to the dog
+ dog = dogs.getNextEntity();
+ }
+ if (done) done();
+ });
+ it('should RETRIEVE the next page of dogs from the collection', function(done) {
+ if (dogs.hasNextPage()) {
+ dogs.getNextPage(function(err) {
+ loop(done);
+ });
+ } else {
+ done();
+ }
+ });
+ it('should RETRIEVE the previous page of dogs from the collection', function(done) {
+ if (dogs.hasPreviousPage()) {
+ dogs.getPreviousPage(function(err) {
+ loop(done);
+ });
+ } else {
+ done();
+ }
+ });
+ it('should RETRIEVE an entity by UUID.', function(done) {
+ var uuid=dogs.getFirstEntity().get("uuid")
+ dogs.getEntityByUUID(uuid,function(err, data){
+ assert(!err, "getEntityByUUID returned an error.");
+ assert(uuid==data.get("uuid"), "We didn't get the dog we asked for.");
+ done();
+ })
+ });
+ it('should RETRIEVE the first entity from the collection', function() {
+ assert(dogs.getFirstEntity(), "Could not retrieve the first dog");
+ });
+ it('should RETRIEVE the last entity from the collection', function() {
+ assert(dogs.getLastEntity(), "Could not retrieve the last dog");
+ });
+ it('should reset the paging', function() {
+ dogs.resetPaging();
+ assert(!dogs.hasPreviousPage(), "Could not resetPaging");
+ });
+ it('should reset the entity pointer', function() {
+ dogs.resetEntityPointer();
+ assert(!dogs.hasPrevEntity(), "Could not reset the pointer");
+ assert(dogs.hasNextEntity(), "Dog has no more entities");
+ assert(dogs.getNextEntity(), "Could not retrieve the next dog");
+ });
+ it('should RETRIEVE the next entity from the collection', function() {
+ assert(dogs.hasNextEntity(), "Dog has no more entities");
+ assert(dogs.getNextEntity(), "Could not retrieve the next dog");
+ });
+ it('should RETRIEVE the previous entity from the collection', function() {
+ assert(dogs.getNextEntity(), "Could not retrieve the next dog");
+ assert(dogs.hasPrevEntity(), "Dogs has no previous entities");
+ assert(dogs.getPrevEntity(), "Could not retrieve the previous dog");
+ });
+ it('should DELETE the entities from the collection', function(done) {
+ this.timeout(20000);
+ function remove(){
+ if(dogs.hasNextEntity()){
+ dogs.destroyEntity(dogs.getNextEntity(),function(err, data){
+ assert(!err, "Could not destroy dog.");
+ remove();
+ })
+ }else if(dogs.hasNextPage()){
+ dogs.getNextPage();
+ remove();
+ }else{
+ done();
+ }
+ }
+ remove();
+ });
+ });
+ describe('Usergrid Counters', function() {
+ var client = getClient();
+ var counter;
+ var MINUTE = 1000 * 60;
+ var HOUR = MINUTE * 60;
+ var time = Date.now() - HOUR;
+
+ it('should CREATE a counter', function(done) {
+ counter = new Usergrid.Counter({
+ client: client,
+ data: {
+ category: 'mocha_test',
+ timestamp: time,
+ name: "test",
+ counters: {
+ test: 0,
+ test_counter: 0
+ }
+ }
+ });
+ assert(counter, "Counter not created");
+ done();
+ });
+ it('should save a counter', function(done) {
+ counter.save(function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ it('should reset a counter', function(done) {
+ time += MINUTE * 10
+ counter.set("timestamp", time);
+ counter.reset({
+ name: 'test'
+ }, function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ it("should increment 'test' counter", function(done) {
+ time += MINUTE * 10
+ counter.set("timestamp", time);
+ counter.increment({
+ name: 'test',
+ value: 1
+ }, function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ it("should increment 'test_counter' counter by 4", function(done) {
+ time += MINUTE * 10
+ counter.set("timestamp", time);
+ counter.increment({
+ name: 'test_counter',
+ value: 4
+ }, function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ it("should decrement 'test' counter", function(done) {
+ time += MINUTE * 10
+ counter.set("timestamp", time);
+ counter.decrement({
+ name: 'test',
+ value: 1
+ }, function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ it('should fetch the counter', function(done) {
+ counter.fetch(function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ it('should fetch counter data', function(done) {
+ counter.getData({
+ resolution: 'all',
+ counters: ['test', 'test_counter']
+ }, function(err, data) {
+ assert(!err, data.error_description);
+ done();
+ });
+ });
+ });
+ describe('Usergrid Folders and Assets', function() {
+ var client = getClient();
+ var folder,
+ asset,
+ user,
+ image_type,
+ image_url = 'http://placekitten.com/160/90',
+ // image_url="https://api.usergrid.com/yourorgname/sandbox/assets/a4025e7a-8ab1-11e3-b56c-5d3c6e4ca93f/data",
+ test_image,
+ filesystem,
+ file_url,
+ filename = "kitten.jpg",
+ foldername = "kittens",
+ folderpath = '/test/' + Math.round(10000 * Math.random()),
+ filepath = [folderpath, foldername, filename].join('/');
+ before(function(done) {
+ var req = new XMLHttpRequest();
+ req.open('GET', image_url, true);
+ req.responseType = 'blob';
+ req.onload = function() {
+ test_image = req.response;
+ image_type = req.getResponseHeader('Content-Type');
+ done();
+ }
+ req.onerror = function(err) {
+ console.error(err);
+ done();
+ };
+ req.send(null);
+ });
+ before(function(done) {
+ this.timeout(10000);
+ client.request({
+ method: 'GET',
+ endpoint: 'Assets'
+ }, function(err, data) {
+ var assets = [];
+ if(data && data.entities && data.entities.length){
+ assets.concat(data.entities.filter(function(asset) {
+ return asset.name === filename
+ }));
+ }
+ if (assets.length) {
+ assets.forEach(function(asset) {
+ client.request({
+ method: 'DELETE',
+ endpoint: 'assets/' + asset.uuid
+ });
+ });
+ done();
+ } else {
+ done();
+ }
+ });
+ });
+ before(function(done) {
+ this.timeout(10000);
+ client.request({
+ method: 'GET',
+ endpoint: 'folders'
+ }, function(err, data) {
+ var folders = [];
+ if(data && data.entities && data.entities.length){
+ folders.concat(data.entities.filter(function(folder) {
+ return folder.name === foldername
+ }));
+ }
+ if (folders.length) {
+ folders.forEach(function(folder) {
+ client.request({
+ method: 'DELETE',
+ endpoint: 'folders/' + folder.uuid
+ });
+ });
+ done();
+ } else {
+ done();
+ }
+ });
+ });
+ before(function(done) {
+ this.timeout(10000);
+ user = new Usergrid.Entity({
+ client: client,
+ data: {
+ type: 'users',
+ username: 'assetuser'
+ }
+ });
+ user.fetch(function(err, data) {
+ if (err) {
+ user.save(function() {
+ done();
+ })
+ } else {
+ done();
+ }
+ })
+ });
+ it('should CREATE a folder', function(done) {
+ folder = new Usergrid.Folder({
+ client: client,
+ data: {
+ name: foldername,
+ owner: user.get("uuid"),
+ path: folderpath
+ }
+ }, function(err, response, folder) {
+ assert(!err, err);
+ done();
+ });
+ });
+ it('should CREATE an asset', function(done) {
+ asset = new Usergrid.Asset({
+ client: client,
+ data: {
+ name: filename,
+ owner: user.get("uuid"),
+ path: filepath
+ }
+ }, function(err, response, asset) {
+ if(err){
+ assert(false, err);
+ }
+ done();
+ });
+ });
+ it('should RETRIEVE an asset', function(done) {
+ asset.fetch(function(err, response, entity){
+ if(err){
+ assert(false, err);
+ }else{
+ asset=entity;
+ }
+ done();
+ })
+ });
+ it('should upload asset data', function(done) {
+ this.timeout(5000);
+ asset.upload(test_image, function(err, response, asset) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ done();
+ });
+ });
+ it('should retrieve asset data', function(done) {
+ this.timeout(5000);
+ asset.download(function(err, response, asset) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ assert(asset.get('content-type') == test_image.type, "MIME types don't match");
+ assert(asset.get('size') == test_image.size, "sizes don't match");
+ done();
+ });
+ });
+ it('should add the asset to a folder', function(done) {
+ folder.addAsset({
+ asset: asset
+ }, function(err, data) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ done();
+ })
+ });
+ it('should list the assets from a folder', function(done) {
+ folder.getAssets(function(err, assets) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ done();
+ })
+ });
+ it('should remove the asset from a folder', function(done) {
+ folder.removeAsset({
+ asset: asset
+ }, function(err, data) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ done();
+ })
+ });
+ after(function(done) {
+ asset.destroy(function(err, data) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ done();
+ })
+ });
+ after(function(done) {
+ folder.destroy(function(err, data) {
+ if(err){
+ assert(false, err.error_description);
+ }
+ done();
+ })
+ });
+ });
+});
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/tests/qunit/apigee_test.html
----------------------------------------------------------------------
diff --git a/tests/qunit/apigee_test.html b/tests/qunit/apigee_test.html
new file mode 100644
index 0000000..2dae960
--- /dev/null
+++ b/tests/qunit/apigee_test.html
@@ -0,0 +1,31 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>QUnit Example</title>
+ <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.12.0.css">
+</head>
+<body>
+ <div id="qunit"></div>
+ <div id="qunit-fixture"></div>
+ <script src="http://code.jquery.com/qunit/qunit-1.12.0.js"></script>
+ <script src="tests.js"></script>
+</body>
+</html>
http://git-wip-us.apache.org/repos/asf/usergrid-javascript/blob/94020d26/tests/qunit/tests.js
----------------------------------------------------------------------
diff --git a/tests/qunit/tests.js b/tests/qunit/tests.js
new file mode 100644
index 0000000..1d58b00
--- /dev/null
+++ b/tests/qunit/tests.js
@@ -0,0 +1,20 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+test( "hello test", function() {
+ ok( 1 == "1", "Passed!" );
+});