npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

citronella

v1.0.1

Published

webdriver extension with a page object wrapper

Downloads

3

Readme

Citronella

npm version

webdriver extension with a page object wrapper.

Example Tests

const { Builder } = require("selenium-webdriver");
const { WebPage } = require("citronella");
const ContentsPage = require("../page/contents-page");
const assert = require("assert");

describe("test navigation", function () {
  this.timeout(10000);
  before(async function () {
    driver = await new Builder().forBrowser("chrome").build();
    web = new WebPage(driver, 10000, true);
    web.page = ContentsPage;
    await web.driver.get("https://www.npmjs.com/");
  });

  after(async function () {
    driver.quit();
  });

  it("navigate to a pro page", async function () {
    await web.page.homePage.proButton.click();
    title = await web.driver.getTitle();
    await assert.match(title, /Pro/);
  });

  it("navigate to a teams page", async function () {
    await web.page.proPage.teamsButton.click();
    title = await web.driver.getTitle();
    await assert.match(title, /Teams/);
  });

  it("navigate to a products page", async function () {
    await web.page.teamsPage.pricingButton.click();
    title = await web.driver.getTitle();
    await assert.match(title, /Products/);
  });

  it("navigate to a home page", async function () {
    await web.page.productsPage.npmHomepageIcon.click();
    title = await web.driver.getTitle();
    await assert.match(title, /npm/);
  });
});

alt terminal

Even though this module is mainly designed for the page object model, it can also be used without it for quick prototyping or mockups, etc.

const { By, Builder } = require("selenium-webdriver");
const { WebPage } = require("citronella");
const assert = require("assert");

describe("test search package with locate method", function () {
  this.timeout(10000);
  before(async function () {
    driver = await new Builder().forBrowser("chrome").build();
    web = new WebPage(driver, 10000, true);
    await web.driver.get("https://www.npmjs.com/");
  });

  after(async function () {
    driver.quit();
  });

  it("results list include citronella", async function () {
    await web.locate(By.name("q")).sendKeys("citron");
    await web.locate(By.css('button[type="submit"]')).click();
    let ElementsResult =
      await web.locate(By.css('a[target="_self"]')).getElements();
    let textList = [];
    for (let i in ElementsResult) {
      textList.push(await ElementsResult[i].getText());
    }
    assert.match(textList.join(), /citronella/);
  });
});

alt terminal2


Install Package

npm i citronella

Documentation

There are only two modules import in this package:

  • The first module is for the test script.
const { Builder } = require("selenium-webdriver");
const { WebPage } = require("citronella");

describe("test navigation", function () {
  this.timeout(10000);
  before(async function () {
    driver = await new Builder().forBrowser("chrome").build();
    web = new WebPage(driver, 10000, true);
  });
});
  • The second module are for the page object model.
const { By } = require("selenium-webdriver");
const { ui } = require("citronella");
const MenuBar = require("../components/menu-bar");

class HomePage extends MenuBar {
  get signUpForFreeButton() {
    return ui(By.css('div.w-100 a[href="/signup"]'));
  }

  get signUpForFreeButton() {
    return ui(By.css('div.w-100 a[href="/products/pro"]'));
  }
}

module.exports = HomePage;

Page Object Design / Strategy

see full Page object example

const { By, Builder } = require("selenium-webdriver");
const { ui, WebPage } = require("citronella");

class HomePage {
  get signUpForFreeButton() {
    return ui(By.css('div.w-100 a[href="/signup"]'));
  }
}

class SignupPage {
  get usernameInput() {
    return ui(By.id("signup_name"));
  }  

  get passwordInput() {
    return ui(By.id("signup_password"));
  }

  get signUpButton() {
    return ui(By.id("signup_button"));
  }
}

class ContentsPage {
  get homePage() {
    return HomePage;
  }

  get signupPage() {
    return SignupPage;
  }
}

main(async function () {
  driver = await new Builder().forBrowser("chrome").build();
  web = new WebPage(driver, 10000, true);
  web.page = ContentsPage;
  await web.driver.get("https://www.npmjs.com/");

  await web.page.homePage.signUpForFreeButton.click();
  await web.page.signupPage.usernameInput.sendKeys("[email protected]");
  await web.page.signupPage.passwordInput.sendKeys("FizzBuzz");
  await web.page.signupPage.signUpButton.click();
}

main();

Usage

citronella.WebPage

Args:
  • driver / webdriver
  • wait (ms)
  • logger (bool)
Method Lists:

| Method Name | Args* | Kwargs** | Note | | ------------------ |:-----------:|:----------------:|:----:| | driver | - | - | return selenium webdriver object | | locate | by | - | similar asdriver.findElement as input & return citronella.WebUi object | | page | page object | - | setter | | page | - | - | getter | | readyState | timeout(ms) | - | execute javascript document.readyState manually | | sleep | number(ms) | - | |

citronella.ui / citronella.WebUi

Args:
  • by
Method Lists:

| Method Name | Args* | Kwargs** | Note | | ------------- |:------:|:------------------:|:----:| | sendKeys | text, returnKey(bool) | - | | | click | - | - | | | getElement | - | - | | | getElements | - | - | | | untilElementLocated | - | - | wrapper of webdriverWait / elementLocated | | untilElementsLocated | - | - | wrapper of webdriverWait / elementsLocated | | untilElementIsVisible | - | - | wrapper of webdriverWait / elementIsVisible | | untilElementIsNotVisible | - | - | wrapper of webdriverWait / elementIsNotVisible | | untilElementIsEnabled | - | - | wrapper of webdriverWait / elementIsEnabled | | untilElementIsDisabled | - | - | wrapper of webdriverWait / elementIsDisabled | | untilElementIsSelected | - | - | wrapper of webdriverWait / elementIsSelected | | untilElementIsNotSelected | - | - | wrapper of webdriverWait / elementIsNotSelected |

Testing powered by

BrowserStack Open-Source Program