mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-28 05:55:17 -07:00
Increase code coverage for core packages (#12872)
This commit is contained in:
@@ -647,6 +647,254 @@ describe('IdeClient', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveDiffFromCli', () => {
|
||||
beforeEach(async () => {
|
||||
// Ensure client is "connected" for these tests
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
// We need to set the client property on the instance for openDiff to work
|
||||
(ideClient as unknown as { client: Client }).client = mockClient;
|
||||
mockClient.request.mockResolvedValue({
|
||||
isError: false,
|
||||
content: [],
|
||||
});
|
||||
});
|
||||
|
||||
it("should resolve an open diff as 'accepted' and return the final content", async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const closeDiffSpy = vi
|
||||
.spyOn(
|
||||
ideClient as unknown as {
|
||||
closeDiff: () => Promise<string | undefined>;
|
||||
},
|
||||
'closeDiff',
|
||||
)
|
||||
.mockResolvedValue('final content from ide');
|
||||
|
||||
const diffPromise = ideClient.openDiff('/test.txt', 'new content');
|
||||
|
||||
// Yield to the event loop to allow the openDiff promise executor to run
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
|
||||
await ideClient.resolveDiffFromCli('/test.txt', 'accepted');
|
||||
|
||||
const result = await diffPromise;
|
||||
|
||||
expect(result).toEqual({
|
||||
status: 'accepted',
|
||||
content: 'final content from ide',
|
||||
});
|
||||
expect(closeDiffSpy).toHaveBeenCalledWith('/test.txt', {
|
||||
suppressNotification: true,
|
||||
});
|
||||
expect(
|
||||
(
|
||||
ideClient as unknown as { diffResponses: Map<string, unknown> }
|
||||
).diffResponses.has('/test.txt'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("should resolve an open diff as 'rejected'", async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const closeDiffSpy = vi
|
||||
.spyOn(
|
||||
ideClient as unknown as {
|
||||
closeDiff: () => Promise<string | undefined>;
|
||||
},
|
||||
'closeDiff',
|
||||
)
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
const diffPromise = ideClient.openDiff('/test.txt', 'new content');
|
||||
|
||||
// Yield to the event loop to allow the openDiff promise executor to run
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
|
||||
await ideClient.resolveDiffFromCli('/test.txt', 'rejected');
|
||||
|
||||
const result = await diffPromise;
|
||||
|
||||
expect(result).toEqual({
|
||||
status: 'rejected',
|
||||
content: undefined,
|
||||
});
|
||||
expect(closeDiffSpy).toHaveBeenCalledWith('/test.txt', {
|
||||
suppressNotification: true,
|
||||
});
|
||||
expect(
|
||||
(
|
||||
ideClient as unknown as { diffResponses: Map<string, unknown> }
|
||||
).diffResponses.has('/test.txt'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should do nothing if no diff is open for the given file path', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const closeDiffSpy = vi
|
||||
.spyOn(
|
||||
ideClient as unknown as {
|
||||
closeDiff: () => Promise<string | undefined>;
|
||||
},
|
||||
'closeDiff',
|
||||
)
|
||||
.mockResolvedValue(undefined);
|
||||
|
||||
// No call to openDiff, so no resolver will exist.
|
||||
await ideClient.resolveDiffFromCli('/non-existent.txt', 'accepted');
|
||||
|
||||
expect(closeDiffSpy).toHaveBeenCalledWith('/non-existent.txt', {
|
||||
suppressNotification: true,
|
||||
});
|
||||
// No crash should occur, and nothing should be in the map.
|
||||
expect(
|
||||
(
|
||||
ideClient as unknown as { diffResponses: Map<string, unknown> }
|
||||
).diffResponses.has('/non-existent.txt'),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('closeDiff', () => {
|
||||
beforeEach(async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
(ideClient as unknown as { client: Client }).client = mockClient;
|
||||
});
|
||||
|
||||
it('should return undefined if client is not connected', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
(ideClient as unknown as { client: Client | undefined }).client =
|
||||
undefined;
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should call client.request with correct arguments', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
// Return a valid, empty response as the return value is not under test here.
|
||||
mockClient.request.mockResolvedValue({ isError: false, content: [] });
|
||||
|
||||
await (
|
||||
ideClient as unknown as {
|
||||
closeDiff: (
|
||||
f: string,
|
||||
o?: { suppressNotification?: boolean },
|
||||
) => Promise<void>;
|
||||
}
|
||||
).closeDiff('/test.txt', { suppressNotification: true });
|
||||
|
||||
expect(mockClient.request).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
params: {
|
||||
name: 'closeDiff',
|
||||
arguments: {
|
||||
filePath: '/test.txt',
|
||||
suppressNotification: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
expect.any(Object), // Schema
|
||||
expect.any(Object), // Options
|
||||
);
|
||||
});
|
||||
|
||||
it('should return content from a valid JSON response', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const response = {
|
||||
isError: false,
|
||||
content: [
|
||||
{ type: 'text', text: JSON.stringify({ content: 'file content' }) },
|
||||
],
|
||||
};
|
||||
mockClient.request.mockResolvedValue(response);
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<string> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBe('file content');
|
||||
});
|
||||
|
||||
it('should return undefined for a valid JSON response with null content', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const response = {
|
||||
isError: false,
|
||||
content: [{ type: 'text', text: JSON.stringify({ content: null }) }],
|
||||
};
|
||||
mockClient.request.mockResolvedValue(response);
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined if response is not valid JSON', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const response = {
|
||||
isError: false,
|
||||
content: [{ type: 'text', text: 'not json' }],
|
||||
};
|
||||
mockClient.request.mockResolvedValue(response);
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined if request result has isError: true', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const response = {
|
||||
isError: true,
|
||||
content: [{ type: 'text', text: 'An error occurred' }],
|
||||
};
|
||||
mockClient.request.mockResolvedValue(response);
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined if client.request throws', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
mockClient.request.mockRejectedValue(new Error('Request failed'));
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined if response has no text part', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
const response = {
|
||||
isError: false,
|
||||
content: [{ type: 'other' }],
|
||||
};
|
||||
mockClient.request.mockResolvedValue(response);
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined if response is falsy', async () => {
|
||||
const ideClient = await IdeClient.getInstance();
|
||||
// Mocking with `null as any` to test the falsy path, as the mock
|
||||
// function is strictly typed.
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
mockClient.request.mockResolvedValue(null as any);
|
||||
|
||||
const result = await (
|
||||
ideClient as unknown as { closeDiff: (f: string) => Promise<void> }
|
||||
).closeDiff('/test.txt');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('authentication', () => {
|
||||
it('should connect with an auth token if provided in the discovery file', async () => {
|
||||
const authToken = 'test-auth-token';
|
||||
|
||||
Reference in New Issue
Block a user