Giter Club home page Giter Club logo

auto-playwright's Introduction

Auto Playwright

Run Playwright tests using AI.

Setup

  1. Install auto-playwright dependency:
npm install auto-playwright -D
  1. This package relies on talking with OpenAI (https://openai.com/). You must export the API token as an enviroment variable or add it to your .env file:
export OPENAI_API_KEY='sk-..."
  1. Import and use the auto function:
import { test, expect } from "@playwright/test";
import { auto } from "auto-playwright";

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 });

  // `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 });

  // `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 });

  expect(searchInputHasHeaderText).toBe(true);
});

Setup with Azure OpenAI

Include the StepOptions type with the values needed for connecting to Azure OpenAI.

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

At minimum, the auto function requires a plain text prompt and an argument that contains your page and test (optional) objects.

auto("<your prompt>", { page, test });

Browser automation

Running without the test parameter:

import { chromium } from "playwright";
import { auto } from "auto-playwright";

(async () => {
  const browser = await chromium.launch({ headless: true });
  const context = await browser.newContext();
  const page = await context.newPage();
  // Navigate to a website
  await page.goto("https://www.example.com");

  // `auto` can query data
  // In this case, the result is plain-text contents of the header
  const res = await auto("get the header text", { page });

  // use res.query to get a query result.
  console.log(res);
  await page.close();
})();

Debug

You may pass a debug attribute as the third parameter to the auto function. This will print the prompt and the commands executed by OpenAI.

await auto("get the header text", { page, test }, { debug: true });

You may also set environment variable AUTO_PLAYWRIGHT_DEBUG=true, which will enable debugging for all auto calls.

export AUTO_PLAYWRIGHT_DEBUG=true

Supported Browsers

Every browser that Playwright supports.

Additional Options

There are additional options you can pass as a third argument:

const options = {
  // If true, debugging information is printed in the console.
  debug: boolean,
  // The OpenAI model (https://platform.openai.com/docs/models/overview)
  model: "gpt-4-1106-preview",
  // The OpenAI API key
  openaiApiKey: 'sk-...',
};

auto("<your prompt>", { page, test }, options);

Supported Actions & Return Values

Depending on the type of action (inferred by the auto function), there are different behaviors and return types.

Action

