Code Example

Process data to ERP

An example how to use Aiviro to create a story, which at first reads emails from a mailbox and extracts the data from the email’s attachment, then it continues by adding this data into the ERP. In the end, all opened windows are closed by robot and a report is sent.

Main Story

An example how to use Aiviro, which handles the main loop with all the required actions and steps. To see more information about used classes, please see BaseScenario, ShellCommands, InvoiceReader.
Download here main_story_example.py
from pathlib import Path
from typing import Generator, Tuple

import aiviro
from aiviro.modules.config import YAMLConfig
from aiviro.modules.pdf import create_pdf_robot
from aiviro.modules.powershell import ShellCommands
from aiviro.modules.reader import InvoiceData, InvoiceReader
from docs.code_examples.erp_handler_example import ERPHandler


class MainStoryXX(aiviro.BaseScenario):
    """
    This class inherits from BaseScenario and implements the main logic of the story.
    This class handles a process of parsing attachments from an email and adding this
    data to an ERP system. In the end, all opened windows are closed by a shell command
    and a report is generated and sent to the list of recipients defined in the config file.
    """

    def __init__(self, config: YAMLConfig):
        super().__init__(config)
        self.pdf_robot = create_pdf_robot()

        # name of the robot is set in the config file
        self.r = self.robot(robot_name="rdp_robot")
        self.erp_handler = ERPHandler(
            rdp_robot=self.r, export_folder=self.tmp_folder.unique_folder
        )
        self.invoice_reader = InvoiceReader(self.pdf_robot)
        self.shell_commands = ShellCommands(self.r)
        self.notifier = self.email_notifier()

    def _before_run(self) -> None:
        """
        e.g. wait until robot is connected to the RDP machine
        """
        self.r.wait_until_ready()

    def _after_run(self) -> None:
        """
        e.g. close all opened applications, send a report etc.
        """
        self.shell_commands.close_all_open_windows().execute()
        self.notifier.send_report()

    def _run(self):
        """
        This method handles the main loop of the story
        """
        for parsed_data, pdf_path in self._get_data_from_emails_pdf():
            try:
                self.erp_handler.handle_story_xx(data=parsed_data, pdf_path=pdf_path)
            except Exception as e:
                self.notifier.error(
                    f"An error occurred when processing PDF file {pdf_path} - {e}"
                )
            else:
                self.notifier.successful(
                    f"Data from PDF file {pdf_path} was successfully added to ERP"
                )

    @aiviro.step
    def _get_data_from_emails_pdf(
        self,
    ) -> Generator[Tuple[InvoiceData, Path], None, None]:
        """
        All the required parameters for email extractor can be set in the
         .yaml config file , for example:
         - maximum number of emails to be processed by setting variable
           'max_valid_emails'
         - conditions for email attachments by setting variable 'attachment_conditions',
           e.g. if email contains pdf files within its attachments, then each
           attachment is checked if it is a pdf file, otherwise it is skipped
        """
        for _email, attachments in self.email_extractor().extract_all():
            for one_attachment in attachments:
                if one_attachment.suffix != ".pdf":
                    continue
                data = self._parse_file(one_attachment)
                yield data, one_attachment

    @aiviro.step
    def _parse_file(self, one_attachment: Path) -> InvoiceData:
        # set required pdf file as a source for the pdf robot
        self.pdf_robot.parse(one_attachment)
        return self.invoice_reader.parse()

ERP Handler

An example how to use Aiviro to handle actions in ERP system. In this case, Aiviro robot is used to add parsed data from the pdf file to the ERP system.
import datetime
import pathlib

import aiviro
from aiviro.modules.reader import InvoiceData


class ERPHandler:
    def __init__(self, rdp_robot: "aiviro.RDPRobot", export_folder: pathlib.Path):
        self.r = rdp_robot
        self._export_folder = export_folder

    @aiviro.step
    def handle_story_xx(self, data: InvoiceData, pdf_path: pathlib.Path) -> None:
        """Method called to handle whole process of adding data to ERP"""
        self._start_erp()
        self._open_invoices_with_new_record()
        self._write_to_new_record(data)
        self._attach_pdf(pdf_path)
        self._save_new_record()
        self._close_erp()

    @aiviro.step
    def _start_erp(self) -> None:
        """Method to start ERP program via WIN+R shortcut"""
        self.r.start_process(r"path\to\your\erp\program.exe")

    @aiviro.step
    def _open_invoices_with_new_record(self) -> None:
        """Method to open invoices tab in ERP"""
        self.r.double_click(aiviro.Text("Přijaté faktury", element_index=0))
        self.r.click(aiviro.Text("Nový záznam", element_index=0))

    @aiviro.step
    def _write_to_new_record(self, data: InvoiceData) -> None:
        """Method to write provided data to new record"""
        self.r.type_text(
            element=aiviro.Input("Číslo dokladu", element_index=0),
            text_to_type=data.invoice_id.value,
        )
        self.r.type_text(
            element=aiviro.Input("Celková částka", element_index=0),
            text_to_type=str(data.total_amount.value),
        )
        self.r.type_text(
            element=aiviro.Input("Celková částka bez DPH", element_index=0),
            text_to_type=str(data.total_amount_without_tax.value),
        )
        self.r.type_text(
            element=aiviro.Input("Daňový doklad", element_index=0),
            text_to_type=datetime.date.strftime(data.tax_date.value, "%d.%m.%Y"),
        )

    @aiviro.step
    def _attach_pdf(self, pdf_path: pathlib.Path) -> None:
        """Method to attach pdf to the new record"""
        self.r.transfer_files_to_guests_clipboard(pdf_path)
        self.r.click(aiviro.Button("Připojit ze schránky", element_index=0))

    @aiviro.step
    def _save_new_record(self) -> None:
        """Method to save new record simply by clicking on the Save button.
        And transfer generated files from guest clipboard to the export folder on the host machine.
        """
        self.r.click(aiviro.Button("Uložit", element_index=0))
        self.r.click(aiviro.Text("Nový záznam", element_index=0))
        self.r.transfer_files_from_guests_clipboard(self._export_folder, copy=True)

    @aiviro.step
    def _close_erp(self) -> None:
        """Method to close ERP program"""
        self.r.click(aiviro.Button("Zavřít", element_index=0))
        self.r.click(aiviro.Button("Ano", element_index=0))

