UNPKG

ember-cli-page-object

Version:

This ember-cli addon eases the construction of page objects on your acceptance and integration tests

98 lines (81 loc) 3.03 kB
import { resolve } from 'rsvp'; import { getExecutionContext } from './execution_context'; import { getRoot } from './helpers'; import Ceibo from 'ceibo'; /** * Run action * * @param {Ceibo} node Page object node to run action on * @param {Function} cb Some async activity callback * @returns {Ceibo} */ export function run(node, cb) { const adapter = getExecutionContext(node); const chainedRoot = getRoot(node)._chainedTree; if (typeof adapter.andThen === 'function') { // With old ember-testing helpers, we don't make the difference between // chanined VS independent action invocations. Awaiting for the previous // action settlement, before invoke a new action, is a part of // the legacy testing helpers adapters for backward compat reasons chainedRoot._promise = adapter.andThen(cb); return node; } else if (!chainedRoot) { // Our root is already the root of the chained tree, // we need to wait on its promise if it has one so the // previous invocations can resolve before we run ours. let root = getRoot(node) root._promise = resolve(root._promise).then(() => cb(adapter)); return node; } else { // Store our invocation result on the chained root // so that chained calls can find it to wait on it. chainedRoot._promise = cb(adapter); return chainable(node); } } export function chainable(branch) { if (isChainedNode(branch)) { return branch; } // See explanation in `create.js` -- here instead of returning the node on // which our method was invoked, we find and return our node's mirror in the // chained tree so calls to it can be recognized as chained calls, and // trigger the chained-call waiting behavior. // Collecting node keys to build a path to our node, and then use that // to walk back down the chained tree to our mirror node. let path = []; let node; for (node = branch; node; node = Ceibo.parent(node)) { path.unshift(Ceibo.meta(node).key); } // The path will end with the root's key, 'root', so shift that back off path.shift(); node = getRoot(branch)._chainedTree; path.forEach((key) => { node = getChildNode(node, key) }); return node; } function isChainedNode(node) { let root = getRoot(node); return !root._chainedTree; } function getChildNode(node, key) { // Normally an item's key is just its property name, but collection // items' keys also include their index. Collection item keys look like // `foo[2]` and legacy collection item keys look like `foo(2)`. let match; if ((match = /\[(\d+)\]$/.exec(key))) { // This is a collection item let [ indexStr, index ] = match; let name = key.slice(0, -indexStr.length); return node[name].objectAt(parseInt(index, 10)); } else if ((match = /\((\d+)\)$/.exec(key))) { // This is a legacy collection item let [ indexStr, index ] = match; let name = key.slice(0, -indexStr.length); return node[name](parseInt(index, 10)); } else { return node[key]; } }