From e39e4f9ecb1998d379330b1bc08a9818e9202323 Mon Sep 17 00:00:00 2001
From: Lars-Dominik Braun <lars@6xq.net>
Date: Sun, 2 Dec 2018 11:36:16 +0100
Subject: behavior: Improve click testing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Some pages require scrolling, so we need a SinglePageController. Also
mark network-dependent tests with xfail, so they won’t affect the
overall test result unless you know what you’re doing (--runxfail).
---
 crocoite/data/click.yaml  | 24 ++++++++++++++++-----
 crocoite/test_behavior.py | 54 ++++++++++++++++++++++++++++++++---------------
 2 files changed, 56 insertions(+), 22 deletions(-)

(limited to 'crocoite')

diff --git a/crocoite/data/click.yaml b/crocoite/data/click.yaml
index d9557eb..60db0c2 100644
--- a/crocoite/data/click.yaml
+++ b/crocoite/data/click.yaml
@@ -1,19 +1,24 @@
-# configuration for behavior.py:Click
+# Configuration for behavior.py:Click
+# Example URLs are random. Believe me.
 match: ^www\.facebook\.com$
 selector:
   - description: show more comments
     selector: a.UFIPagerLink[role=button]
+    urls: ["https://www.facebook.com/tagesschau"]
   - description: show nested comments
     selector: a.UFICommentLink[role=button]
   - description: initially show comments below a single post/video, i.e. /user/post/123
     selector: form.commentable_item a[data-comment-prelude-ref=action_link_bling][rel=ignore]
+    urls: ["https://www.facebook.com/tagesschau/posts/10157061068659407"]
   - description: close the “register now” nag screen. for better screen shots
     selector: a#expanding_cta_close_button[role=button]
+    urls: ["https://www.facebook.com/tagesschau"]
 ---
 match: ^twitter\.com$
 selector:
   - description: expand threads
     selector: a.ThreadedConversation-moreRepliesLink
+    urls: ["https://twitter.com/realDonaldTrump/status/1068826073775964160"]
   - description: show hidden profiles
     selector: button.ProfileWarningTimeline-button
   - description: show hidden/sensitive media
@@ -30,6 +35,8 @@ selector:
   - description: show more comments, reddit’s javascript ignores events if too frequent
     selector: span.morecomments a
     throttle: 500
+    # disabled: No idea why it is not working. The selector is fine.
+    #urls: ["https://www.reddit.com/r/funny/comments/a21rxz/well_this_was_a_highlight_of_my_day/"]
 ---
 match: ^www\.instagram\.com$
 selector:
@@ -42,26 +49,33 @@ match: ^www\.youtube\.com$
 selector:
   - description: expand comment thread
     selector: ytd-comment-thread-renderer div.more-button
+    urls: ["https://www.youtube.com/watch?v=udtFqQuBFSc"]
 ---
 match: ^www\.patreon\.com$
 selector:
   - description: load more content
-    selector: div[display=flex] div[display=block] button[color=gray][type=button]
-    multi: True
+    # I’ve been trying to avoid these generated css class selectors *so* hard,
+    # but it’s just not possible on this one.
+    selector: div.sc-bZQynM.fSJOpK button
+    urls: ["https://www.patreon.com/nkjemisin"]
   - description: load more comments
-    selector: div.stackable[display=block] > div  > div  > a[color=dark][target=_self]
+    selector: div[display=flex] div[display=block] a[color="dark"][role="button"][tabindex="0"]
+    urls: ["https://www.patreon.com/posts/what-im-on-22124040"]
   - description: load more replies
     selector: div > a[scale="0"][color=blue][size="1"]
 ---
 match: ^(www\.)?gab\.ai$
 selector:
-  - description: post comments
+  - description: more replies
     selector: post-detail post-comment .post-comment__replies__count a
+    urls: ["https://gab.ai/gab/posts/40014689"]
   - description: more comments
     selector: post-detail .post-comment-list__loading a
+    urls: ["https://gab.ai/gab/posts/41804462"]
   - description: more posts
     selector: post-list a.post-list__load-more
     multi: True
+    urls: ["https://gab.ai/gab"]
 ---
 match: ^(www\.)?github\.com$
 selector:
diff --git a/crocoite/test_behavior.py b/crocoite/test_behavior.py
index 03e151c..280b35b 100644
--- a/crocoite/test_behavior.py
+++ b/crocoite/test_behavior.py
@@ -20,12 +20,14 @@
 
 import asyncio, os, yaml, re
 from urllib.parse import urlparse
+from functools import partial
 import pytest
 
 import pkg_resources
-from .browser import Item, SiteLoader, VarChangeEvent
-from .logger import Logger, Consumer
+from .logger import Logger
 from .devtools import Process
+from .behavior import Scroll, Behavior
+from .controller import SinglePageController
 
 with pkg_resources.resource_stream (__name__, os.path.join ('data', 'click.yaml')) as fd:
     sites = list (yaml.load_all (fd))
@@ -35,27 +37,28 @@ for o in sites:
         for u in s.get ('urls', []):
             clickParam.append ((u, s['selector']))
 
-@pytest.mark.parametrize("url,selector", clickParam)
-@pytest.mark.asyncio
-async def test_click_selectors (url, selector):
+class ClickTester (Behavior):
     """
-    Make sure the CSS selector exists on an example url
+    Test adapter checking a given selector exists after loading the page
     """
-    logger = Logger ()
-    async with Process () as browser, SiteLoader (browser, url, logger) as l:
-        tab = l.tab
-        await l.start ()
-        # XXX: not sure why this is needed, must be a bug.
-        await asyncio.sleep (0.5)
-        if not l.idle.get ():
-            await l.idle.wait ()
+
+    __slots__ = ('selector', )
+
+    name = 'testclick'
+
+    def __init__ (self, loader, logger, selector):
+        super ().__init__ (loader, logger)
+        self.selector = selector
+
+    async def onfinish (self):
+        tab = self.loader.tab
         results = await tab.DOM.getDocument ()
         rootNode = results['root']['nodeId']
-        results = await tab.DOM.querySelectorAll (nodeId=rootNode, selector=selector)
-        assert results['nodeIds'], selector
+        results = await tab.DOM.querySelectorAll (nodeId=rootNode, selector=self.selector)
+        assert results['nodeIds'], self.selector
 
         # XXX: this is not true for every element we click. Github uses <button
-        # type=submit> and <form> without an event listener
+        # type=submit> and <form> without an event listener on the <button>
 #        # verify that an event listener exists
 #        for nid in results['nodeIds']:
 #            obj = (await tab.DOM.resolveNode (nodeId=nid))['object']
@@ -63,6 +66,23 @@ async def test_click_selectors (url, selector):
 #            listeners = (await tab.DOMDebugger.getEventListeners (objectId=obj['objectId']))['listeners']
 #            assert any (map (lambda x: x['type'] == 'click', listeners)), listeners
 
+        return
+        yield
+
+@pytest.mark.parametrize("url,selector", clickParam)
+@pytest.mark.asyncio
+@pytest.mark.xfail(reason='depends on network access')
+async def test_click_selectors (url, selector):
+    """
+    Make sure the CSS selector exists on an example url
+    """
+    logger = Logger ()
+    # Some selectors are loaded dynamically and require scrolling
+    controller = SinglePageController (url=url, logger=logger,
+            service=Process (),
+            behavior=[Scroll, partial(ClickTester, selector=selector)])
+    await controller.run ()
+
 matchParam = []
 for o in sites:
     for s in o['selector']:
-- 
cgit v1.2.3