Sessions is temporarily moving to YouTube, check out all our new videos here.

Ember Test Recorder

Nikos Katsikanis speaking at Ember London in May, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

Watch Nikos demo his Ember Test Recorder: it records your interaction with a web page, and generates code to test if things are visible or not.


- All right, ladies and gentlemen, thank you again for coming here. One of my friends asked me am I ready to give this talk. But then I asked him, I said, "That's not important, "are you ready to listen?" Does anyone like this picture? I think it looks pretty cool, doesn't it? - [Audience Member] Is that anywhere you know? - No idea, man. Okay, that's intermission with fat cat versus fox. Right okay, anyone here go to Ancient History? Or came to my last talk on this? One, two, three, okay. So, does anybody here like writing tests? Okay, you may leave now. So, I try to automate things that can be automated. Which is kinda the way the world's going with artificial intelligence and yadda, yadda, yadda. So back in the day, two years ago to be precise, I wrote this thing called the Ember Test Recorder, which records your interaction with the page. Basically back then, it was click events on various parts. And it would generate some code to test if things were visible or not. And it would also check for things like, if you write on an input, what did you write here, and if you changed root, it would change according to the test for that. Now, either this project was written so well that there's never been any issues with it, or no one's actually used it. But if you look at the stats for the add-on, I dunno what's going on because there's a lot of stuff here. And I haven't updated in two years so I should presume that there's some people downloading it or using it. But anyway, it was quite an interesting idea, this test recorder, but I realised that there wasn't really anything super specific about Ember that was doing under the hood. So what I decided to do was abstract it, so that it could be running for any framework. So what I've done now is I've taken the code out of Ember, and put it on another npm package. It supports something called Nightwatch now. Have you heard of Nightwatch? And it's also a plan support protector. So now let's move to this one here. A test recorder. I've also created the Discord channel that hopefully, we got some people using WinsDesk start using it. I've not actually used in production yet, to be honest, I have actually not done much Ember in like the last year or so anyway. 'Cause of you know, typescript, and vanilla and stuff like that. So I wrote all this stuff in typescript, I'll give you a quick demonstration of some of it in action. Now, I'll show you in a test application which I use to test the base inputs and stuff like that. And permutations of what it's doing. And then I'll show ya in a real Ember app, one I downloaded off the web, I think one, and see how it goes. I do have some videos up on YouTube, if you go to my Get Help page here. So this the app that I use to test various things like this. Before, it was basically a black rectangle and it sat on the bottom side of the page like this. But now, you can resize it. And it is a transparent background. And there's some little bit of UI here. Click on this tag, it tells you what version it is, it's a debug thing, you click on that and it outputs the state of the test recorder, which helps me. May help you, but I dunno. And there's basically a copy button, which copies the code to the clipboard. So, for example, if I just click on the body, it will click gen its code here for Ember. Nothing's actually happened so the and end statement is empty. You can clear this by just clicking this button here. So this is a button that, ya know, it could be an Ember app button or whatever. At the moment, its generating code for EMBER CLI. You can toggle it to Nightwatch, and it'll generate code for Nightwatch. But I think a few Ember guys will like Ember. So click on the Create a div. So what happen here is, because there's no ID on this, it generates the least complicated path to click on this. Then the app listens for changes on the page, and writes the test for it. If I click on this button which removes the text, you can see that uses the ID here, and it checks to see whether or not this element was removed. Miguel I had a talk with, he told me about this thing called, what was it again? - [Miguel] - Has anyone heard of that? So I'm gonna put that on the 2D list to support that. So that it finds that, then we'll use that as a selector. Text, blah, blah, blah, blah, blah. So what happens here is it fills in this input with this text here, and then it checks to see that there is text in this here. And because I clicked on the page, then it also registered another click here. And finally there is this one. And it generates the test for Ember to change the select input. So the idea is when I can be bothered to update this, I'll have more and more inputs and more different types of interactions and every interaction I will support the beta test stream work. I will show you some code in a minute, but first of all, we have an intermission! Who likes cat videos? - [Audience Member] I like fox videos. - Do you like cat and fox videos? So I actually recorded this in my backyard the other day. - [Audience Member] Any odds on who wins? - So that's the question, who thinks the fox'll win? I was a bit hesitant to this video actually. Five minutes before, there was a tree, and the cat was up the tree, and the fox was at the bottom of the tree. Now, the situation has changed, so what do you think happens? All right, here we go. - [Video] You win! Perfect! - All right, that's good, means you can concentrate for the next five minutes. So I've downloaded big Ember app. Okay let's clear this. And I just put my test recorder on it to see what would happen once I played around with the app. I'll just zoom out a little bit. Though, anyone seen a SAT before? It's something to do with Travis or something like that. It's a big Ember app. Let's click on stuff and see what happens. Branches, let's make sure it doesn't nagivate off the page here. Boom, except all this stuff happens here. Build History, pretty good. Nothing happened. More options. Settings. Okay, okay, something should've, I would have imagined something would have happened there. All right, there's nothing changing. - [Audience Member] It always happens when you want to show something to someone. - That's all right. Profile. All right. Click on this, now this would be a lot easier if you actually wrote the app. I would understand everything that's going on. I don't really understand. That's why I need you guys to use it. You know, 'cause I'm not gonna make an Ember app just to test this. I have a life. Just record something. Sync account. Anyway, let's jump into the code a little bit. Does anyone have a clue how I did this? So, the way it works is, I've actually simplified it from the last time. Basically, the UI, the little, this stuff here, there's like four listeners, and this is basically the app. The decoding app. Then I have the actual stuff that listens to what the user's doing. So for click events, I have a listener on the root here. And then I filter a bunch of stuff that I don't wanna listen to for clicks. Then there's ones for change, so like, selects and stuff like that. And there's also one to focus out. And then, as I add more and more, I'll just add more and more events. There's something called the current code generator, which is links to one of these instances of my Typescript interface, I just call them ICodeGenerator. And all the code generators, like the one for Ember, and the one for Nightwatch, they implement this interface. Which is really nice because if I wanna update all the interfaces, I can just change it here, I don't have to be forced to go and update it. Because it doesn't compile. The actual mutations... Before I was recursively adding mutations to everything in a sort of chi level, but then I discovered there's something in the config of a mutation observer called the subtree. Which then, it listens to anything if you just start it from the root. And also the mutation, when something changes like a, an attribute changes or an element's added, and then I have some generator stuff that gets put into the strings in the code generator. So that's basically all there is to it. There's a to-do. Donations, yeah Where does it stick that? Up at the top right, okay. So what I wanna do is, I removed the root think function out because I'm still thinking about that, how to write that. I wanna allow other inputs like Select To inputs. I can't remember what that was, but it was a good idea at the time. Create code for key-presses. - [Audience Member] Is that to write code of each individual keystroke? - No, I do that already. Oh yeah yeah, that's right, I do it on text inputs, but I suppose I could do it on keys that happen. It could listen to it no matter where it is, right? Key up, down. For the Nightwatch tests, we don't have the. There isn't the Ember knows when to write the test. The and then thing has this sort of, it just knows when to write the sessions. But the Nightwatch is a bit different. The only one I'm just paused 500 milliseconds in all this stuff. So that's where Ember wins hands down there, ya know. So you can see he's a bit different from the Ember tests. Nightwatch is pretty cool as well, it's framework, not agnostic. I was actually asking if the Ember testing thing could be abstracted out of it. And one of the guys in Ember CLI was like, "Why do you wanna do that!" Great test for changes of lengths and less, that may work easier if I have Ember test helper stuff. And cucumber generator protector. End of story, that's it. - [Man] Now were there any questions? - [Audience Member] Like exactly like it did. - Wow. Right. - Okay, hmm, something to think about. Maybe I can get them to sponsor me through. Think this'll feel tame there. - [Audience Member] They could acquire you. - Yeah. I need to close the source though. Invent a JavaScript encryptor that runs and-- - [Man] Any other questions? - All right, thanks.