- In this section,
we're going to look at two companion libraries
which accompany and extend testing library.
So remember, testing library has functions
get by, query by, and find by which help you locate content.
We're gonna look at two additional libraries
that build on top of that
to provide some additional useful capabilities for testing.
So, first of all, there's an additional library
on top of testing library,
an additional library called user-event.
A simple API to simulate browser events.
So, you can use the user-event library
to mimic a button click, for example, a text box entry.
And also the second library jest-dom a nice way of writing,
of writing tests to say
having found the element using the testing library.
Now, I want to check some content on the element.
Is it empty?
Does it have a CSS class?
Does it have the input focus?
So, user-event helps you to simulate events
as if the user was interacting with your webpage.
And jest-dom allows you to check, having found the elements
what do those elements contain afterwards?
It makes it easier for you
to check the contents of those elements
after the event has happened.
So, you would typically use
all of these three libraries together.
Testing library to find an element,
user-event to fire an event on the element
and jest-dom to check the content of the element afterwards.
So, we're gonna have a look at an example,
quite a nice example I think.
TestingLibrary_CompanionLibraries.
So, here it is in file Explorer
TestingLibrary_CompanionLibraries.
If you open that up in your code editor,
it looks like this.
So, some configuration files that I'm gonna go through
and one script file and one test file.
Okay?
Quite a realistic example, actually
to round off this lesson.
So first of all,
in terms of libraries that we need to install on our machine
in package.json, we have the babel libraries as before
in order to support ECMAScript modules.
So, we can import an export symbols.
Obviously the testing library
which gives us the ability to call the get by function
find by, query by
plus the testing library also has user-event
for emulating user interactions
and jest-dom to check the content developments afterwards.
So, as you can see user-event and jest-dom
are layers on top of the basic testing library
that we've seen already.
So, those are the dependencies you need.
In my package.json file here,
you can see I've specified those dependencies.
You would need to install these dependencies
on your machine.
So, npm install or yarn install.
I've already done that on my demo folder.
So, you would need to do that as well
just to download those libraries into node models,
so, we can actually run the tests.
The other configuration is the same as we've been looking at
for the last few sections.
So, we also have jest config which says, yes we run in,
you know, client side mode as opposed to server side mode.
Plus the babel configuration that will convert our code
into ECMAScript 2015,
the lowest common denominator for JavaScript.
Right, so, now we're gonna have a look at the code
that's under test, under test that will actually execute it.
So, this is the basic idea,
the user-event library, you import the user-event function
from the user-event library.
And then you can say user-event click
or user-event change or user-event double click.
So, the user-event has various different functions
to, you know, basically indicate
what event you wanna emulate and upon which element.
Okay?
So, this will call in the user-event click
will simulate the click event occurring on this button.
So, there were whole set of different functions
you can call here, dot click, double click,
change, select whatever.
Those, the function names basically correspond
to JavaScript event names.
And then you just say
upon which element do we simulate that event occurring on?
Right, so we can then use jest-dom
to check the content of like, of an element.
So, we found an element,
we simulated some user interaction on the element
like a click or whatever.
Now, after that, we can say right upon this element
we can use these are the, jest-dom matches basically
which are kind of related to HTML dom related tasks.
Is my text box enabled or disabled?
That's clearly some kind of graphical user interface
feature.
So this, these functions here are provided by
by jest-dom to check the content of elements
in an HTML kind of way, is my element enabled or disabled?
Is the text box valid or invalid?
You know, a text boxes can have like properties
like minimum value, maximum value.
You can use these functions
to check whether the content is valid
according to its constraints.
You can check whether some parent element
contains a child element
or whether an element contains some HTML.
You know, it doesn't contain this text value, for example.
So, it enables you to
against an element to write higher level tests
based on HTML semantics.
Right.
Have a look here
for the full range of functions available, okay?
I'm not gonna attempt to be comprehensive
because there are lots of different types
of check you can make, as you can imagine.
So, if you look here,
it'll tell you about all these different functions
that you can call to make your tests more expressive.
So, an example then we are gonna have a look at the
myscript.js the code and example.test.js to test it.
So, first of all then let's look at my.script.js,
the idea, what I'll probably do first of all
is I'll show you the test code.
So, you can kind of imagine where this is going.
So, let me just explain a few things.
First of all, we are gonna be calling those functions
and using those objects from the testing library.
Okay?
And I've imported the user-event
there.
And basically the user-event
and I've imported all the functions from the from jest-dom.
Okay.
I've got a function called addProduct
which I'm gonna show you in a moment.
But before we do that I just wanted to show you
this is the HTML content that my code will run against.
We've seen something similar to this before.
So, my addProduct function which I'm gonna be testing
is gonna be interacting with this content.
This is the HTML content that I've provided.
So, it's a simple product webpage,
the user, there's a text box
where the user can enter a description of a product.
So, the important point to notice that this text box
has a label associated with it.
And that label says description;
Okay.
So, I'm gonna use in my code, I'm going to use this label
to find that text box
and, you know, to get simulate user input
into that text box.
And likewise, I've got another label here, price;
which will give me access to this text box
and a button that I'm gonna simulate a button click on
using the user-event.
And I've got a table here.
The table is gonna display all products.
The idea is while you can imagine
when the user clicks add product
what the code will do is get the value of the description,
skis,
get the value of the price, 800
and add another row into this table.
The caption will enable me to locate that table
using my testing library.
So, that's the HTML.
Here, I'm getting a handle onto the button, okay.
So, this is using testing library
effectively in my document body.
Find the element that has the role of button, okay.
So, that would be a button then.
Oh, specifically a button that has this text add product.
So this, this here will give me back a reference
to this button object in the dom tree.
And I wanna basically hook up an event.
You hook up the events as before on that button,
if it's clicked then call the add product function.
All right.
The add product function is what we're trying to test
from our script.
So, we need to look at that next.
Let's have look at the, in myscript,
let's have a look at the add product function.
This is gonna be called when the user clicks the button
and I've got some comments here that explain
what's going on.
Let me just quickly run through,
first of all I'm trying to add a new row into the table.
So, it'll have two columns.
This first paragraph of code is gonna create
a table data cell with a CSS class.
The description entered by the user in the text box.
Okay, so create a new element, add a CSS class
this is how you can add CSS classes to an element, okay.
So, it knows that it's the description data cell.
Oh, get the value from the text box.
This is my real code now,
you don't use the, jest-dom API in your code,
you just use it in your test.
This is my regular JavaScript code
whereby I get the text box called description,
get the value from it
And that becomes the value of my TD, okay?
So effectively, it'll, it'll create an element called the TD
with the CSS class of description
and the inner HTML of that element
will be whatever the user typed in
to the description text box.
I do then the same for the second table cell.
I create another table cell.
It'll have a different CSS class.
It'll have a class of price.
We'll get the value of the price text box from the webpage
whatever value the users entered in there
assign that into my new TD.
So, my new TD will have a CSS class of price
and it will have the value
whatever the user typed into the text box.
Okay then, so I'll have created a TD with a description
and I'll have, I'll have created a TD with a price.
I don't need to, need to add those into a table row.
Let's create a table row
and let's append both of those table cells.
And then finally take that table row
and add it into my products table.
My products table had an ID of products
grab that table and at the bottom of that table
as its final child add that table row,
the table should now have another row,
if this has worked correctly
I'm gonna test this in a minute.
Oh, and then after we've done that
empty the two text boxes
and put the input focus back into the description text box,
ready for the user to type in another product.
So, that should actually be quite a nice user interface.
Let's test the code here.
So, in my test, from the top,
use the screen and get by role from testing library
to find elements,
use user-event to simulate the button click
and use the jest-dom to check the content developments
after the click.
Import the function we just looked at.
Right then, let's set up the HTML.
We could have loaded this from an actual file
but that's just a hard coded for simplicity.
Remember screen, remember screen?
Screen basically is document body.
So, somewhere in this document body
find by role a button called add product.
And when you found that button
if it's clicked call the add product function,
the one that we just looked at.
Right let's test that function.
Let's test the add product function.
So, I'm gonna mimic user input.
So, let's have a look at this, first of all.
I'm gonna mimic the user entering two texts.
So, get by label text.
Remember, and that's using the testing library.
Remember the first text box,
the first text box was accompanied by a label description.
So, basically find the text box accompanied by that label.
This will gimme back a pointer to the text box
not the label, but the text box that it's for.
Okay, right from that description text box.
Oh, also by the way, get the text box
whose label is price
that'll gimme this text box here.
And then in the first text box,
imagine the user entered skis.
And in the second text box set the value to 800.
So, that's simulating or mimicking user input.
And then to mimic a button click,
find the button called add product
and then using the user-event,
simulate a click event on that button, like so.
So, you'll say user-event,
the name of the event you wanna generate
and then the target element
upon as if the user had clicked that button.
Well, when the user click that button
it should call add product.
So, immediately we can now check.
What's the content of my webpage
after that function's been called, right?
Well, let's get the products table
get the table whose name is product.
Remember get by role that will find the table
with a caption of products.
Okay, so get the table whose caption is products.
Okay.
Inside that table, if you want to find rows in the table,
you can say, get by row, okay?
Get all rows.
You don't say TR, you just say row.
Each TR element has an area role of row.
So, this would give me back a node list
that contains all the rows in the table
and there should just be one row.
Initially my table had no rows after clicking the button.
My table should now have one row.
Does it have one row?
Hopefully, yes.
Okay, so in that row, there should be two cells.
Again, you can say, get by row in the row that we have
get all elements that have the cell role.
A TD element has a cell role.
So, this would be back the two table columns inside my row.
There should be two columns in my row.
Let's check the content of the first column.
It says in TD zero,
this is using jest-dom.
I'm checking that the element
has a CSS class of description.
And I'm checking that it has text content of skis.
So, this is the jest-dom API.
It enables us to check elements in an HTML sensitive way.
What about the second column in my table row?
The second column should have a CSS class of price
and it should have text content of 800.
So, we can use the user library to simulate events.
We can use the, jest-dom library to check the content
in a dom kind of way afterwards, like so,
or we can go further as well, just to finish off.
We can say the input description
that's the text box should no have the value.
It should be empty.
Remember at the end of my add product
it set the text boxes to be clear.
Let's check that my input description is empty
and so is my price.
And also let's check that the text box for description
has the input focus.
We put the input focus back into the first text box.
Let's make sure that it worked.
So, these functions are semantically rich.
They enable to you to write tests that are,
you know, quite expressive and quite concise
in a way that would be difficult to do otherwise.
So, I guess all we need to do now
is to actually run the test.
I've opened up a command prompt window here,
testinglibrary_companionlibraries.
I've already done an npm install.
Okay.
So, you would need to do that first
and then we can just run the tests.
So, it'll load that content,
simulate the user clicking the button.
It'll run my code to add a product,
afterwards I can check that my product has a new,
my product table has a new row
with two columns description and price
and that the text boxes were emptied
and the focus we set afterwards
and it's all worked beautifully.
So, I would hardly recommend
using these libraries for testing web pages,
testing library to locate content,
user-event to simulate events on those elements
and then jest-dom to make it easier
to check the contents of those elements afterwards.