An action (e.g. "click") is some simulated user interaction with the page, e.g. a click on a link. Actions will return `undefined`` if they were successful and will throw an error if they failed, e.g.

try {
  await auto("click the link", { page, test });
} catch (e) {
  console.error("failed to click the link");
}

Query

A query will return requested data from the page as a string, e.g.

const linkText = await auto("Get the text of the first link", { page, test });

console.log("The link text is", linkText);

Assert

An assertion is a question that will return true or false, e.g.

const thereAreThreeLinks = await auto("Are there 3 links on the page?", {
  page,
  test,
});

console.log(`"There are 3 links" is a ${thereAreThreeLinks} statement`);

Why use Auto Playwright?

Aspect Conventional Approach Testing with Auto Playwright
Coupling with Markup Strongly linked to the application's markup. Eliminates the use of selectors; actions are determined by the AI assistant at runtime.
Speed of Implementation Slower implementation due to the need for precise code translation for each action. Rapid test creation using simple, plain text instructions for actions and assertions.
Handling Complex Scenarios Automating complex scenarios is challenging and prone to frequent failures. Facilitates testing of complex scenarios by focusing on the intended test outcomes.
Test Writing Timing Can only write tests after the complete development of the functionality. Enables a Test-Driven Development (TDD) approach, allowing test writing concurrent with or before functionality development.

Supported Playwright Actions

  • locator.blur
  • locator.boundingBox
  • locator.check
  • locator.clear
  • locator.click
  • locator.count
  • locator.fill
  • locator.getAttribute
  • locator.innerHTML
  • locator.innerText
  • locator.inputValue
  • locator.isChecked
  • locator.isEditable
  • locator.isEnabled
  • locator.isVisible
  • locator.textContent
  • locator.uncheck
  • page.goto

Adding new actions is easy: just update the functions in src/completeTask.ts.

Pricing

This library is free. However, there are costs associated with using OpenAI. You can find more information about pricing here: https://openai.com/pricing/.

Example

Using https://ray.run/ as an example, the cost of running a test step is approximately $0.01 using GPT-4 Turbo (and $0.001 using GPT-3.5 Turbo).

The low cost is in part because auto-playwright uses HTML sanitization to reduce the payload size, e.g. What follows is the payload that would be submitted for https://ray.run/.

Naturally, the price will vary dramatically depending on the payload.

<div class="cYdhWw dKnOgO geGbZz bGoBgk jkEels">
  <div class="kSmiQp fPSBzf bnYmbW dXscgu xJzwH jTWvec gzBMzy">
    <h1 class="fwYeZS fwlORb pdjVK bccLBY fsAQjR fyszFl WNJim fzozfU">
      Learn Playwright
    </h1>
    <h2 class="cakMWc ptfck bBmAxp hSiiri xJzwS gnfYng jTWvec fzozfU">
      Resources for learning end-to-end testing using Playwright automation
      framework
    </h2>
    <div
      class="bLTbYS gvHvKe cHEBuD ddgODW jsxhGC kdTEUJ ilCTXp iQHbtH yuxBn ilIXfy gPeiPq ivcdqp isDTsq jyZWmS ivdkBK cERSkX hdAwi ezvbLT jNrAaV jsxhGJ fzozCb"
    ></div>
  </div>
  <div class="cYdhWw dpjphg cqUdSC fasMpP">
    <a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/blog"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Blog</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Learn in depth subjects about end-to-end testing.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/ask"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Ask AI</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Ask ChatGPT Playwright questions.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/tools"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Dev Tools</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>All-in-one toolbox for QA engineers.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/jobs"
      ><div class="plfYl bccLBY hSiiri fNBpvX">QA Jobs</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Handpicked QA and Automation opportunities.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/questions"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Questions</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Ask AI answered questions about Playwright.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/discord-forum"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Discord Forum</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Archive of Discord Forum posts about Playwright.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/videos"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Videos</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Tutorials, conference talks, and release videos.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/browser-extension"
      ><div class="plfYl bccLBY hSiiri fNBpvX">Browser Extension</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>GUI for generating Playwright locators.</p>
      </div></a
    ><a
      class="gacSWM dCgFix conipm knkqUc bddCnd dTKJOB leOtqz hEzNkW fNBBKe jTWvec fIMbrO fzozfU group"
      href="/wiki"
      ><div class="plfYl bccLBY hSiiri fNBpvX">QA Wiki</div>
      <div class="jqqjPD fWDXZB pKTba bBmAxp hSiiri evbPEu">
        <p>Definitions of common end-to-end testing terms.</p>
      </div></a
    >
  </div>
  <div
    class="kSmiQp fPSBzf pKTba eTDpsp legDhJ hSiiri hdaZLM jTWvec gzBMzy bGySga fzoybr"
  >
    <p class="dXhlDK leOtqz glpWRZ fNCcFz">
      Use <kbd class="bWhrAL XAzZz cakMWc bUyOMB bmOrOm fyszFl dTmriP"></kbd> +
      <kbd>k</kbd> + "Tools" to quickly access all tools.
    </p>
  </div>
</div>

Implementation

HTML Sanitization

The auto function uses sanitize-html to sanitize the HTML of the page before sending it to OpenAI. This is done to reduce cost and improve the quality of the generated text.

ZeroStep

This project draws its inspiration from ZeroStep. ZeroStep offers a similar API but with a more robust implementation through its proprietary backend. Auto Playwright was created with the aim of exploring the underlying technology of ZeroStep and establishing a basis for an open-source version of their software. For production environments, I suggest opting for ZeroStep.

Here's a side-by-side comparison of Auto Playwright and ZeroStep:

Criteria Auto Playwright ZeroStep
Uses OpenAI API Yes No1
Uses plain-text prompts Yes No
Uses functions SDK Yes No
Uses HTML sanitization Yes No
Uses Playwright API Yes No2
Uses screenshots No Yes
Uses queue No Yes
Uses WebSockets No Yes
Snapshots HTML DOM
Implements parallelism No Yes
Allows scrolling No Yes
Provides fixtures No Yes
License MIT MIT
Zero Step License
MIT License

Copyright (c) 2023 Reflect Software Inc

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Footnotes

  1. Uses ZeroStep proprietary API.

  2. Uses some Playwright API, but predominantly relies on Chrome DevTools Protocol (CDP).

auto-playwright's People

Contributors

agamm avatar elie222 avatar lucgagan avatar merkie avatar rajeshdavidbabu avatar roberto-mardeni avatar thomas-phillips-nz avatar tmcneal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

auto-playwright's Issues

Added actions are not getting read

I have added new action to the create action file but when I execute the code its not being read, and it shows the action is not defined
selectOption: {
function: async (args: { value: string; elementId: string }) => {
await getLocator(args.elementId).selectOption(args.value);

    return {
      success: true,
    };
  },
  name: "selectOption",
  description: "Selectoption value from a dropdown list",
  parse: (args: string) => {
    return z
      .object({
        elementId: z.string(),
        value: z.string(),
      })
      .parse(JSON.parse(args));
  },
  parameters: {
    type: "object",
    properties: {
      value: {
        type: "string",
      },
      elementId: {
        type: "string",
      },
    },
  },
},  

Getting "Expected to have result"error after completion of a step

Below is my test.But am getting the error ""Expected to have result"" just after typing in username.Can you help me here.

test.only("executes query", async ({ page }) => {
await page.goto("https://www.saucedemo.com/");

const headerText="Playwright";
await auto(`type "${headerText}" in the username`, { page, test },{model: 'gpt-3.5-turbo-1106', debug: true});
await auto(`type "Hello" in the password`, { page, test },{model: 'gpt-3.5-turbo-1106', debug: true});
await page.pause();

});

How to handle SPA website

Hey, I come across auto-playwright via the ray.run blog post, and I really wanted to test it on the project I'm working on.

Still, I don't think it's working, this is the debug output:

message {
  role: 'user',
  content: 'This is your task: go to sign up page\n' +
    '\n' +
    '* When creating CSS selectors, ensure they are unique and specific enough to select only one element, even if there are multiple elements of the same type (like multiple h1 elements).\n' +
    "* Avoid using generic tags like 'h1' alone. Instead, combine them with other attributes or structural relationships to form a unique selector.\n" +
    '* You must not derive data from the page if you are able to do so by using one of the provided functions, e.g. locator_evaluate.\n' +
    '\n' +
    'Webpage snapshot:\n' +
    '\n' +
    '```\n' +
    '\n' +
    '    Cloaked\n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '    \n' +
    '  \n' +
    '  \n' +
    '    \n' +
    "      <strong>We're sorry but cloaked-dashboard doesn't work\n" +
    '        properly without JavaScript enabled. Please enable it to\n' +
    '        continue.</strong>\n' +
    '    \n' +
    '    <main data-v-6aa2cce8><div data-v-170fc09e data-v-100ecb37 data-v-6aa2cce8 class="mount-event" default="default"></div></main>\n' +
    '    \n' +
    '  \n' +
    '\n' +
    '<div></div><div></div><div style="visibility:visible"><div></div><div></div></div>\n' +
    '```\n'
}

