Reputation: 851
I'm new to Angular2 and haven't developed the Angular components to be tested. However, I'm supposed to write some some UI (e2e) tests but I'm not even able to input text in an input field.
My problem is that
element(by.id('username')).sendKeys('test')
is not working. (Same with Button elements and so on)
I'm sure that it is only a small thing but I'm not able to find out what it is.
I have the following configuration:
Spec file:
import { LoginPage } from './login.po';
describe('login tests', function() {
let page: LoginPage;
beforeEach(() => {
page = new LoginPage();
});
it('Demo', () => {
page.navigateTo();
page.getUsernameInput().sendKeys('test');
});
});
Page Object file:
import { browser, element, by } from 'protractor';
export class LoginPage {
navigateTo() {
return browser.get('/login');
}
getParagraphText() {
return element(by.class('app-root h1')).getText();
}
getUsernameInput() {
return element(by.id('username'));
}
}
The HTML template:
....
<div>
<input
id="username"
name="username"
ngModel
type="text"
placeholder="{{something}}"
autocomplete="off"
class="input-text"
required>
</div>
...
Proctractor config
var SpecReporter = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 120000,
getPageTimeout: 120000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
seleniumAddress: 'http://localhost:4444/wd/hub',
baseUrl: 'http://localhost:8001',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
useAllAngular2AppRoots: true,
beforeLaunch: function() {
require('ts-node').register({
project: 'e2e'
});
},
onPrepare: function() {
jasmine.getEnv().addReporter(new SpecReporter());
}
};
Any help is highly appreciated.
EDIT:
None of the solutions worked in my case. I ended up using browser.driver.findElement(by.id('username'));
instead of element(by.id('username'));
This is unsatisfying because I still don't understand why this doesn't work. I'd be thankful if someone could give me a hint or explanation.
Upvotes: 0
Views: 1438
Reputation: 7108
I think your problem is timing.
What happens if you do:
it('Demo', () => {
// wait for page to change to /login
return page.navigateTo().then(() => {
// then look for user input and write 'test'
return page.getUsernameInput().sendKeys('test');
});
});
Edit:
Sounds odd to me that browser.driver.findElement(by.id('username'))
works since element(by.id('username'))
should be equivalent.
I use a helper class for a lot of the browser interactions, perhaps worth a shot.
Snippets I use for finding element and sending keystrokes:
public static async getElement(locator: By | Function, waitMs?: number): Promise<ElementFinder | any> {
await BrowserHelper.waitForVisibilityOf(locator, waitMs | 1000);
return element(locator);
}
public static sendKeys(locator: By | Function, keys: string, clear?: boolean, waitMs?: number): Promise<void> {
return BrowserHelper.getElement(locator, waitMs).then((element: ElementFinder) => {
if (!clear) {
return element;
}
return element.clear().then(() => element);
}).then((element: ElementFinder) => {
return element.sendKeys(keys)
});
}
public static async waitForVisibilityOf(locator: By | Function, waitMs?: number): Promise<any> {
await browser.wait(EC.presenceOf(element(locator)), waitMs || 5000).then(() => {
// visible
}, (error) => {
console.error('timeout at waitForVisibilityOf', locator, error);
});
}
Upvotes: 2
Reputation: 4264
I believe this is due to your getUsernameInput()
method returning not the locator in this case. As per Protractor documentation,
The element() function returns an ElementFinder object. The ElementFinder knows how to locate the DOM element using the locator you passed in as a parameter, but it has not actually done so yet. It will not contact the browser until an action method has been called.
You can try this modified code
getUsernameInput() {
element(by.id('username')).sendKeys('text');
}
}
and then using
it('Demo', () => {
page.navigateTo();
page.getUsernameInput();
});
});
Also, I'm not sure your getText()
would return the text, because getText()
returns a Promise, which you would have to resolve. This has been explained here.
Upvotes: 0