Skip to content

Commit

Permalink
test: add suitable test suites.
Browse files Browse the repository at this point in the history
suitable test suites.

test: suitable test suites.

test: add suitable test suites

- Add `Copilot`, `StepPerformer`, `index` and `PromptCreator` suites
- Add utils file
- Add snapshot file for `PromptCreator` test
  • Loading branch information
LironMShemen committed Jan 6, 2025
1 parent 4180c3b commit 73e1858
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 18 deletions.
59 changes: 52 additions & 7 deletions src/Copilot.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { Copilot } from '@/Copilot';
import { StepPerformer } from '@/actions/StepPerformer';
import { CopilotError } from '@/errors/CopilotError';
import { Config } from "@/types";
import fs from "fs";
import { mockCache, mockedCacheFile } from "./test-utils/cache";
import {Copilot} from '@/Copilot';
import {StepPerformer} from '@/actions/StepPerformer';
import {CopilotError} from '@/errors/CopilotError';
import {Config} from "@/types";
import {mockCache, mockedCacheFile} from "./test-utils/cache";
import {
customActionsCategory,
actionsCategory2,
actionsCategory,
tapButtonContext
} from "./test-utils/expendAPICatalogUtils";

jest.mock('@/actions/StepPerformer');
jest.mock('fs');
Expand All @@ -28,7 +33,8 @@ describe('Copilot', () => {
isSnapshotImageSupported: jest.fn().mockReturnValue(true)
}
};
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {
});

(StepPerformer.prototype.perform as jest.Mock).mockResolvedValue({code: 'code', result: true});
});
Expand Down Expand Up @@ -188,4 +194,43 @@ describe('Copilot', () => {
expect(mockedCacheFile).toBeUndefined();
});
});

describe('extend API catalog', () => {
const spyStepPerformer = jest.spyOn(StepPerformer.prototype, 'extendJSContext');
it('should extend the API catalog with a new category', () => {
Copilot.init(mockConfig);
const instance = Copilot.getInstance();

instance.extendAPICatalog(actionsCategory);

expect(mockConfig.frameworkDriver.apiCatalog.categories).toEqual(actionsCategory);
expect(spyStepPerformer).not.toHaveBeenCalled();

});

it('should extend the API catalog with a new category and context', () => {
Copilot.init(mockConfig);
const instance = Copilot.getInstance();
instance.extendAPICatalog(actionsCategory, tapButtonContext);

expect(mockConfig.frameworkDriver.apiCatalog.categories).toEqual(actionsCategory);
expect(spyStepPerformer).toHaveBeenCalledWith(tapButtonContext);
});

it('should expend the API catalog with an existing category and an additional new category', () => {
Copilot.init(mockConfig);
const instance = Copilot.getInstance();

// item is added to existing category
instance.extendAPICatalog(actionsCategory)
instance.extendAPICatalog(actionsCategory2, tapButtonContext);
expect(mockConfig.frameworkDriver.apiCatalog.categories).toEqual([...actionsCategory]);
expect(mockConfig.frameworkDriver.apiCatalog.categories[0].items).toHaveLength(2);
expect(spyStepPerformer).toHaveBeenCalledWith(tapButtonContext);

// another category is added
instance.extendAPICatalog(customActionsCategory);
expect(mockConfig.frameworkDriver.apiCatalog.categories).toEqual([...actionsCategory, ...customActionsCategory]);
});
});
});
35 changes: 35 additions & 0 deletions src/actions/StepPerformer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {SnapshotManager} from '@/utils/SnapshotManager';
import {CacheHandler} from '@/utils/CacheHandler';
import {PromptHandler, TestingFrameworkAPICatalog} from '@/types';
import * as crypto from 'crypto';
import {functionContext, tapButtonContext, newFunctionContext} from "../test-utils/expendAPICatalogUtils";