I even added timeout between the page.goto and auto() to give time to JS, but it seems that JS is disabled at all. What can I do for it?

Bun doesn't work with auto-playwright

When I try to run with bun I get:

myuser@myuser-Laptop:~/dev/myproject$ bun main.ts 
64 |     const e = new TargetClosedError(error.error.message);
65 |     e.stack = error.error.stack || '';
66 |     return e;
67 |   }
68 |   const e = new Error(error.error.message);
69 |   e.stack = error.error.stack || '';
                ^
TypeError: launch: launch: undefined is not an object (evaluating 'pipeRead.on')
Call log:
  - <launching> /home/myuser/.cache/ms-playwright/chromium-1091/chrome-linux/chrome --disable-field-trial-config --disable-background-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-back-forward-cache --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-component-update --no-default-browser-check --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,HttpsUpgrades --allow-pre-commit-input --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-backgrounding --force-color-profile=srgb --metrics-recording-only --no-first-run --enable-automation --password-store=basic --use-mock-keychain --no-service-autorun --export-tagged-pdf --disable-search-engine-choice-screen --headless --hide-scrollbars --mute-audio --blink-settings=primaryHoverType=2,availableHoverTypes=2,primaryPointerType=4,availablePointerTypes=4 --no-sandbox --disable-blink-features=AutomationControlled --no-first-run --no-default-browser-check --user-data-dir=/tmp/playwright_chromiumdev_profile-RvP6xI --remote-debugging-pipe --no-startup-window
  - <launched> pid=32470

