﻿1
00:00:04,626 --> 00:00:11,267
So far, our game has been contained
within this single wordleboard component.

2
00:00:11,479 --> 00:00:15,433
It's been working great,
but since our application started growing,

3
00:00:15,653 --> 00:00:18,233
this component grew with it.

4
00:00:18,733 --> 00:00:21,933
This component is currently
responsible for two things,

5
00:00:22,453 --> 00:00:27,700
rendering the feedback
and gathering user input.

6
00:00:28,733 --> 00:00:30,776
This can be a good time for us

7
00:00:30,801 --> 00:00:35,000
to extract one of these concerns
into a dedicated component.

8
00:00:36,306 --> 00:00:39,175
Notice that we did not start this project

9
00:00:39,200 --> 00:00:41,033
by already predetermining

10
00:00:41,058 --> 00:00:44,767
which vue components our application
is going to need.

11
00:00:45,220 --> 00:00:49,367
Instead, we have opted
to wait for these components

12
00:00:49,400 --> 00:00:53,167
to naturally appear
as the application evolves.

13
00:00:54,563 --> 00:00:58,600
Okay, let's move everything related
to gathering user input

14
00:00:58,633 --> 00:01:01,867
into a dedicated guess input component.

15
00:01:02,413 --> 00:01:04,680
Since most of this logic over here

16
00:01:04,705 --> 00:01:07,067
is going to be related
to gathering the guess input,

17
00:01:07,100 --> 00:01:11,867
I think we should be able
to duplicate this wordleboard

18
00:01:12,140 --> 00:01:14,137
into a guess input component

19
00:01:14,162 --> 00:01:18,100
and then delete anything
that is related to just rendering guess.

20
00:01:19,210 --> 00:01:26,470
So this part over here
does not belong to the guess input.

21
00:01:28,670 --> 00:01:32,342
We also don't need to receive
the word of the day.

22
00:01:34,463 --> 00:01:37,722
And we don't need to keep track
of the guess submitted.

23
00:01:37,800 --> 00:01:42,467
What we are going to do
is communicate with the parent

24
00:01:42,653 --> 00:01:46,333
whenever the user truly submits a guess.

25
00:01:47,199 --> 00:01:51,500
The most common way a child component
communicates with a parent

26
00:01:51,525 --> 00:01:54,133
is via emitting events.

27
00:01:54,700 --> 00:01:59,667
For us to emit an event in this component,
we can make use of defineEmit.

28
00:02:00,067 --> 00:02:04,167
And we're going to define
that it emits an event called guess-submitted

29
00:02:04,400 --> 00:02:07,517
that contains a string as the payload

30
00:02:07,533 --> 00:02:11,300
that is going to represent
the guess the user is submitting.

31
00:02:12,127 --> 00:02:14,233
We can do so, like this.

32
00:02:18,653 --> 00:02:21,633
Through this,
we're determining that our component

33
00:02:21,667 --> 00:02:23,663
emits a guess-submitted event

34
00:02:24,333 --> 00:02:27,897
that has a payload containing
only a single element of guess

35
00:02:27,900 --> 00:02:29,233
that is of type string.

36
00:02:31,223 --> 00:02:32,674
Pretty nice, right?

37
00:02:32,699 --> 00:02:34,567
By defining emits like this,

38
00:02:34,592 --> 00:02:39,100
we're leveraging TypeScript
to give us pretty nice intellisense.

39
00:02:39,125 --> 00:02:40,403
So check this out.

40
00:02:43,290 --> 00:02:47,767
If I try to emit an event that hasn't
been defined, for example, foobar,

41
00:02:51,417 --> 00:02:54,400
you can see that I'm getting
a type error, because foobar,

42
00:02:54,500 --> 00:02:56,640
is not an event that I have determined.

43
00:02:57,393 --> 00:03:02,700
And if I provide the correct event
with an invalid payload,

44
00:03:02,933 --> 00:03:07,233
I also get an error because the payload
must be of type string.

45
00:03:08,366 --> 00:03:14,033
This is a very simple but effective way
to make our code base more robust.

46
00:03:22,730 --> 00:03:27,003
Okay, it looks like we're good
on the guessInput component.

47
00:03:27,028 --> 00:03:30,128
Now let's make use of it
in the worldeboard.

48
00:03:39,557 --> 00:03:42,167
We no longer need this onSubmit method.

