Example #1
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()
Example #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
Example #3
0
def test_search_publications( webdriver, flask_app, dbconn ):
    """Test searching publications."""

    # initialize
    init_tests( webdriver, flask_app, dbconn )

    # test searching publication names/descriptions
    _do_test_searches( ["journal","good"], [] )
    create_publication( {
        "name": "ASL Journal", "description": "A pretty good magazine."
    } )
    _do_test_searches( ["journal","good"], ["ASL Journal"] )

    # edit the publication
    sr = find_search_result( "ASL Journal" )
    edit_publication( sr, {
        "name": "ASL Magazine", "description": "Not a bad magazine."
    } )
    _do_test_searches( ["journal","good"], [] )
    _do_test_searches( ["magazine","bad"], ["ASL Magazine"] )

    # delete the publication
    sr = find_search_result( "ASL Magazine" )
    select_sr_menu_option( sr, "delete" )
    check_ask_dialog( "Delete this publication?", "ok" )
    _do_test_searches( ["journal","good","magazine","bad"], [] )
Example #4
0
def test_search_articles( webdriver, flask_app, dbconn ):
    """Test searching articles."""

    # initialize
    init_tests( webdriver, flask_app, dbconn )

    # test searching article titles/subtitles/snippets
    _do_test_searches( ["low","some","game"], [] )
    create_article( {
         "title": "Hit 'Em High, Or Hit 'Em Low",
         "subtitle": "Some things about light mortars you might like to know",
         "snippet": "Light mortars in ASL can be game winners."
    } )
    _do_test_searches( ["low","some","game"], ["Hit 'Em High, Or Hit 'Em Low"] )

    # edit the article
    sr = find_search_result( "Hit 'Em High, Or Hit 'Em Low" )
    edit_article( sr, {
        "title": "Hit 'Em Hard",
        "subtitle": "Where it hurts!",
        "snippet": "Always the best way to do things."
    } )
    _do_test_searches( ["low","some","game"], [] )
    _do_test_searches( ["hard","hurt","best"], ["Hit 'Em Hard"] )

    # delete the article
    sr = find_search_result( "Hit 'Em Hard" )
    select_sr_menu_option( sr, "delete" )
    check_ask_dialog( "Delete this article?", "ok" )
    _do_test_searches( ["hard","hurt","best"], [] )
    def do_test( publ_name, expected_warning, expected_deletions ):

        # initialize
        load_fixtures( session, "cascading-deletes-1.json" )
        results = do_search( SEARCH_ALL )

        # delete the specified publisher
        sr = find_search_result( publ_name, results )
        select_sr_menu_option( sr, "delete" )
        check_ask_dialog( ( "Delete this publisher?", publ_name, expected_warning ), "ok" )

        # check that deleted associated publications/articles were removed from the UI
        def check_publications():
            check_results(
                "publication", [ "2", "3", "4", "5a", "5b", "6a", "6b", "7a", "7b", "8a", "8b" ],
                expected_deletions
            )
        def check_articles():
            check_results(
                "article", [ "3", "4a", "4b", "6a", "7a", "7b", "8a.1", "8a.2", "8b.1", "8b.2" ],
                expected_deletions
            )
        check_publications()
        check_articles()

        # check that associated publications/articles were removed from the database
        results = do_search( SEARCH_ALL )
        check_publications()
        check_articles()
Example #6
0
    def do_test(pub_name, expected_warning, expected_articles):

        # initialize
        load_fixtures(session, "cascading-deletes-2.json")
        results = do_search(SEARCH_ALL)

        # delete the specified publication
        sr = find_search_result(pub_name, results)
        select_sr_menu_option(sr, "delete")
        check_ask_dialog(
            ("Delete this publication?", pub_name, expected_warning), "ok")

        def check_results():
            results = wait_for(2, lambda: get_results(len(expected_articles)))
            assert set(results) == set(expected_articles)

        def get_results(expected_len):
            # NOTE: The UI will remove anything that has been deleted, so we need to
            # give it a bit of time to finish doing this.
            try:
                results = get_search_result_names()
            except StaleElementReferenceException:
                return None
            results = [r for r in results if r.startswith("article")]
            if len(results) == expected_len:
                return results
            return None

        # check that deleted associated articles were removed from the UI
        check_results()

        # check that associated articles were removed from the database
        results = do_search(SEARCH_ALL_ARTICLES)
        check_results()