Unexpected token 'export'playwright - 1.8.0 version error

When testing with version 1.8.0

import { test, expect } from "@playwright/test";
import { auto } from "auto-playwright";

...
  // `auto` can assert the state of the website
  // In this case, the result is a boolean outcome
  
  // this is missing a comma at the end
  const searchInputHasHeaderText = await auto(`Is the contents of the search box equal to "${headerText}"?` { page, test });
  
  // this seems to correct the code
  const searchInputHasHeaderText = await auto(`Is the contents of the search box equal to "${headerText}"?`, { page, test });
...

Once this was corrected I am getting this error on the import statement for { auto } Unexpected token 'export'playwright
image

model parameter appears to be ignored

I was trying to get the model parameter working for me, as I do not have access to GPT 4. It appears like the model parameter is ignored, however:

image

test('Test Google using GPT', async({ page }) => {
  await page.goto('https://www.google.com/');
  await auto('Search for "something else"', { page, test }, {model: 'gpt-3.5-turbo-1106', debug: true});
});

Maybe it might be good to log the model parameter if debugging is turned on?

Save the tests after a successful run

Is it feasible to persistently save test results after a successful run? Imagine running the test once, leveraging AI to generate all necessary components, and then executing subsequent runs from the saved tests. During local development, you could use a flag to generate the tests, while in a pipeline, they would execute directly from the saved data. This approach ensures persistence in managing test results.

Getting connection error - may be openai api key is not set property - need help

Hello,
I have set my api key within options variable as below:

import { test, expect } from '@playwright/test'
import { auto } from 'auto-playwright'

