def check_results(expected_url, expected_title, expected_sr): wait_for(2, lambda: check_title(expected_title)) assert get_url() == "{}/{}".format( url_stem, expected_url) if expected_url else url_stem results = get_search_results() assert get_search_result_names(results) == expected_sr return results
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_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
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)
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)
def click_on_author( sr, expected_author, expected_sr ): authors = find_children( ".authors .author", sr ) assert len(authors) == 1 assert authors[0].text == expected_author authors[0].click() wait_for( 2, lambda: get_search_result_names() == expected_sr ) return get_search_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" )
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 )
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
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
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" ) == ""
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 )
def flask_app(request): """Prepare the Flask server.""" # initialize flask_url = request.config.getoption("--flask-url") #pylint: disable=no-member # initialize # WTF?! https://github.com/pallets/flask/issues/824 def make_flask_url(endpoint, **kwargs): """Generate a URL for the Flask backend server.""" with app.test_request_context(): url = flask.url_for(endpoint, _external=True, **kwargs) if flask_url: url = url.replace("http://localhost", flask_url) else: url = url.replace("localhost/", "{}:{}/".format(*_FLASK_SERVER_URL)) return url app.url_for = make_flask_url # check if we need to start a local Flask server if not flask_url: # FUDGE! If we're going to create our own Flask server, we want to stop it from checking # the *configured* database connection string (since it will fail to start if there's a problem). asl_articles._disable_db_startup = True #pylint: disable=protected-access # yup - make it so thread = threading.Thread( target=lambda: app.run(host=_FLASK_SERVER_URL[0], port=_FLASK_SERVER_URL[1], use_reloader=False)) thread.start() # wait for the server to start up def is_ready(): """Try to connect to the Flask server.""" try: resp = urllib.request.urlopen(app.url_for("ping")).read() assert resp == b"pong" return True except URLError: return False except Exception as ex: #pylint: disable=broad-except assert False, "Unexpected exception: {}".format(ex) utils.wait_for(5, is_ready) # return the server to the caller try: yield app finally: # shutdown the local Flask server if not flask_url: urllib.request.urlopen(app.url_for("shutdown")).read() thread.join()
def test_parent_publisher(webdriver, flask_app, dbconn): """Test setting an article's parent publication.""" # initialize init_tests(webdriver, flask_app, dbconn, fixtures="parents.json") 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 # create an article with no parent publication create_article({"title": "My Article"}) results = get_search_results() assert len(results) == 1 sr = wait_for(2, lambda: check_result(results[0], None)) # change the article to have a publication edit_article(sr, {"publication": "ASL Journal"}) sr = wait_for(2, lambda: check_result(sr, (1, "ASL Journal"))) # change the article back to having no publication edit_article(sr, {"publication": "(none)"}) sr = wait_for(2, lambda: check_result(sr, None))
def test_parent_publisher(webdriver, flask_app, dbconn): """Test setting a publication's parent publisher.""" # initialize init_tests(webdriver, flask_app, dbconn, fixtures="parents.json") def check_result(sr, expected_parent): #pylint: disable=too-many-return-statements # check that the parent publisher was updated in the UI elem = find_child(".header .publisher", 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 publisher was updated in the database 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)) if expected_parent: if pub["publ_id"] != expected_parent[0]: return None else: if pub["publ_id"] is not None: return None # check that the parent publisher was updated in the UI results = do_search('"MMP News"') assert len(results) == 1 sr = results[0] elem = find_child(".header .publisher", sr) if expected_parent: if elem.text != "{}".format(expected_parent[1]): return None else: if elem is not None: return None return sr # create a publication with no parent publisher create_publication({"name": "MMP News"}) results = get_search_results() assert len(results) == 1 sr = wait_for(2, lambda: check_result(results[0], None)) # change the publication to have a publisher edit_publication(sr, {"publisher": "Multiman Publishing"}) sr = wait_for(2, lambda: check_result(sr, (1, "Multiman Publishing"))) # change the publication back to having no publisher edit_publication(sr, {"publisher": "(none)"}) sr = wait_for(2, lambda: check_result(sr, None))
def check_article_date(has_date): # check the article's publication date 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] wait_for(2, do_check)
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 )
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 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" )
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 test_constraints(webdriver, flask_app, dbconn): """Test constraint validation.""" # initialize init_tests(webdriver, flask_app, dbconn, disable_constraints=False, fixtures="publications.json") # try to create a publication with no name dlg = create_publication({}, expected_error="Please give it a name.") def do_create_test(vals, expected): return create_publication(vals, dlg=dlg, expected_constraints=expected) def do_edit_test(sr, vals, expected): return edit_publication(sr, vals, expected_constraints=expected) # set the publication's name do_create_test({"name": "ASL Journal"}, [ "The publication's edition was not specified.", "The publication date was not specified.", "A publisher was not specified.", ]) # try to create a duplicate publication create_publication( {"edition": 1}, dlg=dlg, expected_error="There is already a publication with this name/edition." ) # set the publication's edition and date do_create_test({ "edition": 3, "pub_date": "yesterday" }, [ "A publisher was not specified.", ]) # accept the constraint warnings find_child("button.ok", dlg).click() find_child("#ask button.ok").click() results = wait_for(2, get_search_results) pub_sr = results[0] # check that the search result was updated in the UI check_search_result(pub_sr, _check_sr, ["ASL Journal", "3", "yesterday", "", [], ""]) # try editing the publication dlg = do_edit_test(pub_sr, {}, [ "A publisher was not specified.", ]) find_child("button.cancel", dlg).click() # set the publisher do_edit_test(pub_sr, {"publisher": "Avalon Hill"}, None)
def do_test( author_names ): # test each author in the alias group expected = set( "By {}".format(a) for a in author_names ) for author_name in author_names: # find the author's article results = do_search( '"{}"'.format( author_name ) ) assert len(results) == 1 # click on the author's name authors = find_children( ".author", results[0] ) assert len(authors) == 1 authors[0].click() # check that we found all the articles by the aliased names wait_for( 2, lambda: set( get_search_result_names() ) == expected )
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)
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"] )
def test_publisher_article_dates(webdriver, flask_app, dbconn): """Test "published" dates for publisher articles.""" # initialize init_tests(webdriver, flask_app, dbconn, disable_constraints=False, fixtures="publisher-article-dates.json") # initialize article_title, article_date = "test article", "1st January, 2000" article_sr = None def check_article_date(has_date): # check the article's publication date 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] wait_for(2, do_check) # create an article associated with a publication create_article({ "title": article_title, "publication": "ASL Journal", "snippet": "This is a test article.", "pageno": 42, "authors": ["+Joe Blow"] }) article_sr = wait_for(2, lambda: find_search_result(article_title)) check_article_date(False) # change the article to be associated with a publisher edit_article(article_sr, {"publisher": "Avalon Hill"}, expected_constraints=["The article date was not specified."], accept_constraints=True) check_article_date(False) # give the article a published date edit_article(article_sr, {"article_date": article_date}) check_article_date(True) # change the article back to the publication edit_article(article_sr, {"publication": "ASL Journal"}) check_article_date(False)
def do_test( create, edit, refresh ): # create a new object webdriver.refresh() create() results = get_search_results() assert len(results) == 1 sr = results[0] # add images to the object # NOTE: We're testing that images in an object already on-screen is updated correctly. fname = os.path.join( os.path.split(__file__)[0], "fixtures/images/1.gif" ) description = 'foo <img src="/images/app.png" style="height:2em;" class="preview"> bar' edit( sr, fname, description ) _check_previewable_images( sr ) # refresh the object # NOTE: We're testing that images in an object loaded afresh is set up correctly. webdriver.refresh() wait_for( 2, lambda: find_child( "#search-form" ) ) results = refresh() assert len(results) == 1 _check_previewable_images( results[0] )
def test_check_db_links(webdriver, flask_app, dbconn): """Test checking links in the database.""" # initialize init_tests(webdriver, flask_app, dbconn, docs="docs/", fixtures="db-report.json") # check the initial report _, links, _, _ = _get_db_report() assert links == { "publishers": [2, []], "publications": [2, []], "articles": [2, []], } # check the links btn = find_child("#db-report button.check-links") btn.click() status = find_child("#db-report .db-links .status-msg") wait_for(10, lambda: status.text == "Checked 6 links.") # check the updated report _, links, _, _ = _get_db_report() assert links == { "publishers": [ 2, [("Multiman Publishing", "/publisher/2", "HTTP 404: http://{FLASK}/unknown")] ], "publications": [2, []], "articles": [2, [("MMP publisher article", "/article/299", "HTTP 404: /unknown")]], }
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
def click_on_tag( tag, expected ): tag.click() wait_for( 2, lambda: get_search_result_names() == expected ) return get_search_results()
def test_constraints(webdriver, flask_app, dbconn): """Test constraint validation.""" # initialize init_tests(webdriver, flask_app, dbconn, disable_constraints=False, fixtures="publications.json") # try to create an article with no title dlg = create_article({}, expected_error="Please give it a title.") def do_create_test(vals, expected): return create_article(vals, dlg=dlg, expected_constraints=expected) def do_edit_test(sr, vals, expected): return edit_article(sr, vals, expected_constraints=expected) # set the article's title do_create_test({"title": "New article"}, [ "No publication was specified.", "No snippet was provided.", "No authors were specified." ]) # set the article's page number do_create_test({"pageno": 99}, [ "No publication was specified.", "A page number was specified but no publication.", "No snippet was provided.", "No authors were specified." ]) # assign the article to a publisher do_create_test({ "publication": "MMP News", "pageno": "" }, [ "No page number was specified.", "No snippet was provided.", "No authors were specified." ]) # set a non-numeric page number do_create_test({"pageno": "foo!"}, [ "The page number is not numeric.", "No snippet was provided.", "No authors were specified." ]) # set the article's page number and provide a snippet do_create_test({ "pageno": 123, "snippet": "Article snippet." }, ["No authors were specified."]) # accept the constraint warnings find_child("button.ok", dlg).click() find_child("#ask button.ok").click() results = wait_for(2, get_search_results) article_sr = results[0] # check that the search result was updated in the UI check_search_result( article_sr, _check_sr, ["New article", "", "Article snippet.", "123", [], [], None]) # try editing the article dlg = do_edit_test(article_sr, {}, ["No authors were specified."]) find_child("button.cancel", dlg).click() # set the article's author do_edit_test(article_sr, {"authors": ["+Joe Blow"]}, None) # check that the search result was updated in the UI check_search_result( article_sr, _check_sr, ["New article", "", "Article snippet.", "123", ["Joe Blow"], [], None])