Example #7
0
def test_delete_article(webdriver, flask_app, dbconn):
    """Test deleting articles."""

    # initialize
    init_tests(webdriver, flask_app, dbconn, fixtures="articles.json")

    # start to delete an article, but cancel the operation
    article_name = "Smoke Gets In Your Eyes"
    results = do_search(SEARCH_ALL_ARTICLES)
    result_names = get_search_result_names(results)
    sr = find_search_result(article_name, results)
    select_sr_menu_option(sr, "delete")
    check_ask_dialog(("Delete this article?", article_name), "cancel")

    # check that search results are unchanged on-screen
    results2 = get_search_results()
    assert results2 == results

    # check that the search results are unchanged in the database
    results3 = do_search(SEARCH_ALL_ARTICLES)
    assert get_search_result_names(results3) == result_names

    # delete the article
    sr = find_search_result(article_name, results3)
    select_sr_menu_option(sr, "delete")
    set_toast_marker("info")
    check_ask_dialog(("Delete this article?", article_name), "ok")
    wait_for(2, lambda: check_toast("info", "The article was deleted."))

    # check that search result was removed on-screen
    wait_for(2, lambda: article_name not in get_search_result_names())

    # check that the search result was deleted from the database
    results = do_search(SEARCH_ALL_ARTICLES)
    assert article_name not in get_search_result_names(results)
Example #8
0
def test_delete_publication(webdriver, flask_app, dbconn):
    """Test deleting publications."""

    # initialize
    init_tests(webdriver, flask_app, dbconn, fixtures="publications.json")

    # start to delete a publication, but cancel the operation
    article_title = "ASL Journal (2)"
    results = do_search(SEARCH_ALL_PUBLICATIONS)
    result_names = get_search_result_names(results)
    sr = find_search_result(article_title, results)
    select_sr_menu_option(sr, "delete")
    check_ask_dialog(("Delete this publication?", article_title), "cancel")

    # check that search results are unchanged on-screen
    results2 = get_search_results()
    assert results2 == results

    # check that the search results are unchanged in the database
    results3 = do_search(SEARCH_ALL_PUBLICATIONS)
    assert get_search_result_names(results3) == result_names

    # delete the publication
    sr = find_search_result(article_title, results3)
    select_sr_menu_option(sr, "delete")
    set_toast_marker("info")
    check_ask_dialog(("Delete this publication?", article_title), "ok")
    wait_for(2, lambda: check_toast("info", "The publication was deleted."))

    # check that search result was removed on-screen
    wait_for(2, lambda: article_title not in get_search_result_names())

    # check that the search result was deleted from the database
    results = do_search(SEARCH_ALL_PUBLICATIONS)
    assert article_title not in get_search_result_names(results)
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" )
Example #10
0
def test_search_publishers( webdriver, flask_app, dbconn ):
    """Test searching publishers."""

    # initialize
    init_tests( webdriver, flask_app, dbconn )

    # test searching publisher names/descriptions
    _do_test_searches( ["hill","original"], [] )
    create_publisher( {
        "name": "Avalon Hill", "description": "The original ASL vendor."
    } )
    _do_test_searches( ["hill","original"], ["Avalon Hill"] )

    # edit the publisher
    sr = find_search_result( "Avalon Hill" )
    edit_publisher( sr, {
        "name": "Avalon Mountain", "description": "The first ASL vendor."
    } )
    _do_test_searches( ["hill","original"], [] )
    _do_test_searches( ["mountain","first"], ["Avalon Mountain"] )

    # delete the publisher
    sr = find_search_result( "Avalon Mountain" )
    select_sr_menu_option( sr, "delete" )
    check_ask_dialog( "Delete this publisher?", "ok" )
    _do_test_searches( ["hill","original","mountain","first"], [] )
