ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.
The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.
React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React, TypeScript, and TDD
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.
AI Generated Video Summary
Today's workshop focuses on test-driven development in React, covering topics such as running, building, and testing React apps, using Prettier for code formatting, refactoring and creating subcomponents, implementing state and event handling in components, and project management and IDE integration. The workshop emphasizes the benefits of test-driven development, the use of IDEs, and the integration with tools like Jest and React Testing Library. TypeScript is also highlighted as a valuable tool for type checking and improving code quality. Overall, the workshop provides a comprehensive guide to developing React components test-first and following best practices in software development.
1. Introduction to Test-Driven Development in React
Today's workshop is about developing React components test first. Writing a test before writing the code and continuing to develop the code and component. At the end, you can see the actual result in the browser. The tutorial provides a URL where you can follow along, with write-ups, code, and videos. Each step in the tutorial has a link to working code for that segment.
Today's workshop is going to be me trying to convince you about an idea. And that idea is about developing your React components test first. Writing a test before you write the code. Writing a test as the way to continue developing the code and the component. And only at the very end when you need to see what it actually looks like do you go to a browser.
This tutorial has associated with it something you can follow along on. You can follow along on this url www.jetbrains.com webstorm guide. If you click on tutorials you'll get to this tutorial. And you will find in this tutorial that I'm kind of cheating. Every single thing has the write up that I'm going to talk about it has the code that I'm going to show. It even has a video which is mostly correct.
Let me cover that point real quick about the yes I can. I put it in discord, but you're right. I should have put it over to someone else did all right. All right got me thanks for doing that. Every single thing I have is kind of cheating and putting in here but there's a reason for this I want you to be able to follow along and play around and not worry about every single thing. I say if there's something you didn't get there is something you want to follow up on. I can be easy you easily replaced by a URL to a website. And I should also know that each step in the tutorial has a link to working code for that segment of the tutorial.
2. Setting Up a React Project
In this part, we will discuss the benefits of test-driven development and the use of IDEs in the development process. We will also cover the setup and cleanup process, testing, and debugging. The tutorial is up to date with the latest version of Create React App and focuses on writing React components. We will create a new project using WebStorm and NPX, ensuring we have the latest version of Create React App. TypeScript support will be included. The output of Create React App will install the necessary dependencies for our project. Let's dive in!
So what we're going to do is we're going to go through this. make the case for this way of doing development. As I go through building working code. We will try to do a stop maybe like an hour and a half from now or something like that. Take a five minute break. So I've got my timer set for that. We will also be talking in chat. I will try to get both the Discord channel and the, let me make the Zoom chat a little bit bigger, so I won't make a mistake on it.
All right, excuse me for a second. Apologies, I wonder if my microphone picked up that sneeze. We will be taking a little bit of a break, we'll be following along on all these things. And if you get stuck, that's okay, because the link to the working code for each step will teleport you into a magical future where everything works correctly.
One last caveat before beginning, I am a developer advocate for our IDEs. So at JetBrains, for this, it would mean WebStorm, or any of the other IDEs that include the WebStorm plugin. I'm not going to really over promote WebStorm on this. It will be – I use the word IDE, because then it will apply to other smart editors that can look at structure instead of just the strings of text. But at the same time, as I do this tutorial, I get really excited about how the tooling can help us, the tooling of testing and the tooling of typing can make us have a better development experience and stay in the flow.
So, with that in mind, let's begin. This is the sequence we're going to do setup and cleanup and then jump right into testing. We'll do a little bit of debugging to show the benefit of sitting in an IDE, and then straight into a number of things about writing React components. This is up to date as of create React app last week, so I updated all the code for this. I didn't update the videos. There are a couple of places where the videos are out of date on using a jest selector for roles, but we're all smart. We can work around it. I don't know how far we will get through all of this today, but, again, I'm easily replaceable, so if we don't get to the end, you can just watch the video on your own time and see about these last couple of things. They're pretty interesting topics, and they really do show off how far you can go with test first.
All right, let's begin, so I'm going to go to project set up, and I'm going to get us a sample application, and we're going to show three kinds of running things in the code. We're going to show running the development set up, the build your final site set up, and the test set up. And along the way, we're going to start introducing a little bit of things about the IDE. So, with that in mind, if you want to follow along on this page, that's fine. I also have it in the background so I can cheat. I'm going to go over to my IDE, I'm going to start on the welcome to WebStorm screen. I'm going to create a new project.
Now, I could, if you're not using WebStorm, that's fine, you can type this. So, I'm going to create a new project, it's going to be a react project. I'm going to call it Create React App and it's going to prompt it's going to tell me some of the things that's going to be using by default. Let me make sure I have it. I gotta scroll up. We're good. There. We're good here. I'm using hug. I think node 16. Yeah. 16.10 Thank you, WebStorm for answering that question for me. It's going to be using NPX to get create React app. So let's see if you have intelligent idea ultimate, then you have access to the Node JS plugin. And if you've installed Node JS, you have access to all of this.
A little disclaimer about this, I'm going to explain as if some things for some of you might be new. But I also realize that some of you do know what NPX is. I won't dwell on it because it's all really well explained elsewhere. In the world of Node JS. But if you're creating a project, you can use the NPM command to install packages. But what if you want to install like a application, something that you're going to run, which will then create a package. There's this thing called NPX which says, Okay, go get the latest version of this put it in a temporary environment and run it. So you see a lot of these command line tools like learners and formatters and scaffolds like this. Create React app using NPM so that you're always getting the latest version. What is the latest version of Create React app? Which is the scaffolding tool that we want to use. It's four point oh point three. And finally, I want to make a Typescript project because typing is an important part of this.
Okay, with that in mind. a little bit off the end. I should have. I'm going to go back and make a new one. I did well I will go and delete that scratch pen. All right. Okay, and then I'll come back. My apologies I should have deleted that. So new project, react going to call it CRA, and I'm going to ask for TypeScript support, say create new project and WebStorm is putting on my external monitor. So let me resize this here. And then. So. So what WebStorm did was it created a new quote unquote project in that directory and ran some things that it knows how to run, such as create react out, which is creating all the software and then installing all the dependencies. So that's what you see right now is the output of create react app, as if I was doing it on the command line.
Ah, yes next JS, in fact, we're getting more interested in next JS, my colleague Ebenezer Dawn has a long blog post about MDX and next JS that we published recently. Alright, so this is going and getting I mean, let me talk about create react app. For those of you who don't know it, it is a scaffold to generate the best collection of supported software for a modern react app. What that means is add on packages, you might want to use and tooling that you might want to use like lenders and stuff like that. It's going to be over a thousand, maybe 1,500 packages that it installs. And this is just madness. It's so hard to keep all of this stuff in your head. And then as it changes like every single day, this will break that create react app is doing us all a really big favor by taking ownership of what software should you use. And what versions of what software should you use? And they will say we will support all of that. So this is a really important thing to be doing for create react app. And that's why I'm using it as the start point.
How luck we have co-workers here together. All right. And yes, June, you're correct. There are always 100 options to do the same thing for everything, especially in the front end world.
3. Running, Building, and Testing React Apps
In this part, we learn about running and configuring a React app using Create React App. We explore running the app using the terminal and the IDE, as well as the benefits of using the IDE's npm tool. We also discuss the build process and the generation of a production-ready build directory. Finally, we touch on the topic of testing and the use of Jest as the official test runner.
There are always 100 options to do the same thing for everything, especially in the front end world. I think you all know that. OK, now at this point, all of my software has been installed. I'll resize all of this and I want to run something. I want to run something that's in my package dot JSON file. I suspect that font is a little bit small. Let me make it a little bit bigger.
OK, create React app generates a package dot JSON with some of the things in it. But what's interesting is it's moved a lot of the configuration and a lot of this scripting over into software that can be updated later without you having to change your package dot JSON or the dependencies or anything like that. Now I could go ahead and start this using the terminal. And I will I'll say NPM Run script start. And this is the way you're probably used to doing. That is opening a terminal. And then let's see you opened Chrome. I'm going to go and change my browser. To be Firefox first listed. Yeah, that's good. So, this needs to come over here. Right. I wanted you on Firefox but that's alright. We're good. npm start runs a developer server.
Okay, all right. So I'm showing in WebStorm, but if you go to Find Files, hopefully you have it over here. If you don't have it under here, then it might not be installed correctly. Okay, I'll close this Build tool window. And we're talking about testing. And so what we want to run is this run script for test. Now what's it really doing? Again, create React app is kind of the official scaffold for the React project. And it has made some choices about testing. It has made the choice that Jest is the official test runner.
4. Running Tests and Project Cleanup
Jest is the official test runner, and the testing library used is called testing library. They ensure compatibility between versions of Jest, testing library, and React. Running tests can be done from the command line, NPM scripts, or the package.json file. The tutorial covers the setup of npm run scripts in the IDE and create React app. Next, we will clean up the project and explore TypeScript. Any questions or comments before we begin? We'll use the expression 'Fail Faster' to catch mistakes early and focus on code reformatting with Prettier. We'll also remove unnecessary files generated by Create React App.
Let's see if I've got it. Yes, Jest is the official test runner, and the testing library that's used for a search and test automation and stuff like that is something called testing library. And they make sure that this version of Jest and this version of testing library works with this version of React. This is an important thing because that stuff breaks all the time. Especially when you introduce TypeScript into the equation. So it's very helpful that someone else is doing that work for us.
How can I run my test right now? Let's see. So let me come back over here. I could run it from the command line like I did before. And it will give us the output. Or I could run it from the NPM scripts. Or I could do the package.json thing. So I'm going to run it from here. It's going to open another run tool window. And it's going to launch up my test watcher, which is running my tests constantly on every change to see if something is broken. Briefly, I'll go break something. And I will. Let's see, In Test. It wants something called Learn React. And so let's see. Learn. Yeah. If I save that, the test rerun. And it says I failed a test. Put it back, save it. In this case, it didn't run the test again because it's in a mode where it only OK. So those are our ways of kind of getting started with npm run scripts in the IDE and getting started with create React app and testing. So what we saw was there's a lot of tooling involved. And create React is doing a great job at helping us stay up to date and managing all of that tooling.
In this next step, we're going to clean up some of the things that were in our system that we got out of the box that we don't need and take a little bit more at take a little bit more of a look at TypeScript. OK. Let's see. All right. I think I'm up to date. Let's go to the next step in the tutorial. We're going to go to the project cleanup step. I'll take this little moment to take any questions you have or see any commentary you have and offer up some commentary of my own. This site is a developer advocacy project at Jet Brains. We have guides for PyCharm, WebStorm,.NET, Goland, Space, IntelliJ, which is doing a great job with their guide. And I chose to implement it using Gatsby. Gatsby. And it was a great first week. And it has been a really tough 200 weeks since then. All right, anybody have any other questions or comments about Create React App, or the world of React or IDEs and tooling? OK. We'll begin. We're going to clean up our project a little bit, remove some things that we aren't using, and along the way, kind of show how the IDE can help us. I'm going to use an expression. I'm going to use a couple of expressions in several places. I'm going to use an expression called Fail Faster. Odd expression intended to be odd. And the point being, if there's going to be a mistake later, show it to me now. Show it to me right in my face visually so that I know I've made a mistake. And so as we go along, I'll talk about Fail Faster a little bit. In this sample, in this step, we're going to look at getting our code reformatted, ultimately with Prettier. We're going to strip down what we got out of the box to include deleting some files that were generated by Create React App, which we aren't going to use.
5. Using Prettier for Code Formatting in WebStorm
In this part, we learn about cleaning up files and using IDE features for code formatting. We explore the use of Prettier as a code formatter and discuss the choice of package manager between Yarn and npm. We also address the placement of development dependencies in Create React App and the installation of Prettier for code formatting. The IDE provides options to configure Prettier and run it on code reformatting. The audience engages in a discussion about why Create React App puts development dependencies under runtime dependencies.
Yes, Alexis Gatsby. Is that smiley face, Alexis, is that a smiley face of love or pain? If anybody's a Gatsby lover or user that are here, I apologize if I've misspoken. Share your thoughts about Gatsby in the channel, and let me see what you think.
So we're going to do some cleanup of some files and see how the IDE can tell us, hey, you're about to make a mistake. Fail faster. We're going to see a little bit about IDE goodies, how it can warn you about certain problems. It can do cleanups for you, and a little bit of refactoring. So let's begin, I'm going to start by reformatting my code, and I'm going to do it first in, I'll leave Package.JSON open. I'm going to start in here, and in the IDE, in Mac OS, it's Command Alt L. You'll see that I've got this tool called, a plug-in called, Presentation Assistant installed. It's for all of our IDEs, and it pops up what keystroke was pressed, what action was invoked, so I'll do it again. That tells you the key binding that you can use on your side. The tutorial also has the key binding listed as well in the text.
Yes, Alexei, good point. It can use Yarn as a package manager. Our IDEs are fairly transparent about that. If I go to find action, no, to preferences, and I search for npm, I can switch between Yarn and npm. Good point. In the package.json, in the dependencies, it actually lists some of the ones that you mentioned. The types just are listed here. Is it, I wonder if it's not in my text. Is that, if the problem is it's not in my text, then I need to update it. But I thought I copy and pasted all that correctly. If not, I apologize.
6. Code Reformatting, Cleanup, and Renaming
We reformat the code using Printier, make the top-level component simple, and add a heading. We optimize imports, delete unused files, and handle import warnings. We also rename the app to My App and update the file name based on the React convention.
And now, watch what happens. You see that single quote? I'm going to reformat code. And because Printier has a different opinion than the IDE, it thinks things should be double quotes. When I reformat code, it's running Printier. All right, so that's great. We have Printier running. Let's do a little bit of cleanup. I'm going to change my top level component to be super simple. And I'll run Printier, get some indentation on it. And I'm going to put a little heading in there to get it to say, let's say, hello React. And I'm going to use Emmet to do this. I'll get rid of this as well. I cut and pasted and cheated. But I could say div.h1 tab. And then say no, that's not what I wanted. Div. Oh yeah. Sorry. It made a class name for that. And then tab. div.h1. Div.h1. I have messed this up. I won't belabor that. I'm obviously typing something wrong here. And I will say, hello, React. All right. Oh, OK. No space. That's what I'll. Yeah, you're right. div.h1. No. div.h1. Yes, tab. My apologies. That's something I do all the time. I don't know why my hand didn't automatically understand it. OK, so we have now a very simple React component that will form the basis for our testing later. But we see that we've got some problems in our code now. In fact, we have two. And let's see. Logo is defined, but never used. I could go back up to the top and just delete this. But that would mean stopping what I'm doing and breaking out of the flow. Instead, I do optimize imports. And that's the key binding for it. And that will remove any unused imports, and it will resort my imports, combine my imports where necessary without moving my cursor. And that's a great, great thing for me. Optimize imports or any format code I do all the time. Now other cleanups I can do. I'm not using app.css or anymore, so I can delete that line. And then I can delete these two files since I'm not using them anymore. So that's Logo.SVG and app.css. I'm going to delete that. But this is smart delete. It's going to say, do you want to go look for anything that might be using it? I'll say, sure, great. And nothing was using it. Now, let's take a look at if I deleted something that was being used. Like, OK, well, if I'm deleting CSS, let's delete some more CSS. Uh-oh. Wait. Something is using it. What is using it? Oh, the top-level thing is using it. Let's not do it. All right. And then some other things. If I keep that line out, in some cases, if you don't, in older versions of React or depending on how you set up your project, that's like pre-React 17, you had to import React if you were doing JSX. And then the IDE would give you a little warning and say, hey, you need to import it. Do you want me to import it for you? And you say yes. And it does the janitorial work for you. It's interesting. Create React app still generates this import, even though we are clearly beyond React 17. All right, great. All right, we've gone through some of these cleanups. We talked about this IDE goodie where if you are on earlier version and you delete the import of React, then you will get this warning that you're missing an import. And you'll get an alt-enter, which will be a friend of ours during the course of this workshop, as a help. And then you choose the action and it generates it for you. Let's do another thing. Let's say that app is such a boring name, I want to change it to my app. Well, what we could do is go look around everywhere in our project and find all references to app, hope that we found them all, and change it. Or I could refactor rename and say My App. And you see, as I type down on the bottom, it's changing that reference. And when I'm done, I hit Enter. And it does even smarter than just finding references. In the world of React, there is a convention, a single responsibility principle, that you name the file the same name as the default exported component. So the IDE is helping me, saying, hey, remember there's this style guide. You might want to change the name of the file. Yes, in fact, thank you, IDE. I do want to do that.
7. Undoing Refactorings in IDEs
When renaming components or files, IDEs offer the ability to undo the changes made during the refactoring process. This allows you to easily revert back to the previous state, including changes made in test code. It's a convenient feature that ensures you can easily undo an entire unit of work and restore everything to its original state.
Now when I go look at the usages of this, like the index.tsx top of my app, its import is now different. It's importing from a differently named file, and it's importing a differently named symbol. My app is still in good working condition because refactor, rename went everywhere and did the right thing for me, including in my test code. Let's say I then, though, decided, oh no, that's dumb because everybody names it app. If I name it my app, then no one will know that that's really the top level component. Hey, IDE, can you put it all back the way it was? Can you change that function name to app? Can you change the file name to app? Can you change the get reference? Can you change all the things that point at it? All you have to do is an undo, and it's going to undo everything that was done in that action. So the file name is back to app, get is back to app, and the things that reference it are back to using app. That's a really handy thing for all of our refactorings, that you can do an undo and put things that entire unit of work, you can put it back the way it was before.
8. Introduction to Testing
Next up, we're going to do actual testing. The workshop emphasizes the importance of enjoying the development process and finding the most productive way to work. We'll demonstrate this through the perspective of testing.
OK, next up we're going to do actual testing. The point of this workshop now that we're all set up, I will pause for a moment. Anybody have any questions? I see Reggie talking about optimizing imports and VS code, at least Mac OS. And that's again, this is about IDEs in general, smart editors. This isn't focused just on WebStorm. Let your tooling to the janitorial work for you. Which also means spend a little bit of time learning your tooling. You're a professional. Get good at your tools. Leave time during the week to brush up on your old skills and learn some new skills. The 10 minutes or 20 minutes that you spend will pay off during the course of a year. Thanks, Dylan. By the way, Dylan, is my audio too loud or too quiet? I have a habit of talking loud. Thanks, Jim. And Sherry, I agree with you about running them as a combo, which is something for WebSRM, at least in 2021.2 you can have that all happen in a configurable way. OK, over to testing. I call this test first instead of test-driven development because what I want to convince you of is it's not eat your vegetables. OK. You have a choice, am I going to eat the dessert or the broccoli. Going to eat the dessert. Instead, I want to convince you this is a more pleasurable and joyful and productive way to work. To start in a test I'm not trying to convince you quality. Quality is good, but the point here is what's the best way for me to work right now. And we're going to show it from the perspective of testing.
9. Running Tests with Jest and IDE Integration
Jest is the test runner used in the world of React and has great integration with IDEs like Webstorm. We can run our tests under a user-friendly interface and focus on fine-grained components. By stubbing code and returning dummy data, we can minimize errors and concentrate on specific parts. Let's set up a pretty face for testing by running tests directly from the gutter or running everything in a file.
All right so as you come through this, again all the code is linked from here. Jest is the test runner, that the world of React seems to have adopted. It's also from Facebook I believe. And IDEs such as Webstorm and others have great integration with Jest. And for our IDEs, our IDEs all have a consistent UI atop any test runner. So you learn one, you learn them all across all of our IDEs, and Jest is wired into that.
So let's run our tests the way they are right now, but under this pretty face that we put on top of Jest. Jun, you are correct that you will run into some errors. What you can do, though, is have your stub code just return dummy data to stop the errors as you're filling things in. But as you'll see during the course of this, because we're doing really fine-grained small components, you can point the test at this very small thing and ignore the rest of the universe. And so you're only getting a couple of errors, which happens to be the thing you're thinking about at the moment. So June, ask me again in an hour and a half and see if you disagree with this approach.
So what I want to do here is I want to get myself set up on the other monitor. What I want to do here, what I want to do here is get a pretty face on my testing. And this is in this segment, pretty jest, if you're following along. So what I want to do is be able to walk up to a test. And in this case, my tests are in app.test.tsx, and just like package JSON, I get these icons where I can run things directly from the gutter, and it will run just this one test. Or, I right-click somewhere in the editor, or I right-click somewhere on the tab, and I can run everything in just this file. So I'm going to do that. I'm going to run app.test.tsx.
10. Test-Driven Development in React
Test-driven development in React can be slower due to the transpiler and TypeScript compiler cycles. However, the IDE provides a dedicated tool window for testing, allowing developers to stay focused on the code and receive immediate feedback on test results. By setting up a run configuration, developers can run all tests or individual tests, depending on their needs. The IDE's integration with Jest and the Node.js debugger further enhances the testing experience, providing features like code autocompletion, failure notifications, and the ability to run tests in the debugger. This approach to development, known as TDD, helps developers work deliberately and under control, without distractions.
Test-driven development, test-first development in the world of React is a little slower. Actually, in the front end world, a little slower than other languages. Such as Python, because you have the whole transpiler cycle. You got the whole TypeScript compiler cycle to do before it can actually execute the code. So in this case, we got a pretty face on our test output. We have a tool window dedicated to testing with a little tree that shows all the files that ran. And then within each file, each test that ran, and some little icons that tell you what failed, what passed.
And in fact, it goes back into the test code, changes the gutter icon to show you that it failed, and puts a little squiggly letting you know that a test failed and why. So you don't have to go to the tool window. You can stay in your editor and stay focused on text output. Now, we know that this failed because we changed it during clean-up. So it would no longer say that. What we can do, though, is set up a run configuration that has all of our correct options that runs all of our code, rather than walking up to a single test. I actually find walking up to a single test to be the way I work most of the time. But sometimes, and this comes back to what June is saying, sometimes I want to run all the tests to see if this change here broke that thing over there.
So let's create what, in our IDEs, is called a run configuration. I'm going to manually create a run configuration based on Jest. And I'm going to say all tests. Our Jest run configuration knows about Jest. It knows certain things that you're going to want to do with Jest. In fact, it knows that not only are there just options, they give you the placeholder text that tells you what some of the options you might want are. And in fact, that's the option I'm going to choose. I'm going to choose the dash watch option. Now when I drop down for the available configurations and I just ran, which was the single file. And then this new configuration called all tests. And when I run it, I'm going to get the same output. But I'm going to get the same output, but it's still running. So that if I came over to here and I see, oh, it's hello react. Now, if I need to fix my tests, as soon as I save, it's going to rerun my tests. I don't even have to do the action to run my tests. I just have to type and save and it will do the rest.
So I've now fixed my tests. They're all working. Lucy and I'm getting to that in the next segment. Yes. Is it the next segment? Well, yeah, down here. All right, that is the way I do is a split windows approach. So let's get into a little bit more of TDD in action where I do something that fails. I know it's going to fail. And I see the failure, and then I look at some of the things I can do, and then I fix it. So I'm going to put in this code here and see a little bit of autocomplete in action. I'll make this a little bit smaller. All right. I'm going to say, what do I call that? Actual expected. const actual equal one, constant expected equal two. I could put those on the same line. I'm going to write a test assertion about these values that happen to be embedded in the test, but that's actually OK as you're doing a test first approach. And I want to expect actual to equal, and that's how I'm doing autocomplete there. I don't have to type the entire thing, to equal expected, complete statement, save, and my test fails. And it tells me exactly why my test fails. Expected and actual were not equal. And again, if I come back, change, save, didn't type the action, it's watching, and it reruns the tests. That's an interesting question, Chris. At the top of this, just before you joined, I used create, react, out 4.0.3. And then everything is the same since then, which I believe it means it got its own TypeScript, but that wouldn't affect this. So I don't know if for some reason you got a earlier version of, oh, yeah, OK. I suspect it's because hello react is different than this. Make sure those two things are the same. I hope they are the same because otherwise I'm gonna have a hard time debugging this man. All right, we just did test-driven development. We wrote a test. It failed, and then we saw that it failed, and we fixed it. And along the way we saw that the IDE will help us fail faster by putting bleep in our face. Red squiggly on this assertion. It failed. Gutter icon changed to red, letting you know which tests failed. Down in the test runner output, one test failed, one test passed, or whatever. And you can do all these different ways to navigate to your successful tests and your failures. And that overlay, let me go back to that overlay, make this test fail again. I'm increasingly using this as my entry, my window into test running. I just put my mouse over that. It tells me what happened. And most importantly, I can click that, and it will launch the test in the debugger. It'll run just under the Node.js debugger, which is integrated in WebStorm. And it will stop on that breakpoint. And I can step around and see what values are. And I can even say things like Expected, Expected plus 1, et cetera. And then when I'm done running the tests, the debugger shuts down, and it removes that breakpoint. So this is a pretty rich way to develop. And I'll go to the end of the story. I never went to the browser. All right. TDD Basics. This is what let's see, Lucian was talking about. This is the way I develop. It appears to be the way Lucian develops as well. I don't like distractions. I like focusing on the thing that I'm currently doing. And I'm a man of a certain age. I can't be bothered to remember 500 tabs, and I need something to trick my mind into getting into the flow of testing, getting into the flow of working slowly, deliberately, joyfully, under control.
11. Test-Driven Development Workflow
To practice test-driven development, the speaker hides the project tool, turns off tabs, and splits the windows. They have their code on the left, test on the right, and test output running at the bottom. The speaker demonstrates making a change in the code that breaks the tests, highlighting the benefit of having everything on one screen. They also mention receiving desktop notifications for test results.
And so the way I do that is I hide the project tool. I actually turn off tabs. I go to the Action Tab Placement. Tab. That's symbols. Oh, sorry. Actions. Tab Placement, None. I choose that, so my tabs go away. And I split my windows. This is all in the text, by the way. And so then I have my code on the left. My test for that code on the right. And my test output constantly running on the bottom. And I work, and I fix things, and I implement things, and it's all on the screen. Now sometimes when I'm on my big monitor, I take this test window, and I turn it into a window that I can move to another monitor. And then I really can concentrate code on the left, actually no, I'm backwards, for you, code on the left, test on the right. And in this case, test runner output on another monitor. All right, let's make a change in our code that will break this. I'll go ahead and delete these three lines, save my test run okay. My test run okay. The other one that I just closed wasn't in auto run mode. And if I change something in my implementation, and then my tests break, that's great because I'm looking at this, I'm sitting on it, I don't have to go to some other tab or open some other file, everything I need for my code, my test and my test runner is on one screen. So congratulations, you just did TDD, you just made a change that caused things to fail, I will revert it back, save, things will be fine, we remove those lines. You may have seen that bumping, that jumping of the icon. My big monitor over here, I got a desktop notification saying that my tests passed. So really, I could even hide that tool window and know I'm gonna get a desktop notification telling me something about my tests.
12. Debugging and Parameterization of Components
13. Parameterization and Test-Driven Development
We want to have it be parameterized so you can say hello, world, for example, or do something like capitalize the thing that was passed. Now we're going to do test driven development. We're going to change it to break. So I'm going to change this to react all upper.
We want to have it be parameterized so you can say hello, world, for example, or do something like capitalize the thing that was passed. Now we're going to do test driven development. We're going to change it to break. So I'm going to change this to react all upper. When I save, it fails. Adam is right. Right. It says exactly as a user would interact with it. That's Kent's big point, which then I think at least encourages writing small components so that you keep your velocity up. So my test failed. Now I have to go do the implementation and fix it.
14. Implementing Behavior and Debugging
To implement the behavior being tested, a parameter called 'name' is accepted and used in a template string. The IDE does not provide help for this, but TypeScript identifies the issue. By passing a value to the test, the failure is caught early. The IDE warns about missing type information, but can infer it automatically. The combination of TypeScript, test-first development, and the debugger allows for efficient debugging without the need for console.log statements. The tests can be stepped through and the problem can be identified and fixed. This approach allows developers to stay in the flow and work efficiently.
I need to implement the behavior that I'm testing. And so what I want to do is come over here and accept a parameter called name. And then I want to change this to a template string. Thank you IDE. And I want to say name dot uppercase. Now, you see, I don't get any help from the IDE on this. It doesn't know what type oh, wait. Yes, I will. Now, when I save. In the test run. In the test run. Test fail because I'm not passing an argument in and it's null. So what I want to do is change my test to pass in a value. In this case, the I'm failing faster. The IDE is giving me red Squiggly's saying you violated the contract on React. I didn't even have to run the test to know that I failed. Much less ship it into production and have my users tell me you forgot to supply an argument here. So now when I supply the argument test run. And let's see label. I'm not supplying a value down here, either. The other place that I'm using it. So my test here passed my test up here didn't. I'll go ahead and fix this one now by putting in react. Now my tests pass, but I'm getting a warning in my I.D. What's this warning? This is where typing comes in. This is where TypeScript comes in. Typescript is telling me, hey, we're a Typescript project. You didn't put any type information on this function parameter. I could go type in the typing information. Or again, IDEs are good at this kind of thing. Maybe they can help you. I'm going to do Alt Enter. And I'm going to say infer. And the IDE, in this case, or maybe the Typescript Language Service, looked at my code, took a good guess at what name was supposed to be, and provided the type information for it. So that worked out pretty well. I wrote a test. I wrote some implementation. I cleaned up some of the typing information. I have confidence. Remember, I never went to my browser. I stayed in the flow in my tool. So the IDE gave us an Alt Enter. We fixed the TypeScript problem. But let's say that we do something that we just can't figure out. We're like tired. We've been staring at it all day. We know it's a stupid, dumb, obvious problem, and I can't figure it out. I'm going to pass in 42. All right? And my test is going to fail. Now, again, fail faster. I've got a red squiggly. This is where the combination of TypeScript and test first really helps me. But in this case, let's say I'm not even looking at squiggly. I'm like, what is going on? I can't figure this out. You know what I'm going to do? YOLO. I'm going to run it under the debugger. I'm going to poke around kind of interactively, see what's going on, and see if I can stumble across the problem. So execution has stopped in my tests. There's another good thing about if you want it right, left, or left, right, but in this mode where you've got your code, your test, and your test runner output, it's all very familiar where the bodies are buried. I'm on this line in my test, and I can step through the code. In this case, I think I'll step into, I'll just step into the code. Execution jumps into label because we called label, and the next step was to jump into label, and it puts my cursor here. I get to see the value of name, I get to see the closure, I get to see the global, all these things. I get to see the stack trace if I want to go up higher and see what everything was higher up in the stack, and I get to poke around. So I could say, all right, aM, what is going on with name? It's 42. All right, let's see, two uppercase, oh, gosh, that's the problem. I passed in an int. I didn't pass in a number, I didn't pass in a string. That's what my problem is. So I was able to poke around, see what the problem was, realize my mistake, and make it a string. When I save, at the end of that little poking around session, find the solution of the problem, rerun my test, everything's green, I'm good. So we use the combination, we actually just used a really cool combination. We're writing components, and we want to write components and stay in the flow. We don't want a context switch between an editor and a terminal and a browser and where am I. And I combined test first, I combined TypeScript, and I combined Debugger to have an experience that made it really easy for me to get into just the spot I want to be in and poke around. no console.log statements. So we stepped into our code, we saw what the problem was, let's kind of put things back where they were. We got out of the debugger. We'll close the debugger tab, put it back to being working correctly and we're good. Our tests pass, we can go on to the next step. I will stop here for a second, take a look through some of the comments. Steven's got a good point that and that was what resonated with me was with enzyme, I was thinking of my tests kind of like implementations and I poked at the insides of things and. Not only was that not valuable to my customer who didn't care about it, it actually created this huge maintenance burden because whenever I would change the internals, I'd have to go fix all these tests that were broken for reasons that didn't really matter, there's this other strategy of, making sure you understand tests are both good and bad, they're like this weight that you're dragging around on your project and when you refactor things, you got to go change a whole bunch of tests. Let's get a link for the guy, and I'll paste up to the top of the guy where you can see a bunch of tips. That covers that, let's see if there's anything in here. Yes, inferring the type information is really nice. That's a good question about mocking, in the world of Python mocking is controversial, sometimes people call it a smell, I would be interested in others who are doing testing here, do you use just mock very much? I know in Gatsby I do. Ah, therapy, sorry, okay back to this, I'm going to skip over this segment, because it doesn't add anything new to the important part which is teaching about test-driven, test first development, just understand that if you have a need, you can execute your tests in the browsers engine, or I should say, to execute your, you could debug things in the browsers engine. I stay away from doing that, but Web Store makes it really easy to do that and I suspect that other tools do as well. And so in this case what I, it's all written here.
15. Using Chrome Dev Protocol and IDE Features
All right. Onward, we're going to look at using some features in TSX and ECMAScript 6, and seeing how the IDE can help complete things for us and keep us on the right track. We're going to clean up our code and test a little bit, make sure that your test configuration is running. I'm actually still running my web server, my dev, Webpack dev server. I'm going to stop it, because you know what? I haven't gone to the browser in a long time. I've been writing components, writing functions, writing tests. Never go to the browser exactly the way it should be, baby. Yes. Let's do some cleanup. Let's put app.test.txt back to its original state. I'll get rid of this, and I'm going to get my component back to just having that. So hello React. Get rid of this. Reformat code, optimize imports, because I do that a thousand times a day.
16. Refactoring and Creating Subcomponents
Alexei suggests using Cypress for unit tests. The speaker discusses the benefits of test-driven development and the use of IDEs. They mention taking a break and the use of Postman for APIs. The speaker plans to start refactoring and creating subcomponents. They explain the process of test-driven development and demonstrate making a subcomponent. The test fails, but the speaker plans to import the component and continue the refactoring process.
OK, Alexei is saying that he does like running things in the DOM headless, and I guess that's, you know, karma is big about that in Angular. Alexei, I would ask you, would you prefer using Cypress for that? Instead of just and say, just have to basically parallel test suites, one that is about unit testing and one that's about kind of browser testing. OK, there you go, Cypress. Cypress for everybody. Unit tests in Cypress. OK. Alright. All right. I learned something today. I learned I back over we're back into a blank slate spot. And that was my timer for giving us a little bit of a break. We're one hour and 20 minutes into this audience poll. Do you want a break? Put yes for break, no for no break. It's 50-50. It's 50-50, so we will do half a break. We will do a three minute break. So I have it is basically 20 minutes after the hour at 23 minutes after the hour, we will break. I'll type it in both. 23 minutes after the hour, we resume. I will get some water also. All right, be right back. All right, that's a good point Alexis about not testing visibility. Suzanne, the Postman for APIs is pretty cool. And our IDEs have this HTTP files thing, which lets you write in a file the request that you're going to issue. And then it feels a little bit like you're in an IDE in an editor, so actually kind of cool. Paul, just a note. Your Zoom chat is stuck with DM, so just make sure you switch to everyone. My Zoom chat is stuck with, oh gosh, huh. Thank you, Sherry. OK. OK, we will begin, or we'll resume. We will resume. What we're going to do is we've got it back into a working condition. All right, and what we want to do is start doing subcomponents. Refactoring because that's what react is all about. Making big rocks into little rocks, and we will do this refactoring kind of in a test-first way so that we will work with confidence, but we will stay in the flow because we don't leave our IDE. We don't have to go and look over at, let me turn off the ding. We don't have to go look at the browser all the time. My apologies. Apologies for the dinging. So I'm going to make a subcomponent. But I'm going to go to my test first. And I'm going to write a test that will be broken, but that's OK. I expect it to be broken because I'm still in the process of writing the implementation. So here we go. Let's actually do test-driven development. I'm going to sit in app.test.tsx. I'm going to write a new test. Let me make sure that I'm good. That question about Cypress, five minutes ago, I would have said just. But Alexi is trying to convince everyone that we should be using Cypress for unit tests. Alexi, I've got to get you to come on a webinar with us for WebStorm and show this to everybody, including me. OK, I'm going to render the heading. Renders a heading. And I'm going to make an arrow function. I'm going to start using the React testing library a little bit. I'm going to say const. I'm going to destructure. This is an ES6 thing. I'm going to destructure the results of rendering and grab one thing out of it, a closure called Get by Text. And this is going to be running render. Like we do above and like we do here. And so I'm going to be in this case rendering heading which smart people will say doesn't exist. And then what do I want to do with this text? I want to go grab something out of the fake document. So I want to grab a link element like I do above. Get by text. And I'm going to expect it to be this regular expression again. And then I'm going to do my assertion. Expect link element to be in the document. Now, when I say, what do you think happens? It breaks because heading doesn't exist yet. What we want to do is make a subcomponent out of this. And what would I do normally? I would go up here. I'll go to another file I would start typing our IDE is smart. It can help us with these janitorial tools. So I'm going to say, hey, IDE. Can you help me refactor this by extracting this to a component? Sure. What would you like to name this? I don't like this heading. Do you want it to be a class component or a function component? Function is the new sexy. So we're going to have a functional component and it took that. It made a new function. It replaced the plate, it did everything I would have had to do myself. It put a call to that function here. I will it even did prettier for me. Gosh, you're so smart. Thank you. Um, now when I save, my test still fail because I haven't imported it, but that's okay. Fail faster, read squiggly to me. It told me there was a problem. So go and get that import for me.
17. Extracting Subcomponent and Refactoring
In this part, the speaker demonstrates test-driven development by extracting a subcomponent. They show how to trigger the extract component feature using the IDE's refactor menu. The speaker discusses violating the single responsibility principle and decides to move the subcomponent to its own file. They demonstrate the IDE's ability to automatically generate imports and clean up unnecessary symbols. The importance of unit tests focusing on a single unit and the benefits of test-driven development in refactoring are emphasized.
So go and get that import for me. Oh, it can't import it because I didn't export it. So now I can generate the import. It generated the import for me. I no longer have something called label. I thought, Oh, that was leftover. I removed that test, but I didn't clean up my imports. So now I did test driven development to extract a subcomponent. I wrote a failing test. I went over to the parent component. I found the thing I wanted to extract. I selected it. I asked the IDE to do a refactoring. It did the refactoring for me. I had to add an export and I went back and generated an import. I will show again how to... Let's say I want to convert that to a component. This answers the question how to trigger extract component. You bring up the refactor menu. On Mac, it's control T. I'm about to hit it. Watch in the bottom of the screen if you want to see the Windows Key Binding. Refactor. Then I chose extract component. I did that by typing speed typing. I could have hit 0. I could have used the mouse, whatever. So I brought up the refactor menu and I chose extract component. Now I've got this entire thing selected. I don't have to. I can just click on the symbol and initiate it from there. All right, let me come over and look. I see there's a beautiful conversation in Zoom about why is it awesome about testing. That's all great stuff. Now I'm violating single responsibility principle. So I've got a sub component heading in the file of the parent component app. So what I think I'd like to do is extract this to its own file and then write its own test for it. Can the IDE do the dirty work for us. Probably otherwise I wouldn't be making this point right now. So bring up refactor move. I should say I didn't select all of this. I just put my cursor on the symbol. Refactor move. Then I'm going to get a dialog. Where would you like to move it to? Look what it did. It filled in the file name for me. The exactly way I wanted it to be. Gives you some choice about some members to move later. We'll see how the props, the type that we use definition we use for props can go with it. I'll go ahead and hit refactor. It opens it, asks me to add it to get. I've got this here and look what I have back where I was. An import replaces the definition that I have clever folks will see that my test that can get dragged along into a new file. I suspect that probably is asking too much of the IDE, so I would like to move this. Snakes. But I don't think I can extract this now, again, right. So I will take this and I'll make a new file called adding that test that yes, X. Paste this in there. Notice when I pasted pasting has the habit of generating the imports that I need for me. Okay, and then I do have a little bit of leftovers back here. A symbol that I don't need from the import because I'm not I'm not testing heading in this file app. Not test texts anymore. I could delete it or I could say, Hey, I D.E. clean up on a file five go run optimize imports and now that import is gone this test file single responsibility principle. It's about a. This test file single responsibility principle it's about heading. Save everything one more time. Keep my CPU fan going and all of my tests and all my files run. OK good. And let's see. Yes beauty of you of unit test is speed speed of execution a second benefit to this. I wonder if Lexi would agree with me that a secondary benefit is not hauling around the universe when you're refactoring. Unit tests should really focus on a unit so that if something else changes you don't have to go to a hundred things and remember try to remember what you were doing six months ago.
18. Refactoring and Default Prop Value
We extract the inline type information about the props to a standalone type called Heading Props. We reference this type in the code, making it easier to read. However, we still need to address the issue of the default prop value. By using an ES6 default argument, we can satisfy the old contract and ensure that the tests pass. TypeScript may raise an error due to the required name prop, but we can resolve this by informing TypeScript that the name prop is optional. This approach allows us to adhere to the single responsibility principle and maintain a clean code structure.
OK so we've done the heading sub component. We did the refactoring. We did the extraction and it's in its own file. Now let's say I think I did it. Yeah I did it out of order. I apologize. So what I want to do is bring back arguments and add defaults so that my heading is parameterizable. So I'll take this test. I'll go I'm in the heading test file and I wrote a test so that we could pass called name to our heading. And I haven't even run the test runner yet and I know it fails because I got read squiggled because of Typescript. Typescript's telling me what my problem is. But I'll go ahead and run it anyway. Let the test fail. And we kind of saw what was going to be happening over here. We need to put in a parameter. In this case, though, since it's a function, we're not going to pass name as an argument. We're going to be getting props and we need to destructure the prop name from it. And so I'm going to say name, which allows me to here say. Am I doing the two uppercase? No, I'm not. I will save. And this test will let's say. I need. I'll slowly but surely go through some of these things and fix them. So that should be. Oh, dollar sign. Duh. I'm not in a literal. So this test passes. This test fails, because I now have a required prop. I've done a refactoring, which broke the contract. And other usages of it are telling me that the contract was broken. Now I didn't have to run the test to know that I failed, because I got a red squiggly for that. So what is the solution for this? We get into props and typing. Now the first stab at this will be to inline the prop type information. I save that. And TypeScript is happier about some of this, but I don't have a solution to this yet. I want to be able to use heading without passing in an argument. The first thing I'll do though, is instead of inline type information, just about everybody puts the prop types in a standalone symbol in TypeScript. For the longest time I used interface. I still think most people use interface. I saw a good article saying use type not interface, because type is more limited. And the typing information you put on props should be limited. So I could extract this and go start typing type, up there, come back, type some more stuff here. Do you think I could extract an interface? Do you think I could do refactor in something about interface? Why? Yes, I can. Oh, got to be inside. So let's say, yeah. And I'm going to call this Heading Props. And you'll see what it did up here. It created something called Interface Heading Props. Let's see, I want I set extract to an interface on this. So all that preaching I just did about types, etc. So I'll leave it as interface because I think that's what I have in my tutorial. Now, let's see. That's what I wanted to do. OK. Already formatted. So I've extracted the inline type information about my props, I extracted it to a standalone type, and then referenced it. And this is so easy to read. That's really cool to see. All right. Now I still haven't solved the problem about the default prop value. What I want is to satisfy the old contract by using an ES6 default argument. So let's go do that. Let's fix this so that hello, React still works. And I would do that by putting a default argument here. But something else is going to go weird here. I run my tests and my tests pass. I'm green. I'm green. I'm green, I'm green, I'm green. But TypeScript is mad at me. TypeScript is mad at me on this line. Why is TypeScript mad at me? Let's hover over it. I think one of you has your microphone on. We can hear some background noise. TypeScript is telling us exactly what the problem is. It's in heading props. And it's saying that something is required. Name is required. But it's not being provided here. So what I need to do is tell TypeScript that name, according to this contract, is actually optional because we have a default argument. Save that. Test still run. TypeScript compiler is happy. We're all in a good spot on this. And if I would have done that in the very beginning of this refactoring, I wouldn't have had that broken test if I would have said, OK, optional. You don't have to pass a name to a heading. All right, and I went over the single responsibility principle already. We already moved the type, the subcomponent to its own file. What I should point out is I will do, I'll pretend to say subheading.
19. Refactoring and Extracting Components
We refactor and extract a component by moving the subcomponent and its dependencies to a new file. JSX and TSX have certain restrictions and error messages provided by TypeScript. The combination of test-first development and typing in TypeScript allows us to fail faster and receive immediate feedback in our IDE. We discuss various topics related to testing, such as mocking child components, code coverage, and the use of the React Testing Library. Storybook is also mentioned as a tool for showcasing component variations. We then switch to class components and introduce the concept of props. We create a new file for a counter component and write a test for it.
Refactor and extract component. Extract. Anyway, when I brought it up, it would have given me the option to take not just the component, but also the type definition and move the symbol to the new file. So that's a pretty smart approach to the refactoring. Take the subcomponent that you want to create and all things that it depends on, and move it to the new file. We are in good shape from a single responsibility principle perspective.
20. Wiring Counter Component and Testing
We resolved the import for the counter component and added tests for the label and count. We extracted the type information for the props to a standalone type and added a default value for the label prop. We then wired the counter component into the app and wrote tests to ensure it was rendering correctly. Everything passed, and we are ready to move on.
We want to resolve the import now that it's there. Oh, actually, as soon as I pasted, it did it for me. Thank you. Or it detected that it was there. Thank you IDE. So I have a counter, and it is rendering a label in a counter. It's a span with a title. This is the evidence of me finding out that react changed its or type script typings, decided to disallow label and for on spans. So this is the public contract, there will be a label with a value. And then there will be another span that has the actual count. And I'm testing both of them, the label and I'm testing the count. Let me see if there's anything. NPM audit, yeah, yeah, I guess I kind of did trust yarn ones audit and I didn't trust NPM audit, but that's a good point. I wonder if there's any progress on that. Does anybody know if NPM 45 is ever going to have audit capabilities. OK there's a question about checking to see if count to test instead of in the document. Good question I could be checking to see if the value just checking that. I guess at this point, I don't want to over test and if I change my mind, my test break. I say this count this test will still pass, but if I tested the actual value it wouldn't. And I guess I've kind of made my decision. I don't really care what it says, but you got to have a label like if you localized it to have a different word for count NOM. We're good. We're going to show with class based components how to do a prop. And we're going to do it using this consistent process we've been doing. We're going to write a failing test, fix the new dumb component, and then go to the thing that calls it, which we don't have anything calling it yet, and make sure that that uses it correctly. So we're going to add another test for the case where we're passing in a label. Think you know how this movie is going to go. It's going to break pretty fast. So cut and paste. I'm still in the counter tests. It failed pretty fast. Why did you fail? And I haven't even run the test yet. Why did you fail? Oh, you're telling me exactly why you fail, because label is missing. All right, but I will run the test anyway just so that we can see that the tests also fail. No, the tests don't fail, because this is a TypeScript failure. This isn't a runtime failure. All right, so what we want is more typing on our component. We have our component here, and we want some typing here. And what we want to say is, we saw this before as well, inline typing of the props. And when we do that, some things change. It's optional, the question mark, so this still passed. But we accept the passing of a label, so this still is fine with TypeScript. But what we want to do again is, we don't want that type information inline. So we ask the IDE to extract it to a stand alone type. And I choose type alias, and I'm going to say counter props. And it makes the type definition for me. That has the optional label. So TypeScript is happy, Jest is happy, I'm happy. And component is what's called a generic for the class of a component. We've moved it to a stand alone. The type definition says label can be optional. Can we have a default value though? And this is trickier now, because before when we had the heading, we were passing in to a function the value called props, which was an object that could be destructured and ES6 destructuring supports this. But we're not in destructuring. Unless I have a constructor or something, I don't even know if I can do it for that. So where can I say a default value for the label prop? So what I'm going to do is start here and I'm going to say in my render, I'm going to do destructuring again, which then lets me have a default value, which only kicks in if the props, this doesn't have a label. Otherwise the thing that's passed in is used. And so then I need to do this. I'll just get my cover here. Now when I save, run my tests, all my tests pass and I have a default value for the count. And so again, using the locals for render, let me take a look over here and say. All right, Lexi has used data test ID. Lexi, when you use it, do you always have the feeling that I'm doing something wrong that should be done a better way? Elaina, I think there were answers to your question about the localizing. And Adam gives a response front, but this tutorial is not about accessibility and localizing. All right, thank you, Elaina. Okay, now we need to wire in the UI. It's not actually in our application yet because our parent component isn't using the counter. So we need the parent component to use the counter. I'm gonna go to app.tsx, and I'm going to add it just after this. Do I need to stop and go to the top, and add by import, and then come back where I was, try to remember where I was, try to remember what I was doing? No, IDEs these days, TypeScript Language Service can automate all this for us. So I want to result in a counter with that label. I can just start typing. And it's looked in my project, it's already indexed my project actually, so it knows where all the bodies are buried, and I can just choose counter. It knows the props, so I can just use label, and I will say, what's my current? So it generated the import for me when I did the autocomplete. So we're in good shape. We now have something using our counter, but our test didn't break because the app test didn't really even expect that to be there. We should have written a test first before we added this. All right, let's do that. So my test pass, but I want to test in app to see if the label is in. I'm only going to see if the component is in there, not every single thing about the component, the sub-component, because it's not really necessary. So they rendered in. Oh, I'll just take the whole thing and cut and paste it. It's doing a better job of testing, anyway. So this is the top level app. We want to see whether that text is in there. We want to see if our component counter is in there. And so we're going to do the same thing we just had in our counter test. This thing we want. Really, that's all I did was I cut and pasted this to here. It's failing because I went back in time and pretended that I did TDD and I haven't put it in yet. So now when I put it in, I say, did I implement this correctly? Well, sure I did.
21. Implementing State in Counter Component
My tests passed, proving that my counter class component is in the parent app component. Let's take a look at it in the browser. The counter component is styled poorly, but we'll address that in the next part. We have one hour left, so let's stop for questions. We discuss testing child components and the use of selectors. There's also mention of visual testing and the use of Cypress. We switch from a functional component to a class-based component to have easy local state. We start with a failing test and implement the counter component. The test fails because the counter does not start at zero. We proceed to implement the state in the class component.
Because my tests passed. Yay. So now I have a test that proves my counter class component is in the parent app component. That's good news. We are all good so far. And I think that's a typo. No, no, no, it's not a typo. It's encouraging me at long last. Can we finally take a look at what it looks like in the browser? So I'm going to go back to my start script. Fire it up. It's going to generate the browser or generate the bundle dev server, et cetera. And I actually see the counter component styled poorly because it's two spans, showing current and one. All right, I will go get started for the next part, stop, take some questions, take a look at time. And we have one hour left. We're going to run out of time. OK, lots of plus ones for storybook. Yay. Alexei is typing in this Discord. So I'll go back over to the Zoom chat. Suzanne, hopefully I got it right. That's not Suzanne. Correctly poking me about not putting a test first. You were right. Should have done a test first. Let's see. All right, we're up to date on that. Alexei is asking, write an integration test first to make sure the app is using Counter. I think that's similar to what Suzanne was poking me about, that I should have done that first before pasting it in. I wonder if I did it right in my text. Let's see. My text, nope, I didn't. My text broke the rules. I should swap that and that and put the test first. Note to self, I will never remember that note. Let's see what else we got. Get by title is expecting two to three arguments. You got it working. What was it, Dylan? What was it that went wrong with it? Alexi is right, that now that I've got kind of an integrated test, if I change the inner structure of counter, then the app test will break and the counter test will break. And so the question of parent components with child components, should you test the structure of the child components or should you just see if they are in the document? Alexi, am I saying correctly the point you're making? It's really a question of, yeah. So there you go. Yeah, I guess what you would do for that, Is there React testing library selector that says a component is in a tree? I guess there wouldn't be. What you would wind up doing is on the counter, you would put something on here that said, hey, I'm class name, title, or some selector that was visible. Data test. Ha ha, here we go, yeah, data test. Let's see. I restructured get by title from the thing. Oh, yeah, OK. Destructuring bit you, huh? All right, did you get any warning from the TypeScript Language Service, Dillon, when you did the destructuring wrong? Should you have? Oh, good, all right. You got red squiggled. You failed faster. Great. All right, some comments over in Discord. Visual testing, I'm interested in something like that as well. Kind of like that I've seen some things where they can snapshot essentially the pixels of a page and then compare later and see if your CSS layout changed. I wonder if you're talking about something like that. I believe it's Florian but also mentions that you can do some of the computed properties to see if things are in the position that they think they are. I suspect that's a Cypress thing, though it's not going to be a JS DOM thing. Cypress does that, June says. All roads lead to Cypress, right? All roads lead to infinite energy consumption when running your tests. All right, I'm going to move on and we're going to go back to this and why we switch from a functional component to a class-based component so that we can have easy local state. In this case, account. We're going to make a very simple class component. It's going to have state. And then that state needs some typescriptification on it so that we get red squigglies and autocomplete. But it's going to get a little bit weird, which will then make you think, I'm going to go back to functional components and hooks. OK. Always start with a test. We're going to write a failing test first to the implementation, wired into the parent. Blah, blah, blah. We want counter and counter. So I've got counter over here. I want counter.test over here. And now I will shut you off. And just have my test runner. We're going to write a new test. This is going to be about the state, not about the presentation. And we want our counter to start at zero. So I will cut and paste this. And then save it, which makes it run. And it fails because we don't start at zero. We currently are at one. But that's not an actual stateful value. It's just the character on the screen. So this test failed correctly. Now we need to go into the implementation. We have a class base component. I'll move this out of the way for a second. I have a class base component which has a type definition for props. Maybe it needs a type definition for state. And what we're going to do this time, I don't know.
22. Managing Component State with TypeScript
I learned class-based components first and there's a place for local state. We added a second generic for the state alongside the prompts and put in some initial state as a class variable. However, immutability is a problem and we should use the set state method. We can use TypeScript to detect read-only assignments. We set a module scope value for the initial state and use the read-only prefix. We can now change the value of the state. Let's get back to having a starting value and implement it using a lifecycle method. If a prop was passed in, we call setState instead of manual assignment.
I could have done the same thing inlining it and then extracting it, but there's just something about state that makes me want to reason about it separately from the component implementation. And so I'll go ahead and type this out. I'm going to go make a new type. I'm going to call it CounterState. And it's going to have, what did I call that value? Count. That's a number. And the IDE is telling me you're not using that yet. I know that. And where do I put this in my CLASS statement inside the generic? And that lets me then say the first argument to the generic is the prop information. The second argument to the generic is the state information. In fact, look at that. The pop up tells us with P and S, the ever helpful P and the ever helpful S. That is the order of the arguments inside the generic. June, I'm OK with class-based components, probably because I learned them first, and the world of Python isn't as big on functional programming as the front-end world has gotten. But I mean, there's a place for local state, local components state. So now I've got the type information correct. I need to get the actual state. And so I'm going to do this in iterations and learn along the way about some mistakes. I'll be interested to see if what I call the best way is wrong, if there's a bester way these days because things always change. I'm inside the class now. And I'm going to add some like a class attribute field thingy. I'm going to give it type information and say that the state is of type this, and here's the initial value. So that's good. And then that let's me do this. So I will replace the one with this dot state dot, look at that, autocomplete, yay! All right. I'll save, let my tests rerun. Look at that, it went green and I got a little pop up on my desktop saying that my tests pass. So I now have a stateful component that internally decides that it starts at zero. I am so happy that y'all are discussing it with each other about the place of class components versus functional components. I could participate, but I would probably get it wrong because it's very much a style thing. So we added a second generic for the state alongside the prompts and we put in some initial state as a class variable, which gave us some benefits. But as you know the big problem with this is immutability, you're not supposed to just assign to that object, you're supposed to use the set state method to get there. What if you don't? What if you're like this.state.count plus equal one? Wouldn't you like it if the compiler could red squiggle that? If TypeScript could detect that something was read only and you were assigning to it? You can do it, and so we're going to do it. We're going to replace our type definition with this. We're going to set a module scope value for the initial state with its values. And I'm going to do this weirdo type definition. We had counterstate before. We see it here. And so what it's saying is it's using read only as the type. That's a built in keyword in TypeScript. That's why it's not imported. And in the generic, we're going to say that the shape of this thing that is read only is this. And so once we do that, we need to use initial state now instead of our kind of manual definition. So we're going to change it to also use the read only. Prefix, so read only. And now if I wanted to do something that changed the value, we'll see in a second that we can now I'll go into it now. What if I wanted to say in here this state count? Equals nine, look at that. Awesome. Anyway, back to what we're supposed to be doing, which is incrementing the count. I'll pause there and look over here. That's wonderful. Yeah. That's a good point, Elena. That the opposite problem. that's funny. It's rich. Actually, I think I agree with you more than the position of who was it that was saying the opposite. Right? What was that? June. OK. So let's get back to having a starting value. So the outside world can tell, hey, go make me a counter but use this as the starting value, change in behavior, change in promises and contract means a new test, right? I'm going to take this test. Go back to counter. Hey, red squiggles for the win, I'm breaking the contract. Of course I'm breaking the contract. There is no start prop. All right, and we'll save it so the test will run. Test fails because of 10 not being the value, but TypeScript fails because start isn't a prop. So we'll fix the type definition and counter also allow, I'll type it. You wanna start? Alright, so now the red squiggle went away. The test is still gonna fail because I haven't implemented starting point yet. How do I want to implement starting point? Things get tricky here a little bit. Read only. Can't plop this in in the beginning. So I'm gonna use a life cycle method, and in this life cycle method, I will then have access to the props, the passed in value. And from that, I can get a starting point. So in componentDidMount, I have access to props. So I'll come over here, add that method. It's run once. If a prop was passed in, if I have a prop, I'm gonna call setState this time, rather than just doing the manual assignment. I will save, see if my tests run. And my tests all ran. Let's make sure that they actually ran, that it ran all screen. All right. Starting point. So I've done something on the starting point, which didn't work. I passed in start as a prop. If props.start, if props.startState. I wonder if this is because the test doesn't have access to lifecycle level. Can't be. All right.
23. Handling Clicks to Increment Counter
We fixed the issue with the test not running the componentMount lifecycle. Now we need to wire the counter component into the UI. We have a counter component that can be passed props and state, is configurable from the outside, and keeps track of counts. We discuss the importance of being specific in a component's contract. We move on to the next part, where we will handle clicks to increment the counter and simulate clicks in testing.
I will put in a debugger statement. Why didn't I put read only count number? So Matt, I was trying to model the entire state instead of just the count. I could have done, you're right, I could have had just the count. The idea being later, I might add other things to the state. But you actually have a good point. You should be as specific as possible and not try to adhere to an infinite contract. All right, so I'm starting at zero. This.props.startzero. So I should let's see. Okay. You might see my problem. All right. This.props.start should evaluate to be true. So I am setting state, and I guess this is just a case in my test. I'm not actually doing the componentMount lifecycle. All right. Note to self, I'm fixing that. Maybe Angela's about to give me the correct answer on this. All right. Now we've got to do the third step. We talked about all three steps. We've written a failing test. We did an implementation. Now we need to go to the parent and wire it into the UI. So I will start with app.test.tsx. I'm just doing all three things in one big jumbo test. Probably not the smartest thing to do. All right. This will run. And I don't actually need to do anything in the code because I was including the subcomponent, and I was peeking into the subcomponent. Oh. I think it is the F for Florian. I'll guess and say it is. I just happened to choose something that was still going to be in the document. Oh, you dummy. So if I would have said 99, it would have failed. Because 110 still has one zero in it. I'm tired. Maybe that's what I'll blame it on. OK. So fixed, and we have a counter component that can be passprops, passstate, is configurable from the outside. You can give it not just the label, but you can give it the starting point, and it will keep track of counts. And we've got that all wrapped into type information, which does some kind of attempt at mimicking read-only. And I will agree with I can't remember who it was that said it. I will agree with you that instead of modeling anything possible, I should be more specific in, say, what is this component's contract. Good job. Is it Florian? Is that what the F stands for? Or am I projecting? Frank. OK, sorry. All right. Karlsruhe, right? Do I remember that correctly? Good. All right. Onward. On to some fun stuff. And you can see, we're getting close to the end of the movie, and we're doing pretty well on time. Before I go into this, as a note, things are about to get real. So let's take a little pause. Any questions? Any advice on rewriting this tutorial if I do so in the future? Any things you've seen presented that you've got your own ideas about? usehooks.com, oh, that looks like an interesting workshop. I'm going to go ahead and click on that link, Suzanne. Thanks. OK. No points. We will go ahead and continue. We have a counter. It keeps track of nothing. So we have no way to increment it, except for a test. We haven't wired it into any event handling. Let's add to our counter component handling clicks to increment and show how we're going to model this in TypeScript and then how we're going to work with this and simulate clicks in testing. This one's a fun one. I'll also be interested to see if some of you pros out there have a good latest and greatest set of suggestions. So we're going to do the same old, same old. We're going to write tests, going to get squiggles. We're going to do our implementation, et cetera. This time, though, we're actually going to fire up a browser at the end and do some clicking. I'll take this moment to note how far we've gone without really looking at a browser. Isn't that cool? We can do React development without type type type, tab to a browser, hit reload, click the universe, go to the console, console, lock some things, go back to your editor and type type type. Oh, God. Just killing me. We're going to write a first failing test encounter. And this is going to be a incrementer, an event clicker thingy. And you'll see, we're going to get another import from testing library, fire event. That looks sexy. So I'm going to copy and paste this, go back over to counter, hide this, and add a new test. I will need an import. So hey, thank you IDE. Go do that import for me. I'll optimize import free format code like Pavlov's dog. And what's happening here is I'm going to write a test for the starting point of the counter. And in this case, I'm looking at this thing. It's matching on this attribute title, current count. I'm getting its value, its text content.
24. Implementing Event Handling in Counter Component
I wanted to simulate clicking on an element to go from 0 to 1. The test failed because the event handler was not implemented. We need an on-click handler in the counter component. We wrote failing tests and implemented the on-click handler using an arrow function. However, this approach is discouraged due to frequent recompilation. We moved the arrow function to a class method for better test isolation. The onClick handler was modeled correctly with the event passed in. The tests passed, demonstrating the benefits of doing it the right way.
And I wanted to go from 0 to 1, and I want to do that by simulating clicking on that element. So let's walk through this a little bit. I've got a counter component. And I'm going to render it. And I'm going to extract some closures that let me peek at it in rich and interesting ways, such as finding elements that match a title. So I'm going to go find an element which matches the title. Let me mouse over this. It is of type HTML element. That's what's returned by GetByTitle. And then I'm going to fire an event on it, the click event, I'm going to fire on that element, that HTML element that I located. And then I'm going to assert, hey, you incremented now. So we're good. All right? So we walk through what all that does. And look, it failed, obviously. Because it's still zero. The element is still zero. It didn't, firing the event on it had no effect, because we haven't done an event handler. User event, then fire event. I don't know. Alexei, how about this? Just tell me, tell me that's correct, and I will believe you. I will open a tab. React. React, no, just testing library, and you're saying user event. Are you saying it's more specific, and it better matches the actual TypeScript type that is being used? I see user event and good docs for it. It's a more advanced, here we go, it's a more advanced simulation of browser interactions than Fire event. Today's winner goes to Alexei for getting it right. We have two Alexeis, so Alexei with a Y. OK, which means I have to change my tutorial again. Wait till React 25. We need a handler, an on-click handler, because the component doesn't handle clicks. Let's go do our implementation. We wrote our failing tests. Let's make the test pass. So I'm going to go over to my counter here. I probably want it on the span for the number. I guess I could put it on the div, but I'll put it on the span for the number. I'm going to get it to say this for now. It's going to be an arrow function, and it's going to grab this and call setState. But this is a little bit problematic. My test now passes, but this is problematic because you're discouraged from putting arrow function definitions as event handlers. Why? Because all of this is going to get reinterpreted and recompiled whenever this thing is re-rendered. It's running in the render cycle. It might be 60 times the second that it's redoing all of this compilation. So we want to move it out of the event handler. And I'm going to put it into kind of a class method. And that also helps me do test isolation. I can test the counting of something without needing to go through a render. And then this onClick handler can just say this. For those of you that are about to complain to me, that's the point. I'm walking through variations of this to get to the right thing. And obviously, I can do auto-complete. All right, when I save that, I'm getting my test paths. And what I want to point out is that I think I actually said method. This isn't actually a method. If it was a method, we would get into the problem of this. This is actually a field, or property, or attribute, or whatever you want to call it, that's an arrow function, which then gets the binding of this correct so that it isn't tied to an event as this. The component is this. But it is still getting the event passed in. We're not using it, and it's going to be the this isn't the event, but this is the component. We are, though, getting an event passed it. So let's model that correctly. And then it'll get mad because it says it's any. And so, OK, I will just shut you up, TypeScript compiler. Now you're happy, aren't you? Well, we still get some warnings about an unused event, we'll get to that in a second. But if my tsconfig.json turns off the ability to have any, I'll get some complaints. So I'm cheating by saying any. I'm just shutting up the compiler. Let's do it the right way. And let's prove that doing the right way has its benefits. That type information can show us problems. OK, and I'm going to get back over here to having my, yep, the Discord open. All right. My first stab at it is going to say that it's a mouse event. And a mouse event is a generic for the kind of thing that was clicked. So I'm going to say that. Right, good. And then I'm going to start the process of using this information by saying what we want to eventually get to is did you press Shift Click? If so, we're going to increment by 10. And that's why we want to get access to the event is we want to handle the Shift Click usage. So I'm going to come over. I'm going to start the process of making some mistakes. All right? So this is my first attempt at it. And I'll save. See what happens with the tests running. Tests failed because it doesn't have the right answer in it. Something is gone wrong. What went wrong? Hmm. By the way, the end of the story is I always get the ternary wall. Can typing help me see when I got the ternary wrong? OK, I can't do a plus on a number or number in Boolean. So this can be either a Boolean or a number. Why is that? I'm saying one and I'm saying 10 here.
25. Refactoring and Handling Shift Click Test
We set the type explicitly to eliminate the squiggle. We realized the order of the ternary was wrong and corrected it. TypeScript helped us along the way by providing autocomplete and type information. The tests passed, and we now have a shift clickable counter. We need to handle the test for shift click. We discuss the use of user event and fire event in testing library. We decide to use fire event as the better option. We run the import manually and focus on the task at hand.
It's a number. It can't be a Boolean. So I'll go on to the next stab at this. TypeScript told us the problem. Let's set the type explicitly and say, ha, I know better than you. I'll shut you up and say you're a number. Well, that red squiggle went away. But that wasn't our goal. Our goal wasn't to move the squiggle. Our goal was to eliminate the squiggle. What are you mad about now? Same thing, it thinks the right hand side of the equal can be either a number or a boolean. So let's keep looking at this a little bit more. And we finally realize that I've got the order of the ternary wrong. It's if this, then that, otherwise that. And TypeScript helped flag me the whole way because I decided to take the extra step and put event information, type information, on the event. It was able to help me autocomplete. It was able to tell me that that evaluates to a boolean, all of that stuff. And June is correct. It squiggles all the way down, right? The typo, Shift key is Boolean. It just says, you see where it says Boolean at the end here. It just says whether shift was pressed or not. For this event was shift pressed. Alexei, does that answer the question? All right, cool. All right, with that in mind, I will save and see what happens. My tests pass. All right, I have a shift clickable counter. Yay. Do you see any shift in my test? No, so we need to handle the test for that. Advanced by 10 was shift click. Testing library has some event firing. I wonder if this is even true anymore. Is user event bundled? Whoever it was that told me about user event. Oh, Alexei. Is it bundled, or I still have to do this? I'm going to presume I still have to do this. I only thought I wanted user event for cases where I couldn't use fire event. It appears like fire event is the better thing to do at all times. Oh, look. Yeah, yarn. I should've typed yarn just then. OK, while you're running, I will type the import manually on this so that we can focus a little bit as we do this.
26. Testing Increment Counter and Simulating Event
27. Refactoring Counter Component and Testing
In this step, we refactor the counter component to remove its state and logic about event handling. The parent component will handle these responsibilities and pass them as props to the counter. We also discuss the testing strategy and modeling in TypeScript. The tests are modified to accommodate the changes, and TypeScript issues are resolved. We are now ready to proceed with the final step.
All right, that's an interesting point about extracting into custom hooks and easier testing. Some of the things that we're doing in this workshop do a little bit extra work now to give you a level of granularity that's easy to test just that thing, easy to modify and refactor in the future. And that's a good example, Andre, of doing a little bit extra work now to create a custom hook. Because then I can just test that damn thing and it's packaged up a set of decisions and the outside world doesn't have to know anything about it. Usually we do that for components with child components. It's neat doing that with state as well so that little parts of your global state can be treated logically different.
OK, we are getting to the end, the last step in the tutorial. Before I do, I will pause for a moment and see if we have any questions or comments. All right, we will continue. What we're going to do in this step is refactor this to be the way you're supposed to do it for presentation components, child components, or container components and DOM components. And what we want is the counter to get a lot dumber. It shouldn't keep track of its state, and it shouldn't really have the logic about what to do on the event. The parent should do that and pass it in and make it available to the child. What we want to do is see a testing strategy for this as we go through the iterations of refactoring, and we also want to see how to model this in TypeScript information.
OK, we will start with the counter state. We're going to remove the state from the counter component, and if we're going to remove the state from the counter component, we're probably going to want to turn it back into a functional component. So let's start by making this be the props where I remove count since passing a starting point won't matter anymore since it isn't keeping track of the count. So I'll come over to my counter and here, the start I will get rid of. And then I'm going to change the counter component itself to be a functional component. I'm going to leave in this thing about the initial state now because I'm going to have to go put that somewhere else later and I should have it around so I can reason about it. And let's see. Oh, no. I need to add count. That's right. See, I got red squiggled. Count is now a prop, which is being managed by my parent and passed into me. And as it changes in the parent, I will get it repassed as a prop and rerendered and all that stuff.
Now, our tests, though, we've got compiler problems in our tests because we have a contract that's broken. The count is required, and the counter increase is required. So what I need is, let me see. The first two pass, and the second two fail. So we're going to fix these two tests because we're not really testing click handling right now. We don't care about the clicking. There just needs to be something there. We're going to make a fake click handler. And we're going to pass it in, along with an initial count, as the two props that are currently maxing out. That's what we're currently missing. So now TypeScript is happy on that one. Let's see. I'll just cut and paste the whole thing. I think I got a stray something because of... Oh, no. Sorry. I'm supposed to be fixing the one above. Yeah. These are the ones that the tests are passing, but it's TypeScript that's mad. So what I'll do is I'll go back and do this again. TypeScript is mad because I'm passing account but I'm not passing in a handler. Let's make a mock. And then I can use that as the. Handler and now TypeScript is happy on that one. I'll do the same thing here. And so the tests will run. And these two tests pass again and they have no TypeScript problem. Let me go see what Alexey is saying about makes it hard to. Alexey, when you say definitely makes it harder to test React components, which way makes it harder? Hooks, the new way or the old way of presentation trial. All right. Got it. OK, so we are in good shape with those two tests, and we got about five minutes.
28. Handling Clicks to Increment Counter
We fixed the issue with the test not running the componentMount lifecycle. Now we need to wire the counter component into the UI. We have a counter component that can be passed props and state, is configurable from the outside, and keeps track of counts. We discuss the importance of being specific in a component's contract. We move on to the next part, where we will handle clicks to increment the counter and simulate clicks in testing.
The count is required, and the counter increase is required. So what I need is, let me see. The first two pass, and the second two fail. So we're going to fix these two tests because we're not really testing click handling right now. We don't care about the clicking. There just needs to be something there. We're going to make a fake click handler. And we're going to pass it in, along with an initial count, as the two props that are currently maxing out. That's what we're currently missing. So now TypeScript is happy on that one. Let's see. I'll just cut and paste the whole thing. I think I got a stray something because of... Oh, no. Sorry. I'm supposed to be fixing the one above. Yeah. These are the ones that the tests are passing, but it's TypeScript that's mad. So what I'll do is I'll go back and do this again. TypeScript is mad because I'm passing account but I'm not passing in a handler. Let's make a mock. And then I can use that as the. Handler and now TypeScript is happy on that one. I'll do the same thing here. And so the tests will run. And these two tests pass again and they have no TypeScript problem. Let me go see what Alexey is saying about makes it hard to. Alexey, when you say definitely makes it harder to test React components, which way makes it harder? Hooks, the new way or the old way of presentation trial. All right. Got it. OK, so we are in good shape with those two tests, and we got about five minutes. So what I will do in the rest of this, instead of typing it in, I'll just talk through it and then we'll wrap up. Event handling is a little trickier because sure, you're done. Presentational child component isn't going to be doing the work. But we at least want to see if the function was called and was it called correctly. So what we're going to do in this case is change the third test. We're going to delete the last test. We're going to make a handler. We're going to pass it in. We're going to do the clicking. And then this handler thing, we're going to be to call an assertion on it. To make sure it got called, did my component call the function when it was clicked. Pretty smart, easy concept of the contract. But how do I write a test for it like this? I make a mock. I use that mock or spy is the thing passed into the DOM component. Do all the work and then look at it and say, hey, spy, did you get called correctly? That's really easy. And when combined with fire event and user event and stuff like that, it's a really nice I mean, how else would you do it? You go to the browser. Click the universe, see if everything worked correctly. We can make the DOM component a little bit smarter because it's having its interface between the parent and the child is expressing some things. That could be moved maybe a little bit to the child. What we have now is the encounter increase function passes the entire event. But we know that the child doesn't care about the entire event. It's only interested in shift. Click. So we're going to say, hey, call me with an argument about whether shift was pressed. So that's the first change. And then in the implementation, we're going to make a callable. Which then does the counter increase with the value of the shift key, and then that will be the handler used by the child. Because the parent has access to the entire event. We're not going to make the child have access to the entire event. I'm sorry, I'm in the child. Sorry, so I've got this handle click function that is doing that. Then we can go back up to the container component, sorry, the test is now written to be able to look at just that one thing about false. Because that was what the handler had. And then just to wrap this up a little bit, we can go up to the parent component component. I said that we were going to leave these lines around in the counter. That's so that we can copy and paste them up into the parent where the contract is. And let's see. I think, yeah, I need to change that. It's no longer a class component. Then on the parent, we're going to do an increment function that gets passed in, and this is where we get the whole. I was like, this is the thing that's called by the child, and it's going to be passed back up. The shift information, which we then use. We don't have to parse an event. So going through all this, we can write tests that does everything for the app state that includes some clicking on the counter component. Now, I will start the process of wrapping up, taking any comments and things like this. I would like to point out something. I said it a couple of times, but I'd like to end with it. We almost never looked. At the app in the browser, we were able to do all of this work, whether it was rendering, whether it was props, whether it was state, whether it was event handlers, all of this stuff we were able to do, staying in our tools, staying in the flow, being able to debug, getting good trace facts, click ability, refactoring all these other things and that ability to stay in the flow and work methodically and not feel like you're overwhelmed. That is a really good feeling for development. You're working with confidence. You know that because of tests, you know that everything is working correctly, but because the tests, you also get to focus on the problem. So I'll stop there for a moment. Let's go ahead and wrap up any input, any questions, any feedback, any observations about your feelings about testing, maybe even about TypeScript as well. So I'll look through some of the comments in in the chat. I will have to keep an eye on the impact of hooks on the way people are splitting components and about writing tests and stuff like that. So, June, thanks for bringing that up. Alexei, the TypeScript in the last two years. You're right, I follow the TypeScript Roadmap.
29. Project Management and IDE Integration
They do a great job running the project and keeping the roadmap up to date. They're into type theory now and trying to move huge parts. TypeScript is mentioned as well. The licenses for WebSR and IntelliJ are separate, but there's an all products pack for access to all IDs. The calmness and discipline of staying in the IDE during development are appreciated. Dylan's comment is acknowledged, and the speaker expresses interest in learning from them. June's point is mentioned, but the speaker is unsure of its significance.
They do a great job running that project and they do a great job of keeping their roadmap up to date. And sometimes they have a bullet on, you know, what's coming or what just got implemented. And they're using words that I don't understand because they're like really into type theory now. They're really trying to move huge parts. A framework development can be expressible in types type information. TypeScript is evil. And unfortunately, the license for WebSR and license for IntelliJ are separate, we do have something called the all products pack, which lets you get access to all of our IDs.
And Alexa, your point about not leaving the IDE. Do you feel like this is a way of development that you would like? When I can have the discipline to stay in this mode, It's just so calm. I don't feel frantic. Maybe that's not the right way to put it.
Yep. Well, thank you, Dylan. I appreciate that. Maybe I'll see a presentation by you one day and I'll learn some stuff from you. All right. I think this is most of the comments. June, what you're saying really is, the thing that got me into this is... I don't know.