Simple scripts

Example how to automate login testing.
Download here simplehq_login.py
import aiviro

if __name__ == "__main__":
    # init aiviro logger
    aiviro.init_logging()

    #################
    # Test case
    #################
    # create web-robot
    r = aiviro.create_web_robot(headless=False)  # only works in non-headless mode
    r.go_to_url("https://app.simplehq.co/login.html")

    # wait until page is fully loaded
    r.wait_for(aiviro.Text("Hello!"))

    # type login credentials & click log-in button
    r.type_text(aiviro.Input("Email"), "jelenovi.pivo.nelej@wtf.com")
    r.type_text(aiviro.Input("Password"), "123456789")
    r.click(aiviro.Button("Log In"))

    # check that the log-in was invalid
    r.wait_for(aiviro.Text("Information provided is incorrect."), timeout=10)

    # close the web-robot
    r.close()
Example how to check the alignment of elements.
Download here todo_mvc_alignment.py
import aiviro

URLS = [
    "http://todomvc.com/examples/vanillajs/",
    "http://todomvc.com/examples/backbone/",
    "http://todomvc.com/examples/angularjs/#/",
    "http://todomvc.com/examples/emberjs/",
    "http://todomvc.com/examples/knockoutjs/",
    "http://todomvc.com/examples/dojo/",
    "http://todomvc.com/examples/knockback/",
    "http://todomvc.com/examples/canjs/",
    "http://todomvc.com/examples/polymer/index.html",
    "http://todomvc.com/examples/react/#/",
    "http://todomvc.com/examples/mithril/#/",
    "http://todomvc.com/examples/vue/",
    "http://todomvc.com/examples/backbone_marionette/",
]


if __name__ == "__main__":
    # init aiviro logger
    aiviro.init_logging()

    #################
    # Test case
    #################
    # create web-robot
    r = aiviro.create_web_robot(headless=True)

    for url in URLS:
        r.go_to_url_in_new_tab(url)

        # create Input search-object & wait until it appears on the website
        input_object = aiviro.Or(
            aiviro.Button("What needs to be done?", element_index=0),
            aiviro.Input("What needs to be done?", element_index=0),
        )
        input_box = r.wait_for(input_object, timeout=15)

        # add 3 tasks into list
        r.type_text(input_box, "Do the laundry\n")
        r.type_text(input_box, "Go shopping\n")
        r.type_text(input_box, "Pay the bills\n")

        # wait until the last task appears in the list
        r.wait_for(aiviro.Text("Pay the bills"), timeout=10)
        do_the_laundry_label = aiviro.Text("Do the laundry")
        go_shopping_label = aiviro.Text("Go shopping")
        pay_the_bills_label = aiviro.Text("Pay the bills")

        # check different alignment of the elements
        r.check_are_in_column(
            do_the_laundry_label,
            go_shopping_label,
            pay_the_bills_label,
            anchor=aiviro.layout_anchor.LEFT,
            tolerance=10,
        )
        r.check_is_positioned(
            do_the_laundry_label,
            go_shopping_label,
            direction_type=aiviro.layout_positions.IS_ABOVE,
        )
        r.check_is_positioned(
            pay_the_bills_label,
            go_shopping_label,
            direction_type=aiviro.layout_positions.IS_BELOW,
        )

    # close the web-robot
    r.close()
Example of filling up the registration forms.
Download here eshop_registration.py
import aiviro

if __name__ == "__main__":
    aiviro.init_logging()

    r = aiviro.create_web_robot(headless=True)
    r.set_animation_timeout(5)

    FIRST_NAME = "Aiviro"
    LAST_NAME = "Test"
    EMAIL = "aiviro@test.cz"
    PHONE_NUMBER = "777189234"

    # e-shop Nazuby
    r.go_to_url("https://www.nazuby.cz/")
    r.click(aiviro.Icon("Prihlasit"), aiviro.Text("Registrace"))
    r.type_text(aiviro.Input("Jmeno"), FIRST_NAME + " " + LAST_NAME)
    r.type_text(aiviro.Input("Vas e-mail"), EMAIL)

    # e-shop MALL
    r.go_to_url("https://www.mall.cz")
    r.move(aiviro.Text("Muj ucet"))

    box_button = r.wait_for(aiviro.Button("Zaregistrovat"))
    r.click(box_button)

    r.type_text(aiviro.Input("Jmeno"), FIRST_NAME)
    r.type_text(aiviro.Input("Prijmeni"), LAST_NAME)
    r.type_text(aiviro.Input("Vas e-mail"), EMAIL)
    r.type_text(aiviro.Input("Telefon"), PHONE_NUMBER)