Example #11
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]]
def test_publication_lists( webdriver, flask_app, dbconn ):
    """Test showing publications that belong a publisher."""

    # initialize
    init_tests( webdriver, flask_app, dbconn, fixtures="publishers.json" )

    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

    # check that the publishers have no publications associated with them
    results = do_search( SEARCH_ALL_PUBLISHERS )
    publ_name1, publ_name2 = "Avalon Hill", "Multiman Publishing"
    check_publications( results, { publ_name1: None, publ_name2: None } )

    # create a publication that has no parent publisher
    create_publication( { "name": "no parent" } )
    check_publications( results, { publ_name1: None, publ_name2: None } )

    # create a publication that has a parent publisher
    pub_name = "test publication"
    create_publication( { "name": pub_name, "publisher": publ_name1 } )
    check_publications( results, { publ_name1: pub_name, publ_name2: None } )

    # move the publication to another publisher
    pub_sr = find_search_result( pub_name )
    edit_publication( pub_sr, { "publisher": publ_name2 } )
    check_publications( results, { publ_name1: None, publ_name2: pub_name } )

    # change the publication to have no parent publisher
    edit_publication( pub_sr, { "publisher": "(none)" } )
    check_publications( results, { publ_name1: None, publ_name2: None } )

    # move the publication back to a publisher
    edit_publication( pub_sr, { "publisher": publ_name1 } )
    check_publications( results, { publ_name1: pub_name, publ_name2: None } )

    # delete the publication
    select_sr_menu_option( pub_sr, "delete" )
    check_ask_dialog( ( "Delete this publication?", pub_name ), "ok" )
    check_publications( results, { publ_name1: None, publ_name2: None } )
Example #13
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"] )
Example #14
0
    def check_image(expected):

        # check the image in the article's search result
        def check_sr_image():
            img = find_child("img.image", article_sr)
            if expected:
                expected_url = flask_app.url_for("get_image",
                                                 image_type="article",
                                                 image_id=article_id)
                image_url = img.get_attribute("src").split("?")[0]
                return image_url == expected_url
            else:
                return not img

        wait_for(2, check_sr_image)

        # check the image in the article's config
        select_sr_menu_option(article_sr, "edit")
        dlg = wait_for_elem(2, "#article-form")
        if expected:
            # make sure there is an image
            img = find_child(".row.image img.image", dlg)
            image_url = img.get_attribute("src")
            assert "/images/article/{}".format(article_id) in image_url
            # make sure the "remove image" icon is visible
            btn = find_child(".row.image .remove-image", dlg)
            assert btn.is_displayed()
            # make sure the article's image is correct
            resp = urllib.request.urlopen(image_url).read()
            assert resp == open(expected, "rb").read()
        else:
            # make sure there is no image
            img = find_child(".row.image img.image", dlg)
            assert img.get_attribute("src").endswith("/images/placeholder.png")
            # make sure the "remove image" icon is hidden
            btn = find_child(".row.image .remove-image", dlg)
            assert not btn.is_displayed()
            # make sure the article's image is not available
            url = flask_app.url_for("get_image",
                                    image_type="article",
                                    image_id=article_id)
            try:
                resp = urllib.request.urlopen(url)
                assert False, "Should never get here!"
            except urllib.error.HTTPError as ex:
                assert ex.code == 404
        find_child(".cancel", dlg).click()
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
Example #16
0
def test_images(webdriver, flask_app, dbconn):  #pylint: disable=too-many-statements
    """Test article images."""

    # initialize
    init_tests(webdriver, flask_app, dbconn, max_image_upload_size=2 * 1024)
    article_sr = article_id = None

    def check_image(expected):

        # check the image in the article's search result
        def check_sr_image():
            img = find_child("img.image", article_sr)
            if expected:
                expected_url = flask_app.url_for("get_image",
                                                 image_type="article",
                                                 image_id=article_id)
                image_url = img.get_attribute("src").split("?")[0]
                return image_url == expected_url
            else:
                return not img

        wait_for(2, check_sr_image)

        # check the image in the article's config
        select_sr_menu_option(article_sr, "edit")
        dlg = wait_for_elem(2, "#article-form")
        if expected:
            # make sure there is an image
            img = find_child(".row.image img.image", dlg)
            image_url = img.get_attribute("src")
            assert "/images/article/{}".format(article_id) in image_url
            # make sure the "remove image" icon is visible
            btn = find_child(".row.image .remove-image", dlg)
            assert btn.is_displayed()
            # make sure the article's image is correct
            resp = urllib.request.urlopen(image_url).read()
            assert resp == open(expected, "rb").read()
        else:
            # make sure there is no image
            img = find_child(".row.image img.image", dlg)
            assert img.get_attribute("src").endswith("/images/placeholder.png")
            # make sure the "remove image" icon is hidden
            btn = find_child(".row.image .remove-image", dlg)
            assert not btn.is_displayed()
            # make sure the article's image is not available
            url = flask_app.url_for("get_image",
                                    image_type="article",
                                    image_id=article_id)
            try:
                resp = urllib.request.urlopen(url)
                assert False, "Should never get here!"
            except urllib.error.HTTPError as ex:
                assert ex.code == 404
        find_child(".cancel", dlg).click()

    # create an article with no image
    create_article({"title": "Test Article"})
    results = get_search_results()
    assert len(results) == 1
    article_sr = results[0]
    article_id = article_sr.get_attribute("testing--article_id")
    check_image(None)

    # add an image to the article
    fname = os.path.join(os.path.split(__file__)[0], "fixtures/images/1.gif")
    edit_article(article_sr, {"image": fname})
    check_image(fname)

    # change the article's image
    fname = os.path.join(os.path.split(__file__)[0], "fixtures/images/2.gif")
    edit_article(article_sr, {"image": fname})
    check_image(fname)

    # remove the article's image
    edit_article(article_sr, {"image": None})
    check_image(None)

    # try to upload an image that's too large
    select_sr_menu_option(article_sr, "edit")
    dlg = wait_for_elem(2, "#article-form")
    data = base64.b64encode(5000 * b" ")
    data = "{}|{}".format("too-big.png", data.decode("ascii"))
    send_upload_data(data,
                     lambda: find_child(".row.image img.image", dlg).click())
    check_error_msg("The file must be no more than 2 KB in size.")
