- In this section, we are gonna take a closer look
at the query API provided in Testing Library.
So, if you wanna follow along,
there's the folder, TestingLibrary_QueryAPi.
So here it is
in the file explorer.
And if you open that up in the code editor.
So, I've actually just got all the tests
in one file for this section.
I've got about half a dozen tests
that we'll have a look at in there,
looking at various different types of check we can do.
The configuration files are the same as before,
So quickly remind you.
Telling Babel to transpile our JavaScript
into ECMAScript 2015
and configuring Jest.
So it runs in JS do mode.
So we have a document object that we can use in our tests.
And then importing the testing library
plus the Babel libraries as well.
So remember again, if you wanna run these tests
open up a command window or terminal window
and run an npm install
just to download these libraries
before you can run the tests
all the tests are actually in this file.
So let me start explaining what we're going to do.
So, as I've said the Testing Library
favors a user centric approach
to locating content.
So as a programmer, we think about elements having Ids
and CSS classes
and element names,
but the user just sees the webpage
and testing library focuses on
how can we find an element
based on what the user sees in the webpage?
So there are various different ways
of locating content based on their visual appearance.
So you can locate the button
or any element by the text that it displays.
You can locate a text box by its adjacent label.
You can locate an element by the tooltip
that appears when you hover over it.
These are all things that the user experiences
that you can use to locate that content in your webpage.
Find the button that looks like this
so that we can click it.
That's the philosophy for testing library.
So at the moment, we've only been looking at text
we've been using like getByText
and queryByText
and findByText.
But there's a whole suite
of different kinds of way to locate content.
So we have a bunch of functions
that allow us to locate content.
ByRole, Role is an ARIA technique
ARIAs of assistive technology.
For if people with visual impairment
they can have screen readers
which kind of announce the meaning of elements.
When the user tabs into a button, for example, or text box,
the screen reader can read out loud
the some kind of descriptive information.
So each element on the webpage can have an ARIA role
that you can also locate
find the element whose ARIA role is button, for example.
Find ByLabelText.
I'm gonna show an example of each of these functions
over the next five minutes or so.
get a text box
or get an element based on the label that sits next to it.
Input fields, text boxes can have placeholder text.
You know the idea?
A text box appears inside the text box
is like a grade out placeholder text.
Please empty your name here.
Once you tap into the text box
the placeholder text disappears,
but it's like a hint; what you're meant to enter.
You can search for elements with placeholder text.
You can find elements
but the actual text that they display
like the label on a button,
the display value.
Okay. We'll have a look at that.
Alternative text when you have an image.
Images are meant to have an alternative text
in case the browser can't load the image.
It can display the alternative text Instead.
That's something that you can locate.
Find the image whose alternative text is something.
A title means pop up.
So when you hover over an element
it has a pop up title tooltip.
So you can search on that and by its Test Id.
This is kind of like an ultimate fallback.
If there isn't any other way of locating an element
then you can basically give it like a dummy Id
that it can search for in your tests.
So you can use all of these functions in the getByFamily
or the findByFamily
and the all suffix.
So you can say getByRole,
or you can say findByRole
or you could say queryByRole.
You could say, getAllByRole
queryAllByRole
and findAllByRole.
I'm just gonna look at the get family.
It would be exactly the same code if you call query
or find
or getAll,
queryAll
or findAll, okay.
So it's the same basic idea.
So we are just focus on the get functions
because they're the most straightforward.
Right. So getByRole.
That's the first one we're gonna look at.
We're gonna look at all of those in the next few minutes.
getByRole is probably the trickiest one.
It gets a node that matches an ARIA role.
ARIA is the Accessible Rich Internet Application
framework, if you like.
It's a set of adjectives that describe the purpose
of a div in terms of assistive technologies, okay.
So there are a wide range of different roles
or types of element specified by the ARIA standard.
If you click on the link, this is what it looks like.
The accessibility tree basically elements
in ARIA can have a role
and the roles can be things like buttons
or nav bar
or list, Okay.
So if you go here you find all the information you need
about all the different types of role available in ARIA.
It's quite a rich area.
If you've done work with ARIA before,
you know, there's quite a lot of detail.
If you haven't worked with it before
then it'll be quite odd initially
but hopefully it'll become a bit clearer
in the next few minutes.
Some of the roles.
So you can basically have a div, for example
and you can give it the role heading.
You can have text boxes,
they are input fields
but you can also give them the ARIA role of input.
Okay.
Which can be detected more easily
by assistive technologies like screen readers.
So it's an like an extra description.
The purpose of this element is it's an input field
or button
or check box
or table
or row in a table
or a cell in a table.
So there were lots of these,
there's like a couple of dozen
of different roles defined by ARIA.
So have a look at this example
I've got a simple, all of these tests,
by the way, are an example test JS.
So the first test getByRole.
This is my first example.
I've got some simple content that I've loaded
a button with this text here.
You can say, document body is screen, getByRole.
You specify the role that you're looking for
but that's the role, button is like a role.
That's the purpose of an element.
That's the role name.
And then here, you can give it a criteria
to say, actually I'm looking for a button
you specify the name property
and then you give it effectively the text
that you're looking for inside the button, Okay.
So it looks a bit odd.
You probably wanna have a play with this.
What role are we looking for?
That's an ARIA role.
Buttons, implicitly have the button role.
So it's basically say find a button.
The name property here is effectively the label, Okay.
So find the button whose label contains submit in lowercase
that should find this button element
that should give me back appointed to that button.
So that should be truthfully
and the N HTML should be, submit form.
It should have found that element
and it should have matched.
Okay. Here's the next example
getByRole, slightly more interesting.
My document content to have a table.
Tables can have a caption,
like an internal heading,
products table.
Each row here is a separate product
with a description and a price, two rows.
I can say, getByRole table.
That will find a table whose name
now, in this case, when you have a table
the name property is the caption.
So to paraphrase,
look for a table whose caption contains that text, okay?
The user will see products table
displayed on the screen.
Find back, find me a table.
Find me an element whose role is table
and which contains this caption
or partially contains that caption.
That should give me back appointed
this element here should be that table
inside that table, inside that table element
search for element called tr, okay.
There should be two table rows.
The length of that node list should be two.
So getByRole.
I think the key point here is knowing
what roles are available.
It's a very flexible way
of finding particular kinds of content.
The table element in DOM
implicitly has the table role in ARIA.
And the caption is what we're looking for here.
That'll tell you the table.
And then in here you can do any checks you want to
on the content of that table.
Okay. getByLabel text.
This is much more straightforward.
I've got some separate content here.
I've got a label.
When you have a label that relates to a text box
we have a full property which programmatically
would link this label to a text box, whose idea is price.
So this label is for the element whose Id is price.
Okay.
But when you're using Testing Library
it looks at what the user sees
not what's in the programmatic underlyings.
So when we say getByLabel text,
we're looking at the actual text of the label
not what happens to be any Id
because Ids can come and go programmatically
but the appearance here should be stable.
So find an element,
find based on the label price.
This will basically give you back
the corresponding element, Okay.
It'll find that text.
It'll know that this label is for that input field
and it'll give you back the value of that, Okay.
So this will actually give you back the input field
for which that label relates
find the label, and then give me
the input field to which it relates
and give me the value of that input field 300, right.
Have a look at this example
I'm using getByPlaceholder text.
Here's my label.
Here's an input field
with some placeholder text that will appear
inside the text box when it first appears in enterprise.
So, right.
getByPlaceholder text,
this year is the placeholder text of the text box.
So it'll find that text box
because it has that placeholder text.
It'll give me back a pointer to that text box.
What's the value of that text box?
It should be 25.
And it is 25.
Obviously in reality you'd have written some code
to change the value.
This allows you to get the text box
based on its placeholder,
get the text box.
Oh, and get the value of that text box.
Okay. What about this one?
A true statement.
I have a div.
It says whales are going to win the world cup in 2022.
Funny enough, I was just chatting about that.
About 10 minutes ago with my wife.
In Qatar in November, 2022.
If you are watching this video after November, 2022
then you will realize that Whales
did win the world cup in 2022.
That's a div and it's got some text
getByText.
Find a div that contains this text somewhere.
Remember when you have a regular expression
as long as the text contains that somewhere
then it's a match case insensitive.
And remember it's gonna be a single match
when you call a get function.
That will hopefully give me back the div.
And then I can say in that div,
does it somewhere inside that div contain the word whales
in a case insensitive manner?
Well, yes.
This text will have located the element
and the inner HTML contains whales somewhere
in a case insensitive kind of way.
The display value, right.
Well, here's an input field.
Here's the value that's actually currently being displayed.
So you can check for that.
Find the element that contains this display value
the actual text box, the value of it
that's being displayed to the user,
actually inside the text box whales in 2022.
It'll search for a text box
or search for any element that displays 2022.
Hopefully that'll just be a single match.
It gives you back appointed to it.
And it says, okay, so this is appointed to that element.
The whole point is to try to find an element based
on different criteria.
Find the element.
Does the value match this partial regular expression?
Does it contain whales?
This is part of my brainwashing experiment.
So yes it does.
It contains whales.
You get the message by now.
Alternative text,
an image according to the rules of HTML
can have a source attribute
but it's also meant to have alternative text
in case the image can't be loaded
and the browser will display the text instead.
Find the element whose alternative text
is image one, two, three.
So it'll find the image tag
and I can say
what is the source property of that image tag?
It should be image one, two, three .JPEG.
What I'm testing here
is that this alternative image corresponds
to the correct source URL
for the image to be displayed, okay.
Searching for alternative text.
That's the best way to find an image when using document
like testing library.
Title remember is the pop up text.
So here's a div,
I'm sure you're getting the message by now.
That's the popup title and that's the displayed text.
Find an element whose popup title contains 2022.
It'll find me this div
and I can say,
and who are the world cup winners in 2022?
What is the inner HTML command?
It should be Whales.
Right.
Okay. And then Test Id.
Test Id is kind of like an emergency escape route.
Sometimes there are elements
that you just can't get to using these techniques, you know,
it isn't specific, you know,
there isn't any easy way to highlight the single element.
So what you can do
is you can parachute into the element
like a dummy Id, just for testing purposes.
In HTML5, it introduced the concept of data attributes.
This is what a data attribute looks like on an element.
You can have an attribute called data-something
and it's kind of like an extension hook.
You can have any data attributes you like on any element.
It's like extensibility mechanism.
So here, this is what you do.
This is what test in library looks for.
You basically have an element,
an element that you want to locate Test-wise
you give it an artificial Id attribute
called data-TestId
and then you give it some kind of string.
That's again artificial Id
that only makes sense to the test framework.
It won't affect the actual rendered content in any way.
So an artificial Id that I can locate to Test-wise.
So in my code here, I can screen
I can do a check for Test Id.
I'm basically looking for when you say getByTestId,
it is looking for an attribute called data-TestId.
Exactly that.
Based on this check, it's gonna contain 2022.
And who are the winners of the 2022 world cup?
Well, I don't know, could be Whales.
Right. So there we are
lots of different ways of running tests
different lots of different ways of locating content.
So when I run the test, we can get elements by role,
by the ARIA role.
We can get by the label text
that sits next to a text box.
We can get by a placeholder text
that sits inside the text box
and before you start typing
the text that's actually on a button label,
the display value,
the value that's actually currently displayed
inside the text box,
the alternative text for an image
the popup title for any element.
And then finally, if you can't get the element
by any other means, give it an artificial test Id
and that should be your last possible attempt.
I can't find the element uniquely any other way,
give it an artificial test Id
and that will allow you to do it.
Okay. So very flexible way of checking for elements,
located elements, using a wide range of techniques.