I think a good thing we could enforce next
is that a defeat message appears if the user makes an incorrect guess.
I realize wordle allows you to make multiple mistakes,
but I want to keep things simple for now.
Let's just say that in our worldle game,
if you make a correct guess, you win the game.
If as soon as you make your first incorrect guess, you lose the game.
Most test frameworks allow you to write placeholder tests
where we can just type down ideas for the future.
Vitest is not an exception to that.
We can write placeholder test in vitest, by adding the word todo after the test.
In this case, let's just write two difference todo tests here.
One that says a defeat message appears
if the user makes a guess that is incorrect.
Another one that says that no range of game message appears
if the user has not yet made a guess.
Great. Do you wanna try writing this test down yourself?
Post this video and try it out?
Okay. Let's write the implementation of our first todo.
I think a lot of the heavy lifting for this task
can be copied over from the previous test that we have.
All we want to change in here
is that instead of making a guess that matches the word of the day,
let's make a guess that doesn't.
Finally, for our search phase,
I want to assert that we see a defeat message.
Let's go with better luck next time.
If we run our tests,
we can see that we are passing on the first test,
but in this new one, we are failing.
We expected to see better luck next time.
But we saw You won!,
by the way, as a rule of thumb,
always run the entire test switch.
Even if you think exactly which tests are being affected,
by the work that you are doing,
running the entire test switch will protect you against regressions.
To get this test to pass.
We can do the same approach that we've done for the victory message.
Let's just go to our wordle board and always render the defeat message.
So if we run our tests, we can see that we're back to the green stage.
Let's make a commit.
Display defeat message.
Now, as you are probably expecting, we are back to the refactor phase.
I think that just like how we've done with the victory message,
we can reduce complexity here
by extracting another constant that will contain our defeat message.
We can also do the same thing for our test.
If we run our test, still passing.
Let's make a commit, extract constant.
Another extraction we can do is for the word of the day.
So let's do that.
Whenever you have a key equals to the value in an object,
you can just simplify it, just having the key.
Perfect. If we run our tests or is still passing, that's great.
So let's make a commit and call this extract variable.
Okay, now, we're ready to implement the body of our next todo test.
Once again, let's make use of our existing tests as a reference.
So, I'm going to copy the previous test.
And in this case, we're not doing any user input.
And we are hoping that we're not going to see
neither the victory message
nor the defeat message.
And we are back to the red stage
because we're seeing those two messages all the time.
To get this test to pass, we'll have to do a couple of things.
We have to keep track of the guess that the user is about to submit.
And once the user submits their guess,
we will compare it. with the word of the day.
If they match, we show the victory message.
If they don't, we show the defeat message
to keep track of the guess that the user is typing.
We can make use of a ref.
So the guessing progress can be tracked via this ref.
The submission happens when the user presses the enter key.
Let's have another ref over here for the guess submitted.
And when enter is pressed,
the guess meters receives the value of the guess in progress.
Perfect. Now regards to showing the messages,
we can check to see if the guess submitted
is equal to word of the day, then we show victory message.
Otherwise, we show the defeat message.
Now, this is not gonna be enough.
If we run our tests, we can see that we are still failing,
because even though we didn't submit any guesses,
so we are already showing the defeat message to the user.
This is because an empty string
is going to be different from the word of the day.
That was tests.
We're gonna have to add an additional check in here
that we only render the message
if a guess has a length greater than zero.
if you run this, now we're in a green stage.
Perfect. Let's make a commit.
Only render end-of-game feedback
after the game is over.
Reducing duplication is one key focus of the refractory phase.
And we can reduce duplication in our test suite.
Notice that every test we have,
it starts with exactly the same arrange phase.
Let's extract this common logic into a hook that runs before each test.
This can be done in vitest
by writing a function called beforeEach.
Whatever we write in this function,
it is guaranteed to run before every single test in this group.
Now notice that I've made wrapper be a variable
that is in the context of this describe group.
You might notice that our typescript configuration
doesn't like the fact that we're using an implicit type of any to our wrapper
because I'm not defining the type right now.
But if we go to the definition of the mount function,
we can see that the return type can be pretty daunting.
Here's a little typescript hint
that might help you a lot when working with complex types.
Since we know our wrapper is always going to be containing
whatever mount is returning,
we can leverage a utility type that typescript makes available for us
specifically for this kind of scenario.
We can type each wrapper as the return type
of the mount function.
And there you go. Just like that.
Our wrapper is explicitly typed now to whatever the mount function returns.
If we run all of our tests, we can see that they are passing.
Alright, now let's make a commit.
Extract arrange phase to beforeEach.
Another chunk of code that is being repeated multiple times
is the act of having the player type and submit their guess.
Let's extract this into a custom helper message.
And in this case, I'm gonna call this playerSubmitGuess.
This function, I'm gonna have the guess that the players are meeting
right here.
And in this case, we're passing the word of the day.
In this other case, over here, we're passing the word WRONG.
If we run our task,
we are still passing.
This refractory technique over here
that i've just done is called extract method,
so, because our tests are passing.
I'm gonna make another commit and say, extract method.
Great. We've learned different ways.
We can refactor our codebase to make it easier to work with,
with by extracting constants and methods.
We also learned how we can leverage beauty and hooks of vitest,
to handle common parts of our arranged phase.