Ejemplo n.º 1
0
    def check_article_order(expected):

        # check the article order in the database
        articles = defaultdict(list)
        query = dbconn.execute("SELECT pub_name, article_title, article_seqno"
                               " FROM article LEFT JOIN publication"
                               " ON article.pub_id = publication.pub_id"
                               " ORDER BY article.pub_id, article_seqno")
        for row in query:
            articles[row[0]].append((row[1], row[2]))
        assert articles == expected

        # check the article order in the UI
        results = do_search(SEARCH_ALL)
        for pub_name in expected:
            if not pub_name:
                continue
            sr = find_search_result(pub_name, results)
            select_sr_menu_option(sr, "edit")
            dlg = wait_for_elem(2, "#publication-form")
            articles = [
                a.text for a in find_children(".articles li.draggable", dlg)
            ]
            find_child(".cancel", dlg).click()
            assert articles == [a[0] for a in expected[pub_name]]
Ejemplo n.º 2
0
def edit_article(sr,
                 vals,
                 toast_type="info",
                 expected_error=None,
                 expected_constraints=None):  #pylint: disable=too-many-branches
    """Edit a article's details."""

    # initialize
    if sr:
        select_sr_menu_option(sr, "edit")
    else:
        pass  # nb: we assume that the dialog is already on-screen
    dlg = wait_for_elem(2, "#article-form")

    # update the specified article's details
    _update_values(dlg, vals)
    set_toast_marker(toast_type)
    find_child("button.ok", dlg).click()

    # check what happened
    if expected_error:
        # we were expecting an error, confirm the error message
        check_error_msg(expected_error)
        return dlg  # nb: the dialog is left on-screen
    elif expected_constraints:
        # we were expecting constraint warnings, confirm them
        check_constraint_warnings("Do you want to update this article?",
                                  expected_constraints, "cancel")
        return dlg  # nb: the dialog is left on-screen
    else:
        # we were expecting the update to work, confirm this
        expected = "updated OK" if sr else "created OK"
        wait_for(2, lambda: check_toast(toast_type, expected, contains=True))
        wait_for_not_elem(2, "#article-form")
        return None
Ejemplo n.º 3
0
def _update_values(dlg, vals):
    """Update a publication's values in the form."""
    for key, val in vals.items():
        if key == "image":
            if val:
                change_image(dlg, val)
            else:
                remove_image(dlg)
        elif key == "name":
            elem = find_child(".row.name .react-select input", dlg)
            set_elem_text(elem, val)
            elem.send_keys(Keys.RETURN)
        elif key == "publisher":
            select = ReactSelect(
                find_child(".row.publisher .react-select", dlg))
            select.select_by_name(val)
        elif key == "tags":
            select = ReactSelect(find_child(".row.tags .react-select", dlg))
            select.update_multiselect_values(*val)
        else:
            if key == "edition":
                sel = "input.edition"
            elif key == "description":
                sel = ".row.description textarea"
            else:
                sel = ".row.{} input".format(key)
            set_elem_text(find_child(sel, dlg), val)
Ejemplo n.º 4
0
 def remove_multiselect_value(self, val):
     """Remove a multi-select value."""
     for elem in find_children(".react-select__multi-value", self.select):
         if elem.text == val:
             find_child(".react-select__multi-value__remove", elem).click()
             return
     assert False, "Can't find multi-select value: {}".format(val)
Ejemplo n.º 5
0
def edit_publisher( sr, vals, toast_type="info", expected_error=None ):
    """Edit a publisher's details."""

    # initialize
    if sr:
        select_sr_menu_option( sr, "edit" )
    else:
        pass # nb: we assume that the dialog is already on-screen
    dlg = wait_for_elem( 2, "#publisher-form" )

    # update the specified publisher's details
    _update_values( dlg, vals )
    set_toast_marker( toast_type )
    find_child( "button.ok", dlg ).click()

    # check what happened
    if expected_error:
        # we were expecting an error, confirm the error message
        check_error_msg( expected_error )
    else:
        # we were expecting the update to work, confirm this
        expected = "updated OK" if sr else "created OK"
        wait_for( 2,
            lambda: check_toast( toast_type, expected, contains=True )
        )
        wait_for_not_elem( 2, "#publisher-form" )
