You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2016/03/28 11:46:37 UTC

[1/3] ambari git commit: AMBARI-15596. Add missing unit tests files for ambari-web utils (alexantonenko)

Repository: ambari
Updated Branches:
  refs/heads/trunk aa033d0c1 -> d5d1afea8


http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/polling_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/polling_test.js b/ambari-web/test/utils/polling_test.js
new file mode 100644
index 0000000..f2cc35b
--- /dev/null
+++ b/ambari-web/test/utils/polling_test.js
@@ -0,0 +1,1333 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+var testHelpers = require('test/helpers');
+require('utils/polling');
+
+describe('App.Poll', function () {
+
+  var poll;
+
+  beforeEach(function () {
+    poll = App.Poll.create();
+  });
+
+  describe('#isCompleted', function () {
+
+    var cases = [
+      {
+        isError: true,
+        isSuccess: false,
+        isCompleted: true,
+        title: 'error'
+      },
+      {
+        isError: false,
+        isSuccess: true,
+        isCompleted: true,
+        title: 'success'
+      },
+      {
+        isError: false,
+        isSuccess: false,
+        isCompleted: false,
+        title: 'incomplete'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        poll.setProperties({
+          isError: item.isError,
+          isSuccess: item.isSuccess
+        });
+        expect(poll.get('isCompleted')).to.equal(item.isCompleted);
+      });
+
+    });
+
+  });
+
+  describe('#showLink', function () {
+
+    var cases = [
+      {
+        isPolling: true,
+        isStarted: false,
+        showLink: true,
+        title: 'polling'
+      },
+      {
+        isPolling: false,
+        isStarted: true,
+        showLink: true,
+        title: 'started'
+      },
+      {
+        isPolling: false,
+        isStarted: false,
+        showLink: false,
+        title: 'not polling, not started'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        poll.setProperties({
+          isPolling: item.isPolling,
+          isStarted: item.isStarted
+        });
+        expect(poll.get('showLink')).to.equal(item.showLink);
+      });
+
+    });
+
+  });
+
+  describe('#start', function () {
+
+    var cases = [
+      {
+        setRequestIdCallCount: 1,
+        startPollingCallCount: 0,
+        title: 'request id not defined'
+      },
+      {
+        requestId: null,
+        setRequestIdCallCount: 1,
+        startPollingCallCount: 0,
+        title: 'request id is null'
+      },
+      {
+        requestId: 0,
+        setRequestIdCallCount: 0,
+        startPollingCallCount: 1,
+        title: 'request id is zero'
+      },
+      {
+        requestId: 1,
+        setRequestIdCallCount: 0,
+        startPollingCallCount: 1,
+        title: 'request id is non-zero'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          sinon.stub(poll, 'setRequestId', Em.K);
+          sinon.stub(poll, 'startPolling', Em.K);
+          poll.set('requestId', item.requestId);
+          poll.start();
+        });
+
+        afterEach(function () {
+          poll.setRequestId.restore();
+          poll.startPolling.restore();
+        });
+
+        it('set request id', function () {
+          expect(poll.setRequestId.callCount).to.equal(item.setRequestIdCallCount);
+        });
+
+        it('start polling', function () {
+          expect(poll.startPolling.callCount).to.equal(item.startPollingCallCount);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#setRequestId', function () {
+
+    var ajaxObj;
+
+    beforeEach(function () {
+      $.ajax.restore();
+      sinon.stub($, 'ajax', function (obj) {
+        return obj;
+      });
+    });
+
+    it('AJAX request parameters', function () {
+      var ajaxProps = {
+        url: '/default',
+        data: {}
+      };
+      poll.setProperties(ajaxProps);
+      poll.setRequestId();
+      ajaxObj = $.ajax.firstCall.args[0];
+      expect(Em.Object.create(ajaxObj).getProperties(['url', 'data'])).to.eql(ajaxProps);
+    });
+
+    describe('#success', function () {
+
+      var cases = [
+        {
+          data: undefined,
+          isSuccess: true,
+          isError: false,
+          requestId: 1,
+          doPollingCallCount: 0,
+          title: 'data not defined'
+        },
+        {
+          data: 'null',
+          isSuccess: true,
+          isError: false,
+          requestId: 1,
+          doPollingCallCount: 0,
+          title: 'null data'
+        },
+        {
+          data: '',
+          isSuccess: true,
+          isError: false,
+          requestId: 1,
+          doPollingCallCount: 0,
+          title: 'empty data'
+        },
+        {
+          data: '{}',
+          isSuccess: false,
+          isError: true,
+          requestId: undefined,
+          doPollingCallCount: 1,
+          title: 'empty object'
+        },
+        {
+          data: '{"Requests":null}',
+          isSuccess: false,
+          isError: true,
+          requestId: null,
+          doPollingCallCount: 1,
+          title: 'no requests info'
+        },
+        {
+          data: '{"Requests":{}}',
+          isSuccess: false,
+          isError: true,
+          requestId: undefined,
+          doPollingCallCount: 1,
+          title: 'empty requests info'
+        },
+        {
+          data: '{"Requests":{"name":"r0"}}',
+          isSuccess: false,
+          isError: true,
+          requestId: undefined,
+          doPollingCallCount: 1,
+          title: 'no request id'
+        },
+        {
+          data: '{"Requests":{"id":0}}',
+          isSuccess: false,
+          isError: true,
+          requestId: 0,
+          doPollingCallCount: 1,
+          title: 'request id available'
+        }
+      ];
+
+      cases.forEach(function (item) {
+
+        describe(item.title, function () {
+
+          var ajaxObject;
+
+          beforeEach(function () {
+            sinon.stub(poll, 'doPolling', Em.K);
+            poll.setProperties({
+              isSuccess: false,
+              isError: true,
+              requestId: 1
+            });
+            poll.setRequestId();
+            ajaxObject = $.ajax.firstCall.args[0];
+            ajaxObject.success(item.data);
+          });
+
+          afterEach(function () {
+            poll.doPolling.restore();
+          });
+
+          it('isSuccess', function () {
+            expect(poll.get('isSuccess')).to.equal(item.isSuccess);
+          });
+
+          it('isError', function () {
+            expect(poll.get('isError')).to.equal(item.isError);
+          });
+
+          it('requestId', function () {
+            expect(poll.get('requestId')).to.equal(item.requestId);
+          });
+
+          it('doPolling call', function () {
+            expect(poll.doPolling.callCount).to.equal(item.doPollingCallCount);
+          });
+
+        });
+
+      });
+
+    });
+
+    describe('#error', function () {
+
+      beforeEach(function () {
+        poll.setProperties({
+          isSuccess: true,
+          isError: false
+        });
+        poll.setRequestId();
+        ajaxObj = $.ajax.firstCall.args[0];
+        ajaxObj.error();
+      });
+
+      it('isSuccess', function () {
+        expect(poll.get('isSuccess')).to.be.false;
+      });
+
+      it('isError', function () {
+        expect(poll.get('isError')).to.be.true;
+      });
+
+    });
+
+  });
+
+  describe('#updateTaskLog', function () {
+
+    beforeEach(function () {
+      sinon.stub(poll, 'pollTaskLog', Em.K);
+      poll.set('currentTaskId', 0);
+      poll.updateTaskLog(1);
+    });
+
+    afterEach(function () {
+      poll.pollTaskLog.restore();
+    });
+
+    it('should change task id', function () {
+      expect(poll.get('currentTaskId')).to.equal(1);
+    });
+
+    it('should poll task log', function () {
+      expect(poll.pollTaskLog.calledOnce).to.be.true;
+    });
+
+  });
+
+  describe('#doPolling', function () {
+
+    var cases = [
+      {
+        requestId: undefined,
+        startPollingCallCount: 0,
+        title: 'request id is undefined'
+      },
+      {
+        requestId: null,
+        startPollingCallCount: 0,
+        title: 'request id is null'
+      },
+      {
+        requestId: 0,
+        startPollingCallCount: 1,
+        title: 'request id is 0'
+      },
+      {
+        requestId: 1,
+        startPollingCallCount: 1,
+        title: 'request id is gra than 0'
+      }
+    ];
+
+    beforeEach(function () {
+      sinon.stub(poll, 'startPolling', Em.K);
+    });
+
+    afterEach(function () {
+      poll.startPolling.restore();
+    });
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        poll.set('requestId', item.requestId);
+        poll.doPolling();
+        expect(poll.startPolling.callCount).to.equal(item.startPollingCallCount);
+      });
+
+    });
+
+  });
+
+  describe('#pollTaskLog', function () {
+
+    var cases = [
+      {
+        currentTaskId: undefined,
+        ajaxCallArguments: undefined,
+        title: 'current task id is undefined'
+      },
+      {
+        currentTaskId: null,
+        ajaxCallArguments: undefined,
+        title: 'current task id is null'
+      },
+      {
+        currentTaskId: 0,
+        ajaxCallArguments: [{
+          name: 'background_operations.get_by_task',
+          data: {
+            requestId: 0,
+            taskId: 0
+          },
+          success: 'pollTaskLogSuccessCallback'
+        }],
+        title: 'current task id is 0'
+      },
+      {
+        currentTaskId: 1,
+        ajaxCallArguments: [{
+          name: 'background_operations.get_by_task',
+          data: {
+            requestId: 0,
+            taskId: 1
+          },
+          success: 'pollTaskLogSuccessCallback'
+        }],
+        title: 'current task id is more than 0'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        poll.setProperties({
+          requestId: 0,
+          currentTaskId: item.currentTaskId
+        });
+        poll.pollTaskLog();
+        if (item.ajaxCallArguments) {
+          item.ajaxCallArguments[0].sender = poll;
+        }
+        expect(testHelpers.findAjaxRequest('name', 'background_operations.get_by_task')).to.eql(item.ajaxCallArguments);
+      });
+
+    });
+
+  });
+
+  describe('#pollTaskLogSuccessCallback', function () {
+
+    it('polled data', function () {
+      poll.set('polledData', [
+        {
+          Tasks: {
+            id: 0
+          }
+        },
+        {
+          Tasks: {
+            id: 1
+          }
+        },
+        {
+          Tasks: {
+            id: 2
+          }
+        }
+      ]);
+      poll.pollTaskLogSuccessCallback({
+        Tasks: {
+          id: 1,
+          stdout: 'stdout',
+          stderr: 'stderr'
+        }
+      });
+      expect(poll.get('polledData').toArray()).to.eql([
+        {
+          Tasks: {
+            id: 0
+          }
+        },
+        {
+          Tasks: {
+            id: 1,
+            stdout: 'stdout',
+            stderr: 'stderr'
+          }
+        },
+        {
+          Tasks: {
+            id: 2
+          }
+        }
+      ]);
+    });
+
+  });
+
+  describe('#startPolling', function () {
+
+    var cases = [
+      {
+        requestId: undefined,
+        ajaxCallArguments: undefined,
+        result: false,
+        pollTaskLogCallCount: 0,
+        title: 'request id is undefined'
+      },
+      {
+        requestId: null,
+        ajaxCallArguments: undefined,
+        result: false,
+        pollTaskLogCallCount: 0,
+        title: 'request id is null'
+      },
+      {
+        requestId: 0,
+        ajaxCallArguments: [{
+          name: 'background_operations.get_by_request',
+          data: {
+            requestId: 0,
+            errorLogMessage: 'Install services all retries failed'
+          },
+          success: 'reloadSuccessCallback',
+          error: 'reloadErrorCallback'
+        }],
+        result: true,
+        pollTaskLogCallCount: 1,
+        title: 'request id is 0'
+      },
+      {
+        requestId: 1,
+        ajaxCallArguments: [{
+          name: 'background_operations.get_by_request',
+          data: {
+            requestId: 1,
+            errorLogMessage: 'Install services all retries failed'
+          },
+          success: 'reloadSuccessCallback',
+          error: 'reloadErrorCallback'
+        }],
+        result: true,
+        pollTaskLogCallCount: 1,
+        title: 'request id is more than 0'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      var result;
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          sinon.stub(poll, 'pollTaskLog', Em.K);
+          poll.set('requestId', item.requestId);
+          result = poll.startPolling();
+          if (item.ajaxCallArguments) {
+            item.ajaxCallArguments[0].sender = poll;
+            item.ajaxCallArguments[0].data.callback = poll.startPolling;
+          }
+        });
+
+        afterEach(function () {
+          poll.pollTaskLog.restore();
+        });
+
+        it('AJAX request', function () {
+          expect(testHelpers.findAjaxRequest('name', 'background_operations.get_by_request')).to.eql(item.ajaxCallArguments);
+        });
+
+        it('result', function () {
+          expect(result).to.equal(item.result);
+        });
+
+        it('pollTaskLog', function () {
+          expect(poll.pollTaskLog.callCount).to.equal(item.pollTaskLogCallCount);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#reloadSuccessCallback', function () {
+
+    var cases = [
+      {
+        parseInfo: false,
+        startPollingCallCount: 1,
+        title: 'no parsed data'
+      },
+      {
+        parseInfo: true,
+        startPollingCallCount: 0,
+        title: 'data parsed'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          sinon.stub(poll, 'parseInfo').returns(item.parseInfo);
+          sinon.stub(window, 'setTimeout', Em.clb);
+          sinon.stub(poll, 'startPolling', Em.K);
+          poll.reloadSuccessCallback(null);
+        });
+
+        afterEach(function () {
+          poll.parseInfo.restore();
+          window.setTimeout.restore();
+          poll.startPolling.restore();
+        });
+
+        it('set timeout', function () {
+          expect(window.setTimeout.callCount).to.equal(item.startPollingCallCount);
+        });
+
+        it('timeout callback', function () {
+          expect(poll.startPolling.callCount).to.equal(item.startPollingCallCount);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#reloadErrorCallback', function () {
+
+    var cases = [
+      {
+        status: undefined,
+        isSuccess: false,
+        isError: false,
+        title: 'status is undefined'
+      },
+      {
+        status: null,
+        isSuccess: false,
+        isError: false,
+        title: 'status is null'
+      },
+      {
+        status: 0,
+        isSuccess: false,
+        isError: false,
+        title: 'status is 0'
+      },
+      {
+        status: 200,
+        isSuccess: true,
+        isError: false,
+        title: 'success'
+      },
+      {
+        status: 404,
+        isSuccess: false,
+        isError: true,
+        title: 'error'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        poll.setProperties({
+          isSuccess: item.isSuccess,
+          isError: false
+        });
+        poll.reloadErrorCallback({
+          status: item.status
+        }, null, null, null, {});
+        expect(poll.get('isError')).to.equal(item.isError);
+      });
+
+    });
+
+  });
+
+  describe('#replacePolledData', function () {
+
+    var cases = [
+      {
+        currentTaskId: undefined,
+        data: [],
+        result: [],
+        title: 'current task id is undefined'
+      },
+      {
+        currentTaskId: null,
+        data: [],
+        result: [],
+        title: 'current task id is null'
+      },
+      {
+        currentTaskId: 0,
+        polledData: [
+          {
+            Tasks: {
+              id: 0
+            }
+          },
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        data: [
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        result: [
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        title: 'current task id is 0, no corresponding task passed'
+      },
+      {
+        currentTaskId: 1,
+        polledData: [
+          {
+            Tasks: {
+              id: 0
+            }
+          }
+        ],
+        data: [
+          {
+            Tasks: {
+              id: 0
+            }
+          },
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        result: [
+          {
+            Tasks: {
+              id: 0
+            }
+          },
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        title: 'current task id is more than 0, no corresponding task set'
+      },
+      {
+        currentTaskId: 2,
+        polledData: [
+          {
+            Tasks: {
+              id: 0
+            }
+          },
+          {
+            Tasks: {
+              id: 2,
+              stdout: 'stdout',
+              stderr: 'stderr'
+            }
+          }
+        ],
+        data: [
+          {
+            Tasks: {
+              id: 0
+            }
+          },
+          {
+            Tasks: {
+              id: 2
+            }
+          },
+          {
+            Tasks: {
+              id: 3
+            }
+          }
+        ],
+        result: [
+          {
+            Tasks: {
+              id: 0
+            }
+          },
+          {
+            Tasks: {
+              id: 2,
+              stdout: 'stdout',
+              stderr: 'stderr'
+            }
+          },
+          {
+            Tasks: {
+              id: 3
+            }
+          }
+        ],
+        title: 'current task id is more than 0, corresponding task set and passed'
+      },
+      {
+        currentTaskId: 3,
+        polledData: [
+          {
+            Tasks: {
+              id: 0
+            }
+          }
+        ],
+        data: [
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        result: [
+          {
+            Tasks: {
+              id: 1
+            }
+          }
+        ],
+        title: 'current task id is more than 0, corresponding task neither set nor passed'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        poll.setProperties({
+          currentTaskId: item.currentTaskId,
+          polledData: item.polledData || null
+        });
+        poll.replacePolledData(item.data);
+        expect(poll.get('polledData').toArray()).to.eql(item.result);
+      });
+
+    });
+
+  });
+
+  describe('#calculateProgressByTasks', function () {
+
+    var cases = [
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'QUEUED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'QUEUED'
+            }
+          }
+        ],
+        result: 9,
+        title: 'all tasks pending'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'IN_PROGRESS'
+            }
+          },
+          {
+            Tasks: {
+              status: 'IN_PROGRESS'
+            }
+          }
+        ],
+        result: 35,
+        title: 'all tasks in progress'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        result: 100,
+        title: 'all tasks completed'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'FAILED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'FAILED'
+            }
+          }
+        ],
+        result: 100,
+        title: 'all tasks failed'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'ABORTED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'ABORTED'
+            }
+          }
+        ],
+        result: 100,
+        title: 'all tasks aborted'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'TIMEDOUT'
+            }
+          },
+          {
+            Tasks: {
+              status: 'TIMEDOUT'
+            }
+          }
+        ],
+        result: 100,
+        title: 'all tasks timed out'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'QUEUED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        result: 55,
+        title: 'pending and finished tasks'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'IN_PROGRESS'
+            }
+          },
+          {
+            Tasks: {
+              status: 'FAILED'
+            }
+          }
+        ],
+        result: 68,
+        title: 'running and finished tasks'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'IN_PROGRESS'
+            }
+          },
+          {
+            Tasks: {
+              status: 'QUEUED'
+            }
+          }
+        ],
+        result: 22,
+        title: 'running and pending tasks'
+      },
+      {
+        tasksData: [
+          {
+            Tasks: {
+              status: 'IN_PROGRESS'
+            }
+          },
+          {
+            Tasks: {
+              status: 'QUEUED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'ABORTED'
+            }
+          }
+        ],
+        result: 48,
+        title: 'running, pending and finished tasks'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        expect(poll.calculateProgressByTasks(item.tasksData)).to.equal(item.result);
+      });
+
+    });
+
+  });
+
+  describe('#isPollingFinished', function () {
+
+    var cases = [
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'QUEUED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: false,
+        isSuccess: false,
+        isError: false,
+        title: 'some queued tasks'
+      },
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'IN_PROGRESS'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: false,
+        isSuccess: false,
+        isError: false,
+        title: 'some running tasks'
+      },
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'PENDING'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: false,
+        isSuccess: false,
+        isError: false,
+        title: 'some pending tasks'
+      },
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'FAILED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: true,
+        isSuccess: false,
+        isError: true,
+        title: 'all tasks finished, some failed'
+      },
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'ABORTED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: true,
+        isSuccess: false,
+        isError: true,
+        title: 'all tasks finished, some aborted'
+      },
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'ABORTED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: true,
+        isSuccess: false,
+        isError: true,
+        title: 'all tasks finished, some timed out'
+      },
+      {
+        polledData: [
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          },
+          {
+            Tasks: {
+              status: 'COMPLETED'
+            }
+          }
+        ],
+        isPollingFinished: true,
+        isSuccess: true,
+        isError: false,
+        title: 'all tasks finished successfully'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        var result;
+
+        beforeEach(function () {
+          poll.setProperties({
+            isSuccess: false,
+            isError: false
+          });
+          result = poll.isPollingFinished(item.polledData);
+        });
+
+        it('isPollingFinished', function () {
+          expect(result).to.equal(item.isPollingFinished);
+        });
+
+        it('isSuccess', function () {
+          expect(poll.get('isSuccess')).to.equal(item.isSuccess);
+        });
+
+        it('isError', function () {
+          expect(poll.get('isError')).to.equal(item.isError);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#parseInfo', function () {
+
+    var cases = [
+      {
+        polledData: {
+          Requests: {
+            id: 1
+          }
+        },
+        replacePolledDataCallCount: 0,
+        progress: '0',
+        result: false,
+        title: 'no corresponding request data'
+      },
+      {
+        polledData: {
+          tasks: []
+        },
+        replacePolledDataCallCount: 1,
+        progress: '100',
+        result: false,
+        title: 'no request id info'
+      },
+      {
+        polledData: {
+          Requests: {
+            id: 0
+          },
+          tasks: []
+        },
+        replacePolledDataCallCount: 1,
+        progress: '100',
+        result: false,
+        title: 'no tasks'
+      },
+      {
+        polledData: {
+          Requests: {
+            id: 0
+          },
+          tasks: [
+            {
+              Tasks: {
+                status: 'PENDING'
+              }
+            },
+            {
+              Tasks: {
+                status: 'COMPLETED'
+              }
+            }
+          ]
+        },
+        replacePolledDataCallCount: 1,
+        progress: '100',
+        result: false,
+        title: 'not all tasks finished'
+      },
+      {
+        polledData: {
+          Requests: {
+            id: 0
+          },
+          tasks: [
+            {
+              Tasks: {
+                status: 'FAILED'
+              }
+            },
+            {
+              Tasks: {
+                status: 'COMPLETED'
+              }
+            }
+          ]
+        },
+        replacePolledDataCallCount: 1,
+        progress: '100',
+        result: true,
+        title: 'all tasks finished'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        var result;
+
+        beforeEach(function () {
+          sinon.stub(poll, 'replacePolledData', Em.K);
+          sinon.stub(poll, 'calculateProgressByTasks').returns(100);
+          sinon.stub(poll, 'isPollingFinished', function (data) {
+            return data.length > 0 && !(data.someProperty('Tasks.status', 'QUEUED') || data.someProperty('Tasks.status', 'IN_PROGRESS')
+              || data.someProperty('Tasks.status', 'PENDING'));
+          });
+          poll.setProperties({
+            requestId: 0,
+            progress: '0'
+          });
+          result = poll.parseInfo(item.polledData);
+        });
+
+        afterEach(function () {
+          poll.replacePolledData.restore();
+          poll.calculateProgressByTasks.restore();
+          poll.isPollingFinished.restore();
+        });
+
+        it('replacePolledData call', function () {
+          expect(poll.replacePolledData.callCount).to.equal(item.replacePolledDataCallCount);
+        });
+
+        if (item.replacePolledDataCallCount) {
+          it('replacePolledData argument', function () {
+            expect(poll.replacePolledData.firstCall.args).to.eql([item.polledData.tasks]);
+          });
+        }
+
+        it('progress', function () {
+          expect(poll.get('progress')).to.equal(item.progress);
+        });
+
+        it('result', function () {
+          expect(result).to.equal(item.result);
+        });
+
+      });
+
+    });
+
+  });
+
+});


