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/02/24 23:34:43 UTC
[06/45] 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/a0dd70c1
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/a0dd70c1
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/a0dd70c1
Branch: refs/heads/TEZ-2980
Commit: a0dd70c191228d6ddfb37fe17e4dd3f59a43fd2d
Parents: 1292bf4
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Mon Jan 4 22:28:44 2016 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Thu Feb 25 03:31:59 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/a0dd70c1/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/a0dd70c1/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/a0dd70c1/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/a0dd70c1/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/a0dd70c1/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/a0dd70c1/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"));
});