In our previous lesson, we worked on handling the player inputs,
but we've only been testing our application through feature tests.
Automated tests are a crucial part of having a robust codebase
that is easier to work with,
but they are not a replacement for manual tests,
since there is always a chance that we have overlooked behaviors
while working on our automated tests.
Alright, let's check out our app so far.
And look at this!
We're getting a warning
because we're providing an invalid prop to our worldleboard.
And this is great! We wrote a test for this.
Remember, the word of the day must be a 5 characters long,
real English word with everything in uppercase.
So I'm opening the app.vue
and I'm gonna pass the word-of-the-day of TESTS.
If we save it, run all of our tests again,
we can see that we're still passing,
so I'm just gonna make a commit over here.
And I'll call it, use word of the day that passes validation.
But okay, let's test our app manually now.
If we go back to the browser and we refresh the page,
we can see that that warning is no longer showing up.
I'll also be displaying my keyboard over here
so you can see what I am typing.
Alright, so if I type a lowercase character,
you can see that it immediately becomes uppercase automatically.
And if I type a number, you can see that the number appears.
So this is a bug, but if I type a valid character afterwards,
the number disappears.
So this is great, right?
We discovered a bug in our application.
This is because Vue isn't refreshing the render
until a change is reflected in the guessInProgress.
This is a great opportunity for us to write a regression test
and make sure that this bug that we just identified
and will soon be fixing, won't return to the app in the future.
So I'm gonna go back to our test suite
and create a brand new test.
And for the description of this test,
I'm gonna name something that is describing the bug that I saw,
but explaining the behavior that I want my app to have.
So non-letter characters,
do not render on the screen while being typed.
And how can we demonstrate this bug?
Well, we can do this by mounting our component just fine
and typing a player guess, as we saw before,
that if I start typing numbers and I don't type something that is valid,
the number stays on the screen.
So let's just type numbers in here.
And in this case, what I want to see is a complete empty input.
Let's run our tests. And look at this.
We effectively reproduced the bug that we've witnessed it, manually.
A good way for us to force a re-render in this case
would be to unset the value of guessInProgress
at the start of each update of the formatted guess.
We can achieve this by making the guessInProgress nullable
and then set it to null right at the start.
So let's do this.
So guessInProgress is either a string or null.
And I'll have it start as null.
And now in here, you can see that because of our formatted guessInProgress,
I want it to still be a string.
So I want to make sure that whenever you're trying to get
a formatted guessInProgress,
if the guessInProgress right now is null,
this is going to coalesce into an empty string.
Because over here is the null coalescing operator.
For the case of our setter,
what I want to do at the very start
is set the guessInProgress value to be null.
And then I can calculate the value to be whatever is the processed raw value.
And for the case of the onSubmit function,
I'll just be operating with the formatted guessInProgress.
The guessInProgress is now just an internal ref
for the sake of the formatted guessInProgress.
And that's it.
All right, with these changes, we should be able to run our tests
and see that we're back to a green stage.
And just like that, the bug is gone.
Look at this, I'm trying to type special characters, nothing appears,
I can type regular characters and they do appear right away.
So we fixed the bug. Amazing.
We can no longer type invalid characters at all.
Not only that, but we also have a test suite
that will guard our application from this bug ever returning.
Hello folks, this is a quick update to episode 9
of a Wordle on Test Driven Development with Vue.
During that episode, we wrote a regression task
that proved that at the moment,
a player was being able to type numbers directly into the input box.
And remember, the worlde game does not allow that,
so, we wrote a task that exposed this bug and we made that test pass
by setting the guessInProgress.value to null
and only then, recalculating that.
So, if I run the test over here, you can see that these tests are all passing.
However, it came to our attention that for some people
this test was failing, even after this change.
And what is the cause behind this?
Well, turns out that when we recorded this course
we were using vue version 3.3,
but now the latest version of vue is 3.4.
And since then, vue has changed some things about how computed references work.
So, let me change the version of vue to 3.4 in here,
and if I try running the test once again,
you can all see that this test is failing.
So, if this is happening to you, as well,
this video should help you out.
Alright, so vue is now being more performant
on how it works with computed references.
Setting this value to null, and then assign it to have a new value afterwards,
is no longer enough to trigger a re-render.
If you want to cause this re-render to happen,
what we're gonna have this of, is this global helper function
called triggerRef.
And you can see over here comes straight from the vue package itself,
and what it takes,
is a ref whose tied effects will be executed.
So, in our case, we wanna trigger the side effects
of formattedGuessInProgress.
So, let's just copy it, paste triggerRef,
and if I try running the test once again,
we can see that now all the tests are passing.
I also want to give a huge shoutout to Hank Yang
for providing the suggestion of using triggerRef
and to ViFeng to sharing this issue in our github issues
for the repo of this class.
Thank you so much folks, and I hope this will help you.
Happy coding!
Let's make another commit.
Fix bug that allowed player to type guesses with numbers.
Whenever you write a regression test and implement the fix,
make sure to test your test.
What do I mean by this?
For example, for this test we just wrote,
if we were to go back to our code and delete line 20
and run the test again,
we can see that the test suite is still passing.
Therefore, a developer looking into our code
might think that this line over here is cluttered and can be removed.
But we know that this line
is only optional for the very first interaction of the player,
since the guess in progress starts at null when the component is mounted.
But for every further interactions,
if we don't reset the guess in progress back to null,
the bug that allows invalid characters to appear, will return.
We should, therefore, make this need very clear through our test.
We can prove the necessity of that line by doing one small modification.
Instead of having our player only interact with the component once,
we're going to have them interact with the component two times.
So the player is going to type 12 over here, and then 123 over here,
If I were to run our test right now, we are still passing.
And if another developer thinks that this line is not needed,
and they were to remove this, we can see that now the tests are failing.
So we've made our test more robust
to demonstrate the need for the lines that we're adding here.
So always keep that in mind.
Okay, so we're passing. Let's make another commit.
Make test more robust.
Writing tests is not an exact science,
and we can only strive to be more comfortable with them over time.
A lesson here is to always test your tests
and make sure they are indeed guarding the requirements you're describing.
In this episode, not only we had a great opportunity
to see the value of manual tests,
but we also were able to implement a regression test in practice.
This kind of flow is exactly what we see in our day-to-day as developers.
If we see a bug, instead of just fixing it,
we want to make sure to write a test first that exposes that bug,
and only then we fix it.
This pattern makes our app more robust and reliable,
and will also reduce the odds of this bug returning in the future.
Hopefully, this will be something that we'll all be striving for,
from this point onwards.