Ejemplo n.º 6
0
def create_article(vals,
                   toast_type="info",
                   expected_error=None,
                   expected_constraints=None,
                   dlg=None):
    """Create a new article."""

    # initialize
    set_toast_marker(toast_type)

    # create the new article
    if not dlg:
        select_main_menu_option("new-article")
        dlg = wait_for_elem(2, "#article-form")
    _update_values(dlg, vals)
    find_child("button.ok", dlg).click()

    # check what happened
    if expected_error:
        # we were expecting an error, confirm the error message
        check_error_msg(expected_error)
        return dlg  # nb: the dialog is left on-screen
    elif expected_constraints:
        # we were expecting constraint warnings, confirm them
        check_constraint_warnings("Do you want to create this article?",
                                  expected_constraints, "cancel")
        return dlg  # nb: the dialog is left on-screen
    else:
        # we were expecting the create to work, confirm this
        wait_for(2,
                 lambda: check_toast(toast_type, "created OK", contains=True))
        wait_for_not_elem(2, "#article-form")
        return None
Ejemplo n.º 7
0
 def check_publication_highlights( query, expected, name, description, tags ):
     results = _do_test_search( query, [expected] )
     assert len(results) == 1
     sr = results[0]
     assert find_highlighted( find_child( ".name", sr ) ) == name
     assert find_highlighted( find_child( ".description", sr ) ) == description
     assert find_highlighted( find_children( ".tag", sr ) ) == tags
Ejemplo n.º 8
0
def create_publisher( vals, toast_type="info", expected_error=None, dlg=None ):
    """Create a new publisher."""

    # initialize
    set_toast_marker( toast_type )

    # create the new publisher
    if not dlg:
        select_main_menu_option( "new-publisher" )
        dlg = wait_for_elem( 2, "#publisher-form" )
    _update_values( dlg, vals )
    find_child( "button.ok", dlg ).click()

    # check what happened
    if expected_error:
        # we were expecting an error, confirm the error message
        check_error_msg( expected_error )
        return dlg # nb: the dialog is left on-screen
    else:
        # we were expecting the create to work, confirm this
        wait_for( 2,
            lambda: check_toast( toast_type, "created OK", contains=True )
        )
        wait_for_not_elem( 2, "#publisher-form" )
        return None
Ejemplo n.º 9
0
def test_clean_html( webdriver, flask_app, dbconn ):
    """Test cleaning HTML content."""

    # initialize
    init_tests( webdriver, flask_app, dbconn )
    replace = [
        "[\u00ab\u00bb\u201c\u201d\u201e\u201f foo\u2014bar \u2018\u2019\u201a\u201b\u2039\u203a]",
        "[\"\"\"\"\"\" foo - bar '''''']"
    ]

    # create a publisher with HTML content
    create_publisher( {
        "name": "name: <span onclick='boo!'> <b>bold</b> <xxx>xxx</xxx> <i>italic</i> {}".format( replace[0] ),
        "description": "bad stuff here: <script>HCF</script> {}".format( replace[0] )
    }, toast_type="warning" )

    # check that the HTML was cleaned
    sr = check_search_result( None, _check_sr, [
        "name: bold xxx italic {}".format( replace[1] ),
        "bad stuff here: {}".format( replace[1] ),
        None
    ] )
    assert find_child( ".name", sr ).get_attribute( "innerHTML" ) \
        == "name: <span> <b>bold</b> xxx <i>italic</i> {}</span>".format( replace[1] )
    assert check_toast( "warning", "Some values had HTML cleaned up.", contains=True )

    # update the publisher with new HTML content
    edit_publisher( sr, {
        "name": "<div onclick='...'>updated</div>"
    }, toast_type="warning" )
    results = get_search_results()
    assert len(results) == 1
    wait_for( 2, lambda: find_child( ".name", sr ).text == "updated" )
    assert check_toast( "warning", "Some values had HTML cleaned up.", contains=True )
