﻿1
00:00:04,580 --> 00:00:09,633
Right now, our game is always
displaying the unknown guess feedback.

2
00:00:09,833 --> 00:00:12,033
It is time for us to improve this.

3
00:00:12,400 --> 00:00:17,000
I want the feedback to tell me correct
if the letter exists

4
00:00:17,025 --> 00:00:18,590
and is in the right position,

5
00:00:18,906 --> 00:00:23,100
almost if the letter exists
but is in the wrong position,

6
00:00:23,367 --> 00:00:28,167
and incorrect if the letter does not exist
in the world of the day at all.

7
00:00:28,700 --> 00:00:31,467
I think a great way for us
to test this behavior

8
00:00:31,500 --> 00:00:33,020
is by having a test

9
00:00:33,045 --> 00:00:39,133
in which the word of the day is world
and the player guess is wrong.

10
00:00:39,400 --> 00:00:41,633
Because in this case over here,

11
00:00:41,767 --> 00:00:45,250
all three feedbacks
are going to be necessary.

12
00:00:45,275 --> 00:00:46,533
So take a look at this.

13
00:00:47,259 --> 00:00:51,633
You can see over here that for W,
for example, should be correct

14
00:00:51,700 --> 00:00:55,067
because W exists on both world and wrong.

15
00:00:55,286 --> 00:00:57,423
In the case of R,

16
00:00:58,033 --> 00:01:03,200
the feedback should be almost because
even though it exists on both worlds,

17
00:01:03,600 --> 00:01:08,500
the position is different
with R showing up at position 2

18
00:01:08,733 --> 00:01:12,867
when we consider that our arrays
start counting at 0.

19
00:01:14,417 --> 00:01:18,733
Finally, the letter N does not exist
in the world of the day

20
00:01:18,758 --> 00:01:21,633
and therefore the feedback
should be incorrect.

21
00:01:23,003 --> 00:01:25,733
To get the actual feedback
for each letter,

22
00:01:25,767 --> 00:01:28,570
I've made use of the function findAll

23
00:01:28,595 --> 00:01:33,133
to identify the letter
and then with the .at function,

24
00:01:33,300 --> 00:01:39,600
I targeted a letter at a specific position
and then via the .attributes function,

25
00:01:39,600 --> 00:01:44,233
I could gather what is the value
of the attribute data letter feedback.

26
00:01:46,290 --> 00:01:50,567
If I run all the tests, you can see
that we now have five new tests

27
00:01:50,767 --> 00:01:54,267
considering each kind of feedback.

28
00:01:55,167 --> 00:01:58,200
Since we want to focus
at one thing at a time,

29
00:01:58,225 --> 00:01:59,983
let's skip the tests

30
00:02:00,000 --> 00:02:04,533
in which the expected feedback
is something different from correct.

31
00:02:05,626 --> 00:02:10,567
To do this, we can make use
of the function skipIf.

32
00:02:10,633 --> 00:02:16,233
So I can chain skipIf from the test
and then define the conditional in here.

33
00:02:16,400 --> 00:02:23,233
In this case, I want all the cases
in which expected feedback is not correct.

34
00:02:23,927 --> 00:02:28,900
If I run all my tests now,
you can see that all the other tests

35
00:02:28,925 --> 00:02:31,233
in which the feedback
was different from correct

36
00:02:31,258 --> 00:02:35,417
are being skipped
and we can focus our TTG efforts

37
00:02:35,442 --> 00:02:38,000
into providing the correct feedback.

38
00:02:38,333 --> 00:02:40,267
Okay, so let's focus on that.

39
00:02:40,967 --> 00:02:44,963
To get this test to pass,
the least amount of work we could do

40
00:02:45,033 --> 00:02:49,200
is to simply always return
the feedback of correct

41
00:02:49,225 --> 00:02:52,100
whenever a feedback is requested.

42
00:02:52,400 --> 00:02:57,067
So if you run the tests again,
we can see that we're passing.

43
00:02:57,199 --> 00:02:59,633
Awesome. Let's make a commit.

44
00:03:00,563 --> 00:03:05,600
This could be display feedback
for correct letter guesses.

45
00:03:07,563 --> 00:03:10,633
I don't see anything that I want
to refactor just yet.

46
00:03:10,893 --> 00:03:16,033
So I think we're at a good point
to move on to the next battery of tests.

47
00:03:16,300 --> 00:03:18,527
All right, so we got the correct done.

48
00:03:18,567 --> 00:03:21,633
Now I want to focus
on the incorrect feedback.

49
00:03:22,033 --> 00:03:25,400
So what we're going to skip
are just the tests

50
00:03:25,425 --> 00:03:28,433
in which the feedback is equal to almost.

51
00:03:29,080 --> 00:03:30,667
If we run our tests again,

52
00:03:31,067 --> 00:03:34,933
we can see that our previous correct test
is still running

53
00:03:35,133 --> 00:03:40,500
and now we have two new failing tests
that are related to the incorrect guess.

54
00:03:41,300 --> 00:03:43,400
Okay, so to get this one to pass,

55
00:03:43,467 --> 00:03:47,733
I feel like we need to start to do
some real guess analysis here.

56
00:03:49,000 --> 00:03:54,033
So to begin, this component should know
what is the correct answer.

57
00:03:54,267 --> 00:03:57,042
So instead of just passing
a boolean called shouldFlip,

58
00:03:57,067 --> 00:03:59,433
I want to change this prop to say

59
00:03:59,533 --> 00:04:02,433
it's going to be
an optional prop of answer.

60
00:04:02,740 --> 00:04:05,684
And if an answer
is provided to this component,

61
00:04:05,709 --> 00:04:10,067
it will be giving feedback to the user,
otherwise it will not.

62
00:04:11,320 --> 00:04:13,457
Answer will not have any defaults.

63
00:04:13,482 --> 00:04:17,706
So if you don't provide an answer,
it's just going to be undefined.

64
00:04:19,316 --> 00:04:25,367
We also need to be sure to provide
answer in the WordleBoard.

65
00:04:27,043 --> 00:04:30,800
Snswer in this case
is simply the word of the day.

66
00:04:31,842 --> 00:04:34,668
Great. And we're still
in a failing state, of course,

67
00:04:34,693 --> 00:04:38,933
because we are not providing
the incorrect feedback just yet.

68
00:04:39,426 --> 00:04:41,467
Now we're at a good point to do this.

69
00:04:42,679 --> 00:04:46,603
It's kind of difficult for me
to work in line over here.

70
00:04:46,700 --> 00:04:49,967
So I am going to extract a function
right away in this case.

71
00:04:50,267 --> 00:04:55,033
And let's just say that this function
is going to be called getFeedback.

72
00:04:57,310 --> 00:05:00,300
And in this case,
I'm going to pass the index around,

73
00:05:01,380 --> 00:05:03,410
function getFeedback

74
00:05:05,863 --> 00:05:09,767
and what the feedback represents
is the letter position.

75
00:05:13,583 --> 00:05:17,800
All right. So one thing
that we need to keep in mind

76
00:05:17,825 --> 00:05:21,533
is that answer is something
that might not be provided to us.

77
00:05:21,600 --> 00:05:23,567
So we need to check for that.

78
00:05:25,990 --> 00:05:28,000
If answer is not defined,

79
00:05:30,763 --> 00:05:34,000
I'm just going to be doing
an early return of null.

80
00:05:34,447 --> 00:05:38,400
If the letters match perfectly,
then we return the correct feedback.

81
00:05:38,425 --> 00:05:40,900
Otherwise, we return incorrect.

82
00:05:47,330 --> 00:05:49,767
Letter position is going to be a number.

83
00:05:50,699 --> 00:05:54,367
Perfect. If I run the tests,

84
00:05:55,693 --> 00:05:58,900
we can see
that we are in a green stage now.

85
00:05:59,500 --> 00:06:01,300
All right. Let's make a commit.

86
00:06:01,600 --> 00:06:03,600
And I'm going to call this one

87
00:06:04,233 --> 00:06:08,233
display feedback
for incorrect letter guesses.

88
00:06:09,333 --> 00:06:11,930
For refactoring,
I think it would be nice for us

89
00:06:11,955 --> 00:06:15,590
to provide some type hints
for this function over here.

90
00:06:16,153 --> 00:06:22,367
It can return either null
or one of the feedbacks that we expect.

91
00:06:22,539 --> 00:06:25,567
So let's just add this type hint.

92
00:06:25,733 --> 00:06:29,867
So it's either going to be null
or correct or incorrect.

93
00:06:30,573 --> 00:06:34,333
Or soon enough, we're going
to be implementing this, almost.

94
00:06:35,100 --> 00:06:38,108
If I run the tests,
nothing should have changed.

95
00:06:38,133 --> 00:06:40,467
So we're good to make another commit.

96
00:06:41,543 --> 00:06:42,833
Add type hint.

97
00:06:47,930 --> 00:06:52,867
Okay, we are at a point
where we can finally stop skipping tests.

98
00:06:52,973 --> 00:06:56,133
So I'm just going to delete this skipIf

99
00:06:56,273 --> 00:06:59,473
function call over here
and run the tests again.

100
00:07:00,940 --> 00:07:04,933
Beautiful. We have two new tests
that are failing,

101
00:07:04,967 --> 00:07:08,800
and they're all related
to the almost feedback.

102
00:07:09,800 --> 00:07:14,733
To get this one to pass, we need
to return to our guest view component.

103
00:07:14,833 --> 00:07:18,633
But now we're going to change
our implementation a little bit.

