text: import Ember from 'ember-metal/core';
  import { get } from 'ember-metal/property_get';
  import { set } from 'ember-metal/property_set';
  import run from 'ember-metal/run_loop';
  import { computed } from 'ember-metal/computed';
  import EmberObject from 'ember-runtime/system/object';
  import ArrayProxy from 'ember-runtime/system/array_proxy';
  import Namespace from 'ember-runtime/system/namespace';
  import { A as emberA } from 'ember-runtime/system/native_array';
  import { runAppend, runDestroy } from 'ember-runtime/tests/utils';
  import CollectionView from 'ember-views/views/collection_view';
  import EmberView from 'ember-views/views/view';
  import jQuery from 'ember-views/system/jquery';
  import compile from 'ember-template-compiler/system/compile';
  
  import buildOwner from 'container/tests/test-helpers/build-owner';
  import { OWNER } from 'container/owner';
  
  import { registerKeyword, resetKeyword } from 'ember-htmlbars/tests/utils';
  import viewKeyword from 'ember-htmlbars/keywords/view';
  
  import { objectAt } from 'ember-runtime/mixins/array';
  
  var trim = jQuery.trim;
  
  var view;
  
  var originalLookup = Ember.lookup;
  var TemplateTests, owner, lookup, originalViewKeyword;
  
  
  function nthChild(view, nth) {
    return objectAt(get(view, 'childViews'), nth || 0);
  }
  
  var firstChild = nthChild;
  
  function firstGrandchild(view) {
    return objectAt(get(objectAt(get(view, 'childViews'), 0), 'childViews'), 0);
  }
  
  QUnit.module('collection helper [LEGACY]', {
    setup() {
      originalViewKeyword = registerKeyword('view',  viewKeyword);
  
      Ember.lookup = lookup = {};
      lookup.TemplateTests = TemplateTests = Namespace.create();
      owner = buildOwner();
  
      owner.registerOptionsForType('template', { instantiate: false });
      owner.register('view:toplevel', EmberView.extend());
    },
  
    teardown() {
      runDestroy(owner);
      runDestroy(view);
      owner = view = null;
  
      Ember.lookup = lookup = originalLookup;
      TemplateTests = null;
  
      resetKeyword('view', originalViewKeyword);
    }
  });
  
  QUnit.test('Collection views that specify an example view class have their children be of that class', function() {
    var ExampleViewCollection = CollectionView.extend({
      itemViewClass: EmberView.extend({
        isCustom: true
      }),
  
      content: emberA(['foo'])
    });
  
    view = EmberView.create({
      exampleViewCollection: ExampleViewCollection,
      template: compile('{{#collection view.exampleViewCollection}}OHAI{{/collection}}')
    });
  
    runAppend(view);
  
    ok(firstGrandchild(view).isCustom, 'uses the example view class');
  });
  
  QUnit.test('itemViewClass works in the #collection helper with a property', function() {
    var ExampleItemView = EmberView.extend({
      isAlsoCustom: true
    });
  
    var ExampleCollectionView = CollectionView;
  
    view = EmberView.create({
      possibleItemView: ExampleItemView,
      exampleCollectionView: ExampleCollectionView,
      exampleController: ArrayProxy.create({
        content: emberA(['alpha'])
      }),
      template: compile('{{#collection view.exampleCollectionView content=view.exampleController itemViewClass=view.possibleItemView}}beta{{/collection}}')
    });
  
    runAppend(view);
  
    ok(firstGrandchild(view).isAlsoCustom, 'uses the example view class specified in the #collection helper');
  });
  
  QUnit.test('itemViewClass works in the #collection via container', function() {
    owner.register('view:example-item', EmberView.extend({
      isAlsoCustom: true
    }));
  
    view = EmberView.create({
      [OWNER]: owner,
      exampleCollectionView: CollectionView.extend(),
      exampleController: ArrayProxy.create({
        content: emberA(['alpha'])
      }),
      template: compile('{{#collection view.exampleCollectionView content=view.exampleController itemViewClass="example-item"}}beta{{/collection}}')
    });
  
    runAppend(view);
  
    ok(firstGrandchild(view).isAlsoCustom, 'uses the example view class specified in the #collection helper');
  });
  
  
  QUnit.test('passing a block to the collection helper sets it as the template for example views', function() {
    var CollectionTestView = CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo', 'bar', 'baz'])
    });
  
    view = EmberView.create({
      collectionTestView: CollectionTestView,
      template: compile('{{#collection view.collectionTestView}} <label></label> {{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('label').length, 3, 'one label element is created for each content item');
  });
  
  QUnit.test('collection helper should try to use container to resolve view', function() {
    var ACollectionView = CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo', 'bar', 'baz'])
    });
  
    owner.register('view:collectionTest', ACollectionView);
  
    view = EmberView.create({
      [OWNER]: owner,
      template: compile('{{#collection "collectionTest"}} <label></label> {{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('label').length, 3, 'one label element is created for each content item');
  });
  
  QUnit.test('collection helper should accept relative paths', function() {
    view = EmberView.create({
      template: compile('{{#collection view.collection}} <label></label> {{/collection}}'),
      collection: CollectionView.extend({
        tagName: 'ul',
        content: emberA(['foo', 'bar', 'baz'])
      })
    });
  
    runAppend(view);
  
    equal(view.$('label').length, 3, 'one label element is created for each content item');
  });
  
  QUnit.test('empty views should be removed when content is added to the collection (regression, ht: msofaer)', function() {
    var EmptyView = EmberView.extend({
      template : compile('<td>No Rows Yet</td>')
    });
  
    var ListView = CollectionView.extend({
      emptyView: EmptyView
    });
  
    var listController = ArrayProxy.create({
      content : emberA()
    });
  
    view = EmberView.create({
      _viewRegistry: {},
      listView: ListView,
      listController: listController,
      template: compile('{{#collection view.listView content=view.listController tagName="table"}} <td>{{view.content.title}}</td> {{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('tr').length, 1, 'Make sure the empty view is there (regression)');
  
    run(function() {
      listController.pushObject({ title : 'Go Away, Placeholder Row!' });
    });
  
    equal(view.$('tr').length, 1, 'has one row');
    equal(view.$('tr:nth-child(1) td').text(), 'Go Away, Placeholder Row!', 'The content is the updated data.');
  });
  
  QUnit.test('should be able to specify which class should be used for the empty view', function() {
    var App;
  
    run(function() {
      lookup.App = App = Namespace.create();
    });
  
    var EmptyView = EmberView.extend({
      template: compile('This is an empty view')
    });
  
    owner.register('view:empty-view', EmptyView);
  
    view = EmberView.create({
      [OWNER]: owner,
      template: compile('{{collection emptyViewClass="empty-view"}}')
    });
  
    runAppend(view);
  
    equal(view.$().text(), 'This is an empty view', 'Empty view should be rendered.');
  
    runDestroy(App);
  });
  
  QUnit.test('if no content is passed, and no \'else\' is specified, nothing is rendered', function() {
    var CollectionTestView = CollectionView.extend({
      tagName: 'ul',
      content: emberA()
    });
  
    view = EmberView.create({
      collectionTestView: CollectionTestView,
      template: compile('{{#collection view.collectionTestView}} <aside></aside> {{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('li').length, 0, 'if no "else" is specified, nothing is rendered');
  });
  
  QUnit.test('if no content is passed, and \'else\' is specified, the else block is rendered', function() {
    var CollectionTestView = CollectionView.extend({
      tagName: 'ul',
      content: emberA()
    });
  
    view = EmberView.create({
      collectionTestView: CollectionTestView,
      template: compile('{{#collection view.collectionTestView}} <aside></aside> {{ else }} <del></del> {{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('li:has(del)').length, 1, 'the else block is rendered');
  });
  
  QUnit.test('a block passed to a collection helper defaults to the content property of the context', function() {
    var CollectionTestView = CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo', 'bar', 'baz'])
    });
  
    view = EmberView.create({
      collectionTestView: CollectionTestView,
      template: compile('{{#collection view.collectionTestView}} <label>{{view.content}}</label> {{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('li:nth-child(1) label').length, 1);
    equal(view.$('li:nth-child(1) label').text(), 'foo');
    equal(view.$('li:nth-child(2) label').length, 1);
    equal(view.$('li:nth-child(2) label').text(), 'bar');
    equal(view.$('li:nth-child(3) label').length, 1);
    equal(view.$('li:nth-child(3) label').text(), 'baz');
  });
  
  QUnit.test('a block passed to a collection helper defaults to the view', function() {
    var CollectionTestView = CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo', 'bar', 'baz'])
    });
  
    view = EmberView.create({
      collectionTestView: CollectionTestView,
      template: compile('{{#collection view.collectionTestView}} <label>{{view.content}}</label> {{/collection}}')
    });
  
    runAppend(view);
  
    // Preconds
    equal(view.$('li:nth-child(1) label').length, 1);
    equal(view.$('li:nth-child(1) label').text(), 'foo');
    equal(view.$('li:nth-child(2) label').length, 1);
    equal(view.$('li:nth-child(2) label').text(), 'bar');
    equal(view.$('li:nth-child(3) label').length, 1);
    equal(view.$('li:nth-child(3) label').text(), 'baz');
  
    run(function() {
      set(firstChild(view), 'content', emberA());
    });
    equal(view.$('label').length, 0, 'all list item views should be removed from DOM');
  });
  
  QUnit.test('should include an id attribute if id is set in the options hash', function() {
    var CollectionTestView = CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo', 'bar', 'baz'])
    });
  
    view = EmberView.create({
      collectionTestView: CollectionTestView,
      template: compile('{{#collection view.collectionTestView id="baz"}}foo{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('ul#baz').length, 1, 'adds an id attribute');
  });
  
  QUnit.test('should give its item views the class specified by itemClass', function() {
    var ItemClassTestCollectionView = CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo', 'bar', 'baz'])
    });
    view = EmberView.create({
      itemClassTestCollectionView: ItemClassTestCollectionView,
      template: compile('{{#collection view.itemClassTestCollectionView itemClass="baz"}}foo{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('ul li.baz').length, 3, 'adds class attribute');
  });
  
  QUnit.test('should give its item views the class specified by itemClass binding', function() {
    var ItemClassBindingTestCollectionView = CollectionView.extend({
      tagName: 'ul',
      content: emberA([EmberObject.create({ isBaz: false }), EmberObject.create({ isBaz: true }), EmberObject.create({ isBaz: true })])
    });
  
    view = EmberView.create({
      itemClassBindingTestCollectionView: ItemClassBindingTestCollectionView,
      isBar: true,
      template: compile('{{#collection view.itemClassBindingTestCollectionView itemClass=view.isBar}}foo{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('ul li.is-bar').length, 3, 'adds class on initial rendering');
  
    // NOTE: in order to bind an item's class to a property of the item itself (e.g. `isBaz` above), it will be necessary
    // to introduce a new keyword that could be used from within `itemClassBinding`. For instance, `itemClassBinding="item.isBaz"`.
  });
  
  QUnit.test('should give its item views the property specified by itemProperty', function() {
    var ItemPropertyBindingTestItemView = EmberView.extend({
      tagName: 'li'
    });
  
    owner.register('view:item-property-binding-test-item-view', ItemPropertyBindingTestItemView);
  
    // Use preserveContext=false so the itemView handlebars context is the view context
    // Set itemView bindings using item*
    view = EmberView.create({
      [OWNER]: owner,
      baz: 'baz',
      content: emberA([EmberObject.create(), EmberObject.create(), EmberObject.create()]),
      template: compile('{{#collection content=view.content tagName="ul" itemViewClass="item-property-binding-test-item-view" itemProperty=view.baz preserveContext=false}}{{view.property}}{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('ul li').length, 3, 'adds 3 itemView');
  
    view.$('ul li').each(function(i, li) {
      equal(jQuery(li).text(), 'baz', 'creates the li with the property = baz');
    });
  
    run(function() {
      set(view, 'baz', 'yobaz');
    });
  
    equal(view.$('ul li:first').text(), 'yobaz', 'change property of sub view');
  });
  
  QUnit.test('should work inside a bound {{#if}}', function() {
    var testData = emberA([EmberObject.create({ isBaz: false }), EmberObject.create({ isBaz: true }), EmberObject.create({ isBaz: true })]);
    var IfTestCollectionView = CollectionView.extend({
      tagName: 'ul',
      content: testData
    });
  
    view = EmberView.create({
      ifTestCollectionView: IfTestCollectionView,
      template: compile('{{#if view.shouldDisplay}}{{#collection view.ifTestCollectionView}}{{content.isBaz}}{{/collection}}{{/if}}'),
      shouldDisplay: true
    });
  
    runAppend(view);
  
    equal(view.$('ul li').length, 3, 'renders collection when conditional is true');
  
    run(function() { set(view, 'shouldDisplay', false); });
    equal(view.$('ul li').length, 0, 'removes collection when conditional changes to false');
  
    run(function() { set(view, 'shouldDisplay', true); });
    equal(view.$('ul li').length, 3, 'collection renders when conditional changes to true');
  });
  
  QUnit.test('should pass content as context when using {{#each}} helper [DEPRECATED]', function() {
    view = EmberView.create({
      template: compile('{{#each view.releases as |release|}}Mac OS X {{release.version}}: {{release.name}} {{/each}}'),
  
      releases: emberA([
                  { version: '10.7',
                    name: 'Lion' },
                  { version: '10.6',
                    name: 'Snow Leopard' },
                  { version: '10.5',
                    name: 'Leopard' }
                ])
    });
  
    runAppend(view);
  
    equal(view.$().text(), 'Mac OS X 10.7: Lion Mac OS X 10.6: Snow Leopard Mac OS X 10.5: Leopard ', 'prints each item in sequence');
  });
  
  QUnit.test('should re-render when the content object changes', function() {
    var RerenderTest = CollectionView.extend({
      tagName: 'ul',
      content: emberA()
    });
  
    view = EmberView.create({
      rerenderTestView: RerenderTest,
      template: compile('{{#collection view.rerenderTestView}}{{view.content}}{{/collection}}')
    });
  
    runAppend(view);
  
    run(function() {
      set(firstChild(view), 'content', emberA(['bing', 'bat', 'bang']));
    });
  
    run(function() {
      set(firstChild(view), 'content', emberA(['ramalamadingdong']));
    });
  
    equal(view.$('li').length, 1, 'rerenders with correct number of items');
    equal(trim(view.$('li:eq(0)').text()), 'ramalamadingdong');
  });
  
  QUnit.test('select tagName on collection helper automatically sets child tagName to option', function() {
    var RerenderTest = CollectionView.extend({
      content: emberA(['foo'])
    });
  
    view = EmberView.create({
      rerenderTestView: RerenderTest,
      template: compile('{{#collection view.rerenderTestView tagName="select"}}{{view.content}}{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('option').length, 1, 'renders the correct child tag name');
  });
  
  QUnit.test('tagName works in the #collection helper', function() {
    var RerenderTest = CollectionView.extend({
      content: emberA(['foo', 'bar'])
    });
  
    view = EmberView.create({
      rerenderTestView: RerenderTest,
      template: compile('{{#collection view.rerenderTestView tagName="ol"}}{{view.content}}{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('ol').length, 1, 'renders the correct tag name');
    equal(view.$('li').length, 2, 'rerenders with correct number of items');
  
    run(function() {
      set(firstChild(view), 'content', emberA(['bing', 'bat', 'bang']));
    });
  
    equal(view.$('li').length, 3, 'rerenders with correct number of items');
    equal(trim(view.$('li:eq(0)').text()), 'bing');
  });
  
  QUnit.test('itemClassNames adds classes to items', function() {
    view = EmberView.create({
      context: { list: emberA(['one', 'two']) },
      template: compile('{{#collection content=list itemClassNames="some-class"}}{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('div > .some-class').length, 2, 'should have two items with the class');
  });
  
  QUnit.test('should render nested collections', function() {
    owner.register('view:inner-list', CollectionView.extend({
      tagName: 'ul',
      content: emberA(['one', 'two', 'three'])
    }));
  
    owner.register('view:outer-list', CollectionView.extend({
      tagName: 'ul',
      content: emberA(['foo'])
    }));
  
    view = EmberView.create({
      [OWNER]: owner,
      template: compile('{{#collection "outer-list" class="outer"}}{{content}}{{#collection "inner-list" class="inner"}}{{content}}{{/collection}}{{/collection}}')
    });
  
    runAppend(view);
  
    equal(view.$('ul.outer > li').length, 1, 'renders the outer list with correct number of items');
    equal(view.$('ul.inner').length, 1, 'the inner list exsits');
    equal(view.$('ul.inner > li').length, 3, 'renders the inner list with correct number of items');
  });
  
  QUnit.test('should render multiple, bound nested collections (#68)', function() {
    var view;
  
    run(function() {
      TemplateTests.contentController = ArrayProxy.create({
        content: emberA(['foo', 'bar'])
      });
  
      var InnerList = CollectionView.extend({
        tagName: 'ul',
        contentBinding: 'parentView.innerListContent'
      });
  
      var OuterListItem = EmberView.extend({
        innerListView: InnerList,
        template: compile('{{#collection view.innerListView class="inner"}}{{content}}{{/collection}}{{content}}'),
        innerListContent: computed(function() {
          return emberA([1, 2, 3]);
        })
      });
  
      var OuterList = CollectionView.extend({
        tagName: 'ul',
        contentBinding: 'TemplateTests.contentController',
        itemViewClass: OuterListItem
      });
  
      view = EmberView.create({
        outerListView: OuterList,
        template: compile('{{collection view.outerListView class="outer"}}')
      });
    });
  
    runAppend(view);
  
    equal(view.$('ul.outer > li').length, 2, 'renders the outer list with correct number of items');
    equal(view.$('ul.inner').length, 2, 'renders the correct number of inner lists');
    equal(view.$('ul.inner:first > li').length, 3, 'renders the first inner list with correct number of items');
    equal(view.$('ul.inner:last > li').length, 3, 'renders the second list with correct number of items');
  
    runDestroy(view);
  });
  
  QUnit.test('should allow view objects to be swapped out without throwing an error (#78)', function() {
    var view, dataset, secondDataset;
  
    run(function() {
      TemplateTests.datasetController = EmberObject.create();
  
      var ExampleCollectionView = CollectionView.extend({
        contentBinding: 'parentView.items',
        tagName: 'ul',
        _itemViewTemplate: compile('{{view.content}}')
      });
  
      var ReportingView = EmberView.extend({
        exampleCollectionView: ExampleCollectionView,
        datasetBinding: 'TemplateTests.datasetController.dataset',
        readyBinding: 'dataset.ready',
        itemsBinding: 'dataset.items',
        template: compile('{{#if view.ready}}{{collection view.exampleCollectionView}}{{else}}Loading{{/if}}')
      });
  
      view = ReportingView.create();
    });
  
    runAppend(view);
  
    equal(view.$().text(), 'Loading', 'renders the loading text when the dataset is not ready');
  
    run(function() {
      dataset = EmberObject.create({
        ready: true,
        items: emberA([1, 2, 3])
      });
      TemplateTests.datasetController.set('dataset', dataset);
    });
  
    equal(view.$('ul > li').length, 3, 'renders the collection with the correct number of items when the dataset is ready');
  
    run(function() {
      secondDataset = EmberObject.create({ ready: false });
      TemplateTests.datasetController.set('dataset', secondDataset);
    });
  
    equal(view.$().text(), 'Loading', 'renders the loading text when the second dataset is not ready');
  
    runDestroy(view);
  });
  
  QUnit.test('context should be content', function() {
    var view;
  
    var items = emberA([
      EmberObject.create({ name: 'Dave' }),
      EmberObject.create({ name: 'Mary' }),
      EmberObject.create({ name: 'Sara' })
    ]);
  
    owner.register('view:an-item', EmberView.extend({
      template: compile('Greetings {{name}}')
    }));
  
    view = EmberView.create({
      [OWNER]: owner,
      controller: {
        items: items
      },
      template: compile('{{collection content=items itemViewClass="an-item"}}')
    });
  
    runAppend(view);
  
    equal(view.$().text(), 'Greetings DaveGreetings MaryGreetings Sara');
  
    runDestroy(view);
  });
  