Home > Software engineering >  How can I test/validate the header hierarchy of a section in cypress?
How can I test/validate the header hierarchy of a section in cypress?

Time:03-05

i want to enforce the structure that headers follow a hierarchy. Meaning if you go from bottom to top of the dom, thr next heading must be <= current or 1.

Here is the console log of my headings in one of my sections for example:

Yielded:

0: h2.mt-4
1: h3.mt-16.text-base.w-64
2: h4.mt-0.font-normal.text-sm
3: h4.mt-0.font-normal.text-sm
4: h4.mt-0.font-normal.text-sm
5: h3.mt-16.text-base.w-64
6: h4.mt-0.font-normal.text-sm
7: h4.mt-0.font-normal.text-sm
8: h4.mt-0.font-normal.text-sm
9: h4.mt-0.font-normal.text-sm
10: h3.mt-16.text-base.w-64
11: h4.mt-0.font-normal.text-sm
12: h4.mt-0.font-normal.text-sm

This would be valid ^

Yielded:   

0: h2.mt-4
1: h3.mt-16.text-base.w-64
2: h4.mt-0.font-normal.text-sm
3: h4.mt-0.font-normal.text-sm
4: h4.mt-0.font-normal.text-sm
5: h3.mt-16.text-base.w-64
6: h4.mt-0.font-normal.text-sm
7: h4.mt-0.font-normal.text-sm
8: h4.mt-0.font-normal.text-sm
9: h4.mt-0.font-normal.text-sm
10: h3.mt-16.text-base.w-64
11: h1.mt-0.font-normal.text-sm
12: h1.mt-0.font-normal.text-sm

And this is not ^^^

So far I can loop through the sections and get each sections headers, but a bit stumped on how to loop through and force that rule. It would require comparing the current header and the next one in the array.

What I have so far:

Cypress.Commands.add("checkHeadingHeirarchy", () => {
  cy.get("section").each(($section) => {
    cy.get($section).within(() => {
      cy.get("h1,h2,h3,h4,h5,h6"); //now what?...
    });
  });
});

@agoff: The console.log shows us the first $el and then the $list[index 1]:

This is the $el: jQuery.fn.init [h2.mt-4]
This is the $el: <h3 data-cy=​"header" class=​"mt-16 text-base w-64">​Engineering​</h3>​

@agoff: This works, but its hacky:

Cypress.Commands.add("checkHeadingHeirarchy", () => {
  cy.get("section").each(($section) => {
    cy.get($section).within(() => {
      cy.get("h1,h2,h3,h4,h5,h6").each(($el, index, $list) => {
        // Don't run the validation on the last item in the list
        if (index !== $list.length - 1) {
          // Get the size of the current and next header
          const currSize = getHeaderNumber($el);
          const nextSize = getHeaderNumber($list, index   1);
          try {
            expect(currSize <= nextSize || currSize   1 === nextSize).to.eql(
              true
            );
          } catch {
            console.log("Failed on current size:", currSize);
            console.log("Failed on next size:", nextSize);
            throw error;
          }
        }
      });
    });
  });
});

// helper function to get header number
const getHeaderNumber = ($el, index) => {
  console.log("Going to parse this:", $el.get(index ?? 0));
  try {
    console.log("Got this:", parseInt($el.get(index ?? 0).tagName.slice(1)));
    return parseInt($el.get(index ?? 0).tagName.slice(1));
  } catch {
    console.log("ERROR ON:", $el.get(index ?? 0));
  }
};

CodePudding user response:

You can yield the index of the elements yielded, as well as the entire list. Using that, we can easily compare the next yielded item.

Cypress.Commands.add("checkHeadingHeirarchy", () => {
  cy.get("section").each(($section) => {
    cy.wrap($section).within(($sectionWithin) => {
      cy.get("h1,h2,h3,h4,h5,h6").each(($el, index, $list) => {
        // Don't run the validation on the last item in the list
        if (index !== $list.length - 1) {
          // Get the size of the current and next header
          const currSize = getHeaderNumber($el)
          const nextSize = getHeaderNumber($list[index   1])
          expect(currSize <= nextSize || currSize   1 === nextSize).to.eql(true);
        }
      });
    });
  });
});

// helper function to get header number
const getHeaderNumber = ($el) => {
  const tagName = $el.prop('tagName') ?? $el.get(0).tagName
  return parseInt(tagName.slice(1), 10);
}
  • Related