"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assertViewModelValue = void 0;
const oj_module_proxy_1 = require("./oj-module-proxy");
/**
 * Assert a given expectation against a JET application's viewmodel.
 * Assertions are [Chai](https://www.chaijs.com)-like expressions, represented
 * by the {@link Expectation} class, and compared remotely on the test browser
 * against the identified viewmodel and its path to the target value.
 *
 * The viewmodel is typically identiied by the DOM node on which Knockout's
 * <code>ko.applyBindings</code> was called, but can also be descendants of
 * that originial "root" node.
 * ```javascript
 * new Expectation(...)
 * ```
 *
 * The target value within the viewmodel is identified by a dot-notated path
 * and/or expression which yields the value. For instance, a value may be an
 * observable, therefore, the expression must include parenthesis to unwrap
 * the observable.
 * ```javascript
 * new Expecation(By.id('view-container'), 'firstName()')
 * ```
 *
 * The expression to which the viewmodel value will be compared is expressed
 * as BDD-style chains, such as
 * ```javascript
 * const fnExpectation = new Expectation('firstName()')
 *   .to.equal('Joe');
 * ```
 *
 * If a viewmodel value returns a Promise, the assertion will wait for it to
 * resolve before doing the comparison.
 *
 * @param driver The instance of WebDriver to use in performing the expectation
 * @param vmLocator The Locator which identifies the DOM node associated with the
 * viewmodel on the client.
 * @param expression The path within the viewmodel to locate the value
 * @param expectation The Expectation object to evaluate on the client browser.
 */
async function assertViewModelValue(driver, vmLocator, expectation) {
    const viewmodelEl = (await driver.findElement(vmLocator));
    // Script executes on client to build the Chai assertion from the Expectation.
    // Any exceptions (including failed assertions) will be returned to the test.
    await viewmodelEl.whenBusyContextReady();
    const result = await (0, oj_module_proxy_1.executeWithModules)(driver, ['Chai', 'Knockout', 'CspExpressionEvaluator'], [viewmodelEl, expectation.assertion], `
    ((chai, ko, ExpressionEval, viewmodelEl, assertion) => {
      try {
        var viewmodel = ko.dataFor(viewmodelEl);
        // Use ExpressionEval to get the value from the viewmodel
        var evaluator = new ExpressionEval();
        var value = evaluator.createEvaluator(assertion.expression).evaluate([viewmodel]);
  
        function compare(value) {
          var expect = chai.expect(value);
          // For each chained assertion, call the assertion method with the arguments
          assertion.chain.forEach((desc) => {
            if (typeof desc === 'string') {
              // Simple assertions, "is", "to", "be", etc
              expect = expect[desc];
            } else {
              // Complex assertions (chained functions)
              const name = desc.name;
              const args = desc.args;
              let evaluatedArgs = [];
  
              if (name === 'match') {
                args[0] = new RegExp(args[0]);
              }
  
              if (args) {
                evaluatedArgs = args;
              }
  
              expect = expect[name](...evaluatedArgs);
            }
          });
          return true;
        }
  
        // If "value" is a Promise
        if (value && typeof value.then === 'function') {
          value.then(compare).catch((ex) => ex.message);
        } else {
          return compare(value);
        }
      } catch (ex) {
        return ex.message;
      }
    })
    `);
    if (result !== true) {
        throw Error(String(result));
    }
    return result;
}
exports.assertViewModelValue = assertViewModelValue;
//# sourceMappingURL=viewmodel-utils.js.map