def test_pypi(): """ LocatorModules/PageObjectLess LocatorModules == page locators/selectors are simply vars in python modules Might be also called as PageModules =========================================================================== Here the page model is implemented in the simplest modular way with simplification to "just vars, no functions for steps" in python modules. GO FOR: * a bit higher abstraction (no more technical selectors in tests code) * extra readability in test code * reusable vars with locators * easier refactoring (Refactor>Rename, etc. can be applied) * yet KISS modeling (Keep It Simple Stupid) TRADEOFFS: - common ones for "programming without functions" style ;) some code might be too bulky, business steps might be hardly visible in a long e2e test """ browser.open(pypi.url) pypi.search.type('selene').press_enter() pypi.results\ .should(have.size_greater_than_or_equal(9)) \ .first.should(have.text('Concise API for selenium in Python')) pypi.results.first.click() browser.should(have.url(pypi.url + 'project/selene/')) browser.should(have.title_containing('selene · PyPI'))
def open_app(self): browser.open('#/') browser.should( have.js_returned( True, 'return Object.keys(require.s.contexts._.defined).length === 39' ))
def test_duckduckgo(): """ Straightforward/PageObjectLess style =================================== GO FOR: * KISS (Keep It Simple Stupid), straightforward style * easy for newbies in automation (no need to learn modules/OOP(classes)) * easy for some DEVs if they will use these tests (and they should!) they know selectors and internals of app they develop hence, building more abstractions (modules/classes) on top of more low level straightforward code (like below) would add too much complexity to them, and harder in day-to-day usage TRADEOFFS: - given selectors are duplicated all over the project code base when you want to change it then you have to use global Find&Replace text, with sometimes pretty thorough manual checks line by line all places where the change will be applied. You CAN'T use some refactoring features of IDE like Refactor>Rename """ browser.open('https://duckduckgo.com/') browser.element('[name=q]')\ .should(be.blank)\ .type('yashaka selene python').press_enter() browser.all('.result__body') \ .should(have.size_greater_than(5)) \ .first.should(have.text('User-oriented Web UI browser tests')) browser.all('.result__body').first.element('a').click() browser.should(have.title_containing('yashaka/selene'))
def test_selene_demo(self): tasks = browser.all("#todo-list>li") active_tasks = tasks.filtered_by(have.css_class("active")) browser.open(app_url) browser.should(have.js_returned(True, is_TodoMVC_loaded)) for task_text in ["1", "2", "3"]: browser.element("#new-todo").set_value(task_text).press_enter() tasks.should(have.texts("1", "2", "3")).should_each(have.css_class("active")) browser.element("#todo-count").should(have.text('3')) tasks[2].element(".toggle").click() active_tasks.should(have.texts("1", "2")) active_tasks.should(have.size(2)) tasks.filtered_by(have.css_class("completed")).should(have.texts("3")) tasks.element_by(not_(have.css_class("completed"))).should( have.text("1")) tasks.filtered_by(not_(have.css_class("completed"))).should( have.texts("1", "2")) browser.element(by.link_text("Active")).click() tasks[:2].should(have.texts("1", "2")) tasks[2].should(be.hidden) browser.element(by.id("toggle-all")).click() browser.element("//*[@id='clear-completed']").click() tasks.should(be.empty)
def test_search(): browser.open('https://www.ecosia.org/') browser.element(by.name('q')).type('github yashaka selene').press_enter() browser.all('.result').first.element('.result-url').click() browser.should(have.title_containing('yashaka/selene'))
def visit(self): download_page = "return $._data($('#clear-completed')[0],"\ "'events').hasOwnProperty('click')" browser.open('https://todomvc4tasj.herokuapp.com') browser.should(have.js_returned(True, download_page)) return self
def open_app(): browser.open('https://todomvc4tasj.herokuapp.com/') window_uploaded = "return $._data($('#clear-completed')[0], 'events')" \ ".hasOwnProperty('click') " \ "& " \ "Object.keys(require.s.contexts._.defined).length == 39" browser.should(have.js_returned(True, window_uploaded))
def visit(): browser.config.hold_browser_open = True browser.open("http://todomvc4tasj.herokuapp.com/") browser.should( have.js_returned( True, "return $._data($('#clear-completed')[0], 'events').hasOwnProperty('click')" ))
def test_search(): browser.open('https://google.com/ncr') browser.element(by.name('q')).should(be.blank)\ .type('python selene').press_enter() results = browser.all('#search .g') results.should(have.size_greater_than_or_equal(6)) results.first.should(have.text('Concise API for Selenium')) results.first.element('.r>a').click() browser.should(have.title_containing('yashaka/selene'))
def open_todomvc(): # browser.open('#/') \ # .should(have.js_returned(True, # 'return ($._data($("#clear-completed").get(0), "events")' # '.hasOwnProperty("click") && ' # '(Object.keys(require.s.contexts._.defined).length === 39))')) browser.open('#/') # browser.element('#main').should( # have.attribute('style').value('display: none;') # .or_(have.attribute('style').value('display: block;'))) # browser.element('#main').should(be.in_dom) # .should(have.js_returned(True, # 'return ($._data($("#clear-completed").get(0), "events")' # '.hasOwnProperty("click") && ' # '(Object.keys(require.s.contexts._.defined).length === 39))')) browser.should( have.js_returned( True, '$("#main")[0].style.display === "none" ||' '$("#main")[0].style.display === "block"'))
def step(repo='yashaka/selene'): browser.should(have.title_containing(repo))
def open(self): browser.open('https://todomvc4tasj.herokuapp.com/') script_on_clear_completed = "return 'click' in \ $._data($('#clear-completed')[0],'events')" browser.should(have.js_returned(True, script_on_clear_completed)) return self
def open(self): browser.open('https://todomvc4tasj.herokuapp.com/') app_wait = "return $._data($('#clear-completed')[0], 'events')"\ ".hasOwnProperty('click')" browser.should(have.js_returned(True, app_wait)) return self
def should_be_on_github(repo='yashaka/selene'): browser.should(have.title_containing(repo))
from selene import have from selene.support.shared import browser browser.config.hold_browser_open = True browser.open("http://todomvc4tasj.herokuapp.com/") browser.should(have.js_returned(True, "return $._data($('#clear-completed')[0], 'events').hasOwnProperty('click')")) # Add browser.element('#new-todo').type('a').press_enter() browser.element('#new-todo').type('b').press_enter() browser.element('#new-todo').type('c').press_enter() browser.all('#todo-list>li').should(have.exact_texts('a', 'b', 'c')) # Edit browser.all('#todo-list>li').element_by(have.exact_text('b')).double_click() browser.all('#todo-list>li').element_by(have.css_class('editing')).element('.edit').type(' edited').press_enter() # Complete & Clear browser.all('#todo-list>li').element_by(have.exact_text('b edited')).element('.toggle').click() browser.element('#clear-completed').click() browser.all('#todo-list>li').should(have.exact_texts('a', 'c')) # Cancel Edit browser.all('#todo-list>li').element_by(have.exact_text('c')).double_click() browser.all('#todo-list>li').element_by(have.css_class('editing')).element('.edit').type('to be canceled').press_escape() # Delete browser.all('#todo-list>li').element_by(have.exact_text('c')).hover().element('.destroy').click() browser.all('#todo-list>li').should(have.exact_text('a'))
def should_be_on(self, title_text): browser.should(have.title_containing(title_text))
def githib_page_shuold_be(partial_title): browser.should(have.title_containing(partial_title))
def should_be_opened(): browser.should(have.url(_url))
def open(self, relative_url='/'): browser.open(TodoMvcPage.base_url + relative_url) app_loaded_require_js = 'return Object.keys(' \ 'require.s.contexts._.defined).length === 39' browser.should(have.js_returned(True, app_loaded_require_js)) return self