We're a little late today. No, not a problem. Just about to get started. Just as soon as my clock clicks over to 12.03, we'll do it. Oh, and there we go. All right, let's go ahead and do this thing. Hold on a minute. Catch Fabio Jose later. All right, so agenda. I don't think there's anything too exciting with the AIs going on. Just want to remind people that per the discussion we had, I think it was two weeks ago, we are going to cancel the conference call. The weekly conference call for Coup Con next week because of being in Shanghai, and because of US Thanksgiving after the week after that. So the next two calls are going to be canceled. People have my calendar skills right. So just want to remind people of that. Actually, let me do this. Make it bold to remind people. All right, community time. Is there anybody on the call who is not a normal person or not a normal working member who has a topic related to activities from the community that they'd like to bring forward? All right, not hearing any. Let's move forward then. Okay, SDK workgroup. Now Austin, I know you weren't able to join the call that we had the, I guess it was Tuesday this week, I think. So let me just quickly summarize what I think happened there that other people can chime in. The goal line and Java SDKs are well underway. There's definitely some activity going on there. Clement said the C-sharp one should get started relatively soon, so expect some activity in that repo. We don't have a whole lot of activity. Actually, we have zero activity so far on the Python and JavaScript ones. Now, I know some people are interested in those. So if you are, please speak up and I'll give you access rights to merge and do stuff with PRs in there. But I'd like to see those get started as soon as possible. We did briefly talk about whether we wanted to have some sort of overarching design document to provide consistency across the various implementations. And the general consensus at this point in time was that while that would be good to see if we can provide some consistency, it may be a little soon to be thinking about that because we wanted to get some initial code base out there so people can start playing with it. And then we'll take a step back and say, okay, where should these different SDKs or different languages line up better than they do right now? Since anything would come out with any time soon would be an alpha anyway, we should really make some changes to align that then hopefully it would be more superficial, syntactical type changes anyway. But that's kind of where we landed at that. People were more focused on trying to get something up and running first rather than looking at the bigger picture type stuff. We are still kind of hoping to do an alpha, at least for some of these SDKs, by KubeCon North America. Whether that plays out or not, we'll have to see. Obviously each group is gonna probably decide that on their own, but that's still the goal. So if you want to try to make that happen, please join the activities in the particular repos. From anybody on the call or Austin, is there any other comments or topics that you guys think we need to bring up that I may have missed? On my end, we started an SDK design document that is there and it does provide some suggestions. It was never meant to be firm requirements, but just suggestions. So it's there for guidance, but I'm all in favor of just moving forward, getting something out there sooner rather than later. So I think that's the best course right now. And then if anyone is curious or wants to learn more about stuff we've discussed, you could go look at that document. Right, and just to let you know, you and I got an action item from this week's call. Whoops, sorry, I did that wrong. You and I got an action item from this week's call to basically see if we can produce some sort of status or plan or some kind of doc, because you're right, this doc is kind of what we've been using for those purposes. But the problem is this doc also seems to serve the purpose of a running notes document from each of the phone calls. So it may be a little difficult for someone new to the group to see exactly where we are relative to what they should be thinking about if they want to design, for example, a new SDK for a new language. So I thought it might be good to pull that, those types of design decisions into either a separate doc or a well-known location, like maybe at the top of this doc, just put them on those lines. So I was gonna work with you offline about that one. Does that make sense? I'm sure. Okay. All right, any other questions or comments about the SDK work from people? I'll read the doc as Neil here. I'm just curious as to how we move forward with transport bindings and SDKs and whatnot, but I'll read the doc and I'll come back to you. Yeah, one thing that did go up on this week's call was whether we were gonna have plug points or extensibility points within the SDK so people can create new transports per SDK. And if I'm remembering correctly, I think there was general consensus that that would be a good thing, that way you don't have to modify the repo or do a complete recompile of everything just to add a new transport, you don't have some sort of plug-in mechanism. But I don't think we got as far as to say what that plug-in mechanism would look like. It may be very language specific anyway, but that's as far as we got was just saying, yes, it would be a good idea. Okay, cool. And I presume security concerns are kind of just out in the future for now. They have not come up in the conversation as far as I remember, so I think it's probably fair to say yeah. Okay, cool, thanks. Okay. All right, any other questions, comments? All right, moving forward then. I don't see Kathy on the call, so I don't think there's been any activity in this workflow subgroup, so I think we can probably move on to the next topic. Kupkan Shanghai, the slides are pretty much done. We've sent them in for translation. Feel free to look at them. If you notice anything really bad that we need to fix, let us know. I think we can obviously make small changes, but I think the basic flow is there. So I think that's pretty much behind us. Interop work, we have four endpoints as right now. IBM Oracle, a K-native one, and then an OpenFaz. We are definitely shooting to do something in time for Kupkan North America. However, if we get enough participation, I don't know what the magic number is, but if we get enough participation that we feel like, hey, why not show this at Kupkan Shanghai? We may do so. But please, if you're interested in joining, or if you have an endpoint you want to include in there, if you're not already, ping me and I'll add you to the Cloud Events demo Slack channel. It is a private one, because we do talk about endpoint and stuff like that, so we don't want those advertised across the internet. But please join that, and this doc that's up here behind this work URL contains information about what your endpoints expected to do. And we do make some design changes periodically as we go along, so you do want to join the Slack channel to keep up the date with those. Any questions on that? All right, cool. In that case, let's go ahead and jump into the PRs. Now, I did try to order these, put the easy ones first, because we have quite a few to get through, but I want to get the easy ones out of the way before we get to the ones that might involve some discussion. So this one was mine. There's an issue, I can't read the gentleman who opened it up, but he basically was saying that as a newbie coming into our documents, it wasn't quite clear where to start in terms of which document to look at first, just to sort of introduce themselves into our work. So what I did is I added these couple lines of text to the read me, just pointing people to basically start with the primer, and then head over to the core specification. Just a little bit of guidance there, nothing too exciting, definitely not normative, it's just in the read me, but I want to make sure people are okay with this general text, obviously we'd be tweaking later if needed. I thought this was better than nothing, and the original author of the issue thought this was good enough for his needs. Yeah, it looks good to me. Okay, cool, any other questions or comments on it? All right, any objection to approving? Excellent, cool. Doug, I can't remember his last name, but it does start with an M, he's not on the call unfortunately. He had some minor wording changes to some of our documents, I think he was just trying to get consistent, for example, using the words producer and consumer throughout the entire doc, or throughout all of our docs, that was probably the biggest change. Minor wording changes here, I don't think any of his changes are normative at all, or if he did make any normative changes it was by accident, but I don't think I spotted any. So these are strictly just, in my opinion, syntactical or types of changes. What do people think about this? Any questions or comments on it? It seemed like they're all good changes to make for a consistent perspective. I think it's probably the biggest. But as the confusion we had before about the currents versus event, yep, that's good. Okay, any other questions or comments? Any objections to adopting this PR? Excellent, thank you guys. Oops, all right. This one, I think I did because of you, Austin. You had mentioned something about when we had dropped the event type versions property, you were wondering about whether it made sense, all right, what was our decision to include as part of the event type string itself made sense, and you thought maybe some guidance around how you might include a version string or some sort of version type of information within the event type itself. So I just added this text here and gave an example down here, just trying to address some of your concerns to provide additional clarity and direction for people. Is this, at least come close to satisfying your concern there, Austin? It provides additional clarity, so I think that's good. Okay. Definitely not normative. Any questions or comments on this? One quick question, Doug. In this example, the version is in the middle of the event type, so com.example.object.v2.delete. We do refer for it to be someplace else. Like after the delete? Yeah, I imagine that that whole event type is what the payload is corresponding to and then probably just pegging the version right at the very end. So you could keep it more sense. So you want that? Yeah. Okay. That's, it throws me off a little bit when I see it tucked in the middle there. Okay, that's fine. I think the only reason I did that was because I was thinking version one versus two may have actually different verbs. But I don't honestly care. I'm okay with this change. Anybody have any objection to putting the v2 at the end? Okay, so let me make that comment. I can get that change in there. With that one change, is there any other comments or questions before I ask the approval question? There was some talk about both the event type and the schema fulfilling parts of the version field. I don't actually have any idea how to clarify that, but someone who did have the idea of using the schema should I think comment on that VR. Comment on how that could be used as well. Are you suggesting that we may need additional text like this under the schema URL? I have no idea. I just remember from last week's call someone else pointed this schema field instead of the event type field as a replacement for the event type version. I would like to hear from whoever that was about what they thought. Oh, does anybody remember that comment? Would the person who made the comments on the call? Might have been me that I mentioned this, but only because it was mentioned at the original discussion a few months back. Yeah, because I know schema URL, at least in my experience, oftentimes does include a date string somewhere in there or some sort of version string in there. So I think it may have been mentioned in context as an example of this type of stuff being done before, which is why we felt comfortable using event or sticking the version string inside the event type. It may have just been used as an example. Yeah, I think we just talked of XML namespaces in that context. Yeah. Okay. Well, if someone thinks we need to do additional wordsmithing around schema URL, obviously we could do that. And if you don't feel comfortable creating a PR for it, then go ahead and open up an issue and someone else will pick it up. So if anybody on the call feels like we need that, feel free to open it. I'll say one thing and I'll be silent because I'm not feeling so strongly about this one, but Backcompat is a, hey, here's Microsoft. So backward compatibility might be a big thing where you have clients that are writing to the type, to the certain event type. The block created event, right? The one that we've used. And now that block created event changes slightly because it adds further information. So that should have a new version number, but now the question is, are you willing to break all the existing clients and then all the existing subscriptions that are based on that old event if you are just making a small and effectively ignorable change in the schema? So that's something that I'm generally worried about. So even if that's a rule here, our approach to that might be to go and just include a special version number in the message bot in the body or if we have a URL to have that reflected in the URL because I'm really worried about existing infrastructures and the existing applications that are assuming that they have subscribed to the event and that they expect a certain event type that they dispatch on and then you make a new change and you effectively breaking your entire employee infrastructure. So that's why I'm reluctant to have the event type as the core dispatch criterion change with versions. Oh, are you trying to figure out, are you suggesting that we may need just additional text in the primer to provide guidance on how to and how event producers should be producing these strings or do you actually think a narrative change to specification is required? Yeah, I wonder what that addition that we're adding here is sending people down a path that might have consequences that they might not see if they're reading that because if you only really make an added change in the schema, you really usually would not care. And so that now puts people into the conflict of when am I really gonna change the version number? Only if I have a breaking change, then that's probably justified. But if I do a point where at least I'm just adding data, which ideally by principles of, I always keep citing the same Ruby, it's okay to add things, then you never do a version revision and just keep things the same. So I said, from an implementation perspective, I know how to go and deal with that. It's just for me that the question of what the guidance is that we're giving. So I don't have a strong opinion if other people feel about this being the way how we should go and guide people, but I just wanted to point out the risk and with that I'm done. Okay, so Matt, I think that's a little simple as you were trying to raise your hand. Matt? No, that was me joining the meeting present. Oh, I thought you were trying to speak on this one. Okay, sorry. Okay, well, so let me ask you this, Clemens. Would you prefer if we hold off on this? The guidance makes me a little uneasy. Okay, well, like I said, I was hoping to get the easy ones out first and this one sounds like you're a little nervous so I don't want to rush it. So let's table this one for right now as that and then we can revisit it to see whether we just killed the whole thing, add additional text, either here in the primer, but let's talk about that later. Is that fair? You don't want to rush it. Can I just comment on that, Clemens? Since you're talking about additive changes, now that we're talking about it more, I think originally in the discussion, the point was that it would be major version changes, would be a part of the event type string, so breaking changes and additive changes would be dealt by having the schema change anyway, because if you have additive changes, you should be changing your schema URL probably with a date or something as Doug was talking about. So I would propose that we have a versioning discussion. So you can use the event type, you can use that event type attribute as you like, right? Obviously, you can use it for versioning, you can use it for everything. So I think instead of putting this here, we can make a version section that says, and here's three ways you can think about versioning and really how you deal with them is really up to you, but that's kind of, so basically making the guidance thing, but not making that necessarily a, and it can be even in the normative part, but I think standing alone is complicated because schema URL plays into that. And as we said, you know, you want to have a major change versus a minor change, and I think that needs to have a little bit more explanation. I'm just worried about it from an education perspective and not setting people up on the wrong path. Okay, well, like I said, let's hold off on this one. I don't want to rush this, especially if you are correct, Clemens, and that it may lead people down the wrong path. I definitely, that is definitely not my intent. I thought it was my, I thought it was mindless text and if it's not, then I want to take a step back and think about it some more. So let's take this one offline and see if we can address your concerns and then come back to the group with a more, with a different proposal. How's that? Great. Also, I just want to chime in real quick, Doug. I think Clemens has a great point and if we're going to usher in this event-driven future, we really have to give some pretty good guidance as to how cloud events can help data evolution. And I think Clemens' suggestion of just writing some of that guidance in here as like an initial step until we get this out to the market and learn more and see how people are approaching the problem seems like a good one. So I'd encourage you to see anything in that direction. Sounds like a good initial step. Very kind of you. Okay, cool. Thank you, Clemens. I'm glad you mentioned that. So as a reminder to anybody on the call, please, if you ever feel uncomfortable on something, want to bring up some concerns, feel free to do that. Save what Clemens did. Because at times when we start sort of rushing through some of these PRs, I'm doing it mainly because we only meet once a week and I want to make sure we get through as much as possible. But even if you have just a nagging feeling like Clemens did, feel free to mention it and that will slow us down and we can take it offline and discuss it. I definitely don't need to rush things. So thank you, Clemens for doing that. I also think the separate section for versioning or scheme evolution as a guidance sounds like a great idea. Okay. Okay, cool. Thank you guys. Next one, Kristoff. I think you actually just joined the call too. So maybe you want to talk to this one? Yes. So we had a PR that we discussed on last week's call from Fabio and basically he came and said, I took your JSON example and I tried to pass it by the JSON schema and it didn't validate. And it didn't validate because you used the relative URI but actually you say it should only be URI. And then there were multiple people including me who said, yeah, you're right. We only support URIs. But actually then Doc found out this is not true. So if you scroll down to the spec you would see that we actually said all the time here that is a string expression conforming to URI reference. Well, then we go and name it URI and then everyone is confused by that. And then if you look at the JSON schema you can see that the mistake was applied there. So in the JSON schema it actually said URI but it should have said URI reference. So with this PR I'm trying to make the name URI reference so that it should be clear for everyone who reads the spec that this is not a plain URI by the URI reference. And I'm also fixing the JSON schema and I'm also adding one more example to the spec the last change basically that's a relative URI. Any questions or comments on this one? All right, any, oh, I'm sorry. Is someone gonna say something? Yeah, I just wanted to ask has there been a discussion about whether the relative URIs are actually wanted? Many moons ago, yes. So this was, we had a long discussion about URI references versus URIs and we literally landed on URI references. We can open that box of Pandora again but there are cases where you are acting. So the argument was if you're acting holy within the scope of a single system then further qualifying the URI might not be necessary. Example, Azure, the events that we're raising from the Azure platform all have relative paths because they're relating to azure.com because it is the Azure platform that is raising those events and effectively the event paths are all ending up being unique because they're anchored on a resource structure. So for Azure, we don't need to have absolute URIs but we would want to go and distinguish between these and URIs that are not part of our scope. So we would also then allow absolute URIs if they refer to other scopes and other systems. Yeah, great. I just wanted to ask if there had been a discussion that sounded like that. Yeah, we had a debate about this and I think the debate lasted like eight weeks. Just an additional question since you brought up a great example. When you export events from Azure to another domain would you then still keep the relative URI? Yes, because the event type... So the event type is meant to be domain qualified and actually is. So you can already tell from the event type what that is and where that comes from. So you have that qualification, but yeah, if we're thinking about federation, if we're thinking about federation across systems then we might go and consider adding the URI. I don't wanna expand the scope here all that much in that discussion, but there are some thoughts that we're having in a different realm that's kind of related to this and I'm probably gonna bring this here because we have an NTP binding about addressing in general and thinking about what a logical identifier is versus actual network addresses and that kind of plays into that because azure.com in that sense would be really just the name. And then the question is, what is the right name for the sources? What is the right URI? What is even the right URI scheme to use for those? Because HDP or NTP is not the right thing because there's a lot of addressable entities and those prefixes imply some protocol behind it. So these probably should be your ends, but then what is... There are no rules governing the uniqueness of the authority portion if you don't have a scheme that matches that. So in NTP specifically, we're trying to go and resolve some of those concerns about multi-level routing, et cetera. And once we have a model for that, then we would probably want to bring that here. Or obviously you're all invited to come to ASIP. All right. So it's fascinating, sounds fascinating. So okay, so I think there are two things coming out of this. One is it seems to me it might be good to add even if it's just a short paragraph or sentence or two to the primer to explain why we allow URI references. And I added a note to our agenda doc to make a note of that and I'll do an action item around that or how to get someone to do an action item around that. I do think that'd be useful to explain that. And Clements, I thought you'd get a good example of why that might be needed. But the second thing and more important thing is this PR itself. Any other questions or comments on this one? I love it. There you go, that's a good comment. Anybody else? If nothing else, it definitely provides clarity, which is good. Okay, any objections then to adopting it? All right, not hearing any. Thank you guys very much. Clements, hopefully the next easy one, integers. Would you like to quickly talk to this one? Oh, I don't even get any Delta during this call. Yeah, so this was easy. That was an omission. This was, it was noted that when we added the integer type to the abstract type system that it wasn't in the mappings and that was correct. So I just added that. And for the JSON format, since we all be low integers and I'm trying to keep the, at least I am trying to keep our type system compact, I'm literally making the constraint that you can look at the JSON number there, but you can only really use it. And if you look at the JSON spec, we don't have to go and click that. You'll find that in that section, they talk about an int component and that is expectedly an integer. And then I'm just adjusting the text. And I make the text a little bit more robust at the bottom like line 81, where I'm saying basically it can be any valid type so that I get out of the iteration and have to go and adjust it all the time. And then above, I'm making effect of the same change, mapping the, our integer type to the MQP long for the MQP type mapping, which is the other one that we have. Yep, and that's up there. So there are no, there should be no surprises. And for MQP, I didn't have the, we didn't have that word that we have for JSON because MQP knows that construct of any type by itself. All right, cool, thank you. Any questions or comments on this one? All right, any objection to adopting? Excellent, thank you, Clemens. All right, ProtoBuff. I don't think Spencer is on the call. Now, this one has been out there for quite some time. I think there were some, in my opinion, I thought relatively minor updates recently, but at least three days ago or more. Let me ask the Googlers, Rachel or Scott. Is there anything you guys would like to add on this one before I ask if there are any questions or comments? Any comments you guys want to make? I think Spencer tried to address the changes that people brought up. So if you see something that is still not addressed, that let me know and you can address it. Yeah, I think he did get everything, I agree. So, hey, this is Jim. So I just wanted to raise the comment on the media types. And I know Spencer had sort of commented on that, but I didn't see any updates to the documentation sort of describing what we should do, yeah. So, well, so in the last comment, he was saying, oh, so you're saying that you would like to see a change in the PR itself?  And given that there isn't a registered one for Protobuf, what I really was looking for was this standard to say, and this is the media type we'll use, yeah, to actually make it explicit. Okay, I'll pass that along. Is that something that would be in the Protobuf spec itself already? So, is that a question? Yeah, I'm just wondering whether the Protobuf spec itself dictates what the content type would be. It doesn't right now, but it could. Okay, I didn't want us to repeat stuff, that's the one I was asking. Okay, so, Jim, I'm trying to figure out if, okay, so you're asking for that change. The reason I'm kind of hesitating here is I know this PR has been out there for quite some time and I feel bad that we haven't merged it yet because I don't think there's anything major that needs to be done to it. I'm not at this kind of your content type thing, obviously I do think that's important. I guess what I'm kind of wondering is, would people prefer to wait until that change is made to this PR or could we do that as a follow-on PR? Well, to be clear, I don't want to say, we'll definitely include that. I want to say I can pass that along to Spencer. I don't know if we include that in the other specs. I assume that we do, but I don't know for sure I have to go check. We did, in the JSON format, in the envelope section, it says such a representation uses the media type application slash cloud events plus JSON. So this one basically would be plus, plus, plus protocol. Because that's what we're using the plus notation format where we basically have a base type. We still have to register that one, by the way. And then we're effectively adding the encoding format at the end of that. So it will be application slash cloud events plus protocol. So what do you guys want to do? Would you like to see if we're gonna merge this one as is and do a follow-on PR or wait until this change is made before we consider adopting it? I can go either way. Is that a question to the entire group? Yeah, mainly to, I think, you Googlers and Jim, because you guys are the ones that are focused on the content type question, but to the whole group in general, too. So I don't think it should necessarily hold this up, but if you merge this one, I'd like an issue or something to be opened up sort of fairly promptly afterwards to get it clarified. How about this? How about we merge this and then I will open a PR against this file as soon as it merges to make that change? Yep, that works for me. Like I said, I just feel guilty because I know Spencer spent a lot of time in this and it's been lingering for a while. I don't want to nitpick at the death. Okay, so the proposal out there is to try to get this one in so that we can prove it. And if it is, do a quickly follow on PR to adjust Jim's content type question. So any objection to that process? Okay, not hearing any objection then. Is there any objection then to adopting this PR as it stands? All right, cool. So let me just make some notes here. Approved. All right, cool, thank you guys very much. Jim, yours, oh, okay, this one. Would you like to quickly talk to this one? Sure, so this was one that I rather foolishly promised to do last week, just really to reduce and simplify the property and attribute naming. And I think the only one that was sort of questionable at the time was whether people wanted to reduce the attribute called cloud events version to version or spec version. So this change is actually to reduce that to spec version. There was one comment, I believe, from Roberto. I don't know if he's on the call. Yeah, on the call, I think ID is too generic because there's so many IDs in JSON. So I think that this is the one that I would prefer to preserve as event ID instead of ID. That's my only comment. Right, so I think my response to that was I have no strong opinion. I think I'd prefer it to stay as ID because it keeps it consistent with everything else. But I'll go with a flow if the group wants to change that then I'll do that. I'm not wedded. What I would say and apologize in advance to the people working on the Kafka transport spec because if this gets merged, then your spec will need to change as well. Yeah, I think we've got a few dependencies upon other stuff at the moment. Yeah. Okay, so I think there are two open questions then aside from the overall question of the PR itself. So first, cloud events version changing to spec version. Is there any concerns about that change? Okay, I think that may have actually been driven by Austin's request last week too. So hopefully he'll be okay with that. And I think he actually was for what he said in last week's call. So I think the bigger question, more interesting and possibly harder is event ID versus ID. What do people think about that change? Are we waving hands or? Yeah, or just speak up. You can either put a plus hand in the chat or just start talking if no one's talking, yeah. I'll be quick. I think it's contextual. So I'm okay with ID because you're only gonna see the ID ideally in the context of a cloud event. So I think it's kind of self-explanatory. Yeah, I agree. I'd rather have all of them either be prefixed with event or none of them having event as a prefix. Anybody else wanna chime in? Hi, this is Vladimir. I would also prefer just to have it clean without the prefix event in front of everything. Okay, thank you. And obviously I haven't biased him at all in that. Yeah. I guess I agree. I'm outnumbered. Well, it's like- I agree for sure. Okay, Roberto, since you seem like you wanna shortcut it, let me change the question. Is there anybody on the call who strongly feels that it should remain event ID? Okay, so yeah, Roberto, I think you're kind of outnumbered on that one. But it's interesting that you mentioned it though because this is the exact example I think I used last week on why I thought prefixing everything with event might actually be good. And because I said ID versus foo ID be kind of annoying. But anyway, so I think the general consensus so far is that keep it with ID without prefixing it. Is that fair conclusion or am I misreading the group? Okay, go ahead. I think the event ID is better but in the face of everything else changing, they're not having the events. Front of it, it would look weird and break consistency and the such even though it would be better in terms of understandable, it's not actually better. Yeah, I agree with that. It would be way clearer but if that one has events in front of it, all of them should. We can't have an event just on one. We would definitely get PRs and people would get confused if just one of them has events like, okay, time is the time the event was generated. Is it the time of the event? Is it the time of actually sending the event? So if one has event, all of them should have event in front of it. So I'll raise my hand here, not as a moderator but I would tend to agree. If we're gonna do it on one, we gotta do it on all for consistency. I like consistency a lot. My head is much happier that way. Anyway, so any other questions or comments on this PR then? Okay, any objection then to adopting it? I'm watching the ramifications fly. Okay, not hearing any objections. So this means that once this thing's merged, we gotta change our demos and the Kafka spec. We just broke the world but that's okay. We did just break the world, yes. Thank you, Jim, I appreciate that. You're welcome. I mean, it's so point one. So I know it's safe, it's just funny. Okay, last one. This one I thought might take some time to respond to some recent comments. Neil, would you like to talk to this one, the Kafka of transport? Yeah, sure. I mean, it flows in line with the other transport bindings. There's been a bit of a discussion about halfway down where we talk about the header mapping and a prefix everything with cloud events, underscore, yeah, that's it there. And we weren't sure. So I asked Doug and I also asked Clements. And I think the interesting thing is that the bottom Clements has said, it looks like we might be going for a CE underscore. My concern is if we're propagating cloud events between multiple transports, we don't, ideally we want consistency between those transports. So we don't have to do any kind of namespace mapping. But I'm really looking for opinions from other people as to do we have a standard consensus for how do transports propagate events between them?  You have two namespaces, but you have your transport space properties and stuff that is necessary for routing and handling stuff at your transport level. And then we're effectively taking the metadata that the cloud events brings, certainly for the binary mapping, we're kind of overlaying this. So since we now make our world very easy and very compact by just did with ID, we now need to go in namespace things, right? So if we now say for Kafka, you make CE underscore ID and CE underscore time and all those, then if you're presenting this up in an SDK, then you would basically go and toss all those prefixes out and you would simply service the normal names for cloud events. And if we're doing these, if we're mapping stuff onto the transport frame as we're doing with that binary mode, then you already need some code that sits in the middle that kind of does the translation between transports. And the logical way of doing that is to go through the SDK. And the SDK will therefore go and present you normalized names. And then you go with those normalized names back to the transport web, the other transport, the next one, HTTP, where they will again be prefixed so that they don't clash with the wire reality in HTTP. So I think of these prefixes that we have in the wire representation really just as a namespacing trick to disambiguate from the native headers that you have there. But in terms of how do you project this out to an application, these prefixes basically just go away because they're giving you a filter condition for how you can find, even if you don't, if your SDK doesn't know about all the cloud events headers because we have the extensibility, then you know that they originate from cloud events because they are the CE underscore prefix, which means you can go and collect them all up, strip the prefixes and present them as a collection. Okay. So in that case, we can go with like a packaging semantic like the IO.cloud events. Yeah, exactly. Within the binding. Okay, that's good. Yeah, you can use what's idiosyncratic. So for AMPP, I'll probably go and change this to C, because that's the idiosyncratic way to represent this because AMPP uses as a kind of implied namespace model. And then we have CE dash for HTTP because idiosyncratic there. We don't need to have those things look alike, I think, because the assumption is that we'll normalize off the transport into the normal names. Okay, that's great. And the other thing was this, there's a dependent PR here with the event key. And obviously we can't put data into Kafka without it belonging to the correct partition. I have a comment on that as well. Yeah, so I think Jay Roper or John Roper opened a PR a while ago. It's been open for some time. And I know you left a comment earlier today about exposing transport binding dependencies up to the event model. The question is, if we do hide it within the data payload and that data payload is binary or it's encrypted or it's secured, then for whatever's actually trying to look at that to extract out the event key, it's a fair bit of overhead. It's also might break some security concerns which we haven't kind of got to yet. That's true. But then if you have payload-specific information, I would argue that you then have a header that you're promoting out. So I have to effectively attribute that you're promoting out of your payload, which is payload-specific. Because that is then an extension. And I think what the Kafka binding ought to do it ought to have an expression effectively that can define how you fish some element out of the event that you can then go and use as the event key. So basically in the subscription, so I think of these transports as effectively subscribers to the event flow. And you might have the situation where, as I wrote in that comment, where you have a device and the device is publishing events over MPTT because that's the only protocol it knows, those ends up, those end up in a gateway. And that gateway then turns around, takes that event and throws it down the Kafka pipe. At that point, the MPTT, the device is oblivious to the fact that you want to do that with it, right? And it's been shipped with MPTT support four years ago and you might not know. And of course, it has known cloud events will continue at that point. And then you need to have a mechanism, I think to go and construct, you need to have a rule to go and construct a partition key for Kafka because it always needs one from the content of the message. And that might mean that you map from an existing attributes, that might mean that you go and do a query into the payload. But I think it'll effectively have to do a reference to an attribute that's in the message without that attribute in the message being predestined to become a Kafka key. Like from a conceptual building, it's leaving your ability to do whatever you want. But from a conceptual perspective, I think that the Kafka binding should basically refer to stuff in the message and then make that the key rather than for us to have a preconceived notion of key from the start of the event flow until it potentially sometimes hits the Kafka endpoint. Yeah, I guess the aspect of this, I mean, until we figure out 218 that Doug had opened about the event key field or property is until we can figure that out, we're not really sure what to do in the Kafka transport binding. I mean, there's been some proposals to append it to the source as some kind of like a URL parameter or something like that. But we, yeah. What do you mean? Something that needs to, so like say the source is a IoT device and then you've got an ampersand event key or device source or something like that becomes the event key. You can, so I think the other thing you can do is the, so the simple way of solving this is of course the Kafka binding can make an extension and say, here's the default key that we're picking up. I mean, it could default to source, but that's not gonna please everyone. There's always gonna be some kind of scenario that source is not sufficient. And see, that's why that's what my concern is because our event key is not going to be because our event hub works the same way, right? And we just released the Kafka binding for that as well. So we have the same problem. The way how you're choosing your partition, your partitions really also depends on the use case, right? You might go and want to create partitions based on event type. You might want to create partitions based on the source. You might, I mean, there's all kinds of criteria by which you want to go and partition your event stream for processing and having some kind of mechanism that allows you to say, you know, in my binding, I can, and in my implementation, I basically select a criteria, the select effective expression, whatever that is, that then points to the cloud events message and does a transform and that transform yields a key is, I think, better because you have more flexibility than if you have to go and put a key in a priority into the message, even though the ultimate sender, the sender might not even know what your partitioning criterion is. Because there's always the case of, you know, the single device sits out on the edge, sends stuff in, and then you have, you know, concentrator, concentrator step, and then in the second level concentrator step, that's when you want to have some different partitioning that the device has no concept of. So we've got a couple people with their hands up and I want to get to them before we run out of time. So Christoph first, then Vlad. So go ahead, Christoph. Yeah, I agree with Clemens. I think it's somewhat similar to rooting. So I'm mainly looking at it from a producer perspective. I don't know how my consumer will want to root the stuff. So what I want to do is I want to give them options of what they can root on. It's event type, this on my source, where I may be going to put a bit more data than is strictly necessary. I may introduce extra attributes. So then the consumer or the middleware can decide where and how it's going to root based on these attributes. And I think the same should be true for the partitioning.  This is for me as an event producer, it's really hard to pick the right partition key and there's probably not one that will fit all use cases. So whichever I'll pick, I will make some parts of some people unhappy. Okay, Vlad, your hands up next. Yeah, all my comment is on the same line. What about the producers that can't, for some reason, generate the partition key? That's not ideal and having this as a required field is not ideal. And I do believe this would be perfect as an extension. Like, if the partition key is there, use it. If not, we're gonna combine it in this way or generate it by concatenating these three fields with source ID, event ID and whatever. Okay, Tepini, I think you're next. Yeah, to continue from Clendon's comment, the producer cannot know the partitioning strategy for all of the consumers. It's just not possible. So, what I actually wanna comment on is, does it make a difference whether it's an expression in the field that points to another field or just duplicating that data from that field into the event key field? Why do you prefer a path expression or something? So can I jump in here just for a second? I wanna make sure that we're talking about this only within the context of the Kafka transfer binding. I don't think... I didn't wanna necessarily go into PR or issue, or I'm sorry, PR 218 yet, unless it has to be solved for the transport, for the Kafka transport. So let me ask that question, Neil. Because Kafka needs to have a key. Okay, that's what I was wondering. So Neil, is it fair then to say we cannot even think about merging your PR until we resolve 218? That's right. Okay, okay, in that case, let me continue. Sorry, I wanna make sure of that though. Yeah, it was mainly just a clarification that the producer will not be setting that key anyway, because he kind of know what the value should be. It will be the middleware or something else that actually does the partitioning and knows the strategy that it should be partitioned by. But I just wanted to ask Clemens, why do you think a path expression brings some advantage over just... If you want a reference, why are you not just copying the data into the event key extension field or whatever? No, you could, but it's a subscription operation. So basically the event exists, the event exists, and now you're having the Kafka transport provider, however the implementation happens. And now that thing needs to get configured to go and look at that event and now pick out something from that event that then becomes the key. So I think the point is mostly, the producer, it's a matter of the middleware configuration effectively and really addressing the specific concern of your Kafka deployments. And how you want to have the downstream consumption model look like is how do you want to go and select the key? Oh, so you're saying it wouldn't be the event key field that has the path expression, but rather the configuration for your transport provider. So I don't think there's necessarily a path expression. There might be, I just said there is some kind of expression, some kind of mechanism, but with which you can go pick something out of the event. The point I was trying to make is we can't assume that a priori there will be something key-like or Kafka specific key-like in an event that shows up at the client that goes and takes the event and then renders it onto Kafka. No, well, sure. There has been discussion just before in the event key PR I think about make that transport could require an extension such as an event key, but I do think it sounds very interesting to instead have that configured on the transport configuration instead of in the event, I think. That is the first time I think we really talk about some idiosyncratic needs, configuration needs of the transport, but I think that's the case here. Like we really need to write down in the, and this is the, it's a little weird because we don't prescribe a particular format, but we would probably prescribe a particular mechanism or it washing course, we describe a mechanism that basically says you need to have a key and there will be cloud events message showing up here and how you derive that key doesn't matter, but the key really needs to be there. I don't, I would have to think about how to express it in a normative way, but that's ultimately what it is. The key needs to appear for it to be put into Kafka, but the implementation of the Kafka transport needs to construct that from the message. And it might use extension, it might use existing data that's in the message that's really up to the spec and also I think it's up to the spec how specific it wants to be. Okay, and with that I'm gonna have to call time because we're at the top of the hour, but it does sound like we're in agreement that we can't address, we can't think about merging the Kafka transport until we resolve 218. So please can you discuss your 218 in the PR itself, especially since we're not gonna be meeting for the next two weeks. So let's see if we can get that one resolved and then Neil can finish up the transport, the Kafka transport binding.  So Fabio, are you still there? Yeah, I'm here. Okay, Brian, are you there? Yep, I'm here. Okay, David Lyle? Yes, I'm here. Okay, cool. Ehor, I didn't see you here. Yeah, Ehor, you left, right? Yeah, I think you left. Colin, I saw through the chat. Christoph, I heard. Klaus, are you there? Yes, I'm here. Excellent. Are you there, Renato? I think you spoke earlier, right? I'm gonna be not, Renato, are you there? And what about Siraj, S-I-R-A-J? Are you there? Yep, I'm here. Okay, and what about Renato or Ehor? Okay, is there anybody I missed for attendance purposes? Vladimir Bekvansky? Vladimir, okay, thank you. Thank you. Anybody else? All right, cool. In that case, thank you guys very much and we'll talk in two or three weeks, I guess. And I'll see some of you in Shanghai. Have a good one. Hi, everybody. Thanks, guys. Clemens. Yes? Can you write down even just a short description of what we were talking about in the issue since you actually have the idea and you clearly have more of a clear idea of what that is? Sorry, which one? Which issue? We're talking about... The 218, the MNK issue about how it might not be an extension in the actual... It might not be an extension attribute, but rather a configuration of the transport. That's a very... Yeah, to put an ugly picture in your head, think of it as an X-path expression or some reg X or something of that sort or literally a function that you can figure into your Kafka transport so that it goes and sees an uncommon cloud events message, can run that transport over the message and get the key out. Oh, sure, sure. I get the idea. Callback is what I obviously jumped to first because I come from JavaScript, but just to have that idea in the issue because that has not been discussed before. It's always been discussed as an extension attribute. Yeah. Yes, okay. Let me note that down. Because I think that actually sounds way more like... That makes much more sense because then that eliminates the need for the middle word to modify the event to get the MNK in. Yeah, correct. It's a part of the transport configuration. It's an adapter of binding configuration element, if you will, and we're prescribing... What we're describing is transport. No, transport is an abstraction, but we're really being prescriptive about how a piece of code ought to take this abstract notion of a cloud event, which will be backed by code eventually, and then goes and transforms it into a wire projection. That's what the transport bindings do is they basically prescribe all that software all to operate, and we now make an extra prescription here that says... And you also need to have a way to go and harvest information from the input event to go and generate synthesized effectively that key. And that might be an extension, but that might, you know, however that might be, but it's something that is in the obligate... It's an obligation of the Kafka transport implementation to go and create that. Oh, sure. The reason I was looking for an extension attribute is that I think it should be surfaced on the consumer side and the most obvious place to do that would be an extension, but that... But the Kafka consumer kind of gets that key, but once you know... Once you pop out of Kafka, it again probably doesn't matter. Oh, sure. But yeah. But if I have a consumer using Kafka transport, I would like to know... Yeah, but you already have that, like you're walking in with the key and you have the key here, something that is on the message frame itself, right? Right. But if I use an SDK that transforms the... That just gives me a cloud event. Well, then that should probably... If we support extensions, if we support transport probability, then we better have a way to kind of reach back into whatever the underlying transport is so we can go and find out details, because in MVP... Oh, sure. So it's like... You always need to kind of tunnel back into the original context to get stuff that you can't get out of our abstraction. Oh, sure. You could be an accessory next to the actual attribute accessor or data accessor to have those transfer-specific data. Yeah, that was some great, great conversation. Thank you. Thank you. All right. So come on, Joel. You'll add some more commentary to the... I'll find that right now, because oh, I don't think I have... Excellent. All right. Thank you guys very much. I'll talk later. Thanks.