Example #17
0
def test_article_lists(webdriver, flask_app, dbconn):
    """Test showing articles that belong to a publication."""

    # initialize
    init_tests(webdriver, flask_app, dbconn, fixtures="publications.json")

    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()

    # check that the publications have no articles associated with them
    results = do_search(SEARCH_ALL_PUBLICATIONS)
    pub_name1, pub_name2 = "ASL Journal (1)", "MMP News"
    check_articles(results, {pub_name1: None, pub_name2: None})

    # create an article that has no parent publication
    create_article({"title": "no parent"})
    check_articles(results, {pub_name1: None, pub_name2: None})

    # create an article that has a parent publication
    article_title = "test article"
    create_article({"title": article_title, "publication": pub_name1})
    check_articles(results, {pub_name1: article_title, pub_name2: None})

    # move the article to another publication
    article_sr = find_search_result(article_title)
    edit_article(article_sr, {"publication": pub_name2})
    check_articles(None, {pub_name1: None, pub_name2: article_title})

    # change the article to have no parent publication
    edit_article(article_sr, {"publication": "(none)"})
    check_articles(None, {pub_name1: None, pub_name2: None})

    # move the article back into a publication
    edit_article(article_sr, {"publication": pub_name1})
    check_articles(None, {pub_name1: article_title, pub_name2: None})

    # delete the article
    select_sr_menu_option(article_sr, "delete")
    check_ask_dialog(("Delete this article?", article_title), "ok")
    check_articles(None, {pub_name1: None, pub_name2: None})
