Skip to content

Commit

Permalink
feat: add support for Azure OpenAI
Browse files Browse the repository at this point in the history
  • Loading branch information
lucgagan authored Jun 4, 2024
2 parents 22c8f2f + bb88763 commit 9c19164
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 12 deletions.
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,45 @@ test("auto Playwright example", async ({ page }) => {
expect(searchInputHasHeaderText).toBe(true);
});
```
### Setup with Azure OpenAI
Include the StepOptions type with the values needed for connecting to Azure OpenAI.
```ts
import { test, expect } from "@playwright/test";
import { auto } from "auto-playwright";
import { StepOptions } from "../src/types";
const apiKey = "apikey";
const resource = "azure-resource-name";
const model = "model-deployment-name";
const options: StepOptions = {
model: model,
openaiApiKey: apiKey,
openaiBaseUrl: `https://${resource}.openai.azure.com/openai/deployments/${model}`,
openaiDefaultQuery: { 'api-version': "2023-07-01-preview" },
openaiDefaultHeaders: { 'api-key': apiKey }
};
test("auto Playwright example", async ({ page }) => {
await page.goto("/");
// `auto` can query data
// In this case, the result is plain-text contents of the header
const headerText = await auto("get the header text", { page, test }, options);
// `auto` can perform actions
// In this case, auto will find and fill in the search text input
await auto(`Type "${headerText}" in the search box`, { page, test }, options);
// `auto` can assert the state of the website
// In this case, the result is a boolean outcome
const searchInputHasHeaderText = await auto(`Is the contents of the search box equal to "${headerText}"?`, { page, test }, options);
expect(searchInputHasHeaderText).toBe(true);
});
```
## Usage
Expand Down
1 change: 1 addition & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig } from "@playwright/test";

export default defineConfig({
timeout: 90000,
webServer: {
command: "npm run start",
url: "http://127.0.0.1:3000",
Expand Down
3 changes: 3 additions & 0 deletions src/auto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ async function runTask(
model: options.model ?? "gpt-4-1106-preview",
debug: options.debug ?? false,
openaiApiKey: options.openaiApiKey,
openaiBaseUrl: options.openaiBaseUrl,
openaiDefaultQuery: options.openaiDefaultQuery,
openaiDefaultHeaders: options.openaiDefaultHeaders,
}
: undefined,
});
Expand Down
7 changes: 6 additions & 1 deletion src/completeTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ export const completeTask = async (
page: Page,
task: TaskMessage
): Promise<TaskResult> => {
const openai = new OpenAI({ apiKey: task.options?.openaiApiKey });
const openai = new OpenAI({
apiKey: task.options?.openaiApiKey,
baseURL: task.options?.openaiBaseUrl,
defaultQuery: task.options?.openaiDefaultQuery,
defaultHeaders: task.options?.openaiDefaultHeaders,
});

let lastFunctionResult: null | { errorMessage: string } | { query: string } =
null;
Expand Down
2 changes: 1 addition & 1 deletion src/sanitizeHtml.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as sanitize from "sanitize-html";
import sanitize from "sanitize-html";

/**
* The reason for sanitization is because OpenAI does not need all of the HTML tags
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export type StepOptions = {
debug?: boolean;
model?: string;
openaiApiKey?: string;
openaiBaseUrl?: string;
openaiDefaultQuery?: {};
openaiDefaultHeaders?: {};
};

export type TaskMessage = {
Expand Down
25 changes: 15 additions & 10 deletions tests/auto.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { expect, test } from "@playwright/test";
import { auto } from "../src/auto";

const options = undefined;

test("executes query", async ({ page }) => {
await page.goto("/");

const headerText = await auto("get the header text", { page, test });
const headerText = await auto("get the header text", { page, test }, options);

expect(headerText).toBe("Hello, Rayrun!");
});
Expand All @@ -15,7 +17,7 @@ test("executes query using locator_evaluate", async ({ page }) => {
const headerText = await auto("get the first letter of the header text", {
page,
test,
});
}, options);

// TODO assert that we are using locator_evaluate to get the first letter
expect(headerText).toBe("H");
Expand All @@ -24,7 +26,7 @@ test("executes query using locator_evaluate", async ({ page }) => {
test("executes action", async ({ page }) => {
await page.goto("/");

await auto(`Type "foo" in the search box`, { page, test });
await auto(`Type "foo" in the search box`, { page, test }, options);

await page.pause();

Expand All @@ -37,7 +39,7 @@ test("executes click", async ({ page }) => {
await auto("Click the button until the counter value is equal to 2", {
page,
test,
});
}, options);

await expect(page.getByTestId("current-count")).toHaveText("2");
});
Expand All @@ -47,7 +49,8 @@ test("asserts (toBe)", async ({ page }) => {

const searchInputHasHeaderText = await auto(
`Is the contents of the header equal to "Hello, Rayrun!"?`,
{ page, test }
{ page, test },
options
);

expect(searchInputHasHeaderText).toBe(true);
Expand All @@ -58,7 +61,8 @@ test("asserts (not.toBe)", async ({ page }) => {

const searchInputHasHeaderText = await auto(
`Is the contents of the header equal to "Flying Donkeys"?`,
{ page, test }
{ page, test },
options
);

expect(searchInputHasHeaderText).toBe(false);
Expand All @@ -67,13 +71,14 @@ test("asserts (not.toBe)", async ({ page }) => {
test("executes query, action and assertion", async ({ page }) => {
await page.goto("/");

const headerText = await auto("get the header text", { page, test });
const headerText = await auto("get the header text", { page, test }, options);

await auto(`type "${headerText}" in the search box`, { page, test });
await auto(`type "${headerText}" in the search box`, { page, test }, options);

const searchInputHasHeaderText = await auto(
`is the contents of the search box equal to "${headerText}"?`,
{ page, test }
{ page, test },
options
);

expect(searchInputHasHeaderText).toBe(true);
Expand All @@ -82,7 +87,7 @@ test("executes query, action and assertion", async ({ page }) => {
test("runs without test parameter", async ({ page }) => {
await page.goto("/");

const headerText = await auto("get the header text", { page });
const headerText = await auto("get the header text", { page }, options);

expect(headerText.query).toBe("Hello, Rayrun!");
});

0 comments on commit 9c19164

Please sign in to comment.