You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2016/01/20 18:05:59 UTC

[33/50] [abbrv] tez git commit: TEZ-3023. Tez UI 2: Abstract adapter and route (sree)

TEZ-3023. Tez UI 2: Abstract adapter and route (sree)


Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/bfc4aeb9
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/bfc4aeb9
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/bfc4aeb9

Branch: refs/heads/TEZ-2980
Commit: bfc4aeb9ea4b510e0f427e3af48a703d98d492a2
Parents: 025bbb7
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Mon Jan 4 22:28:44 2016 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Wed Jan 20 22:26:21 2016 +0530

----------------------------------------------------------------------
 TEZ-2980-CHANGES.txt                            |   1 +
 .../src/main/webapp/app/adapters/abstract.js    |  58 ++++++
 .../main/webapp/app/errors/unlinked-promise.js  |  34 ++++
 tez-ui2/src/main/webapp/app/routes/abstract.js  |  68 +++++++
 .../webapp/tests/unit/adapters/abstract-test.js |  82 ++++++++
 .../webapp/tests/unit/routes/abstract-test.js   | 186 ++++++++++++++++++-
 6 files changed, 428 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/bfc4aeb9/TEZ-2980-CHANGES.txt
----------------------------------------------------------------------
diff --git a/TEZ-2980-CHANGES.txt b/TEZ-2980-CHANGES.txt
index 77a8d29..0eb31bf 100644
--- a/TEZ-2980-CHANGES.txt
+++ b/TEZ-2980-CHANGES.txt
@@ -8,3 +8,4 @@ ALL CHANGES:
   TEZ-3020. Tez UI 2: Add entity blueprint
   TEZ-2985. Tez UI 2: Create loader and entity classes
   TEZ-3021. Tez UI 2: Add env service & initializer
+  TEZ-3023. Tez UI 2: Abstract adapter and route

