""" Test publication operations. """ import os import urllib.request import urllib.error import json import base64 from collections import defaultdict from selenium.webdriver.common.keys import Keys from selenium.common.exceptions import StaleElementReferenceException from asl_articles.search import SEARCH_ALL, SEARCH_ALL_PUBLICATIONS, SEARCH_ALL_ARTICLES from asl_articles.tests.test_articles import create_article, edit_article from asl_articles.tests.utils import init_tests, load_fixtures, select_main_menu_option, select_sr_menu_option, \ do_search, get_search_results, get_search_result_names, check_search_result, \ do_test_confirm_discard_changes, find_parent_by_class, \ wait_for, wait_for_elem, wait_for_not_elem, find_child, find_children, find_search_result, set_elem_text, \ set_toast_marker, check_toast, send_upload_data, check_ask_dialog, check_error_msg, check_constraint_warnings, \ change_image, remove_image, get_publication_row from asl_articles.tests.react_select import ReactSelect # --------------------------------------------------------------------- def test_edit_publication( webdriver, flask_app, dbconn ): """Test editing publications.""" # initialize init_tests( webdriver, flask_app, dbconn, fixtures="publications.json" ) # edit "ASL Journal #2" results = do_search( SEARCH_ALL_PUBLICATIONS ) sr = find_search_result( "ASL Journal (2)", results ) edit_publication( sr, { "name": " ASL Journal (updated) ", "edition": " 2a ", "pub_date": "Jan 2020", "description": " Updated ASLJ description. ", "tags": [ "+abc", "+xyz" ], "url": " http://aslj-updated.com ", } ) # check that the search result was updated in the UI sr = find_search_result( "ASL Journal (updated) (2a)" ) check_search_result( sr, _check_sr, [ "ASL Journal (updated)", "2a", "Jan 2020", "Updated ASLJ description.", ["abc","xyz"], "http://aslj-updated.com/" ] ) # remove all fields from the publication edit_publication( sr, { "name": "ASLJ", "edition": "", "pub_date": "", "description": "", "tags": [ "-abc", "-xyz" ], "url": "", } ) # check that the search result was updated in the UI expected = [ "ASLJ", "", "", "", [], "" ] check_search_result( sr, _check_sr, expected ) # check that the publication was updated in the database results = do_search( SEARCH_ALL_PUBLICATIONS ) sr = find_search_result( "ASLJ", results ) check_search_result( sr, _check_sr, expected ) # --------------------------------------------------------------------- def test_create_publication( webdriver, flask_app, dbconn ): """Test creating new publications.""" # initialize init_tests( webdriver, flask_app, dbconn, fixtures="publications.json" ) do_search( SEARCH_ALL_PUBLICATIONS ) # create a new publication create_publication( { "name": "New publication", "edition": "#1", "pub_date": "1st January, 1900", "description": "New publication description.", "tags": [ "+111", "+222", "+333" ], "url": "http://new-publication.com" } ) # check that the new publication appears in the UI expected = [ "New publication", "#1", "1st January, 1900", "New publication description.", ["111","222","333"], "http://new-publication.com/" ] check_search_result( "New publication (#1)", _check_sr, expected ) # check that the new publication has been saved in the database results = do_search( SEARCH_ALL_PUBLICATIONS ) sr = find_search_result( "New publication (#1)", results ) check_search_result( sr, _check_sr, expected ) # --------------------------------------------------------------------- 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 test_confirm_discard_changes( webdriver, flask_app, dbconn ): """Test confirmation of discarding changes made to a dialog.""" # initialize init_tests( webdriver, flask_app, dbconn, disable_confirm_discard_changes=False, fixtures="publications.json" ) # do the test def update_react_select( elem, val ): select = ReactSelect( find_parent_by_class( elem, "react-select" ) ) select.select_by_name( val ) def update_multiselect( elem, vals ): select = ReactSelect( find_parent_by_class( elem, "react-select" ) ) select.update_multiselect_values( *vals ) do_test_confirm_discard_changes( "new-publication", { "publisher": ( lambda elem: update_react_select( elem, "Avalon Hill" ), lambda elem: update_react_select( elem, "(none)" ) ), "tags": ( lambda elem: update_multiselect( elem, ["+foo"] ), lambda elem: update_multiselect( elem, ["-foo"] ), ) } ) # --------------------------------------------------------------------- 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 test_images( webdriver, flask_app, dbconn ): #pylint: disable=too-many-statements """Test publication images.""" # initialize init_tests( webdriver, flask_app, dbconn, max_image_upload_size=2*1024 ) def check_image( expected ): # check the image in the publication's search result def check_sr_image( expected ): img = find_child( "img.image", pub_sr ) if expected: expected_url = flask_app.url_for( "get_image", image_type="publication", image_id=pub_id ) image_url = img.get_attribute( "src" ).split( "?" )[0] return image_url == expected_url else: return not img wait_for( 2, lambda: check_sr_image( expected ) ) # check the image in the publisher's config select_sr_menu_option( pub_sr, "edit" ) dlg = wait_for_elem( 2, "#publication-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/publication/{}".format( pub_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 publication's image is correct with urllib.request.urlopen( image_url ) as resp: with open( expected, "rb" ) as fp: assert resp.read() == fp.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 publication's image is not available url = flask_app.url_for( "get_image", image_type="publication", image_id=pub_id ) try: with urllib.request.urlopen( url ): pass assert False, "Should never get here!" except urllib.error.HTTPError as ex: assert ex.code == 404 find_child( ".cancel", dlg ).click() # create an publication with no image create_publication( {"name": "Test Publication" } ) results = get_search_results() assert len(results) == 1 pub_sr = results[0] pub_id = pub_sr.get_attribute( "testing--pub_id" ) check_image( None ) # add an image to the publication fname = os.path.join( os.path.split(__file__)[0], "fixtures/images/1.gif" ) edit_publication( pub_sr, { "image": fname } ) check_image( fname ) # change the publication's image fname = os.path.join( os.path.split(__file__)[0], "fixtures/images/2.gif" ) edit_publication( pub_sr, { "image": fname } ) check_image( fname ) # remove the publication's image edit_publication( pub_sr, { "image": None } ) check_image( None ) # try to upload an image that's too large select_sr_menu_option( pub_sr, "edit" ) dlg = wait_for_elem( 2, "#publication-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." ) # --------------------------------------------------------------------- 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 ) with urllib.request.urlopen( url ) as resp: pub = json.load( resp ) 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 test_cascading_deletes( webdriver, flask_app, dbconn ): """Test cascading deletes.""" # initialize session = init_tests( webdriver, flask_app, dbconn ) 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() # do the tests do_test( "Cascading Deletes 1", "No articles will be deleted", ["article 2","article 3a","article 3b"] ) do_test( "Cascading Deletes 2", "1 associated article will also be deleted", ["article 3a","article 3b"] ) do_test( "Cascading Deletes 3", "2 associated articles will also be deleted", ["article 2"] ) # --------------------------------------------------------------------- def test_unicode( webdriver, flask_app, dbconn ): """Test Unicode content.""" # initialize init_tests( webdriver, flask_app, dbconn ) # create a publication with Unicode content create_publication( { "name": "japan = \u65e5\u672c", "edition": "\u263a", "tags": [ "+\u0e51", "+\u0e52", "+\u0e53" ], "url": "http://\ud55c\uad6d.com", "description": "greece = \u0395\u03bb\u03bb\u03ac\u03b4\u03b1" } ) # check that the new publication is showing the Unicode content correctly results = do_search( SEARCH_ALL_PUBLICATIONS ) assert len( results ) == 1 check_search_result( results[0], _check_sr, [ "japan = \u65e5\u672c", "\u263a", None, "greece = \u0395\u03bb\u03bb\u03ac\u03b4\u03b1", [ "\u0e51", "\u0e52", "\u0e53" ], "http://xn--3e0b707e.com/" ] ) # --------------------------------------------------------------------- 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 publication with HTML content create_publication( { "name": "name: bold xxx italic {}".format( replace[0] ), "edition": "2", "description": "bad stuff here: {}".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] ), "2", None, "bad stuff here: {}".format( replace[1] ), [], None ] ) assert find_child( ".name", sr ).get_attribute( "innerHTML" ) \ == "name: bold xxx italic {} (2)".format( replace[1] ) assert check_toast( "warning", "Some values had HTML cleaned up.", contains=True ) # update the publication with new HTML content edit_publication( sr, { "name": "
updated
" }, toast_type="warning" ) results = get_search_results() assert len(results) == 1 wait_for( 2, lambda: find_child( ".name", results[0] ).text == "updated (2)" ) assert check_toast( "warning", "Some values had HTML cleaned up.", contains=True ) # --------------------------------------------------------------------- def test_timestamps( webdriver, flask_app, dbconn ): """Test setting of timestamps.""" # initialize init_tests( webdriver, flask_app, dbconn ) # create a publication create_publication( { "name": "My Publication" } ) results = get_search_results() assert len(results) == 1 pub_sr = results[0] pub_id = pub_sr.get_attribute( "testing--pub_id" ) # check its timestamps row = get_publication_row( dbconn, pub_id, ["time_created","time_updated"] ) assert row[0] assert row[1] is None # update the publication edit_publication( pub_sr, { "name": "My Publication (updated)" } ) # check its timestamps row2 = get_publication_row( dbconn, pub_id, ["time_created","time_updated"] ) assert row2[0] == row[0] assert row2[1] > row2[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_article_order( webdriver, flask_app, dbconn ): """Test ordering of articles.""" # initialize init_tests( webdriver, flask_app, dbconn, fixtures="article-order.json" ) 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] ] # create some articles (to check the seq# is being assigned correctly) create_article( { "title": "Article 1", "publication": "Publication A" } ) check_article_order( { "Publication A": [ ("Article 1",1) ] } ) create_article( { "title": "Article 2", "publication": "Publication A" } ) check_article_order( { "Publication A": [ ("Article 1",1), ("Article 2",2) ] } ) create_article( { "title": "Article 3", "publication": "Publication A" } ) check_article_order( { "Publication A": [ ("Article 1",1), ("Article 2",2), ("Article 3",3) ] } ) # create some articles (to check the seq# is being assigned correctly) create_article( { "title": "Article 5", "publication": "Publication B" } ) check_article_order( { "Publication A": [ ("Article 1",1), ("Article 2",2), ("Article 3",3) ], "Publication B": [ ("Article 5",1) ] } ) create_article( { "title": "Article 6", "publication": "Publication B" } ) check_article_order( { "Publication A": [ ("Article 1",1), ("Article 2",2), ("Article 3",3) ], "Publication B": [ ("Article 5",1), ("Article 6",2) ] } ) # NOTE: It would be nice to test re-ordering articles via drag-and-drop, # but Selenium just ain't co-operating... :-/ # move an article to another publication sr = find_search_result( "Article 1" ) edit_article( sr, { "publication": "Publication B" } ) check_article_order( { "Publication A": [ ("Article 2",2), ("Article 3",3) ], "Publication B": [ ("Article 5",1), ("Article 6",2), ("Article 1",3) ] } ) # remove the article from the publication sr = find_search_result( "Article 1" ) edit_article( sr, { "publication": "(none)" } ) check_article_order( { "Publication A": [ ("Article 2",2), ("Article 3",3) ], "Publication B": [ ("Article 5",1), ("Article 6",2) ], None: [ ("Article 1", None) ] } ) # add the article to another publication sr = find_search_result( "Article 1" ) edit_article( sr, { "publication": "Publication A" } ) check_article_order( { "Publication A": [ ("Article 2",2), ("Article 3",3), ("Article 1",4) ], "Publication B": [ ("Article 5",1), ("Article 6",2) ], } ) # --------------------------------------------------------------------- def test_default_image( webdriver, flask_app, dbconn ): """Test displaying a publication's default image.""" # initialize init_tests( webdriver, flask_app, dbconn, fixtures="default-publication-image.json" ) # initialize from asl_articles.tests.test_publishers import edit_publisher #pylint: disable=import-outside-toplevel images = [ "1.gif", "2.gif", "3.gif" ] image_fnames = { f: os.path.join( os.path.split(__file__)[0], "fixtures/images/"+f ) for f in images } def read_image_data( fname ): with open( fname, "rb" ) as fp: return fp.read() image_data = { f: read_image_data( image_fnames[f] ) for f in images } # show the test publisher/publication results = do_search( SEARCH_ALL ) publ_sr = find_search_result( "Joe Publisher", results ) pub_sr = find_search_result( "My Publication", results ) def check_images( publ_expected, pub_expected ): do_check_image( publ_sr, publ_expected ) do_check_image( pub_sr, pub_expected ) def do_check_image( sr, expected ): img = find_child( "img.image", sr ) if img: assert expected image_url = img.get_attribute( "src" ) with urllib.request.urlopen( image_url ) as resp: assert resp.read() == image_data[ expected ] else: assert not expected # add an image to the publisher edit_publisher( publ_sr, { "image": image_fnames["1.gif"] } ) check_images( "1.gif", "1.gif" ) # add an image to the publication edit_publication( pub_sr, { "image": image_fnames["2.gif"] } ) check_images( "1.gif", "2.gif" ) # remove the publisher's image edit_publisher( publ_sr, { "image": None } ) check_images( None, "2.gif" ) # add a different image to the publisher edit_publisher( publ_sr, { "image": image_fnames["3.gif"] } ) check_images( "3.gif", "2.gif" ) # remove the publication's image edit_publication( pub_sr, { "image": None } ) check_images( "3.gif", "3.gif" ) # detach the publication from the publisher edit_publication( pub_sr, { "publisher": "(none)" } ) check_images( "3.gif", None) # --------------------------------------------------------------------- def create_publication( vals, toast_type="info", expected_error=None, expected_constraints=None, dlg=None ): """Create a new publication.""" # initialize set_toast_marker( toast_type ) # create the new publication if not dlg: select_main_menu_option( "new-publication" ) dlg = wait_for_elem( 2, "#publication-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 publication?", 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, "#publication-form" ) return None def edit_publication( sr, vals, toast_type="info", expected_error=None, expected_constraints=None ): """Edit a publication'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, "#publication-form" ) # update the specified publication'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 publication?", 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, "#publication-form" ) return None 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 ) # --------------------------------------------------------------------- def _check_sr( sr, expected ): """Check a search result.""" # check the name and edition expected_name = expected[0] if expected[1]: expected_name += " ({})".format( expected[1] ) if find_child( ".name", sr ).text != expected_name: return False # check the publication date elem = find_child( ".pub_date", sr ) if expected[2]: assert elem if elem.text != expected[2]: return False else: assert elem is None # check the description if find_child( ".description", sr ).text != expected[3]: return False # check the tags tags = [ t.text for t in find_children( ".tag", sr ) ] if tags != expected[4]: return False # check the publication's link elem = find_child( "a.open-link", sr ) if expected[5]: assert elem if elem.get_attribute( "href" ) != expected[5]: return False else: assert elem is None return True