vtaits / react-select-async-paginate

Wrapper above react-select that supports pagination on menu scroll
MIT License
303 stars 75 forks source link

How to Testing? #103

Open jeff00seattle opened 2 years ago

jeff00seattle commented 2 years ago

Great module, and great results. Question: How does one test this component when in use?

Before switching out <select> for this solution, testing involved navigating through this component using CSS selectors, and then was able to verify all expected <option>(s).

Screen Shot

DevTools inspection shows nothing to navigate to validate runtime usage of this component.

Thank you

vtaits commented 2 years ago

Hello. What you want to test?

This library is a wrapper above react-select.

If you use selenium-like test framework with css-selectors, you can use props className and classNamePrefix.

https://react-select.com/props

If you want to inspect DOM with devtools, I can recommend a strange solution:

  1. Execute in console
setTimeout(() => {
  debugger;
}, 2000);
  1. Immediately open select-box
jeff00seattle commented 2 years ago

@vtaits Thank you for your response. I am using Cypress test runner. Checking out your suggestions.

What do you want to test?

  1. Default select value
  2. Available options for selection
  3. Select an option and assure it sticks
jeff00seattle commented 2 years ago

@vtaits

This is the generated react-select-async-paginate:

<div>
  <div class="***-singleValue">Offer Letter w/ Signature</div>
  <div class=" css-ackcql" data-value="">
    <input 
        id="react-select-2-input" 
        aria-autocomplete="list" 
        aria-expanded="false" 
        aria-haspopup="true"
        aria-controls="react-select-2-listbox" 
        aria-owns="react-select-2-listbox" 
        role="combobox">
  </div>
</div>

This is the attempt for selecting an option, but it does not loads selected option into <div class="***-singleValue">.

This Cypress script selects an option:

  cy.get(`${selectorReactSelectPaginate}`)
    .find('input[role="combobox"]')
    .focus()
    .type($valueSelect, { force: true })
    .then(() => {
      cy.wrap(true);
    });

As would able to validated using this Cypress script:

  cy.get(selectorReactSelectPaginate)
    .find('div[class*="-singleValue"]')
    .contains($valueSelectContains)
    .then(() => {
      cy.wrap(true);
    });
IvoLeist commented 2 years ago

since I am also struggling right now with testing a filterable selection box created with this library, see the issue in the cypress repository: https://github.com/cypress-io/cypress/issues/20668

maybe we could help each other :v: This is how far I have come in regards of how to select an option

Cypress.Commands.add("selectItem, function (item_id) {
  cy.intercept("POST", `${Cypress.env("apiUrl")}/items/list`).as(
    "itemsList"
  );

 cy.get(selectorReactSelectPaginate)
    .click()
    .then(() => {
      cy.wait("@itemsList").then((res) => {
        cy.log("res.response.body >>", res.response.body); // [item1, item2, item3]
        const idx = res.response.body.indexOf(item_id));
        cy.log("idx >>", idx);
        const option = `[id*=option-${res.response.body.indexOf(item_id)}]`;
        cy.get(option)
          .click()
          .then(() => {
            cy.get(selector).should("contain", item_id);
          });
      });
    });
});

With what I still struggle is when I do not use .click() but .type()

cy.get(selectorReactSelectPaginate)
    .type(item_id, {delay:0})
    .then(() => {...

Because cypress delay functionality does not seem to work together with this library(?):

data_query :>> {item_id: ''} data_query :>> {Item_id: '1'} data_query :>> {item_id: '12'} data_query :>> {item_id: '123'} data_query :>> {item_id: '1234'}

each line is a console.log of the fetch function to our API

IvoLeist commented 2 years ago

FYI:

I resolved the issue with testing the filtering:

Cypress.Commands.add("inputChange", (input, value) => {
  // taken from https://stackoverflow.com/a/69552958/11217233
  const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
    window.HTMLInputElement.prototype,
    "value"
  ).set;

  const changeInputValue = (inputToChange) => (newValue) => {
    nativeInputValueSetter.call(inputToChange[0], newValue);
    inputToChange[0].dispatchEvent(
      new Event("input", {
        newValue,
        bubbles: true,
        composed: true,
      })
    );
  };
  return cy.get(input).then((input) => {
    changeInputValue(input)(value);
  });
});

and in Cypress it works as follows:

cy.intercept("POST", `${Cypress.env("apiUrl")}/items/list`).as("itemsList");
cy.get("#react-select-2-input")
      .then((input) => {
        cy.inputChange(input,"1234")
        cy.wait("@itemsList").then((res) => {
          expect(res.response.body.length).to.eq(1);
          expect(res.response.body[0]).to.eq("1234");
        })
    })
sdenisen commented 2 years ago

Hello!

Could you please explain how to correctly use loadOptionsOnMenuOpen property? When I set the property to true - nothing happened.

Thank you in advance

IvoLeist commented 2 years ago

I am not a maintainer of the library but a user. Nevertheless, I believe that this question has nothing to do with the initial request of @jeff00seattle so I would suggest you @sdenisen to open a new issue. Good luck with solving your bug :v:

wilsonmedeiros commented 2 years ago

how to test with jest and testing-library?