From 235ca353ff753837565f6dc284bc723f0d089da5 Mon Sep 17 00:00:00 2001 From: Santiago Ferreira Date: Sun, 4 Feb 2018 19:08:48 -0300 Subject: [PATCH] Enable array like accessors when Proxy is available --- addon/-private/properties/collection.js | 23 +++++++++++++++++++ addon/-private/properties/collection/main.js | 20 ++++++++++++++++ .../-private/properties/collection-test.js | 14 +++++++++++ 3 files changed, 57 insertions(+) diff --git a/addon/-private/properties/collection.js b/addon/-private/properties/collection.js index a07a0447..afdebc52 100644 --- a/addon/-private/properties/collection.js +++ b/addon/-private/properties/collection.js @@ -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. @@ -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 + * + * // + * // + * // + * // + * // + * //
Mary + * //
John + * //
+ * + * 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} diff --git a/addon/-private/properties/collection/main.js b/addon/-private/properties/collection/main.js index dee94082..7cbb0fb5 100644 --- a/addon/-private/properties/collection/main.js +++ b/addon/-private/properties/collection/main.js @@ -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, @@ -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); + } } }; diff --git a/tests/unit/-private/properties/collection-test.js b/tests/unit/-private/properties/collection-test.js index bbf09d04..d70c6e7a 100644 --- a/tests/unit/-private/properties/collection-test.js +++ b/tests/unit/-private/properties/collection-test.js @@ -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, ` + Lorem + Ipsum + `); + + assert.equal(page.foo[0].text, 'Lorem'); + assert.equal(page.foo[1].text, 'Ipsum'); + }); });