-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tests for Edit.focusHint #468
Comments
@pcardune working on this now, and plan of attack is to add an The problem is that the editor is just a |
I would say to avoid changing any interface for the sole purpose of writing a test. I was imagining these being more like unit tests. Using I was imagining just directly calling it("DeleteChildEdit removes a node from its parent", () => {
const edit = edit_delete(ast, [...ast.rootNodes[1].children()][1]);
expect(edit.toString()).toEqual("DeleteChild 2:13-2:26");
const result = apply([edit]);
if (!result.successful) {
fail();
}
expect(edit.focusHint(result.value.newAST)).toEqual(...);
...
}); Separately, it would be useful to have tests for In the end, the line that you draw in the sand that determines what code is being tested is a highly debatable topic. You could argue (as many people do) that you should only write integration tests since that's how users will interact with your code and it's easier to completely rewrite/refactor the implementation without having to change any tests (yay!). At the same time, you could argue (as many people do) that you should just write unit tests that cover the smallest area of code possible (like an individual function), since it makes it easier to determine where the problem is when a test fails, generally encourages you to design better APIs that are easier to test, and can serve as documentation for how the code works (yay!). Finally, there is the giant gray area of what you should consider a "unit". It could be an individual function, or an individual file, or an individual collection of files that support a specific feature, or an individual npm package, etc. I could be convinced that the entire collection of files in the |
@pcardune spent a few hours trying to track down the discontinuity between the way focusHint is constructed in the test vs. how it runs in the editor. I originally thought the culprit was a difference in the way edits are passed, but before the focusHint is computed these edits are coalesced in a way that results in the same hint being used no matter what. So why is the hint different when the same operation is performed in the test vs. the editor? I was able to trace it back to the creation of the To get some debugging output, I changed the
When making the same change in the editor that's made in the test, I get two different console outputs! The test output includes the prevId ( I'm surprised to see that the id is different, and stumped as to why the node isn't getting returned. I'm guessing there is something about the way the tests are run that results in different state than the live version, but I don't know what that is. I've pushed the code with the debugging out to schanzer/fix-468. |
@pcardune I again modified the
BEFORE THE EDIT: AFTER THE EDIT: The live editor goes looking for nodeId |
This is great sleuthing. I'm not really surprised that the node ids are different in the tests. It's really not the goal of the tests to replicate the behavior of the live editor (they are unit tests, not integration tests), and the fact that the ids are different doesn't indicate that there is necessarily a bug. I think the discrepancies you are running into, and the confusion you are having in the face of those discrepancies, is really an indication of the (over?) complexity of the system and how poorly defined the contracts are between different areas of code. For example, the In an ideal world, the API is designed in such a way that it can't be used "incorrectly". In practice, that's rarely possible, and it's just a question of how close you can get with the tools available to you. Static types help, runtime error checking helps, certain design patterns help, documentation helps, but you'll always have some degree of "if you call this function in the wrong way, the expected behavior is undefined." I think a good goal for you with these tests would be to:
And to be a bit more specific about all of the above points, the goal would be to understand, document, and test the usage of performEdits.ts without referencing anything outside of performEdits.ts. If your answer to the question "how is it supposed to be used?" is "however it's currently being used", then that is the wrong answer. If I'm brand new to the code, I don't want to have to understand how all the code works in order to understand how part of the code works. In going through the above steps, you might notice that performEdits.ts actually does a lot of stuff, and some of those things seem very unrelated to the other things it does, and it's really hard to explain it all in a straightforward way without complex diagrams. At that point it will be easier to see how you might (or might not) be able to refactor it into simpler components that are harder to use incorrectly. But I wouldn't pull too hard on that thread before getting the current implementation documented and tested. FWIW, I think the difference in node ids is because the full editor generates several new copies of the AST when switching to block mode: 1) parse the text to generate an AST, 2) pretty-print that AST back to text and then parse the pretty-printed version back again to make sure you can do a full round trip. The tests operate at a layer of abstraction below the notion of "block mode" vs "text mode" so none of that needs to happen. |
@pcardune agreed that my first concern is just a function of the full editor doing the double-parse. I wasn't sure if the CMFacade skipped that, so I'm glad to hear this is expected. That means the issue could be second concern: the I think you're absolutely right that the most suspicious thing here is some kind of misalignment between which AST is used when. I'll start digging there first, and if I come up empty I'll look more closely at the differences in trees created by |
Some of this is covered by focus-test, but since focusing is so complex, it would be nice to have some tests that just deal with how performEdit provides hints for which node to focus on after the edit has occurred. These can go in performEdit-test.ts
The text was updated successfully, but these errors were encountered: