npm package: @kbourro/ts-browser
Description: Automated browser in TypeScript
Author: Kristofer Bourro
Latest version: 1.1.2

```typescript
import {
  Browser, Page, ElementHandleExtended, BrowserSettings, UserAgent
} from './browser';
import helpers from './helpers';

async function main() {
  const device = new UserAgent((
    data: {
      viewportHeight: null;
      viewportWidth: null;
      screenHeight: null;
      screenWidth: null;
      userAgent: string | string[];
      deviceCategory: any;
    },
  ) => {
    if (
      data.viewportHeight === null
      || data.viewportWidth === null
      || data.screenHeight === null
      || data.screenWidth === null
    ) {
      return false;
    }
    return (
      data.deviceCategory === 'desktop'
      && !data.userAgent.includes('-CN')
      && !data.userAgent.includes('baidu')
      && !data.userAgent.includes('alibaba')
      && !data.userAgent.includes('iPhone')
    );
  });
  const browserSettings: BrowserSettings = {
    location: {
      latitude: helpers.chance.floating({ min: 37.670777, max: 38.25975 }),
      longitude: helpers.chance.floating({ min: 23.640615, max: 23.975921 }),
    },
    languages: ['el-GR', 'el', 'en-US', 'en'],
    userAgent: device,
    proxy: new Proxy({ url: 'IP:PORT:USERNAME:PASSWORD' }), // OR url: 'http://USERNAME:PASSWORD@IP:PORT' OR username: 'USERNAME', password: 'PASSWORD' ...
  };
  const browserInstance: Browser = new Browser(browserSettings);
  const page = await browserInstance.launch();
  // browserInstance.goto(page,"https://bot.sannysoft.com/")
  await test(browserInstance, page);
}

async function test(browserObj: Browser, page: Page) {
  let element: ElementHandleExtended|null = null;
  let elements:ElementHandleExtended[]|null = null;
  await browserObj.goto(page, 'https://www.youtube.com');
  try {
    element = await browserObj.getElement(
      page,
      "//paper-button[@class='style-scope yt-button-renderer style-text size-small']",
      0,
      { visible: true, timeout: 5000 },
    );
    await browserObj.click(page, element);
    await browserObj.waitFor(5000);
  } catch (error) {
    element = null;
  }
  try {
    element = await browserObj.getElement(
      page,
      "//div[@id='introAgreeButton']/span",
      0,
      { visible: true, timeout: 2000 },
    );
    await browserObj.click(page, element);
    await browserObj.waitFor(5000);
  } catch (error) {
    element = null;
  }
  try {
    element = await browserObj.getElement(
      page,
      "//c3-material-button[@class='button-renderer compact upsell-dialog-dismiss-button']",
      0,
      { visible: true, timeout: 1000 },
    );
    await browserObj.click(page, element);
    await browserObj.waitFor(5000);
  } catch (error) {
    element = null;
  }
  try {
    element = await browserObj.getElement(
      page,
      "//div[@class='dialog mandatory-consent-kickin']//div[@class='consent-bump-button-wrapper']//button",
      0,
      { visible: true, timeout: 2000 },
    );
    await browserObj.click(page, element);
    await browserObj.waitFor(5000);
  } catch (error) {
    element = null;
  }

    element = await browserObj.getElement(
      page,
      "(//button[@class='icon-button topbar-menu-button-avatar-button'])[1]/c3-icon",
      0,
      { timeout: 2000 },
    );
    await browserObj.click(page, element);
    await browserObj.waitFor(5000);
    try {
      element = await browserObj.getElement(
        page,
        "//input[@name='search']",
        0,
        {
          visible: true,
          timeout: 5000,
        },
      );
      await browserObj.type(
        page,
        element,
        helpers.chance.pickone(['κλειδαράς πειραιά']),
        {
          delay: 500,
        },
        true,
      );
      await browserObj.waitFor(3000);
    } catch (error) {
      throw Error("Element //input[@name='search'] not found.");
    }
    try {
      element = await browserObj.getElement(
        page,
        "(//form[@class='searchbox-form cbox']/button)[2]",
        0,
        { visible: true, timeout: 5000 },
      );
      await browserObj.click(page, element);
    } catch (error) {
      throw Error(
        "Element //form[@class='searchbox-form cbox']/button not found.",
      );
    }
    await browserObj.waitFor(5000);

    elements = await browserObj.getElements(
      page,
      "//a[@class='compact-media-item-metadata-content']",
      { visible: true, timeout: 10000 },
    );
    for (const el of elements) {
      const href = await el.evaluate((el) => el.getAttribute('href'));
      if (href && href.includes('Q7sDE95WoxY')) {
        await browserObj.click(page, el);
        break;
      }
    }

    await browserObj.waitFor(3000);
    try {
      element = await browserObj.getElement(
        page,
        "//paper-button[@class='style-scope yt-button-renderer style-text size-small']",
        0,
        { visible: true, timeout: 2000 },
      );
      await browserObj.click(page, element);
      await browserObj.waitFor(5000);
    } catch (error) {
      element = null;
    }
    try {
      element = await browserObj.getElement(
        page,
        "//div[@id='introAgreeButton']/span",
        0,
        { visible: true, timeout: 2000 },
      );
      await browserObj.click(page, element);
      await browserObj.waitFor(5000);
    } catch (error) {
      element = null;
    }
    try {
      element = await browserObj.getElement(
        page,
        "//div[@class='watchPlayBugVerticalAlign']",
        0,
        { visible: true, timeout: 5000 },
      );
      await browserObj.click(page, element);
      await browserObj.waitFor(3000);
    } catch (error) {
      element = null;
    }
  await browserObj.close();
}
```