-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: create Docusaurus documentation site for Copilot by Detox
This commit adds a new Docusaurus-based documentation site with: ### Guides Section: - **Integrating with Testing Frameworks:** Overview of Copilot's capabilities. - **Technical Overview:** Adapted from Detox docs (to be removed there). - **Best Practices:** Framework-agnostic step-by-step guidance. - **Custom Driver Implementation:** Guide to creating and adding testing framework drivers. - **Contributing:** Details on adding prompt handlers and drivers, with tips and github link. ### API Section: - **Interface Overview:** Lifecycle commands (`init`, `start`, `perform`, `end`). - **Prompt Handlers:** Writing and contributing (`src/prompt-handlers`). - **Framework Drivers:** Custom implementation, snapshot support, and type references. ### Showcase Page: - Highlights Detox as the initial use case and invites collaboration with other frameworks.
- Loading branch information
1 parent
629378c
commit 0e57f7b
Showing
62 changed files
with
19,074 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Dependencies | ||
/node_modules | ||
|
||
# Production | ||
/build | ||
|
||
# Generated files | ||
.docusaurus | ||
.cache-loader | ||
|
||
# Misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# Website | ||
|
||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. | ||
|
||
### Installation | ||
|
||
``` | ||
$ yarn | ||
``` | ||
|
||
### Local Development | ||
|
||
``` | ||
$ yarn start | ||
``` | ||
|
||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. | ||
|
||
### Build | ||
|
||
``` | ||
$ yarn build | ||
``` | ||
|
||
This command generates static content into the `build` directory and can be served using any static contents hosting service. | ||
|
||
### Deployment | ||
|
||
Using SSH: | ||
|
||
``` | ||
$ USE_SSH=true yarn deploy | ||
``` | ||
|
||
Not using SSH: | ||
|
||
``` | ||
$ GIT_USER=<Your GitHub username> yarn deploy | ||
``` | ||
|
||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
id: basic-interface-overview | ||
title: Basic Interface Overview | ||
sidebar_label: Basic Interface Overview | ||
sidebar_position: 1 | ||
--- | ||
|
||
# Basic Interface Overview | ||
The Copilot class serves as the core of the testing process, allowing seamless interaction between natural language prompts and your testing framework. Below is an overview of its main lifecycle commands that help control the test flow: | ||
|
||
## 1. `init(config: Config): void` | ||
The init method initializes the Copilot instance with the provided configuration. This must be called before using Copilot to ensure it is set up with the necessary framework drivers and prompt handlers. | ||
|
||
```typescript | ||
Copilot.init(config); | ||
``` | ||
|
||
## 2. `start(): void` | ||
The start method begins a new test flow, resetting previous steps and clearing any temporary cache. It must be called before performing any steps in the test. | ||
|
||
```typescript | ||
copilot.start(); | ||
``` | ||
Note: Calling start after an active test flow has already been started will result in an error. Be sure to call end() before starting a new flow. | ||
|
||
## 3. `performStep(step: string): Promise<any>` | ||
The performStep method allows Copilot to perform a test step based on a natural language prompt. The input step is parsed and evaluated by Copilot, interacting with the underlying framework to execute the corresponding action. | ||
|
||
```typescript | ||
const result = await copilot.performStep("Click the login button"); | ||
``` | ||
If Copilot is not running (i.e., start() has not been called), an error will be thrown. | ||
|
||
## 4. `end(saveToCache: boolean = true): void` | ||
The end method concludes the test flow. It can optionally save temporary data to the main cache, ensuring any relevant information is retained for future tests. | ||
|
||
```typescript | ||
copilot.end(true); // Save to cache | ||
``` | ||
Note: The end method should be called when the test flow is complete, and start() must be invoked again before starting a new test. | ||
|
||
## Error Handling | ||
If any method is called out of sequence, such as trying to perform steps without starting Copilot, or attempting to start Copilot while it is already running, the class will throw a CopilotError. This ensures that the test flow is controlled and prevents inconsistent states. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
--- | ||
id: framework-driver | ||
title: Framework Driver | ||
sidebar_label: Framework Driver | ||
sidebar_position: 3 | ||
--- | ||
|
||
# Framework Driver | ||
|
||
In this section, we will explain how to implement custom drivers for different testing frameworks in **Copilot by Detox**. A **Framework Driver** is a crucial component that ensures **Copilot** remains agnostic to the underlying testing framework, allowing it to work seamlessly with different frameworks like Detox, Jest, Mocha, etc. | ||
|
||
## What is a Framework Driver? | ||
|
||
A **Framework Driver** provides an abstraction layer between **Copilot** and the underlying testing framework. It defines the necessary methods to interact with the testing framework's API and potentially supports features such as taking snapshots of the app's UI and capturing the view hierarchy. | ||
|
||
By implementing a custom driver, you enable **Copilot** to communicate with your chosen testing framework, making it flexible and adaptable to a variety of testing environments. | ||
|
||
### TestingFrameworkDriver Interface | ||
|
||
The `TestingFrameworkDriver` interface defines the essential methods that a driver should implement: | ||
|
||
- **`captureSnapshotImage`**: Takes a snapshot of the current screen and returns the path to the saved image. If the driver does not support snapshot functionality, it should return `undefined`. | ||
- **`captureViewHierarchyString`**: Returns the current view hierarchy in a string representation, which helps the AI understand the structure of the app’s UI. | ||
- **`apiCatalog`**: Provides access to the available methods of the testing framework's API, such as matchers and actions. | ||
|
||
Here’s the interface definition for the driver: | ||
|
||
```typescript | ||
/** | ||
* Interface for the testing driver that will be used to interact with the underlying testing framework. | ||
*/ | ||
export interface TestingFrameworkDriver { | ||
/** | ||
* Takes a snapshot of the current screen and returns the path to the saved image. | ||
* If the driver does not support image, return undefined. | ||
*/ | ||
captureSnapshotImage: () => Promise<string | undefined>; | ||
|
||
/** | ||
* Returns the current view hierarchy in a string representation. | ||
*/ | ||
captureViewHierarchyString: () => Promise<string>; | ||
|
||
/** | ||
* The available guides methods of the testing framework. | ||
*/ | ||
apiCatalog: TestingFrameworkAPICatalog; | ||
} | ||
``` | ||
### Example: Detox Testing Framework Driver | ||
|
||
The following example demonstrates **part of the implementation** of a **Framework Driver** for the **Detox** testing framework. This snippet focuses on integrating core functionality like matchers, actions, and snapshot capabilities: | ||
|
||
```typescript | ||
const jestExpect = require('expect').default; | ||
const detox = require('../..'); | ||
|
||
const detoxCopilotFrameworkDriver = { | ||
apiCatalog: { | ||
context: { ...detox, jestExpect }, | ||
categories: [ | ||
{ | ||
title: 'Matchers', | ||
items: [ | ||
{ | ||
signature: 'by.id(id: string)', | ||
description: 'Matches elements by their test ID.', | ||
example: "element(by.id('loginButton'))", | ||
guidelines: ['Use test IDs (accessibility identifiers) to uniquely identify elements. This is the best-practice matcher.'], | ||
}, | ||
{ | ||
signature: 'by.text(text: string)', | ||
description: 'Matches elements by their text (value).', | ||
example: "element(by.text('Login'))", | ||
guidelines: ['Prefer test IDs over text matchers when possible.'], | ||
}, | ||
// Additional matchers can be added here... | ||
], | ||
}, | ||
{ | ||
title: 'Actions', | ||
items: [ | ||
{ | ||
signature: 'tap(point?: Point2D)', | ||
description: 'Simulates tap on an element.', | ||
example: "await element(by.id('loginButton')).tap();", | ||
}, | ||
{ | ||
signature: 'longPress(point?: Point2D, duration?: number)', | ||
description: 'Simulates long press on an element.', | ||
example: "await element(by.id('menuItem')).longPress();", | ||
guidelines: ['Tapping on edges of elements might work better when adding a small offset to the point.'], | ||
}, | ||
// Additional actions can be added here... | ||
], | ||
}, | ||
], | ||
}, | ||
// Example method implementations: | ||
captureSnapshotImage: async () => { | ||
try { | ||
const screenshot = await detox.device.takeScreenshot(); | ||
return screenshot; | ||
} catch (error) { | ||
console.error('Error capturing snapshot:', error); | ||
return undefined; | ||
} | ||
}, | ||
|
||
captureViewHierarchyString: async () => { | ||
try { | ||
const hierarchy = await detox.device.getUIHierarchy(); | ||
return hierarchy; | ||
} catch (error) { | ||
console.error('Error capturing view hierarchy:', error); | ||
return ''; | ||
} | ||
}, | ||
}; | ||
|
||
module.exports = detoxCopilotFrameworkDriver; | ||
``` | ||
### Optional Support for Snapshot | ||
|
||
The **Framework Driver** can optionally support snapshot functionality. If the underlying framework supports capturing screenshots or images of the app, this feature can be implemented in the `captureSnapshotImage` method. If the driver does not support snapshots, it should return `undefined`. | ||
|
||
### Referencing Relevant Types | ||
|
||
The types related to the **Testing Framework Driver** can be found in the source code files under the following locations: | ||
|
||
- `TestingFrameworkDriver` interface is defined in the `src/types` folder. | ||
- `TestingFrameworkAPICatalog` provides information about the available API methods and can also be found in the same folder. | ||
|
||
## Conclusion | ||
|
||
By implementing a **Framework Driver**, **Copilot by Detox** can work with any testing framework, giving users flexibility in their testing setup. For more detailed instructions, you can refer to the relevant types and source code for guidance. | ||
|
||
If you are interested in contributing or have any suggestions for improving the **Framework Driver** system, check out the open tasks on our [GitHub repository](https://github.com/wix-incubator/detox-copilot/issues). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
--- | ||
id: prompt-handler | ||
title: Prompt Handler | ||
sidebar_label: Prompt Handler | ||
sidebar_position: 2 | ||
--- | ||
|
||
# Prompt Handler | ||
|
||
In this section, we will cover how to implement a **Prompt Handler** to interact with AI services, such as OpenAI, in the context of **Copilot by Detox**. | ||
|
||
## What is a Prompt Handler? | ||
|
||
A **Prompt Handler** is responsible for sending a prompt to an AI service and receiving the response. It may also handle the inclusion of additional context, such as a snapshot image, to enhance the AI's understanding of the app's UI state. Implementing a prompt handler allows **Copilot** to generate intelligent test scripts based on natural language commands. | ||
|
||
## How to Write a Prompt Handler | ||
|
||
A **Prompt Handler** follows a defined interface, which ensures it can communicate with any AI service in a standardized way. | ||
|
||
### PromptHandler Interface | ||
|
||
The `PromptHandler` interface includes the following methods: | ||
|
||
- **`runPrompt`**: Sends a prompt to the AI service and returns the generated response. | ||
- **`isSnapshotImageSupported`**: Checks if the AI service supports snapshot images to provide additional context. | ||
|
||
Here’s an example of the `PromptHandler` interface: | ||
|
||
```typescript | ||
/** | ||
* Interface for the prompt handler that will be used to interact with the AI service (e.g. OpenAI). | ||
*/ | ||
export interface PromptHandler { | ||
/** | ||
* Sends a prompt to the AI service and returns the response. | ||
* @param prompt The prompt to send to the AI service. | ||
* @param image Optional path to the image to upload to the AI service that captures the current UI state. | ||
* @returns The response from the AI service. | ||
*/ | ||
runPrompt: (prompt: string, image?: string) => Promise<string>; | ||
|
||
/** | ||
* Checks if the AI service supports snapshot images for context. | ||
*/ | ||
isSnapshotImageSupported: () => boolean; | ||
} | ||
``` | ||
|
||
### Example: Implementing the Prompt Handler for Sonnet | ||
|
||
```typescript | ||
const axios = require('axios'); | ||
const fs = require('fs').promises; | ||
|
||
class PromptHandler { | ||
// Upload an image to the AI service | ||
async uploadImage(imagePath) { | ||
const image = await fs.readFile(imagePath); | ||
|
||
try { | ||
const response = await axios.post('https://bo.wix.com/mobile-infra-ai-services/v1/image-upload', { | ||
image, | ||
}); | ||
|
||
const imageUrl = response.data.url; | ||
if (!imageUrl) { | ||
throw new Error('Cannot find uploaded URL, got response:', response.data); | ||
} | ||
|
||
return imageUrl; | ||
} catch (error) { | ||
console.error('Error while uploading image:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
// Run the prompt and return the generated text | ||
async runPrompt(prompt, image) { | ||
if (!image) { | ||
throw new Error('Image is required'); | ||
} | ||
|
||
const imageUrl = await this.uploadImage(image); | ||
|
||
try { | ||
const response = await axios.post('https://bo.wix.com/mobile-infra-ai-services/v1/prompt', { | ||
prompt, | ||
model: 'SONNET_3_5', | ||
ownershipTag: 'Detox OSS', | ||
project: 'Detox OSS', | ||
images: [imageUrl] | ||
}); | ||
|
||
const generatedText = response.data.generatedTexts[0]; | ||
if (!generatedText) { | ||
throw new Error('Failed to generate text, got response:', response.data); | ||
} | ||
|
||
return generatedText; | ||
} catch (error) { | ||
console.error('Error running prompt:', error); | ||
throw error; | ||
} | ||
} | ||
|
||
// Check if snapshot images are supported | ||
isSnapshotImageSupported() { | ||
return true; | ||
} | ||
} | ||
|
||
module.exports = PromptHandler; | ||
``` | ||
|
||
## Open Tasks For Contributors | ||
If you're interested in contributing to Copilot by Detox and adding new prompt handlers or improving the existing ones, check out the open tasks on our [GitHub repository](https://github.com/wix-incubator/detox-copilot/issues). |
Oops, something went wrong.