TEZ-2985. Tez UI 2: Create loader and entity classes (sree)
Project: http://git-wip-us.apache.org/repos/asf/tez/repo Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/6e18c9b9 Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/6e18c9b9 Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/6e18c9b9 Branch: refs/heads/TEZ-2980 Commit: 6e18c9b9414f3a2b56c76ce71a606e8c39dbdbde Parents: 72a1060 Author: Sreenath Somarajapuram <s...@apache.org> Authored: Mon Jan 4 03:25:04 2016 +0530 Committer: Sreenath Somarajapuram <s...@apache.org> Committed: Thu Feb 25 03:31:59 2016 +0530 ---------------------------------------------------------------------- TEZ-2980-CHANGES.txt | 1 + .../src/main/webapp/app/adapters/abstract.js | 54 ---- tez-ui2/src/main/webapp/app/adapters/loader.js | 58 ++++ tez-ui2/src/main/webapp/app/entities/entity.js | 65 ++++- .../src/main/webapp/app/initializers/loader.js | 27 ++ .../src/main/webapp/app/serializers/abstract.js | 26 -- .../src/main/webapp/app/serializers/loader.js | 81 ++++++ tez-ui2/src/main/webapp/app/services/loader.js | 145 ++++++++++ .../webapp/tests/unit/adapters/abstract-test.js | 39 --- .../webapp/tests/unit/adapters/loader-test.js | 137 ++++++++++ .../webapp/tests/unit/entities/entity-test.js | 139 ++++++++++ .../tests/unit/initializers/loader-test.js | 40 +++ .../tests/unit/serializers/abstract-test.js | 31 --- .../tests/unit/serializers/loader-test.js | 193 ++++++++++++++ .../webapp/tests/unit/services/loader-test.js | 267 +++++++++++++++++++ 15 files changed, 1152 insertions(+), 151 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/TEZ-2980-CHANGES.txt ---------------------------------------------------------------------- diff --git a/TEZ-2980-CHANGES.txt b/TEZ-2980-CHANGES.txt index da361d6..4cf5c4a 100644 --- a/TEZ-2980-CHANGES.txt +++ b/TEZ-2980-CHANGES.txt @@ -6,3 +6,4 @@ ALL CHANGES: TEZ-3019. Tez UI 2: Replace BaseURL with Host TEZ-2984. Tez UI 2: Create abstract classes TEZ-3020. Tez UI 2: Add entity blueprint + TEZ-2985. Tez UI 2: Create loader and entity classes http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/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 deleted file mode 100644 index aca0faf..0000000 --- a/tez-ui2/src/main/webapp/app/adapters/abstract.js +++ /dev/null @@ -1,54 +0,0 @@ -/*global more*/ - -/** - * 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 DS from 'ember-data'; - -var MoreString = more.String; - -export default DS.RESTAdapter.extend({ - ajax: function(url, method, hash) { - return this._super(url, method, Ember.$.extend(hash || {}, { - crossDomain: true, - xhrFields: { - withCredentials: true - } - })); - }, - buildURL: function(type, id, record) { - var url = this._super(type, undefined, record); - return MoreString.fmt(url, record); - }, - findQuery: function(store, type, query) { - var record = query.metadata; - delete query.metadata; - - return this.ajax(this.buildURL( - Ember.String.pluralize(type.typeKey), - record.id, - Ember.Object.create(record) - ), - 'GET', - { - data: query - } - ); - } -}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/app/adapters/loader.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/adapters/loader.js b/tez-ui2/src/main/webapp/app/adapters/loader.js new file mode 100644 index 0000000..d4b502c --- /dev/null +++ b/tez-ui2/src/main/webapp/app/adapters/loader.js @@ -0,0 +1,58 @@ +/*global more*/ +/** + * 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 DS from 'ember-data'; + +var MoreString = more.String; + +export default DS.RESTAdapter.extend({ + _isLoader: true, + + buildURL: function(modelName, id, snapshot, requestType, query, params) { + var url = this._super(modelName, id, snapshot, null, query); + return params ? MoreString.fmt(url, params) : url; + }, + + _loaderAjax: function (url, queryParams, nameSpace) { + if (this.sortQueryParams && queryParams) { + queryParams = this.sortQueryParams(queryParams); + } + + // Inject nameSpace + return this.ajax(url, 'GET', { data: queryParams }).then(function (data) { + return { + nameSpace: nameSpace, + data: data + }; + }); + }, + + queryRecord: function(store, type, query) { + var queryParams = query.params, + url = this.buildURL(type.modelName, query.id, null, null, queryParams, query.urlParams); + return this._loaderAjax(url, queryParams, query.nameSpace); + }, + + query: function (store, type, query/*, recordArray*/) { + var queryParams = query.params, + url = this.buildURL(type.modelName, null, null, 'query', queryParams, query.urlParams); + return this._loaderAjax(url, queryParams, query.nameSpace); + } + +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/app/entities/entity.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/entities/entity.js b/tez-ui2/src/main/webapp/app/entities/entity.js index 3d858c8..4d524fe 100644 --- a/tez-ui2/src/main/webapp/app/entities/entity.js +++ b/tez-ui2/src/main/webapp/app/entities/entity.js @@ -1,3 +1,4 @@ +/*global more*/ /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,5 +19,67 @@ import Ember from 'ember'; -export default Ember.ObjectProxy.extend({ +var MoreObject = more.Object; + +export default Ember.Object.extend({ + + loadRelations: function (loader, model) { + var needsPromise = this.loadNeeds(loader, model); + + if(needsPromise) { + return needsPromise.then(function () { + return model; + }); + } + + return model; + }, + + normalizeNeed: function(name, options) { + var attrName = name, + attrType = name, + idKey = options, + lazy = false; + + if(typeof options === 'object') { + attrType = options.type || attrType; + idKey = options.idKey || idKey; + if(options.lazy) { + lazy = true; + } + } + + return { + name: attrName, + type: attrType, + idKey: idKey, + lazy: lazy + }; + }, + + loadNeeds: function (loader, parentModel) { + var needLoaders = [], + that = this, + needs = parentModel.get("needs"); + + if(needs) { + MoreObject.forEach(needs, function (name, options) { + var need = that.normalizeNeed(name, options), + needLoader = loader.queryRecord(need.type, parentModel.get(need.idKey)); + + needLoader.then(function (model) { + parentModel.set(need.name, model); + }); + + if(!need.lazy) { + needLoaders.push(needLoader); + } + }); + } + + if(needLoaders.length) { + return Ember.RSVP.all(needLoaders); + } + }, + }); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/app/initializers/loader.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/initializers/loader.js b/tez-ui2/src/main/webapp/app/initializers/loader.js new file mode 100644 index 0000000..2956d2c --- /dev/null +++ b/tez-ui2/src/main/webapp/app/initializers/loader.js @@ -0,0 +1,27 @@ +/** + * 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. + */ + +export function initialize(application) { + application.inject('route', 'loader', 'service:loader'); + application.inject('entity', 'loader', 'service:loader'); +} + +export default { + name: 'loader', + initialize +}; http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/app/serializers/abstract.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/serializers/abstract.js b/tez-ui2/src/main/webapp/app/serializers/abstract.js deleted file mode 100644 index c032c30..0000000 --- a/tez-ui2/src/main/webapp/app/serializers/abstract.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * 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 DS from 'ember-data'; - -export default DS.RESTSerializer.extend({ - normalize: function(type, hash /*, prop */) { - return Ember.JsonMapper.map(hash, this.get('map')); - } -}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/app/serializers/loader.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/serializers/loader.js b/tez-ui2/src/main/webapp/app/serializers/loader.js new file mode 100644 index 0000000..9c97886 --- /dev/null +++ b/tez-ui2/src/main/webapp/app/serializers/loader.js @@ -0,0 +1,81 @@ +/** + * 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 DS from 'ember-data'; + +// TODO - Move to more js +function mapObject(hash, map) { + var mappedObject = Ember.Object.create(); + for (var key in map) { + mappedObject.set(key, Ember.get(hash, map[key])); + } + return mappedObject; +} + +export default DS.JSONSerializer.extend({ + _isLoader: true, + + maps: null, + + extractId: function (modelClass, resourceHash) { + var id = this._super(modelClass, resourceHash.data), + nameSpace = resourceHash.nameSpace; + + if(nameSpace) { + return nameSpace + ":" + id; + } + return id; + }, + extractAttributes: function (modelClass, resourceHash) { + var maps = this.get('maps'), + data = resourceHash.data; + return this._super(modelClass, maps ? mapObject(data, maps) : data); + }, + extractRelationships: function (modelClass, resourceHash) { + return this._super(modelClass, resourceHash.data); + }, + + extractSinglePayload: function (payload) { + return payload; + }, + extractArrayPayload: function (payload) { + return payload; + }, + + normalizeSingleResponse: function (store, primaryModelClass, payload, id, requestType) { + payload.data = this.extractSinglePayload(payload.data); + return this._super(store, primaryModelClass, payload, id, requestType); + }, + + normalizeArrayResponse: function (store, primaryModelClass, payload, id, requestType) { + var nameSpace = payload.nameSpace; + + // convert into a _normalizeResponse friendly format + payload = this.extractArrayPayload(payload.data); + Ember.assert("Loader expects an array in return for a query", Array.isArray(payload)); + payload = payload.map(function (item) { + return { + nameSpace: nameSpace, + data: item + }; + }); + + return this._super(store, primaryModelClass, payload, id, requestType); + } +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/app/services/loader.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/app/services/loader.js b/tez-ui2/src/main/webapp/app/services/loader.js new file mode 100644 index 0000000..054a6b5 --- /dev/null +++ b/tez-ui2/src/main/webapp/app/services/loader.js @@ -0,0 +1,145 @@ +/** + * 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'; + +export default Ember.Service.extend({ + + nameSpace: '', + store: Ember.inject.service('store'), + cache: null, + + _setOptions: function (options) { + var nameSpace = options.nameSpace; + if(nameSpace) { + // We need to validate only if nameSpace is passed. Else it would be stored in the global space + Ember.assert(`Invalid nameSpace. Please pass a string instead of ${Ember.inspect(nameSpace)}`, typeof nameSpace === 'string'); + this.set("nameSpace", nameSpace); + } + }, + + init: function (options) { + this._super(); + this._setOptions(options || {}); + this.set("cache", Ember.Object.create()); + }, + + checkRequisite: function (type) { + var store = this.get("store"), + adapter = store.adapterFor(type), + serializer = store.serializerFor(type); + + Ember.assert( + `No loader adapter found for type ${type}. Either extend loader and create a custom adapter or extend ApplicationAdapter from loader.`, + adapter && adapter._isLoader + ); + Ember.assert( + `No loader serializer found for type ${type}. Either extend loader and create a custom serializer or extend ApplicationSerializer from loader.`, + serializer && serializer._isLoader + ); + }, + + lookup: function (type, name) { + name = Ember.String.dasherize(name); + return this.get("container").lookup(type + ":" + name); + }, + + entityFor: function (entityName) { + var entity = this.lookup("entitie", entityName); + if(!entity) { + entity = this.lookup("entitie", "entity"); + } + entity.name = entityName; + return entity; + }, + + getCacheKey: function (type, query, id) { + var parts = [type]; + + if(id) { + parts.push(id); + } + if(query) { + parts.push(JSON.stringify(query)); + } + + return parts.join(":"); + }, + + queryRecord: function(type, id, query, urlParams, options) { + var entity = this.entityFor(type), + cache = this.get("cache"), + cacheKey = this.getCacheKey(type, query, id), + that = this, + record; + + this.checkRequisite(type); + + options = options || {}; + if(!options.reload) { + record = cache.get(cacheKey); + if(record) { + return record; + } + } + + record = this.get('store').queryRecord(type, { + id: id, + nameSpace: this.get('nameSpace'), + params: query, + urlParams: urlParams + }).then(function (record) { + return entity.loadRelations(that, record); + }); + + cache.set(cacheKey, record); + return record; + }, + query: function(type, query, urlParams, options) { + var entity = this.entityFor(type), + cache = this.get("cache"), + cacheKey = this.getCacheKey(type, query), + that = this, + records; + + this.checkRequisite(type); + + options = options || {}; + if(!options.reload) { + records = cache.get(cacheKey); + if(records) { + return records; + } + } + + records = this.get('store').query(type, { + nameSpace: this.get('nameSpace'), + params: query, + urlParams: urlParams + }).then(function (records) { + return Ember.RSVP.all(records.map(function (record) { + return entity.loadRelations(that, record); + })).then(function () { + return records; + }); + }); + + cache.set(cacheKey, records); + return records; + } +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/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 deleted file mode 100644 index 00be0ac..0000000 --- a/tez-ui2/src/main/webapp/tests/unit/adapters/abstract-test.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 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', function(assert) { - let adapter = this.subject(); - - assert.ok(adapter); -}); - -test('buildURL test', function(assert) { - let adapter = this.subject(); - - assert.equal(adapter.buildURL("{x}/{y}/type", null, { - x: "x_x", - y: "y_y" - }), "/x_x/y_y/types"); -}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/tests/unit/adapters/loader-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/adapters/loader-test.js b/tez-ui2/src/main/webapp/tests/unit/adapters/loader-test.js new file mode 100644 index 0000000..7b4a2df --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/unit/adapters/loader-test.js @@ -0,0 +1,137 @@ +/** + * 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 { moduleFor, test } from 'ember-qunit'; + +moduleFor('adapter:loader', 'Unit | Adapter | loader', { + // Specify the other units that are required for this test. + // needs: ['serializer:foo'] +}); + +test('Basic creation', function(assert) { + let adapter = this.subject(); + + assert.ok(adapter); + assert.ok(adapter._isLoader); + assert.ok(adapter.buildURL); + assert.ok(adapter._loaderAjax); + assert.ok(adapter.queryRecord); + assert.ok(adapter.query); +}); + +test('buildURL test', function(assert) { + let adapter = this.subject(); + + assert.equal(adapter.buildURL("dag"), "/dags"); + assert.equal(adapter.buildURL("dag", "dag1"), "/dags/dag1"); + assert.equal(adapter.buildURL("{x}dag", "dag1", null, null, null, {x: "x_x"}), "/x_xdags/dag1", "Test for substitution"); +}); + +test('_loaderAjax test', function(assert) { + let adapter = this.subject(), + testURL = "/dags", + testQueryParams = { x:1 }, + testRecord = {}, + testNameSpace = "ns"; + + assert.expect(2 + 1 + 2); + + adapter.ajax = function (url, method/*, options*/) { + + assert.equal(url, testURL); + assert.equal(method, "GET"); + + return Ember.RSVP.resolve(testRecord); + }; + + adapter.sortQueryParams = function (queryParams) { + assert.ok(queryParams, "sortQueryParams was called with query params"); + }; + + adapter._loaderAjax(testURL, testQueryParams, testNameSpace).then(function (data) { + assert.equal(data.nameSpace, testNameSpace, "Namespace returned"); + assert.equal(data.data, testRecord, "Test record returned"); + }); +}); + +test('queryRecord test', function(assert) { + let adapter = this.subject(), + testURL = "/dags", + testModel = { modelName: "testModel" }, + testStore = {}, + testQuery = { + id: "test1", + params: {}, + urlParams: {}, + nameSpace: "ns" + }; + + assert.expect(4 + 3); + + adapter.buildURL = function (modelName, id, snapshot, requestType, query, params) { + assert.equal(modelName, testModel.modelName); + assert.equal(id, testQuery.id); + assert.equal(query, testQuery.params); + assert.equal(params, testQuery.urlParams); + + return testURL; + }; + + adapter._loaderAjax = function (url, queryParams, nameSpace) { + assert.equal(url, testURL); + assert.equal(queryParams, testQuery.params); + assert.equal(nameSpace, testQuery.nameSpace); + }; + + adapter.queryRecord(testStore, testModel, testQuery); +}); + +test('query test', function(assert) { + let adapter = this.subject(), + testURL = "/dags", + testModel = { modelName: "testModel" }, + testStore = {}, + testQuery = { + id: "test1", + params: {}, + urlParams: {}, + nameSpace: "ns" + }; + + assert.expect(5 + 3); + + adapter.buildURL = function (modelName, id, snapshot, requestType, query, params) { + assert.equal(modelName, testModel.modelName); + assert.equal(id, null); + assert.equal(requestType, "query"); + assert.equal(query, testQuery.params); + assert.equal(params, testQuery.urlParams); + + return testURL; + }; + + adapter._loaderAjax = function (url, queryParams, nameSpace) { + assert.equal(url, testURL); + assert.equal(queryParams, testQuery.params); + assert.equal(nameSpace, testQuery.nameSpace); + }; + + adapter.query(testStore, testModel, testQuery); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/tests/unit/entities/entity-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/entities/entity-test.js b/tez-ui2/src/main/webapp/tests/unit/entities/entity-test.js new file mode 100644 index 0000000..23e349d --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/unit/entities/entity-test.js @@ -0,0 +1,139 @@ +/** + * 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 { moduleFor, test } from 'ember-qunit'; + +moduleFor('entitie:entity', 'Unit | Entity | entity', { + // Specify the other units that are required for this test. + // needs: ['entitie:foo'] +}); + +test('Basic creation', function(assert) { + let adapter = this.subject(); + + assert.ok(adapter); + assert.ok(adapter.loadRelations); + assert.ok(adapter.normalizeNeed); + assert.ok(adapter.loadNeeds); +}); + +test('loadRelations creation', function(assert) { + let adapter = this.subject(), + testLoader = {}, + testModel = {}, + relationsPromise; + + assert.expect(2 + 1 + 2 + 2); + + // Test model without needs + adapter.loadNeeds = function (loader, model) { + assert.equal(loader, testLoader); + assert.equal(model, testModel); + + return null; + }; + relationsPromise = adapter.loadRelations(testLoader, testModel); + + assert.equal(relationsPromise, testModel, "Model without needs"); + + // Test model with needs + adapter.loadNeeds = function (loader, model) { + assert.equal(loader, testLoader); + assert.equal(model, testModel); + + return Ember.RSVP.resolve(); + }; + relationsPromise = adapter.loadRelations(testLoader, testModel); + + assert.notEqual(relationsPromise, testModel); + relationsPromise.then(function (model) { + assert.equal(model, testModel); + }); + +}); + +test('normalizeNeed creation', function(assert) { + let adapter = this.subject(); + + assert.deepEqual(adapter.normalizeNeed("app", "appKey"), { + name: "app", + type: "app", + idKey: "appKey", + lazy: false + }, "Test 1"); + + assert.deepEqual(adapter.normalizeNeed( "app", { idKey: "appKey" }), { + name: "app", + type: "app", + idKey: "appKey", + lazy: false + }, "Test 2"); + + assert.deepEqual(adapter.normalizeNeed( "app", { type: "application", idKey: "appKey" }), { + name: "app", + type: "application", + idKey: "appKey", + lazy: false + }, "Test 3"); + + assert.deepEqual(adapter.normalizeNeed( "app", { lazy: true, idKey: "appKey" }), { + name: "app", + type: "app", + idKey: "appKey", + lazy: true + }, "Test 4"); +}); + +test('loadNeeds creation', function(assert) { + let adapter = this.subject(), + loader, + testModel = Ember.Object.create({ + needs: { + app: "appID", + foo: "fooID" + }, + appID: 1, + fooID: 2 + }); + + assert.expect(1 + 2 + 1); + + assert.equal(adapter.loadNeeds(loader, Ember.Object.create()), null, "Model without needs"); + + loader = { + queryRecord: function (type, id) { + + // Must be called twice, once for each record + switch(type) { + case "app": + assert.equal(id, testModel.get("appID")); + break; + case "foo": + assert.equal(id, testModel.get("fooID")); + break; + } + + return Ember.RSVP.resolve(); + } + }; + adapter.loadNeeds(loader, testModel).then(function () { + assert.ok(true); + }); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/tests/unit/initializers/loader-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/initializers/loader-test.js b/tez-ui2/src/main/webapp/tests/unit/initializers/loader-test.js new file mode 100644 index 0000000..cc32e92 --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/unit/initializers/loader-test.js @@ -0,0 +1,40 @@ +/** + * 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 LoaderInitializer from '../../../initializers/loader'; +import { module, test } from 'qunit'; + +let application; + +module('Unit | Initializer | loader', { + beforeEach() { + Ember.run(function() { + application = Ember.Application.create(); + application.deferReadiness(); + }); + } +}); + +// Replace this with your real tests. +test('it works', function(assert) { + LoaderInitializer.initialize(application); + + // you would normally confirm the results of the initializer here + assert.ok(true); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/tests/unit/serializers/abstract-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/serializers/abstract-test.js b/tez-ui2/src/main/webapp/tests/unit/serializers/abstract-test.js deleted file mode 100644 index 006d69c..0000000 --- a/tez-ui2/src/main/webapp/tests/unit/serializers/abstract-test.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * 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 { moduleForModel, test } from 'ember-qunit'; - -moduleForModel('abstract', 'Unit | Serializer | abstract', { - // Specify the other units that are required for this test. - needs: ['serializer:abstract'] -}); - -test('it serializes records', function(assert) { - let record = this.subject(); - let serializedRecord = record.serialize(); - - assert.ok(serializedRecord); -}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/tests/unit/serializers/loader-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/serializers/loader-test.js b/tez-ui2/src/main/webapp/tests/unit/serializers/loader-test.js new file mode 100644 index 0000000..5add84a --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/unit/serializers/loader-test.js @@ -0,0 +1,193 @@ +/** + * 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 { moduleFor, test } from 'ember-qunit'; + +moduleFor('serializer:loader', 'Unit | Serializer | loader', { + // Specify the other units that are required for this test. + // needs: ['serializer:loader'] +}); + +test('Basic creation test', function(assert) { + let serializer = this.subject(); + + assert.ok(serializer); + assert.ok(serializer._isLoader); + + assert.ok(serializer.extractId); + assert.ok(serializer.extractAttributes); + assert.ok(serializer.extractRelationships); + + assert.ok(serializer.extractSinglePayload); + assert.ok(serializer.extractArrayPayload); + + assert.ok(serializer.normalizeSingleResponse); + assert.ok(serializer.normalizeArrayResponse); +}); + +test('extractId test', function(assert) { + let serializer = this.subject(), + modelClass = {}, + resourceHash = { + nameSpace: "ns", + data: { + id: 1, + entityID: 3 + } + }; + + assert.equal(serializer.extractId(modelClass, resourceHash), "ns:1", "With name-space"); + assert.equal(serializer.extractId(modelClass, { data: {id: 2} }), 2, "Without name-space"); + + serializer.primaryKey = "entityID"; + assert.equal(serializer.extractId(modelClass, resourceHash), "ns:3", "Different primary key"); +}); + +test('extractAttributes test', function(assert) { + let serializer = this.subject(), + modelClass = { + eachAttribute: function (callback) { + callback("id", {type: "string"}); + callback("appID", {type: "string"}); + callback("status", {type: "string"}); + } + }, + resourceHash = { + nameSpace: "ns", + data: { + id: 1, + appID: 2, + applicationID: 3, + info: { + status: "SUCCESS" + } + } + }; + + assert.deepEqual(serializer.extractAttributes(modelClass, resourceHash), { + id: 1, + appID: 2 + }); + + serializer.maps = { + id: "id", + appID: "applicationID", + status: "info.status" + }; + + assert.deepEqual(serializer.extractAttributes(modelClass, resourceHash), { + id: 1, + appID: 3, + status: "SUCCESS" + }); +}); + +test('extractRelationships test', function(assert) { + let serializer = this.subject(), + modelClass = { + eachAttribute: Ember.K, + eachRelationship: function (callback) { + callback("app", { + key: "app", + kind: "belongsTo", + options: {}, + parentType: "parent", + type: "app" + }); + }, + eachTransformedAttribute: Ember.K + }, + resourceHash = { + nameSpace: "ns", + data: { + id: 1, + app: "", + } + }; + + assert.deepEqual(serializer.extractRelationships(modelClass, resourceHash), { + app: { + data: { + id: null, + type:"app" + } + } + }); + +}); + +test('normalizeSingleResponse test', function(assert) { + let serializer = this.subject(), + modelClass = { + eachAttribute: function (callback) { + callback("id", {type: "string"}); + callback("appID", {type: "string"}); + callback("status", {type: "string"}); + }, + eachRelationship: Ember.K, + eachTransformedAttribute: Ember.K + }, + resourceHash = { + nameSpace: "ns", + data: { + id: 1, + appID: 2, + applicationID: 3, + info: { + status: "SUCCESS" + } + } + }; + + var response = serializer.normalizeSingleResponse({}, modelClass, resourceHash, null, null); + + assert.equal(response.data.id, "ns:1"); + assert.equal(response.data.attributes.id, 1); + assert.equal(response.data.attributes.appID, 2); +}); + +test('normalizeArrayResponse test', function(assert) { + let serializer = this.subject(), + modelClass = { + eachAttribute: function (callback) { + callback("id", {type: "string"}); + callback("appID", {type: "string"}); + callback("status", {type: "string"}); + }, + eachRelationship: Ember.K, + eachTransformedAttribute: Ember.K + }, + resourceHash = { + nameSpace: "ns", + data: [{ + id: 1, + appID: 2, + },{ + id: 2, + appID: 4, + }] + }; + + var response = serializer.normalizeArrayResponse({}, modelClass, resourceHash, null, null); + + assert.equal(response.data.length, 2); + assert.deepEqual(response.data[0].id, "ns:1"); + assert.deepEqual(response.data[1].id, "ns:2"); +}); http://git-wip-us.apache.org/repos/asf/tez/blob/6e18c9b9/tez-ui2/src/main/webapp/tests/unit/services/loader-test.js ---------------------------------------------------------------------- diff --git a/tez-ui2/src/main/webapp/tests/unit/services/loader-test.js b/tez-ui2/src/main/webapp/tests/unit/services/loader-test.js new file mode 100644 index 0000000..548aca8 --- /dev/null +++ b/tez-ui2/src/main/webapp/tests/unit/services/loader-test.js @@ -0,0 +1,267 @@ +/** + * 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 { moduleFor, test } from 'ember-qunit'; + +moduleFor('service:loader', 'Unit | Service | loader', { + // Specify the other units that are required for this test. + // needs: ['service:foo'] +}); + +test('Basic creation test', function(assert) { + let service = this.subject(); + + assert.ok(service.cache); + assert.ok(service.store); + assert.ok(service._setOptions); + + assert.ok(service.checkRequisite); + + assert.ok(service.lookup); + assert.ok(service.entityFor); + + assert.ok(service.getCacheKey); + + assert.ok(service.queryRecord); + assert.ok(service.query); +}); + +test('_setOptions test', function(assert) { + let service = this.subject(); + + assert.equal(service.get("nameSpace"), ''); + + service._setOptions({ + nameSpace: "ns" + }); + + assert.equal(service.get("nameSpace"), 'ns'); +}); + +test('checkRequisite test', function(assert) { + let service = this.subject(), + testType = "type"; + + assert.expect(3 + 3 + 2); + + // Not found + service.store = { + adapterFor: function (type) { + assert.equal(type, testType); + }, + serializerFor: function (type) { + assert.equal(type, testType); + } + }; + assert.throws(function () { + service.checkRequisite(testType); + }); + + // Not loader found + service.store = { + adapterFor: function (type) { + assert.equal(type, testType); + return {}; + }, + serializerFor: function (type) { + assert.equal(type, testType); + return {}; + } + }; + assert.throws(function () { + service.checkRequisite(testType); + }); + + service.store = { + adapterFor: function (type) { + assert.equal(type, testType); + return { _isLoader: true }; + }, + serializerFor: function (type) { + assert.equal(type, testType); + return { _isLoader: true }; + } + }; + + service.checkRequisite(testType); +}); + +test('lookup test', function(assert) { + let service = this.subject(); + + assert.expect(1); + + service.container.lookup = function (fullName) { + assert.equal(fullName, "typ:na-me"); + }; + + service.lookup("typ", "NaMe"); +}); + +test('entityFor test', function(assert) { + let service = this.subject(), + testName = "abc", + entity; + + assert.expect(3 + 4 + 3); + + // All lookups fail + service.lookup = function (type, name) { + if(name === testName) { + assert.equal(type, "entitie"); + } + if(name === "entity") { + assert.equal(type, "entitie"); + } + }; + assert.throws(function () { + service.entityFor(testName); + }, "All lookups fail"); + + // Default lookups succeeded + service.lookup = function (type, name) { + if(name === testName) { + assert.equal(type, "entitie"); + } + if(name === "entity") { + assert.equal(type, "entitie"); + return { + actualName: "entity" + }; + } + }; + entity = service.entityFor(testName); + assert.equal(entity.actualName, "entity", "Default lookups succeeded"); + assert.equal(entity.name, testName, "Default lookups succeeded"); + + // Primary lookups succeeded + service.lookup = function (type, name) { + if(name === testName) { + assert.equal(type, "entitie"); + return { + actualName: name + }; + } + if(name === "entity") { + assert.equal(type, "entitie"); // Shouldn't be called + } + }; + entity = service.entityFor(testName); + assert.equal(entity.name, testName, "Default lookups succeeded"); + assert.equal(entity.name, testName, "Default lookups succeeded"); +}); + +test('getCacheKey test', function(assert) { + let service = this.subject(); + + assert.equal(service.getCacheKey("type"), "type"); + assert.equal(service.getCacheKey("type", {a:1}), 'type:{"a":1}'); + assert.equal(service.getCacheKey("type", null, 1), "type:1"); + assert.equal(service.getCacheKey("type", {a:1}, 1), 'type:1:{"a":1}'); +}); + +test('queryRecord test', function(assert) { + let service = this.subject(), + testNameSpace = "ns", + testQueryParams = {}, + testUrlParams = {}, + testType = "type", + testRecord = {}, + testID = 1, + cacheKey = service.getCacheKey(testType, testQueryParams, testID); + + assert.expect(3 + 5 + 3); + + service.nameSpace = testNameSpace; + service.checkRequisite = Ember.K; + service.entityFor = function (type) { + assert.equal(type, testType); + + return { + loadRelations: function (thisService, record) { + assert.equal(thisService, service); + assert.equal(record, testRecord); + + return record; + } + }; + }; + service.get("store").queryRecord = function (type, query) { + assert.equal(type, testType); + + assert.equal(query.id, testID); + assert.equal(query.nameSpace, testNameSpace); + assert.equal(query.params, testQueryParams); + assert.equal(query.urlParams, testUrlParams); + + return Ember.RSVP.resolve(testRecord); + }; + + service.cache = Ember.Object.create(); + assert.notOk(service.get("cache").get(cacheKey)); + service.queryRecord(testType, testID, testQueryParams, testUrlParams).then(function (record) { + assert.equal(record, testRecord); + }); + assert.ok(service.get("cache").get(cacheKey)); +}); + +test('query test', function(assert) { + let service = this.subject(), + testNameSpace = "ns", + testQueryParams = {}, + testUrlParams = {}, + testType = "type", + testRecord = {}, + testRecords = [testRecord, testRecord], + cacheKey = service.getCacheKey(testType, testQueryParams); + + assert.expect(1 + (2 + 2) + 4 + 3); + + service.nameSpace = testNameSpace; + service.checkRequisite = Ember.K; + service.entityFor = function (type) { + assert.equal(type, testType); + + return { + loadRelations: function (thisService, record) { + assert.equal(thisService, service); + assert.equal(record, testRecord); + + return record; + } + }; + }; + service.get("store").query = function (type, query) { + assert.equal(type, testType); + + assert.equal(query.nameSpace, testNameSpace); + assert.equal(query.params, testQueryParams); + assert.equal(query.urlParams, testUrlParams); + + return Ember.RSVP.resolve(testRecords); + }; + + service.cache = Ember.Object.create(); + assert.notOk(service.get("cache").get(cacheKey)); + service.query(testType, testQueryParams, testUrlParams).then(function (records) { + assert.equal(records, testRecords); + }); + assert.ok(service.get("cache").get(cacheKey)); +});