test.describe('todo tests', () => {

const options = {
openaiApiKey: '12eretretrtydsfgfdgxcxdv',
}

test('sample AI test @auto', async ({ page }) => {
const email = ''
const password = '
'
await page.goto('https://
***********')
await page.waitForTimeout(3000)

await auto('Verify that **** Logo is displayed', { page, test }, options)
await auto('Click on "Sign In" button', { page, test }, options)
await page.waitForTimeout(5000)
await auto('Verify that a pop up modal is displayed', { page, test }, options)
await auto('Click on link "**********"', { page, test })
await auto('Verify a login screen is displayed', { page, test }, options)

but I get error:

Error: Connection error.

    at OpenAI.makeRequest (/Users/suraj.kelkar/Downloads/playwright-typeScript/node_modules/.pnpm/[email protected]/node_modules/openai/src/core.ts:400:13)
    at ChatCompletionRunner._createChatCompletion (/Users/suraj.kelkar/Downloads/playwright-typeScript/node_modules/.pnpm/[email protected]/node_modules/openai/src/lib/AbstractChatCompletionRunner.ts:432:28)
    at ChatCompletionRunner._runFunctions (/Users/suraj.kelkar/Downloads/playwright-typeScript/node_modules/.pnpm/[email protected]/node_modules/openai/src/lib/AbstractChatCompletionRunner.ts:481:46)

TypeError: Cannot read properties of undefined (reading 'defaults') in auto-playwright

I am encountering a TypeError when using the auto function from the auto-playwright library in conjunction with crawlee. The error message indicates that the defaults property is undefined in the sanitize-html library, which is used internally by auto-playwright.

Steps to Reproduce:

Install the latest versions of auto-playwright and sanitize-html.
Set up a route handler using crawlee (routes.ts) and auto-playwright as shown below:

import { createPlaywrightRouter } from 'crawlee';
import { auto } from 'auto-playwright';

export const router = createPlaywrightRouter();

router.addDefaultHandler(async ({ page, log }) => {
    try {
        await auto('Click the start button', { page });
    } catch (error) {
        log.error(`Error in auto-playwright: ${error.message}`);
    }
});

Run the crawler.

The following error is thrown:

TypeError: Cannot read properties of undefined (reading 'defaults')
    at sanitizeHtml (/path/to/node_modules/auto-playwright/dist/sanitizeHtml.js:23:46)
    at getSnapshot (/path/to/node_modules/auto-playwright/dist/getSnapshot.js:7:46)
    at async runTask (/path/to/node_modules/auto-playwright/dist/auto.js:37:19)
    at async auto (/path/to/node_modules/auto-playwright/dist/auto.js:14:16)
    at <anonymous> (/path/to/project/src/routes.ts:8:5)

Additional Information:

The issue seems related to the sanitize-html library and its type definitions.
I have verified that I am using the latest versions of both auto-playwright and sanitize-html.
The problem persists despite the issue being marked as resolved in version 1.12.2 of auto-playwright.

Environment:

Node.js version: v20.13.1
auto-playwright version: 1.15.0
sanitize-html version: 2.13.0
Operating System: Ubuntu

References:

GitHub Issue #7 - Similar issue reported and marked as resolved.

Possible Workaround:

Manually adjust the sanitizeHtml function in the auto-playwright library to ensure it correctly references sanitize-html:

const sanitizeHtml = (subject) => {
    return sanitize(subject, {
        allowedTags: sanitize.defaults.allowedTags.concat([
            "button",
            "form",
            "img",
            "input",
            "select",
            "textarea",
        ]),
        allowedAttributes: false,
    });
};

Thank you!

Consider adjusting the API to an OOP design

Hey lucgagan, I really love this project.
I noticed that the API requires you to pass in the same options every time you call auto. Would you consider a more object-oriented approach like this one so users can initialize the function once and then call it repeatedly with the same state? This would also be useful for setting token limits and other configurations due to the nature of the persistent state in objects.

Here's the kind of syntax I was imagining:

import AutoPlaywright from "auto-playwright";

const ap = new AutoPlaywright({
    openAiKey: "sk-...",
    model: "gpt-4-1106-preview", // this can mirror the model types from OpenAI
    // ...whatever else here
});

ap.auto("Get the text of the first link", { page, test })

Let me know what you think, as this would be a bigger change, so I didn't want to start coding anything yet, but I think taking up this approach would have numerous benefits like the ones I mentioned previously. This is also similar to how many other packages behave.

Thanks!
Keep up the good work man

issue with type definitions for sanitize-html

It seems like I'm getting invalid javascript generated from sanitizeHtml.ts

this code

export const sanitizeHtml = (subject: string) => {
  return sanitize(subject, {
    // The default allowedTags list already includes _a lot_ of commonly used tags.
    // https://www.npmjs.com/package/sanitize-html#default-options
    //
    // I don't see a need for this to be configurable at the moment,
    // as it already covers all the layout tags, but we can revisit this if necessary.
    allowedTags: sanitize.defaults.allowedTags.concat([
      "button",
      "form",
      "img",
      "input",
      "select",
      "textarea",
    ]),
    // Setting allowedAttributes to false will allow all attributes.
    allowedAttributes: false,
  });
};

turns into

const sanitizeHtml = (subject) => {
    return (0, sanitize_html_1.default)(subject, {

        // The default allowedTags list already includes _a lot_ of commonly used tags.
        // https://www.npmjs.com/package/sanitize-html#default-options
        //
        // I don't see a need for this to be configurable at the moment,
        // as it already covers all the layout tags, but we can revisit this if necessary.
        allowedTags: sanitize_html_1.default.defaults.allowedTags.concat([
            "button",
            "form",
            "img",
            "input",
            "select",
            "textarea",
        ]),
        // Setting allowedAttributes to false will allow all attributes.
        allowedAttributes: false,
    });
};

which fails with

 TypeError: Cannot read properties of undefined (reading 'defaults')
    at sanitizeHtml (/Users/vijay/work/prj/workspace/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/auto-playwright/dist/sanitizeHtml.js:25:46)
    at getSnapshot (/Users/vijay/work/prj/workspace/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/auto-playwright/dist/getSnapshot.js:7:46)

If i manually adjust the javascript file in dist to be like

const sanitizeHtml = (subject) => {
    return (0, sanitize_html_1)(subject, {

        // The default allowedTags list already includes _a lot_ of commonly used tags.
        // https://www.npmjs.com/package/sanitize-html#default-options
        //
        // I don't see a need for this to be configurable at the moment,
        // as it already covers all the layout tags, but we can revisit this if necessary.
        allowedTags: sanitize_html_1.defaults.allowedTags.concat([
            "button",
            "form",
            "img",
            "input",
            "select",
            "textarea",
        ]),
        // Setting allowedAttributes to false will allow all attributes.
        allowedAttributes: false,
    });
};

it all seems to work... looking at the underlying type in https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/sanitize-html/index.d.ts it seems correct to me...

Code error

My code :
import { expect, test } from "@playwright/test";
import { auto } from "auto-playwright";

test("executes query, action and assertion", 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 },
);

// 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 },
);

// 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 },
);

expect(searchInputHasHeaderText).toBe(true);
});
ERROR:
TypeError: Cannot read properties of undefined (reading 'defaults')
at sanitizeHtml (/Users/jiangjiangbing/Documents/AutoPlaywright/auto-playwright/node_modules/auto-playwright/dist/sanitizeHtml.js:23:46)
at getSnapshot (/Users/jiangjiangbing/Documents/AutoPlaywright/auto-playwright/node_modules/auto-playwright/dist/getSnapshot.js:7:46)
at runTask (/Users/jiangjiangbing/Documents/AutoPlaywright/auto-playwright/node_modules/auto-playwright/dist/auto.js:37:19)
at auto-playwright/node_modules/auto-playwright/dist/auto.js:17:24
at auto-playwright/tests/ttt.spec.ts:9:22

