- The testing library is quite flexible
and it contains lots of different ways
in which you can search for content.
In fact, there are three categories of functions
that you can use to locate content using testing library.
The first category, there's a bunch of functions
called get by something.
Get by text, for example.
The get by functions, they look for a single match.
If it finds no matches, or if it finds multiple matches,
it'll give you back an error.
So get by only works with a single result.
Query by is a little bit more flexible.
It'll return one matching node, if it finds it,
or null if it doesn't find anything,
But again, it returns an error,
it throws an error if there are many matches.
The third category is a bit different.
There are find by functions, like find by text.
This function or this group of functions returns a promise.
That promise resolves successfully
if it finds one match and it rejects
if it finds either zero or many matches.
So each of these functions are geared up
to find one match, ideally.
If you wanna find multiple matches,
then there are similar functions called get by...
Get all by, query all by and find all by.
Okay? The same functions,
but instead of just finding one node,
they find all matching nodes.
Okay, so we have these three categories of functions,
get by, find by, and query by.
In each of those functions, you've gotta specify
the text that you're looking for.
And it turns out there are three different ways
to specify the text.
So you have a lot of flexibility here.
Three different groups of functions and for each function,
three different ways to specify the text.
So you can say I'm looking for an element
whose text is exactly this string
or you can specify a regular expression
or you can specify a callback function
where you've got some kind of complicated algorithm
to figure out what elements you're looking for.
So when you call any other functions,
you can say find a node that matches this string
or this regular expression or call this callback function.
And if that callback function returns true,
that's the element I'm looking for.
I'm gonna show you an example of all of this
in the next few minutes.
So go into this demo folder.
Testing library, types of query.
Here it is.
If you open that up in your code editor, it looks like this.
So bit of housekeeping, first of all.
We have the usual configuration.
We've seen this at few times now, Babel config.
It tells Babel to transpile my code to ECMAScript 15, 2015.
We have jest config that makes sure
that jest runs in jsdom mode,
so it creates a document object
for our webpage to access.
And then package json enable the Babel transpilation
and also to import the testing library, if you remember.
So remember again that if you want to run these examples,
you have to install these packages,
open up a command prompt window, NPM install.
It'll load these libraries into your local folder
and then you're ready to go.
So what we're gonna do over the next few minutes
is I'm gonna show you examples
of using the get by functions,
the query by functions and the find by functions.
Okay, just to give you a good example of each one of those.
Okay, so we're gonna look at one test file
that illustrates the get by family.
And then the second test file illustrates the query by,
where you may get back a result or no results.
And then the find by functions where you have a callback.
I'm just going to be using the single checks
in each of these examples.
It would be, you know, the same idea
if you use the get all for example.
Okay, so you can extrapolate the concept I'm sure.
Right, so this is the first example using the get by tests.
Okay, so using the get by tests,
I've got some code that runs before each tests
and then I've got three different tests to illustrate
the three different ways of doing text matching.
Right, oh, actually one other thing I need to say,
a bit of housekeeping.
Remember the screen object provided by testing library?
Basically that's the document body.
And then before each test,
I load my document body with some simple HTML.
And again, obviously I could have loaded this in
from an actual HTML document.
The principle would be the same.
So we're gonna use the screen function, screen get by,
and we're gonna give it three different types of check.
To get by text, to get by regular expression,
and to get via some kind of callback.
Great. Okay, so first things first, then.
At the top there, load some basic content into my document,
which I can then test against.
Okay, then in this first test,
get an element via a string text match.
So you call screen get by text.
So basically document dot body.
In my document body, get by text.
This will only match, or this must match a single element.
If there were multiple matches or no matches,
this would throw an error.
So in my document, hopefully, there was one element
whose text is hello,
and hopefully I'll get back a pointer to it.
This is going to be a pointer to the element with hello.
So when I get the text here,
it should correct match correctly.
Here, I'm using a regular expression, okay?
Search for, again, screen, get by text,
but I'm specifying a regular expression.
Remember the i means case insensitive.
I'm looking for a case insensitive text match.
The letter h dot means any character.
So h, any character, any character, any character, o.
Find one element whose text matches that pattern.
Okay, well that will match.
And the inner HTML that we find,
basically it finds that element
and the inner HTML of that element should be hello.
And it is.
Okay.
The third check is when you say,
when you parse in a callback function, okay?
So here's my callback function.
This is the element that it would've checked against.
Okay, so e
is basically the element that it's trying to check against.
C is the content of it, okay?
So e will be this element.
If the element's tag name in lowercase is div
and the content length is five
that's the element I'm looking for.
Remember, whenever you call the get functions,
they have to return a single match.
So hopefully there will be a single element
in my document whose content length is five
and whose name of the element is div.
It'll search for an element that has that characteristic.
And if there's one element,
it'll return me back a reference to it.
And there is, it returns back a reference
to this element here.
So this kind of callback mechanism is quite useful
when you've got a complicated check that you want to do.
You're not just checking something simple,
like the actual text,
but it's something a bit more involved.
You can have a callback function
and effectively what will happen
is the get by text function will call this arrow function
on each element to check if it matches
and hopefully we'll get a single match back
whose inner HTML is correct.
Okay, so if I run that test,
you can run it yourself and it'll work.
Okay, so that was the get by,
where you wanna get back definitely one match.
Next up, we're going to look at the query by functions.
Similar idea, the same kind of text check in,
but it allows you to maybe have a match
or maybe not have a match.
Okay, so query an element with a successful match.
Here's my HTML that I've loaded.
- Query by text.
I'm saying hopefully I'll find either zero
or one element that matches this.
Find an element
whose text matches
h, something, something, something, o.
Obviously, it's going to be that element.
It'll gimme back the element.
Okay, it's not null, because it should exist.
And it says, yeah, there it is.
Now, what about this one?
Query by text is allowed to return null.
If I give it some check, some test here
that clearly isn't located in my document,
getting back null is allowable for query by text.
If you say get by, it would throw an error,
but with query by, it's when you are trying to assure it.
Does it exist or doesn't it?
I'm checking that this should gimme back null, okay,
because there is no such element in the document.
That's the query by function.
The third in the trilogy...
Oh, let me just run that test first.
It would, great.
The third approach is when you call, find by.
Remember, get by is one match,
query by is one or zero matches,
and find by, it basically returns a promise,
and that promise will either resolve if it matches,
or it'll reject if it doesn't.
So let's have a look at this example.
Again, I've loaded the same content initially.
Screen find by, I give it the text that I'm trying to find,
and the find by function returns a promise
and if that promise succeeds, it'll call the then handler.
Okay, so remember with promises,
a promise basically resolves successfully, or it rejects.
If it resolves successfully, then upon your promise object,
this then returns a promise,
upon your promise, it'll call the then callback.
So I'm expecting it that it should
call that, it should find it.
And in here I say, I'm expecting the HTML to be hello.
Whenever you've got a callback,
you've gotta call the done function.
We've seen this a few times before,
to say it basically tells jest
when is my callback completed?
Now it's complete.
It found hello.
Yes, it did. Resolves.
I can check that the content really is correct.
And then I can say to jest that this test is now done.
It can now go onto the next test.
So when you call find by text, if it finds it,
it'll resolve and it'll call your then callback.
If it fails, it'll call your catch callback.
So in this case, I'm expecting it to fail.
Find this text.
I'm hoping it fails.
If it fails, it'll reject.
In other words, it'll call my catch handler.
Verify that it called the catch handler.
I can check the kind of error that occurred.
Okay, so this thing here that I've caught,
is it an error object?
Yes or no.
So did it basically resolve--
Sorry, did it reject with an error,
in which case we're done?
So don't really feel any particular
pressing need to use find by.
Having to have a promise object here is kind of handy
if you've got some kind of asynchronous check going on,
but in general, it'd probably be the case that
find by is a little bit over the top.
Get by and query by are probably gonna be sufficient
in most cases, but you never know.
It is there in case you need it.
So to run that test, run that test and it works.
So to summarize,
we have three different ways of doing a check.
We can call the get by functions,
which must return one match,
otherwise it raises an error.
There's the get by text using screen.
And there's the get by text using the callback, okay?
And then we had the find by functions.
Let's look at query second.
The query functions that return either the element,
if it finds it, or null if it doesn't find it.
And then the third family functions, the find by functions,
where you tell it what you're looking for.
It'll resolve if it finds it,
and it'll call you a then handler.
It'll reject and call you a catch handler if it doesn't.