Ejemplo n.º 10
0
    def check_result(sr, expected_parent):  #pylint: disable=too-many-return-statements

        # check that the parent publication was updated in the UI
        elem = find_child(".header .publication", sr)
        if expected_parent:
            if elem.text != "{}".format(expected_parent[1]):
                return None
        else:
            if elem is not None:
                return None

        # check that the parent publication was updated in the database
        article_id = sr.get_attribute("testing--article_id")
        url = flask_app.url_for("get_article", article_id=article_id)
        article = json.load(urllib.request.urlopen(url))
        if expected_parent:
            if article["pub_id"] != expected_parent[0]:
                return None
        else:
            if article["pub_id"] is not None:
                return None

        # check that the parent publication was updated in the UI
        results = do_search('"My Article"')
        assert len(results) == 1
        sr = results[0]
        elem = find_child(".header .publication", sr)
        if expected_parent:
            if elem.text != "{}".format(expected_parent[1]):
                return None
        else:
            if elem is not None:
                return None

        return sr
Ejemplo n.º 11
0
 def select_by_name(self, val):
     """Select an option by name."""
     find_child(".react-select__dropdown-indicator", self.select).click()
     options = [
         e for e in find_children(".react-select__option", self.select)
         if e.text == val
     ]
     assert len(options) == 1
     options[0].click()
Ejemplo n.º 12
0
def _check_previewable_images( sr ):
    """Check that previewable images are working correctly."""
    images = list( find_children( "a.preview img", sr ) )
    assert len(images) == 2
    for img in images:
        assert find_child( ".jquery-image-zoom" ) is None
        img.click()
        preview = wait_for( 2, lambda: find_child( ".jquery-image-zoom" ) )
        call_with_retry( preview.click, [ElementClickInterceptedException] )
        wait_for( 2, lambda: find_child( ".jquery-image-zoom" ) is None )
Ejemplo n.º 13
0
 def check_article_highlights( query, expected, title, subtitle, snippet, authors, scenarios, tags ):
     results = _do_test_search( query, [expected] )
     assert len(results) == 1
     sr = results[0]
     assert find_highlighted( find_child( ".title", sr ) ) == title
     assert find_highlighted( find_child( ".subtitle", sr ) ) == subtitle
     assert find_highlighted( find_child( ".snippet", sr ) ) == snippet
     assert find_highlighted( find_children( ".author", sr ) ) == authors
     assert find_highlighted( find_children( ".scenario", sr ) ) == scenarios
     assert find_highlighted( find_children( ".tag", sr ) ) == tags
Ejemplo n.º 14
0
 def check_parent_in_dlg(dlg, pub, publ):
     """Check the article's parent publication/publication in the edit dialog."""
     if pub:
         select = find_child(".row.publication .react-select", dlg)
         assert select.is_displayed()
         assert select.text == pub
     elif publ:
         select = find_child(".row.publisher .react-select", dlg)
         assert select.is_displayed()
         assert select.text == publ
     else:
         assert False, "At least one publication/publisher must be specified."
Ejemplo n.º 15
0
 def check_publications( results, expected ):
     for publ_name,pub_name in expected.items():
         publ_sr = find_search_result( publ_name, results )
         pubs = find_child( ".collapsible", publ_sr )
         if pub_name:
             # check that the publication appears in the publisher's search result
             assert find_child( ".caption", pubs ).text == "Publications:"
             pubs = find_children( "li", pubs )
             assert len(pubs) == 1
             assert pubs[0].text == pub_name
         else:
             # check that the publisher has no associated publications
             assert pubs is None
Ejemplo n.º 16
0
 def click_on_publication( sr, expected_pub, expected_sr ):
     classes = sr.get_attribute( "class" ).split()
     if "article" in classes:
         elem = find_child( ".header .publication", sr )
     elif "publisher" in classes:
         elems = find_children( ".content .collapsible li", sr )
         elem = elems[0] # nb: we just use the first one
     else:
         assert "publication" in classes
         elem = find_child( ".header .name", sr )
     assert elem.text == expected_pub
     elem.click()
     wait_for( 2, lambda: get_search_result_names() == expected_sr )
Ejemplo n.º 17
0
def _check_tags( flask_app, expected ): #pylint: disable=too-many-locals
    """Check the tags in the UI and database."""

    # get the complete list of expected tags
    expected_available = set()
    for tags in expected.values():
        expected_available.update( tags )

    def check_tags( sr ):
        name = get_search_result_names( [sr] )[ 0 ]
        tags = [ t.text for t in find_children( ".tag", sr ) ]
        if tags == expected[name]:
            return name
        return None

    # check the tags in the UI
    results = get_search_results()
    assert set( get_search_result_names( results ) ) == set( expected.keys() )
    for sr in results:

        # check the tags in the search result
        name = wait_for( 2, lambda sr=sr: check_tags( sr ) )

        # check the tags in the publication/article
        select_sr_menu_option( sr, "edit" )
        dlg = wait_for_elem( 2, ".modal-form" )
        select = ReactSelect( find_child( ".row.tags .react-select", dlg ) )
        assert select.get_multiselect_values() == expected[ name ]

        # check that the list of available tags is correct
        # NOTE: We don't bother checking the tag order here.
        assert set( select.get_multiselect_choices() ) == expected_available.difference( expected[name] )

        # close the dialog
        find_child( "button.cancel", dlg ).click()

    def fixup_tags( tags ):
        return [] if tags is None else tags

    # check the tags in the database
    for sr in results:
        if sr.text.startswith( "publication" ):
            pub_id = sr.get_attribute( "testing--pub_id" )
            url = flask_app.url_for( "get_publication", pub_id=pub_id )
            pub = json.load( urllib.request.urlopen( url ) )
            assert expected[ pub["pub_name"] ] == fixup_tags( pub["pub_tags"] )
        elif sr.text.startswith( "article" ):
            article_id = sr.get_attribute( "testing--article_id" )
            url = flask_app.url_for( "get_article", article_id=article_id )
            article = json.load( urllib.request.urlopen( url ) )
            assert expected[ article["article_title"] ] == fixup_tags( article["article_tags"] )
Ejemplo n.º 18
0
 def check_articles(results, expected):
     for pub_name, article_title in expected.items():
         pub_sr = find_search_result(pub_name, results)
         articles = find_child(".collapsible", pub_sr)
         if article_title:
             # check that the article appears in the publication's search result
             assert find_child(".caption", articles).text == "Articles:"
             articles = find_children("li", articles)
             assert len(articles) == 1
             assert articles[0].text == article_title
             # check that the "edit publication" dialog is correct
             select_sr_menu_option(pub_sr, "edit")
             dlg = find_child(".MuiDialog-root")
             articles = find_children(".articles li", dlg)
             assert len(articles) == 1
             assert articles[0].text == article_title
             find_child("button.cancel", dlg).click()
         else:
             # check that the publication has no associated articles
             assert articles is None
             # check that the "edit publication" dialog is correct
             select_sr_menu_option(pub_sr, "edit")
             dlg = find_child(".MuiDialog-root")
             articles = find_children(".articles", dlg)
             assert len(articles) == 0
             find_child("button.cancel", dlg).click()
Ejemplo n.º 19
0
    def do_test( msg_type ):

        # check that the startup message was shown in the UI correctly
        set_toast_marker( msg_type )
        assert startup_msgs[ msg_type ] == []
        asl_articles.startup.log_startup_msg( msg_type, "TEST: {}", msg_type )
        webdriver.refresh()
        expected = startup_msgs[ msg_type ][0]
        wait_for( 2, lambda: check_toast( msg_type, expected ) )
        startup_msgs[ msg_type ] = []

        # check if the webapp started up or not
        if msg_type == "error":
            assert not find_child( "#search-form" )
        else:
            assert find_child( "#search-form" )