Hi everyone, welcome. My name is CJ Kilbone. And I'm Jonas Niklas. And we're from a Rails Consultancy in Sweden called Elabs. And we're going to be talking about the front end testing frontier. Now I assume the reason that all of you are here is that you've already seen Glenn Vanderberg's talk, which is going on in the other room. Because if you haven't seen that, I highly recommend that instead. So I won't be offended if you leave. Given that you're here, I expect that you want to hear about testing front end code, testing JavaScript code. I want to start by asking you, how many of you here test your Ruby code? That's pretty much everyone, right? We love testing. The Ruby community is so gung-ho about testing. There's a lot of, in my mind, positive peer pressure about testing in the Ruby community. It's unlike any other community that I've ever seen. And that's great. But how many of you test your JavaScript code? A few people, but significantly less, right? And of those few people, I think I saw maybe five max ten hands. How many of you find it frustrating? Yeah, that's pretty much all of you. So we love testing in the Ruby community, but only our Ruby code, really. JavaScript code, not so much. So why is that? We think that one big part is that JavaScript testing is neglected in many ways. The reason that I really got into testing when I started using Rails was that it gave me so much for free, really. As soon as I generated a model or a controller or, God forbid, a scaffold, it just put a lot of tests there for me and I just had to fill in the blanks. It was a really, really easy, clear path forward. Not easy necessarily, but it was a clear path forward. I knew what I had to do. I knew where I had to write my tests. And just running rake would take care of the rest for me. With JavaScript testing, there's nothing like that, really. We're completely left on our own. We add some JavaScript functionality to our application. And where do we go next, right? There's no clear path forward. It's also neglected in many ways when it comes to the other things, like the things that go around the ecosystem in terms of tutorials, documentation in general. It's way less than what we have for our normal Ruby testing. So again, not including Rails. This is probably, for me, was the biggest hurdle to get over or the biggest win when it came to Ruby testing. But with JavaScript testing, there's nothing like that. Another piece that plays into this, I think, is that in many ways we don't consider JavaScript real code. A real code is the Ruby code that we have in our models and controllers. But the JavaScript code is just something we sort of sprinkle in to make things a bit nicer. Maybe it's some Ajax to help out with the flow of the application. Maybe it's just toggling an element so that it's only displayed when it needs to. It's not really a real code. It's just something that's a pretty separate application of it. And of course, all of this leads to the conception that JavaScript testing is hard. It's hard to get started. It's hard to get it working. It's hard to maintain. So difficult to set up is probably the biggest part for me, at least. It was really hard to find out where to start. And hard to maintain, JavaScript lives on the client side, usually. So it has all the problems that we have with view tests in general, that views usually can be quite brittle. Just changing the text on the button can break our entire test suite. And stuff like that really puts a barrier in front of us and makes us reluctant to get started with really testing our JavaScript code, I think. And again, there are no established best practices. With Ruby code or with Rails testing, there are really, there are established best practices. DHH has run the other week here, maybe through a wrench into things. But we have test units, we have RSpec, and they're both great. So you can pick either one and you're golden. With JavaScript testing, there's not really one established best practice. There's a myriad of different frameworks, different libraries that all have their strengths and weaknesses. And it's really hard to choose, unless you maybe have help from someone who's done it before and can help you with that choice. So our goal with this talk is to show you that it doesn't have to be hard. We're here to show you that there is a fairly simple way to really get started with JavaScript and to go beyond that as well. But why do we care? If it's just a bunch of tiny bits sprinkled here and there to make our application pretty, is it really that important to invest a lot of time learning, maybe, or a lot of time at least writing the tests, isn't it enough to just load up the browser and click around a bit and see that things work the way we expect? Well, with today's applications, we're writing web applications that really blur the line between web and desktop applications. As our user interfaces become more and more rich, more and more desktop-like, we move a lot of our logic into the client side. And that logic, of course, needs to be tested or we would have tested it if it was on the backend. So we really need to test it on the just moving it to the front and doesn't change that really. So we need to be careful about that. Another big benefit and fairly easy benefit is if we have good tests, we know when we break stuff. We know when we think we're just going to make a little change somewhere and our tests show us that, whoops, this actually broke something in the part that you weren't expecting. And this is something you get for free, basically, with writing tests. It's a very, very important benefit, I think, but probably not the most important. For us, when we're writing an application, we know that it's going to be around for a long time, probably. And as we're working with different clients, we know that we're probably going to be away from an application for a long time and then come back to it maybe six months, a year later. And we want to be able to dive right in and be comfortable in making changes to the application. Or we're turning it over to a client that has to maintain it for a long period of time, training new developers in it, et cetera. And the tests really help with that as well, of course. There's also the issue of refactoring. As all of you know, writing tests in your Ruby code, the most important part of red, green refactor is the refactor bit, right? It's the refactoring that leads us to create really, really good code. And this, of course, helps with the sustainability as well. So by having the confidence in our code that the tests give us, we can refactor mercilessly and know that we're still green. So all of this is about better design, really, which has always been the point of testing code. Writing code that's hard to test is a code smell. So by using tests, you're making sure that your code can be tested and that leads to better design. It leads you to create code that has good isolation, that's not coupled to a lot of different things, and it really, really improves the design of your code. And with JavaScript, this is especially important because if you've been writing an application with JavaScript for any period of time, you know that you usually end up with a huge mess of spaghetti code, right? You're just throwing functions into the application .js file and, you know, after five minutes it's a mess. So by having our tests force us to have a nice design, even for our JavaScript code, by forcing us to isolate pieces in a good way, it's much, much easier to develop that application or maintain that. So what it comes down to is that we're testing our JavaScript code for the exact same reasons that we're testing our Ruby code. It's in no way shape or form different, really. It's all about having confidence in our code and better design. But how do we do it? What level should we test it at? We're going to talk about two different levels, really, and that's unit tests versus integration tests. And that'll cover most of it. Now with unit testing, we're trying to test widgets or components, usually. We're trying to find any isolated logic that doesn't rely on too many different pieces of your code. We're testing pieces that doesn't necessarily need to use rails. If we're testing something that relies on the back end a lot, there's going to be a lot of mocking, et cetera. So unit testing is perfect for the pieces of your application that's very standalone or the JavaScript pieces that is very standalone. Now integration testing, on the other hand, has a lot of other benefits. It's really easy with integration testing to test those pieces of glue code that can be quite hard to test effectively with unit testing. So that's especially true for AJAX. Unit testing AJAX usually leads a lot of frustration. There's a lot of mocking that you need to do. But with integration testing, it's a piece of cake because you don't really see the AJAX. It just happens in the background. We're just testing the behavior of the application instead of the implementation. Another good candidate for integration testing is when we have a very complicated DOM. If we have a page where we pull in a bunch of information from different parts of the application, unit testing those parts might be very, very complicated, needing a lot of setup, a lot of complicated fixtures, maybe templates to create that complicated DOM. But with integration testing, we are testing the actual application as it is, and there's no need for the complicated setup there. So that was a bit of an intro to the frustrations of JavaScript testing, why it's hard, the different levels that we're going to talk about, and I'm going to turn it over to Jonas to talk about how we can actually do this. All right. So let's kick it off with integration testing. Let's talk a bit about how integration testing has been done in the past and how it's being done now. We've had a number of solutions in the Ruby community over the years, and it all started when DHH introduced Rails integration tests. And that was sort of, integration tests had been done before that, obviously, but it was sort of a fringe thing. And when DHH, for the first time, integrated that into Rails, into the framework itself, for the first time, people were actually starting to write these tests for real. And these Rails integration tests, if you've used them, you know that they're written from an HTTP perspective. What this means, basically, is that we're talking about how HTTP interacts with your application. So you're issuing, get requests to your application, you're posting data, you're posting to a specific URL, some parameters, and so on and so forth. This is one major flaw, and that's we're not really testing what the user does with your application. So if we're talking about posting into a particular URL, for example, with these certain parameters, how would the user get there? The user would have filled out a form and posted that form to that particular URL. But Rails integration tests don't really allow you to check in any kind of effective way if that form is actually on the page, if it even has the right names on the input fields, or for that matter, if the labels on the field are even correct. So you don't know if your user can actually see that form, you don't know if filling out that form even posts to the right action, and you don't know if the user can see what fields even to fill in. So Brian Helmkamp, he wrote this library called WebRat, and he wrote this library from the user's perspective. So he tried to sort of capture how does a user work with your web application. A user would go to your site, he would fill in an address in his browser, he would press enter, he would come to your site, he would fill in a form, he would click a couple of links, click a button, he would check for some content on the page and so on and so forth. This library also had a kind of flaw and that was that its support for JavaScript was really limited. It did eventually come with a built in Selenium mode which allowed you to sort of run JavaScript, but it was pretty unstable and it didn't really share the same API. So it was sort of tricky to switch between the two. You really had to make a choice in the beginning of the project over which to use. And this is probably the sort of oldest solution that's still in use for integration tests. Selenium was released in 2004 by ThoughtWorks and I guess most of you know this, it's pretty much a remote control for a browser. So it opens up a real browser, Firefox, Chrome, IE, whatever, and it issues commands to that browser and then in turn clicks, links, interacts with your application and so on and so forth. It really does allow you to test the full stack. It does CSS, it does JavaScript, it does HTML, it does HTTP in exactly the same way that a real browser does because it is a real browser. But for a lot of tests, this does introduce a lot of unnecessary overhead.  Maybe that part of your application doesn't need JavaScript, maybe it doesn't need CSS. Selenium kind of forces you to use those anyway. So you're running a huge overhead for testing a really simple thing and that leads to really slow tests. And slow tests are hard to maintain. And what a lot of the early solutions using Selenium had as a problem was that they were pretty tricky to set up. So if you wanted to get started with using Selenium in your application, you had to install a lot of crazy stuff and you had to put a lot of setup into your application and usually it just took a really long time to get going. So to summarize this whole experience, it's not that fun. And we sat down with a lot of beer and tried to come up with some solutions to these problems. Not sure if the beer helped. I do claim that it did. So what we really wanted to get was an easy setup. A setup that's as simple as possible. We really wanted that same experience that Rails gave you with the integration tests and that WebRAT gave you with the user-facing tests. But we wanted this for full stack testing as well. We wanted to have multiple ways of running tests. We didn't want the overhead of slow executing Selenium tests for everything. We wanted to be able to say that this particular test is simple and it only needs to run your Ruby code. But whereas this other test, it's complicated and it needs JavaScript and we need to run this as close to the user experience as possible. Sorry. We wanted to run everything from the user's perspective, just like WebRAT did. That was sort of our goal when we set out. And the result of that goal was this library, our world called Capybara. So Capybara is a simulator which simulates the user's behavior when interacting with your application. And it uses the same or very similar DSL to WebRAT. But what happened was that I started to sort of poke around in the WebRAT internals and I tried to see if I could make it do the things I wanted to do and I couldn't really do it. Because the thing I couldn't really get at was the easy setup. And that was really sort of my main design goal with Capybara. And the DSL looks something like this. As I said, visiting pages, filling in stuff, clicking buttons, checking for content and so on and so forth. It allows you to switch pretty seamlessly between drivers. So you can say that this one test, it should execute in a pure Ruby environment, this other test, it should execute in Selenium and this third test, it should execute in NFJS or whatever. Over the past year or so, there have been a really huge number of Capybara drivers released. If you were here for the lightning talks yesterday, you maybe saw Terminus, which is a pretty cool Capybara but the ones that we've used to great success have been these four. The top two are the ones that are built into Capybara right now, Rack Test and Selenium. And Rack Test is pretty fast and simple. It's a pure Ruby implementation, which means it has no JavaScript support. Selenium, you know, remote control does JavaScript and CSS. It's slow. And this Akefalos, which is unspellable and unpronounceable, I still have no idea how to actually pronounce that. I think we need some Greeks. It's headless. So it has fairly good JavaScript support through HTML unit, but it's pretty slow. And Capybara NFJS is a pure JavaScript implementation, so it's actually written in JavaScript. But as you can imagine, it's not really that compatible. It doesn't really cover the full extent of the DOM, so it's only of limited use if you're doing a really simple JavaScript. And you can switch between these just simply by specifying Capybara current driver is whatever, Selenium in this case. So after this, your test will execute in Selenium. And you can even do this in Cucumber. You can tell Cucumber to, by using these nice tags, that this particular scenario should be run in Capybara and does all this in the same test run. So you don't have to have separate test runs for using Racktest or Selenium or whatever. It's adorable, isn't it? So let's talk a little bit about unit testing. We have a ton of different solutions for unit testing JavaScript. And what they really have in common is that it's incredibly hard with most of them to get started. They usually put a lot of code into your project. I personally really dislike that. They often bundle themselves into your project. So they put the actual testing library into your code. There's really sort of no best practices established for how you're going to go about. They're really hard to maintain. And that's mostly due to that most of these libraries really lack this isolation of tests. And what I mean by that is that if you're writing multiple tests, the results of one test will affect the next one. And that leads to your test being dependent on the order which they are running. And I find that this is incredibly brittle. We also have a problem that many of these test frameworks are kind of unstable. They're written sort of as a hack by people who just really needed to solve the problem of JavaScript testing. And they wrote this framework and then abandoned it a month later. And it turns out that it's pretty buggy. And it doesn't really have a very clean implementation and so on and so forth. So the entire experience of writing JavaScript unit tests is pretty unpleasant. And a big part of that to me is that it's the syntax often is just ugly. Writing tests in JavaScript just doesn't have that same sort of Zen-like feel that if you're using RSpec you get these nice blocks and descriptions and everything. And it just looks clean. And in JavaScript your test code is just littered with unnecessary punctuation and function statements. And even for the test frameworks that have the nicest syntax it just doesn't look very good. So as I said the implementations are buggy. And we looked at all this and we really wanted to find a good solution. We really wanted to find a way of testing our JavaScript unit test that made us actually do it. Because that's what we weren't doing.  So again tying back to the same thing as with the integration test is the easy setup. We need to get people to actually get going with this in order for them to write tests. And we really wanted to have that sort of opinionated solution. We found a lot of solutions which were solving a very specific problem. And we didn't really want that. We wanted this sort of solution that works for the 90% case. That for most people would solve the unit testing problems. We didn't really want to want to cover everything. So we didn't want to build anything huge that covered all the edge cases. But we wanted something that was good enough for the majority case. And we wanted it to be really well packaged. We wanted this to be as standalone as possible. We wanted there to be no setup, no code in our projects. It should not add any files to your project. And that obviously makes it easy to upgrade because all the code would be contained in that one single package. Basically we wanted just a Ruby gem. We wanted a Ruby gem that you could throw into your application, bundle, install and go. We also wanted this solution to be a very easy to run. That was one problem we experienced. We wanted this to be able to run in the browser because that gives you the fastest feedback loop. And when you're developing, that's really important that you can run your tests pretty much instantly. We wanted to be able to run this from the command line so that we could integrate it into our existing workflow so that we could run it on a continuous integration server and so on. And we wanted this to be able to run against multiple drivers. So one problem we found with many of the solutions was that they did come with a command line interface, but it only ran against Selenium. And they often wrote that, yeah, we have this theoretical support for other solutions, but it never actually materialized. So we wanted a solution that could, as you saw before, we have lots of different ways of running JavaScript code from the command line. But they all have their drawbacks and their advantages. And we wanted to be able to choose by project which one we were going to use. So what we came up with is this solution, Evergreen and Jasmine. So we chose what we found to be the best sort of general purpose JavaScript testing framework which is called Jasmine. It's written by Pivotal Labs. And this was really just simply what we liked best. We found that this was stable. I've yet to find any kind of bugs in it to be honest. It's pretty small and doesn't have a giant code base, but it does have all the features you'd expect. It even comes with built-in mocking framework, or spies as they call it. And it's general purpose. You can pretty much test anything you want with it. But that's also kind of its downfall. Because we found this really great testing library and we thought, yeah, let's use this for testing our Rails applications. The JavaScript and our Rails applications rather. And then we just did that and we're like, yeah, but how do we do that? And we couldn't really find a good way. It does come with a Ruby gem which is supposed to integrate it into your Rails applications. But just reading through the instructions of it, it's just, it's so complicated. There's lots of steps to getting it set up and it just, it didn't really work that well for our needs. So we wrote this sort of testing harness called Evergreen. And we think it's really cool. So what it does is it has no generators. It doesn't add any code to your project and there's no setup. And that's really what we wanted to get. It does work great with Rails.  It's however not tied to Rails in any way. And that was really one of the other things that we thought was really important. We wanted to test framework that would allow us to test JavaScript in a Sinatra app that would allow us to test our JavaScript even in an application that doesn't use Ruby at all. Or when we're building a standalone JavaScript library, like some kind of JavaScript widget or something. We didn't have a solution for that. And the existing solutions we could find, they would always tie your JavaScript tests to Rails. And we really wanted to have a nicer syntax. And at some point we found CoffeeScript. And CoffeeScript is a language which compiles down to JavaScript. So it's its own programming language but it's very similar to JavaScript. Basically with nicer syntax. And we integrated this from the beginning into Evergreen so that it would allow you to write your tests in CoffeeScript with this beautiful syntax. And you wouldn't ever have to be bothered about having to write function on every single line of your test code if you've ever written JavaScript tests. You probably know the pain of that. And one thing we really were sort of pain about with many solutions was the notion of templates. Obviously when you're writing JavaScript tests that's supposed to access the DOM, you need some kind of DOM to work against. And the usual solution to that is to have a static template which would include your JavaScript test framework and the test code you were using. And whatever HTML you would need to test against. And the problem we found with this is that you add a lot of unnecessary glue code to that template. A lot of code that you don't really need in the end and that just sort of gets in the way and becomes hard to maintain. So what we did instead is we just did these template fragments. So this was just our templates just include the actual HTML that we're testing against. They're reloaded for each test which means we have one specific div on the page which we dump all this HTML into and for each test run that div is emptied and the template is copied into it again. So that each test we're writing is isolated from the others as long as you stick to using only that div. And that really makes it very nice to sort of isolate your tests one from each other. And for running your tests we could run them in browser just by going to slash evergreen and that's a sort of default in Rails and in another framework you would have to manually mount it at a particular URL but for Rails it's mounted at slash evergreen so you can just go there, you can click on a particular spec and it will run that spec. We'll show you that in a minute. You could run them from the command line just by using rake or by using the built-in command line interface. And we built this using Kappibara obviously because that's what we know and we made it so that it can use any Kappibara driver. So you can use Selenium to run your unit tests or you can use NFJS if your code doesn't do anything fancy that wouldn't work in NFJS and so on and so forth. And that's it really. So let's show some code. We've created a very, very simple demo application. I'm just going to start by showing you the app. It looks like this. It's a whiskey browser so we can select our favorite region and show the distilleries in that region and we can select a distillery and show some of its spot lengths that it has produced. So this is a very, very simple application. No JavaScript as it is right now. To test this we have, let's see, let's get rid of that. We're just using normal R-spec integration tests and we're also using just to show in this example Cucumber as well. Probably wouldn't do both in a real application. That'd be kind of overkill. So again this is no JavaScript at all, just normal Cucumber or normal R-spec integration tests. Using Kappibara. Using Kappibara, right, but without JavaScript. But the user interface isn't really that good. I mean we're going to be relying on this application heavily. So we want to get rid of these annoying buttons when we're browsing. So we have a different branch of the code here where we've added JavaScript support. So in this case the buttons are gone. We select the region, select the distillery, same behavior, but way faster. So that's good. Now how do we test this? If we check our R-spec integration tests, we've added, actually let me get this higher up on the screen for you. So we've added a separate statement here. Can everyone see that? Good. So if we see the one without JavaScript here first, this is still using using Kappibara. So we're just saying visit the root path here and then select ILA from the region. We're clicking a button, selecting a distillery and clicking a button again and then checking for content. Now with the JavaScript the only difference here really is this part, way out to the right here. So we just say pass in js true to the it statement. That enables, that will make sure that this it statement or this code will be run in using a driver that is JavaScript compatible. And it's using, in this case the default JavaScript driver which is Selenium. But you could also configure it easily to use anything else. So the only difference here is that I've just simply removed the button clicks. So we're, the only thing we're doing is visiting the root path, selecting from the first select menu and then selecting from the second select menu and then checking for content again. And if we run this, so we can just run our spec. Good call. There we go. So we'll run the acceptance or the test in the acceptance folder here. So it runs the first one very quickly because that's without, without JavaScript. The second one takes all to load because it has to launch Firefox and, and gets Selenium going and that's the overhead of, of using Selenium there. But it runs and everything works. We can quickly just see what happens if we remove this and run it again. And we get a failure now because there is no art big option and it's still remaining because that hasn't been loaded if we're not using JavaScript. And I'm not going to show the Cucumber. This code will all be available on GitHub so you can look at it yourselves later if you want. But it's exactly the same thing just using the Cucumber's plain text and then using tags to switch, switch to the JavaScript driver. Now those were the integration tests. We also have the unit tests. So if I go to the slash evergreen path in the application, I can see that we have two unit tests here. And one for the region menu and one for the distillery menu. And I can run either one just by clicking on it. If I select show past, it shows me all of the unit tests here. And in this case, maybe a bit contrived example, but I'm actually unit testing the AJAX as well with Mox just to get some example code in there. And I can run the other one and it passes as well. So using the browser like this gives you a very, very quick feedback loop. It's very easy to just to rerun the test here. Just have to reload the page and they run. So if I don't have to wait for Selenium to start to run the test, et cetera. So this is the very, very important quick feedback loop that we're after when we're using TDD. But of course, that's not going to work in a continuous integration environment, for instance. So we can also just run them from the command line, running rake spec JavaScripts. And this will launch the Kappa Barrow driver and run it in the background. So that works as well. So what does this look like? In our spec folder here, we have a JavaScript folder and this is where the tests are. So as Jonah said, Evergreen doesn't add any code to your project. It's just a gem that you include in your gem file. And then you simply create your spec files in the spec slash JavaScript folder. And by having them end on underscore spec dot js, Evergreen picks them up automatically and runs them for you. And everything in this file is jasmine, really. We have some additions with require and we can also load templates through Evergreen here. But other than that, this is just normal jasmine. But it's still quite noisy, as you can see here. There's still all the anonymous functions that you have on every single line in your JavaScript tests. And that's not very pleasant as we talked about. So what you can do is you can write your specs in CoffeeScript instead, as Jonas mentioned. So I'll just switch to another branch here and now remove the spec dot js files and instead have spec dot coffee files. And again, there's no configuration for this. Just name your files dot coffee instead. And Evergreen will take care of the rest for you. And this is exactly same tests only written in CoffeeScript instead. So you can see it's, if you haven't looked at CoffeeScript, I'm going to encourage you to take a look at it because it's really very, very nice, especially I find when writing tests. Instead of having to write function on every line, we have the stabby lambda syntax that we have in Ruby 1.9 and it just leads to cleaner code with less noise in it really. And it runs exactly the same. If I go back to Evergreen and the browser here, you can see it has picked up the dot coffee files and I just clicked them and they run in exactly the same way. So that's really all there is to it for the demo. Again, we're making the code available so you can have a look at it, play around with it and see what this looks like in practice. So with that, we have just a few minutes left for questions. So I think if anyone has a question, you can either come up to a mic or just shout it out and we'll repeat the question. Yes. Sorry? For Kappabarra? So the question was, are there any plans to support test unit as well in Kappabarra? And Kappabarra already supports test unit. You just need to include Kappabarra in your test case class. It currently doesn't really have any special feature for sort of switching between drivers like it does in Aspect or Cucumber. So you have to call that manually. But other than that, it already does support test unit. All right. So the question was, how do you deal with the templates potentially getting out of sync with the code in your view? And for us, we found that the best solution for us was sort of to not deal with that at all. And what I mean by that is, you have, if you have your integration tests that sort of test how your components interact with each other and your JavaScript components that your unit testing are sufficiently isolated, then we found that it worked better for us to not have any kind of sort of syncing of templates or anything like that. We actually tried that in the beginning. And we found that it didn't really work quite as well as we hoped to. So in that case where we find that it would really be nice to have that, it would probably make more sense to write an integration test than a unit test. So basically you're treating your templates as fixtures and relying on the integration tests to catch any when they've come out of sync, basically. Anyone else? Yes. So the question was if we can talk about how the Selenium driver and recording video of your tests. And I don't know. I've heard a lot from different people who capture screenshots when the tests fail. I haven't actually seen anyone record an entire video of the test. I guess it would be doable if you have a scriptable application which records your screen somehow. Must exist. I don't know anything about it. Do you have anything to say? PDI. Standard answer. Any further questions? So where will it be? Yes. Thank you. Well, with that, I'm going to encourage or we're going to start drinking for the day, I think. These are the most awesome teppie bars you'll ever see, probably. They smoke cigars and drink matinis. One could be more awesome than that. Yeah, so thank you very much for coming. We have some resources here for you to check out. And I just see that Markdown has screwed up our formatting here. Yeah, it's supposed to be underscores in between. Yeah. So if you go to github.com slash elabs, there's a front-end testing repository there that has all the example code. Check out Jonas's GitHub page for Capybara and Evergreen and, of course, Pivotals for Jasmine. If you have any further questions, this is actually wrong as well. I see now. Let's see. Ping us on Twitter or something like that. Find us here and we'd be happy to talk with you. Thank you very much. Thank you.


