Skip to content

Add tests for Model Details View#2735

Merged
norascheuch merged 6 commits intomainfrom
nora/test-model-details-view
Aug 24, 2023
Merged

Add tests for Model Details View#2735
norascheuch merged 6 commits intomainfrom
nora/test-model-details-view

Conversation

@norascheuch
Copy link
Copy Markdown
Contributor

Adds tests for

  • model details panel set state
  • reveal logic
  • model details provider getChildren

Checklist

  • CHANGELOG.md has been updated to incorporate all user visible changes made by this pull request.
  • Issues have been created for any UI or other user-facing changes made by this pull request.
  • [Maintainers only] If this pull request makes user-facing changes that require documentation changes, open a corresponding docs pull request in the github/codeql repo and add the ready-for-doc-review label there.

@norascheuch norascheuch requested a review from a team as a code owner August 22, 2023 13:13
Copy link
Copy Markdown
Contributor

@robertbrignull robertbrignull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like what the tests are testing. That's exactly what I meant and wanted to see! 🙇🏼

I think the tests would be better and more robust to changes if we reduced the frequency of mockedObject and defined objects more fully. What are other people's thoughts?

});

it("should return [] if item is a usage", async () => {
const item = { usages: undefined } as unknown as ModelDetailsTreeViewItem;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid using as unknown as X? Instead define a proper Usage object.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


describe("getChildren", () => {
const externalApiUsages: ExternalApiUsage[] = [
mockedObject<ExternalApiUsage>({ supported: true }),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the desire here is to avoid the pain of providing full objects, but mockedObject is going to potentially cause some issues here that will be hard to debug for future developers. I think you've already hit this, as evidenced by needing to pass usages: undefined in some cases.

In ModelDetailsDataProvider we use isExternalApiUsage to determine if the object we have is an ExternalApiUsage or a Usage. Unfortunately this check won't work correctly when given an object created using mockedObject, or at least you have to know exactly what you're doing and pass the right field values to make isExternalApiUsage behave correctly. While it is possible to have everything work correctly like this, it's quite error prone.

While it's is great for things like CodeQLCliServer, I would recommend not using mockedObject for types like ExternalApiUsage and Usage. How much effort would it be to not do this?

methodParameters: "test",
},
];
const dbItem = mockedObject<DatabaseItem>({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We define the exact same dbItem in each describe block. Could we move the definition one level higher, like where we make mockCliServer?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

});

it("should reveal the correct item in the tree view", async () => {
const externalApiUsages = mockedObject<ExternalApiUsage[]>([
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again as commented on the other file, I suggest avoiding using mockedObject for the ExternalApiUsage type. We already define a full ExternalApiUsage object earlier in this file, so could we reuse that? Or perhaps add a factory method for making ExternalApiUsage objects (see the test/factories directory)?

@norascheuch norascheuch requested a review from a team as a code owner August 23, 2023 16:06
Copy link
Copy Markdown
Contributor

@charisk charisk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Just some comments for potential improvements.

});

it("should show all externalApiUsages if hideModeledApis is false and item is undefined", async () => {
const hideModeledApis: boolean = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Minor) you shouldn't need to define the type

Suggested change
const hideModeledApis: boolean = false;
const hideModeledApis = false;

Same on L132 and a few places in model-details-panel.test.ts - worth doing a search for const hideModeledApis: boolean = to find all occurrences.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

beforeEach(() => {
mockTreeView = {
reveal: jest.fn(),
} as unknown as TreeView<unknown>;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is similar to as any as X so we should ideally avoid it. Is there a way to get around it easily, or is creating mock TreeView<>T> items too painful? I'm happy to take it on as tech debt too.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem lies in the reveal: jest.fn(). Without it we could remove the as unknown. With it we would have to mock the vs code reveal method better. I'm not sure if that is easily possible? We only check if reveal was called, not what it does. Therefore I leaned towards leaving it as is. However, can we introduce other errors by using as unknown here apart from the reveal method?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets leave it as is. I imagine creating the mock properly isn't trivial.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for talking this through. I think mockedObject could be a good solution for this case. I've opened #2768 for this where I've tried to explain my reasoning, so let me know what you think.

expect(dataProvider.getChildren(externalApiUsage)).toEqual([usage]);
});

it("should show all externalApiUsages if hideModeledApis is false and item is undefined", async () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Minor) The item is undefined bit confused me a little bit but I realised what it meant once I got to know the code a bit better. We don't have to change it, but do you think the following description is accurate/better:

Suggested change
it("should show all externalApiUsages if hideModeledApis is false and item is undefined", async () => {
it("should show all externalApiUsages if hideModeledApis is false and looking at the root", async () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good, will rename!

@norascheuch norascheuch merged commit 422f6de into main Aug 24, 2023
@norascheuch norascheuch deleted the nora/test-model-details-view branch August 24, 2023 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants