Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't call overridden method #20

Open
voropa opened this issue Jun 24, 2019 · 10 comments
Open

Can't call overridden method #20

voropa opened this issue Jun 24, 2019 · 10 comments
Assignees
Labels
Milestone

Comments

@voropa
Copy link
Contributor

voropa commented Jun 24, 2019

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"
@Xotabu4 Xotabu4 added the bug label Jun 25, 2019
@Xotabu4 Xotabu4 self-assigned this Jun 25, 2019
@voropa
Copy link
Contributor Author

voropa commented Jun 25, 2019

Seems that i've found the root of the problem.
Actually we could override ElementFinder class methods as we extends it. For example isPresent() method could be overriden and works good. But as for other native selenium methods like click, sendKeys, isDisplayed: they are declared inside WebdriverWebElement interface and override doesn't work for them.

export default class ElementDecorator extends ElementFinder {
/**

  • Extend this class, to describe single custom fragment on your page
  • @param {ElementFinder} elementFinder ElementFinder that you want to extend
    */
    constructor(elementFinder: ElementFinder) {
    // Basically we are recreating ElementFinder again with same parameters
    super(elementFinder.browser_, elementFinder.elementArrayFinder_);
    }
    // Works fine
    public async isPresent(): Promise {
    console.log('my isPresent');
    return super.isPresent();
    }
    // Doesn't work
    public async isDisplayed(): Promise {
    console.log('my isDisplayed');
    return super.isDisplayed();
    }
    }

@Xotabu4
Copy link
Owner

Xotabu4 commented Jun 25, 2019

@voropa
Yes, i also did investigation. Protractor has monkey-patching for some of the methods - https://github.com/angular/protractor/blob/master/lib/element.ts#L831

This patching seems to be applied AFTER instance is created, so it override your declared methods in
ElementDecorator. And also this added methods seems to be NOT available on 'super' because of this patching.

I will take a look how this can be fixed on protractor-element-extend level.

Thanks for bug report!

For now, as a workaround i can suggest to not override methods:

    class ElementDecorator extends BaseFragment {
        constructor(el) {
            super(el)
        }

        async myClick() {
            console.log('OWN click')
            await this.click()
        }
    }

@voropa
Copy link
Contributor Author

voropa commented Jun 25, 2019

@voropa
Yes, i also did investigation. Protractor has monkey-patching for some of the methods - https://github.com/angular/protractor/blob/master/lib/element.ts#L831

This patching seems to be applied AFTER instance is created, so it override your declared methods in
ElementDecorator. And also this added methods seems to be NOT available on 'super' because of this patching.

I will take a look how this can be fixed on protractor-element-extend level.

Thanks for bug report!

For now, as a workaround i can suggest to not override methods:

    class ElementDecorator extends BaseFragment {
        constructor(el) {
            super(el)
        }

        async myClick() {
            console.log('OWN click')
            await this.click()
        }
    }

Sure. And I've found another workaround but it is not stable and depends on elementArrayFinder realization.
image

@voropa
Copy link
Contributor Author

voropa commented Jun 25, 2019

Anyway protractor and native selenium action methods are protected from overriding by default.

Xotabu4 added a commit that referenced this issue Jul 4, 2019
- Updated WEBELEMENTS methods patching to patch prototype instead patching 'this' object
@Xotabu4
Copy link
Owner

Xotabu4 commented Jul 4, 2019

@voropa
Hi, i think i have solution.

Can you please test with 2.3.0-alpha-2 version that is published to NPM ?
I tested manually and it looks good from my side.

And also i fixed same issue for BaseArrayFragment also

@voropa
Copy link
Contributor Author

voropa commented Jul 5, 2019

@Xotabu4
Thank you for update but unfortunately it still doesn't work for me((
image
image

And then i'm getting TypeError when trying to run the test using this element wrapper:
Message:
Failed: Cannot read property 'apply' of undefined
Stack:
TypeError: Cannot read property 'apply' of undefined
at MyElement.(anonymous function).args [as click] (C:\workspace\SSL\selenium\test-protractor-project-ts\node_modules\protractor\built\element.js:831:22)
at Object. (C:\workspace\SSL\selenium\test-protractor-project-ts\e2e\onliner.spec.ts:12:35)
at Generator.next ()
at C:\workspace\SSL\selenium\test-protractor-project-ts\tmp\e2e\onliner.spec.js:7:71
at new Promise ()
at __awaiter (C:\workspace\SSL\selenium\test-protractor-project-ts\tmp\e2e\onliner.spec.js:3:12)
at UserContext.it (C:\workspace\SSL\selenium\test-protractor-project-ts\e2e\onliner.spec.ts:11:31)
at C:\workspace\SSL\selenium\test-protractor-project-ts\node_modules\jasminewd2\index.js:112:25
at new ManagedPromise (C:\workspace\SSL\selenium\test-protractor-project-ts\node_modules\selenium-webdriver\lib\promise.js:1077:7)
at ControlFlow.promise (C:\workspace\SSL\selenium\test-protractor-project-ts\node_modules\selenium-webdriver\lib\promise.js:2505:12)
From: Task: Run it("first test") in control flow
at UserContext. (C:\workspace\SSL\selenium\test-protractor-project-ts\node_modules\jasminewd2\index.js:94:19)
From asynchronous test:
Error
at Object. (C:\workspace\SSL\selenium\test-protractor-project-ts\e2e\onliner.spec.ts:11:3)
at Generator.next ()
at C:\workspace\SSL\selenium\test-protractor-project-ts\tmp\e2e\onliner.spec.js:7:71
at new Promise ()
at __awaiter (C:\workspace\SSL\selenium\test-protractor-project-ts\tmp\e2e\onliner.spec.js:3:12)
at Suite.fdescribe (C:\workspace\SSL\selenium\test-protractor-project-ts\e2e\onliner.spec.ts:4:41)

@Xotabu4 Xotabu4 added this to the 3.0.0 milestone Sep 25, 2019
@Xotabu4
Copy link
Owner

Xotabu4 commented Oct 7, 2019

@voropa angular/protractor#5328
This fix to protractor should fix this issue as well

@Skidush
Copy link

Skidush commented Feb 18, 2020

Hello. Any updates on this issue? I wrap my own classes so its not really nice to see methods myClick() and click() existing on the same object.

@Xotabu4
Copy link
Owner

Xotabu4 commented Feb 18, 2020

@Skidush Hello, unfortunately i can't fix this on library side. Protractor uses monkey patching after constructor was called, so all methods from this list

let WEB_ELEMENT_FUNCTIONS = [
'click', 'sendKeys', 'getTagName', 'getCssValue', 'getAttribute', 'getText', 'getRect',
'isEnabled', 'isSelected', 'submit', 'clear', 'isDisplayed', 'getId', 'takeScreenshot'
];

are patched after extended component is created so this overrides methods back to default.

I will ask protractor team again to merge PR and release a new version.

@Skidush
Copy link

Skidush commented Feb 18, 2020

@Skidush Hello, unfortunately i can't fix this on library side. Protractor uses monkey patching after constructor was called, so all methods from this list

let WEB_ELEMENT_FUNCTIONS = [
'click', 'sendKeys', 'getTagName', 'getCssValue', 'getAttribute', 'getText', 'getRect',
'isEnabled', 'isSelected', 'submit', 'clear', 'isDisplayed', 'getId', 'takeScreenshot'
];

are patched after extended component is created so this overrides methods back to default.

I will ask protractor team again to merge PR and release a new version.

Wow that was quick. Thanks for the response!

Great library btw!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants