def test_update(): config = Config.default() assert "browser" in config config.update({"x": "y"}) assert config.x == "y" config.update("x=z") assert config.x == "z" config.update("a.b.c=True") assert config.a.b.c config.update("a.b.d=False") assert not config.a.b.d config.update("a.b.e=123") assert config.a.b.e == 123 config.update("a.b.e=123.4") assert config.a.b.e == 123.4 config.update("desktop") assert config.browser.browser == "chrome" with pytest.raises(FileNotFoundError): config.update(Path("a/b/c/d")) with pytest.raises(ValueError): config.update(123)
def test_page_snapshot(): source = """ <body> <div wtl-uid=12> <a href="x" wtl-uid=23> <p wtl-uid=15></p> </a> <p wtl-uid=19></p> <p wtl-uid=7></p> </div> </body> """ metadata = [ { "wtl_uid": 12, "x": "hi" }, { "wtl_uid": 15, "x": "hello" }, { "wtl_uid": 7, "x": "whatup" }, { "wtl_uid": 19, "x": "shoo bre" }, { "wtl_uid": 23, "x": "sho" }, ] snapshot = PageSnapshot( bs4.BeautifulSoup(source, Config.default().bs_html_parser), {}, metadata) elements = snapshot.elements assert len(elements) == 5 assert len(elements.by_subtree(Selector("div"), include_root=False)) == 4 assert len(elements.by_subtree(Selector("div"))) == 5 assert len(elements.by_selector(Selector("p"))) == 3 counter = 0.3 for p in elements.by_selector(Selector("p")): p.metadata["a"] = counter p.raw_scores["a"] = counter * 2 counter += 0.1 assert len(elements) == 5 assert len(elements.by_score("a")) == 3 assert len(elements.by_raw_score("a")) == 3 assert len(elements.by_score("a", 0.35)) == 2 assert len(elements.by_raw_score("a", 0.65)) == 2 assert not elements.by_score("b") assert not elements.by_raw_score("b")
def test_complex(): @wtl.single_tab def policy(w, view): menu_actions = view.actions.by_type(Click).by_score("menu") w.metadata["clicks"] = w.metadata["clicks"] + 1 return random.choice(menu_actions) def menu_classifier_func(elements, _): return [ elem for elem in elements if elem.location.x < 10 and elem.location.y < 200 and elem.metadata["tag"] == "a" ] config = Config.default(["headless", "desktop"]) workflow = wtl.Workflow(url=TESTURL, config=config, policy=policy, goal=wtl.goals.N_STEPS(3)) workflow.metadata["clicks"] = 0 workflow.classifiers.add(wtl.ActiveElementFilter(action=Click)) workflow.classifiers.add( wtl.ElementClassifier(name="menu", action=Click, subset="is_active", highlight=True, callback=menu_classifier_func)) workflow.run() assert workflow.success assert workflow.metadata["clicks"] == 3 workflow.quit()
def test_abort(): # Abort a workflow config = Config.default(["headless"]) workflow = wtl.Workflow( url=TESTURL, config=config, policy=lambda *_, **__: {wtl.Workflow.SINGLE_TAB: Abort()}, goal=wtl.goals.N_STEPS(3), ) workflow.run() assert not workflow.success workflow.quit()
def test_update(): config = Config.default() assert "browser" in config config.update({"x": "y"}) assert config.x == "y" config.update("x=z") assert config.x == "z" config.update("a.b.c=True") assert config.a.b.c config.update("a.b.d=False") assert not config.a.b.d config.update("a.b.e=123") assert config.a.b.e == 123 config.update("a.b.e=123.4") assert config.a.b.e == 123.4
def test_multiple(): config = Config.default(["headless"]) @wtl.multi_tab_coroutine def policy(): yield _, views = yield {} urls = set(v.snapshot.page_metadata["url"] for v in views.values()) print([v.snapshot.page_metadata["url"] for v in views.values()]) assert len(urls) == 1 _, views = yield { "1": wtl.actions.Click(wtl.Selector(".sidenav a:nth-of-type(2)")), "2": None, "3": wtl.actions.Click(wtl.Selector(".sidenav a:nth-of-type(3)")), "4": None, } urls = set(v.snapshot.page_metadata["url"] for v in views.values()) print([v.snapshot.page_metadata["url"] for v in views.values()]) assert len(urls) == 3 _, views = yield { "4": wtl.actions.Click(wtl.Selector(".sidenav a:nth-of-type(4)")) } urls = set(v.snapshot.page_metadata["url"] for v in views.values()) assert len(urls) == 4 yield {} workflow = wtl.Workflow(url={ "A": { "1": TESTURL, "2": TESTURL }, "C": { "3": TESTURL, "4": TESTURL } }, config=config, policy=policy) workflow.run() assert workflow.loop_idx == 4 workflow.quit()
def test_simple(browser): # Just navigate to a single tab, do nothing. config = Config.default(["headless", browser]) workflow = wtl.Workflow( url=TESTURL, config=config, policy=lambda *_, **__: {wtl.Workflow.SINGLE_TAB: Wait(1)}, goal=wtl.goals.N_STEPS(3), ) workflow.run() assert workflow.success workflow.quit() with pytest.raises(Error): workflow.run()
def test_page_snapshot(): source = """ <body> <div wtl-uid=12> <p wtl-uid=15></p> <p wtl-uid=19></p> <p wtl-uid=7></p> </div> </body> """ metadata = [ { "wtl_uid": 12, "x": "hi" }, { "wtl_uid": 15, "x": "hello" }, { "wtl_uid": 7, "x": "whatup" }, { "wtl_uid": 19, "x": "shoo bre" }, ] snapshot = PageSnapshot( bs4.BeautifulSoup(source, Config.default().bs_html_parser), {}, metadata) assert snapshot.elements assert len(snapshot.elements) == 4 assert str(snapshot.elements[1].tag) == '<p wtl-uid="15"></p>'
def test_json(): config = Config.default() json = config.to_json() assert len(json) == len(config)
def test_default(): config = Config.default() assert "browser" in config
def test_non_default(): with pytest.raises(ValueError): Config() with pytest.raises(ValueError): Config.default(["timeout='abc'"])