Fix non-breaking spaces breaking formatting in sent messages.

This ensures that non-breaking space chars (not HTML entities) are
removed from text obtainined from the composer, and moves the F=F text
formatting from JS back to Vala, to minimimse the JS footprint and return
to using the old (working) version again.

* src/client/composer/composer-web-view.vala (ClientWebView::get_text):
  Restore the old F=F formatting code previously in webkit-util, apply it
  to plain text obtained from the composer.

* test/client/components/client-web-view-test-case.vala: New base class
  for tests involving ClientWebView.

* test/client/composer/composer-web-view-test.vala: New tests for
  ComposerWebView::get_html and ::get_text.

* test/js/composer-page-state-test.vala: Reworked to use
  ClientWebViewTestCase, updated tests now that JS is returning
  QUOTE_MARKER-delinated text, not F=F text.

* test/testcase.vala (TestCase): Move ::async_complete and ::async_result
  from ComposerPageStateTest so all test cases can test async code.

* test/CMakeLists.txt: Add new source files.

* test/main.vala (main): Add new test.

* ui/composer-web-view.js: Update doc comments, remove F=F code, break
  out non-breaking space replacement so it can be tested.
This commit is contained in:
Michael James Gratton 2017-01-02 10:23:35 +11:00
parent 57f10446a9
commit 17fda41b85
8 changed files with 341 additions and 99 deletions

View file

@ -5,13 +5,7 @@
* (version 2.1 or later). See the COPYING file in this distribution.
*/
// Defined by CMake build script.
extern const string _BUILD_ROOT_DIR;
class ComposerPageStateTest : Gee.TestCase {
private ComposerWebView test_view = null;
private AsyncQueue<AsyncResult> async_results = new AsyncQueue<AsyncResult>();
class ComposerPageStateTest : ClientWebViewTestCase<ComposerWebView> {
public ComposerPageStateTest() {
base("ComposerPageStateTest");
@ -21,19 +15,7 @@ class ComposerPageStateTest : Gee.TestCase {
add_test("get_text_with_nested_quote", get_text_with_nested_quote);
add_test("resolve_nesting", resolve_nesting);
add_test("quote_lines", quote_lines);
}
public override void set_up() {
ClientWebView.init_web_context(File.new_for_path(_BUILD_ROOT_DIR).get_child("src"), true);
try {
ClientWebView.load_scripts();
ComposerWebView.load_resources();
} catch (Error err) {
print("\nComposerPageStateTest::set_up: %s\n", err.message);
assert_not_reached();
}
Configuration config = new Configuration(GearyApplication.APP_ID);
this.test_view = new ComposerWebView(config);
add_test("replace_non_breaking_space", replace_non_breaking_space);
}
public void get_html() {
@ -53,7 +35,7 @@ class ComposerPageStateTest : Gee.TestCase {
public void get_text() {
load_body_fixture("<p>para</p>");
try {
assert(run_javascript(@"window.geary.getText();") == "para\n\n\n\n\n");
assert(run_javascript(@"window.geary.getText();") == "para\n\n\n\n");
} catch (Geary.JS.Error err) {
print("Geary.JS.Error: %s", err.message);
assert_not_reached();
@ -64,10 +46,11 @@ class ComposerPageStateTest : Gee.TestCase {
}
public void get_text_with_quote() {
unichar q_marker = Geary.RFC822.Utils.QUOTE_MARKER;
load_body_fixture("<p>pre</p> <blockquote><p>quote</p></blockquote> <p>post</p>");
try {
assert(run_javascript(@"window.geary.getText();") ==
"pre\n\n> quote\n> \npost\n\n\n\n\n");
@"pre\n\n$(q_marker)quote\n$(q_marker)\npost\n\n\n\n");
} catch (Geary.JS.Error err) {
print("Geary.JS.Error: %s", err.message);
assert_not_reached();
@ -78,10 +61,11 @@ class ComposerPageStateTest : Gee.TestCase {
}
public void get_text_with_nested_quote() {
unichar q_marker = Geary.RFC822.Utils.QUOTE_MARKER;
load_body_fixture("<p>pre</p> <blockquote><p>quote1</p> <blockquote><p>quote2</p></blockquote></blockquote> <p>post</p>");
try {
assert(run_javascript(@"window.geary.getText();") ==
"pre\n\n> quote1\n> \n>> quote2\n>> \npost\n\n\n\n\n");
@"pre\n\n$(q_marker)quote1\n$(q_marker)\n$(q_marker)$(q_marker)quote2\n$(q_marker)$(q_marker)\npost\n\n\n\n");
} catch (Geary.JS.Error err) {
print("Geary.JS.Error: %s", err.message);
assert_not_reached();
@ -144,7 +128,35 @@ class ComposerPageStateTest : Gee.TestCase {
}
}
protected void load_body_fixture(string? html = null) {
public void replace_non_breaking_space() {
load_body_fixture();
string single_nbsp = "a b";
string multiple_nbsp = "a b c";
try {
assert(run_javascript(@"ComposerPageState.replaceNonBreakingSpace('$(single_nbsp)');") ==
"a b");
assert(run_javascript(@"ComposerPageState.replaceNonBreakingSpace('$(multiple_nbsp)');") ==
"a b c");
} catch (Geary.JS.Error err) {
print("Geary.JS.Error: %s\n", err.message);
assert_not_reached();
} catch (Error err) {
print("WKError: %s\n", err.message);
assert_not_reached();
}
}
protected override ComposerWebView set_up_test_view() {
try {
ComposerWebView.load_resources();
} catch (Error err) {
assert_not_reached();
}
Configuration config = new Configuration(GearyApplication.APP_ID);
return new ComposerWebView(config);
}
protected override void load_body_fixture(string? html = null) {
this.test_view.load_html(html, null, false);
while (this.test_view.is_loading) {
Gtk.main_iteration();
@ -161,17 +173,4 @@ class ComposerPageStateTest : Gee.TestCase {
return WebKitUtil.to_string(result);
}
protected void async_complete(AsyncResult result) {
this.async_results.push(result);
}
protected AsyncResult async_result() {
AsyncResult? result = null;
while (result == null) {
Gtk.main_iteration();
result = this.async_results.try_pop();
}
return result;
}
}