Giter Club home page Giter Club logo

protractor-element-extend's Introduction

Oleksandr Khotemskyi

  • JavaScript/TypeScript software developer engineer in test
  • Independent Contractor, more than 10 years of experience in QA automation
  • Speaker at conferences, meetups. Online and offline. Open to have a talk on your event!
  • Teaching UI, API, test infrastructure and different open and private courses
  • Winner and Judge of Ukrainian Dev Challenge (QA)
  • Opensource contributor and "javascript testing" community developer.

Feel free to talk to me: xotabu4.github.io

protractor-element-extend's People

Contributors

gitter-badger avatar marketionist avatar tom-hudson avatar voropa avatar xotabu4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

protractor-element-extend's Issues

Cannot override a method

When i trying to overrid the method getText, my IDE highlight error in TextboxClass, and if i change name method getText to something like getText1, the error has gone a way.

import {BaseFragment} from 'protractor-element-extend'
import {browser, ExpectedConditions as EC, $, $$, element, by, ElementFinder} from 'protractor'
class TextboxClass extends BaseFragment {
    constructor(element) {
        super(element) //that's it! now your 'this' reference, is reference to element passed to super constructor
    }

    //You can extend it with any methods that you what, and use internal reference to your element


    getText() {
        let self = this;
        self.getAttribute('value')

            .then(function (textGet) {
                return textGet;
            })


    }

}

Filter function does not work properly if constructor has no parameters

Just example:

<components>
    <component>
         <name>...</name>
    </component>
    <component>
    </component>
</components>
class MyArrayOfComponents extends BaseArrayFragment<MyComponent> {
    // No params in constructor:
    constructor() {
         super($$('components component'), MyComponent)
    }

    getComponentsWithName() {
        return this.filter(component => component.hasName())
    }
}

class MyComponent extends BaseFragment {
     hasName(){
           return this.$('.name').isPresent()
     }
}

console.log(await new MyArrayOfComponents().getComponentsWithName().count()) // 2, but expected 1

Since filter function uses this.constructor(array, class) - it passes parameters, but they are not used.

Workaround for this is to use default params:

    constructor(elems = $$('components component'), clazz = MyComponent) {
         super(elems, clazz)
    }

Class constructor BaseFragment cannot be invoked without 'new' (ES5)

I'm using WebStorm with compiler target is ES6 so i don't recognize this error.
However, when i integrate with jenkin, the issue happens. Because when i set target is ES6, some issue happens and grunt ts cannot compile code to ES6. Perhaps, it does not fully support.
That's why i set target is ES5. However, with target is ES5 i got this error in runtime. I also change WebStorm with compiler target is ES5, and i also get this issue
Jenkin with grunt-ts

