- In this section,
we're going to investigate static rendering in Enzyme.
We're going to call the render function
with a component.
And it does static rendering.
So, what that means is it'll render the component
plus sub-components but all you get back is the html.
The components have disappeared from the endproduct.
Okay, so, it'll render a component to static HTML,
basically, what the user will see in the webpage.
So you can check that the HTML content is correct,
and that all the elements can interact
with each other properly.
So, the example I'm going to look at is here,
"Enzyme Static, demo-app."
I created the application using the create react app tool,
same application as before,
but this we're gonna be doing static rendering
in our tests.
So, let's have a thing.
The render function is quite different
from the other two we've seen so far.
When we do shallow rendering, with a shallow function,
it'll give us back a- it'll render a component,
the component is still there,
in the result that we get back,
plus the HTML that it renders.
And it's the same for mount.
When we call the mount function,
the components that we rendered,
like product and product this,
they actually still exist,
in the result that we get back.
But when you call the render function,
the components have disappeared.
They get rendered, and they are not present
in the result document.
All you get back is the actual HTML,
literally, just the raw HTML that's going to be displayed
in the browser.
And, you can use a DOM API, CheerioWrapper,
effectively provides a DOM API,
to allow it to access that document content.
So it has classes such as:
Document, you know, for the document node;
Element; Node, that's useful
for representing text elements
for example, text nodes; and so on.
So, let's have a look, the API is here.
Okay, so, there is a Document class provided,
There's an Element class provided,
And it allows you to kind of navigate the content
of the Element, like get its child nodes.
Very much like low-level DOM programming.
There's a Node class.
The Node class allows you to access you know,
the data value in a text node, for example.
So what you'll find using the Cheerio API,
it is quite simple,
you are accessing the HTML using a primitive DOM API.
So, we're going to see how to do that.
Right, so, the classes are the same as we've seen already.
We've had a product item class, there was an app component,
a ProductList component, a product component,
and a TotalValue component.
I'm gonna test the ProductList component.
First of all, without any products.
So, here we are, ProductList test tsx.
I render the ProductList component
with an empty array of products.
Okay, so, probably worthwhile just reminding ourselves
what we actually expect to get back in that scenario.
So, here's the code.
And if you just drill down into the ProductList component...
Okay, so, we see if an array of product items,
if the array is empty, then the HTML that we get back
should be a div.
It has one h1 with this content:
"No products in stock."
Right, let's have a look.
Let's have a look at my test.
So, having rendered that,
we get back a wrapper, a CheerioWrapper.
When you call the find function,
it'll give you back all elements that match.
There should be one element that matches,
there should should be one h1.
The length of this array should be one.
And then you can use indexing to get the first heading.
Okay, so, find element "0" in my collection of h1's.
You gotta be a bit careful with typescript
because we need to clarify variables in typescript.
It needs to know what types things are.
So, I'm using "any" here.
Basically says to the compiler, "don't worry about that."
Right, so, this will hopefully be a pointer
to an h1 element.
You know, the first h1 in the result.
So, h1 element node should point to the h1.
If you only get the text content of it,
you've gotta get its child.
The element has a child node,
and that child node is a text node,
here, and it's that text node that contains the text.
You know, "no products in stock."
Like that.
So, the child, the first child property will give you
back the text node.
So, the text node is that node, there.
All right, good.
And, then, so, it's a bit more involved.
And, then you say like:
"take that text node,
give me the data inside that text node."
It should be "no products in stock."
Okay, so, there you go.
So, it's very low-level DOM API to access the content.
Obviously, we don't have any products,
and we don't have any TotalValue
because there weren't any products in the collection.
So, you know, these counters, the count of these elements,
should be zero.
Right, that's the first test, and the second test is
where we actually pass in some products,
and see what happens.
Let's take a look at this. This is the second test.
So, "ProductList test tsx."
Here's my sample of products,
you've seen that a few times, now.
Here's my second test function.
Let's take a look what's going on here.
Right, so, render, the ProductList component,
it'll render everything underneath it as well,
passing in that product collection.
Again, it's worthwhile thinking,
"what would you expect to get back in that situation?"
Let's have a look.
So, ProductList, here it is.
When you have, like, proper collection passed in,
it should come into the else part.
And in the else part, it should return a div.
The div should have a heading, three products in stock.
And each product should be rendered
using the product component.
Well, let's have a think about that in a moment.
Let's see how can we check that the content we get back
is correct.
Okay, so, what I've done here
is that I've got a dot dot dot.
Okay, so, in my slide, I've kind of missed out
a bit of the testing.
So, if I go to the actual code, we'll see that
the full test.
Let's do that.
All right, so here we are.
So, I get back the content that has been rendered
in all of its HTML goodie.
Find, the collection of h1 elements,
there should be one h1.
Okay, so give me that first h1,
and a 0.
That's my h1 element node.
And from that h1 element, give me the firstChild,
that's the text element.
Watch the text content of that heading.
It should be "3 products in stock."
Okay, now then.
When you call the render function,
it does render everything underneath the component.
It will render all the child content,
it will render three products.
And it will render a TotalValue.
But what you get back, the result you get back,
doesn't contain the actual component itself.
It just contains the result of rendering that component.
Okay, so, even though the product component was invoked,
it isn't present, it is not present in my result list.
All I've got back is what it actually rendered.
So, have a look at this.
In my test, if I check to see
how many product elements there are,
there aren't any.
Okay, my DOM tree doesn't have a product element.
It has been rendered, it's been rendered as a div.
Okay, so, each product component was rendered,
and I should find there are three div productItems.
Okay?
I should find three of those.
Each product component should have rendered itself as,
when I render the product component,
each product component should render itself as
a div with the csx class of productItem.
So, when you are using, when you call the render function,
you don't have access to the components anymore.
You just see what they rendered at the end of the day.
So, my test- let's check that we do actually have
three of these divs.
Three divs with that csx class. Let's check it.
We got that back.
Let's check that in my rendered HTML,
I have three divs with the csx class of "productItem,"
there should be three of those.
Okay, hopefully that makes sense.
And then if you want to, you can say,
"well, let's see what's inside those elements,
let's have a look at the first productItem."
So, that's what I'm doing here.
Get my collection of div productItems.
There will be three of those,
because of the three products,
let's get the first one, that'll be the first product.
Okay, so, when I get back here,
the first product will be a div
that contains the render details for the first product.
So effectively, it'll be a div
that contains this information here.
And I'm gonna verify that this content is correct.
Okay, so, that product has a child,
the first child of the product,
now you have to be quite careful here.
You have to be, you have to know where you're at so far.
So, at this point in time, what I've just obtained there,
is the div.
Okay, so, I've basically gained access to the div.
Okay, and then I'm gonna check each of its children.
Okay, I'm gonna check that child,
and then that child,
and then that child.
Okay, so, starting at this div,
let's see what it contains.
Okay, so, that's the div.
Child 0, child 0 is going to be the first element here.
Okay, that's child 0. It's the h2.
And that h2 itself has a child with the text.
So, let's have a look at this, then.
Let's just see what's going on.
So, in my div, get the first child.
Okay, and get the text content inside it.
And that's the h2 text content.
The h2 text content should be "Skis."
So, the h2 child content should be "Skis."
Okay.
Then, we'd say, "get child 1,"
let's see what its content is.
Okay, so, let's get on the div, let's get child content 1,
and let's see what its text content is.
Its text content should be "Price: 1000."
So, this should say "Price: 1000."
Good seeing how this is handled together, now.
Finally, we'll get child element 2 from the div.
Now, I'm gonna get child element number two.
Okay, child element 0, child element 1, child element 2,
and let's see what its text content is.
So, this is child element 2.
Its text content should be: "In stock: 5."
Okay, so, that's what we should see here.
In stock, in stock 5.
Obviously, knowing what data I passed in for the product,
I can predict what these strings are actually going to be.
Okay, that's good.
And then finally, don't forget
that at the end of the product,
it also displays the TotalValue.
Remember that? At the end of my product list.
It displays the TotalValue.
This element won't exist, but it will be rendered.
What does it render, and what do we expect?
It should render a div with a csx class,
with a total value of 7000, wasn't it.
Let's check that this div actually exists.
Let's check if I find a div with a total value,
there should be one such element,
one total value at the end of the whole page.
It has a text node,
and the value of that text node should be:
"Total value: 7000."
Okay, so, you have to really understand the DOM,
you have to understand what elements are children
of which elements, and you have to remember as well,
that the text content is also in a separate child.
The text node is one below the element.
Yeah, so it's not difficult, really, it's just, fiddly.
You just have to concentrate.
Now, that's the, that's the summary of what we've just seen.
So, we rendered the product list and all of its content,
and we checked, you know, the headings and so on,
there was no product component in the end result.
Okay, it was rendered, but the product component itself
is not present in the result.
The result of it is, but the product itself isn't there.
Okay, there we are.
And this is the first product,
which I can check the content of, I can say:
"for that product, if I get the first child,
that will be the h2, the text content of that h2 should be:
'skis' and so on, and so on, and so on."
Right, so, you know, quite a lot of code in there,
you have to decide how deep do you want to go
in your testing.
Do you want to check all the content?
Or just part of it?
But, you know, you have access to the whole h2 document,
if you want to.
So, it's just now a matter of running the test
and hoping that it works,
and relax.