104
00:07:18,973 --> 00:07:21,967
So we're going to do
a guard clause over here

105
00:07:21,992 --> 00:07:24,792
that provides an early return of incorrect

106
00:07:24,886 --> 00:07:29,933
if the letter that the user typed does not
exist in the world of the day at all.

107
00:07:31,870 --> 00:07:35,367
Finally, if we are at line 15,

108
00:07:35,467 --> 00:07:39,967
we know for a fact that the letter
at least exists somewhere in the world.

109
00:07:40,080 --> 00:07:43,967
So if they are not existing
at the exact same position,

110
00:07:44,067 --> 00:07:48,200
then we know
that the feedback should be almost.

111
00:07:49,020 --> 00:07:53,233
If we run our tests,
we can see that we're passing.

112
00:07:53,258 --> 00:07:55,367
All 32 tests are passing now.

113
00:07:56,420 --> 00:07:58,833
Amazing. Let's make another commit.

114
00:08:00,567 --> 00:08:03,367
This time,
I'm going to say display feedback

115
00:08:03,467 --> 00:08:06,400
for almost correct letter guesses.

116
00:08:06,966 --> 00:08:08,327
For refactoring,

117
00:08:08,506 --> 00:08:12,267
I think a good thing that we could do
in here to increase readability

118
00:08:12,367 --> 00:08:17,500
is to extract constants for the letter
the player guessed

119
00:08:17,525 --> 00:08:19,700
and the letter we expect.

120
00:08:21,550 --> 00:08:26,433
So this over here represents
the letter the player has guessed.

121
00:08:28,277 --> 00:08:31,267
So I'm going to extract this
into letterGuessed.

122
00:08:34,360 --> 00:08:39,167
Finally, this one over here
represents the letter expected.

123
00:08:41,500 --> 00:08:44,233
I'm going to move those two constants
next to each other.

124
00:08:48,227 --> 00:08:51,000
And I think that's it.
Let's run the test again.

125
00:08:51,633 --> 00:08:54,067
And we can see that the tests
are still passing.

126
00:08:54,226 --> 00:08:57,917
So I'm going to make another commit
called extract constants.

127
00:08:59,943 --> 00:09:04,733
Before we end this lesson, I want
to add a little bit of additional styling.

128
00:09:04,859 --> 00:09:09,133
So let's just define different colors
for the different feedback.

129
00:09:09,746 --> 00:09:12,930
Like this.
So I already wrote this beforehand.

130
00:09:12,955 --> 00:09:14,423
I'm just going to paste it in here.

131
00:09:14,533 --> 00:09:16,839
And you can see
that based on the feedback,

132
00:09:16,864 --> 00:09:21,567
I'm rendering a different back color
for the letter card.

133
00:09:23,120 --> 00:09:24,740
All right. If we run the test again,

134
00:09:24,767 --> 00:09:27,870
again, the test should not be affected
by our CSS changes.

135
00:09:27,895 --> 00:09:29,167
So they're all passing.

136
00:09:29,367 --> 00:09:31,533
And we're good to make another commit.

137
00:09:32,667 --> 00:09:36,733
Provide dedicated colors
for the different types of feedback.

138
00:09:38,943 --> 00:09:43,600
All right. We've now managed to create
a simple clone of the game wordle

139
00:09:43,625 --> 00:09:46,833
with its requirements protected by tests.

140
00:09:47,220 --> 00:09:50,467
Of course, there are still
a lot of grounds to improve.

141
00:09:50,527 --> 00:09:55,900
After all, the point was not to
perfectly replicate the real wordle game,

142
00:09:55,967 --> 00:10:00,067
but rather to learn test-driven
development while having fun.

143
00:10:01,067 --> 00:10:02,533
We would like to challenge you

144
00:10:02,567 --> 00:10:05,200
to implement
a couple more features on your own.

145
00:10:05,393 --> 00:10:11,233
For example, the game should prevent
players from submitting repeated guesses,

146
00:10:11,413 --> 00:10:14,867
and it should also have
an on-screen keyboard

147
00:10:14,892 --> 00:10:18,300
that shows
which letters have been used so far.

148
00:10:18,900 --> 00:10:21,967
Awesome. And look at this.

149
00:10:22,366 --> 00:10:24,167
In a fraction of a second,

150
00:10:24,192 --> 00:10:26,563
we can run our 32 tests

151
00:10:26,588 --> 00:10:30,567
to ensure the rules of the wordle game
are being respected,

152
00:10:30,600 --> 00:10:34,867
even after refactoring
or adding more functionality to our app.

153
00:10:35,500 --> 00:10:39,833
These tests not only protect
these features from regressions,

154
00:10:40,033 --> 00:10:43,333
but also read-like documentation

155
00:10:43,367 --> 00:10:47,667
to anyone who wants to know
what our app is all about.