�[31mF�[0m ✗ #2 Login to the page (0.103 s)
- Failed: TypeError: Class constructor BaseFragment cannot be invoked without 'new'
â–» #3 Verify select organization text
Webstorm
#2 Login to the page (0.201 s)

  • Failed: TypeError: Class constructor BaseFragment cannot be invoked without 'new'
/**.
 */
import {BaseFragment} from 'protractor-element-extend'
import {browser, ExpectedConditions as EC, $, $$, element, by, ElementFinder} from 'protractor'
import {Locator} from "protractor/built/locators";

class TextboxClass extends BaseFragment {
    constructor(element) {
        super(element) //that's it! now your 'this' reference, is reference to element passed to super constructor
    }//-

    //You can extend it with any methods that you what, and use internal reference to your element
    setContent(textSet) {
        let self = this;
        this.clear()
            .then(function () {
                return self.sendKeys(textSet);
            })
            .then(function () {
                return self.getAttribute('value');

            })
            .then(function (textGet) {
                if (textGet == textSet) {
                    console.log("Set Text '" + textGet + "' Successfully !");
                    return true;
                }
                else {
                    console.warn("Set Text '" + textGet + "' Unsuccessfully !");
                    return false;
                }
            })


    }

    getContent() {
        let self = this;
        self.getAttribute('value')

            .then(function (textGet) {
                return textGet;
            })


    }

}
class CheckboxClass extends BaseFragment {
    constructor(element) {
        super(element) //that's it! now your 'this' reference, is reference to element passed to super constructor
    }

    //You can extend it with any methods that you what, and use internal reference to your element
    select() {
        this.isSelected().then(selected => {
            if (!selected) {
                this.click()
                // Notice that because your element is valid ElementFinder - you can pass it as parameter to ExpectedConditions!
                browser.wait(EC.elementToBeSelected(this), 5000, `Checkbox ${this.locator()} must became selected after click, but it wasn't`)
            } else {
                console.warn(`Checkbox ${this.locator()} was already selected, skipping select`)
            }
        })
    }

    unselect() {
        this.isSelected().then(selected => {
            if (selected) {
                this.click()
                // Notice that because your element is valid ElementFinder - you can pass it as parameter to ExpectedConditions!
                browser.wait(EC.not(EC.elementToBeSelected(this)), 5000, `Checkbox ${this.locator()} must became unselected after click, but it wasn't`)
            } else {
                console.warn(`Checkbox ${this.locator()} was already unselected, skipping unselect`)
            }
        })
    }

}

class ComboboxClass extends BaseFragment {
    constructor(element) {
        super(element) //that's it! now your 'this' reference, is reference to element passed to super constructor
    }

    selectDropdownByIndex(index, milliseconds) {
        this.findElements(by.tagName('option'))
            .then(function (options) {
                options[index].click();
            });
        if (typeof milliseconds !== 'undefined') {
            browser.sleep(milliseconds);
        }
    }

    selectRandom() {

        this.element(by.xpath('//option[3]')).click();
            // .then(function (options) {
            //     let random = Math.floor((Math.random() * (options.length - 1)));
            //     if (random == -1) {
            //         random = 0
            //     }
            //     console.log(options.length);
            //     if (options.length > 0) {
            //         options[random].click();
            //     }
            // });


    }

    selectDropdownByText(Text, milliseconds) {
        this.findElements(by.tagName('option'))
            .then(function (options) {
                for (let i = 0; i < options.length; i++) {
                    if (options[i].getText()
                            .then(function (textGet) {
                                if (textGet == Text) {
                                    return true;
                                }
                                else {
                                    return false;
                                }
                            })) {

                        options[i].click();
                    }

                }
            });
        if (typeof milliseconds !== 'undefined') {
            browser.sleep(milliseconds);
        }
    }

}

//Export part
export function textBox(locator, elementFlag = false) {
    if (elementFlag != false) {
        return new TextboxClass(locator);
    }
    else {
        return new TextboxClass(element(locator));
    }


}
export function checkBox(locator, elementFlag = false) {
    if (elementFlag != false) {
        return new CheckboxClass(locator);
    }
    else {
        return new CheckboxClass(element(locator));
    }


}
export function comboBox(locator, elementFlag = true) {
    if (elementFlag != false) {
        return new ComboboxClass(locator);
    }
    else {
        return new ComboboxClass(element(locator));
    }


}

Find elements from a parent element

I tried 3 ways to Find elements from a parent element but none of them work.

class ComboboxClass extends BaseFragment {
    constructor(element) {
        super(element) 
    }

    selectDropdownByIndex(index, milliseconds) {
        this.findElements(by.tagName('option'))//Error in run time cannot find method findElements
            .then(function (options) {
                options[index].click();
            });
        if (typeof milliseconds !== 'undefined') {
            browser.sleep(milliseconds);
        }
    }

    selectRandom() {
        this.element.all(by.xpath('//option')) //Webstorm hightlight .all
            .then(function (options) {
                let random = Math.floor((Math.random() * (options.length - 1)));
                if (options.length > 0) {
                    options[random].click();
                }
            });


    }
}
selectDropdownByText(Text, milliseconds) {
        this.$$('option'))//Invalid locator
            .then(function (options) {
                for (let i = 0; i < options.length; i++) {
                    if (options[i].getText()
                            .then(function (textGet) {
                                if (textGet == Text) {
                                    return true;
                                }
                                else {
                                    return false;
                                }
                            })) {

                        options[i].click();
                    }

                }
            });
        if (typeof milliseconds !== 'undefined') {
            browser.sleep(milliseconds);
        }
    }

Can't call overridden method

Hi!
I have tried to extend ElemetFinder and override it's "click" method, but when i call element.click() in my test scenario default ElementFinder click() event is fired. Here is the example of my code below.

`export default class ElementDecorator extends BaseFragment {
protected logger = CustomLogger.get('ElementDecorator');

constructor(elementFinder: ElementFinder) {
super(elementFinder);
}

public async click(): Promise {
this.logger.info('my click');
await this.scrollIntoView();
await WaitUtils.waitForClickable(this);
await super.click();
}
}

export default class MyPageObjectClass {
private myButton: ElementDecorator;

constructor() {
this.myButton= new ElementDecorator($(#button));
}

public async clickMyButton() {
this.logger.info('Clicking my button');
await this.myButton.click();
}
}`

"protractor": "5.4.2",
"typescript": "3.4.1"

Looking for some help!

Hi,

I'm relatively new to JavaScript & protractor (with good experience in Java/Selenium).

I'm trying to create a wrapper class by extending protractors elementfinder & elementarrayfinder and add few custom methods and also want to overwrite few existing methods exposed in protractor's element class.

On thing which i couldn't understand is how can i overwrite the protractors default "element" which is exposed in global context with my extended element class.

Lets say my extended class is myElement, then i need to expose this to global context and use it across my specs as myElement(by.id('userId')).myCustomClick(); instead of element(by.id('userId')).click();

should i do something like this in onprepare () with global.myElement = ; ???

Your help/input is much appreciated!

Investigate possibility to print nice locators for fragments on error

Investigate possibility to print nice locators for fragments on error

Problem:
On attempt to use something like this:

$('div').$('.helloworld')

error will be printed something like
'element ".helloworld" is not found'
But it will be more informative to have error with full context -
'element "div > .helloworld " not found '

  • Find possibility to get all parent elements locators
  • Find nice format to print different locators and different contexts
  • Override error message with that nice format

Can't use Protractor $ and $$ shortcuts on calls to this within Extended Class

For example:

class Select extends BaseFragment {
    constructor(element) {
        super(element);
    }

    selectOption(text) {
        this.element(by.cssContainingText('option', text)).click();
    }

    getSelectedText() {
    	// NOTE: Apparently you can't use the shorthand element locators ($ and $$) with this package.
        // e.g. return this.$('select').getAttribute('value')

        return this.element(by.css('select')).getAttribute('value')
            .then((index) => {
                return this.element(by.css(`option[value="${index}"]`)).getText();
            });
    }
}

You have to use this.element(by.css(...)). You can't use this.$(...)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.