Cannot use boolean value as thenable construct in Typescript?

I am converting a Protractor page object library from JavaScript to Typescript. I have a static utility method that is updated until an element is present (or a timeout limit is reached).

For some reason, I cannot use the promised booleanpromise as a construct thenable, and I cannot understand why. Error messageerror TS2345: Argument of type '(value: boolean) => Promise<{}> | undefined' is not assignable to parameter of type '((value: boolean) => {} | IThenable<{}>) | undefined'. Type '(value: boolean) => Promise<{}> | undefined' is not assignable to type '(value: boolean) => {} | IThenable<{}>'. Type 'Promise<{}> | undefined' is not assignable to type '{} | IThenable<{}>'. Type 'undefined' is not assignable to type '{} | IThenable<{}>'.

Below is the source code with a comment showing where the compilation error occurs.

I used this mechanism in a clean version of JavaScript for the platform that I am converting to Typescript. What do I need to do to translate this method to Typescript, which will compile?

import {browser, element, ElementFinder, ExpectedConditions} from 'protractor';
import * as wd from 'selenium-webdriver';
import {By} from "selenium-webdriver";

export class ExtendedExpectedConditions {

    public static refreshUntilElementIsPresent(element: ElementFinder,  numberOfSeconds: number = 30000,
        refreshInterval: number = 5000): void {
        this.refreshElement(element, numberOfSeconds, refreshInterval);
    }

    protected static refreshElement(element: ElementFinder, numberOfSeconds: number = 30000, refreshInterval:
        number = 5000) {


        //This line throws the compile error
        element.isPresent().then(value => {
            if (!value) {
                if (numberOfSeconds <= 0) {
                    return new wd.promise.Promise(function (resolve, reject) {
                        reject('Element cannot be found after expected retry numbers');
                    })
                }
                browser.sleep(refreshInterval).then(() => {
                    browser.refresh().then(() => this.refreshUntilElementIsPresent(element, numberOfSeconds -
                    (refreshInterval / 1000)));
                });
            }
       });
    }
}

My 'package.json' is below:

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "A test suite",
  "scripts": {
    "tsc": "tsc",
    "pretest": "npm run tsc",
    "test": "node_modules/protractor/bin/protractor tmp/conf.js",
    "start_selenium": "node_modules/protractor/node_modules/webdriver-manager/bin/webdriver-manager start",
    "update_selenium": "node_modules/protractor/node_modules/webdriver-manager/bin/webdriver-manager update"
  },
  "author": aperson@someplace.com,
  "dependencies": {
    "@types/jasmine": "^2.5.52",
    "@types/jasminewd2": "^2.0.2",
    "@types/node": "^7.0.31",
    "any-promise": "^1.3.0",
    "jasmine-reporters": "^2.2.1",
    "protractor": "^5.1.2",
    "typescript": "^2.3.4"
  }
}

tsconfig.json :

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "declaration": false,
    "noImplicitAny": false,
    "outDir": "tmp",
    "types": ["jasmine", "node"],
    "strict": true
  },
  "exclude": [
    "node_modules"
  ]
}

conf.ts :

import {Config, browser, protractor} from "protractor";

let testsTimeout = 3600000;
let delayBrowserTimeInSeconds = 0;

export let config: Config = {
    framework: 'jasmine2',
    rootElement: 'body',
    seleniumServerJar:'../node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar',
    chromeDriver: '../node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.30',
    specs: ['tests/*Spec.js'],
    capabilities: {
        browserName: 'chrome',
        acceptSslCerts: true,
        trustAllSSLCertificates: true,
        chromeOptions: {
            args: ['--no-sandbox']
        },
    },
    baseUrl: 'https://www.someurl.com',

    jasmineNodeOpts: {
        defaultTimeoutInterval: testsTimeout,
        showColors: true,
        isVerbose: true
    },

    onPrepare: () => {

        let origFn = browser.driver.controlFlow().execute;

        browser.driver.controlFlow().execute = function () {
            let args = arguments;

            origFn.call(browser.driver.controlFlow(), function () {
                return protractor.promise.delayed(delayBrowserTimeInSeconds * 100);
            });

            return origFn.apply(browser.driver.controlFlow(), args);
        };

        setTimeout(() => {
            browser.driver.executeScript<[number, number]>(() => {
                return [
                    window.screen.availWidth,
                    window.screen.availHeight
            ];
            }).then((result: [number, number]) => {
                browser.driver.manage().window().setSize(result[0], result[1]);
                browser.driver.manage().window().maximize();
            });
        });

    },

    getPageTimeout: 120000,
    allScriptsTimeout: testsTimeout
};
+4
2

, then. , , .

src/test.ts(17,34): error TS2345: Argument of type '(value: boolean) => Promise<{}> | undefined' is not assignable to parameter of type '((value: boolean) => {} | IThenable<{}>) | undefined'.
  Type '(value: boolean) => Promise<{}> | undefined' is not assignable to type '(value: boolean) => {} | IThenable<{}>'.
    Type 'Promise<{}> | undefined' is not assignable to type '{} | IThenable<{}>'.
      Type 'undefined' is not assignable to type '{} | IThenable<{}>'.

, , .then, (value: boolean) => Promise<{}> | undefined. Promise, undefined.

.then() , ((value: boolean) => {} | IThenable<{}>) | undefined ( "" ) , . , undefined, , - IThenable<something>. , then undefined.

, : .then, .

, typescript Selenium Webdriver {} | IThenable<{}> | undefined.

:

export class ExtendedExpectedConditions {

    public static refreshUntilElementIsPresent(element: ElementFinder,  numberOfSeconds: number = 30000,
        refreshInterval: number = 5000): void {
        this.refreshElement(element, numberOfSeconds, refreshInterval);
    }

    protected static refreshElement(element: ElementFinder, numberOfSeconds: number = 30000, refreshInterval:
        number = 5000) {


        //This line throws the compile error
        element.isPresent().then(value => {
            if (!value) {
                if (numberOfSeconds <= 0) {
                    return wd.promise.rejected('Element cannot be found after expected retry numbers');
                }
                browser.sleep(refreshInterval).then(() => {
                    browser.refresh().then(() => this.refreshUntilElementIsPresent(element, numberOfSeconds -
                    (refreshInterval / 1000)));
                });
            }
            return 42; // webdriver `.then` callback must return a result.
       });
    }
}

, - Promise Webdriver .resolve() .reject(), , promise.rejected() .

+4

, , , , , Protractor @returns {Promise<boolean>}, .

- async / await TypeScript. . . .

public static refreshUntilElementIsPresent(element: ElementFinder, numberOfSeconds: number = 30000,
  refreshInterval: number = 5000): void {
  return this.refreshElement(element, numberOfSeconds, refreshInterval);
}

// Add async here
protected static async refreshElement(element: ElementFinder, numberOfSeconds: number = 30000, refreshInterval: number = 5000) {

  // Wait untill the promise is resolved
  const isPresent = await element.isPresent();
  // Use the resolved promise
  if (!isPresent) {
    if (numberOfSeconds <= 0) {
      // You can clean the Promise rejection and create 1 line of code
      return Promise.reject('Element cannot be found after expected retry numbers');
    }
    // Wait for the rest
    await browser.sleep(refreshInterval);
    await browser.refresh();
    return this.refreshUntilElementIsPresent(element, numberOfSeconds - (refreshInterval / 1000));
  }
};
Hide result
0

Source: https://habr.com/ru/post/1679725/


All Articles