49
00:03:42,300 --> 00:03:45,367
We no longer need
the formattedGuessInProgress,

50
00:03:46,903 --> 00:03:48,600
nor the guessInProgress,

51
00:03:49,989 --> 00:03:52,500
and we can eliminate unused imports.

52
00:03:52,567 --> 00:03:54,600
All right, let's run our tests.

53
00:03:55,212 --> 00:03:56,510
And we're passing.

54
00:03:56,533 --> 00:03:59,500
Great, I think we're a good point
to make a commit.

55
00:04:01,417 --> 00:04:06,533
Extract GuessInput
into dedicated component.

56
00:04:08,870 --> 00:04:10,803
Now this could be a good time

57
00:04:10,828 --> 00:04:13,600
to put a little bit of styling
into our component.

58
00:04:14,437 --> 00:04:17,533
Feel free to do this
in whatever way you prefer.

59
00:04:18,657 --> 00:04:22,305
I'll do it over here
and then I'll show you what I've got.

60
00:04:23,287 --> 00:04:25,667
This is what I've got so far.

61
00:04:25,813 --> 00:04:28,679
Since styling
isn't the focus of the lesson,

62
00:04:28,704 --> 00:04:31,133
I'll briefly explain what I have done.

63
00:04:31,633 --> 00:04:34,167
But if you want to discuss
more about this,

64
00:04:34,267 --> 00:04:37,667
please don't hesitate
to reach out to me on Twitter.

65
00:04:38,367 --> 00:04:44,567
For styling, I decided that I wanted
to hide the native input type text element

66
00:04:44,667 --> 00:04:51,067
and instead render
a formatted guess as a list of letters.

67
00:04:52,867 --> 00:04:55,667
But before I started styling anything,

68
00:04:55,692 --> 00:05:01,567
I wanted to make sure that our input
type text was always focused.

69
00:05:02,703 --> 00:05:05,300
This test over here is how I've done it.

70
00:05:05,733 --> 00:05:11,567
And it drives a couple
of advanced concepts of vue test utils,

71
00:05:11,646 --> 00:05:14,133
but I'll give you a brief explanation.

72
00:05:16,810 --> 00:05:20,433
One way you can evaluate to see
if an element is in focus

73
00:05:20,458 --> 00:05:24,033
is by checking
for the active element of the document.

74
00:05:25,000 --> 00:05:30,467
However, your tests won't work
for the active element

75
00:05:30,492 --> 00:05:33,733
if you don't explicitly
define an attachTo.

76
00:05:34,890 --> 00:05:35,988
Let me demonstrate.

77
00:05:36,013 --> 00:05:39,546
If I run just this test over here,
you can see that it's passing,

78
00:05:39,600 --> 00:05:42,928
but if I remove the attachTo
from the mount options,

79
00:05:43,972 --> 00:05:45,652
the test now is failing.

80
00:05:46,731 --> 00:05:52,700
And the reason for the failure
is that the active element is the body,

81
00:05:52,833 --> 00:05:54,267
not the input.

82
00:05:58,670 --> 00:06:00,737
That's why the attachTo is needed.

83
00:06:04,670 --> 00:06:09,333
And as you can see over here,
I'm trying to blur away from the input,

84
00:06:09,367 --> 00:06:12,200
but the input should remain
being the active element.

85
00:06:12,367 --> 00:06:15,800
I also want the input
to be auto-focused at the start.

86
00:06:19,217 --> 00:06:20,967
To get this test to pass,

87
00:06:21,633 --> 00:06:25,300
I've assigned the attribute
of auto-focus to the input,

88
00:06:25,325 --> 00:06:28,433
and I also defined
an event handler for blur

89
00:06:28,567 --> 00:06:34,267
that focus back on the input,
so the user cannot lose focus of it.

90
00:06:36,128 --> 00:06:37,717
To give a bit of flavor,

91
00:06:37,733 --> 00:06:41,100
I also created this property
called data letter,

92
00:06:41,167 --> 00:06:43,767
which keeps track of the letter

93
00:06:43,800 --> 00:06:46,833
that the letter square
is currently rendering.

94
00:06:46,833 --> 00:06:49,500
The reason why I wanted
to keep track of the letter

95
00:06:49,525 --> 00:06:55,233
is just that I wanted a pop animation
to happen every time a letter

96
00:06:55,433 --> 00:06:58,733
would go from empty to something else.

