ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dbhowm...@apache.org
Subject [06/21] ambari git commit: AMBARI-16963: JDBC implementation of hive view. (dipayanb)
Date Tue, 31 May 2016 19:44:22 GMT
http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/saved-queries-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/saved-queries-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/saved-queries-test.js
new file mode 100644
index 0000000..c444523
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/saved-queries-test.js
@@ -0,0 +1,126 @@
+/**
+ * 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 { test } from 'ember-qunit';
+import startApp from '../helpers/start-app';
+import api from '../helpers/api-mock';
+
+var App;
+var server;
+
+module('Integration: Saved Queries', {
+  setup: function() {
+    App = startApp();
+    /* global Pretender: true */
+    server = new Pretender(api);
+  },
+
+  teardown: function() {
+    Ember.run(App, App.destroy);
+    server.shutdown();
+  }
+});
+
+test('Save Queries should list saved queries', function() {
+  expect(1);
+
+  visit("/queries");
+
+
+  andThen(function() {
+    equal(find('#content .table tbody tr').length, 2);
+  });
+});
+
+test('User should be able to filter the queries', function() {
+  expect(8);
+
+  visit("/queries");
+
+  fillIn('column-filter input[placeholder=preview]', "select count");
+  keyEvent('column-filter input[placeholder=preview]', 'keyup');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 1, 'User is able to filter by short query form.');
+  });
+
+  click('.clear-filters');
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 2);
+  });
+
+  fillIn('column-filter input[placeholder=title]', "saved1");
+  keyEvent('column-filter input[placeholder=title]', 'keyup');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 1, 'User is able to filter by title');
+  });
+
+  click('.clear-filters');
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 2);
+  });
+
+  fillIn('column-filter input[placeholder=database]', "db1");
+  keyEvent('column-filter input[placeholder=database]', 'keyup');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 1, 'User is able to filter by database');
+  });
+
+  click('.clear-filters');
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 2);
+  });
+
+  fillIn('column-filter input[placeholder=owner]', "owner1");
+  keyEvent('column-filter input[placeholder=owner]', 'keyup');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 1, 'User is able to filter by owner');
+  });
+
+  click('.clear-filters');
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 2);
+  });
+});
+
+test('User is able to load a query from saved queries', function() {
+  expect(1);
+
+  visit("/queries");
+  click('#content .table tbody tr:first-child td:first-child a');
+
+  andThen(function() {
+    equal(currentURL(), "/queries/1", 'User is redirected');
+  });
+});
+
+test('Saved Query options menu', function() {
+  expect(2);
+
+  visit("/queries");
+  click('.fa-gear');
+
+  andThen(function() {
+    equal(find('.dropdown-menu:visible').length, 1, 'Query menu is visible');
+    equal(find('.dropdown-menu:visible li').length, 2, 'Query menu has 2 options');
+  });
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/tez-ui-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/tez-ui-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/tez-ui-test.js
new file mode 100644
index 0000000..f64dcb2
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/tez-ui-test.js
@@ -0,0 +1,49 @@
+/**
+ * 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 { test } from 'ember-qunit';
+import startApp from '../helpers/start-app';
+import api from '../helpers/api-mock';
+
+var App;
+var server;
+
+module('Integration: Tez UI', {
+  setup: function() {
+    App = startApp();
+    /* global Pretender: true */
+    server = new Pretender(api);
+  },
+
+  teardown: function() {
+    Ember.run(App, App.destroy);
+    server.shutdown();
+  }
+});
+
+test('An error is show when there is no dag', function() {
+  expect(1);
+
+  visit("/");
+  click('#tez-icon');
+
+  andThen(function() {
+    ok(find('.panel .alert .alert-danger'), 'Error is visible');
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/udfs-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/udfs-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/udfs-test.js
new file mode 100644
index 0000000..95a0043
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/integration/udfs-test.js
@@ -0,0 +1,91 @@
+/**
+ * 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 { test } from 'ember-qunit';
+import startApp from '../helpers/start-app';
+import api from '../helpers/api-mock';
+
+var App;
+var server;
+
+module('Integration: Udfs', {
+  setup: function() {
+    App = startApp();
+    /* global Pretender: true */
+    server = new Pretender(api);
+  },
+
+  teardown: function() {
+    Ember.run(App, App.destroy);
+    server.shutdown();
+  }
+});
+
+test('Save Queries should list saved queries', function() {
+  expect(1);
+
+  visit("/udfs");
+
+  andThen(function() {
+    equal(find('#content .table tbody tr').length, 2);
+  });
+});
+
+test('User should be able to filter the udfs', function() {
+  expect(4);
+
+  visit("/udfs");
+
+  fillIn('column-filter input[placeholder="udf name"]', "TestColumn");
+  keyEvent('column-filter input[placeholder="udf name"]', 'keyup');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 1, 'User is able to filter by name');
+  });
+
+  click('.clear-filters');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 2);
+  });
+
+  fillIn('column-filter input[placeholder="udf class name"]', "TestClassName");
+  keyEvent('column-filter input[placeholder="udf class name"]', 'keyup');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 1, 'User is able to filter by class name');
+  });
+
+  click('.clear-filters');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr:visible').length, 2);
+  });
+});
+
+test('User is able to add udf', function() {
+  expect(1);
+
+  visit("/udfs");
+  click('.add-udf');
+
+  andThen(function() {
+    equal(find('#content .table tbody tr').length, 3);
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/test-helper.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/test-helper.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/test-helper.js
new file mode 100644
index 0000000..96975ee
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/test-helper.js
@@ -0,0 +1,24 @@
+/**
+ * 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 resolver from './helpers/resolver';
+import {
+  setResolver
+} from 'ember-qunit';
+
+setResolver(resolver);

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/.gitkeep b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/.gitkeep
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/application.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/application.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/application.js
new file mode 100644
index 0000000..6e28a40
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/application.js
@@ -0,0 +1,48 @@
+/**
+ * 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';
+
+import constants from 'hive/utils/constants';
+
+moduleFor('adapter:application', 'ApplicationAdapter', {
+  // Specify the other units that are required for this test.
+  // needs: ['serializer:foo']
+});
+
+// Replace this with your real tests.
+test('X-Requested-By header is set.', function() {
+  expect(1);
+
+  var adapter = this.subject();
+
+  ok(adapter.get('headers.X-Requested-By'), 'X-Requested-By is set to a truthy value.');
+});
+
+test('buildUrl returns an url with default values for version and instance paramters if not running within an Ambari instance.', function () {
+  expect(1);
+
+  var adapter = this.subject();
+
+  var url = adapter.buildURL();
+
+  equal(url, constants.adapter.apiPrefix + constants.adapter.version + constants.adapter.instancePrefix + 'Hive');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/file.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/file.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/file.js
new file mode 100644
index 0000000..ea70232
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/adapters/file.js
@@ -0,0 +1,39 @@
+/**
+ * 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';
+
+import constants from 'hive/utils/constants';
+
+moduleFor('adapter:file', 'FileAdapter', {
+  // Specify the other units that are required for this test.
+  // needs: ['serializer:foo']
+});
+
+// Replace this with your real tests.
+test('pathForType returns correct path.', function() {
+  expect(1);
+
+  var adapter = this.subject();
+  var type = 'dummy';
+
+  equal(adapter.pathForType(type), constants.adapter.resourcePrefix + type);
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/alert-message-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/alert-message-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/alert-message-widget-test.js
new file mode 100644
index 0000000..8f0f245
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/alert-message-widget-test.js
@@ -0,0 +1,91 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('alert-message-widget', 'AlertMessageWidgetComponent', {
+  needs: []
+});
+
+test('isExpanded is toggled on click', function() {
+  expect(2);
+
+  var message = Ember.Object.create({ isExpanded: false});
+
+  var component = this.subject({
+    message: message
+  });
+
+  Ember.run(function() {
+    component.send('toggleMessage');
+  });
+
+  equal(component.get('message.isExpanded'), true, 'isExpanded is set to true');
+
+  Ember.run(function() {
+    component.send('toggleMessage');
+  });
+
+  equal(component.get('message.isExpanded'), false, 'isExpanded is set to false');
+});
+
+test('removeLater should be called when the message is toggled', function() {
+  expect(1);
+
+  var message = Ember.Object.create({ isExpanded: false});
+
+  var targetObject = {
+    removeLater: function() {
+      ok(true, 'External removeLater called');
+    }
+  };
+
+  var component = this.subject({
+    targetObject: targetObject,
+    removeLater: 'removeLater',
+    message: message
+  });
+
+  Ember.run(function() {
+    component.send('toggleMessage');
+  });
+
+  Ember.run(function() {
+    component.send('toggleMessage');
+  });
+});
+
+test('remove action should call external removeMessage', function() {
+  expect(1);
+
+  var targetObject = {
+    removeMessage: function() {
+      ok(true, 'External removeMessage called');
+    }
+  };
+
+  var component = this.subject({
+    targetObject: targetObject,
+    removeMessage: 'removeMessage'
+  });
+
+  Ember.run(function() {
+    component.send('remove', {});
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/collapsible-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/collapsible-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/collapsible-widget-test.js
new file mode 100644
index 0000000..96a551f
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/collapsible-widget-test.js
@@ -0,0 +1,46 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('collapsible-widget', 'CollapsibleWidgetComponent', {
+  unit: true
+});
+
+test('Component expand/collapse toggle action', function () {
+  expect(1);
+
+  var targetObject = {
+    expanded: function() {
+      ok(true, 'External expanded called');
+    }
+  };
+
+  var component = this.subject({
+    targetObject: targetObject,
+    isExpanded: 'isExpanded',
+    expanded: 'expanded'
+  });
+
+  var $component = this.render();
+
+  Ember.run(function() {
+    component.set('isExpanded', false);
+    component.send('toggle', {});
+   });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/column-filter-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/column-filter-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/column-filter-widget-test.js
new file mode 100644
index 0000000..be8bdc4
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/column-filter-widget-test.js
@@ -0,0 +1,138 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('column-filter-widget', 'ColumnFilterWidgetComponent', {
+  needs: ['component:extended-input']
+});
+
+test('if a filterValue is set when the element is inserted, an action is being sent announcing a filter change', function () {
+  expect(1);
+
+  var column = Ember.Object.create({
+    caption: 'missing.translation'
+  });
+
+  var component = this.subject({ column: column });
+
+  Ember.run(function () {
+    component.set('filterValue', 'initial filter value');
+  });
+
+  var targetObject = {
+    externalAction: function(){
+      ok(true, 'initial filterValue set. Action has been sent.');
+    }
+  };
+
+  component.set('columnFiltered', 'externalAction');
+  component.set('targetObject', targetObject);
+
+  var $component = this.$();
+});
+
+test('isSorted returns true if the table is sorted by this column property', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var column = Ember.Object.create({
+    property: 'some prop'
+  });
+
+  Ember.run(function () {
+    component.set('column', column);
+    component.set('sortProperties', [column.property]);
+  });
+
+  ok(component.get('isSorted'));
+});
+
+test('isSorted returns false if the table is sorted by some other column', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var column = Ember.Object.create({
+    property: 'some prop'
+  });
+
+  Ember.run(function () {
+    component.set('column', column);
+    component.set('sortProperties', ['other prop']);
+  });
+
+  ok(!component.get('isSorted'));
+});
+
+test('isSorted returns false if the table is not sorted by any column', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var column = Ember.Object.create({
+    property: 'some prop'
+  });
+
+  Ember.run(function () {
+    component.set('column', column);
+    component.set('sortProperties', []);
+  });
+
+  ok(!component.get('isSorted'));
+});
+
+test('when sendSort gets called, the columnSorted action gets sent.', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var targetObject = {
+    externalAction: function(){
+      ok(true, 'columnSorted action has been intercepted.');
+    }
+  };
+
+  Ember.run(function () {
+    component.set('targetObject', targetObject);
+    component.set('columnSorted', 'externalAction');
+
+    component.send('sendSort');
+  });
+});
+
+test('when sendFilter gets called, the columnFiltered action gets sent.', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var targetObject = {
+    externalAction: function(){
+      ok(true, 'columnFiltered action has been intercepted.');
+    }
+  };
+
+  Ember.run(function () {
+    component.set('targetObject', targetObject);
+    component.set('columnFiltered', 'externalAction');
+
+    component.send('sendFilter');
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/date-range-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/date-range-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/date-range-widget-test.js
new file mode 100644
index 0000000..766e9ee
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/date-range-widget-test.js
@@ -0,0 +1,132 @@
+/**
+ * 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.
+ */
+
+/* global moment */
+
+import Ember from 'ember';
+import { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('date-range-widget', 'DateRangeWidgetComponent', {
+  needs: ['component:extended-input']
+});
+
+test('Date fields are set correctly', function() {
+  expect(2);
+
+  var component = this.subject();
+
+  var min = moment('04/11/2014', 'DD/MM/YYYY');
+  var max = moment('04/12/2014', 'DD/MM/YYYY');
+  var from = moment('04/11/2014', 'DD/MM/YYYY');
+  var to = moment('04/12/2014', 'DD/MM/YYYY');
+
+  var dateRange = Ember.Object.create({
+    from: from.toString(),
+    to: to.toString(),
+    min: min.toString(),
+    max: max.toString()
+  });
+
+  component.set('dateRange', Ember.Object.create());
+
+  var $component = this.$();
+
+  Ember.run(function() {
+    component.set('dateRange', dateRange);
+  });
+
+  equal($component.find('.fromDate').val(), moment(from).format('MM/DD/YYYY'), "From date is set correctly");
+  equal($component.find('.toDate').val(), moment(to).format('MM/DD/YYYY'), "To date is set correctly");
+});
+
+test('Date fields updates when the date is changed', function() {
+  expect(2);
+
+  var component = this.subject();
+
+  var min = moment('04/11/2014', 'DD/MM/YYYY');
+  var max = moment('04/12/2014', 'DD/MM/YYYY');
+  var from = moment('04/11/2014', 'DD/MM/YYYY');
+  var to = moment('04/12/2014', 'DD/MM/YYYY');
+
+  var dateRange = Ember.Object.create({
+    from: from.toString(),
+    to: to.toString(),
+    min: min.toString(),
+    max: max.toString()
+  });
+
+  Ember.run(function() {
+    component.set('dateRange', dateRange);
+  });
+
+  var $component = this.$();
+  $component.find('.fromDate').datepicker('setDate', '10/10/2014');
+  $component.find('.toDate').datepicker('setDate', '11/11/2014');
+
+  equal($component.find('.fromDate').val(), '10/10/2014', "From date field is updated");
+  equal($component.find('.toDate').val(), '11/11/2014', "To date field is updated");
+});
+
+test('Display dates are formatted correctly', function(){
+  expect(2);
+
+  var component = this.subject();
+
+  var min = moment('04/11/2014', 'DD/MM/YYYY');
+  var max = moment('04/12/2014', 'DD/MM/YYYY');
+  var from = moment('04/11/2014', 'DD/MM/YYYY');
+  var to = moment('04/12/2014', 'DD/MM/YYYY');
+
+  var dateRange = Ember.Object.create({
+    from: from.toString(),
+    to: to.toString(),
+    min: min.toString(),
+    max: max.toString()
+  });
+
+  Ember.run(function () {
+    component.set('dateRange', dateRange);
+  });
+
+  equal(component.get('displayFromDate'), '11/04/2014', "displayFromDate is formatted correctly");
+  equal(component.get('displayToDate'), '12/04/2014', "displayToDate is formatted correctly");
+});
+
+test('If from/to are not passed they are set to min/max', function() {
+  expect(2);
+
+  var component = this.subject();
+
+  var min = moment('04/11/2014', 'DD/MM/YYYY');
+  var max = moment('04/12/2014', 'DD/MM/YYYY');
+
+  var dateRange = Ember.Object.create({
+    min: min.toString(),
+    max: max.toString()
+  });
+
+  Ember.run(function () {
+    component.set('dateRange', dateRange);
+  });
+
+  var $component = this.$();
+
+  equal(component.get('dateRange.from'), min.toString(), "From date is to min date");
+  equal(component.get('dateRange.to'), max.toString(), "To date is set to max date");
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/expander-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/expander-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/expander-widget-test.js
new file mode 100644
index 0000000..8d1f07a
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/expander-widget-test.js
@@ -0,0 +1,59 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('expander-widget', 'ExpanderWidgetComponent', {
+  unit: true
+});
+
+test('should set the heading when provided.', function () {
+  expect(2);
+
+  var component = this.subject();
+  var $component = this.$();
+  var heading = 'some header';
+
+  equal($component.find('.accordion-toggle').text(), '');
+
+  Ember.run(function () {
+    component.set('heading', heading);
+  });
+
+  equal($component.find('.accordion-toggle').text(), heading);
+});
+
+test('should correctly toggle isExpanded property.', function () {
+  expect(2);
+
+  var component = this.subject();
+  this.$();
+
+  Ember.run(function(){
+    component.send('toggle');
+  });
+
+  equal(component.get('isExpanded'), true);
+
+  Ember.run(function(){
+    component.send('toggle');
+  });
+
+  equal(component.get('isExpanded'), false);
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/extended-input-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/extended-input-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/extended-input-test.js
new file mode 100644
index 0000000..aa861aa
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/extended-input-test.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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('extended-input', 'ExtendedInputComponent', {
+  unit: true
+});
+
+test('Component has dynamicValue and dynamicContext', function () {
+  expect(1);
+
+  var component = this.subject({
+    dynamicValue: 'dynamicValue',
+    dynamicContext: Ember.Object.create({ 'dynamicValue' : 'test' })
+  });
+
+  var $component = this.$();
+
+  equal(component.get('value'), 'test', 'Value is set to dynamicValue value');
+});
+
+
+test('Component has no dynamicValue and dynamicContext', function () {
+  expect(1);
+
+  var component = this.subject();
+  var $component = this.$();
+
+  ok(!component.get('value'), 'Value is not set as dynamicValue value');
+});
+
+test("Component's dynamicValue is set", function () {
+  expect(1);
+
+  var component = this.subject({
+    dynamicValue: 'dynamicValue',
+    dynamicContext: Ember.Object.create({ 'dynamicValue' : 'test' })
+  });
+
+  var $component = this.$();
+
+  Ember.run(function() {
+    component.sendValueChanged();
+
+    equal(component.get('value'), component.dynamicContext.get('dynamicValue'), "Value is set and dynamicValue is set");
+  });
+});
+
+test("Component's dynamicValue is not set", function () {
+  expect(1);
+
+  var component = this.subject({
+    dynamicValue: 'dynamicValue',
+    dynamicContext: Ember.Object.create({ })
+  });
+
+  var $component = this.$();
+
+  Ember.run(function() {
+    component.sendValueChanged();
+
+    equal(component.get('value'), undefined, "Value is not set");
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/job-tr-view-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/job-tr-view-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/job-tr-view-test.js
new file mode 100644
index 0000000..d39a85e
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/job-tr-view-test.js
@@ -0,0 +1,62 @@
+/**
+ * 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 constants from 'hive/utils/constants';
+import { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('job-tr-view', 'JobTrViewComponent', {
+  unit: true
+});
+
+test('Statuses are computed correctly', function (assert) {
+  assert.expect(5);
+
+  var component = this.subject();
+
+  Ember.run(function() {
+    component.set('job', Ember.Object.create());
+    component.set('job.status', constants.statuses.running);
+  });
+
+  assert.equal(component.get('canStop'), true, 'Status is running canStop returns true');
+
+  Ember.run(function() {
+    component.set('job.status', constants.statuses.initialized);
+  });
+
+  assert.equal(component.get('canStop'), true, 'Status is initialized canStop returns true');
+
+  Ember.run(function() {
+    component.set('job.status', constants.statuses.pending);
+  });
+
+  assert.equal(component.get('canStop'), true, 'Status is pending canStop returns true');
+
+  Ember.run(function() {
+    component.set('job.status', constants.statuses.canceled);
+  });
+
+  assert.equal(component.get('canStop'), false, 'Status is canceled canStop returns false');
+
+  Ember.run(function() {
+    component.set('job.status', constants.statuses.unknown);
+  });
+
+  assert.equal(component.get('canStop'), false, 'Status is unknown canStop returns false');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/modal-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/modal-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/modal-widget-test.js
new file mode 100644
index 0000000..3016444
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/modal-widget-test.js
@@ -0,0 +1,69 @@
+/**
+ * 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 constants from 'hive/utils/constants';
+import { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('modal-widget', 'ModalWidgetComponent', {
+  needs: ['helper:tb-helper']
+});
+
+test('It send ok action on keyPress enter', function(assert) {
+  assert.expect(1);
+
+  Ember.run.debounce = function(target, func) {
+    func.call(target);
+  };
+
+  var component = this.subject({
+    ok: 'ok',
+    targetObject: {
+      ok: function() {
+        assert.ok(1, 'OK action sent');
+      }
+    }
+  });
+
+  var $component = this.$();
+
+  component.keyPress({ which: 13 });
+  Ember.$('.modal-backdrop').remove(); // remove overlay
+});
+
+test('It send close action on keyPress escape', function(assert) {
+  assert.expect(1);
+
+  Ember.run.debounce = function(target, func) {
+    func.call(target);
+  };
+
+  var component = this.subject({
+    close: 'close',
+    targetObject: {
+      close: function() {
+        assert.ok(1, 'Close action sent');
+      }
+    }
+  });
+
+  var $component = this.$();
+
+  component.keyPress({ which: 27 });
+  Ember.$('.modal-backdrop').remove(); // remove overlay
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/no-bubbling-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/no-bubbling-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/no-bubbling-test.js
new file mode 100644
index 0000000..47a1a0f
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/no-bubbling-test.js
@@ -0,0 +1,44 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('no-bubbling', 'NoBubblingWidgetComponent', {
+  unit: true
+});
+
+
+test('External actions', function() {
+  expect(2);
+
+  var component = this.subject({
+    targetObject: {
+      click: function(data) {
+        ok(true, 'External click action called');
+        equal(data, 'data', 'Data is sent with the action');
+      }
+    },
+    click: 'click',
+    data: 'data'
+  });
+
+  var $component = this.$();
+
+  $component.trigger('click');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/number-range-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/number-range-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/number-range-widget-test.js
new file mode 100644
index 0000000..edc65b1
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/number-range-widget-test.js
@@ -0,0 +1,70 @@
+/**
+ * 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.
+ */
+
+/* global moment */
+
+import Ember from 'ember';
+import { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('number-range-widget', 'NumberRangeWidgetComponent', {
+  needs: ['component:extended-input']
+});
+
+
+test('Component is initialized correctly', function() {
+  expect(2);
+
+  var numberRange = Ember.Object.create({
+    max: 1,
+    min: 0
+  });
+
+  var component = this.subject({ numberRange: numberRange });
+  var $component = this.$();
+
+  equal(component.get('numberRange.from'), numberRange.get('min'), 'from is set to min');
+  equal(component.get('numberRange.to'), numberRange.get('max'), 'to is set to max');
+
+});
+
+test('external change action is called', function() {
+  expect(1);
+
+  var targetObject = {
+    rangeChanged: function() {
+      ok(true, 'rangeChanged external action called');
+    }
+  };
+
+  var numberRange = Ember.Object.create({
+    max: 1,
+    min: 0
+  });
+
+  var component = this.subject({
+    numberRange: numberRange,
+    targetObject: targetObject,
+    rangeChanged: 'rangeChanged'
+  });
+
+  var $component = this.$();
+
+  Ember.run(function() {
+    $component.find('.slider').slider('value', 1);
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/popover-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/popover-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/popover-widget-test.js
new file mode 100644
index 0000000..84bec76
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/popover-widget-test.js
@@ -0,0 +1,36 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('popover-widget', 'PopoverWidgetComponent', {
+  unit: true
+});
+
+test('Component initializes correctly', function () {
+  expect(2);
+
+  var component = this.subject({
+    template: Ember.Handlebars.compile("test")
+  });
+  var $component = this.$();
+
+  ok($component, "Popover element is initialized");
+  equal($component.attr('data-content').trim(), "test", "data-content is populated");
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/progress-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/progress-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/progress-widget-test.js
new file mode 100644
index 0000000..3984f62
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/progress-widget-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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('progress-widget', 'ProgressWidgetComponent', {
+  unit: true
+});
+
+test('Percentage is updated on value change', function() {
+  var component = this.subject({
+    value: 0
+  });
+
+  this.$();
+
+  equal(component.get('percentage'), '0%', 'Progress is at 0%');
+
+  Ember.run(function() {
+    component.set('value', 50);
+  });
+
+  equal(component.get('percentage'), '50%', 'Progress is at 50%');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/query-editor-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/query-editor-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/query-editor-test.js
new file mode 100644
index 0000000..e70b5ee
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/query-editor-test.js
@@ -0,0 +1,52 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('query-editor', 'QueryEditorComponent', {
+  unit: true
+});
+
+test('initEditor sets the editor on didInsertElement', function () {
+  expect(2);
+
+  var component = this.subject();
+
+  equal(component.get('editor'), undefined, 'element not rendered. Editor not set.');
+
+  this.$();
+
+  ok(component.get('editor'), 'element rendered. Editor set.');
+});
+
+test('updateValue sets the query value on the editor.', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var query = 'select something';
+
+  this.$();
+
+  Ember.run(function () {
+    component.set(('query'), query);
+  });
+
+  equal(component.get('editor').getValue(), query, 'set query property. Updated editor value property.');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/select-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/select-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/select-widget-test.js
new file mode 100644
index 0000000..a186508
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/select-widget-test.js
@@ -0,0 +1,158 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('select-widget', 'SelectWidgetComponent', {
+  needs: ['helper:path-binding']
+});
+
+test('selectedLabel returns the selectedValue property indicated by labelPath if selectedValue and labelPath are set.', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var selectedValue = Ember.Object.extend({
+    label: 'db'
+  }).create();
+
+  var labelPath = 'label';
+
+  Ember.run(function () {
+    component.set('labelPath', labelPath);
+    component.set('selectedValue', selectedValue);
+  });
+
+  equal(component.get('selectedLabel'), selectedValue.label, 'selectedValue and labelPath are set. selectedLabel returns selectedValue[labelPath].');
+});
+
+test('selectedLabel returns defaultLabel if selectedValue is falsy and defaultLabel is set.', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  var defaultLabel = 'select...';
+
+  Ember.run(function () {
+    component.set('defaultLabel', defaultLabel);
+  });
+
+  equal(component.get('selectedLabel'), defaultLabel, 'selectedValue falsy and defaultLabel set. selectedLabel returns defaultLabel.');
+});
+
+test('selectedLabel returns undefined if neither selectedValue nor defaultLabel are set.', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  equal(component.get('selectedLabel'), undefined, 'selectedValue and defaultLabel are falsy. selectedLabel returns undefined.');
+});
+
+test('selectedLabel is computed when selectedValue changes.', function () {
+  expect(2);
+
+  var component = this.subject();
+
+  var selectedValue = Ember.Object.extend({
+    label: 'db'
+  }).create();
+
+  var labelPath = 'label';
+
+  equal(component.get('selectedLabel'), undefined, 'selectedValue and defaultLabel are falsy. selectedLabel returns undefined.');
+
+  Ember.run(function () {
+    component.set('labelPath', labelPath);
+    component.set('selectedValue', selectedValue);
+  });
+
+  equal(component.get('selectedLabel'), selectedValue.label, 'selectedValue and labelPath are set. selectedLabel returns selectedValue[labelPath].');
+});
+
+test('renders an li tag for each item in the items collection.', function () {
+  expect(2);
+
+  var component = this.subject();
+  var $component = this.$();
+
+  equal($component.find('li').length, 0, 'items collection is not set. No li tags are rendered.');
+
+  Ember.run(function() {
+    var items = Ember.ArrayProxy.create({ content: Ember.A([Ember.Object.create(), Ember.Object.create()])});
+    component.set('labelPath', 'name');
+    component.set('items', items);
+  });
+
+  equal($component.find('li').length, 2, 'items collection is set containing one item. One li tag is rendered.');
+});
+
+test('if no selected item nor defaultLabel set the selected value with first item', function () {
+  expect(1);
+
+  var items = [
+    'item1',
+    'item2'
+  ];
+
+  var component = this.subject({ items: items });
+  var $component = this.$();
+
+  equal(component.get('selectedValue'), 'item1', 'selectedValue is set to first item')
+});
+
+test('component actions', function() {
+  expect(7);
+
+  var targetObject = {
+    itemAdded: function() {
+      ok(true, 'External action itemAdded called')
+    },
+    itemEdited: function(item) {
+      ok(true, 'External action itemEdited called');
+      equal(item, 'editedItem', 'Data is sent with action');
+    },
+    itemRemoved: function(item) {
+      ok(true, 'External action itemRemoved called');
+      equal(item, 'removedItem', 'Data is sent with action');
+    }
+  };
+  var component = this.subject({
+    items: ['item'],
+    itemAdded: 'itemAdded',
+    itemEdited: 'itemEdited',
+    itemRemoved: 'itemRemoved',
+    targetObject: targetObject
+  });
+
+  var $component = this.$();
+
+  equal(component.get('selectedValue'), 'item', 'selectedValue is set to first item');
+
+  Ember.run(function() {
+    component.send('select', 'newItem');
+    component.send('add');
+    component.send('edit', 'editedItem');
+    component.send('remove', 'removedItem');
+  });
+
+  equal(component.get('selectedValue'), 'newItem', 'selectedValue is set to newItem');
+
+
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/tabs-wiget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/tabs-wiget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/tabs-wiget-test.js
new file mode 100644
index 0000000..17b2242
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/tabs-wiget-test.js
@@ -0,0 +1,117 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('tabs-widget', 'TabsWidgetComponent', {
+  needs: []
+});
+
+test('First tab active by default', function() {
+  expect(2);
+
+  var tabs = Ember.ArrayProxy.create({content: Ember.A([
+    Ember.Object.create(),
+    Ember.Object.create()
+  ])});
+
+  var component = this.subject({ tabs: tabs });
+  var $component = this.$();
+
+  ok(component.get('tabs.firstObject.active'), 'First tab is active');
+  ok(!component.get('tabs.lastObject.active'), 'Second tab is not active');
+});
+
+
+test('Set active tab on init', function() {
+  expect(2);
+
+  var tabs = Ember.ArrayProxy.create({content: Ember.A([
+    Ember.Object.create(),
+    Ember.Object.create(),
+    Ember.Object.create({ active: true })
+  ])});
+
+  var component = this.subject({ tabs: tabs });
+
+  ok(!component.get('tabs.firstObject.active'), 'First tab is not active');
+  ok(component.get('tabs.lastObject.active'), 'Last tab is active');
+});
+
+
+test('Set active tab', function() {
+  expect(3);
+
+  var tabs = Ember.ArrayProxy.create({content: Ember.A([
+    Ember.Object.create(),
+    Ember.Object.create(),
+    Ember.Object.create({ active: true })
+  ])});
+
+  var component = this.subject({ tabs: tabs });
+
+  ok(!component.get('tabs.firstObject.active'), 'First tab is not active');
+  ok(component.get('tabs.lastObject.active'), 'Last tab is active');
+
+  Ember.run(function() {
+    component.send('selectTab', tabs.objectAt(1));
+  });
+
+  ok(component.get('tabs').objectAt(1).get('active'), 'Second tab is active');
+});
+
+test('removeEnabled tabs', function() {
+  expect(2);
+
+  var tabs = Ember.ArrayProxy.create({content: Ember.A([
+    Ember.Object.create(),
+    Ember.Object.create(),
+    Ember.Object.create({ active: true })
+  ])});
+
+  var component = this.subject({ tabs: tabs, canRemove: true });
+
+  ok(component.get('removeEnabled'), 'More than one tab removeEnabled returns true');
+
+  Ember.run(function() {
+    component.get('tabs').popObject();
+    component.get('tabs').popObject();
+  });
+
+  ok(!component.get('removeEnabled'), 'Only one tab removeEnabled returns false');
+});
+
+test('remove tab', function () {
+  expect(1);
+
+  var targetObject = {
+    removeTabAction: function() {
+      ok(true, 'External remove tab action called');
+    }
+  };
+
+  var component = this.subject({
+    'removeClicked': 'removeTabAction',
+    'targetObject': targetObject
+  });
+
+  Ember.run(function() {
+    component.send('remove', {});
+  });
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/typeahead-widget-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/typeahead-widget-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/typeahead-widget-test.js
new file mode 100644
index 0000000..7d989a4
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/components/typeahead-widget-test.js
@@ -0,0 +1,46 @@
+/**
+ * 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 { moduleForComponent, test } from 'ember-qunit';
+
+moduleForComponent('typeahead-widget', 'TypeaheadWidgetComponent', {
+  needs: ['component:ember-selectize']
+});
+
+test('Component is initialized correctly', function () {
+  expect(2);
+
+  var items = [
+    {name: 'item 1', id: 1},
+    {name: 'item 2', id: 2},
+    {name: 'item 3', id: 3},
+    {name: 'item 4', id: 4}
+  ];
+
+  var component = this.subject({
+    content: items,
+    optionValuePath: 'content.id',
+    optionLabelPath: 'content.name'
+  });
+
+  this.$();
+
+  equal(component.get('content.length'), items.length, 'Items are set');
+  equal(component.get('selection'), items[0], 'First object is set as default value');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/databases-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/databases-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/databases-test.js
new file mode 100644
index 0000000..c3ac272
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/databases-test.js
@@ -0,0 +1,276 @@
+/**
+ * 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';
+
+var controller;
+var store;
+
+moduleFor('controller:databases', 'DatabasesController', {
+  needs: [ 'adapter:database',
+           'service:database',
+           'service:notify',
+           'model:database' ],
+
+  setup: function () {
+    //mock getDatabases which is called on controller init
+    this.container.lookup('service:database').getDatabases = function () {
+      var defer = Ember.RSVP.defer();
+
+      defer.resolve();
+
+      return defer.promise;
+    };
+
+    //mock getDatabasesFromServer which is called by the poller
+    this.container.lookup('service:database').getDatabasesFromServer = function () {
+     var defer = Ember.RSVP.defer();
+
+     var databases = [ "database_a", "database_b"];
+
+     defer.resolve(databases);
+     return defer.promise;
+     };
+
+    store = this.container.lookup('store:main');
+    controller = this.subject();
+    controller.store = store;
+
+  },
+
+  teardown: function () {
+    Ember.run(controller, controller.destroy);
+  }
+});
+
+test('controller is initialized properly.', function () {
+  expect(5);
+
+  var controller = this.subject();
+
+  ok(controller.get('tableSearchResults'), 'table search results collection was initialized.');
+  ok(controller.get('tabs'), 'tabs collection was initialized.');
+  equal(controller.get('tabs.length'), 2, 'tabs collection contains two tabs');
+  equal(controller.get('tabs').objectAt(0).get('name'), Ember.I18n.t('titles.explorer'), 'first tab is database explorer.');
+  equal(controller.get('tabs').objectAt(1).get('name'), Ember.I18n.t('titles.results'), 'second tab is search results');
+});
+
+test('setTablePageAvailability sets canGetNextPage true if given database hasNext flag is true.', function () {
+  expect(1);
+
+  var database = Ember.Object.create( { hasNext: true } );
+
+  controller.setTablePageAvailability(database);
+
+  equal(database.get('canGetNextPage'), true);
+});
+
+test('setTablePageAvailability sets canGetNextPage true if given database has more loaded tables than the visible ones.', function () {
+  expect(1);
+
+  var database = Ember.Object.create({
+    tables: [1],
+    visibleTables: []
+  });
+
+  controller.setTablePageAvailability(database);
+
+  equal(database.get('canGetNextPage'), true);
+});
+
+test('setTablePageAvailability sets canGetNextPage falsy if given database hasNext flag is falsy and all loaded tables are visible.', function () {
+  expect(1);
+
+  var database = Ember.Object.create({
+    tables: [1],
+    visibleTables: [1]
+  });
+
+  controller.setTablePageAvailability(database);
+
+  ok(!database.get('canGetNextPage'));
+});
+
+test('setColumnPageAvailability sets canGetNextPage true if given table hasNext flag is true.', function () {
+  expect(1);
+
+  var table = Ember.Object.create( { hasNext: true } );
+
+  controller.setColumnPageAvailability(table);
+
+  equal(table.get('canGetNextPage'), true);
+});
+
+test('setColumnPageAvailability sets canGetNextPage true if given table has more loaded columns than the visible ones.', function () {
+  expect(1);
+
+  var table = Ember.Object.create({
+    columns: [1],
+    visibleColumns: []
+  });
+
+  controller.setColumnPageAvailability(table);
+
+  equal(table.get('canGetNextPage'), true);
+});
+
+test('setColumnPageAvailability sets canGetNextPage true if given database hasNext flag is falsy and all loaded columns are visible.', function () {
+  expect(1);
+
+  var table = Ember.Object.create({
+    columns: [1],
+    visibleColumns: [1]
+  });
+
+  controller.setColumnPageAvailability(table);
+
+  ok(!table.get('canGetNextPage'));
+});
+
+test('getTables sets the visibleTables as the first page of tables if they are already loaded', function () {
+  expect(2);
+
+  var database = Ember.Object.create({
+    name: 'test_db',
+    tables: [1, 2, 3]
+  });
+
+  controller.get('databases').pushObject(database);
+  controller.set('pageCount', 2);
+
+  controller.send('getTables', 'test_db');
+
+  equal(database.get('visibleTables.length'), controller.get('pageCount'), 'there are 2 visible tables out of 3.');
+  equal(database.get('canGetNextPage'), true, 'user can get next tables page.');
+});
+
+test('getColumns sets the visibleColumns as the first page of columns if they are already loaded.', function () {
+  expect(2);
+
+  var table = Ember.Object.create({
+    name: 'test_table',
+    columns: [1, 2, 3]
+  });
+
+  var database = Ember.Object.create({
+    name: 'test_db',
+    tables: [ table ],
+    visibleTables: [ table ]
+  });
+
+  controller.set('pageCount', 2);
+
+  controller.send('getColumns', 'test_table', database);
+
+  equal(table.get('visibleColumns.length'), controller.get('pageCount'), 'there are 2 visible columns out of 3.');
+  equal(table.get('canGetNextPage'), true, 'user can get next columns page.');
+});
+
+test('showMoreTables pushes more tables to visibleTables if there are still hidden tables loaded.', function () {
+  expect(2);
+
+  var database = Ember.Object.create({
+    name: 'test_db',
+    tables: [1, 2, 3],
+    visibleTables: [1]
+  });
+
+  controller.get('databases').pushObject(database);
+  controller.set('pageCount', 1);
+
+  controller.send('showMoreTables', database);
+
+  equal(database.get('visibleTables.length'), controller.get('pageCount') * 2, 'there are 2 visible tables out of 3.');
+  equal(database.get('canGetNextPage'), true, 'user can get next tables page.');
+});
+
+test('showMoreColumns pushes more columns to visibleColumns if there are still hidden columns loaded.', function () {
+  expect(2);
+
+  var table = Ember.Object.create({
+    name: 'test_table',
+    columns: [1, 2, 3],
+    visibleColumns: [1]
+  });
+
+  var database = Ember.Object.create({
+    name: 'test_db',
+    tables: [ table ],
+    visibleTables: [ table ]
+  });
+
+  controller.set('pageCount', 1);
+
+  controller.send('showMoreColumns', table, database);
+
+  equal(table.get('visibleColumns.length'), controller.get('pageCount') * 2, 'there are 2 visible columns out of 3.');
+  equal(table.get('canGetNextPage'), true, 'user can get next columns page.');
+});
+
+test('syncDatabases pushed more databases when new databases are added in the backend', function() {
+  expect(3);
+
+  var databaseA = {
+    id: "database_a",
+    name: "database_a"
+  };
+
+  Ember.run(function() {
+    store.createRecord('database', databaseA);
+    controller.syncDatabases();
+  });
+
+  var latestDbNames = store.all('database').mapBy('name');
+  equal(latestDbNames.length, 2, "There is 1 additional database added to hive");
+  equal(latestDbNames.contains("database_a"), true, "New database list should contain the old database name.");
+  equal(latestDbNames.contains("database_b"), true, "New database list should contain the new database name.");
+});
+
+test('syncDatabases removed database when old databases are removed in the backend', function() {
+  expect(4);
+
+  var latestDbNames;
+
+  var databaseA = {
+    id: "database_a",
+    name: "database_a"
+  };
+  var databaseB = {
+    id: "database_b",
+    name: "database_b"
+  };
+  var databaseC = {
+    id: "database_c",
+    name: "database_c"
+  };
+
+  Ember.run(function() {
+    store.createRecord('database', databaseA);
+    store.createRecord('database', databaseB);
+    store.createRecord('database', databaseC);
+    controller.syncDatabases();
+  });
+
+  latestDbNames = store.all('database').mapBy('name');
+  equal(latestDbNames.length, 2, "One database is removed from hive");
+  equal(latestDbNames.contains("database_a"), true, "New database list should contain the old database name.");
+  equal(latestDbNames.contains("database_b"), true, "New database list should contain the old database name.");
+  equal(latestDbNames.contains("database_c"), false, "New database list should not contain the database name removed in the backend.");
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/history-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/history-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/history-test.js
new file mode 100644
index 0000000..ab45214
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/history-test.js
@@ -0,0 +1,117 @@
+/**
+ * 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('controller:history', 'HistoryController', {
+  needs: [ 'service:file', 'service:job' ]
+});
+
+test('controller is initialized correctly', function () {
+  expect(1);
+
+  var component = this.subject();
+
+  equal(component.get('columns.length'), 4, 'Columns are initialized');
+});
+
+test('date range is set correctly', function () {
+  expect(2);
+
+  var component = this.subject();
+  var min = parseInt(Date.now() / 1000) - (60 * 60 * 24 * 60);
+  var max = parseInt(Date.now() / 1000);
+
+  var history = Ember.ArrayProxy.create({ content: [
+    Ember.Object.create({
+      dateSubmittedTimestamp: min
+    }),
+    Ember.Object.create({
+      dateSubmittedTimestamp: max
+    })
+  ]});
+
+  Ember.run(function() {
+    component.set('history', history);
+  });
+
+  var dateColumn = component.get('columns').find(function (column) {
+    return column.get('caption') === 'columns.date';
+  });
+
+  equal(dateColumn.get('dateRange.min'), min, 'Min date is set correctly');
+  equal(dateColumn.get('dateRange.max'), max, 'Max date is set correctly');
+});
+
+test('interval duration is set correctly', function () {
+  expect(2);
+
+  var component = this.subject();
+
+  var history = Ember.ArrayProxy.create({ content: [
+    Ember.Object.create({
+      duration: 20
+    }),
+    Ember.Object.create({
+      duration: 300
+    })
+  ]});
+
+  Ember.run(function() {
+    component.set('history', history);
+  });
+
+  var durationColumn = component.get('columns').find(function (column) {
+    return column.get('caption') === 'columns.duration';
+  });
+
+  equal(durationColumn.get('numberRange.min'), 20, 'Min value is set correctly');
+  equal(durationColumn.get('numberRange.max'), 300, 'Max value is set correctly');
+});
+
+test('history filtering', function() {
+  expect(2);
+
+  var component = this.subject();
+
+  var history = Ember.ArrayProxy.create({
+    content: [
+      Ember.Object.create({
+        name: 'HISTORY',
+        status: 1
+      }),
+      Ember.Object.create({
+        name: '1HISTORY',
+        status: 2
+      })
+    ]
+  });
+
+  Ember.run(function() {
+    component.set('history', history);
+  });
+
+  equal(component.get('model.length'), 2, 'No filters applied we have 2 models');
+
+  Ember.run(function() {
+    component.filterBy('name', 'HISTORY', true);
+  });
+
+  equal(component.get('model.length'), 1, 'Filter by name we have 1 filtered model');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
new file mode 100644
index 0000000..290f61e
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/index-test.js
@@ -0,0 +1,328 @@
+/**
+ * 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';
+import constants from 'hive/utils/constants';
+
+moduleFor('controller:index', 'IndexController', {
+  needs: [
+          'controller:open-queries',
+          'controller:udfs',
+          'controller:index/history-query/logs',
+          'controller:index/history-query/results',
+          'controller:index/history-query/explain',
+          'controller:settings',
+          'controller:visual-explain',
+          'controller:tez-ui',
+          'service:job',
+          'service:file',
+          'service:database',
+          'service:notify',
+          'service:job-progress',
+          'service:session',
+          'service:settings',
+          'adapter:application',
+          'adapter:database'
+        ]
+});
+
+test('modelChanged calls update on the open-queries cotnroller.', function () {
+  expect(1);
+
+  var controller = this.subject();
+
+  controller.set('openQueries.update', function () {
+    var defer = Ember.RSVP.defer();
+
+    ok(true, 'index model has changed. update was called on open-queries controller.');
+
+    defer.resolve();
+
+    return defer.promise;
+  });
+
+  Ember.run(function () {
+    controller.set('model', Ember.Object.create());
+  });
+});
+
+test('bindQueryParams replaces param placeholder with values', function() {
+  expect(1);
+
+  var controller = this.subject();
+  var queryParams = [
+    { name: '$what', value: 'color' },
+    { name: '$where', value: 'z'}
+  ];
+
+  var query = "select $what from $where";
+  var replacedQuery = "select color from z";
+
+  Ember.run(function() {
+    controller.get('queryParams').setObjects(queryParams);
+  });
+
+  equal(controller.bindQueryParams(query), replacedQuery, 'Params replaced correctly');
+});
+
+test('bindQueryParams replaces same param multiple times', function() {
+  expect(1);
+
+  var controller = this.subject();
+  var queryParams = [
+    { name: '$what', value: 'color' },
+    { name: '$where', value: 'z'}
+  ];
+
+  var query = "select $what from $where as $what";
+  var replacedQuery = "select color from z as color";
+
+  Ember.run(function() {
+    controller.get('queryParams').setObjects(queryParams);
+  });
+
+  equal(controller.bindQueryParams(query), replacedQuery, 'Params replaced correctly');
+});
+
+test('parseQueryParams sets queryParams when query changes', function() {
+  expect(4);
+
+
+  var query = Ember.Object.create({
+    id: 1,
+    fileContent: "select $what from $where"
+  });
+  var updatedQuery = "select $what from $where and $where";
+
+  var controller = this.subject({
+    model: query
+  });
+
+  Ember.run(function() {
+    controller.set('openQueries.queryTabs', [query]);
+    controller.set('openQueries.currentQuery', query);
+  });
+
+  equal(controller.get('queryParams.length'), 2, '2 queryParams parsed');
+  equal(controller.get('queryParams').objectAt(0).name, '$what', 'First param parsed correctly');
+  equal(controller.get('queryParams').objectAt(1).name, '$where', 'Second param parsed correctly');
+
+  Ember.run(function() {
+    controller.set('openQueries.currentQuery.fileContent', updatedQuery);
+  });
+
+  equal(controller.get('queryParams.length'), 2, 'Can use same param multiple times');
+});
+
+test('canExecute return false if query is executing', function() {
+  expect(2);
+  var controller = this.subject();
+
+  Ember.run(function() {
+    controller.set('openQueries.update', function () {
+      var defer = Ember.RSVP.defer();
+      defer.resolve();
+      return defer.promise;
+    });
+
+    controller.set('model', Ember.Object.create({ 'isRunning': false }));
+    controller.set('queryParams', []);
+  });
+
+  ok(controller.get('canExecute'), 'Query is not executing => canExecute return true');
+
+  Ember.run(function() {
+    controller.set('model', Ember.Object.create({ 'isRunning': true }));
+  });
+
+  ok(!controller.get('canExecute'), 'Query is executing => canExecute return false');
+});
+
+test('canExecute return false if queryParams doesnt\'t have values', function() {
+  expect(2);
+  var controller = this.subject();
+
+  var paramsWithoutValues = [
+    { name: '$what', value: '' },
+    { name: '$where', value: '' }
+  ];
+
+  var paramsWithValues = [
+    { name: '$what', value: 'value1' },
+    { name: '$where', value: 'value2' }
+  ];
+
+  Ember.run(function() {
+    controller.set('openQueries.update', function () {
+      var defer = Ember.RSVP.defer();
+      defer.resolve();
+      return defer.promise;
+    });
+    controller.set('model', Ember.Object.create({ 'isRunning': false }));
+    controller.get('queryParams').setObjects(paramsWithoutValues);
+  });
+
+  ok(!controller.get('canExecute'), 'Params without value => canExecute return false');
+
+  Ember.run(function() {
+    controller.get('queryParams').setObjects(paramsWithValues);
+  });
+
+  ok(controller.get('canExecute'), 'Params with values => canExecute return true');
+});
+
+test('Execute EXPLAIN type query', function() {
+  expect(1);
+
+  var query = Ember.Object.create({
+    id: 1,
+    fileContent: "explain select 1" // explain type query
+  });
+
+  var controller = this.subject({
+    model: query,
+    _executeQuery: function (referer) {
+      equal(referer, constants.jobReferrer.explain, 'Explain type query successful.');
+      return {then: function() {}};
+    }
+  });
+
+  Ember.run(function() {
+      controller.set('openQueries.queryTabs', [query]);
+      controller.set('openQueries.currentQuery', query);
+      controller.send('executeQuery');
+  });
+
+});
+
+test('Execute non EXPLAIN type query', function() {
+  expect(1);
+
+  var query = Ember.Object.create({
+    id: 1,
+    fileContent: "select 1" //non explain type query
+  });
+
+  var controller = this.subject({
+    model: query,
+    _executeQuery: function (referer) {
+      equal(referer, constants.jobReferrer.job , 'non Explain type query successful.');
+      return {then: function() {}};
+    }
+  });
+
+  Ember.run(function() {
+      controller.set('openQueries.queryTabs', [query]);
+      controller.set('openQueries.currentQuery', query);
+      controller.send('executeQuery');
+  });
+
+});
+
+
+test('csvUrl returns if the current query is not a job', function() {
+  expect(1);
+  var content = Ember.Object.create({
+      constructor: {
+        typeKey: 'notJob'
+      }
+  });
+
+  var controller = this.subject({ content: content });
+  ok(!controller.get('csvUrl'), 'returns if current query is not a job');
+});
+
+test('csvUrl returns is status in not SUCCEEDED', function() {
+  expect(1);
+  var content= Ember.Object.create({
+      constructor: {
+        typeKey: 'job'
+      },
+      status: 'notSuccess'
+  });
+
+  var controller = this.subject({ content: content });
+  ok(!controller.get('csvUrl'), 'returns if current status is not success');
+});
+
+test('csvUrl return the download results as csv link', function() {
+  expect(1);
+  var content = Ember.Object.create({
+      constructor: {
+        typeKey: 'job'
+      },
+      status: 'SUCCEEDED',
+      id: 1
+  });
+
+  var controller = this.subject({ content: content });
+  ok(controller.get('csvUrl'));
+});
+
+test('donwloadMenu returns null if status is not succes and results are not visible ', function() {
+  expect(1);
+  var content = Ember.Object.create({
+      status: 'notSuccess',
+      queryProcessTabs: [{
+        path: 'index.historyQuery.results',
+        visible: false
+      }]
+  });
+
+  var controller = this.subject({ content: content });
+  ok(!controller.get('downloadMenu'), 'Returns null');
+});
+
+test('donwloadMenu returns only saveToHDFS if csvUrl is false', function() {
+  expect(1);
+  var content = Ember.Object.create({
+      constructor: {
+        typeKey: 'notjob'
+      },
+      status: 'SUCCEEDED',
+  });
+
+  var controller = this.subject({ content: content });
+  Ember.run(function() {
+    var tabs = controller.get('queryProcessTabs');
+    var results = tabs.findBy('path', 'index.historyQuery.results');
+    results.set('visible', true);
+  });
+
+  equal(controller.get('downloadMenu.length'), 1, 'Returns only saveToHDFS');
+});
+
+test('donwloadMenu returns saveToHDFS and csvUrl', function() {
+  expect(1);
+  var content = Ember.Object.create({
+      constructor: {
+        typeKey: 'job'
+      },
+      status: 'SUCCEEDED',
+  });
+
+  var controller = this.subject({ content: content });
+  Ember.run(function() {
+    var tabs = controller.get('queryProcessTabs');
+    var results = tabs.findBy('path', 'index.historyQuery.results');
+    results.set('visible', true);
+  });
+
+  equal(controller.get('downloadMenu.length'), 2, 'Returns saveToHDFS and csvUrl');
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/9dc382a5/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
new file mode 100644
index 0000000..e770bdd
--- /dev/null
+++ b/contrib/views/hive-next/src/main/resources/ui/hive-web/tests/unit/controllers/insert-udfs-test.js
@@ -0,0 +1,68 @@
+/**
+ * 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('controller:insert-udfs', 'InsertUdfsController', {
+  needs: 'controller:udfs'
+});
+
+test('controller is initialized correctly', function () {
+  expect(1);
+
+  var udfs = Ember.A([
+    Ember.Object.create({ fileResource: { id: 1 } }),
+    Ember.Object.create({ fileResource: { id: 1 } }),
+    Ember.Object.create({ fileResource: { id: 2 } }),
+    Ember.Object.create({ fileResource: { id: 2 } })
+  ]);
+
+  var component = this.subject();
+
+  Ember.run(function() {
+    component.set('udfs', udfs);
+  });
+
+  equal(component.get('length'), 2, 'should contain unique file resources');
+});
+
+test('controller updates on new udfs', function () {
+  expect(2);
+
+  var udfs = Ember.A([
+    Ember.Object.create({ fileResource: { id: 1 } }),
+    Ember.Object.create({ fileResource: { id: 2 } }),
+  ]);
+
+  var component = this.subject();
+
+  Ember.run(function() {
+    component.set('udfs', udfs);
+  });
+
+  equal(component.get('length'), 2, '');
+
+  var newUdf = Ember.Object.create({ isNew: true, fileResource: { id: 3 } });
+
+  Ember.run(function() {
+    component.get('udfs').pushObject(newUdf);
+  });
+
+  equal(component.get('length'), 3, '');
+});


Mime
View raw message