最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Testing tab navigation order - Stack Overflow

matteradmin8PV0评论

In one of our tests, we need to make sure that the tab keyboard navigation inside a form is performed in the correct order.

Question: What is the conventional way to check the tab navigation order with protractor?


Currently we are solving it by repeating the following step for as many input fields existing in a form (code below):

  • check the ID of the currently focused element (using getId())
  • send TAB key to the currently focused element

Here is the example spec:

it("should navigate with tab correctly", function () {
    var regCodePage = new RegCodePage();
    browser.wait(protractor.ExpectedConditions.visibilityOf(regCodePage.title), 10000);

    // registration code field has focus by default
    expect(regCodePage.registrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved to Remember Registration Code
    regCodePage.registrationCode.sendKeys(protractor.Key.TAB);
    expect(regCodePage.rememberRegistrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved to Request Code
    regCodePage.rememberRegistrationCode.sendKeys(protractor.Key.TAB);
    expect(regCodePage.requestCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved to Cancel
    regCodePage.requestCode.sendKeys(protractor.Key.TAB);
    expect(regCodePage.cancelButton.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved back to the input
    regCodePage.cancelButton.sendKeys(protractor.Key.TAB);
    expect(regCodePage.registrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
});

where regCodePage is a Page Object:

var RegCodePage = function () {
    this.title = element(by.css("div.modal-header b.login-modal-title"));
    this.registrationCode = element(by.id("regCode"));

    this.rememberRegistrationCode = element(by.id("rememberRegCode"));
    this.requestCode = element(by.id("forgotCode"));

    this.errorMessage = element(by.css("div.auth-reg-code-block div#message"));

    this.sendRegCode = element(by.id("sendRegCode"));
    this.cancelButton = element(by.id("cancelButton"));
    this.closeButton = element(by.css("div.modal-header button.close"));
};

module.exports = RegCodePage;

It is working, but it is not really explicit and readable which makes it difficult to maintain. Also, another "smell" in the current approach is a code duplication.

If the current approach is how you would also do it, I would appreciate any insights about making it reusable.

In one of our tests, we need to make sure that the tab keyboard navigation inside a form is performed in the correct order.

Question: What is the conventional way to check the tab navigation order with protractor?


Currently we are solving it by repeating the following step for as many input fields existing in a form (code below):

  • check the ID of the currently focused element (using getId())
  • send TAB key to the currently focused element

Here is the example spec:

it("should navigate with tab correctly", function () {
    var regCodePage = new RegCodePage();
    browser.wait(protractor.ExpectedConditions.visibilityOf(regCodePage.title), 10000);

    // registration code field has focus by default
    expect(regCodePage.registrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved to Remember Registration Code
    regCodePage.registrationCode.sendKeys(protractor.Key.TAB);
    expect(regCodePage.rememberRegistrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved to Request Code
    regCodePage.rememberRegistrationCode.sendKeys(protractor.Key.TAB);
    expect(regCodePage.requestCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved to Cancel
    regCodePage.requestCode.sendKeys(protractor.Key.TAB);
    expect(regCodePage.cancelButton.getId()).toEqual(browser.driver.switchTo().activeElement().getId());

    // focus moved back to the input
    regCodePage.cancelButton.sendKeys(protractor.Key.TAB);
    expect(regCodePage.registrationCode.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
});

where regCodePage is a Page Object:

var RegCodePage = function () {
    this.title = element(by.css("div.modal-header b.login-modal-title"));
    this.registrationCode = element(by.id("regCode"));

    this.rememberRegistrationCode = element(by.id("rememberRegCode"));
    this.requestCode = element(by.id("forgotCode"));

    this.errorMessage = element(by.css("div.auth-reg-code-block div#message"));

    this.sendRegCode = element(by.id("sendRegCode"));
    this.cancelButton = element(by.id("cancelButton"));
    this.closeButton = element(by.css("div.modal-header button.close"));
};

module.exports = RegCodePage;

It is working, but it is not really explicit and readable which makes it difficult to maintain. Also, another "smell" in the current approach is a code duplication.

If the current approach is how you would also do it, I would appreciate any insights about making it reusable.

Share Improve this question edited May 23, 2017 at 12:05 CommunityBot 11 silver badge asked Feb 27, 2015 at 23:17 alecxealecxe 475k127 gold badges1.1k silver badges1.2k bronze badges
Add a ment  | 

1 Answer 1

Reset to default 6 +50

I think the PageObject should define a tab order list, since that is really a direct property of the page, and should be expressible as simple data. An array of items seems like a sufficient representation, so something like:

this.tabOrder = [ this.registrationCode, this.rememberRegistrationCode, this.requestCode, this.cancelButton ];

Then you need a bit of generic code that can check a tab order.

function testTabOrder(tabOrder) {
    // Assumes TAB order hasn't been messed with and page is on default element
    tabOrder.forEach(function(el) {
       expect(el.getId()).toEqual(browser.driver.switchTo().activeElement().getId());
       el.sendKeys(protractor.Key.TAB);
    });
}

Then your test would be something like:

it('has correct tab order', function() {
    var regCodePage = new RegCodePage();  // this should probably be in the beforeEach
    testTabOrder(regCodePage.tabOrder);
});

Of course, this assumes each element has a "getId()" method that works. (That seems like a reasonable assumption to me, but some environments may not support it.)

I think this keeps the tab-order nicely isolated on the PageObject (so its easy to keep in sync with the page content and doesn't get lost in the code that verifies the order). The testing code seem "optimistic" (I suspect the real world will introduce enough problems that you will end up expanding this code a bit).

I haven't tried any of this yet, so feel free to downvote if this doesn't work. :)

Also, I believe the forEach loop will work as-is, but I wouldn't be surprised if it needs some more explicit promise handling to make the dependencies explicit.

Post a comment

comment list (0)

  1. No comments so far