Ejemplo n.º 20
0
 def check_parent_in_sr(sr, pub, publ):
     """Check the article's parent publication/publisher in a search result."""
     if pub:
         elem = wait_for(2, lambda: find_child(".header a.publication", sr))
         assert elem.is_displayed()
         assert elem.text == pub
         assert re.search(r"^http://.+?/publication/\d+",
                          elem.get_attribute("href"))
     elif publ:
         elem = wait_for(2, lambda: find_child(".header a.publisher", sr))
         assert elem.is_displayed()
         assert elem.text == publ
         assert re.search(r"^http://.+?/publisher/\d+",
                          elem.get_attribute("href"))
     else:
         assert False, "At least one publication/publisher must be specified."
Ejemplo n.º 21
0
 def click_on_article( sr, expected_pub, expected_sr ):
     elems = find_children( ".content .collapsible li", sr )
     elem = elems[0] # nb: we just use the first one
     assert elem.text == expected_pub
     elem.click()
     wait_for( 2, lambda: get_search_result_names() == expected_sr )
     assert find_child( "#search-form input.query" ).get_attribute( "value" ) == ""
Ejemplo n.º 22
0
 def do_check():
     elem = find_child(".article_date", article_sr)
     article_id = article_sr.get_attribute("testing--article_id")
     row = get_article_row(dbconn, article_id, ["article_date"])
     if has_date:
         return elem.text == article_date and row[0] == article_date
     else:
         return not elem and not row[0]
Ejemplo n.º 23
0
 def check_sr_image():
     img = find_child( "img.image", publ_sr )
     if expected:
         expected_image_url = flask_app.url_for( "get_image", image_type="publisher", image_id=publ_id )
         image_url = img.get_attribute( "src" ).split( "?" )[0]
         return image_url == expected_image_url
     else:
         return not img
Ejemplo n.º 24
0
def _update_values(dlg, vals):
    """Update an article's values in the form."""
    for key, val in vals.items():
        if key == "image":
            if val:
                change_image(dlg, val)
            else:
                remove_image(dlg)
        elif key in ("publication", "publisher"):
            row = find_child(".row.{}".format(key), dlg)
            select = ReactSelect(find_child(".react-select", row))
            if not select.select.is_displayed():
                key2 = "publisher" if key == "publication" else "publication"
                row2 = find_child(".row.{}".format(key2), dlg)
                find_child("label.parent-mode", row2).click()
                wait_for(2, select.select.is_displayed)
            select.select_by_name(val)
        elif key in ["authors", "scenarios", "tags"]:
            select = ReactSelect(
                find_child(".row.{} .react-select".format(key), dlg))
            select.update_multiselect_values(*val)
        else:
            if key == "snippet":
                sel = ".row.snippet textarea"
            elif key == "pageno":
                sel = "input.pageno"
            else:
                sel = ".row.{} input".format(key)
            set_elem_text(find_child(sel, dlg), val)
Ejemplo n.º 25
0
 def do_check_image(sr, expected):
     img = find_child("img.image", sr)
     if img:
         assert expected
         image_url = img.get_attribute("src")
         resp = urllib.request.urlopen(image_url).read()
         assert resp == image_data[expected]
     else:
         assert not expected
Ejemplo n.º 26
0
 def get_multiselect_choices(self):
     """Get the available multi-select choices."""
     btn = find_child(".react-select__dropdown-indicator", self.select)
     btn.click()  # show the dropdown
     choices = [
         e.text for e in find_children(".react-select__option", self.select)
     ]
     btn.click()  # close the dropdown
     return choices
