Skip to content

Commit

Permalink
Merge pull request #375 from san650/add-array-accessors-to-collections
Browse files Browse the repository at this point in the history
Enable array like accessors when Proxy is available
  • Loading branch information
san650 authored Feb 5, 2018
2 parents a3d5f8b + 235ca35 commit 3d0f6a2
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
23 changes: 23 additions & 0 deletions addon/-private/properties/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import { collection as legacyCollection } from './collection/legacy';
* Creates a enumerable that represents a collection of items. The collection is zero-indexed
* and has the following public methods and properties:
*
* IMPORTANT: You can use Array accessors only on browsers that support Proxy.
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#Browser_compatibility
*
* - `length` - The number of items in the collection.
* - `objectAt()` - Returns the page for the item at the specified index.
* - `filter()` - Filters the items in the array and returns the ones which match the predicate function.
Expand Down Expand Up @@ -108,6 +111,26 @@ import { collection as legacyCollection } from './collection/legacy';
* let john = page.users.filter((item) => item.firstName === 'John' )[0];
* assert.equal(john.lastName, 'Doe');
*
* @example if the browser you run tests supports Proxy, you can use array accessors to access elements by index
*
* // <table>
* // <tr>
* // <td>Mary<td>
* // </tr>
* // <tr>
* // <td>John<td>
* // </tr>
* // </table>
*
* const page = PageObject.create({
* users: PageObject.collection('tr')
* });
*
* // This only works on browsers that support `Proxy`
* assert.equal(page.users[0].text, 'Mary');
* assert.equal(page.users[1].text, 'John');
*
*
* @param {String} scopeOrDefinition - Selector to define the items of the collection
* @param {Object} [definitionOrNothing] - Object with the definition of item properties
* @return {Descriptor}
Expand Down
20 changes: 20 additions & 0 deletions addon/-private/properties/collection/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@ if (typeof (Symbol) !== 'undefined' && Symbol.iterator) {
}
}

function proxyIt(instance) {
return new window.Proxy(instance, {
get: function(target, name) {
if (typeof(name) === 'number' || typeof(name) === 'string') {
let index = parseInt(name, 10);

if (!isNaN(index)) {
return target.objectAt(index);
}
}

return target[name];
}
});
}

export function collection(scope, definition) {
let descriptor = {
isDescriptor: true,
Expand All @@ -115,6 +131,10 @@ export function collection(scope, definition) {
// This does mutate the descriptor, but because `setup` is always called before the
// value is assigned we are guaranteed to get a new, unique Collection instance each time.
descriptor.value = new Collection(scope, definition, node, key);

if (window.Proxy) {
descriptor.value = proxyIt(descriptor.value);
}
}
};

Expand Down
14 changes: 14 additions & 0 deletions tests/unit/-private/properties/collection-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,4 +429,18 @@ moduleForProperty('collection', function(test) {
assert.deepEqual(page.foo.filterBy('isSpecial').map((i) => i.text), ['Lorem']);
assert.deepEqual(page.foo.filterBy('isFoo').map((i) => i.text), []);
});

test('uses array accessor', function(assert) {
let page = create({
foo: collection('span')
});

this.adapter.createTemplate(this, page, `
<span>Lorem</span>
<span>Ipsum</span>
`);

assert.equal(page.foo[0].text, 'Lorem');
assert.equal(page.foo[1].text, 'Ipsum');
});
});

0 comments on commit 3d0f6a2

Please sign in to comment.