cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.87k stars 3.18k forks source link

Angular Component Harness (Test Harness) support in Cypress #7931

Open Manojms1997 opened 4 years ago

Manojms1997 commented 4 years ago

Current behavior:

Cypress based e2e test cases are not supporting angular Component Harness (Test Harness).

Desired behavior:

Cypress e2e tests shall be able to utilize angular component(test) harness. CypressElement and CypressHarnessEnvironment shall be available similar to ProtractorElement and ProtractorHarnessEnvironment.

Test code to reproduce

After CypressElement and CypressHarnessEnvironment is available, the user shall be able to use harness test cases in cypress e2e like:

 it('should get button label from button harness', async () => {
    harnessLoader = CypressHarnessEnvironment.loader();
    const ButtonHarness = harnessLoader.getHarness(ButtonTestHarness);
    (await ButtonHarness).ButtonLabel().then(async (value) => {
      expect(value).toEqual('label');
    });
  });

Why we need this feature

Currently, our e2e test cases are using Cypress. In order to use test harness APIs provided by UI library in our e2e, we need support from cypress.

Please let me know if there is any plan to support angular test harness.

Note: This is a feature request

juanmendes commented 4 years ago

I tried implementing a TestEnvironment for cypress. One of the difficulties we encountered with implementing the cypress environment is implementingTestElement#text() and other methods query an element (classes, attributes...). Since cypress doesn't return a real Promise, getting the text of a cypress chainable and returning it as a promise is highly recommended against by cypress. Cypress recommends reading text as assertions, it doesn't have a clean way to return the text of the current node.

I know you can use solutions like https://github.com/NicholasBoll/cypress-promise but there were two reasons we didn't move forward:

We ended up writing a different pattern where the page object is just a bunch of calls that locate HTML elements and that can be shared between our karma unit and cypress e2e tests.

// e2e test
it("enables ok button", () => {
    loginWidget.getOkButton().should('be.disabled');
    loginWidget.getUserName().type('username');
    loginWidget.getPassword().type('a$h7r4y');
    loginWidget.getOkButton().should('be.enabled'); 
})
// unit test
it("enables ok button", () => {
    expect(loginWidget.getOkButton().enabled()).toBe(false);
    loginWidget.getUserName().type('username');
    loginWidget.getPassword().type('a$h7r4y');
    expect(loginWidget.getOkButton().enabled()).toBe(false);
})
yjaaidi commented 3 years ago

Hey! Just stumbled upon this issue. Did you try https://github.com/jscutlery/test-utils/tree/master/packages/cypress-harness?

bahmutov commented 3 years ago

See https://github.com/bahmutov/cypress-angular-unit-test

peterhodges commented 1 year ago

cdk/harness is built in an implementation-agnostic way so it can be used by various test frameworks (karma, webdriver etc) which makes sense for cdk as they have a large set of unknown developers.

The cypress-harness package linked above is a cool adapter for cypress & cdk/harness and looks great from what I can see.

For us, we decided against it because it's just another layer of abstraction and adds a bit of complexity.

In case anyone is interested, we follow a simple pattern that looks like this:

class ComponentHarness {
  constructor(protected override root: () => Cypress.Chainable<JQuery<HTMLElement>>) {}
}

class CheckboxHarness extends ComponentHarness {
  toggle() {
    this.root().click();
    return this;
  }

  isSelected(selected = true) {
    if (!selected) {
      this.root().should('not.have.class', 'selected');
      return this;
    }

    this.root().should('have.class', 'selected');
    return this;
  }
}

To consume a harness, we'd do:

const checkboxHarness = new CheckboxHarness(() => cy.get('[test-id="my-specific-checkbox"]'));
checkboxHarness.toggle().isSelected(true)

The key points are:

This has worked really well for us and doesn't require any third-party packages. Obviously, the downside is that it ties your harnesses to cypress but we're tied to cypress for all of our tests anyway.