Ejemplo n.º 27
0
def test_clean_html(webdriver, flask_app, dbconn):
    """Test cleaning HTML content."""

    # initialize
    init_tests(webdriver, flask_app, dbconn)
    replace = [
        "[\u00ab\u00bb\u201c\u201d\u201e\u201f foo\u2014bar \u2018\u2019\u201a\u201b\u2039\u203a]",
        "[\"\"\"\"\"\" foo - bar '''''']"
    ]

    # create a article with HTML content
    create_article(
        {
            "title":
            "title: <span onclick='boo!'> <b>bold</b> <xxx>xxx</xxx> <i>italic</i> {}"
            .format(replace[0]),
            "subtitle":
            "<i>italicized subtitle</i> {}".format(replace[0]),
            "snippet":
            "bad stuff here: <script>HCF</script> {}".format(replace[0])
        },
        toast_type="warning")

    # check that the HTML was cleaned
    sr = check_search_result(None, _check_sr, [
        "title: bold xxx italic {}".format(
            replace[1]), "italicized subtitle {}".format(replace[1]),
        "bad stuff here: {}".format(replace[1]), "", [], [], None
    ])
    assert find_child( ".title", sr ).get_attribute( "innerHTML" ) \
        == "title: <span> <b>bold</b> xxx <i>italic</i> {}</span>".format( replace[1] )
    assert find_child( ".subtitle", sr ).get_attribute( "innerHTML" ) \
        == "<i>italicized subtitle</i> {}".format( replace[1] )
    assert check_toast("warning",
                       "Some values had HTML cleaned up.",
                       contains=True)

    # update the article with new HTML content
    edit_article(sr, {"title": "<div onclick='...'>updated</div>"},
                 toast_type="warning")
    wait_for(2, lambda: get_search_result_names() == ["updated"])
    assert check_toast("warning",
                       "Some values had HTML cleaned up.",
                       contains=True)
Ejemplo n.º 28
0
def _check_sr( sr, expected ):
    """Check a search result."""

    # check the name and description
    if find_child( ".name", sr ).text != expected[0]:
        return False
    if find_child( ".description", sr ).text != expected[1]:
        return False

    # check the publisher's link
    elem = find_child( "a.open-link", sr )
    if expected[2]:
        assert elem
        if elem.get_attribute( "href" ) != expected[2]:
            return False
    else:
        assert elem is None

    return True
Ejemplo n.º 29
0
def _check_scenarios(flask_app, all_scenarios, expected):
    """Check the scenarios of the test articles."""

    # update the complete list of scenarios
    # NOTE: Unlike tags, scenarios remain in the database even if no-one is referencing them,
    # so we need to track them over the life of the entire series of tests.
    for scenarios in expected:
        all_scenarios.update(scenarios)

    def check_scenarios(sr_name, expected):
        sr = find_search_result(sr_name)
        sr_scenarios = [s.text for s in find_children(".scenario", sr)]
        if sr_scenarios == expected:
            return sr
        return None

    # check the scenarios in the UI
    for article_no, expected_scenarios in enumerate(expected):

        # check the scenarios in the article's search result
        sr_name = "article {}".format(1 + article_no)
        sr = wait_for(
            2, lambda n=sr_name, e=expected_scenarios: check_scenarios(n, e))

        # check the scenarios in the article's config
        select_sr_menu_option(sr, "edit")
        dlg = wait_for_elem(2, "#article-form")
        select = ReactSelect(find_child(".row.scenarios .react-select", dlg))
        assert select.get_multiselect_values() == expected_scenarios

        # check that the list of available scenarios is correct
        assert select.get_multiselect_choices() == \
            sorted( all_scenarios.difference( expected_scenarios ), key=lambda s: s.lower() )

        # close the dialog
        find_child("button.cancel", dlg).click()

    # check the scenarios in the database
    url = flask_app.url_for("get_scenarios")
    scenarios = json.load(urllib.request.urlopen(url))
    assert set(_make_scenario_display_name(a)
               for a in scenarios.values()) == all_scenarios
Ejemplo n.º 30
0
def _update_values( dlg, vals ):
    """Update a publishers's values in the form."""
    for key,val in vals.items():
        if key == "image":
            if val:
                change_image( dlg, val )
            else:
                remove_image( dlg )
        else:
            sel = ".row.{} {}".format( key , "textarea" if key == "description" else "input" )
            set_elem_text( find_child( sel, dlg ), val )