');
    
    stop();
    $listView.listView({
      listView: {
        section: 'test',
        fields: {
          fieldA: { label: 'testFieldA' },
          fieldB: { label: 'testFieldB' },
          fieldC: { label: 'testFieldC' }
        },
        preFilter: function(args) {
          return ['fieldC'];
        },
        dataProvider: function(args) {
          args.response.success({
            data: [
              {
                fieldA: '1A',
                fieldB: '1B',
                fieldC: '1C'
              }
            ]
          });
          setTimeout(function() {
            start();
            equal($listView.find('thead th').size(), 2, 'Correct # of filtered columns present');
            equal($listView.find('tbody tr:first td').size(), 2, 'Correct # of body columns present');
            equal($listView.find('tbody tr:first td.fieldA span').html(), '1A', 'Correct table item value for data row');
            equal($listView.find('tbody tr:first td.fieldB span').html(), '1B', 'Correct table item value for data row');
          });
        }
      }
    });
  });
  test('Section select', function() {
    var $listView = $('
');
    
    ok($listView.listView({
      sectionSelect: {
        label: 'testSectionSelect'
      },
      sections: {
        sectionA: {
          type: 'select',
          title: 'sectionA',
          listView: {
            fields: {
              fieldA: { label: 'testFieldA' },
              fieldB: { label: 'testFieldB' }
            },
            dataProvider: function(args) {
              args.response.success({
                data: [
                  {
                    fieldA: '1A',
                    fieldB: '1B'
                  },
                  {
                    fieldA: '2A',
                    fieldB: '2B'
                  }
                ]
              });
            }
          }  
        },
        
        sectionB: {
          type: 'select',
          title: 'sectionB',
          listView: {
            fields: {
              fieldC: { label: 'testFieldC' },
              fieldD: { label: 'testFieldD' },
              fieldE: { label: 'testFieldE' }
            },
            dataProvider: function(args) {
              args.response.success({
                data: [
                  {
                    fieldC: '1C',
                    fieldD: '1D',
                    fieldE: '1E'
                  },
                  {
                    fieldC: '2C',
                    fieldD: '2D',
                    fieldE: '2E'
                  },
                  {
                    fieldC: '3C',
                    fieldD: '3D',
                    fieldE: '3E'
                  },
                  {
                    fieldC: '4C',
                    fieldD: '4D',
                    fieldE: '4E'
                  }
                ]
              });
            }
          }
        }
      }
    }));
    equal($listView.find('.toolbar .section-switcher').size(), 1,
          'Section switcher present in toolbar');
    equal($listView.find('.toolbar .section-switcher .section-select select').size(), 1,
          'Section select present');
    equal($listView.find('.toolbar .section-switcher .section-select label').html(),
          'testSectionSelect' + ':',
          'Section select label is correct');
    equal($listView.find('.toolbar .section-switcher .section-select select option').size(), 2,
          'Selectable sections present as options');
    equal($listView.find('.toolbar .section-switcher .section-select select option:first').html(), 'sectionA',
          'First select has correct title');
    equal($listView.find('.toolbar .section-switcher .section-select select option:selected')[0],
          $listView.find('.toolbar .section-switcher .section-select select option:first')[0],
          'First section option is selected by default');
    equal($listView.find('.toolbar .section-switcher .section-select select option:last').html(), 'sectionB', 'Last select has correct title');
    equal($listView.find('.list-view thead th').size(), 2, 'Correct list view column count present');
    equal($listView.find('.list-view thead th:first').html(), 'testFieldA', 'Column 1 is labeled correctly');
    equal($listView.find('.list-view thead th:last').html(), 'testFieldB', 'Column 2 is labeled correctly');
    equal($listView.find('.list-view tbody tr').size(), 2, 'Correct # of data rows present');
    equal($listView.find('.list-view tbody tr:first td').size(), 2, 'Correct # of data columns present');
    
    $listView.find('.toolbar .section-switcher select').val('sectionB');
    stop();
    ok($listView.find('.toolbar .section-switcher select').change(), 'Change section');
    start();
    
    equal($listView.find('.list-view thead th').size(), 3, 'Correct list view column count present');
    equal($listView.find('.list-view thead th:first').html(), 'testFieldC', 'Column 1 is labeled correctly');
    equal($($listView.find('.list-view thead th')[1]).html(), 'testFieldD', 'Column 2 is labeled correctly');
    equal($listView.find('.list-view thead th:last').html(), 'testFieldE', 'Column 3 is labeled correctly');
    equal($listView.find('.list-view tbody tr').size(), 4, 'Correct # of data rows present');
    equal($listView.find('.list-view tbody tr:first td').size(), 3, 'Correct # of data columns present');
    equal($listView.find('.list-view tbody tr:first td:first span').html(), '1C', 'First table cell has correct data');
    equal($listView.find('.list-view tbody tr:last td:last span').html(), '4E', 'Last table cell has correct data');
    $listView.find('.toolbar .section-switcher select').val('sectionA');
    stop();
    ok($listView.find('.toolbar .section-switcher select').change(), 'Change section');
    start();
    equal($listView.find('.toolbar .section-switcher .section-select select option:last').html(), 'sectionB', 'Last select has correct title');
    equal($listView.find('.list-view thead th').size(), 2, 'Correct list view column count present');
    equal($listView.find('.list-view thead th:first').html(), 'testFieldA', 'Column 1 is labeled correctly');
    equal($listView.find('.list-view thead th:last').html(), 'testFieldB', 'Column 2 is labeled correctly');
    equal($listView.find('.list-view tbody tr').size(), 2, 'Correct # of data rows present');
    equal($listView.find('.list-view tbody tr:first td').size(), 2, 'Correct # of data columns present');
    equal($listView.find('.list-view tbody tr:first td:first span').html(), '1A', 'First table cell has correct data');
    equal($listView.find('.list-view tbody tr:last td:last span').html(), '2B', 'Last table cell has correct data');
  });
  test('Basic sync action', function() {
    var $cloudStack = $('
').appendTo('#qunit-fixture');
    var listView = {
      listView: {
        section: 'test123',
        fields: {
          fieldA: { label: 'testFieldA' },
          fieldB: { label: 'testFieldB' }
        },
        actions: {
          basicSync: {
            label: 'basicAction',
            messages: {
              confirm: function() {
                return 'basicActionConfirm';
              },
              notification: function() {
                return 'basicActionNotification';
              }
            },
            action: function(args) {
              args.response.success();
            }
          }
        },
        dataProvider: function(args) {
          args.response.success({
            data: [
              {
                fieldA: '1A',
                fieldB: '1B',
                fieldC: '1C'
              },
              {
                fieldA: '2A',
                fieldB: '2B',
                fieldC: '2C'
              }
            ]
          });
        }
      }
    };
    // CloudStack object is needed for notification handling for actions
    var cloudStack = {
      sections: {
        testActions: listView
      },
      home: 'testActions'
    };
    
    ok($cloudStack.cloudStack(cloudStack), 'Initialize cloudStack widget w/ list view');
    var $listView = $cloudStack.find('.list-view');
    
    equal($listView.find('table thead th').size(), 3, 'Correct header column count');
    equal($listView.find('table thead th.actions').size(), 1, 'Action header column present');
    equal($listView.find('table tbody tr:first td').size(), 3, 'Correct data column count');
    equal($listView.find('table tbody tr:first td.actions').size(), 1, 'Action data column present');
    equal($listView.find('table tbody tr:first td.actions .action').size(), 1, 'Correct action count');
    equal($listView.find('table tbody tr:first td.actions .action:first .icon').size(), 1, 'Action has icon');
    ok($listView.find('table tbody tr:first td.actions .action:first').hasClass('basicSync'),
       'First action has ID as CSS class');
    ok($listView.find('td.actions .action:first').click(), 'Click first action');
    equal($('.ui-dialog.confirm .message').html(), 'basicActionConfirm', 'Confirmation message present');
    // Make sure dialog is cleaned up -- always put below all confirm tests
    $(':ui-dialog, .overlay').appendTo('#qunit-fixture');
    ok($('.ui-dialog.confirm .ui-button.ok').click(), 'Confirm action');
    equal($cloudStack.find('.notifications .total span').html(), '1', 'Notification total increased');
    equal($('.notification-box ul li').size(), 1, 'Notification list has 1 item');
    equal($('.notification-box ul li span').html(), 'basicActionNotification', 'Notification list item has correct label');
    ok($('.notification-box ul li').hasClass('pending'), 'Notification has pending state');
    stop();
    setTimeout(function() {
      start();
      ok(!$('.notification-box ul li').hasClass('pending'), 'Notification has completed state');
    });
  });
  test('Async action', function() {
    var $cloudStack = $('
').appendTo('#qunit-fixture');
    var listView = {
      listView: {
        id: 'testAsyncListView',
        fields: {
          fieldA: { label: 'testFieldA' },
          fieldB: { label: 'testFieldB' }
        },
        actions: {
          asyncTest: {
            label: 'asyncAction',
            messages: {
              confirm: function() {
                return 'asyncActionConfirm';
              },
              notification: function() {
                return 'asyncActionNotification';
              }
            },
            action: function(args) {
              ok($.isArray(args.context.testAsyncListView), 'List view context passed');
              args.response.success({
                _custom: {
                  jobId: 'job123'
                }
              });
            },
            notification: {
              interval: 0,
              poll: function(args) {
                start();
                equal(args._custom.jobId, 'job123', 'Job ID passed correctly');
                args.complete();
              }
            }
          }
        },
        dataProvider: function(args) {
          args.response.success({
            data: [
              {
                fieldA: '1A',
                fieldB: '1B',
                fieldC: '1C'
              },
              {
                fieldA: '2A',
                fieldB: '2B',
                fieldC: '2C'
              }
            ]
          });
        }
      }
    };
    // CloudStack object is needed for notification handling for actions
    var cloudStack = {
      sections: {
        testActions: listView
      },
      home: 'testActions'
    };
    
    ok($cloudStack.cloudStack(cloudStack), 'Initialize cloudStack widget w/ list view');
    var $listView = $cloudStack.find('.list-view');
    
    equal($listView.find('table thead th').size(), 3, 'Correct header column count');
    equal($listView.find('table thead th.actions').size(), 1, 'Action header column present');
    equal($listView.find('table tbody tr:first td').size(), 3, 'Correct data column count');
    equal($listView.find('table tbody tr:first td.actions').size(), 1, 'Action data column present');
    equal($listView.find('table tbody tr:first td.actions .action').size(), 1, 'Correct action count');
    equal($listView.find('table tbody tr:first td.actions .action:first .icon').size(), 1, 'Action has icon');
    ok($listView.find('table tbody tr:first td.actions .action:first').hasClass('asyncTest'),
       'First action has ID as CSS class');
    ok($listView.find('td.actions .action:first').click(), 'Click first action');
    equal($('.ui-dialog.confirm .message').html(), 'asyncActionConfirm', 'Confirmation message present');
    // Make sure dialog is cleaned up -- always put below all confirm tests
    $(':ui-dialog, .overlay').appendTo('#qunit-fixture');
    ok($('.ui-dialog.confirm .ui-button.ok').click(), 'Confirm action');
    equal($cloudStack.find('.notifications .total span').html(), '1', 'Notification total increased');
    equal($('.notification-box ul li').size(), 1, 'Notification list has 1 item');
    equal($('.notification-box ul li span').html(), 'asyncActionNotification', 'Notification list item has correct label');
    ok($('.notification-box ul li').hasClass('pending'), 'Notification has pending state');
    stop();
  });
  test('Action filter', function() {
    var $cloudStack = $('
').appendTo('#qunit-fixture');
    var listView = {
      listView: {
        id: 'testAsyncListView',
        fields: {
          fieldA: { label: 'testFieldA' },
          fieldB: { label: 'testFieldB' }
        },
        actions: {
          actionA: {
            label: 'actionA',
            messages: {
              confirm: function() { return ''; },
              notification: function() { return ''; }
            },
            action: function(args) { args.response.success(); }
          },
          actionB: {
            label: 'actionB [HIDDEN]',
            messages: {
              confirm: function() { return ''; },
              notification: function() { return ''; }
            },
            action: function(args) { args.response.success(); }
          },
          actionC: {
            label: 'actionC',
            messages: {
              confirm: function() { return ''; },
              notification: function() { return ''; }
            },
            action: function(args) { args.response.success(); }
          }
        },
        dataProvider: function(args) {
          args.response.success({
            actionFilter: function() {
              return ['actionA', 'actionC'];
            },
            data: [
              {
                fieldA: '1A',
                fieldB: '1B',
                fieldC: '1C'
              },
              {
                fieldA: '2A',
                fieldB: '2B',
                fieldC: '2C'
              }
            ]
          });
        }
      }
    };
    // CloudStack object is needed for notification handling for actions
    var cloudStack = {
      sections: {
        testActions: listView
      },
      home: 'testActions'
    };
    
    ok($cloudStack.cloudStack(cloudStack), 'Initialize cloudStack widget w/ list view');
    var $listView = $cloudStack.find('.list-view');
    
    equal($listView.find('table thead th').size(), 3, 'Correct header column count');
    equal($listView.find('table thead th.actions').size(), 1, 'Action header column present');
    equal($listView.find('table tbody tr:first td.actions').size(), 1, 'Action data column present');
    equal($listView.find('table tbody tr:first td.actions .action').size(), 3, 'Correct action count (all)');
    equal($listView.find('table tbody tr:first td.actions .action:not(.disabled)').size(), 2, 'Correct action count (enabled)');
    ok($listView.find('table tbody tr:first td.actions .action:first').hasClass('actionA'),
       'First action has correct ID');
    ok($listView.find('table tbody tr:first td.actions .action:last').hasClass('actionC'),
       'Last action has correct ID');
  });
}(jQuery));