import sys import bs4 import pytest import setpath # noqa:F401, must come before 'import mechanicalsoup' from utils import setup_mock_browser import mechanicalsoup def test_construct_form_fail(): """Form objects must be constructed from form html elements.""" soup = bs4.BeautifulSoup('This is not a form', 'lxml') tag = soup.find('notform') assert isinstance(tag, bs4.element.Tag) with pytest.warns(FutureWarning, match="from a 'notform'"): mechanicalsoup.Form(tag) def test_submit_online(httpbin): """Complete and submit the pizza form at http://httpbin.org/forms/post """ browser = mechanicalsoup.Browser() page = browser.get(httpbin + "/forms/post") form = mechanicalsoup.Form(page.soup.form) input_data = {"custname": "Philip J. Fry"} form.input(input_data) check_data = {"size": "large", "topping": ["cheese"]} form.check(check_data) check_data = {"size": "medium", "topping": "onion"} form.check(check_data) form.textarea({"comments": "warm"}) form.textarea({"comments": "actually, no, not warm"}) form.textarea({"comments": "freezer"}) response = browser.submit(form, page.url) # helpfully the form submits to http://httpbin.org/post which simply # returns the request headers in json format json = response.json() data = json["form"] assert data["custname"] == "Philip J. Fry" assert data["custtel"] == "" # web browser submits "" for input left blank assert data["size"] == "medium" assert data["topping"] == ["cheese", "onion"] assert data["comments"] == "freezer" def test_submit_set(httpbin): """Complete and submit the pizza form at http://httpbin.org/forms/post """ browser = mechanicalsoup.Browser() page = browser.get(httpbin + "/forms/post") form = mechanicalsoup.Form(page.soup.form) form["custname"] = "Philip J. Fry" form["size"] = "medium" form["topping"] = ("cheese", "onion") form["comments"] = "freezer" response = browser.submit(form, page.url) # helpfully the form submits to http://httpbin.org/post which simply # returns the request headers in json format json = response.json() data = json["form"] assert data["custname"] == "Philip J. Fry" assert data["custtel"] == "" # web browser submits "" for input left blank assert data["size"] == "medium" assert data["topping"] == ["cheese", "onion"] assert data["comments"] == "freezer" @pytest.mark.parametrize("expected_post", [ pytest.param( [ ('text', 'Setting some text!'), ('comment', 'Testing preview page'), ('preview', 'Preview Page'), ], id='preview'), pytest.param( [ ('text', '= Heading =\n\nNew page here!\n'), ('comment', 'Created new page'), ('save', 'Submit changes'), ], id='save'), pytest.param( [ ('text', '= Heading =\n\nNew page here!\n'), ('comment', 'Testing choosing cancel button'), ('cancel', 'Cancel'), ], id='cancel'), ]) def test_choose_submit(expected_post): browser, url = setup_mock_browser(expected_post=expected_post) browser.open(url) form = browser.select_form('#choose-submit-form') browser['text'] = dict(expected_post)['text'] browser['comment'] = dict(expected_post)['comment'] form.choose_submit(expected_post[2][0]) res = browser.submit_selected() assert res.status_code == 200 and res.text == 'Success!' @pytest.mark.parametrize("value", [ pytest.param('continue', id='first'), pytest.param('cancel', id='second'), ]) def test_choose_submit_from_selector(value): """Test choose_submit by passing a CSS selector argument.""" text = """
""" browser, url = setup_mock_browser(expected_post=[('do', value)], text=text) browser.open(url) form = browser.select_form() submits = form.form.select(f'input[value="{value}"]') assert len(submits) == 1 form.choose_submit(submits[0]) res = browser.submit_selected() assert res.status_code == 200 and res.text == 'Success!' choose_submit_fail_form = '''
''' @pytest.mark.parametrize("select_name", [ pytest.param({'name': 'does_not_exist', 'fails': True}, id='not found'), pytest.param({'name': 'test_submit', 'fails': False}, id='found'), ]) def test_choose_submit_fail(select_name): browser = mechanicalsoup.StatefulBrowser() browser.open_fake_page(choose_submit_fail_form) form = browser.select_form('#choose-submit-form') if select_name['fails']: with pytest.raises(mechanicalsoup.utils.LinkNotFoundError): form.choose_submit(select_name['name']) else: form.choose_submit(select_name['name']) def test_choose_submit_twice(): """Test that calling choose_submit twice fails.""" text = '''
''' soup = bs4.BeautifulSoup(text, 'lxml') form = mechanicalsoup.Form(soup.form) form.choose_submit('test1') expected_msg = 'Submit already chosen. Cannot change submit!' with pytest.raises(Exception, match=expected_msg): form.choose_submit('test2') choose_submit_multiple_match_form = '''
''' def test_choose_submit_multiple_match(): browser = mechanicalsoup.StatefulBrowser() browser.open_fake_page(choose_submit_multiple_match_form) form = browser.select_form('#choose-submit-form') with pytest.raises(mechanicalsoup.utils.LinkNotFoundError): form.choose_submit('test_submit') submit_form_noaction = '''
''' def test_form_noaction(): browser, url = setup_mock_browser() browser.open_fake_page(submit_form_noaction, url=url) form = browser.select_form('#choose-submit-form') form['text1'] = 'newText1' res = browser.submit_selected() assert res.status_code == 200 and browser.url == url submit_form_action = '''
''' def test_form_action(): browser, url = setup_mock_browser() # for info about example.com see: https://tools.ietf.org/html/rfc2606 browser.open_fake_page(submit_form_action, url="http://example.com/invalid/") form = browser.select_form('#choose-submit-form') form['text1'] = 'newText1' res = browser.submit_selected() assert res.status_code == 200 and browser.url == url set_select_form = '''
''' @pytest.mark.parametrize("option", [ pytest.param({'result': [('entree', 'tofu')], 'default': True}, id='default'), pytest.param({'result': [('entree', 'curry')], 'default': False}, id='selected'), ]) def test_set_select(option): '''Test the branch of Form.set that finds "select" elements.''' browser, url = setup_mock_browser(expected_post=option['result'], text=set_select_form) browser.open(url) browser.select_form('form') if not option['default']: browser[option['result'][0][0]] = option['result'][0][1] res = browser.submit_selected() assert res.status_code == 200 and res.text == 'Success!' set_select_multiple_form = '''
''' @pytest.mark.parametrize("options", [ pytest.param('bass', id='select one (str)'), pytest.param(('bass',), id='select one (tuple)'), pytest.param(('piano', 'violin'), id='select two'), ]) def test_set_select_multiple(options): """Test a or # . Normalize before comparing. out = out.replace('>', '/>') assert out == """ """ assert err == "" page_with_radio = '''
This is a checkbox
''' def test_form_check_uncheck(): browser = mechanicalsoup.StatefulBrowser() browser.open_fake_page(page_with_radio, url="http://example.com/invalid/") form = browser.select_form('form') assert "checked" not in form.form.find("input", {"name": "foo"}).attrs form["foo"] = True assert form.form.find("input", {"name": "foo"}).attrs["checked"] == "" # Test explicit unchecking (skipping the call to Form.uncheck_all) form.set_checkbox({"foo": False}, uncheck_other_boxes=False) assert "checked" not in form.form.find("input", {"name": "foo"}).attrs page_with_various_fields = '''
Pizza Toppings