Not able to select element from a list

Error: locator.fill: Error: Element is not an <input>, <textarea> or [contenteditable] element
Call log:
  - waiting for locator('#elementsPerPageSelect')
  -   locator resolved to <select class="form-control" id="elementsPerPageSelect" …>…</select>
  - elementHandle.fill("20")
  -   waiting for element to be visible, enabled and editable
  -   Element is not an <input>, <textarea> or [contenteditable] element

Run without test parameter

I'd like to run it like so:

import { auto } from "auto-playwright";


(async () => { 
  const browser = await chromium.launch({ headless: true }); 
  const context = await browser.newContext(); 
  const page = await context.newPage(); 
  // Navigate to a website 
  await page.goto('https://www.example.com'); 
  
   // `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});
  ....
``

is it possible?

Problems parsing OpenAI Azure API response

I'm trying to implement some proof-of-concept tests with Auto-Playwright and our company's generative AI chat (based on ChatGPT 3.5), but I'm getting some wierd errors parsing the response.

model: ChatGPT3.5-turbo
api-version: 2024-02-01

When I invoke auto with a simple prompt like Click the "Click me" button, I'm getting a test error because the response does not have a function_call with "result".

Is the latest version of Auto really compatible with Open AI Azure API 2024-02-01?

Sample request:

role: 'user',   
content: 'This is your task: Click the "Click me" button\n' +     '\n' +     
'* When creating CSS selectors, ensure they are unique and specific enough to select only one element, even if there are multiple elements of the same type (like multiple h1 elements).\n' +     
"* Avoid using generic tags like 'h1' alone. Instead, combine them with other attributes or structural relationships to form a unique selector.\n" +     
'* You must not derive data from the page if you are able to do so by using one of the provided functions, e.g. locator_evaluate.\n' +     '\n' +     
'Webpage snapshot:\n' +     
'\n' +     '\n' +     '\n' +     '     Testing \n' +     '    <h1>Hello, Rayrun!</h1>\n' +     '    <form id="search">\n' +     '       Search \n' +     '      <input type="text" name="query" data-testid="search-input" />\n' +     '    </form>\n' +     '    <div id="click-counter">\n' +     '      <p>Click count: <span id="current-count" data-testid="current-count">0</span></p>\n' +     '      <button id="click-button">Click me</button>\n' +     '      \n' +     '    </div>\n' +     '  \n' +     '\n' +     '\n' +     '\n' +     '\n' +     '\n' +     '\n'}

Sample response:

message {   
content: 'To click the button with ID "click-button", you can use the following code:\n' +     
'\n' +     
'```javascript\n' +     'const { locateElement, locator_click } = require("@qawolf/web");\n' +     '\n' +     '// Locate the button element using its ID\n' +     'const buttonElement = await locateElement({ cssSelector: "#click-button" });\n' +     '\n' +     '// Click on the button element\n' +     'await locator_click({ elementId: buttonElement });\n' +     
'```\n' +     
'\n' +     
'This code uses the `locateElement` function to find the button element on the webpage using its ID, and then uses the `locator_click` function to click on the button.',   role: 'assistant'}

⚠ Notice the javascript block instead of the function_call that the code expects.

Has anyone else faced this issue?

TypeError: Cannot read properties of undefined (reading 'defaults')

Hello,

Am facing below error, I have set the OPENAI_API_KEY in .env file and also set in my systems environment variables, but still facing the error. Can anyone pls help me as am exploring this new AI feature to integrate into automation framework.

TypeError: Cannot read properties of undefined (reading 'defaults')

  13 |     const aiArgs = { page, test }
  14 |     await page.waitForTimeout(3000)
> 15 |     await auto(`Type "auto-playwright" in the search box`, aiArgs, options)
     |     ^
  16 |     await auto('Press enter', aiArgs, options)
  17 |     await page.waitForTimeout(5000)

Response is very much appreciated, TIA.

add screnshot analyzes

Now that ChatGPT supports image analyzes, we could send screenshots in addition to HTML.

add snapshots

Add a way to save instructions into a snapshot after the first run.

This would mean that the OpenAI API needs to be called only when:

  1. running the test the first time
  2. re-generating the test when the website has changed

I've used https://vitest.dev/guide/snapshot snapshots before, and they were a pleasure to work with. We could replicate equivalent behavior.

Test timeout of 30000ms exceeded

Consistently getting 'Test timeout of 30000ms exceeded.' error although playwright.config.js has the following timeout settings:

    timeout: 60000,
    actionTimeout: 120 * 1000,
    navigationTimeout: 60 * 1000,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.