Add manual Components.Validator::validator method
Support manual validation where needed, add unit tests. This also slightly changes the behaviour of non-required field, since an empty non-required field should be valid.
This commit is contained in:
parent
c9fc877d12
commit
ca6cbecb83
4 changed files with 127 additions and 10 deletions
|
|
@ -48,7 +48,9 @@ public class Components.Validator : GLib.Object {
|
|||
|
||||
/** The cause of a validity check being required. */
|
||||
public enum Trigger {
|
||||
/** The entry's contents changed */
|
||||
/** A manual validation was requested via {@link validate}. */
|
||||
MANUAL,
|
||||
/** The entry's contents changed. */
|
||||
CHANGED,
|
||||
/** The entry lost the keyboard focus. */
|
||||
LOST_FOCUS,
|
||||
|
|
@ -162,6 +164,17 @@ public class Components.Validator : GLib.Object {
|
|||
this.pulse_timer.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers a validation of the entry.
|
||||
*
|
||||
* In the case of an asynchronous validation implementations,
|
||||
* result of the validation will be known sometime after this call
|
||||
* has completed.
|
||||
*/
|
||||
public void validate() {
|
||||
validate_entry(MANUAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to validate the target entry's value.
|
||||
*
|
||||
|
|
@ -187,7 +200,7 @@ public class Components.Validator : GLib.Object {
|
|||
* By default, this always returns {@link Validity.VALID}, making
|
||||
* it useful for required, but otherwise free-form fields only.
|
||||
*/
|
||||
protected virtual Validity validate(string value, Trigger reason) {
|
||||
protected virtual Validity do_validate(string value, Trigger reason) {
|
||||
return Validity.VALID;
|
||||
}
|
||||
|
||||
|
|
@ -255,12 +268,10 @@ public class Components.Validator : GLib.Object {
|
|||
string value = this.target.get_text();
|
||||
Validity new_state = this.state;
|
||||
if (Geary.String.is_empty_or_whitespace(value)) {
|
||||
new_state = this.is_required
|
||||
? Validity.EMPTY : Validity.INDETERMINATE;
|
||||
new_state = this.is_required ? Validity.EMPTY : Validity.VALID;
|
||||
} else {
|
||||
new_state = validate(value, reason);
|
||||
new_state = do_validate(value, reason);
|
||||
}
|
||||
|
||||
update_state(new_state, reason);
|
||||
}
|
||||
|
||||
|
|
@ -384,8 +395,8 @@ public class Components.EmailValidator : Validator {
|
|||
}
|
||||
|
||||
|
||||
protected override Validator.Validity validate(string value,
|
||||
Validator.Trigger reason) {
|
||||
protected override Validator.Validity do_validate(string value,
|
||||
Validator.Trigger reason) {
|
||||
return Geary.RFC822.MailboxAddress.is_valid_address(value)
|
||||
? Validator.Validity.VALID : Validator.Validity.INVALID;
|
||||
}
|
||||
|
|
@ -435,8 +446,8 @@ public class Components.NetworkAddressValidator : Validator {
|
|||
}
|
||||
|
||||
|
||||
public override Validator.Validity validate(string value,
|
||||
Validator.Trigger reason) {
|
||||
public override Validator.Validity do_validate(string value,
|
||||
Validator.Trigger reason) {
|
||||
if (this.cancellable != null) {
|
||||
this.cancellable.cancel();
|
||||
}
|
||||
|
|
|
|||
104
test/client/components/components-validator-test.vala
Normal file
104
test/client/components/components-validator-test.vala
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 2019 Michael Gratton <mike@vee.net>
|
||||
*
|
||||
* This software is licensed under the GNU Lesser General Public License
|
||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||
*/
|
||||
|
||||
|
||||
public class Components.ValidatorTest : TestCase {
|
||||
|
||||
|
||||
private Gtk.Entry? entry = null;
|
||||
|
||||
|
||||
public ValidatorTest() {
|
||||
base("Components.ValidatorTest");
|
||||
add_test("manual_empty", manual_empty);
|
||||
add_test("manual_valid", manual_valid);
|
||||
add_test("manual_not_required", manual_not_required);
|
||||
}
|
||||
|
||||
public override void set_up() {
|
||||
this.entry = new Gtk.Entry();
|
||||
}
|
||||
|
||||
public override void tear_down() {
|
||||
this.entry = null;
|
||||
}
|
||||
|
||||
public void manual_empty() throws GLib.Error {
|
||||
Validator test_article = new Validator(this.entry);
|
||||
|
||||
bool finished = false;
|
||||
Validator.Trigger? reason = null;
|
||||
Validator.Validity? prev_state = null;
|
||||
test_article.state_changed.connect((r, p) => {
|
||||
finished = true;
|
||||
reason = r;
|
||||
prev_state = p;
|
||||
});
|
||||
|
||||
test_article.validate();
|
||||
|
||||
while (!finished) {
|
||||
this.main_loop.iteration(true);
|
||||
}
|
||||
|
||||
assert_false(test_article.is_valid);
|
||||
assert_true(test_article.state == EMPTY);
|
||||
assert_true(reason == MANUAL);
|
||||
assert_true(prev_state == INDETERMINATE);
|
||||
}
|
||||
|
||||
public void manual_valid() throws GLib.Error {
|
||||
this.entry.text = "OHHAI";
|
||||
Validator test_article = new Validator(this.entry);
|
||||
|
||||
bool finished = false;
|
||||
Validator.Trigger? reason = null;
|
||||
Validator.Validity? prev_state = null;
|
||||
test_article.state_changed.connect((r, p) => {
|
||||
finished = true;
|
||||
reason = r;
|
||||
prev_state = p;
|
||||
});
|
||||
|
||||
test_article.validate();
|
||||
|
||||
while (!finished) {
|
||||
this.main_loop.iteration(true);
|
||||
}
|
||||
|
||||
assert_true(test_article.is_valid);
|
||||
assert_true(test_article.state == VALID);
|
||||
assert_true(reason == MANUAL);
|
||||
assert_true(prev_state == INDETERMINATE);
|
||||
}
|
||||
|
||||
public void manual_not_required() throws GLib.Error {
|
||||
Validator test_article = new Validator(this.entry);
|
||||
test_article.is_required = false;
|
||||
|
||||
bool finished = false;
|
||||
Validator.Trigger? reason = null;
|
||||
Validator.Validity? prev_state = null;
|
||||
test_article.state_changed.connect((r, p) => {
|
||||
finished = true;
|
||||
reason = r;
|
||||
prev_state = p;
|
||||
});
|
||||
|
||||
test_article.validate();
|
||||
|
||||
while (!finished) {
|
||||
this.main_loop.iteration(true);
|
||||
}
|
||||
|
||||
assert_true(test_article.is_valid);
|
||||
assert_true(test_article.state == VALID);
|
||||
assert_true(reason == MANUAL);
|
||||
assert_true(prev_state == INDETERMINATE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -84,6 +84,7 @@ geary_test_client_sources = [
|
|||
'client/application/application-configuration-test.vala',
|
||||
'client/components/client-web-view-test.vala',
|
||||
'client/components/client-web-view-test-case.vala',
|
||||
'client/components/components-validator-test.vala',
|
||||
'client/composer/composer-web-view-test.vala',
|
||||
'client/util/util-avatar-test.vala',
|
||||
'client/util/util-cache-test.vala',
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ int main(string[] args) {
|
|||
client.add_suite(new Application.ConfigurationTest().get_suite());
|
||||
client.add_suite(new ClientWebViewTest().get_suite());
|
||||
client.add_suite(new Composer.WebViewTest().get_suite());
|
||||
client.add_suite(new Components.ValidatorTest().get_suite());
|
||||
client.add_suite(new Util.Avatar.Test().get_suite());
|
||||
client.add_suite(new Util.Cache.Test().get_suite());
|
||||
client.add_suite(new Util.Email.Test().get_suite());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue