def test_query_string_prepopulates_form(web_fixture, value_scenarios): """Widget query string arguments can be used on forms to pre-populate inputs based on the query string.""" fixture = value_scenarios class ModelObject: @exposed def fields(self, fields): fields.arg_on_other_object = fixture.field class FormWithQueryArguments(Form): def __init__(self, view): self.model_object = ModelObject() super().__init__(view, 'name') self.use_layout(FormLayout()) self.layout.add_input(TextInput(self, self.model_object.fields.arg_on_other_object)) @exposed def query_fields(self, fields): fields.arg_on_other_object = self.model_object.fields.arg_on_other_object wsgi_app = web_fixture.new_wsgi_app(enable_js=True, child_factory=FormWithQueryArguments.factory()) browser = Browser(wsgi_app) browser.open('/?%s' % fixture.field_on_query_string.format(field_name='name-arg_on_other_object')) assert browser.get_value(XPath.input_labelled('field')) == fixture.field_value_as_string
def test_email_retained(web_fixture, session_scope_fixture): """The email address used when last logged in is always pre-populated on the Log in page.""" browser = Browser(web_fixture.new_wsgi_app(site_root=SessionScopeUI)) user = session_scope_fixture.user browser.open('/') browser.click(XPath.link().with_text('Log in')) browser.type(XPath.input_labelled('Email'), '*****@*****.**') browser.type(XPath.input_labelled('Password'), 'topsecret') browser.click(XPath.button_labelled('Log in')) # Go away from the page, then back browser.click(XPath.link().with_text('Home')) browser.click(XPath.link().with_text('Log in')) # .. then the email is still pre-populated typed_value = browser.get_value(XPath.input_labelled('Email')) assert typed_value == '*****@*****.**'
def test_form_preserves_user_input_after_validation_exceptions_multichoice( web_fixture): """When a form is submitted and validation fails on the server, the user is presented with the values that were originally entered (even if they were invalid).""" fixture = web_fixture class ModelObject(object): @exposed def events(self, events): events.an_event = Event(label='click me') @exposed def fields(self, fields): choices = [ Choice(1, IntegerField(label='One')), Choice(2, IntegerField(label='Two')), Choice(3, IntegerField(label='Three')) ] fields.no_validation_exception_field = MultiChoiceField( choices, label='Make your invalid choice', default=[]) fields.validation_exception_field = MultiChoiceField( choices, label='Make your choice', default=[], required=True) model_object = ModelObject() class MyForm(Form): def __init__(self, view): super(MyForm, self).__init__(view, 'my_form') self.define_event_handler(model_object.events.an_event) self.add_child(ButtonInput(self, model_object.events.an_event)) input = self.add_child( SelectInput(self, model_object.fields.no_validation_exception_field)) if input.validation_error: self.add_child(self.create_error_label(input)) input = self.add_child( SelectInput(self, model_object.fields.validation_exception_field)) if input.validation_error: self.add_child(self.create_error_label(input)) wsgi_app = web_fixture.new_wsgi_app(child_factory=MyForm.factory()) browser = Browser(wsgi_app) browser.open('/') no_validation_exception_input = '//select[@name="my_form-no_validation_exception_field[]"]' validation_exception_input = '//select[@name="my_form-validation_exception_field[]"]' browser.select_many(no_validation_exception_input, ['One', 'Two']) browser.select_none(validation_exception_input ) # select none to trigger the RequiredConstraint browser.click(XPath.button_labelled('click me')) assert browser.get_value(no_validation_exception_input) == ['1', '2'] assert not browser.get_value(validation_exception_input) label = browser.get_html_for('//label') input_id = browser.get_id_of(validation_exception_input) assert label == '<label for="%s" class="error">Make your choice is required</label>' % input_id #2. Submit again ths time not expecting validation exceptions, also expecting the validation error to be cleared and the domain should have all input browser.select_many(validation_exception_input, ['Two', 'Three']) browser.click(XPath.button_labelled('click me')) assert not browser.is_element_present('//label[@class="error"]') assert browser.get_value(no_validation_exception_input) == ['1', '2'] assert browser.get_value(validation_exception_input) == ['2', '3']
def test_exception_handling(reahl_system_fixture, web_fixture, sql_alchemy_fixture): """When a DomainException happens during the handling of an Event: The database is rolled back. The browser is redirected to GET the original view again (not the target). The screen still displays the values the user initially typed, not those on the ModelObject. """ fixture = web_fixture class ModelObject(Base): __tablename__ = 'test_event_handling_exception_handling' id = Column(Integer, primary_key=True) field_name = Column(Integer) def handle_event(self): self.field_name = 1 raise DomainException() @exposed def events(self, events): events.an_event = Event(label='click me', action=Action(self.handle_event)) @exposed def fields(self, fields): fields.field_name = IntegerField(default=3) with sql_alchemy_fixture.persistent_test_classes(ModelObject): model_object = ModelObject() Session.add(model_object) class MyForm(Form): def __init__(self, view, name, other_view): super(MyForm, self).__init__(view, name) self.define_event_handler(model_object.events.an_event, target=other_view) self.add_child(ButtonInput(self, model_object.events.an_event)) self.add_child(TextInput(self, model_object.fields.field_name)) class MainUI(UserInterface): def assemble(self): self.define_page(HTML5Page).use_layout(BasicPageLayout()) home = self.define_view('/', title='Home page') other_view = self.define_view('/page2', title='Page 2') home.set_slot('main', MyForm.factory('myform', other_view)) wsgi_app = fixture.new_wsgi_app(site_root=MainUI) browser = Browser( wsgi_app ) # Dont use a real browser, because it will also hit many other URLs for js and css which confuse the issue browser.open('/') assert not model_object.field_name browser.type("//input[@type='text']", '5') # any database stuff that happened when the form was submitted was rolled back # with CallMonitor(reahl_system_fixture.system_control.orm_control.rollback) as monitor: # browser.click(XPath.button_labelled('click me')) # assert monitor.times_called == 1 browser.click(XPath.button_labelled('click me')) # the value input by the user is still displayed on the form, NOT the actual value on the model object assert not model_object.field_name retained_value = browser.get_value("//input[@type='text']") assert retained_value == '5' # the browser is still on the page with the form which triggered the exception assert browser.current_url.path == '/'