def test_db_report(webdriver, flask_app, dbconn):
    """Test the database report."""

    # initialize
    init_tests(webdriver, flask_app, dbconn, fixtures="db-report.json")

    # check the initial report
    row_counts, links, dupe_images, image_sizes = _get_db_report()
    assert row_counts == {
        "publishers": 2,
        "publications": 3,
        "articles": 5,
        "authors": 3,
        "scenarios": 2
    }
    assert links == {
        "publishers": [2, []],
        "publications": [2, []],
        "articles": [2, []],
    }
    assert dupe_images == []
    assert image_sizes == {}

    # add some images
    do_search(SEARCH_ALL)
    publ_sr = find_search_result("Avalon Hill", wait=2)
    fname = os.path.join(os.path.split(__file__)[0], "fixtures/images/1.gif")
    edit_publisher(publ_sr, {"image": fname})
    results = get_search_results()
    pub_sr = find_search_result("ASL Journal (1)", results)
    fname = os.path.join(os.path.split(__file__)[0], "fixtures/images/2.gif")
    edit_publication(pub_sr, {"image": fname})
    article_sr = find_search_result("ASLJ article 1", results)
    fname = os.path.join(os.path.split(__file__)[0], "fixtures/images/3.gif")
    edit_article(article_sr, {"image": fname})
    article_sr = find_search_result("ASLJ article 2", results)
    fname = os.path.join(os.path.split(__file__)[0], "fixtures/images/3.gif")
    edit_article(article_sr, {"image": fname})

    # check the updated report
    row_counts, _, dupe_images, image_sizes = _get_db_report()
    assert row_counts == {
        "publishers": 2,
        "publisher_images": 1,
        "publications": 3,
        "publication_images": 1,
        "articles": 5,
        "article_images": 2,
        "authors": 3,
        "scenarios": 2
    }
    assert dupe_images == [[
        "f0457ea742376e76ff276ce62c7a8540",
        "/images/article/100",
        ("ASLJ article 1", "/article/100"),
        ("ASLJ article 2", "/article/101"),
    ]]
    assert image_sizes == {
        "publishers": [
            ("Avalon Hill", "/publisher/1", "/images/publisher/1"),
        ],
        "publications": [
            ("ASL Journal (1)", "/publication/10", "/images/publication/10"),
        ],
        "articles": [
            ("ASLJ article 1", "/article/100", "/images/article/100"),
            ("ASLJ article 2", "/article/101", "/images/article/101"),
        ]
    }

    # delete all the publishers (and associated objects), then check the updated report
    do_search(SEARCH_ALL)
    publ_sr = find_search_result("Avalon Hill", wait=2)
    select_sr_menu_option(publ_sr, "delete")
    check_ask_dialog("Delete this publisher?", "ok")
    results = get_search_results()
    publ_sr = find_search_result("Multiman Publishing", results)
    select_sr_menu_option(publ_sr, "delete")
    check_ask_dialog("Delete this publisher?", "ok")
    row_counts, links, dupe_images, image_sizes = _get_db_report()
    assert row_counts == {
        "publishers": 0,
        "publications": 0,
        "articles": 0,
        "authors": 3,
        "scenarios": 2
    }
    assert links == {
        "publishers": [0, []],
        "publications": [0, []],
        "articles": [0, []],
    }
    assert dupe_images == []
    assert image_sizes == {}
Example #19
0
def test_publisher_articles(webdriver, flask_app, dbconn):  #pylint: disable=too-many-statements
    """Test articles that are associated with a publisher (not publication)."""

    # initialize
    init_tests(webdriver,
               flask_app,
               dbconn,
               fixtures="publisher-articles.json")

    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."

    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."

    # create an article associated with LFT
    create_article({"title": "test article", "publisher": "Le Franc Tireur"})
    results = wait_for(2, get_search_results)
    assert len(results) == 1
    sr = results[0]
    check_parent_in_sr(sr, None, "Le Franc Tireur")

    # open the article's dialog
    select_sr_menu_option(sr, "edit")
    dlg = wait_for_elem(2, "#article-form")
    check_parent_in_dlg(dlg, None, "Le Franc Tireur")

    # change the article to be associated with an MMP publication
    find_child(".row.publisher label.parent-mode").click()
    select = wait_for_elem(2, ".row.publication .react-select")
    ReactSelect(select).select_by_name("MMP News")
    find_child("button.ok", dlg).click()
    results = wait_for(2, get_search_results)
    assert len(results) == 1
    sr = results[0]
    check_parent_in_sr(sr, "MMP News", None)

    # open the article's dialog
    select_sr_menu_option(sr, "edit")
    dlg = wait_for_elem(2, "#article-form")
    check_parent_in_dlg(dlg, "MMP News", None)

    # change the article to be associated with MMP (publisher)
    find_child(".row.publication label.parent-mode").click()
    select = wait_for_elem(2, ".row.publisher .react-select")
    ReactSelect(select).select_by_name("Multiman Publishing")
    find_child("button.ok", dlg).click()
    results = wait_for(2, get_search_results)
    assert len(results) == 1
    sr = results[0]
    check_parent_in_sr(sr, None, "Multiman Publishing")

    # show the MMP publisher
    results = do_search("multiman")
    assert len(results) == 1
    sr = results[0]
    collapsibles = find_children(".collapsible", sr)
    assert len(collapsibles) == 2
    items = find_children("li a", collapsibles[1])
    assert len(items) == 1
    item = items[0]
    assert item.text == "test article"
    assert re.search(r"^http://.+?/article/\d+", item.get_attribute("href"))

    # delete the MMP publisher
    # NOTE: There are 2 MMP articles, the one that is in the "MMP News" publication,
    # and the test article we created above that is associated with the publisher.
    select_sr_menu_option(sr, "delete")
    check_ask_dialog(
        ("Delete this publisher?", "2 articles will also be deleted"), "ok")
    query = dbconn.execute("SELECT count(*) FROM article")
    assert query.scalar() == 0