jest.mock('fs');
jest.mock('crypto');
Expand Down Expand Up @@ -283,4 +284,38 @@ describe('StepPerformer', () => {
expect(mockCodeEvaluator.evaluate).toHaveBeenCalledWith('generated code', mockContext);
expect(mockCacheHandler.addToTemporaryCache).toHaveBeenCalled();
});

describe('extendJSContext', () =>{
it('should extend the context with the given object', async () => {
// Initial context
stepPerformer.extendJSContext(functionContext);

setupMocks();
await stepPerformer.perform(INTENT);
expect(mockCodeEvaluator.evaluate).toHaveBeenCalledWith(PROMPT_RESULT, functionContext);

// Extended context
const newFixedContext = { ...functionContext, ...tapButtonContext };
stepPerformer.extendJSContext(tapButtonContext);

await stepPerformer.perform(INTENT);
expect(mockCodeEvaluator.evaluate).toHaveBeenCalledWith(PROMPT_RESULT, newFixedContext);
});

it('should log when a context is overridden', async () => {
jest.spyOn(console, 'log');
stepPerformer.extendJSContext(functionContext);

setupMocks();
await stepPerformer.perform(INTENT);
expect(mockCodeEvaluator.evaluate).toHaveBeenCalledWith(PROMPT_RESULT, functionContext);

stepPerformer.extendJSContext(newFunctionContext);
expect(console.log).toHaveBeenCalledWith('Notice: Context function is overridden by the new context value');

await stepPerformer.perform(INTENT);
expect(mockCodeEvaluator.evaluate).toHaveBeenCalledWith(PROMPT_RESULT, newFunctionContext);

});
});
});
31 changes: 28 additions & 3 deletions src/integration tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import copilot from "@/index";
import fs from 'fs';
import { Copilot } from "@/Copilot";
import { PromptHandler, TestingFrameworkDriver } from "@/types";
import {Copilot} from "@/Copilot";
import {PromptHandler, TestingFrameworkDriver} from "@/types";
import * as crypto from 'crypto';
import {mockedCacheFile, mockCache} from "../test-utils/cache";
import {PromptCreator} from "../utils/PromptCreator";
import {StepPerformer} from "../actions/StepPerformer";
import {customActionsCategory, actionsCategory, tapButtonContext} from "../test-utils/expendAPICatalogUtils";

jest.mock('crypto');
jest.mock('fs');
Expand Down Expand Up @@ -79,7 +82,6 @@ describe('Copilot Integration Tests', () => {

it('should successfully perform an action', async () => {
mockPromptHandler.runPrompt.mockResolvedValue('// No operation');

await expect(copilot.perform('Tap on the login button')).resolves.not.toThrow();

expect(mockFrameworkDriver.captureSnapshotImage).toHaveBeenCalled();
Expand Down Expand Up @@ -330,4 +332,27 @@ describe('Copilot Integration Tests', () => {
);
});
});

describe('API Catalog Extension', () => {
const spyPromptCreator = jest.spyOn(PromptCreator.prototype, 'extendAPICategories');
const spyStepPerformer = jest.spyOn(StepPerformer.prototype, 'extendJSContext');

beforeEach(() => {
jest.clearAllMocks();
copilot.init({
frameworkDriver: mockFrameworkDriver,
promptHandler: mockPromptHandler,
});
copilot.start();
});
it('should call relevant functions to extend the catalog', () => {

copilot.extendAPICatalog(customActionsCategory);
expect(spyPromptCreator).toHaveBeenCalledTimes(1);

copilot.extendAPICatalog(actionsCategory, tapButtonContext);
expect(spyPromptCreator).toHaveBeenCalledTimes(2);
expect(spyStepPerformer).toHaveBeenCalledTimes(1);
});
});
});
39 changes: 39 additions & 0 deletions src/test-utils/expendAPICatalogUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export const customActionsCategory = [{
title: 'Custom Actions',
items: [
{
signature: 'swipe(direction: string)',
description: 'Swipes in the specified direction.',
example: 'await swipe("up");',
guidelines: ['Use this method to scroll the screen.']
}
]
}];