some free agent news I'll just give you a little bit of a tease Zach Wheeler According to several different Reportings one by John Haman. I saw there are teams that are lining up to get the bidding is now at a hundred million dollars Now Zach Wheeler's a nice pitcher a hundred million dollars and you know what the white socks supposedly are in the lead for him And you know what I was just gonna say this is all bad news for the Yankees now That sounds to me like there are teams willing to overpay for pitching the Yankees don't overpay for pitching John Haman said the Yankees met in Southern California today with Cole and Tomorrow they will meet with Strasburg now that benefits Scott Boris. He represents both of those guys The Yankees are involved that might drive up the price, but again, we'll talk about this a little bit later I'd be kind of surprised at the Yankees get either of those guys because I think the money will be just so outrageous Yeah, I mean I'm looking to Yankee fans on Twitter. You're gonna have to pay whatever you can to get They're not going to do that the way it works They're in they're all in but to a point and when you see that Zach Wheeler's being offered a hundred million dollar contract Cole and Strasburg are gonna ask for even more than that and the Yankees are not gonna overpay But there'll be a team out there that will So if let's say that Strasburg ends up getting not Strasburg a Wheeler gets 23 million a year How much better how much better is Garrett Cole than then Zach Wheeler? How much better is Strasburg than Zach Wheeler? You're talking about a deal in the 30s You're starting in the 30s. Probably I think they'll both end up Well Cole will end up at 35 million a year. How many years probably seven or eight who wants to go there? We'll see the angels might maybe the Yankees say this is the guy we have that we've always said this is Brian Kassman's white whale He's missed out on them twice But it's gonna be a lot of money if Zach Wheeler has bidding that's still going on and he's at a hundred million dollars Imagine what those guys you get imagine what Madison Bumkarner is gonna get Probably more than he's worth at this stage in his career But the problem is Cole's gonna get an offer from the angels and he he likes himself from California. Yeah, well, we'll see