 So this session is on test driving React.js code. Again, it's a fancy title. I didn't know how many people in the audience would expect what, so it's kind of pretty open. We'll figure out what's the best to do as we go along. It's only a 45-minute session. This is typically a 90-minute session where we actually do live programming, but this time I don't think we'll have enough time to do live programming, so I'll mostly kind of walk you through some of the things that I've done. But just kind of to get a feel of who's in the room, let's start with some basic stuff here. How many people do object-oriented programming here? Most people. All right, what about the rest of you who didn't put up your hands? Too busy on your phones? So the folks who do object-oriented programming, probably a lot of, at least my initial career with object orientation was about trying to model the real world, right? To me, object orientation was about how can I model the real world in this thing? And so, you know, you would have stuff like this drawn all over with UMLs and stuff like that. And soon we kind of started getting into things like this where we had different kinds of stuff, so you started having these hierarchy of objects, and you know, you start deriving one object from another object, mostly to reuse code, and you know, less so much in terms of this is structurally how things should be structured and stuff like that. And the next thing you know is your project has kind of grown into some mess like this. Does this sound familiar? Yeah? All right, then I'm in the right room. Or you're in the right room. A few years ago, I used to work for a medical company, and we were building some software to automate a whole bunch of stuff that happens at a hospital. And I remember having this classic debate where, you know, a bunch of programmers were arguing. Basically, we had to figure out... we had patients, we had doctors. Patients basically, doctors give shots to the patients. And so, the classic debate was, you know, you have a patient object and you have a doctor object or a, you know, surgeon object. Would the doctor object have a give-shot method or would the patient have a take-shot method? Where would you put this method? And you wouldn't believe you spent about two hours arguing about it. And in the end, we couldn't conclude what's the right approach. So... Sorry? How? The implementation was we had a clinic object which basically had a record-a-shot method. It doesn't matter who gave a shot to whom, whether the patient took the shot themselves or the doctor gave the shot. Doesn't matter, all we are interested in is we should be charging the patient for it. Right? So, you have all these classic debates and which is why I think OO, in general, gets a pretty bad name. And these days, it's not cool to do object orientation, right? Like, all the cool kids seems to be talking a lot about functional programming these days. So what I want to actually try and sneak in here in this particular demo here is kind of try and strike a balance between object orientation and functional programming and kind of see how TDD can help with that journey. And if you take something like React, I think it's a pretty nice balance of basically, you know, object orientation to a little bit and then a lot of functional thinking behind the scenes, which is kind of what we will build on top of in this particular session. And we're going to try and see how TDD can actually help with something like this. And again, with TDD, as we get into this session, we will see, for a lot of people, TDD is about testing. And to me, that's the last thing about TDD. It's actually a side effect, not the objective. So anyway, what we're going to try and achieve is I'm going to walk you through some basic setup, walk you through some code that we have, which is for basically building a simple commanding system, and then we're going to talk about some of the next steps. So Confingen is a platform that I've built. Some of you might have used. In Confingen, we have this feature where people can comment on proposals and stuff like that. And this whole section, essentially, is what I want to demonstrate how we can build this in a React style programming. Is everyone here familiar with test-driven development? Yep. Cool. Let's do a quick recap just for the benefit of others and then we will jump through. Thanks. So with test-driven development, the idea is we start with an automated test. Yes? We run the test. What do we expect to see? What happens if it passes? Sorry, what was that? What happens? We are screwed up. We are screwed up. Absolutely. Most often, it basically means that the test you wrote was wrong. Very few people actually do that step, and it's surprising because they would have written a whole bunch of code to realize the test was anyway passing before they started. So the idea is that the test should fail, and you make a little change to the code. What do we mean by little? Few seconds, few minutes' worth of change, not few days or years' worth of work. And then you run the test. If it fails, you continue to make a change. The goal is to get the test to pass. Yeah? And then once the test passes, what do we do? We look at, you know, basically, we started with the tests. We did a little bit of design as we coded along, but we didn't really do a deep thinking around the design. And at this point, we want to pause, stand back, reflect on what we just wrote. Is there a better way to design this? Do we see improvements in terms of simplicity, flexibility of communication of the code? And so we basically, you know, do some automated refactoring at this stage. Go back, run the test, because ideally you want to make sure that, you know, you refactor when you have passing tests, and once you're done with refactoring, your tests are still passing. And then you go back and repeat the cycle, right? That's in a nutshell what test-driven development is all about. I remember reading about this in 2001, and I actually fell off a chair laughing because I thought someone was joking. Like, how could you possibly write a test before you write any code? And it just seemed like a completely alien concept. But I think after four years of playing around with stuff, it finally kind of settled in, and I could get a sense of why test-driven development actually makes sense. And the last two years actually have not done any test-driven development, so it's kind of an interesting journey for me over the last 12 years or so, maybe more. But anyway, this section, we're going to look at, you know, this cycle of how we're going to actually do this on a React.js kind of a component. And, you know, especially when we talk about this, a lot of people these days say, this makes sense on the server side of things, and I know how to do it on the server side, but when it comes to UI code, let it be web UI or mobile UI, people have lots of challenges of how to actually do something like this. And I think there are a bunch of frameworks which actually make this relatively easier compared to others, and React is one of them, in my opinion. So all the code that I'm going to be showing is already up on GitHub. You can go get it from GitHub. You can basically clone this GitHub repo. It is essentially a demo of React with Karma, Jasmine, Webpack, Babel, ES6, you know, essentially to get you all of that stuff. So the idea is to kind of get this project, do an NPM update, and then you can do NPM run test, and you should see about the redo test in there passing. I'm going to quickly show a demo here and then kind of jump into what we are doing here. So let me mirror my screen. Already ran the test, so just kind of doing it in real quick. So a whole bunch of tests ran. Let's do it from here again real quick. You would actually see that it does bring up real browsers and runs the tests in the browsers, so you get the feedback. So notice it's brought up all these browsers here, which are essentially listening to the events that we are firing here, and it's run all the tests that we have written so far, and it kind of goes through that. So what I plan to do is spend some time kind of talking through how we've written the test, walk through, talk about some of the typical challenging scenarios and explain how you can actually cover those using tests. So it won't be so much of a live demo because we only have 45 minutes, but I want to do cover interesting things like how do you do stub-out Ajax calls, how do you do other kinds of things, because those are the notorious parts that get in the way of doing test-driven development on something like this. Is that cool? Let's quickly go back to the slides real quick. So quick commercial break. My name is Nareesh. I live in Mumbai. Don't act in Bollywood. I used to work for a company called Direct Eye. We built one of our business units for 900 million. I was a partner at a company called Industrial Logic with Joshua. We built e-learning for learning some of these skills. Changing programmers was really hard, so I decided to quit, and I started building another startup called Adventure Labs where we built games for kids to learn mental arithmetic that was far more fulfilling. I've been doing a whole bunch of conferences in India. I started the agile movement back in 2004. We continued to run the agile India conference. We also run a whole bunch of other conferences in India. Confinement, which is a platform that you might have used, is basically a pet project I keep building. I work at a company called Hype Messenger. We basically is a messaging app customized totally for Indian audience, mostly teenagers. We happen to be the fastest unicorn in India, 7 years to the billion-dollar status. So a lot of interesting learning, a lot of different kinds of startup environments I've worked in which makes me believe that a lot of stuff in agile is just bullshit. Sorry? Don't hold back. It will keep coming through all the long. So let's quickly jump and talk about basically the component that we want to build. This component I'm going to quickly describe what are the features and then we're going to start talking about how we're going to test drive this component. So a component should have ability to accept JSON comments from the server and basically display those comments. That's pretty standard. It should display the most popular, which is the one with the maximum likes on the top. What happens if two comments have the same number of likes? You have to handle that scenario. So if two comments have the same number of likes, then the most recent comment should show on the top. So you also have to take the time into account. There's also a feature of private comments, which are essentially comments. You can think of private or draft comments, which are only visible to the author who's putting the comment. It's not visible to other people. In convention, it's a feature where essentially it's visible to the program committee, but nobody else. So let's say the speaker wants to leave a private message or someone else wants to leave a private message saying, this speaker is bullshit. Don't accept the speaker. So then they leave a private comment. They don't leave a public comment. People should be able to like comments, stuff like that. The one other thing is this Ajax call that refreshes the comments every few seconds, few minutes kind of stuff. So this is kind of what we want to build as a feature set. So what I want you to do is I want you to take, like, five minutes, quickly think about how would you take this kind of a problem and break it down to incrementally build it out, right? To me, the first step of TDD, which is, I think, very few people actually talk about it, is how do you basically take a problem down, get to the essence of it, and then incrementally build out the problem. Like, that's the first step, honestly, in kind of test driving anything and probably the most important step. So what I want you to do is take, like, five minutes and think about, given this problem, how would you actually break it down? And then we will walk through my solution and we will compare notes, yeah? So it's not all sitting here eating popcorns and watching movies. It's a little bit of work as well. Everyone can read what's on the screen, right? They want me to increase the brightness. I can actually do that real quick. So the first one is basically you should accept JSON commands as a JSON format from an HX call from the server. So call the server, get the JSON commands. The most popular one is basically how you're going to sort the array and then what's visible, what's not visible, and then the liking functionality people should be able to like stuff, okay? Anyone wants to go first? What would be the first tests that we would write? Accepting the JSON. So would you call the server and get the JSON back? Or would you basically assume that you've got the server returning the JSON back? And then you feed in the JSON and see what happens, okay? Anyone else like any other approach that you can think of? So he said he would essentially mock out the server, get the JSON, and basically feed in the JSON and see if the commands show up. Can you think of a simpler, smaller step to get started with? So instead of trying to stub out the server and all of that, you would just feed in a stubbed out version of the JSON and see if it'll show up, okay? That's a slight improvement. Can we simplify it further? Does this seal steam like a pretty big jump to me? Sorry? Okay. It's possible that pages might not have any commands. So if you had nothing that came back from the server, if you had an empty JSON, then what happens? Is there some kind of a behavior that's expected on the page? That's a decent starting point, yeah? So you look for basically an empty condition in some cases when you're doing something like this, and you see if the empty condition essentially helps you move forward in the right direction, right? But simplifies reduces the number of things you have to deal with. So it allows you to take a smaller baby step to get kind of started with. Making sense? So shall we look at how that test would look? I'm going to later kind of walk you through and explain some of the stuff that's happening here. But let's kind of start here first. So this says should give a nice message when there are no commands. So let's look at what that looks like. So basically saying mount this commands component that we have and pass in an empty array, right? Because there are no commands in this. And then you would expect commands.find a div empty to be present, and a div empty to have text be the first one to comment. Does this make sense? We'll talk about what those some strange-looking things over there are, but that's kind of our first test that we would write. So now let's kind of step back and talk about what's going on here. So, I mean, JSON, this basically comments component is our React component that we have built, which accepts commands. We passed it empty. And we're using a library called Enzyme. What Enzyme does is it basically allows you to, you can pass in a React component to it. It basically renders it without actually, you know, without, it kind of renders it, simulates it, and gives you handle to what was rendered. And then it gives you access on top of it where you can do more like if you're used to the jQuery-style querying, you can do kind of jQuery-style querying of the DOM in memory DOM by allowing you to do basically things like comments.find, and you can give things that you want to find, selectors basically, and then say, what do you expect to happen? So I've used here, in this particular thing, I've used Enzyme, and then I have used something called... Let's blow this up. There's a plug-in for Jasmine called... Jasmine Enzyme, which allows you to basically write these two present, two have kind of expectations on top of this. So this would be our first test that we would write, and then basically let's jump to our component here real quick. So essentially, if we wrote this from scratch, all you would do is you would check if it's empty, then you would return an empty component with the message saying to be the first person to comment or something like that. Yeah? So once this is done, what's the next test that you're going to write? So we've got the empty condition handled, right? I want to talk through some scenarios, and then I'm going to jump in and talk about some of the plumbing that we have done and stuff like that. That might be helpful for people who want to go back and do this on your project. So once we've got basically the basic condition handled, the next thing that we want to look at is... We handled zero, now we want to do one, right? You pass in one comment, and then you want to handle that. Even with one comment, you don't want to take into account the sorting and the other kind of logic yet, right? You don't want to worry about the likes and other kinds of things. You just want to say, if I give a comment, does the comment actually get rendered correctly? Which basically means the comment has some kind of a header. If we go back here to our example, where was the page? Notice there's some header over here, and then the actual comment below there. So we want to basically figure out if it's actually rendering it in this particular format, right? So the next thing that we'll do is we're going to take a single comment, all right? And we're going to mount a single comment. A single comment is essentially just defined here, which has an id, a message, the user who did this. And when we originally start, we won't have this updated on or likes or whatever. We will incrementally add those later. But when we start, we will only start with basically the id, message, and the user. That's the JSON that we get back. So if we got that JSON back, we're going to do, again, same thing, commence component and pass the comment in there and see what all are the things we will see. We want to see that comment is present. The length is one. And it has a header, which basically has, you know, when you just spit out the text, it should have narration one like. And then actually, when we start, we won't even have the likes. This is over a period of time when we've evolved. And then it should have the first comment, which is what is the comment being passed here. Make sense? And then what is the code that we will write to make this, essentially, this test pass? We would have passed in the comments, which would essentially call commence.map and then create the component, comment component. At this stage, we will start seeing, okay, there will be many comments. So instead of trying to create each of these, we will actually spin off a comment component, which itself knows how to render a comment, right? With a header, which has the user, and then forget about the form right now. They would have the body, which basically has the message. Right? So this will help us basically flush this portion out and call the map method on it to simply spit it out. And that should get us the second test working. Right? I know it can be a little boring to just see code on the screen. Not much interactive. What I'm going to try and do is kind of engage you a little bit more, but I want to just explain some of the basic foundational stuff before we start getting into little bit more details around what's going on here. How many people here program in React, just so I know if it makes sense to you or not? One or two? Okay. Then this might not make a lot of sense to you, but I'll try my best to see if... So actually, let me kind of quickly step back and explain a little bit about React, so maybe it'll help you understand some basic concepts. So you can create a React component by simply extending the React component class. You give in a constructor. This is again ES6, so you're essentially writing more object-oriented style code. So it has a constructor, and then there is a render method, which basically gets called. And the render method should basically spit out the HTML that you want to print. That's the very simplistic way of looking at React. We'll talk a little bit about the... when does the render method called and stuff like that, which is what I think is the nice part about React is that it decouples yourself from having to maintain, you know, directly updating the DOM and stuff like that. It essentially takes care of that. What React has is a concept of state. So whenever the state gets updated, it essentially re-renders the component. And how it re-renders, when it re-renders, basically decouples the programmer from having to worry about those things. Essentially, what it does, which is very important on large, complicated websites, is essentially does a diff of the DOM and only takes the changes that have been applied and only refreshes those elements onto the actual browser. So it maintains something called as a virtual DOM in which it keeps maintaining the state of what's changed and basically applies the delta onto the actual browser DOM. So this way, you know, it basically reduces the jarring effect that you get on a lot of sites, and, you know, programmers have to really work carefully to change those things. It essentially decouples you from worrying about all of those. And at this point, essentially, what they're trying to do is they're trying to apply a bunch of functional transformations by looking at you change this. What is the delta of sequence of changes that happen and then basically work off a virtual DOM and apply those delta changes on the browser? So that's more of a functional style of thinking where you're essentially transforming the DOM from one state to another state in, you know, idempotent kind of a scenario without, you know, having to worry about kind of state changes and state management yourself. So that's a little bit of a background about React. I don't know if I've done justice to explaining React in two minutes, but any doubts? Like, let me pause and ask if people have any doubts or concerns so far. Like, do you get the basic idea behind React? Essentially, you have some state. You update the state. React itself handles the updating of the DOM for you. So you only have to worry about how you want this component to get rendered. The other thing is that the way information gets passed to these React components, there are two ways you can do that. One is through, you will see this, this.props. whatever. So this.props is one way of basically passing in values into the components. So in our case, if you see, we are essentially from here, when you say React component and you say comments over here, inside this, essentially, you would be saying props. Oops. So here we've got the comments. When you mount, you basically pull out the props, props comments, and then you use that to render the component for you. So the two ways, one is the state, this.state, the other is this.props. So in this case, the logged in user case, we're basically using the props. State is anything that actually reflects on the UI that changes the way the UI looks. So you basically store that in state. Things that don't actually affect the UI, you essentially keep it in props, and so you decouple the two that way and essentially manage the state of your components without having to worry about how to render the DOM, when to render the DOM. You simply spit out what HTML you want this to spit out and then your job is done. So this is a classic case of a React component where this has no state. The ideal way is actually not having any state using everything through the props. And essentially, like in this case, there is a callback handle, which when you click on like, callback the props, callback the parent component. So that's my two-minute explanation of React, which is terrible, but I'm not gonna try and do justice to explaining React in five minutes. I would try and assume that keep React as a black box if it's not making too much sense. Don't worry about that. Let's kind of talk through how you will progress through the tests and basically at least understand how we would approach this from a test-driven point of view, right? Would you prefer me switching to some other language or tool? Would that help you understand better? Since only two people understand React, it's a bit of a challenge to explain the whole React thing. Yeah, like what I wanted to actually do in this session was go more deep dive into some of the challenges around how you stub out things and how you do things, which obviously depends on how you're writing your React components and stuff like that. So a little bit of knowledge of React actually would help you appreciate some of this. If you don't quite understand React, maybe it's gonna be a challenge, but I'm happy to go with it. It's easier for me. All right, so we've got the one comment thing passing. What would you do next? So we started with zero comments, so let's assume you didn't get any comments. Notice, so far, we're not even calling the server. We are not interested in calling the server. We're just saying, assuming you've got the JSON, how do you render it? That's step number one. Step number two is assuming that you've got one comment. You want to basically make sure the header and the actual comment bodies displayed correctly, right? Which is what we are verifying over here, that the header and the comment body is shown correctly. What would be the next logical step for us? There are two parts we can go down. One is we can say that the ones with the maximum likes should show up on the top, right? The other part is we can say in the two comments, the most recent comment should show up on the top, right? The two kind of functionality that next we would build. So let's look at the, you know, it should display the most recent comment on the top. And in this case, essentially, we're going to pass in two, three JSONs in this case, three comments JSON, each one having an update time. And then what we'll essentially verify here is once you mount the component, you get back the DOM, then you are going to find out that if you pass in three elements, then the length of the comments div should be three. Essentially, all three comments should be displayed. The header of the first comment should be Jack in this case, because Jack is the one who commented the last, which is 20, 40, 12, 19, which is when I wrote this code. So it's been about two years now. And basically, the last comment should be the most, the oldest comment, which happens to be 2014, 06, 19, right? So this helps us understand that our code is essentially sorting based on the dates and displaying the most recent comment on the top. Right? Yep. We went from one to three and essentially the reason for jumping to, we could have done with two as well, but the reason to jump to three was essentially to see that it displays all three in the sorted order. So first and third is what we are kind of comparing. We could also do it with two. I mean, I think I'm not too hung up either ways. It's fine if we did with two. But three gives me a little bit, slightly a little bit more confidence that all three are actually sorted correctly. Right? And all we are asserting here was the first and the last and assuming the middle one is already there. So that way we kind of get all three validated. So how would you implement this in the code? There is... So if you actually see the structure of the code, we have... We've kind of split it into, you know, model and view. And we have a commence model, which essentially takes all the comments that we've got, constructs these little comment objects out of it, and then has a sort method on it, which essentially sorts based on a compare method. Right? And the actual compare method is in the actual... The smaller comment object that we have, which is essentially if likes are equal, then look at the last updated else return based on the likes. One could technically argue these specs that we are writing here. Where is the spec? The spec that we are writing here. Are these unit tests? What do you think? I wouldn't call them as unit tests. I have a new term for them to confuse people. I call them component tests. Sorry? That's what you would call them. It's more like a spec for this component, how this component behaves. Some people even might go to the extent of calling this as an acceptance test for the component, but this is not really a granular unit test. What would be a unit test in this case? A unit test would essentially be like you would take your model guy and you would test the sort method, for example. A test on the sort would be a unit test. Right? In this case, I have not really written unit tests for these individual components, because I think they're still at a stage where they're relatively simple, but once you start building a lot of logic into them, it would actually make sense to start unit testing them at this level, at the model level directly, instead of trying to test it through the view. Right? Right now, we're actually testing it via the view. So I would call the spec that we have written as a component spec, not necessarily as a unit test, and this is generally what people refer to as an outside-in way of doing test-driven development. So we're kind of doing an outside-in how a consumer would see this perspective, right? Business or user-facing kind of test. So I call these as component tests, or some people might call it acceptance test. I actually have something a little bit more higher for an acceptance test. This is still, like, to me, a component test. And the advantage I find with something like React is I can actually have these component tests, and that should be good enough. Once my component starts getting too complicated, the way I would have structured my code in terms of the models and the views, I could then go into the model and start unit testing the models, and so containing that logic over there and basically testing it out. So it still gives you a fairly good separation, and it gives you a nice way of basically testing at lower layers. When you need to, if you don't, then you just test it at the view layer, and that's good enough. Yeah, make sense? Again, test-driven development would, in my opinion, by itself not force you to do this. So, for example, I could have not separated the component, and I could have had all of that code in, but it's more of just good design thinking, design principles applying those and basically pulling out things into smaller pieces. And if you kind of keep that in mind, you would end up with code which is fairly decoupled, in my opinion, and things that can be nicely managed smaller chunks, and that's kind of typically what we try and push for is having code which is smaller chunks and pushed out, so they are individually manageable units. So we have comment and comments, and in the view we have, again, similarly, comments which essentially manages the rendering of the whole thing, and then rendering of each comment itself is separated out as a thing. So one is a collection, another one is an individual element. Five minutes, all right? Let's look at something a little bit more interesting. So we can go on and we can look at private comments and all of those use cases, but let's look at fetching data from a URL and displaying it, how you would actually do that because that's typically kind of interesting. So the one case is where you try to fetch something from the server, and essentially the server didn't return back on time or the server basically gave an error condition. So in Jasmine there is the spy on method, essentially we are stubbing out the Ajax call and returning a fake call which essentially is kind of a deferred or a promise which says if it's undefined then basically return an error, error getting this, else basically resolve it to a 400 status, and in this case because we are returning, we are basically rejecting this, what you will end up getting from here is essentially comments should be zero, there shouldn't be any comments, and there would be an error being shown saying fail to fetch comments from the URL. So the little trick here is essentially what we are doing is we are spying the Ajax method on jQuery, so under the hood we are essentially using jQuery for making Ajax call. So we are essentially stubbing that out if you will or we are faking out the Ajax call and we are simply returning a promise that would get resolved through, in this case it would basically error out saying please, you know, give a URL. In the passing case just let's look at that one to make a little bit of more sense. So here we are saying expected response is whatever earlier we were passing the JSON, so here we are saying this is the expected response from the Ajax call, and then we are saying Jasmine, Ajax, stub request call to get and return basically this 200 status with the actual stringified JSON that we want. So this is another way to essentially stub out requests on Ajax requests from Jasmine, so you would say jasmine.ajax.stub call and whatever URL that you are using, so in this case it's localhost slash react component slash commence.php or whatever, so you are basically stubbing out that call and returning whatever you want to return as a response. So when you run this test, jasmine essentially intercepts the call, the Ajax call, and returns whatever you have given here in the sub-call response directly. So this way when I now do mount this component, we do need to do a set timeout in this case because this is an asynchronous call, so we do need to do a set timeout and essentially call this. So this is not my favorite way of doing it. I just put both these cases to just demonstrate there are two ways of doing it. I kind of prefer this more spy and promise-based approach because here I don't need to put any sleep or anything, and this is like a more preferred way of doing asynchronous requests. So I don't know if I've done justice to this topic, but I've kind of tried to explain, like stubbing out the requests, how we would break this thing down into smaller tests. The other thing I quickly want to show you is some of the configuration or maybe since most of you are not from the React world, this might not make too much sense, but there is a bunch of plumbing that you need to do in Karma. So I'm right now running on all these browsers if you see the tests, essentially using Webpack to take this code and convert ES6 code, transpile it back to ES5, so it runs actually on the browser. So you have to do a bunch of that stuff here, and there's some dependencies on React that you need to call out. That essentially picks up the pre-processor, which is basically Webpack and source. And whenever you actually run these tests, I've also hooked up coverage with it, so you would actually be able to see the code coverage of what we are doing here. So that's also hooked up as part of this, and every time you run the test, it essentially gets the code coverage spit out as well. I'm not a big fan of code coverage. I only look at it as a way for me to see if I'm kind of missing something, but it's a lot of places I see code coverage gets used as a tool to measure how good someone's writing code, which is kind of absurd. And you can see that there's some portions of the code that are actually not fully tested as part of this. For example, the update command stuff, we've not written a test yet for it. So there is some more stuff to be done, so now this gives me feedback that, ah, I kind of missed this, so let me go write the test for it. All right, I think I'm out of time, but that was a quick walkthrough of test driving some react, even though you didn't really see me test drive, it was already test driven. But I did show you the difference between a spec and a unit test and why you would separate those out. The reason for having models and views and technically how you could run, react, how you could test drive the act code using this. All right, sorry you couldn't do much more than this, but happy to take any other questions you have. I know I'm out of time now, so I'm gonna step down, let the next speaker set up, and then be available for questions. Yep. All right, thank you.