Right now, our game is always displaying the unknown guess feedback.
It is time for us to improve this.
I want the feedback to tell me correct if the letter exists
and is in the right position,
almost if the letter exists but is in the wrong position,
and incorrect if the letter does not exist in the world of the day at all.
I think a great way for us to test this behavior
is by having a test
in which the word of the day is world and the player guess is wrong.
Because in this case over here,
all three feedbacks are going to be necessary.
So take a look at this.
You can see over here that for W, for example, should be correct
because W exists on both world and wrong.
In the case of R,
the feedback should be almost because even though it exists on both worlds,
the position is different with R showing up at position 2
when we consider that our arrays start counting at 0.
Finally, the letter N does not exist in the world of the day
and therefore the feedback should be incorrect.
To get the actual feedback for each letter,
I've made use of the function findAll
to identify the letter and then with the .at function,
I targeted a letter at a specific position and then via the .attributes function,
I could gather what is the value of the attribute data letter feedback.
If I run all the tests, you can see that we now have five new tests
considering each kind of feedback.
Since we want to focus at one thing at a time,
let's skip the tests
in which the expected feedback is something different from correct.
To do this, we can make use of the function skipIf.
So I can chain skipIf from the test and then define the conditional in here.
In this case, I want all the cases in which expected feedback is not correct.
If I run all my tests now, you can see that all the other tests
in which the feedback was different from correct
are being skipped and we can focus our TTG efforts
into providing the correct feedback.
Okay, so let's focus on that.
To get this test to pass, the least amount of work we could do
is to simply always return the feedback of correct
whenever a feedback is requested.
So if you run the tests again, we can see that we're passing.
Awesome. Let's make a commit.
This could be display feedback for correct letter guesses.
I don't see anything that I want to refactor just yet.
So I think we're at a good point to move on to the next battery of tests.
All right, so we got the correct done.
Now I want to focus on the incorrect feedback.
So what we're going to skip are just the tests
in which the feedback is equal to almost.
If we run our tests again,
we can see that our previous correct test is still running
and now we have two new failing tests that are related to the incorrect guess.
Okay, so to get this one to pass,
I feel like we need to start to do some real guess analysis here.
So to begin, this component should know what is the correct answer.
So instead of just passing a boolean called shouldFlip,
I want to change this prop to say
it's going to be an optional prop of answer.
And if an answer is provided to this component,
it will be giving feedback to the user, otherwise it will not.
Answer will not have any defaults.
So if you don't provide an answer, it's just going to be undefined.
We also need to be sure to provide answer in the WordleBoard.
Snswer in this case is simply the word of the day.
Great. And we're still in a failing state, of course,
because we are not providing the incorrect feedback just yet.
Now we're at a good point to do this.
It's kind of difficult for me to work in line over here.
So I am going to extract a function right away in this case.
And let's just say that this function is going to be called getFeedback.
And in this case, I'm going to pass the index around,
function getFeedback
and what the feedback represents is the letter position.
All right. So one thing that we need to keep in mind
is that answer is something that might not be provided to us.
So we need to check for that.
If answer is not defined,
I'm just going to be doing an early return of null.
If the letters match perfectly, then we return the correct feedback.
Otherwise, we return incorrect.
Letter position is going to be a number.
Perfect. If I run the tests,
we can see that we are in a green stage now.
All right. Let's make a commit.
And I'm going to call this one
display feedback for incorrect letter guesses.
For refactoring, I think it would be nice for us
to provide some type hints for this function over here.
It can return either null or one of the feedbacks that we expect.
So let's just add this type hint.
So it's either going to be null or correct or incorrect.
Or soon enough, we're going to be implementing this, almost.
If I run the tests, nothing should have changed.
So we're good to make another commit.
Add type hint.
Okay, we are at a point where we can finally stop skipping tests.
So I'm just going to delete this skipIf
function call over here and run the tests again.
Beautiful. We have two new tests that are failing,
and they're all related to the almost feedback.
To get this one to pass, we need to return to our guest view component.
But now we're going to change our implementation a little bit.
So we're going to do a guard clause over here
that provides an early return of incorrect
if the letter that the user typed does not exist in the world of the day at all.
Finally, if we are at line 15,
we know for a fact that the letter at least exists somewhere in the world.
So if they are not existing at the exact same position,
then we know that the feedback should be almost.
If we run our tests, we can see that we're passing.
All 32 tests are passing now.
Amazing. Let's make another commit.
This time, I'm going to say display feedback
for almost correct letter guesses.
For refactoring,
I think a good thing that we could do in here to increase readability
is to extract constants for the letter the player guessed
and the letter we expect.
So this over here represents the letter the player has guessed.
So I'm going to extract this into letterGuessed.
Finally, this one over here represents the letter expected.
I'm going to move those two constants next to each other.
And I think that's it. Let's run the test again.
And we can see that the tests are still passing.
So I'm going to make another commit called extract constants.
Before we end this lesson, I want to add a little bit of additional styling.
So let's just define different colors for the different feedback.
Like this. So I already wrote this beforehand.
I'm just going to paste it in here.
And you can see that based on the feedback,
I'm rendering a different back color for the letter card.
All right. If we run the test again,
again, the test should not be affected by our CSS changes.
So they're all passing.
And we're good to make another commit.
Provide dedicated colors for the different types of feedback.
All right. We've now managed to create a simple clone of the game wordle
with its requirements protected by tests.
Of course, there are still a lot of grounds to improve.
After all, the point was not to perfectly replicate the real wordle game,
but rather to learn test-driven development while having fun.
We would like to challenge you
to implement a couple more features on your own.
For example, the game should prevent players from submitting repeated guesses,
and it should also have an on-screen keyboard
that shows which letters have been used so far.
Awesome. And look at this.
In a fraction of a second,
we can run our 32 tests
to ensure the rules of the wordle game are being respected,
even after refactoring or adding more functionality to our app.
These tests not only protect these features from regressions,
but also read-like documentation
to anyone who wants to know what our app is all about.