Welcome to Manen documentation!ΒΆ

manen is a package built to extend Selenium user experience. Among the core features, you can find:

  • an implementation of the page object model design pattern

  • a class which completes WebDriver

  • a function to easily find and isolate DOM elements inside a page

This package allows you to write more concise, flexible and powerful code compared to what you would do by using only Selenium. Here is a comparison of the same code written with and without Manen:

from datetime import datetime
from typing import Annotated

from selenium.webdriver.chrome.webdriver import WebDriver

from manen.page_object_model.config import CSS, Default, Wait, XPath
from manen.page_object_model.component import Page, Component


class BlogPage(Page):
   class Article(Component):
      title: Annotated[str, XPath("//h1")]
      n_likes: Annotated[int, CSS("span.n_likes")]
      tags: Annotated[list[str], CSS("span.tag"), Default([])]
      updated_at: Annotated[datetime, CSS("span.updated_at")]

   articles: Annotated[list[Article], CSS('div.article'), Wait(3)]


driver = WebDriver()

page = BlogPage(driver)
article = page.articles[0]

print(article.model_dump())
# {
#   'title': 'Hello, Manen!',
#   'n_likes': 42,
#   'tags': ['python', 'selenium'],
#   'updated_at': datetime.datetime(2021, 1, 1, 0, 0)
# }
from dateparser import dateparser
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

driver = WebDriver()

articles = WebDriverWait(driver, 3).until(
    EC.presence_of_elements_located((By.CSS, "article"))
)
title = articles[0].find_element(By.CSS_SELECTOR, "h1").text
n_likes = int(articles[0].find_element(By.CSS_SELECTOR, "span.n_likes").text)
try:
    tags = articles[0].find_element(By.CSS_SELECTOR, "span.tags")
except NoSuchElementException:
    tags = []
updated_at = dateparser(articles[0].find_element(By.CSS_SELECTOR, "p.date").text)

print({'title': title, 'n_likes': n_likes, 'tags': tags, 'updated': updated_at})
# {
#   'title': 'Hello, Manen!',
#   'n_likes': 42,
#   'tags': ['python', 'selenium'],
#   'updated_at': datetime.datetime(2021, 1, 1, 0, 0)
# }

Besides being more concise, the version using Manen is also more verbose, meaning that it can ease the comprehension of your source code.

You can find a deeper explanation that motivated the development of Manen in the section Why such package?.