Skip to content

Commit

Permalink
chore: add a check in the PromptCreator constructor to merge redund…
Browse files Browse the repository at this point in the history
…ant categories in the API catalog

due to the fact is that a merge like this happens when we extend the API, and to maintain consistency.
  • Loading branch information
LironMShemen committed Jan 13, 2025
1 parent 1d600dc commit 3b44fd6
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 10 deletions.
63 changes: 63 additions & 0 deletions src/test-utils/APICatalogTestUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {TestingFrameworkAPICatalog} from "@/types";

export const bazCategory = {
title: 'Custom Actions',
items: [
Expand Down Expand Up @@ -37,3 +39,64 @@ export const barCategory2 = {
export const dummyContext = {foo: jest.fn()};
export const dummyBarContext1 = {bar: jest.fn()};
export const dummyBarContext2 = {bar: jest.fn()};

export const promptCreatorConstructorMockAPI: TestingFrameworkAPICatalog = {
context: {},
categories: [
{
title: 'Actions',
items: [{
signature: 'tap(element: Element)',
description: 'Taps on the specified element.',
example: 'await element(by.id("button")).tap();',
guidelines: ['Ensure the element is tappable before using this method.']
},
{
signature: 'typeText(element: Element, text: string)',
description: 'Types the specified text into the element.',
example: 'await element(by.id("input")).typeText("Hello, World!");',
guidelines: ['Use this method only on text input elements.']
}]
},
{
title: 'Assertions',
items: [{
signature: 'toBeVisible()',
description: 'Asserts that the element is visible on the screen.',
example: 'await expect(element(by.id("title"))).toBeVisible();',
guidelines: ['Consider scroll position when using this assertion.']
}]
},
{
title: 'Assertions',
items: [{
signature: 'toBeEnabled()',
description: 'Asserts that the element is enabled and can be interacted with.',
example: 'await expect(element(by.id("submitButton"))).toBeEnabled();',
guidelines: ['Ensure that the element is not disabled before performing actions.']
}]
},
{
title: 'Matchers',
items: [
{
signature: 'by.id(id: string)',
description: 'Matches elements by their ID attribute.',
example: 'element(by.id("uniqueId"))',
guidelines: ['Use unique IDs for elements to avoid conflicts, combine with atIndex() if necessary.']
}
]
},
{
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.']
}
]
}
]
};
26 changes: 16 additions & 10 deletions src/utils/PromptCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,30 @@ import {

export class PromptCreator {
constructor(private apiCatalog: TestingFrameworkAPICatalog) {
this.apiCatalog.categories = this.mergeCategories(this.apiCatalog.categories);
}

extendAPICategories(
newCategories: TestingFrameworkAPICatalogCategory[] | TestingFrameworkAPICatalogCategory
newCategories: TestingFrameworkAPICatalogCategory[]
): void {
const categories = Array.isArray(newCategories) ? newCategories : [newCategories];
this.apiCatalog.categories = this.mergeCategories([...this.apiCatalog.categories, ...newCategories]);
}

categories.forEach((category) => {
const existingCategory = this.apiCatalog.categories.find(
(c) => c.title === category.title
);
private mergeCategories(categories: TestingFrameworkAPICatalogCategory[]): TestingFrameworkAPICatalogCategory[] {
return categories.reduce((mergedCategories, category) => {
const existingIndex = mergedCategories.findIndex(c => c.title === category.title);

if (existingCategory) {
existingCategory.items.push(...category.items);
const uniqueItems = (items: TestingFrameworkAPICatalogItem[]) => Array.from(new Set(items));

if (existingIndex >= 0) {
mergedCategories[existingIndex].items = uniqueItems([...mergedCategories[existingIndex].items, ...category.items]);
return mergedCategories;
} else {
this.apiCatalog.categories.push(category);
category.items = uniqueItems(category.items);
}
});

return [...mergedCategories, {...category}];
}, [] as TestingFrameworkAPICatalogCategory[]);
}

createPrompt(
Expand Down
140 changes: 140 additions & 0 deletions src/utils/__snapshots__/PromptCreator.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,145 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PromptCreator constructor should merge redundant categories 1`] = `
"# Test Code Generation
You are an AI assistant tasked with generating test code for an application using the provided UI testing framework API.
Please generate the minimal executable code to perform the desired intent based on the given information and context.
## Context
### Intent to perform
Generate the minimal executable code to perform the following intent: "expect button to be visible"
### View hierarchy
\`\`\`
<View><Button testID="submit" title="Submit" /></View>
\`\`\`
### Snapshot image
No snapshot image is attached for this intent.
## Available Testing Framework API
### Actions
#### tap(element: Element)
Taps on the specified element.
##### Example
\`\`\`
await element(by.id("button")).tap();
\`\`\`
##### Guidelines
- Ensure the element is tappable before using this method.
#### typeText(element: Element, text: string)
Types the specified text into the element.
##### Example
\`\`\`
await element(by.id("input")).typeText("Hello, World!");
\`\`\`
##### Guidelines
- Use this method only on text input elements.
#### swipe(direction: string)
Swipes in the specified direction.
##### Example
\`\`\`
await swipe("up");
\`\`\`
##### Guidelines
- Use this method to scroll the screen.
### Assertions
#### toBeVisible()
Asserts that the element is visible on the screen.
##### Example
\`\`\`
await expect(element(by.id("title"))).toBeVisible();
\`\`\`
##### Guidelines
- Consider scroll position when using this assertion.
#### toBeEnabled()
Asserts that the element is enabled and can be interacted with.
##### Example
\`\`\`
await expect(element(by.id("submitButton"))).toBeEnabled();
\`\`\`
##### Guidelines
- Ensure that the element is not disabled before performing actions.
### Matchers
#### by.id(id: string)
Matches elements by their ID attribute.
##### Example
\`\`\`
element(by.id("uniqueId"))
\`\`\`
##### Guidelines
- Use unique IDs for elements to avoid conflicts, combine with atIndex() if necessary.
## Instructions
Your task is to generate the minimal executable code to perform the following intent: "expect button to be visible"
Please follow these steps carefully:
1. Analyze the provided intent and the view hierarchy to understand the required action.
2. Generate the minimal executable code required to perform the intent using the available API.
3. If you cannot generate the relevant code due to ambiguity or invalid intent, return code that throws an informative error explaining the problem in one sentence.
4. Wrap the generated code with backticks, without any additional formatting.
5. Do not provide any additional code beyond the minimal executable code required to perform the intent.
### Verify the prompt
Before generating the code, please review the provided context and instructions to ensure they are clear and unambiguous. If you encounter any issues or have questions, please throw an informative error explaining the problem.
### Examples
#### Example of throwing an informative error:
\`\`\`typescript
throw new Error("Unable to find the 'Submit' button element in the current context.");
\`\`\`
Please provide your response below:"
`;

exports[`PromptCreator extentAPICategories should extend the API catalog with new category 1`] = `
"# Test Code Generation
Expand Down

0 comments on commit 3b44fd6

Please sign in to comment.