Small

Medium

Large

''' def test_form_print_summary(capsys): browser = mechanicalsoup.StatefulBrowser() browser.open_fake_page(page_with_various_fields, url="http://example.com/invalid/") browser.select_form("form") browser.form.print_summary() out, err = capsys.readouterr() # Different versions of bs4 show either or # . Normalize before comparing. out = out.replace('>', '/>') assert out == """ """ assert err == "" def test_issue180(): """Test that a KeyError is not raised when Form.choose_submit is called on a form where a submit element is missing its name-attribute.""" browser = mechanicalsoup.StatefulBrowser() html = '''
''' browser.open_fake_page(html) form = browser.select_form() with pytest.raises(mechanicalsoup.utils.LinkNotFoundError): form.choose_submit('not_found') def test_issue158(): """Test that form elements are processed in their order on the page and that elements with duplicate name-attributes are not clobbered.""" issue158_form = '''
''' expected_post = [('box', '1'), ('box', '2'), ('box', '0')] browser, url = setup_mock_browser(expected_post=expected_post, text=issue158_form) browser.open(url) browser.select_form() res = browser.submit_selected() assert res.status_code == 200 and res.text == 'Success!' browser.close() def test_duplicate_submit_buttons(): """Tests that duplicate submits doesn't break form submissions See issue https://github.com/MechanicalSoup/MechanicalSoup/issues/264""" issue264_form = '''
''' expected_post = [('box', '1'), ('search', 'Search')] browser, url = setup_mock_browser(expected_post=expected_post, text=issue264_form) browser.open(url) browser.select_form() res = browser.submit_selected() assert res.status_code == 200 and res.text == 'Success!' browser.close() @pytest.mark.parametrize("expected_post", [ pytest.param([('sub2', 'val2')], id='submit button'), pytest.param([('sub4', 'val4')], id='typeless button'), pytest.param([('sub5', 'val5')], id='submit input'), ]) def test_choose_submit_buttons(expected_post): """Buttons of type reset and button are not valid submits""" text = """
""" browser, url = setup_mock_browser(expected_post=expected_post, text=text) browser.open(url) browser.select_form() res = browser.submit_selected(btnName=expected_post[0][0]) assert res.status_code == 200 and res.text == 'Success!' @pytest.mark.parametrize("fail, selected, expected_post", [ pytest.param(False, 'with_value', [('selector', 'with_value')], id='Option with value'), pytest.param(False, 'Without value', [('selector', 'Without value')], id='Option without value'), pytest.param(False, 'We have a value here', [('selector', 'with_value')], id='Option with value selected by its text'), pytest.param(True, 'Unknown option', None, id='Unknown option, must raise a LinkNotFound exception') ]) def test_option_without_value(fail, selected, expected_post): """Option tag in select can have no value option""" text = """
""" browser, url = setup_mock_browser(expected_post=expected_post, text=text) browser.open(url) browser.select_form() if fail: with pytest.raises(mechanicalsoup.utils.LinkNotFoundError): browser['selector'] = selected else: browser['selector'] = selected res = browser.submit_selected() assert res.status_code == 200 and res.text == 'Success!' if __name__ == '__main__': pytest.main(sys.argv)