export const actionsCategory = [{
title: 'Actions',
items: [
{
signature: 'tapButton(id: string)',
description: 'Taps the button with the specified ID.',
example: 'await tapButton("submit");',
guidelines: ['Use this method to tap buttons.']
}
]
}];

export const actionsCategory2 = [{
title: 'Actions',
items: [
{
signature: 'swipe(direction: string)',
description: 'Swipes in the specified direction.',
example: 'await swipe("up");',
guidelines: ['Use this method to scroll the screen.']
}
]
}];

export const tapButtonContext = {tapButton: 'new tap button'};
export const functionContext = {function: 'newFlow'};
export const newFunctionContext = {function: 'newFunction'};
8 changes: 4 additions & 4 deletions src/utils/CacheHandler.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CacheHandler } from './CacheHandler';
import { mockCache, mockedCacheFile} from "../test-utils/cache";
import {CacheHandler} from './CacheHandler';
import {mockCache, mockedCacheFile} from "../test-utils/cache";

jest.mock('fs');

Expand All @@ -13,7 +13,7 @@ describe('CacheHandler', () => {

describe('cache and file operations', () => {
it('should load cache from file successfully if the file exists and is valid', () => {
mockCache({ 'cacheKey': 'value' });
mockCache({'cacheKey': 'value'});

expect(cacheHandler.getStepFromCache('cacheKey')).toBeUndefined();

Expand All @@ -28,7 +28,7 @@ describe('CacheHandler', () => {
cacheHandler.addToTemporaryCache('cacheKey', 'value');
cacheHandler.flushTemporaryCache();

expect(mockedCacheFile).toEqual({ 'cacheKey': 'value' });
expect(mockedCacheFile).toEqual({'cacheKey': 'value'});
});
});

Expand Down
4 changes: 2 additions & 2 deletions src/utils/CodeEvaluator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CodeEvaluator } from '@/utils/CodeEvaluator';
import {CodeEvaluator} from '@/utils/CodeEvaluator';

describe('CodeEvaluator', () => {
let codeEvaluator: CodeEvaluator;
Expand Down Expand Up @@ -26,7 +26,7 @@ describe('CodeEvaluator', () => {
const contextVariable = 43;
const validCode = 'return contextVariable - 1;';

await expect(codeEvaluator.evaluate(validCode, { contextVariable })).resolves.toStrictEqual({
await expect(codeEvaluator.evaluate(validCode, {contextVariable})).resolves.toStrictEqual({
code: 'return contextVariable - 1;',
result: 42
});
Expand Down
22 changes: 21 additions & 1 deletion src/utils/PromptCreator.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { PromptCreator } from './PromptCreator';
import {PromptCreator} from './PromptCreator';
import {
PreviousStep,
TestingFrameworkAPICatalog
} from "@/types";
import {customActionsCategory, actionsCategory2} from "../test-utils/expendAPICatalogUtils";

const mockAPI: TestingFrameworkAPICatalog = {
context: {},
Expand Down Expand Up @@ -93,4 +94,23 @@ describe('PromptCreator', () => {

expect(prompt).toMatchSnapshot();
});

describe('extentAPICategories', () => {
it('should extend the API catalog with new or exist category', () => {
// Add new category
const intent = 'expect button to be visible';
const viewHierarchy = '<View><Button testID="submit" title="Submit" /></View>';

promptCreator.extendAPICategories(customActionsCategory);
const promptNewCategory = promptCreator.createPrompt(intent, viewHierarchy, false, []);

expect(promptNewCategory).toMatchSnapshot();

// Add items to existing category
promptCreator.extendAPICategories(actionsCategory2);
const promptOldCategory = promptCreator.createPrompt(intent, viewHierarchy, false, []);

expect(promptOldCategory).toMatchSnapshot();
});
});
});
Loading

0 comments on commit 73e1858

Please sign in to comment.