6. Controller Service

6.1. About

Controller services allow developers to modularize controllers for larger web applications. Services are a lightweight resource that simply consume a given controller, and allow developers to design functionality using the same contextual logic as they would within a controller.

6.2. Best Practices

If a controller is exceeding some 800 lines of code, it may be beneficial for both organization and productivity to compartementalize strings of functionality operating off of the same base component.

6.3. Attributes

When a service is instantiated, the constructor automatically binds the following attributes:

  • controller: Reference to parent controller instance.
  • browser: Reference to parent controller’s webdriver
  • components: Reference to parent controller’s components.
  • env: Reference to parent controller’s env resource.

6.4. Example

The following example is an abstraction of the Google controller featured on Getting Started:

from pyscc import Controller, Component, Service, component_element, \
    component_elements, component_group

class Home(Component):

    _ = 'body > app'  # optional root selector to be applied to all component items

    def search_bar(self):
        # we only need to return the selector
        # pyscc will automatically determine whether it's xpath or css
        return 'input#lst-ib'

    def search_button(self):
        # the element wrapper allows us to format our selectors
        # ref.search_button.fmt(value='Google Search')
        return '//input[@type="submit"][@value="{value}"]'

class Results(Component):

    def results(self):
        return 'div.g'

class SearchService(Service):

    def search(self, query, redirect=False):
        # navigate to base url
        # create reference to our home component
        home = self.components.home
        # wait 5 seconds for search bar to be visible
        # write query in the search bar
            .wait_visible(5, error=True)\

        # target the search button with the text "Google Search"
        # click on the search button
            .fmt('Google Search')\

class Google(Controller):

    def __init__(self, browser, base_url):
        super(Product, self).__init__(browser, base_url, {
            'home': Home,
            'results': Results
        self.add_service('search', SearchService)

    def number_of_results():
        return self.components.results.results.count()

The sample above can be utilized like so:

from selenium import webdriver

google = Google(webdriver.Chrome(), 'https://google.com')
# ensure at least one result is available within 5 seconds
assert google.components.results.results\
    .wait_for(5, length=1)

# terminate our controller's webdriver