summaryrefslogtreecommitdiff
path: root/packages/core/src/utils/partUtils.test.ts
diff options
context:
space:
mode:
authorHyeongHo Jun <[email protected]>2025-07-23 08:57:06 +0900
committerGitHub <[email protected]>2025-07-22 23:57:06 +0000
commita00f1bb916b551fc17fa5bab80fb51dcdc88f00d (patch)
tree301797288462e03f8e954f03d526cc6ddaf0a7ab /packages/core/src/utils/partUtils.test.ts
parent487debe525fa20c7bbfb3393ce455fbbae1aab3f (diff)
feat(core): add partUtils module with unit tests (#4575)
Co-authored-by: Jacob Richman <[email protected]>
Diffstat (limited to 'packages/core/src/utils/partUtils.test.ts')
-rw-r--r--packages/core/src/utils/partUtils.test.ts166
1 files changed, 166 insertions, 0 deletions
diff --git a/packages/core/src/utils/partUtils.test.ts b/packages/core/src/utils/partUtils.test.ts
new file mode 100644
index 00000000..eda85df2
--- /dev/null
+++ b/packages/core/src/utils/partUtils.test.ts
@@ -0,0 +1,166 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import { describe, it, expect } from 'vitest';
+import { partToString, getResponseText } from './partUtils.js';
+import { GenerateContentResponse, Part } from '@google/genai';
+
+const mockResponse = (
+ parts?: Array<{ text?: string; functionCall?: unknown }>,
+): GenerateContentResponse => ({
+ candidates: parts
+ ? [{ content: { parts: parts as Part[], role: 'model' }, index: 0 }]
+ : [],
+ promptFeedback: { safetyRatings: [] },
+ text: undefined,
+ data: undefined,
+ functionCalls: undefined,
+ executableCode: undefined,
+ codeExecutionResult: undefined,
+});
+
+describe('partUtils', () => {
+ describe('partToString (default behavior)', () => {
+ it('should return empty string for undefined or null', () => {
+ // @ts-expect-error Testing invalid input
+ expect(partToString(undefined)).toBe('');
+ // @ts-expect-error Testing invalid input
+ expect(partToString(null)).toBe('');
+ });
+
+ it('should return string input unchanged', () => {
+ expect(partToString('hello')).toBe('hello');
+ });
+
+ it('should concatenate strings from an array', () => {
+ expect(partToString(['a', 'b'])).toBe('ab');
+ });
+
+ it('should return text property when provided a text part', () => {
+ expect(partToString({ text: 'hi' })).toBe('hi');
+ });
+
+ it('should return empty string for non-text parts', () => {
+ const part: Part = { inlineData: { mimeType: 'image/png', data: '' } };
+ expect(partToString(part)).toBe('');
+ const part2: Part = { functionCall: { name: 'test' } };
+ expect(partToString(part2)).toBe('');
+ });
+ });
+
+ describe('partToString (verbose)', () => {
+ const verboseOptions = { verbose: true };
+
+ it('should return empty string for undefined or null', () => {
+ // @ts-expect-error Testing invalid input
+ expect(partToString(undefined, verboseOptions)).toBe('');
+ // @ts-expect-error Testing invalid input
+ expect(partToString(null, verboseOptions)).toBe('');
+ });
+
+ it('should return string input unchanged', () => {
+ expect(partToString('hello', verboseOptions)).toBe('hello');
+ });
+
+ it('should join parts if the value is an array', () => {
+ const parts = ['hello', { text: ' world' }];
+ expect(partToString(parts, verboseOptions)).toBe('hello world');
+ });
+
+ it('should return the text property if the part is an object with text', () => {
+ const part: Part = { text: 'hello world' };
+ expect(partToString(part, verboseOptions)).toBe('hello world');
+ });
+
+ it('should return descriptive string for videoMetadata part', () => {
+ const part = { videoMetadata: {} } as Part;
+ expect(partToString(part, verboseOptions)).toBe('[Video Metadata]');
+ });
+
+ it('should return descriptive string for thought part', () => {
+ const part = { thought: 'thinking' } as unknown as Part;
+ expect(partToString(part, verboseOptions)).toBe('[Thought: thinking]');
+ });
+
+ it('should return descriptive string for codeExecutionResult part', () => {
+ const part = { codeExecutionResult: {} } as Part;
+ expect(partToString(part, verboseOptions)).toBe(
+ '[Code Execution Result]',
+ );
+ });
+
+ it('should return descriptive string for executableCode part', () => {
+ const part = { executableCode: {} } as Part;
+ expect(partToString(part, verboseOptions)).toBe('[Executable Code]');
+ });
+
+ it('should return descriptive string for fileData part', () => {
+ const part = { fileData: {} } as Part;
+ expect(partToString(part, verboseOptions)).toBe('[File Data]');
+ });
+
+ it('should return descriptive string for functionCall part', () => {
+ const part = { functionCall: { name: 'myFunction' } } as Part;
+ expect(partToString(part, verboseOptions)).toBe(
+ '[Function Call: myFunction]',
+ );
+ });
+
+ it('should return descriptive string for functionResponse part', () => {
+ const part = { functionResponse: { name: 'myFunction' } } as Part;
+ expect(partToString(part, verboseOptions)).toBe(
+ '[Function Response: myFunction]',
+ );
+ });
+
+ it('should return descriptive string for inlineData part', () => {
+ const part = { inlineData: { mimeType: 'image/png', data: '' } } as Part;
+ expect(partToString(part, verboseOptions)).toBe('<image/png>');
+ });
+
+ it('should return an empty string for an unknown part type', () => {
+ const part: Part = {};
+ expect(partToString(part, verboseOptions)).toBe('');
+ });
+
+ it('should handle complex nested arrays with various part types', () => {
+ const parts = [
+ 'start ',
+ { text: 'middle' },
+ [
+ { functionCall: { name: 'func1' } },
+ ' end',
+ { inlineData: { mimeType: 'audio/mp3', data: '' } },
+ ],
+ ];
+ expect(partToString(parts as Part, verboseOptions)).toBe(
+ 'start middle[Function Call: func1] end<audio/mp3>',
+ );
+ });
+ });
+
+ describe('getResponseText', () => {
+ it('should return null when no candidates exist', () => {
+ const response = mockResponse(undefined);
+ expect(getResponseText(response)).toBeNull();
+ });
+
+ it('should return concatenated text from first candidate', () => {
+ const result = mockResponse([{ text: 'a' }, { text: 'b' }]);
+ expect(getResponseText(result)).toBe('ab');
+ });
+
+ it('should ignore parts without text', () => {
+ const result = mockResponse([{ functionCall: {} }, { text: 'hello' }]);
+ expect(getResponseText(result)).toBe('hello');
+ });
+
+ it('should return null when candidate has no parts', () => {
+ const result = mockResponse([]);
+ expect(getResponseText(result)).toBeNull();
+ });
+ });
+});