The information about call-time preference is visually displayed as a description list. In this case, it's a question and then an answer. This content is not marked up as a list.
When content is presented as a list, or a clearly related collection of items, marking it up using semantic list HTML elements helps assistive technology users to navigate and orient themselves within a page of content. Screen reader users can navigate to (or over) lists when they are correctly marked up. Also, when reading content in a list, assistive technology provides rich information about how long the list is and where the user is in the list. For example: "List, 9 items, Home, 1 of 9, About, 2 of 9".
This particular list is confusing because it is displayed even when there is no time indicated, like when a user chooses email as the preferred method of communication.
Recommendation
Remove the list entirely and write this information as a sentence. "We will reach out to you by phone during business hours," for example. If the user indicates that they prefer email, either write a new sentence indicating that preference, "One of our representatives will email you shortly," or remove the sentence altogether.
If you choose to keep the question and answer structure, use a description list (<dl>)for this data.
Code example (simplified)
Resources
Description Lists
Using description lists
Important Information about Techniques
See for important information about the usage of these informative techniques and how they relate to the normative WCAG 2.1 success criteria. The Applicability section explains the scope of the technique, and the presence of techniques for a specific technology does not imply that the technology can be used in all situations to create content that meets WCAG 2.1.
The objective of this technique is to provide the description of names or terms by presenting them in a description list. The list is marked up using the dl element. Within the list, each term is put in a separate dt element, and its description goes in the dd element directly following it. Multiple terms can be associated with a single description, as can a single term with multiple descriptions, provided that semantic sequence is maintained. The title attribute can be used to provide additional information about the description list. Usage of description lists ensures that terms and their descriptions are semantically related even as presentation format changes, as well as ensuring that these terms and descriptions are semantically grouped as a unit.
Description lists are easiest to use when the descriptions are ordered alphabetically. A common use for description lists is a glossary of terms.
NOTE
In HTML5 the name "Description list" was introduced. In previous versions these lists were referred to as "Definition lists".
Examples
Example 1
A list of descriptions of nautical terms used on a Website about sailing.
Resources
Resources are for information purposes only, no endorsement implied.
<dl title="Nautical terms">
<dt>Knot</dt>
<dd>
<p>A <em>knot</em> is a unit of speed equaling 1
nautical mile per hour (1.15 miles per hour or 1.852
kilometers per hour).</p>
</dd>
<dt>Port</dt>
<dd>
<p><em>Port</em> is the nautical term (used on
boats and ships) that refers to the left side
of a ship, as perceived by a person facing towards
the bow (the front of the vessel).</p>
</dd>
<dl>
<dt>If contact by phone is your preference, what time of day is best?</dt>
<dd>Daytime</dd>
</dl>
<dt>Starboard</dt>
<dd>
<p><em>Starboard</em> is the nautical term (used
on boats and ships) that refers to the right
side of a vessel, as perceived by a person
facing towards the bow (the front of the vessel).</p>
</dd>
</dl>
DNT-2860 Go Green Calculator
New Features
New Simple Calculator Input Warning And Block Explanation**
The need for this ticket derives from a fictional unit of energy duke created called a block which is "100 kWh of 'green' energy". Because a block requires whole-number outputs that necessitates a minimum input value; which arguably needs to be explained to the user, and if the user fails to heed the instructions... have the warning change color to red if they input a lower number.
i.e. input modulo 100 should return a number not equal to input.
Additionally the calculator should include an explanation of the fictional unit being used in the output
i.e.
When you participate in the GoGreen Ohio program, you’re supporting the advancement of green power sources. Green power is electricity produced from natural resources – like the sun, wind, and water – that do not emit pollutants into the atmosphere.
As a GoGreen Ohio participant, you can match your home’s electricity use by purchasing blocks* of renewable energy certificates (RECs). These RECs certify the generation of green power on your behalf. Every block you purchase supports the advancement of environmentally friendly, renewable energy sources, thereby reducing dependence on fossil fuels to generate energy.
*One GoGreen Ohio program block represents 100 kWh of clean energy. A 10-block purchase (1,000 kWh) equals one REC (1MWh).
This will be a replacement of the existing calculators:Go Green:(Ohio jurisdiction, calc is under the Go Green Ohio video)
Renewable Advantage:(NC jurisdiction, look for "Calculate Your Estimated Cost"
Design questions contact: \
This will be a replacement of the existing calculators:
Go Green: (Ohio jurisdiction, calc is under the Go Green Ohio video)
Renewable Advantage: (NC jurisdiction, look for "Calculate Your Estimated Cost"
Features a full-width image (light or dark) with superimposed text (light or dark contrasting). See a demo page with a site header.
Usage Guidance
Do
Use on home pages and landing pages with multiple child pages.
When used on pages other than Home Pages or Section Landing Pages, the headline (H1) must be the page title.
Include a title/headline (required), a description (optional), and call-to-action link button(s) (optional).
Do Not
Use more than ONE Hero on a page.
Toggle Component Options
Theme Black to Gray-Darker Blue-Dark to Blue Blue to Teal-Darker Green-Dark to Green Blue-Dark to Green-Dark Green-Dark to Blue-Dark Gray-Light to white Gray-Light to Gray-Lighter Teal-Light to Teal-Lighter Image Business Solar Chef Family Landscape One Person Store Solar Solar Cell Two Person Store Content Content 1 Content 2 Content 3 Too Much Content Action No Actions Primary Action Primary and Secondary Action
Say Yes to Renewables
Striving for sustainability is just smart business
Accessibility
Labeling Expectations
Use a unique `id=""` on the title.
Use a unique `id=""` on the action link button(s).
Use `aria-labelledby=""` on the link buttons referencing the id of the link button(s) and the id of the title.
Keyboard Expectations
When you TAB into the `Hero` component, focus will go onto the link button(s).
Resources
2654-a11y-Audit-Form-Errors
Required and invalid form controls must convey/expose the fact that they are required and invalid
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{{}}
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format </p>{code}
{{}}
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
Recommendation
Set aria-invalid="true" on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the aria-invalid attribute or set it to false.
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use aria-describedby to associate the error message with the form field. Once the field is valid, remove the error message.
Setting aria-describedby to point to an error message
Email <input id="email" type="email" aria-invalid="true" aria-describedby="email_error"> <p id="email_error">Please enter a valid email address in the format name@example.com
Options
6cbe92fc1812489eacd2322b8e5a2e2f
Notes:
Invalid form controls are visually indicated as invalid, but this state is not communicated programmatically. Assistive technology users may have difficulty determining which controls are invalid.
h5. Recommendation
Set {{aria-invalid="true"}} on form fields that contain invalid data. This will ensure that the field is exposed to assistive technologies as an invalid field, and screen readers will announce this, for example, by announcing "invalid entry" as part of the field description. Once the field is valid, remove the {{aria-invalid}} attribute or set it to {{false}}.
Setting aria-invalid
{{<label for="address">Address</label>}}
{{<input id="address" type="text" aria-invalid="true">}}
When an inline error message communicates specific information (e.g., beyond the fact that the field was left blank), use {{aria-describedby}} to associate the error message with the form field. Once the field is valid, remove the error message.
Setting {{aria-describedby}} to point to an error message
{code:java}
<label for="email">Email</label>
<input id="email" type="email" aria-invalid="true" aria-describedby="email_error">
<p id="email_error">Please enter a valid email address in the format name@example.com</p>{code}
DNT-2724 Accordion Testing
5 Things You Didn't Know About React Testing Library
Excerpt
I've just sold myself to the gods of click-baiting by making an "x things you didn't know about y" post. But hey, at least there no subtitle that says "number three will blow your mind!"
I've just sold myself to the gods of click-baiting by making an "x things you didn't know about y" post. But hey, at least there no subtitle that says "number three will blow your mind!"
Jokes aside the items in this list are concepts that I usually see beginners struggling with. At the same time, learning these concepts will vastyly improve your testing game. I know it did with mine.
1. Everything is a DOM node
This is usually the first misconception that beginners have when they start approaching Testing Library. It is especially true for those developers like me that came from .
Many think that getByText and other helper methods return some special wrapper around the React component. People even ask how to implement a getByReactComponent helper.
When you work with Testing Library you are dealing with . This is made clear by the first :
If it relates to rendering components, then it should deal with DOM nodes rather than component instances, and it should not encourage dealing with component instances.
If you want to check for yourself, it's as simple as this:
Once you realize that you're dealing with DOM nodes you can start taking advantage of all the DOM APIs like or 👍
2. debug's optional parameter
Since we now know that we're dealing with a DOM structure, it would be helpful to be able to "see" it. This is what is meant for:
ometimes thought debug's output can be very long and difficult to navigate. In those cases, you might want to isolate a subtree of your whole structure. You can do this easily by passing a node to debug:
3. Restrict your queries with within
Imagine you're testing a component that renders this structure:
You want to test that each ID gets its correct value. You can't use getByText('Apples') because there are two nodes with that value. Even if that wasn't the case you have no guarantee that the text is in the correct row.
What you want to do is to run getByText only inside the row you're considering at the moment. This is exactly what is for:
4. Queries accept functions too
You have probably seen an error like this one:
Usually, it happens because your HTML looks like this:
The solution is contained inside the error message: "[...] you can provide a function for your text matcher [...]".
What's that all about? It turns out matchers accept strings, regular expressions or functions.
The function gets called for each node you're rendering. It receives two arguments: the node's content and the node itself. All you have to do is to return true or false depending on if the node is the one you want.
An example will clarify it:
We're ignoring the content argument because in this case, it will either be "Hello", "world" or an empty string.
What we are checking instead is that the current node has the right . hasText is a little helper function to do that. I declared it to keep things clean.
That's not all though. Our div is not the only node with the text we're looking for. For example, body in this case has the same text. To avoid returning more nodes than needed we are making sure that none of the children has the same text as its parent. In this way we're making sure that the node we're returning is the smallest—in other words the one closes to the bottom of our DOM tree.
5. You can simulate browsers events with user-event
Ok, this one is a shameless plug since I'm the author of user-event. Still, people—myself included—find it useful. Maybe you will too.
All user-event tries to do is to simulate the events a real user would do while interacting with your application. What does it mean? Imagine you have an input field, and in your tests, you want to enter some text in it. You would probably do something like this:
It works but it doesn't simulate what happens in the browser. A real user would most likely move the mouse to select the input field and then start typing one character at the time. This, in turns, fires many events (blur, focus, mouseEnter, keyDown, keyUp...). user-event simulates all those events for you:
<!--
Hero Section wrapper
- Component below hero is required to use a white background color
-->
<section class="relative 2xl:px-24 2xl:pt-24">
<!--
Hero Container
-->
<div class="relative container-5xl flex flex-col justify-center aspect-16/12 sm:aspect-16/9 md:aspect-16/7 lg:aspect-16/6 xl:aspect-16/5 px-24 sm:px-32 md:px-48 py-64 md:py-48">
<!--
- Leave alt attribute empty
- Use 'srcset' and 'sizes' attributes to optimize the hero image
-->
<img
class="absolute top-0 left-0 object-cover object-right w-full h-full 2xl:rounded-lg bg-gray-light"
src="image.jpg?w=800&as=1&bc=ffffff"
srcset="image.jpg?w=800&as=1&bc=ffffff 800w,
image.jpg?w=1600&as=1&bc=ffffff 1600w"
sizes="(min-width: 768px) 1600px, 800px"
alt=""
width="1600"
height="500"
loading="lazy"
>
<!--
Overlay
- Change background gradient colors based on theme of hero
- Default - "from-blue-dark to-blue sm:via-blue"
-->
<div
class="absolute top-0 left-0 h-full w-full 2xl:rounded-l-lg md:w-3/4 bg-gradient-to-tr md:bg-gradient-to-r md:to-transparent opacity-80"
aria-hidden="true"
></div>
<!--
Content Container
-->
<div class="relative w-full container-xs md:container-4xl">
<!--
If dark theme/gradient, text is white
- Use "text-white"
If light theme/gradient, text can be gray or blue
- Use "text-gray-dark" -or- "text-blue"
Default
- "text-white"
-->
<div class="w-full md:w-1/2 text-center md:text-left">
<!-- Hero Title
- If this is the page title, you should use an <h1> element
- Use an <h2> element if you already have a page title on the page
-->
<h2
class="text-3xl md:text-2xl-fixed xl:text-3xl"
id="hero-title"
>
Hero Title
</h2>
<!-- Hero Short Description-->
<p class="text-lg xl:text-xl mt-12 lg:mt-16">
Description goes here.
</p>
<!-- Hero Actions -->
<div class="flex justify-center md:justify-start gap-16 lg:gap-24 mt-16 lg:mt-24">
<!--
If dark theme/gradient
- Use "btn-primary-reversed"
If light theme/gradient
- Use "btn-primary"
Default
- "btn-primary-reversed"
-->
<a
class="btn btn-primary-reversed btn-md"
href="#"
id="hero-primary-action"
aria-labelledby="hero-primary-action hero-title"
>
Primary Action
</a>
<!--
If dark theme/gradient
- Use "btn-secondary-reversed"
If light theme/gradient
- Use "btn-secondary"
Default
- "btn-secondary-reversed"
-->
<a
class="btn btn-secondary-reversed btn-sm lg:btn-md"
href="#"
id="hero-secondary-action"
aria-labelledby="hero-secondary-action hero-title"
>
Secondary Action
</a>
</div>
</div>
</div>
</div>
</section>
Components must receive focus in an order that preserves meaning and operability
Unable to find an element with the text: Hello world.
This could be because the text is broken up by multiple elements.
In this case, you can provide a function for your text
matcher to make your matcher more flexible.
importReactfrom"react";import{render,screen}from"@testing-library/react";test("everything is a node",()=>{constFoo=()=><div>Hello</div>;render(<Foo/>);expect(screen.getByText("Hello")).toBeInstanceOf(Node);});
importReactfrom"react";import{render,screen}from"@testing-library/react";test("the button has type of reset",()=>{constResetButton=()=> (<buttontype="reset"><div>Reset</div></button> );render(<ResetButton/>);constnode=screen.getByText("Reset"); // This won't work because `node` is the `<div>` // expect(node).toHaveProperty("type", "reset");expect(node.closest("button")).toHaveProperty("type","reset"});
DNT-2659 A meaningful image must have a text alternative that serves the equivalent purpose
Info
Throtteling Event Listeners
Throttle
Using Throttling and Debouncing with React hooks - DEV Community
Excerpt
Throttling and debouncing techniques has been in use for past many years in javascript.
In this post I'd like to share my knowledge on how we can use throttle and debounce functions with help of react hooks.
Consider below example with two routes
// # TextMatch type accenpts function: https://testing-library.com/docs/queries/about/#textmatch
import { renderWithCTX, screen, Matcher } from "src/lib/testWrappers";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";
import { Accordion, themeMap } from "./index";
import { compositionFunction } from "./composition";
import data from "./data";
import { stripHTMLTags } from "src/lib/helpers";
jest.mock("src/lib/useIntersection");
describe("Accordion", () => {
const props = compositionFunction(data);
it.skip("should render the correct items", () => {
renderWithCTX(<Accordion {...props} />);
for (let i = 0; i < props.items.length - 1; i++) {
const accordionTitle = screen.getByText(
props?.items[0]?.title?.value as string
);
expect(accordionTitle).toBeTruthy();
}
});
it.skip("should render Accordion Component with image", () => {
renderWithCTX(<Accordion {...props} />);
const img = screen.getByRole("img", { name: /facebook/i });
expect(img).toBeInTheDocument();
});
it("should reveal text when user clicks", async () => {
renderWithCTX(<Accordion {...props} />);
const accordionButton = screen.getByRole("button", {
name: props.items[0].title?.value,
});
// # Full Manual Query:
// (This is actually not good - getByText won't respect eg aria- attrs like getByRole so we aren't actually testing anything)
// These are [not exposed to a11y tree](https://testing-library.com/docs/queries/about/#priority)
// 👉
// screen.getByText(
// /proin laoreet mauris vel urna tempor ultricies\. duis rhoncus lorem sed tellus egestas bibendum\. in aliquam mauris est, vel condimentum metus aliquet a\. nunc volutpat tincidunt nisl luctus pretium\. sagittis elit non, vestibulum metus\. mauris maximus vitae magna in mattis\. integer interdum maximus felis sed placerat\. nam lobortis tellus non felis fermentum, vitae venenatis ligula congue\. donec sit amet luctus odio\. magna commodo, sodales convallis ante scelerisque\. etiam ipsum lorem, rhoncus a sapien id, placerat consequat nunc\. curabitur in orci libero\. morbi tincidunt ante vel sem rutrum tempor\. cras ac purus quis urna maximus volutpat\./i
// );
// # We can still do a findByText,
// but we need to check ourselves whether it is accessible:
// 👉
const hiddenText = await screen.findByText((content, element) => {
const hasTextContent =
element?.innerHTML === props?.items[0]?.text?.value;
return hasTextContent;
});
expect(hiddenText).toBeInTheDocument();
expect(hiddenText).toHaveAttribute("aria-hidden", "true");
await userEvent.click(accordionButton);
// # Compare against textContent stripHTMLTags:
// (similar to https://polvara.me/posts/five-things-you-didnt-know-about-testing-library)
// 👉
// const noTag = stripHTMLTags(props?.items?.[0]?.text?.value as string);
// const [revealedText] = await screen.findAllByText(
// // @ts-ignore
// // eslint-disable-next-line
// (content, element) => element?.textContent === noTag
// // ? console.log('🔥', content) || true : false
// );
// expect(revealedText).toBeInTheDocument();
// console.log('😳', noTag);
// 😳 Proin laoreet mauris vel urna tempor ultricies. Duis rhoncus lorem sed tellus egestas bibendum. In aliquam mauris est, vel condimentum metus aliquet a. Nunc volutpat tincidunt nisl luctus pretium. Duis et ligula semper, sagittis elit non, vestibulum metus. Mauris maximus vitae magna in mattis. Integer interdum maximus felis sed placerat. Nam lobortis tellus non felis fermentum, vitae venenatis ligula congue. Donec sit amet luctus odio. Nam convallis justo vitae magna commodo, sodales convallis ante scelerisque. Etiam ipsum lorem, rhoncus a sapien id, placerat consequat nunc. Curabitur in orci libero. Morbi tincidunt ante vel sem rutrum tempor. Cras ac purus quis urna maximus volutpat.
// # Find by innerHTML:
// 👉
const revealedText = await screen.findByText((content, element) => {
const hasTextContent =
element?.innerHTML === props?.items[0]?.text?.value;
return hasTextContent;
});
expect(revealedText).toBeInTheDocument();
expect(revealedText).toHaveAttribute("aria-hidden", "false");
});
// Overall, probably ultimately more durable / less error prone to use a testid and check aria- attrs
it.skip("renders the correct default style", () => {
const { rerender } = renderWithCTX(<Accordion {...props} />);
const button = screen.getByRole("button", {
name: /accordion trigger one/i,
});
expect(button).toHaveClass(themeMap.default.button);
const altThemeProp = { ...props, theme: "footer" } as const;
rerender(<Accordion {...altThemeProp} />);
expect(button).toHaveClass(themeMap?.footer?.button);
});
});
DNT-2658 Components must receive focus in an order that preserves meaning and operability
Welcome to Duke Energy Enterprise JIRA ~ Please enter a ticket through MyIT if you have any significant problems with the tool. Thank you! Have a great day!
The check mark that indicates a completed step in the form is an <svg> image without a text alternative. Blind and low vision users will not know that this is a completed step.
Recommendation
Use the SVG <title> element to provide a text alternative that's appropriate for the context. To ensure support in assistive technologies, provide role="img" and aria-labelledby attributes in the <svg> element.
SVG with <title> element, role="img", and the aria-labelledby attribute (Simplified code)
Suppose we need to subscribe a scroll event on Count component on its mount and just increment the count on every scroll event.
Code without using throttle or debounce techniques will be like:
Suppose in practical applications you need to use throttle and wait for every 100ms before we execute increaseCount. I have used the lodash throttle function for this example.
Wait, no need to hurry. It will work if you are at /count route. The increaseCount function will be throttled and will increase the count after 100ms of intervals.
But as you move to the / route to render the Home component and unmount the Count component, and start scrolling on home page, you will notice a warning in console which warns about memory leak. This is probably because the scroll event was not cleaned properly.
The reason is _.throttle(increaseCount, 100) is called again during unmount and returns another function which does not match that created during the mount stage.
What if we create a variable and store the throttled instance.
like this
But it has problem too. The throttledCount is created on every render, which is not at all required. This function should be initiated once which is possible inside the useEffect hook. As it will now be computed only once during mount.
Debounce Example using useCallback or useRef
Above example is pretty simple. Let's look at another example where there is an input field and you need to increment the count only after user stops typing for certain time. And there is text which is updated on every keystroke which re renders the component on every input.
Code with debounce:
This will not work. The count will increase for every keystroke. The reason behind is that on every render, a new debouncedCount is created.
We have to store this debounced function such that it is initiated only once like that in useEffect in above example.
Here comes use of useCallback.
useCallback will return a memoized version of the callback that only changes if one of the dependencies has changed - React docs
Replace
with
and it will work. Because this time the function is evaluated only once at the initial phase.
Or we can also use useRef
by doing this
One should always keep in mind that every render call of react functional component will lead to expiration of local variables and re-initiation unless you memoize them using hooks.