[3/3] ambari git commit: AMBARI-15596. Add missing unit tests files for ambari-web utils (alexantonenko)

Posted by al...@apache.org.
AMBARI-15596. Add missing unit tests files for ambari-web utils (alexantonenko)


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

Branch: refs/heads/trunk
Commit: d5d1afea8be684fed1e712f7a80b5e06f4d79ba5
Parents: aa033d0
Author: Alex Antonenko <hi...@gmail.com>
Authored: Mon Mar 28 11:53:29 2016 +0300
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Mon Mar 28 11:53:29 2016 +0300

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |    9 +
 ambari-web/app/utils/array_utils.js             |    2 +-
 ambari-web/app/utils/configs_collection.js      |    2 +-
 ambari-web/app/utils/heatmap.js                 |    1 -
 ambari-web/app/utils/hosts.js                   |   10 +-
 ambari-web/app/utils/polling.js                 |   20 +-
 ambari-web/test/utils/action_sequence_test.js   |  323 ++
 ambari-web/test/utils/array_utils_test.js       |  125 +
 .../test/utils/configs_collection_test.js       |  334 ++
 ambari-web/test/utils/credentials_test.js       |  717 ++++
 ambari-web/test/utils/file_utils_test.js        |  126 +
 .../test/utils/handlebars_helpers_test.js       |   57 +
 ambari-web/test/utils/heatmap_test.js           |  141 +
 ambari-web/test/utils/hosts_test.js             | 3467 ++++++++++++++++++
 ambari-web/test/utils/polling_test.js           | 1333 +++++++
 15 files changed, 6646 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index d114379..db504f2 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -167,9 +167,13 @@ var files = [
   'test/mixins/unit_convert/base_unit_convert_mixin_test',
   'test/utils/ajax/ajax_test',
   'test/utils/ajax/ajax_queue_test',
+  'test/utils/action_sequence_test',
+  'test/utils/array_utils_test',
   'test/utils/batch_scheduled_requests_test',
   'test/utils/blueprint_test',
   'test/utils/config_test',
+  'test/utils/configs_collection_test',
+  'test/utils/credentials_test',
   'test/utils/date/date_test',
   'test/utils/date/timezone_test',
   'test/utils/data_manipulation_test',
@@ -178,9 +182,14 @@ var files = [
   'test/utils/ember_computed_test',
   'test/utils/ember_reopen_test',
   'test/utils/form_field_test',
+  'test/utils/file_utils_test',
+  'test/utils/handlebars_helpers_test',
+  'test/utils/heatmap_test',
   'test/utils/host_progress_popup_test',
+  'test/utils/hosts_test',
   'test/utils/misc_test',
   'test/utils/number_utils_test',
+  'test/utils/polling_test',
   'test/utils/validator_test',
   'test/utils/config_test',
   'test/utils/string_utils_test',

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/app/utils/array_utils.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/array_utils.js b/ambari-web/app/utils/array_utils.js
index bee12ee..643ed67 100644
--- a/ambari-web/app/utils/array_utils.js
+++ b/ambari-web/app/utils/array_utils.js
@@ -26,7 +26,7 @@ module.exports = {
   uniqObjectsbyId: function (arr, id) {
     var result = [];
     arr.forEach(function (item) {
-      var isIdPresent = result.someProperty('id', item.id);
+      var isIdPresent = result.someProperty(id, item[id]);
       if (!isIdPresent) {
         result.pushObject(item);
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/app/utils/configs_collection.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/configs_collection.js b/ambari-web/app/utils/configs_collection.js
index fde7a17..a9a570a 100644
--- a/ambari-web/app/utils/configs_collection.js
+++ b/ambari-web/app/utils/configs_collection.js
@@ -40,7 +40,7 @@ var configsCollection = [],
 App.configsCollection = Em.Object.create({
 
   /**
-   * adds config property to configs array anf map
+   * adds config property to configs array and map
    * should assert error if config has no id
    * @param c
    * @method add

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/app/utils/heatmap.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/heatmap.js b/ambari-web/app/utils/heatmap.js
index 9d8c178..e033005 100644
--- a/ambari-web/app/utils/heatmap.js
+++ b/ambari-web/app/utils/heatmap.js
@@ -16,7 +16,6 @@
  * limitations under the License.
  */
 
-var App = require('app');
 module.exports = {
   mappers: Em.Mixin.create({
     metricMapperWithTransform: function (json, metricName, transformValueFunction) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/app/utils/hosts.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/hosts.js b/ambari-web/app/utils/hosts.js
index 2467e1a..e4a437c 100644
--- a/ambari-web/app/utils/hosts.js
+++ b/ambari-web/app/utils/hosts.js
@@ -151,15 +151,11 @@ module.exports = {
 
             host.set('filterColumnValue', value);
 
-            if (!skip && filterText) {
-              if ((value == null || !value.toString().match(filterText)) && !host.get('host.publicHostName').match(filterText)) {
-                skip = true;
-              }
+            if (!skip && filterText && (value == null || !value.toString().match(filterText)) && !host.get('host.publicHostName').match(filterText)) {
+              skip = true;
             }
-            if (!skip && filterComponent) {
-              if (hostComponentNames.length > 0) {
+            if (!skip && filterComponent && hostComponentNames.length > 0) {
                 skip = !hostComponentNames.contains(filterComponent.get('componentName'));
-              }
             }
             host.set('filtered', !skip);
           }, this);

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/app/utils/polling.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/polling.js b/ambari-web/app/utils/polling.js
index b83ca23..7337fbb 100644
--- a/ambari-web/app/utils/polling.js
+++ b/ambari-web/app/utils/polling.js
@@ -76,7 +76,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
           self.set('isSuccess', true);
           self.set('isError', false);
         } else {
-          var requestId = jsonData.Requests.id;
+          var requestId = Em.get(jsonData, 'Requests.id');
           self.set('requestId', requestId);
           self.doPolling();
         }
@@ -101,7 +101,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
   },
 
   doPolling: function () {
-    if (this.get('requestId')) {
+    if (!Em.isNone(this.get('requestId'))) {
       this.startPolling();
     }
   },
@@ -110,7 +110,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
    * server call to obtain task logs
    */
   pollTaskLog: function () {
-    if (this.get('currentTaskId')) {
+    if (!Em.isNone(this.get('currentTaskId'))) {
       App.ajax.send({
         name: 'background_operations.get_by_task',
         sender: this,
@@ -119,7 +119,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
           taskId: this.get('currentTaskId')
         },
         success: 'pollTaskLogSuccessCallback'
-      })
+      });
     }
   },
 
@@ -139,7 +139,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
    * @return {Boolean}
    */
   startPolling: function () {
-    if (!this.get('requestId')) return false;
+    if (Em.isNone(this.get('requestId'))) return false;
 
     this.pollTaskLog();
     App.ajax.send({
@@ -169,10 +169,8 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
 
   reloadErrorCallback: function (request, ajaxOptions, error, opt, params) {
     this._super(request, ajaxOptions, error, opt, params);
-    if (request.status) {
-      if (!this.get('isSuccess')) {
-        this.set('isError', true);
-      }
+    if (request.status && !this.get('isSuccess')) {
+      this.set('isError', true);
     }
   },
 
@@ -182,7 +180,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
 
   replacePolledData: function (polledData) {
     var currentTaskId = this.get('currentTaskId');
-    if (currentTaskId) {
+    if (!Em.isNone(currentTaskId)) {
       var task = this.get('polledData').findProperty('Tasks.id', currentTaskId);
       var currentTask = polledData.findProperty('Tasks.id', currentTaskId);
       if (task && currentTask) {
@@ -226,7 +224,7 @@ App.Poll = Em.Object.extend(App.ReloadPopupMixin, {
   parseInfo: function (polledData) {
     var tasksData = polledData.tasks;
     var requestId = this.get('requestId');
-    if (polledData.Requests && polledData.Requests.id && polledData.Requests.id != requestId) {
+    if (polledData.Requests && !Em.isNone(polledData.Requests.id) && polledData.Requests.id != requestId) {
       // We don't want to use non-current requestId's tasks data to
       // determine the current install status.
       // Also, we don't want to keep polling if it is not the

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/action_sequence_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/action_sequence_test.js b/ambari-web/test/utils/action_sequence_test.js
new file mode 100644
index 0000000..4ae9dc8
--- /dev/null
+++ b/ambari-web/test/utils/action_sequence_test.js
@@ -0,0 +1,323 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/action_sequence');
+
+describe('App.actionSequence', function () {
+
+  var actionSequence;
+
+  beforeEach(function () {
+    actionSequence = App.actionSequence.create();
+  });
+
+  describe('#setSequence', function () {
+
+    var cases = [
+        {
+          sequenceIn: [{}, {}],
+          sequenceOut: [{}, {}],
+          title: 'array passed'
+        },
+        {
+          sequenceIn: {
+            '0': {},
+            '1': {},
+            'length': 2
+          },
+          sequenceOut: [{}],
+          title: 'array-like object passed'
+        },
+        {
+          sequenceIn: 0,
+          sequenceOut: [{}],
+          title: 'primitive passed'
+        }
+      ],
+      result;
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          actionSequence.set('sequence', [{}]);
+          result = actionSequence.setSequence(item.sequenceIn);
+        });
+
+        it('should return context', function () {
+          expect(result).to.eql(actionSequence);
+        });
+
+        it('sequence property', function () {
+          expect(actionSequence.get('sequence')).to.eql(item.sequenceOut);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#start', function () {
+
+    beforeEach(function () {
+      actionSequence.setProperties({
+        actionCounter: 0,
+        sequence: [{}]
+      });
+      sinon.stub(actionSequence, 'runNextAction', Em.K);
+      actionSequence.start();
+    });
+
+    afterEach(function () {
+      actionSequence.runNextAction.restore();
+    });
+
+    it('should set the counter', function () {
+      expect(actionSequence.get('actionCounter')).to.equal(1);
+    });
+
+    it('should start the sequence', function () {
+      expect(actionSequence.runNextAction.calledOnce).to.be.true;
+    });
+
+    it('should call runNextAction with correct arguments', function () {
+      expect(actionSequence.runNextAction.calledWith(0, null)).to.be.true;
+    });
+
+  });
+
+  describe('#onFinish', function () {
+
+    var cases = [
+        {
+          callbackIn: Em.isNone,
+          callbackOut: Em.isNone,
+          title: 'function passed'
+        },
+        {
+          callbackIn: 'function () {}',
+          callbackOut: Em.clb,
+          title: 'array-like object passed'
+        },
+        {
+          callbackIn: 'function () {}',
+          callbackOut: Em.clb,
+          title: 'primitive passed'
+        }
+      ],
+      result;
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          actionSequence.set('finishedCallback', Em.clb);
+          result = actionSequence.onFinish(item.callbackIn);
+        });
+
+        it('should return context', function () {
+          expect(result).to.eql(actionSequence);
+        });
+
+        it('finishedCallback property', function () {
+          expect(actionSequence.get('finishedCallback')).to.eql(item.callbackOut);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#runNextAction', function () {
+
+    var actions = {
+        callback: Em.K,
+        sync: function (prevResponse) {
+          actions.callback(prevResponse);
+          return prevResponse;
+        },
+        async: function (prevResponse) {
+          actions.callback(prevResponse);
+          return {
+            done: function (callback) {
+              return callback.call(this, prevResponse);
+            }
+          };
+        }
+      },
+      prevResponse = {},
+      cases = [
+        {
+          index: 0,
+          actionCounter: 0,
+          sequence: [
+            {
+              callback: actions.sync,
+              type: 'sync'
+            }
+          ],
+          actionCallCount: 0,
+          title: 'no iterations left (case 1)'
+        },
+        {
+          index: 3,
+          actionCounter: 3,
+          sequence: [
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            }
+          ],
+          actionCallCount: 0,
+          title: 'no iterations left (case 2)'
+        },
+        {
+          index: 1,
+          actionCounter: 3,
+          sequence: [
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            }
+          ],
+          actionCallCount: 2,
+          title: 'starting from the middle'
+        },
+        {
+          index: 0,
+          actionCounter: 2,
+          sequence: [
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            }
+          ],
+          actionCallCount: 2,
+          title: 'ending at the middle'
+        },
+        {
+          index: 0,
+          actionCounter: 3,
+          sequence: [
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            }
+          ],
+          actionCallCount: 3,
+          title: 'all iterations'
+        },
+        {
+          index: 0,
+          actionCounter: 3,
+          sequence: [
+            {
+              callback: actions.sync,
+              type: 'sync'
+            },
+            {
+              callback: actions.async,
+              type: 'async'
+            },
+            {
+              callback: actions.sync,
+              type: 'sync'
+            }
+          ],
+          actionCallCount: 3,
+          title: 'asynchronous action'
+        }
+      ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          sinon.spy(actions, 'callback');
+          sinon.stub(actionSequence, 'finishedCallback', Em.K);
+          actionSequence.setProperties({
+            context: actionSequence,
+            actionCounter: item.actionCounter,
+            sequence: item.sequence
+          });
+          actionSequence.runNextAction(item.index, prevResponse);
+        });
+
+        afterEach(function () {
+          actions.callback.restore();
+          actionSequence.finishedCallback.restore();
+        });
+
+        it('number of calls', function () {
+          expect(actions.callback.callCount).to.equal(item.actionCallCount);
+        });
+
+        if (item.actionCallCount) {
+          it('argument passed to callback', function () {
+            expect(actions.callback.alwaysCalledWith(prevResponse)).to.be.true;
+          });
+        }
+
+        it('finish callback', function () {
+          expect(actionSequence.finishedCallback.calledOnce).to.be.true;
+        });
+
+      });
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/array_utils_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/array_utils_test.js b/ambari-web/test/utils/array_utils_test.js
new file mode 100644
index 0000000..ec7c5d8
--- /dev/null
+++ b/ambari-web/test/utils/array_utils_test.js
@@ -0,0 +1,125 @@
+/**
+ * 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.
+ */
+
+var arrayUtils = require('utils/array_utils');
+
+describe('array_utils', function () {
+
+  describe('#uniqObjectsbyId', function () {
+
+    var arr = [
+        {
+          n: 0,
+          v: 'v0'
+        },
+        {
+          n: 0,
+          v: 'v01'
+        },
+        {
+          n: 1,
+          v: 'v1'
+        },
+        {
+          n: '1',
+          v: 'v11'
+        },
+        {
+          n: 2,
+          v: 'v2'
+        }
+      ],
+      result = [
+        {
+          n: 0,
+          v: 'v0'
+        },
+        {
+          n: 1,
+          v: 'v1'
+        },
+        {
+          n: '1',
+          v: 'v11'
+        },
+        {
+          n: 2,
+          v: 'v2'
+        }
+      ];
+
+    it('should return one element for one id', function () {
+      expect(arrayUtils.uniqObjectsbyId(arr, 'n').toArray()).to.eql(result);
+    });
+
+  });
+
+  describe('#intersect', function () {
+
+    var cases = [
+      {
+        arr1: [Infinity, 0, 1, 2, {a: 1}, {b: 2}, null, undefined],
+        arr2: ['undefined', null, {b: '2'}, {a: 1}, 2.0, '1', 0, Infinity],
+        result: [null, 2, 0, Infinity],
+        title: 'arrays of the same length have common items'
+      },
+      {
+        arr1: [true, false, [0, 1], [2, 3], [4, 5], [6], null, undefined],
+        arr2: [undefined, 'null', 6, [4, 5], ['2', '3'], [String(0), String(1)], '0,1', false, 'true'],
+        result: [false, undefined],
+        title: 'arrays of different length have common items'
+      },
+      {
+        arr1: ['1', function () {}, NaN],
+        arr2: ['function () {}', Number('1'), NaN],
+        result: [],
+        title: 'arrays have no common items'
+      },
+      {
+        arr1: [[0], undefined, null],
+        arr2: [],
+        result: [],
+        title: 'one of arrays is empty'
+      },
+      {
+        arr1: [],
+        arr2: [],
+        result: [],
+        title: 'both arrays are empty'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        it('arrays intersection', function () {
+          expect(arrayUtils.intersect(item.arr1, item.arr2)).to.eql(item.result);
+        });
+
+        it('commutativity', function () {
+          expect(arrayUtils.intersect(item.arr1, item.arr2).sort()).to.eql(arrayUtils.intersect(item.arr2, item.arr1).sort());
+        });
+
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/configs_collection_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/configs_collection_test.js b/ambari-web/test/utils/configs_collection_test.js
new file mode 100644
index 0000000..bd97950
--- /dev/null
+++ b/ambari-web/test/utils/configs_collection_test.js
@@ -0,0 +1,334 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/configs_collection');
+
+describe('App.configsCollection', function () {
+
+  var configsCollection;
+
+  beforeEach(function () {
+    configsCollection = Em.Object.create(App.configsCollection);
+    sinon.spy(Em, 'assert');
+  });
+
+  afterEach(function () {
+    Em.assert.restore();
+  });
+
+  describe('#add', function () {
+
+    var cases = [
+      {
+        collection: [],
+        isError: false,
+        title: 'initial state'
+      },
+      {
+        obj: undefined,
+        collection: [],
+        isError: true,
+        title: 'no item passed'
+      },
+      {
+        obj: undefined,
+        collection: [],
+        isError: true,
+        title: 'null passed'
+      },
+      {
+        obj: {},
+        collection: [],
+        isError: true,
+        title: 'no id passed'
+      },
+      {
+        obj: {
+          id: 1,
+          name: 'n10'
+        },
+        collection: [
+          {
+            id: 1,
+            name: 'n10'
+          }
+        ],
+        mapItem: {
+          id: 1,
+          name: 'n10'
+        },
+        isError: false,
+        title: 'new item'
+      },
+      {
+        obj: {
+          id: 1,
+          name: 'n11'
+        },
+        collection: [
+          {
+            id: 1,
+            name: 'n10'
+          }
+        ],
+        mapItem: {
+          id: 1,
+          name: 'n11'
+        },
+        isError: false,
+        title: 'duplicate id'
+      },
+      {
+        obj: {
+          id: '1',
+          name: 'n12'
+        },
+        collection: [
+          {
+            id: 1,
+            name: 'n10'
+          }
+        ],
+        mapItem: {
+          id: '1',
+          name: 'n12'
+        },
+        isError: false,
+        title: 'duplicate id, key name conversion'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          try {
+            if (item.hasOwnProperty('obj')) {
+              configsCollection.add(item.obj);
+            }
+          } catch (e) {}
+        });
+
+        it('thrown error', function () {
+          expect(Em.assert.threw()).to.equal(item.isError);
+        });
+
+        it('configs array', function () {
+          expect(configsCollection.getAll()).to.eql(item.collection);
+        });
+
+        if (item.obj && item.obj.id) {
+          it('configs map', function () {
+            expect(configsCollection.getConfig(item.obj.id)).to.eql(item.mapItem);
+          });
+        }
+
+      });
+
+    });
+
+  });
+
+  describe('#getConfig', function () {
+
+    var cases = [
+      {
+        result: undefined,
+        isError: true,
+        title: 'no id passed'
+      },
+      {
+        id: null,
+        result: undefined,
+        isError: true,
+        title: 'invalid id passed'
+      },
+      {
+        id: 1,
+        result: {
+          id: 1
+        },
+        isError: false,
+        title: 'existing item'
+      },
+      {
+        id: 1,
+        result: {
+          id: 1
+        },
+        isError: false,
+        title: 'existing item, key name conversion'
+      },
+      {
+        id: 2,
+        result: undefined,
+        isError: false,
+        title: 'item doesn\'t exist'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        var result;
+
+        beforeEach(function () {
+          configsCollection.add({
+            id: 1
+          });
+          try {
+            result = configsCollection.getConfig(item.id);
+          } catch (e) {}
+        });
+
+        it('thrown error', function () {
+          expect(Em.assert.threw()).to.equal(item.isError);
+        });
+
+        it('returned value', function () {
+          expect(result).to.eql(item.result);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#getConfigByName', function () {
+
+    var configIds = ['n0_f0', 'n1_f1'],
+      cases = [
+        {
+          fileName: 'f0',
+          result: undefined,
+          isError: true,
+          title: 'no name passed'
+        },
+        {
+          name: 'n0',
+          result: undefined,
+          isError: true,
+          title: 'no filename passed'
+        },
+        {
+          name: 'n0',
+          fileName: 'f0',
+          result: {
+            id: 'n0_f0'
+          },
+          isError: false,
+          title: 'existing item'
+        },
+        {
+          name: 'n0',
+          fileName: 'f1',
+          result: undefined,
+          isError: false,
+          title: 'not existing item'
+        }
+      ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        var result;
+
+        beforeEach(function () {
+          sinon.stub(App.config, 'configId', function (name, fileName) {
+            return name + '_' + fileName;
+          });
+          configIds.forEach(function (id) {
+            configsCollection.add({
+              id: id
+            });
+          });
+          try {
+            result = configsCollection.getConfigByName(item.name, item.fileName);
+          } catch (e) {}
+        });
+
+        afterEach(function () {
+          App.config.configId.restore();
+          configsCollection.clearAll();
+        });
+
+
+        it('thrown error', function () {
+          expect(Em.assert.threw()).to.equal(item.isError);
+        });
+
+        it('returned value', function () {
+          expect(result).to.eql(item.result);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#getAll', function () {
+
+    var configs = [
+      {
+        id: 'c0'
+      },
+      {
+        id: 'c1'
+      }
+    ];
+
+    beforeEach(function () {
+      configsCollection.clearAll();
+    });
+
+    it('should return all configs', function () {
+      configs.forEach(function (item) {
+        configsCollection.add(item);
+      });
+      expect(configsCollection.getAll()).to.eql(configs);
+    });
+
+  });
+
+
+  describe('#clearAll', function () {
+
+    beforeEach(function () {
+      configsCollection.add({
+        id: 'c0'
+      });
+      configsCollection.clearAll();
+    });
+
+    it('should clear configs array', function () {
+      expect(configsCollection.getAll()).to.have.length(0);
+    });
+
+    it('should clear configs map', function () {
+      expect(configsCollection.getConfig('c0')).to.be.undefined;
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/credentials_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/credentials_test.js b/ambari-web/test/utils/credentials_test.js
new file mode 100644
index 0000000..7bf6791
--- /dev/null
+++ b/ambari-web/test/utils/credentials_test.js
@@ -0,0 +1,717 @@
+/**
+ * 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.
+ */
+
+var credentials = require('utils/credentials');
+var testHelpers = require('test/helpers');
+
+describe('credentials utils', function () {
+
+  var storeTypeStatusMock = function (clusterName, key) {
+    var result = {};
+    result[key] = clusterName;
+    return result;
+  };
+
+  describe('#createCredentials', function () {
+
+    it('should send AJAX request', function () {
+      credentials.createCredentials('c', 'a', {});
+      expect(testHelpers.findAjaxRequest('name', 'credentials.create')).to.eql([
+        {
+          sender: credentials,
+          name: 'credentials.create',
+          data: {
+            clusterName: 'c',
+            resource: {},
+            alias: 'a'
+          },
+          error: 'createCredentialsErrorCallback'
+        }
+      ]);
+    });
+
+  });
+
+  describe('#credentialsSuccessCallback', function () {
+
+    var params = {
+        callback: Em.K
+      },
+      cases = [
+        {
+          items: [],
+          callbackArgument: [],
+          title: 'no data returned'
+        },
+        {
+          items: [{}, {}],
+          callbackArgument: [undefined, undefined],
+          title: 'empty data returned'
+        },
+        {
+          items: [
+            {
+              Credential: {
+                id: 0
+              }
+            },
+            {
+              Credential: {
+                id: 1
+              }
+            }
+          ],
+          callbackArgument: [
+            {
+              id: 0
+            },
+            {
+              id: 1
+            }
+          ],
+          title: 'valid data returned'
+        }
+      ];
+
+    beforeEach(function () {
+      sinon.spy(params, 'callback');
+    });
+
+    afterEach(function () {
+      params.callback.restore();
+    });
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        credentials.credentialsSuccessCallback({
+          items: item.items
+        }, null, params);
+        expect(params.callback.firstCall.args).to.eql([item.callbackArgument]);
+      });
+
+    });
+
+  });
+
+  describe('#createOrUpdateCredentials', function () {
+
+    var mock = {
+        dfd: {
+          getCredential: null,
+          updateCredentials: null,
+          createCredentials: null
+        },
+        callback: Em.K,
+        getCredential: function () {
+          return mock.dfd.getCredential.promise();
+        },
+        updateCredentials: function () {
+          return mock.dfd.updateCredentials.promise();
+        },
+        createCredentials: function () {
+          return mock.dfd.createCredentials.promise();
+        }
+      },
+      cases = [
+        {
+          getCredentialResolve: true,
+          credentialsCallback: 'updateCredentials',
+          isCredentialsCallbackResolve: true,
+          status: 'success',
+          result: {
+            status: 200
+          },
+          callbackArgs: [
+            true,
+            {
+              status: 200
+            }
+          ],
+          title: 'successful credentials update'
+        },
+        {
+          getCredentialResolve: true,
+          credentialsCallback: 'updateCredentials',
+          isCredentialsCallbackResolve: false,
+          status: 'error',
+          result: {
+            status: 404
+          },
+          callbackArgs: [
+            false,
+            {
+              status: 404
+            }
+          ],
+          title: 'failed credentials update'
+        },
+        {
+          getCredentialResolve: false,
+          credentialsCallback: 'createCredentials',
+          isCredentialsCallbackResolve: true,
+          status: 'success',
+          result: {
+            status: 201
+          },
+          callbackArgs: [
+            true,
+            {
+              status: 201
+            }
+          ],
+          title: 'successful credentials creation'
+        },
+        {
+          getCredentialResolve: false,
+          credentialsCallback: 'createCredentials',
+          isCredentialsCallbackResolve: false,
+          status: 'error',
+          result: {
+            status: 500
+          },
+          callbackArgs: [
+            false,
+            {
+              status: 500
+            }
+          ],
+          title: 'failed credentials creation'
+        }
+      ];
+
+    beforeEach(function () {
+      sinon.stub(credentials, 'getCredential', mock.getCredential);
+      sinon.stub(credentials, 'updateCredentials', mock.updateCredentials);
+      sinon.stub(credentials, 'createCredentials', mock.createCredentials);
+      sinon.spy(mock, 'callback');
+      mock.dfd.getCredential = $.Deferred();
+      mock.dfd.updateCredentials = $.Deferred();
+      mock.dfd.createCredentials = $.Deferred();
+    });
+
+    afterEach(function () {
+      credentials.getCredential.restore();
+      credentials.updateCredentials.restore();
+      credentials.createCredentials.restore();
+      mock.callback.restore();
+    });
+
+    cases.forEach(function (item) {
+
+      var getCredentialMethod = item.getCredentialResolve ? 'resolve' : 'reject',
+        credentialsCallbackMethod = item.isCredentialsCallbackResolve ? 'resolve' : 'reject';
+
+      it(item.title, function () {
+        mock.dfd.getCredential[getCredentialMethod]();
+        mock.dfd[item.credentialsCallback][credentialsCallbackMethod](null, item.status, item.result);
+        credentials.createOrUpdateCredentials().done(mock.callback);
+        expect(mock.callback.firstCall.args).to.eql(item.callbackArgs);
+      });
+
+    });
+
+  });
+
+  describe('#getCredential', function () {
+
+    it('should send AJAX request', function () {
+      credentials.getCredential('c', 'a', Em.K);
+      expect(testHelpers.findAjaxRequest('name', 'credentials.get')).to.eql([
+        {
+          sender: credentials,
+          name: 'credentials.get',
+          data: {
+            clusterName: 'c',
+            alias: 'a',
+            callback: Em.K
+          },
+          success: 'getCredentialSuccessCallback',
+          error: 'getCredentialErrorCallback'
+        }
+      ]);
+    });
+
+  });
+
+  describe('#getCredentialSuccessCallback', function () {
+
+    var params = {
+        callback: Em.K
+      },
+      cases = [
+        {
+          data: null,
+          callback: undefined,
+          callbackCallCount: 0,
+          title: 'no callback passed'
+        },
+        {
+          data: null,
+          callback: null,
+          callbackCallCount: 0,
+          title: 'invalid callback passed'
+        },
+        {
+          data: null,
+          callbackCallCount: 1,
+          callbackArgument: null,
+          title: 'no data passed'
+        },
+        {
+          data: {},
+          callbackCallCount: 1,
+          callbackArgument: null,
+          title: 'no credential info passed'
+        },
+        {
+          data: {
+            Credential: 'c'
+          },
+          callbackCallCount: 1,
+          callbackArgument: 'c',
+          title: 'credential info passed'
+        }
+      ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          sinon.spy(params, 'callback');
+          credentials.getCredentialSuccessCallback(item.data, null, item.hasOwnProperty('callback') ? {
+            callback: item.callback
+          } : params);
+        });
+
+        afterEach(function () {
+          params.callback.restore();
+        });
+
+        it('callback call count', function () {
+          expect(params.callback.callCount).to.equal(item.callbackCallCount);
+        });
+
+        if (item.callbackCallCount) {
+          it('callback argument', function () {
+            expect(params.callback.firstCall.args).to.eql([item.callbackArgument]);
+          });
+        }
+
+      });
+
+    });
+
+  });
+
+  describe('#updateCredentials', function () {
+
+    it('should send AJAX request', function () {
+      credentials.updateCredentials('c', 'a', {});
+      expect(testHelpers.findAjaxRequest('name', 'credentials.update')).to.eql([
+        {
+          sender: credentials,
+          name: 'credentials.update',
+          data: {
+            clusterName: 'c',
+            alias: 'a',
+            resource: {}
+          }
+        }
+      ]);
+    });
+
+  });
+
+  describe('#credentials', function () {
+
+    it('should send AJAX request', function () {
+      credentials.credentials('c', Em.K);
+      expect(testHelpers.findAjaxRequest('name', 'credentials.list')).to.eql([
+        {
+          sender: credentials,
+          name: 'credentials.list',
+          data: {
+            clusterName: 'c',
+            callback: Em.K
+          },
+          success: 'credentialsSuccessCallback'
+        }
+      ]);
+    });
+
+  });
+
+  describe('#removeCredentials', function () {
+
+    it('should send AJAX request', function () {
+      credentials.removeCredentials('c', 'a');
+      expect(testHelpers.findAjaxRequest('name', 'credentials.delete')).to.eql([
+        {
+          sender: credentials,
+          name: 'credentials.delete',
+          data: {
+            clusterName: 'c',
+            alias: 'a'
+          }
+        }
+      ]);
+    });
+
+  });
+
+  describe('#storageInfo', function () {
+
+    it('should send AJAX request', function () {
+      credentials.storageInfo('c', Em.K);
+      expect(testHelpers.findAjaxRequest('name', 'credentials.store.info')).to.eql([
+        {
+          sender: credentials,
+          name: 'credentials.store.info',
+          data: {
+            clusterName: 'c',
+            callback: Em.K
+          },
+          success: 'storageInfoSuccessCallback'
+        }
+      ]);
+    });
+
+  });
+
+  describe('#storageInfoSuccessCallback', function () {
+
+    var params = {
+        callback: Em.K
+      },
+      cases = [
+        {
+          callbackArgument: null,
+          title: 'no clusters'
+        },
+        {
+          clusters: null,
+          callbackArgument: null,
+          title: 'invalid clusters info'
+        },
+        {
+          clusters: {},
+          callbackArgument: {
+            persistent: false,
+            temporary: false
+          },
+          title: 'empty clusters info'
+        },
+        {
+          clusters: {
+            credential_store_properties: {
+              'storage.persistent': true,
+              'storage.temporary': true
+            }
+          },
+          callbackArgument: {
+            persistent: false,
+            temporary: false
+          },
+          title: 'invalid storage properties format'
+        },
+        {
+          clusters: {
+            credential_store_properties: {}
+          },
+          callbackArgument: {
+            persistent: false,
+            temporary: false
+          },
+          title: 'no storage properties'
+        },
+        {
+          clusters: {
+            credential_store_properties: {
+              'storage.persistent': 'true',
+              'storage.temporary': 'false'
+            }
+          },
+          callbackArgument: {
+            persistent: true,
+            temporary: false
+          },
+          title: 'valid storage properties format - persistent storage'
+        },
+        {
+          clusters: {
+            credential_store_properties: {
+              'storage.persistent': 'false',
+              'storage.temporary': 'true'
+            }
+          },
+          callbackArgument: {
+            persistent: false,
+            temporary: true
+          },
+          title: 'valid storage properties format - temporary storage'
+        },
+        {
+          clusters: {
+            credential_store_properties: {
+              'storage.persistent': 'true',
+              'storage.temporary': 'true'
+            }
+          },
+          callbackArgument: {
+            persistent: true,
+            temporary: true
+          },
+          title: 'valid storage properties format - both types'
+        }
+      ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        beforeEach(function () {
+          sinon.spy(params, 'callback');
+          credentials.storageInfoSuccessCallback({
+            Clusters: item.clusters
+          }, null, params);
+        });
+
+        afterEach(function () {
+          params.callback.restore();
+        });
+
+        it('callback execution', function () {
+          expect(params.callback.calledOnce).to.be.true;
+        });
+
+        it('callback argument', function () {
+          expect(params.callback.firstCall.args).to.eql([item.callbackArgument]);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#isStorePersisted', function () {
+
+    beforeEach(function () {
+      sinon.stub(credentials, 'storeTypeStatus', storeTypeStatusMock);
+    });
+
+    afterEach(function () {
+      credentials.storeTypeStatus.restore();
+    });
+
+    it('should return storeTypeStatus result', function () {
+      expect(credentials.isStorePersisted('c')).to.eql({
+        persistent: 'c'
+      });
+    });
+
+  });
+
+
+  describe('#isStoreTemporary', function () {
+
+    beforeEach(function () {
+      sinon.stub(credentials, 'storeTypeStatus', storeTypeStatusMock);
+    });
+
+    afterEach(function () {
+      credentials.storeTypeStatus.restore();
+    });
+
+    it('should return storeTypeStatus result', function () {
+      expect(credentials.isStoreTemporary('c')).to.eql({
+        temporary: 'c'
+      });
+    });
+
+  });
+
+  describe('#storeTypeStatus', function () {
+
+    var mock = {
+        successCallback: Em.K,
+        errorCallback: Em.K
+      },
+      data = {
+        clusterName: 'c'
+      },
+      error = {
+        status: 404
+      },
+      cases = [
+        {
+          isSuccess: true,
+          callbackArgument: data,
+          title: 'success'
+        },
+        {
+          isSuccess: false,
+          callbackArgument: error,
+          title: 'fail'
+        }
+      ];
+
+    cases.forEach(function (item) {
+
+      describe(item.title, function () {
+
+        var callbackName = item.isSuccess ? 'successCallback' : 'errorCallback';
+
+        beforeEach(function () {
+          sinon.spy(mock, 'successCallback');
+          sinon.spy(mock, 'errorCallback');
+          sinon.stub(credentials, 'storageInfo', function (clusterName, callback) {
+            var dfd = $.Deferred();
+            if (item.isSuccess) {
+              callback({
+                temporary: data
+              });
+            } else {
+              dfd.reject(error);
+            }
+            return dfd.promise();
+          });
+          credentials.storeTypeStatus(null, 'temporary').then(mock.successCallback, mock.errorCallback);
+        });
+
+        afterEach(function () {
+          mock.successCallback.restore();
+          mock.errorCallback.restore();
+          credentials.storageInfo.restore();
+        });
+
+        it('success callback', function () {
+          expect(mock.successCallback.called).to.equal(item.isSuccess);
+        });
+
+        it('error callback', function () {
+          expect(mock.errorCallback.called).to.not.equal(item.isSuccess);
+        });
+
+        it('callback called once', function () {
+          expect(mock[callbackName].calledOnce).to.be.true;
+        });
+
+        it('callback arguments', function () {
+          expect(mock[callbackName].firstCall.args).to.eql([item.callbackArgument]);
+        });
+
+      });
+
+    });
+
+  });
+
+  describe('#createCredentialResource', function () {
+
+    it('should return object with arguments', function () {
+      expect(credentials.createCredentialResource('p', 'c', 't')).to.eql({
+        principal: 'p',
+        key: 'c',
+        type: 't'
+      });
+    });
+
+  });
+
+  describe('#isKDCCredentialsPersisted', function () {
+
+    var cases = [
+      {
+        credentials: [],
+        isKDCCredentialsPersisted: false,
+        title: 'empty array passed'
+      },
+      {
+        credentials: [{}, {}],
+        isKDCCredentialsPersisted: false,
+        title: 'no aliases passed'
+      },
+      {
+        credentials: [
+          {
+            alias: 'a0'
+          },
+          {
+            alias: 'a1'
+          }
+        ],
+        isKDCCredentialsPersisted: false,
+        title: 'no KDC admin credentials passed'
+      },
+      {
+        credentials: [
+          {
+            alias: 'kdc.admin.credential'
+          },
+          {
+            alias: 'a2'
+          }
+        ],
+        isKDCCredentialsPersisted: false,
+        title: 'no KDC admin credentials type passed'
+      },
+      {
+        credentials: [
+          {
+            alias: 'kdc.admin.credential',
+            type: 'temporary'
+          },
+          {
+            alias: 'a3'
+          }
+        ],
+        isKDCCredentialsPersisted: false,
+        title: 'temporary storage'
+      },
+      {
+        credentials: [
+          {
+            alias: 'kdc.admin.credential',
+            type: 'persisted'
+          },
+          {
+            alias: 'kdc.admin.credential'
+          },
+          {
+            alias: 'a4'
+          }
+        ],
+        isKDCCredentialsPersisted: true,
+        title: 'persistent storage'
+      }
+    ];
+
+    cases.forEach(function (item) {
+
+      it(item.title, function () {
+        expect(credentials.isKDCCredentialsPersisted(item.credentials)).to.equal(item.isKDCCredentialsPersisted);
+      });
+
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/file_utils_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/file_utils_test.js b/ambari-web/test/utils/file_utils_test.js
new file mode 100644
index 0000000..8c9eb6d
--- /dev/null
+++ b/ambari-web/test/utils/file_utils_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.
+ */
+
+var fileUtils = require('utils/file_utils');
+
+describe('file_utils', function () {
+
+  describe('#openInfoInNewTab', function () {
+
+    var mock = {
+      document: {
+        write: Em.K
+      },
+      focus: Em.K
+    };
+
+    beforeEach(function () {
+      sinon.stub(window, 'open').returns(mock);
+      sinon.spy(mock.document, 'write');
+      sinon.spy(mock, 'focus');
+      fileUtils.openInfoInNewTab('data');
+    });
+
+    afterEach(function () {
+      window.open.restore();
+      mock.document.write.restore();
+      mock.focus.restore();
+    });
+
+    it('opening new window', function () {
+      expect(window.open.calledOnce).to.be.true;
+    });
+
+    it('no URL for new window', function () {
+      expect(window.open.firstCall.args).to.eql(['']);
+    });
+
+    it('writing document contents', function () {
+      expect(mock.document.write.calledOnce).to.be.true;
+    });
+
+    it('document contents', function () {
+      expect(mock.document.write.firstCall.args).to.eql(['data']);
+    });
+
+    it('focusing on new window', function () {
+      expect(mock.focus.calledOnce).to.be.true;
+    });
+
+  });
+
+  describe('#safariDownload', function () {
+
+    var linkEl = {
+      click: Em.K
+    };
+
+    beforeEach(function () {
+      sinon.stub(document, 'createElement').returns(linkEl);
+      sinon.stub(document.body, 'appendChild', Em.K);
+      sinon.stub(document.body, 'removeChild', Em.K);
+      sinon.spy(linkEl, 'click');
+      fileUtils.safariDownload('file data', 'csv', 'file.csv');
+    });
+
+    afterEach(function () {
+      document.createElement.restore();
+      document.body.appendChild.restore();
+      document.body.removeChild.restore();
+      linkEl.click.restore();
+    });
+
+    it('creating new element', function () {
+      expect(document.createElement.calledOnce).to.be.true;
+    });
+
+    it('new element is a link', function () {
+      expect(document.createElement.firstCall.args).to.eql(['a']);
+    });
+
+    it('link URL', function () {
+      expect(linkEl.href).to.equal('data:attachment/csv;charset=utf-8,file%20data');
+    });
+
+    it('file name', function () {
+      expect(linkEl.download).to.equal('file.csv');
+    });
+
+    it('appending element to document', function () {
+      expect(document.body.appendChild.calledOnce).to.be.true;
+    });
+
+    it('link is appended', function () {
+      expect(document.body.appendChild.firstCall.args).to.eql([linkEl]);
+    });
+
+    it('link is clicked', function () {
+      expect(linkEl.click.calledOnce).to.be.true;
+    });
+
+    it('removing element from document', function () {
+      expect(document.body.removeChild.calledOnce).to.be.true;
+    });
+
+    it('link is removed', function () {
+      expect(document.body.removeChild.firstCall.args).to.eql([linkEl]);
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/handlebars_helpers_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/handlebars_helpers_test.js b/ambari-web/test/utils/handlebars_helpers_test.js
new file mode 100644
index 0000000..4e705ad
--- /dev/null
+++ b/ambari-web/test/utils/handlebars_helpers_test.js
@@ -0,0 +1,57 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+require('utils/handlebars_helpers');
+
+describe('handlebars_helpers', function () {
+
+  describe('#registerBoundHelper', function () {
+
+    var options = {
+      hash: {}
+    };
+
+    beforeEach(function () {
+      sinon.stub(Em.Handlebars, 'registerHelper', function (name, callback) {
+        callback('prop', options);
+      });
+      sinon.stub(Em.Handlebars.helpers, 'view', Em.K);
+      App.registerBoundHelper('helper', {});
+    });
+
+    afterEach(function () {
+      Em.Handlebars.registerHelper.restore();
+      Em.Handlebars.helpers.view.restore();
+    });
+
+    it('contentBinding', function () {
+      expect(options.hash.contentBinding).to.equal('prop');
+    });
+
+    it('view', function () {
+      expect(Em.Handlebars.helpers.view.calledOnce).to.be.true;
+    });
+
+    it('view arguments', function () {
+      expect(Em.Handlebars.helpers.view.firstCall.args).to.eql([{}, options]);
+    });
+
+  });
+
+});

http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/heatmap_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/heatmap_test.js b/ambari-web/test/utils/heatmap_test.js
new file mode 100644
index 0000000..0a63cbf
--- /dev/null
+++ b/ambari-web/test/utils/heatmap_test.js
@@ -0,0 +1,141 @@
+/**
+ * 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.
+ */
+
+var heatmap = require('utils/heatmap');
+
+describe('heatmap utils', function () {
+
+  describe('mappers', function () {
+
+    var mappers;
+
+    beforeEach(function () {
+      mappers = Em.Object.create(heatmap.mappers);
+    });
+
+    describe('#metricMapperWithTransform', function () {
+
+      var cases = [
+        {
+          hostComponents: null,
+          hostToValueMap: {},
+          title: 'no host components data'
+        },
+        {
+          hostComponents: [null, null],
+          metricName: 'm0',
+          hostToValueMap: {},
+          title: 'host components data is absent'
+        },
+        {
+          hostComponents: [{}, {}],
+          metricName: 'm1',
+          hostToValueMap: {},
+          title: 'provided metric data is absent'
+        },
+        {
+          hostComponents: [{}, {}],
+          metricName: 'm2.m3',
+          hostToValueMap: {},
+          title: 'provided metrics data is absent'
+        },
+        {
+          hostComponents: [
+            null,
+            {},
+            {
+              m4: 1,
+              HostRoles: {
+                host_name: 'h0'
+              }
+            },
+            {
+              m4: 1.5,
+              HostRoles: {
+                host_name: 'h1'
+              }
+            },
+            {
+              m4: 1.60,
+              HostRoles: {
+                host_name: 'h2'
+              }
+            },
+            {
+              m4: 1.72,
+              HostRoles: {
+                host_name: 'h3'
+              }
+            },
+            {
+              m4: 1.85,
+              HostRoles: {
+                host_name: 'h4'
+              }
+            },
+            {
+              m4: 1.97,
+              HostRoles: {
+                host_name: 'h5'
+              }
+            }
+          ],
+          metricName: 'm4',
+          hostToValueMap: {
+            h0: '1.0',
+            h1: '1.5',
+            h2: '1.6',
+            h3: '1.7',
+            h4: '1.9',
+            h5: '2.0'
+          },
+          title: 'no transform function'
+        },
+        {
+          hostComponents: [
+            {
+              m5: 100,
+              HostRoles: {
+                host_name: 'h6'
+              }
+            }
+          ],
+          metricName: 'm5',
+          transformValueFunction: Math.sqrt,
+          hostToValueMap: {
+            h6: '10.0'
+          },
+          title: 'transform function provided'
+        }
+      ];
+
+      cases.forEach(function (item) {
+
+        it(item.title, function () {
+          expect(mappers.metricMapperWithTransform({
+            host_components: item.hostComponents
+          }, item.metricName, item.transformValueFunction)).to.eql(item.hostToValueMap);
+        });
+
+      });
+
+    });
+
+  });
+
+});


[2/3] ambari git commit: AMBARI-15596. Add missing unit tests files for ambari-web utils (alexantonenko)

Posted by al...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/d5d1afea/ambari-web/test/utils/hosts_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/utils/hosts_test.js b/ambari-web/test/utils/hosts_test.js
new file mode 100644
index 0000000..41fe555
--- /dev/null
+++ b/ambari-web/test/utils/hosts_test.js
@@ -0,0 +1,3467 @@
+/**
+ * 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.
+ */
+
+var App = require('app');
+var hostsUtils = require('utils/hosts');
+var validator = require('utils/validator');
+var testHelpers = require('test/helpers');
+
+describe('hosts utils', function () {
+
+  describe('#launchHostsSelectionDialog', function () {
+
+    var popup,
+      mock = {
+        callback: Em.K
+      };
+
+    beforeEach(function () {
+      sinon.stub(App.ModalPopup, 'show', Em.K);
+    });
+
+    afterEach(function () {
+      App.ModalPopup.show.restore();
+    });
+
+    describe('popup header and message', function () {
+
+      var cases = [
+        {
+          popupDescription: {},
+          header: Em.I18n.t('hosts.selectHostsDialog.title'),
+          dialogMessage: Em.I18n.t('hosts.selectHostsDialog.message'),
+          title: 'default header and message'
+        },
+        {
+          popupDescription: {
+            dialogMessage: 'Message 0'
+          },
+          header: Em.I18n.t('hosts.selectHostsDialog.title'),
+          dialogMessage: 'Message 0',
+          title: 'default header, custom message'
+        },
+        {
+          popupDescription: {
+            header: 'Header 0'
+          },
+          header: 'Header 0',
+          dialogMessage: Em.I18n.t('hosts.selectHostsDialog.message'),
+          title: 'custom header, default message'
+        },
+        {
+          popupDescription: {
+            header: 'Header 1',
+            dialogMessage: 'Message 1'
+          },
+          header: 'Header 1',
+          dialogMessage: 'Message 1',
+          title: 'custom header and message'
+        }
+      ];
+
+      cases.forEach(function (item) {
+
+        describe(item.title, function () {
+
+          beforeEach(function () {
+            hostsUtils.launchHostsSelectionDialog(null, null, null, null, null, item.popupDescription);
+            popup = Em.Object.create(App.ModalPopup.show.firstCall.args[0]);
+          });
+
+          it('header', function () {
+            expect(popup.get('header')).to.equal(item.header);
+          });
+
+          it('message', function () {
+            expect(popup.get('dialogMessage')).to.equal(item.dialogMessage);
+          });
+
+        });
+
+      });
+
+    });
+
+    describe('#onPrimary', function () {
+
+      var cases = [
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [],
+          warningMessage: Em.I18n.t('hosts.selectHostsDialog.message.warning'),
+          callbackCallCount: 0,
+          hideCallCount: 0,
+          title: 'no hosts available'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [],
+          hideCallCount: 1,
+          title: 'no hosts available, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: Em.I18n.t('hosts.selectHostsDialog.message.warning'),
+          callbackCallCount: 0,
+          hideCallCount: 0,
+          title: 'no selection state info'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [],
+          hideCallCount: 1,
+          title: 'no selection state info, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: false
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: Em.I18n.t('hosts.selectHostsDialog.message.warning'),
+          callbackCallCount: 0,
+          hideCallCount: 0,
+          title: 'no hosts selected'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: false
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [],
+          hideCallCount: 1,
+          title: 'no hosts selected, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: true
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined],
+          hideCallCount: 1,
+          title: '1 host selected, no host info'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: true
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined],
+          hideCallCount: 1,
+          title: '1 host selected, no host info, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: true,
+              host: {}
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined],
+          hideCallCount: 1,
+          title: '1 host selected, no host id'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: true,
+              host: {}
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined],
+          hideCallCount: 1,
+          title: '1 host selected, no host id, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: true,
+              host: {
+                id: 'h0'
+              }
+            },
+            {
+              selected: false,
+              host: {
+                id: 'h1'
+              }
+            },
+            {
+              host: {
+                id: 'h2'
+              }
+            },
+            {
+              selected: 1,
+              host: {
+                id: 'h3'
+              }
+            },
+            {
+              selected: 'true',
+              host: {
+                id: 'h4'
+              }
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: ['h0'],
+          hideCallCount: 1,
+          title: '1 host selected, host id available'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: true,
+              host: {
+                id: 'h5'
+              }
+            },
+            {
+              selected: false,
+              host: {
+                id: 'h6'
+              }
+            },
+            {
+              host: {
+                id: 'h7'
+              }
+            },
+            {
+              selected: 1,
+              host: {
+                id: 'h8'
+              }
+            },
+            {
+              selected: 'true',
+              host: {
+                id: 'h9'
+              }
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: ['h5'],
+          hideCallCount: 1,
+          title: '1 host selected, host id available, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: true
+            },
+            {
+              selected: true
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined, undefined],
+          hideCallCount: 1,
+          title: 'more than 1 host selected, no host info'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: true
+            },
+            {
+              selected: true
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined, undefined],
+          hideCallCount: 1,
+          title: 'more than 1 host selected, no host info, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: true,
+              host: {}
+            },
+            {
+              selected: true,
+              host: {}
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined, undefined],
+          hideCallCount: 1,
+          title: 'more than 1 host selected, no host id'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: true,
+              host: {}
+            },
+            {
+              selected: true,
+              host: {}
+            },
+            {
+              selected: false
+            },
+            {},
+            {
+              selected: 1
+            },
+            {
+              selected: 'true'
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: [undefined, undefined],
+          hideCallCount: 1,
+          title: 'more than 1 host selected, no host id, no selection requirement'
+        },
+        {
+          selectAtleastOneHost: true,
+          availableHosts: [
+            {
+              selected: true,
+              host: {
+                id: 'h10'
+              }
+            },
+            {
+              selected: true,
+              host: {
+                id: 'h11'
+              }
+            },
+            {
+              selected: false,
+              host: {
+                id: 'h12'
+              }
+            },
+            {
+              host: {
+                id: 'h13'
+              }
+            },
+            {
+              selected: 1,
+              host: {
+                id: 'h14'
+              }
+            },
+            {
+              selected: 'true',
+              host: {
+                id: 'h15'
+              }
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: ['h10', 'h11'],
+          hideCallCount: 1,
+          title: 'more than 1 host selected, host ids available'
+        },
+        {
+          selectAtleastOneHost: false,
+          availableHosts: [
+            {
+              selected: true,
+              host: {
+                id: 'h16'
+              }
+            },
+            {
+              selected: true,
+              host: {
+                id: 'h17'
+              }
+            },
+            {
+              selected: false,
+              host: {
+                id: 'h18'
+              }
+            },
+            {
+              host: {
+                id: 'h19'
+              }
+            },
+            {
+              selected: 1,
+              host: {
+                id: 'h20'
+              }
+            },
+            {
+              selected: 'true',
+              host: {
+                id: 'h21'
+              }
+            }
+          ],
+          warningMessage: null,
+          callbackCallCount: 1,
+          arrayOfSelectedHosts: ['h16', 'h17'],
+          hideCallCount: 1,
+          title: 'more than 1 host selected, host ids available, no selection requirement'
+        }
+      ];
+
+      cases.forEach(function (item) {
+
+        describe(item.title, function () {
+
+          beforeEach(function () {
+            sinon.spy(mock, 'callback');
+            hostsUtils.launchHostsSelectionDialog(null, null, item.selectAtleastOneHost, null, mock.callback, {});
+            popup = Em.Object.create(App.ModalPopup.show.firstCall.args[0], {
+              warningMessage: '',
+              availableHosts: item.availableHosts,
+              hide: Em.K
+            });
+            sinon.spy(popup, 'hide');
+            popup.onPrimary();
+          });
+
+          afterEach(function () {
+            mock.callback.restore();
+            popup.hide.restore();
+          });
+
+          it('warning message', function () {
+            expect(popup.get('warningMessage')).to.equal(item.warningMessage);
+          });
+
+          it('callback', function () {
+            expect(mock.callback.callCount).to.equal(item.callbackCallCount);
+          });
+
+          if (item.callbackCallCount) {
+            it('callback argument', function () {
+              expect(mock.callback.firstCall.args).to.eql([item.arrayOfSelectedHosts]);
+            });
+          }
+
+          it('hide popup', function () {
+            expect(popup.hide.callCount).to.equal(item.hideCallCount);
+          });
+
+        });
+
+      });
+
+    });
+
+    describe('#disablePrimary', function () {
+
+      var cases = [
+        {
+          isLoaded: true,
+          disablePrimary: false,
+          title: 'enable button'
+        },
+        {
+          isLoaded: false,
+          disablePrimary: true,
+          title: 'disable button'
+        }
+      ];
+
+      cases.forEach(function (item) {
+
+        it(item.title, function () {
+          hostsUtils.launchHostsSelectionDialog(null, null, null, null, null, item.popupDescription);
+          popup = Em.Object.create(App.ModalPopup.show.firstCall.args[0], {
+            isLoaded: item.isLoaded
+          });
+          expect(popup.get('disablePrimary')).to.equal(item.disablePrimary);
+        });
+
+      });
+
+    });
+
+    describe('#onSecondary', function () {
+
+      beforeEach(function () {
+        sinon.spy(mock, 'callback');
+        hostsUtils.launchHostsSelectionDialog(null, null, null, null, mock.callback, {});
+        popup = Em.Object.create(App.ModalPopup.show.firstCall.args[0], {
+          hide: Em.K
+        });
+        sinon.spy(popup, 'hide');
+        popup.onSecondary();
+      });
+
+      afterEach(function () {
+        mock.callback.restore();
+        popup.hide.restore();
+      });
+
+      it('callback', function () {
+        expect(mock.callback.calledOnce).to.be.true;
+      });
+
+      it('callback argument', function () {
+        expect(mock.callback.firstCall.args).to.eql([null]);
+      });
+
+      it('hide popup', function () {
+        expect(popup.hide.calledOnce).to.be.true;
+      });
+
+    });
+
+    describe('#bodyClass', function () {
+
+      var view,
+        validComponents = [
+          {
+            componentName: 'c0'
+          },
+          {
+            componentName: 'c1'
+          }
+        ];
+
+      beforeEach(function () {
+        hostsUtils.launchHostsSelectionDialog([
+          {
+            host: {
+              id: 'h0'
+            },
+            filtered: false
+          },
+          {
+            host: {
+              id: 'h1'
+            }
+          }
+        ], null, null, validComponents, null, {});
+        popup = Em.Object.create(App.ModalPopup.show.firstCall.args[0]);
+        view = popup.get('bodyClass').create({
+          parentView: popup
+        });
+      });
+
+      describe('#filteredContentObs', function () {
+
+        beforeEach(function () {
+          sinon.stub(view, 'filteredContentObsOnce', Em.K);
+          sinon.stub(view, 'filterHosts', Em.K);
+          sinon.stub(Em.run, 'once', function (context, callback) {
+            callback.call(context);
+          });
+        });
+
+        afterEach(function () {
+          view.filteredContentObsOnce.restore();
+          view.filterHosts.restore();
+          Em.run.once.restore();
+        });
+
+        it('should run filteredContentObsOnce', function () {
+          popup.set('availableHosts', [
+            {
+              filtered: true
+            }
+          ]);
+          expect(view.filteredContentObsOnce.calledOnce).to.be.true;
+        });
+
+      });
+
+      describe('#filteredContentObsOnce', function () {
+
+        var cases = [
+          {
+            availableHosts: [],
+            filteredContent: [],
+            title: 'no hosts available'
+          },
+          {
+            availableHosts: [
+              {},
+              {
+                filtered: false
+              },
+              {
+                filtered: null
+              },
+              {
+                filtered: 0
+              }
+            ],
+            filteredContent: [],
+            title: 'no hosts filtered'
+          },
+          {
+            availableHosts: [
+              {},
+              {
+                filtered: false
+              },
+              {
+                filtered: null
+              },
+              {
+                filtered: 0
+              },
+              {
+                filtered: true
+              },
+              {
+                filtered: 'true'
+              },
+              {
+                filtered: 1
+              }
+            ],
+            filteredContent: [
+              {
+                filtered: true
+              },
+              {
+                filtered: 'true'
+              },
+              {
+                filtered: 1
+              }
+            ],
+            title: 'filtered hosts present'
+          }
+        ];
+
+        beforeEach(function () {
+          sinon.stub(view, 'filteredContentObs', Em.K);
+          sinon.stub(view, 'filterHosts', Em.K);
+        });
+
+        afterEach(function () {
+          view.filteredContentObs.restore();
+          view.filterHosts.restore();
+        });
+
+        cases.forEach(function (item) {
+
+          it(item.title, function () {
+            popup.set('availableHosts', item.availableHosts);
+            view.filteredContentObsOnce();
+            expect(view.get('filteredContent')).to.eql(item.filteredContent);
+          });
+
+        });
+
+      });
+
+      describe('#filterComponents', function () {
+
+        it('should be set from validComponents', function () {
+          expect(view.get('filterComponents')).to.eql(validComponents);
+        });
+
+      });
+
+      describe('#isDisabled', function () {
+
+        var cases = [
+          {
+            isLoaded: true,
+            isDisabled: false,
+            title: 'enabled'
+          },
+          {
+            isLoaded: false,
+            isDisabled: true,
+            title: 'disabled'
+          }
+        ];
+
+        cases.forEach(function (item) {
+
+          it(item.title, function () {
+            popup.set('isLoaded', item.isLoaded);
+            expect(view.get('isDisabled')).to.equal(item.isDisabled);
+          });
+
+        });
+
+      });
+
+      describe('#didInsertElement', function () {
+
+        beforeEach(function () {
+          sinon.stub(view, 'filterHosts', Em.K);
+          sinon.stub(view, 'filteredContentObs', Em.K);
+          sinon.stub(view, 'filteredContentObsOnce', Em.K);
+          view.get('filterColumns').setEach('selected', false);
+          view.get('filterColumns').findProperty('id', 'cpu').set('selected', true);
+          view.didInsertElement();
+        });
+
+        afterEach(function () {
+          view.filterHosts.restore();
+          view.filteredContentObs.restore();
+          view.filteredContentObsOnce.restore();
+        });
+
+        it('column for filter', function () {
+          expect(view.get('filterColumn')).to.eql(Em.Object.create({
+            id: 'cpu',
+            name: 'CPU',
+            selected: true
+          }));
+        });
+
+        it('available hosts', function () {
+          expect(view.get('parentView.availableHosts').toArray()).to.eql([
+            {
+              host: {
+                id: 'h0'
+              },
+              filtered: true
+            },
+            {
+              host: {
+                id: 'h1'
+              },
+              filtered: true
+            }
+          ]);
+        });
+
+        it('isLoaded', function () {
+          expect(view.get('parentView.isLoaded')).to.be.true;
+        });
+
+        it('observer called', function () {
+          expect(view.filteredContentObsOnce.calledOnce).to.be.true;
+        });
+
+      });
+
+      describe('#filterHosts', function () {
+
+        var cases = [
+          {
+            filterText: '',
+            filterComponent: null,
+            showOnlySelectedHosts: true,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: false
+              })
+            ],
+            title: 'no filter text, no component for filter, show selected hosts only'
+          },
+          {
+            filterText: '',
+            filterComponent: null,
+            showOnlySelectedHosts: false,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: true
+              })
+            ],
+            title: 'no filter text, no component for filter, show all hosts'
+          },
+          {
+            filterText: 'n',
+            filterComponent: null,
+            showOnlySelectedHosts: true,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                selected: true,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              })
+            ],
+            title: 'filter text set, no component for filter, show selected hosts only'
+          },
+          {
+            filterText: 'n',
+            filterComponent: null,
+            showOnlySelectedHosts: false,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                selected: true,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                selected: false,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: true
+              })
+            ],
+            title: 'filter text set, no component for filter, show all hosts'
+          },
+          {
+            filterText: '',
+            filterComponent: Em.Object.create({
+              componentName: 'c0'
+            }),
+            showOnlySelectedHosts: true,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: false
+              })
+            ],
+            title: 'no filter text, component filter set, show selected hosts only'
+          },
+          {
+            filterText: '',
+            filterComponent: Em.Object.create({
+              componentName: 'c1'
+            }),
+            showOnlySelectedHosts: false,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  osType: 'centos7'
+                }),
+                hostComponentNames: ['c1', 'c2'],
+                selected: false,
+                filterColumnValue: 'centos7',
+                filtered: true
+              })
+            ],
+            title: 'no filter text, component filter set, show all hosts'
+          },
+          {
+            filterText: 'n',
+            filterComponent: Em.Object.create({
+              componentName: 'c2'
+            }),
+            showOnlySelectedHosts: true,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h12'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h13'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn14'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn15'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h16',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h17',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn18',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn19',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h20',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h21',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn22',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn23',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h24'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h25'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn26'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn27'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h28',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h29',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn30',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn31',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h32',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h33',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn34',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn35',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h12'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h13'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn14'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn15'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h16',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h17',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn18',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn19',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h20',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h21',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn22',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn23',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h24'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h25'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn26'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn27'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h28',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h29',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn30',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn31',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h32',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h33',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn34',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn35',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c2'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              })
+            ],
+            title: 'filter text set, component filter set, show selected hosts only'
+          },
+          {
+            filterText: 'n',
+            filterComponent: Em.Object.create({
+              componentName: 'c3'
+            }),
+            showOnlySelectedHosts: false,
+            availableHosts: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h12'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h13'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn14'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn15'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h16',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h17',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn18',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn19',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h20',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h21',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn22',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn23',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h24'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h25'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn26'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn27'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h28',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h29',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn30',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn31',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h32',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h33',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn34',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn35',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false
+              })
+            ],
+            result: [
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h0'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h1'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn2'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn3'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h4',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h5',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn6',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn7',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h8',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h9',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn10',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn11',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: [],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h12'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h13'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn14'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn15'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h16',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h17',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn18',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn19',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h20',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h21',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn22',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn23',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c1'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h24'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h25'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false,
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn26'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn27'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false,
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h28',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h29',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn30',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn31',
+                  osType: 'centos6'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false,
+                filterColumnValue: 'centos6',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h32',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'h33',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: false
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn34',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: true,
+                filterColumnValue: 'suse11',
+                filtered: true
+              }),
+              Em.Object.create({
+                host: Em.Object.create({
+                  publicHostName: 'hn35',
+                  osType: 'suse11'
+                }),
+                hostComponentNames: ['c0', 'c3'],
+                selected: false,
+                filterColumnValue: 'suse11',
+                filtered: true
+              })
+            ],
+            title: 'filter text set, component filter set, show all hosts'
+          }
+        ];
+
+        cases.forEach(function (item) {
+
+          var arrayForCheck;
+
+          it(item.title, function () {
+            view.setProperties({
+              'showOnlySelectedHosts': item.showOnlySelectedHosts,
+              'filterText': item.filterText,
+              'filterCompon

<TRUNCATED>