0

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:

  • Proctractor: 5.1.2
  • chrome driver: 58.0.3029.110
  • OS: Windows NT 6.1.7601 SP1 x86_64

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.

Vetemi
  • 784
  • 2
  • 9
  • 26

2 Answers2

2

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);
    });
}
cYrixmorten
  • 7,110
  • 3
  • 25
  • 33
  • This is not the problem. It's still not working unfortunately. See my edit for more information. – Vetemi Jun 07 '17 at 07:41
  • Strange, and still no output indicating what is going on with the `element()` version? Perhaps try adding ` --verbose` flag when running protractor. – cYrixmorten Jun 07 '17 at 08:13
0

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.

demouser123
  • 4,108
  • 9
  • 50
  • 82
  • Oh yes, the getText() is not used. It was generated and I just forgot to delete it. Even with your change it does not work unfortunately. Any other guess, maybe? – Vetemi Jun 02 '17 at 16:30