97
00:06:58,758 --> 00:07:00,463
So this is what's happening here.

98
00:07:00,488 --> 00:07:04,070
I'm looking for all the list items
that don't have a data letter

99
00:07:04,126 --> 00:07:05,833
of an empty space.

100
00:07:06,166 --> 00:07:09,533
And if that happens,
then the pop animation triggers.

101
00:07:15,123 --> 00:07:19,233
Lastly, a key takeaway
from this styling over here

102
00:07:19,326 --> 00:07:21,967
is this scoped keyword.

103
00:07:22,300 --> 00:07:25,167
I like to use this
by default in my projects

104
00:07:25,192 --> 00:07:28,833
because it forces all the styles
defined in this component

105
00:07:28,867 --> 00:07:31,833
to only apply to this component.

106
00:07:34,610 --> 00:07:38,463
Well, these are the main key points
I wanted to cover regarding styling.

107
00:07:38,488 --> 00:07:41,067
But if you want to look deeper into this,

108
00:07:41,426 --> 00:07:44,400
the link to the repository
is in the description.

109
00:07:44,567 --> 00:07:47,733
And again, don't hesitate to reach out.

110
00:07:49,067 --> 00:07:53,600
The worldeboard itself also had
a little bit of revamping looks.

111
00:07:54,800 --> 00:07:57,900
I added a little animation
for the feedback passage

112
00:07:58,133 --> 00:07:59,833
to appear on the screen,

113
00:08:00,073 --> 00:08:03,867
and I also centralized
the elements of the worldeboard.

114
00:08:07,737 --> 00:08:11,133
And here is a really nice thing
about all of this.

115
00:08:11,200 --> 00:08:15,767
I did not have to alter
any of our existing tests,

116
00:08:15,807 --> 00:08:17,700
but look at this.

117
00:08:19,273 --> 00:08:21,700
They are all passing.

118
00:08:23,326 --> 00:08:27,133
We did a complete revamp
in the looks for the application,

119
00:08:27,167 --> 00:08:30,600
but the core functionality
remains unchanged.

120
00:08:31,059 --> 00:08:32,406
Since we wrote our tests

121
00:08:32,431 --> 00:08:35,633
by focusing on behavior
instead of implementation,

122
00:08:35,700 --> 00:08:38,400
our tests are all still passing.

123
00:08:38,433 --> 00:08:39,767
Pretty nice, right?

124
00:08:40,033 --> 00:08:44,667
I also want to emphasize that I did
my restyling of the app in little chunks.

125
00:08:44,767 --> 00:08:48,133
I would do something, then run the tests,

126
00:08:48,133 --> 00:08:51,067
see they were all passing,
and then make a commit.

127
00:08:51,767 --> 00:08:55,033
And sometimes if the commit
was still related to styling,

128
00:08:55,067 --> 00:08:58,733
I would just amend with the previous
commit for that component.

129
00:08:59,186 --> 00:09:01,333
Make life easier for us.

130
00:09:01,358 --> 00:09:04,367
Commit often. Test often.

131
00:09:04,967 --> 00:09:11,133
Great! Together, we have seen firsthand
the benefits of writing flexible tests.

132
00:09:11,400 --> 00:09:13,433
Always strive for writing tests

133
00:09:13,467 --> 00:09:16,267
that are not tied
to implementation details,

134
00:09:16,267 --> 00:09:19,400
but rather to behavior and functionality.

135
00:09:19,967 --> 00:09:23,267
Writing tests that are tightly
coupled to implementation

136
00:09:23,300 --> 00:09:26,267
will result in a fragile test switch,

137
00:09:26,467 --> 00:09:30,433
which has a higher chance
of providing false negatives,

138
00:09:30,500 --> 00:09:34,100
that is,
tests failing when they shouldn't.

139
00:09:34,767 --> 00:09:38,633
If you see your tests driving
too much into internal properties

140
00:09:38,658 --> 00:09:40,400
and attributes of a component,

141
00:09:40,425 --> 00:09:44,367
it could be a sign
that your test should be refactored.

142
00:09:45,133 --> 00:09:49,400
Focusing on behavior,
leads to a test switch that is robust,

143
00:09:49,646 --> 00:09:51,400
and not fragile,

144
00:09:51,867 --> 00:09:55,967
which will embrace
and facilitate future changes

145
00:09:55,992 --> 00:10:00,900
and refactors to your codebase,
as opposed to creating attrition.


