Before we start writing our tests,
I want us to make one quick update to our configurations.
Vitest allows us to make use of their functions such as describe,
expect, and it without having to import them ourselves,
every time we need them. Τo do this, we need to enable globals.
We can do so by going to our vitest.config
and setting the flag of globals to true, like this.
Finally, since we were using typescript,
we should let the interpreter know that vitest globals are available.
To do this, we need to go to our tsconfig.vitest.json,
and add an extra type vitest/globals.
Perfect. Now we can go back to our test and delete this import statement.
If I try running them,
you can see they were still passing.
Great. We should be good to make a commit now.
Now, I'm gonna call this commit, use vitest globals.
Now let's start writing our first test.
As we coverage in the first lesson,
a key principle behind test driven development
is the red green refactor development loop.
This means that the very first step
will take to get our worldle game implemented
is to write the first test with our requirements
we want our application to fulfill.
Since we're making a world clone,
I would say that a good first requirement
could be that if a user makes a guess that matches the word of the day,
we should show them a victory message.
Let's do this.
When I'm thinking about a name for a test,
I like to come up with a name that,
even somebody who is a judge developer can understand.
Furthermore, I try to avoid using words like correct and incorrect,
because by themselves, they don't carry a lot of meaning.
I like to explain what it means to be correct in my task name.
For example, in this case over here,
I would say that a reasonable test name could be test a victory message appears
when the user makes a guess that matches the word of the day.
Let's type it out.
Perfect.
To write this test,
we need to first arrange the environment with all the initial conditions
that are needed to put our test in a good stage.
In our case here, we need to prepare a wordle board component
with a given word of the day.
I decided to arbitrarily choose the word of the day to be tests.
Now, what we need to make sure
is that since our user is gonna be making a guess that matches,
when we get to the act phase,
our user is gonna be typing exactly this word.
But great, so this over here is enough to finish our arrange phase.
Now yes, let's move on to the act phase.
In the act phase, we are going to perform the actions
that the user is going to be doing.
That will drive a response from our application.
In this case over here, our player is going to type a guess,
and then they're gonna submit it.
How should they submit their guess?
Maybe pressing on a button?
I'm gonna go with, they can press enter if they type a guess,
as soon as they press enter.
The game is gonna interpret us they are submitting their guess.
So, first, let's identify the input
that the player is gonna be interacting with.
I'm just saying here that I'm finding an input that takes text.
Now we want our player to be typing into that input and to do this,
With vue/test-utils we can use the function such value.
Notice how I'm having our player
type exactly the word of the day as their guests.
Finally, we want our player to press enter,
so that they can submit their guess.
We can do this by using the trigger function from vue/test-utils
And perfect. We have finally finished the act phase of our test.
Now we are ready to perform our assertion.
How should the application respond to this?
As the test name describes?
We expect a victory message to appear.
Let's just hope that a message that says, you won, shows on the screen.
To do this, one thing that we can do is just a assert over all the text
that is being rendered by that component.
We can do it like this.
Now, if we run our tests, we can see that it is immediately failing.
And the reason for the failure is that first,
we were missing a required prop of message.
And also, it could not call the set value function in an empty DOMWrapper.
This means that there was no input of type text
being rendered to the screen.
Let's fix these errors.
If we go to our component,
you can see over here that we do have a prop of message,
that's what came from the boilerplate.
Let's rename this to word of the day.
And also, let's make sure that in app.vue,
we are also using the word of the day prop now,
because we just changed it in our component.
By the way, I tend to prefer to use kebab case for props,
choose whatever you prefer.
It's just a matter of style.
Okay, of course we're still failing
because we still don't have the inputs of type text.
So let's get that rendered to the screen as well.
If I run my test now, I can see that I'm failing for a new reason.
I expected they were the sentence of you want to be rendered to the screen,
but I can only see the word tests.
And that's because we're rendering the prop, right here.
To get it to pass, what is the least amount of work necessary?
We could simply always render the You won message.
That's what the test is looking for, right?
So let's just do this.
If I run my test again, I'm passing.
Now, you must be thinking that we're cheating, right?
After all, the test was asking us to render the victory message.
When the player guesses correctly,
we're just rendering the victory message all the time.
It might look silly,
but this concept of doing the very least amount of work necessary is critical.
And it protects us against two main issues, over abstraction,
which is over complicating things before they even need to be complicated.
And having a test suite that is not robust enough.
And I would say that in our case right now,
we're suffering from the second scenario.
Our test suite is tiny. It's just a single test.
We can refine it more as we're working on this project.
But for the moment, just always rendering the victory message
is good enough.
We are fulfilling the requirements of this task.
Great. Now that the tests are green, let's make a commit.
Whenever I'm having a hard time thinking of what my commit message should be,
I like to look into the name of the task that I just wrote,
because, the core part of the work I've just done,
was to focus on getting these tests to pass, right?
So I was working on the features required
to fulfill the requirements of this task.
So in this case, maybe we could say that render victory message
is a valid description of what we just worked on.
Great. At this point, we have successfully gone through the red,
and the green phase.
Now, we're about to enter the reflector phase.
This is where we can make our code easier to understand and maintain.
There are a couple of tricks that we can use.
There is this amazing workshop from Woody Zuill and Llewellyn Falco,
where they discuss a couple of strategies for refractory.
I've included the link in the description.
But in short, one of the things that they look for, is clutter.
And what is clutter?
Clutter is anything in your code base that is useless.
It's just taken up space.
I would argue, for example, that,
these comments over here that are included
to describe the different test phases, are not useful. So let's delete them.
If I run my task again, you can see that we're still passing.
Great. Let's make a commit, remove clutter.
Another thing that Woody Zuill and Llewellyn Falco suggest looking for,
is reducing complexity.
And there are a couple of things that we can account for
in regards to complexity.
But one of them is magic numbers or magic strings.
I would say that this You won! message would be an example of a magic string.
One of the things that we can do in here is extract a common constant
that is going to be used both by our test and by our water board.
So let's do this.
I'm gonna make a file called settings.
At the base of the project,
And this is going to contain this constant over here that can be recorded.
I also wanna do the same thing for our,
that's not what I want.
I also want to do the same thing for our wordle word.
Let's just in here, render victory message.
And perfect. There we go. So if we run the tests,
we can see there were still passing.
So let's make a commit and call that extract constant.
Amazing. We just finished our first TDD loop.
We wrote a test, we got it to pass,
and then we cleaned up our code a little bit
to increase the maintainability of the code base.
Now, let's start the process all over again.