http://git-wip-us.apache.org/repos/asf/tez/blob/bfc4aeb9/tez-ui2/src/main/webapp/app/adapters/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/abstract.js b/tez-ui2/src/main/webapp/app/adapters/abstract.js
new file mode 100644
index 0000000..b412a46
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/adapters/abstract.js
@@ -0,0 +1,58 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+import LoaderAdapter from './loader';
+
+export default LoaderAdapter.extend({
+  serverName: null, //Must be set by inheriting classes
+
+  host: Ember.computed("serverName", function () {
+    var serverName = this.get("serverName");
+    return this.get(`hosts.${serverName}`);
+  }),
+  namespace: Ember.computed("serverName", function () {
+    var serverName = this.get("serverName"),
+        env = this.get("env");
+    return env.getAppConfig(`namespaces.webService.${serverName}`);
+  }),
+  pathTypeHash: Ember.computed("serverName", function () {
+    var serverName = this.get("serverName"),
+        env = this.get("env");
+
+    return env.getAppConfig(`paths.${serverName}`);
+  }),
+
+  ajaxOptions: function(url, method, options) {
+    options = options || {};
+    options.crossDomain = true;
+    options.xhrFields = {
+      withCredentials: true
+    };
+    options.targetServer = this.get('serverName');
+    return this._super(url, method, options);
+  },
+
+  pathForType: function(type) {
+    var serverName = this.get("serverName"),
+        path = this.get("pathTypeHash")[type];
+    Ember.assert(`Path not found for type:${type} to server:${serverName}`, path);
+    return path;
+  },
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/bfc4aeb9/tez-ui2/src/main/webapp/app/errors/unlinked-promise.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/errors/unlinked-promise.js b/tez-ui2/src/main/webapp/app/errors/unlinked-promise.js
new file mode 100644
index 0000000..770b095
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/errors/unlinked-promise.js
@@ -0,0 +1,34 @@
+/**
+ * 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.
+ */
+
+import Ember from 'ember';
+
+let UnlinkedPromise = function (errors, message = 'Promise chain was unlinked.') {
+  Ember.Error.call(this, message);
+
+  this.errors = errors || [
+    {
+      title: 'Unlinked promise chain.',
+      detail: message
+    }
+  ];
+};
+
+UnlinkedPromise.prototype = Object.create(Ember.Error.prototype);
+
+export default UnlinkedPromise;

http://git-wip-us.apache.org/repos/asf/tez/blob/bfc4aeb9/tez-ui2/src/main/webapp/app/routes/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/routes/abstract.js b/tez-ui2/src/main/webapp/app/routes/abstract.js
index a4d2bb5..d0f3c3d 100644
--- a/tez-ui2/src/main/webapp/app/routes/abstract.js
+++ b/tez-ui2/src/main/webapp/app/routes/abstract.js
@@ -17,10 +17,18 @@
  */
 
 import Ember from 'ember';
+import LoaderService from '../services/loader';
+import UnlinkedPromise from '../errors/unlinked-promise';
 
 export default Ember.Route.extend({
   title: null, // Must be set by inheriting class
 
+  isLoading: false,
+  currentPromiseId: null,
+  loadedValue: null,
+
+  queryParams: null,
+
   setDocTitle: function () {
     Ember.$(document).attr('title', this.get('title'));
   },
@@ -28,5 +36,65 @@ export default Ember.Route.extend({
   setupController: function (controller, model) {
     this._super(controller, model);
     this.setDocTitle();
+  },
+
+  beforeModel: function (transition) {
+    this.set('queryParams', transition.queryParams);
+    return this._super(transition);
+  },
+
+  checkAndCall: function (id, functionName, value) {
+    if(id === this.get("currentPromiseId")) {
+      return this[functionName](value);
+    }
+    else {
+      throw new UnlinkedPromise();
+    }
+  },
+
+  loadData: Ember.observer("queryParams", function () {
+    var promiseId = Math.random();
+
+    this.set('currentPromiseId', promiseId);
+
+    return Ember.RSVP.resolve().
+      then(this.checkAndCall.bind(this, promiseId, "setLoading")).
+      then(this.checkAndCall.bind(this, promiseId, "beforeLoad")).
+      then(this.checkAndCall.bind(this, promiseId, "load")).
+      then(this.checkAndCall.bind(this, promiseId, "afterLoad")).
+      then(this.checkAndCall.bind(this, promiseId, "setValue"));
+  }),
+
+  setLoading: function () {
+    this.set('isLoading', true);
+  },
+  beforeLoad: function (value) {
+    return value;
+  },
+  load: function (value) {
+    return value;
+  },
+  afterLoad: function (value) {
+    return value;
+  },
+  setValue: function (value) {
+    this.set('loadedValue', value);
+    this.set('isLoading', false);
+  },
+
+  _setControllerModel: Ember.observer("_controller", "loadedValue", function () {
+    var controller = this.get("controller");
+    if(controller) {
+      controller.set("model", this.get("loadedValue"));
+    }
+  }),
+
+  setLoader: function (nameSpace) {
+    this.set("loader", LoaderService.create({
+      nameSpace: nameSpace,
+      store: this.get("store"),
+      container: this.get("container")
+    }));
   }
+
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/bfc4aeb9/tez-ui2/src/main/webapp/tests/unit/adapters/abstract-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/adapters/abstract-test.js b/tez-ui2/src/main/webapp/tests/unit/adapters/abstract-test.js
new file mode 100644
index 0000000..bc00679
--- /dev/null
+++ b/tez-ui2/src/main/webapp/tests/unit/adapters/abstract-test.js
@@ -0,0 +1,82 @@
+/**
+ * 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.
+ */
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('adapter:abstract', 'Unit | Adapter | abstract', {
+  // Specify the other units that are required for this test.
+  // needs: ['serializer:foo']
+});
+
+test('Basic creation test', function(assert) {
+  let adapter = this.subject();
+
+  assert.ok(adapter);
+  assert.equal(adapter.serverName, null);
+
+  assert.ok(adapter.host);
+  assert.ok(adapter.namespace);
+  assert.ok(adapter.pathTypeHash);
+
+  assert.ok(adapter.ajaxOptions);
+  assert.ok(adapter.pathForType);
+});
+
+test('ajaxOptions test', function(assert) {
+  let adapter = this.subject(),
+      testUrl = "foo.bar",
+      testMethod = "tm",
+      testOptions = {
+        a: 1
+      },
+      testServer = "ts",
+
+      result;
+
+  // Without options
+  adapter.serverName = testServer;
+  result = adapter.ajaxOptions(testUrl, testMethod);
+  assert.ok(result);
+  assert.ok(result.crossDomain);
+  assert.ok(result.xhrFields.withCredentials);
+  assert.equal(result.targetServer, testServer);
+
+  // Without options
+  adapter.serverName = testServer;
+  result = adapter.ajaxOptions(testUrl, testMethod, testOptions);
+  assert.ok(result);
+  assert.ok(result.crossDomain);
+  assert.ok(result.xhrFields.withCredentials);
+  assert.equal(result.targetServer, testServer);
+  assert.equal(result.a, testOptions.a);
+});
+
+test('pathForType test', function(assert) {
+  let adapter = this.subject(),
+      testHash = {
+        typ: "type"
+      };
+
+  assert.expect(2);
+
+  adapter.pathTypeHash = testHash;
+  assert.equal(adapter.pathForType("typ"), testHash.typ);
+  assert.throws(function () {
+    adapter.pathForType("noType");
+  });
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/bfc4aeb9/tez-ui2/src/main/webapp/tests/unit/routes/abstract-test.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/tests/unit/routes/abstract-test.js b/tez-ui2/src/main/webapp/tests/unit/routes/abstract-test.js
index e11183e..9513b91 100644
--- a/tez-ui2/src/main/webapp/tests/unit/routes/abstract-test.js
+++ b/tez-ui2/src/main/webapp/tests/unit/routes/abstract-test.js
@@ -16,6 +16,10 @@
  * limitations under the License.
  */
 
+import Ember from 'ember';
+
+import UnlinkedPromise from '../../../errors/unlinked-promise';
+
 import { moduleFor, test } from 'ember-qunit';
 
 moduleFor('route:abstract', 'Unit | Route | abstract', {
@@ -23,7 +27,187 @@ moduleFor('route:abstract', 'Unit | Route | abstract', {
   // needs: ['controller:foo']
 });
 
-test('Basic test for existence', function(assert) {
+test('Basic creation test', function(assert) {
   let route = this.subject();
+
   assert.ok(route);
+  assert.ok(route.setDocTitle);
+  assert.ok(route.setupController);
+  assert.ok(route.beforeModel);
+
+  assert.ok(route.checkAndCall);
+
+  assert.ok(route.setLoading);
+  assert.ok(route.loadData);
+  assert.ok(route.beforeLoad);
+  assert.ok(route.load);
+  assert.ok(route.afterLoad);
+  assert.ok(route.setValue);
+
+  assert.ok(route._setControllerModel);
+  assert.ok(route.setLoader);
+});
+
+test('beforeModel test', function(assert) {
+  let route = this.subject(),
+      testQueryParams = {};
+
+  route.loadData = Ember.K;
+  assert.notOk(route.queryParams.queryParams);
+  route.beforeModel({queryParams: testQueryParams});
+  assert.equal(route.queryParams, testQueryParams);
+});
+
+test('checkAndCall test', function(assert) {
+  let route = this.subject(),
+      testValue = {};
+
+  assert.expect(2);
+
+  route.testFunction = function (value) {
+    assert.equal(value, testValue, "Call with current id");
+  };
+  route.currentPromiseId = 1;
+
+  route.checkAndCall(1, "testFunction", testValue);
+  assert.throws(function () {
+    route.checkAndCall(2, "testFunction", testValue);
+  });
+});
+
+test('loadData test - Hook sequence check', function(assert) {
+  let route = this.subject();
+
+  // Bind poilyfill
+  Function.prototype.bind = function (context, val1, val2) {
+    var that = this;
+    return function (val) {
+      return that.call(context, val1, val2, val);
+    };
+  };
+
+  assert.expect(4 + 1);
+
+  route.setLoading = function () {
+    return 1;
+  };
+  route.beforeLoad = function (value) {
+    assert.equal(value, 1, "beforeLoad");
+    return ++value;
+  };
+  route.load = function (value) {
+    assert.equal(value, 2, "load");
+    return ++value;
+  };
+  route.afterLoad = function (value) {
+    assert.equal(value, 3, "afterLoad");
+    return ++value;
+  };
+  route.setValue = function (value) {
+    assert.equal(value, 4, "setValue");
+    return ++value;
+  };
+
+  route.loadData().then(function (value) {
+    assert.equal(value, 5, "Value returned by loadData");
+  });
+
+});
+
+test('loadData test - ID change check with exception throw', function(assert) {
+  let route = this.subject();
+
+  // Bind poilyfill
+  Function.prototype.bind = function (context, val1, val2) {
+    var that = this;
+    return function (val) {
+      return that.call(context, val1, val2, val);
+    };
+  };
+
+  assert.expect(2 + 1);
+
+  route.setLoading = function () {
+    return 1;
+  };
+  route.beforeLoad = function (value) {
+    assert.equal(value, 1, "beforeLoad");
+    return ++value;
+  };
+  route.load = function (value) {
+    assert.equal(value, 2, "load");
+
+    route.currentPromiseId = 0;
+
+    return ++value;
+  };
+  route.afterLoad = function (value) {
+    assert.equal(value, 3, "afterLoad");
+    return ++value;
+  };
+  route.setValue = function (value) {
+    assert.equal(value, 4, "setValue");
+    return ++value;
+  };
+
+  route.loadData().then(function () {
+    assert.notOk("Shouldn't be called");
+  }).catch(function (e) {
+    assert.ok(e instanceof UnlinkedPromise, "Exception thrown");
+  });
+});
+
+test('setLoading test', function(assert) {
+  let route = this.subject();
+
+  assert.equal(route.get("isLoading"), false);
+  route.setLoading();
+  assert.equal(route.get("isLoading"), true);
+});
+
+test('beforeLoad load afterLoad test', function(assert) {
+  let route = this.subject(),
+      testVal = {};
+
+  assert.equal(route.beforeLoad(testVal), testVal);
+  assert.equal(route.load(testVal), testVal);
+  assert.equal(route.afterLoad(testVal), testVal);
+});
+
+test('setValue test', function(assert) {
+  let route = this.subject(),
+      testVal = {};
+
+  route.setLoading();
+  assert.equal(route.get("loadedValue"), null);
+  assert.equal(route.get("isLoading"), true);
+  assert.equal(route.setValue(testVal), testVal);
+  assert.equal(route.get("loadedValue"), testVal);
+  assert.equal(route.get("isLoading"), false);
+});
+
+test('_setControllerModel test', function(assert) {
+  let route = this.subject(),
+      testValue = {},
+      testController = Ember.Object.create();
+
+  route.set("loadedValue", testValue);
+  route.set("controller", testController);
+
+  assert.notOk(testController.model);
+  route._setControllerModel();
+  assert.equal(testController.model, testValue, "With controller");
+});
+
+test('setLoader test', function(assert) {
+  let route = this.subject(),
+      testNamespace = "tn",
+      oldLoader = route.get("loader");
+
+  route.setLoader(testNamespace);
+
+  assert.notEqual(route.get("loader"), oldLoader);
+  assert.equal(route.get("loader.nameSpace"), testNamespace);
+  assert.equal(route.get("loader.store"), route.get("store"));
+  assert.equal(route.get("loader.container"), route.get("container"));
 });