862a24d7d04ee0cbdd8977291054164b51114531
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebKitGtk / TestWebViewEditor.cpp
1 /*
2  * Copyright (C) 2012 Igalia S.L.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2,1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "WebViewTest.h"
22 #include <wtf/glib/GRefPtr.h>
23
24 class EditorTest: public WebViewTest {
25 public:
26     MAKE_GLIB_TEST_FIXTURE(EditorTest);
27
28     static const unsigned kClipboardWaitTimeout = 50;
29     static const unsigned kClipboardWaitMaxTries = 2;
30
31     EditorTest()
32         : m_clipboard(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))
33         , m_canExecuteEditingCommand(false)
34         , m_triesCount(0)
35         , m_editorState(nullptr)
36     {
37         gtk_clipboard_clear(m_clipboard);
38     }
39
40     static gboolean webViewDrawCallback(GMainLoop* mainLoop)
41     {
42         g_main_loop_quit(mainLoop);
43         return G_SOURCE_REMOVE;
44     }
45
46     void flushEditorState()
47     {
48         // FIXME: It would be better to call WebViewTest::showInWindowAndWaitUntilMapped
49         // at the start of the test, rather than creating and destroying temporary windows.
50         showInWindow(GTK_WINDOW_TOPLEVEL);
51
52         g_signal_connect_swapped(m_webView, "draw", G_CALLBACK(webViewDrawCallback), m_mainLoop);
53         gtk_widget_queue_draw(GTK_WIDGET(m_webView));
54         g_main_loop_run(m_mainLoop);
55
56         gtk_container_remove(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView));
57         gtk_widget_destroy(m_parentWindow);
58         m_parentWindow = nullptr;
59     }
60
61     static void canExecuteEditingCommandReadyCallback(GObject*, GAsyncResult* result, EditorTest* test)
62     {
63         GUniqueOutPtr<GError> error;
64         test->m_canExecuteEditingCommand = webkit_web_view_can_execute_editing_command_finish(test->m_webView, result, &error.outPtr());
65         g_assert(!error.get());
66         g_main_loop_quit(test->m_mainLoop);
67     }
68
69     bool canExecuteEditingCommand(const char* command)
70     {
71         m_canExecuteEditingCommand = false;
72         webkit_web_view_can_execute_editing_command(m_webView, command, 0, reinterpret_cast<GAsyncReadyCallback>(canExecuteEditingCommandReadyCallback), this);
73         g_main_loop_run(m_mainLoop);
74
75         if (!strcmp(command, WEBKIT_EDITING_COMMAND_CUT))
76             g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_cut_available(editorState()));
77         else if (!strcmp(command, WEBKIT_EDITING_COMMAND_COPY))
78             g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_copy_available(editorState()));
79         else if (!strcmp(command, WEBKIT_EDITING_COMMAND_PASTE))
80             g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_paste_available(editorState()));
81         // FIXME: Figure out how to add tests for undo and redo. It will probably require using user
82         // scripts to message the UI process when the content has been altered.
83         else if (!strcmp(command, WEBKIT_EDITING_COMMAND_UNDO))
84             g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_undo_available(editorState()));
85         else if (!strcmp(command, WEBKIT_EDITING_COMMAND_REDO))
86             g_assert(m_canExecuteEditingCommand == webkit_editor_state_is_redo_available(editorState()));
87
88         return m_canExecuteEditingCommand;
89     }
90
91     static gboolean waitForClipboardText(EditorTest* test)
92     {
93         test->m_triesCount++;
94         if (gtk_clipboard_wait_is_text_available(test->m_clipboard) || test->m_triesCount > kClipboardWaitMaxTries) {
95             g_main_loop_quit(test->m_mainLoop);
96             return FALSE;
97         }
98
99         return TRUE;
100     }
101
102     void copyClipboard()
103     {
104         webkit_web_view_execute_editing_command(m_webView, WEBKIT_EDITING_COMMAND_COPY);
105         // There's no way to know when the selection has been copied to
106         // the clipboard, so use a timeout source to query the clipboard.
107         m_triesCount = 0;
108         g_timeout_add(kClipboardWaitTimeout, reinterpret_cast<GSourceFunc>(waitForClipboardText), this);
109         g_main_loop_run(m_mainLoop);
110     }
111
112     gchar* cutSelection()
113     {
114         g_assert(canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
115         g_assert(canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
116
117         webkit_web_view_execute_editing_command(m_webView, WEBKIT_EDITING_COMMAND_CUT);
118         // There's no way to know when the selection has been cut to
119         // the clipboard, so use a timeout source to query the clipboard.
120         m_triesCount = 0;
121         g_timeout_add(kClipboardWaitTimeout, reinterpret_cast<GSourceFunc>(waitForClipboardText), this);
122         g_main_loop_run(m_mainLoop);
123
124         return gtk_clipboard_wait_for_text(m_clipboard);
125     }
126
127     WebKitEditorState* editorState()
128     {
129         if (m_editorState)
130             return m_editorState;
131
132         m_editorState = webkit_web_view_get_editor_state(m_webView);
133         assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_editorState));
134         return m_editorState;
135     }
136
137     static void quitMainLoopInCallback(EditorTest* test)
138     {
139         g_main_loop_quit(test->m_mainLoop);
140     }
141
142     unsigned typingAttributes()
143     {
144         return webkit_editor_state_get_typing_attributes(editorState());
145     }
146
147     unsigned waitUntilTypingAttributesChanged()
148     {
149         unsigned long handlerID = g_signal_connect_swapped(editorState(), "notify::typing-attributes", G_CALLBACK(quitMainLoopInCallback), this);
150         g_main_loop_run(m_mainLoop);
151         g_signal_handler_disconnect(m_editorState, handlerID);
152         return typingAttributes();
153     }
154
155     GtkClipboard* m_clipboard;
156     bool m_canExecuteEditingCommand;
157     size_t m_triesCount;
158     WebKitEditorState* m_editorState;
159 };
160
161 static const char* selectedSpanHTMLFormat =
162     "<html><body contentEditable=\"%s\">"
163     "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
164     "<script>document.getSelection().removeAllRanges();\n"
165     "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
166     "</script></body></html>";
167
168 static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpointer)
169 {
170     // Nothing loaded yet.
171     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
172     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
173     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
174
175     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
176     test->loadHtml(selectedSpanHTML.get(), nullptr);
177     test->waitUntilLoadFinished();
178     test->flushEditorState();
179
180     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
181     // It's not possible to cut and paste when content is not editable
182     // even if there's a selection.
183     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
184     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
185
186     test->copyClipboard();
187     GUniquePtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard));
188     g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
189 }
190
191 static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointer)
192 {
193     // Nothing loaded yet.
194     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
195     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
196     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
197
198     g_assert(!test->isEditable());
199     test->setEditable(true);
200     g_assert(test->isEditable());
201
202     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
203     test->loadHtml(selectedSpanHTML.get(), nullptr);
204     test->waitUntilLoadFinished();
205     test->flushEditorState();
206
207     // There's a selection.
208     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
209     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
210     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
211
212     test->copyClipboard();
213     GUniquePtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard));
214     g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
215 }
216
217 static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointer)
218 {
219     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
220
221     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
222     test->loadHtml(selectedSpanHTML.get(), nullptr);
223     test->waitUntilLoadFinished();
224     test->flushEditorState();
225
226     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
227
228     test->copyClipboard();
229     GUniquePtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard));
230
231     // Initially only the subspan is selected.
232     g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
233
234     webkit_web_view_execute_editing_command(test->m_webView, WEBKIT_EDITING_COMMAND_SELECT_ALL);
235     test->copyClipboard();
236     clipboardText.reset(gtk_clipboard_wait_for_text(test->m_clipboard));
237
238     // The mainspan should be selected after calling SELECT_ALL.
239     g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy.");
240 }
241
242 static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer)
243 {
244     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
245
246     g_assert(!test->isEditable());
247     test->setEditable(true);
248     g_assert(test->isEditable());
249
250     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
251     test->loadHtml(selectedSpanHTML.get(), nullptr);
252     test->waitUntilLoadFinished();
253     test->flushEditorState();
254
255     g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
256
257     test->copyClipboard();
258     GUniquePtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard));
259
260     // Initially only the subspan is selected.
261     g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
262
263     webkit_web_view_execute_editing_command(test->m_webView, WEBKIT_EDITING_COMMAND_SELECT_ALL);
264     test->copyClipboard();
265     clipboardText.reset(gtk_clipboard_wait_for_text(test->m_clipboard));
266
267     // The mainspan should be selected after calling SELECT_ALL.
268     g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy.");
269 }
270
271 static void loadContentsAndTryToCutSelection(EditorTest* test, bool contentEditable)
272 {
273     // View is not editable by default.
274     g_assert(!test->isEditable());
275
276     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, contentEditable ? "true" : "false"));
277     test->loadHtml(selectedSpanHTML.get(), nullptr);
278     test->waitUntilLoadFinished();
279     test->flushEditorState();
280
281     g_assert(!test->isEditable());
282     test->setEditable(true);
283     g_assert(test->isEditable());
284
285     test->flushEditorState();
286
287     // Cut the selection to the clipboard to see if the view is indeed editable.
288     GUniquePtr<char> clipboardText(test->cutSelection());
289     g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
290
291     // Reset the editable for next test.
292     test->setEditable(false);
293     g_assert(!test->isEditable());
294 }
295
296 static void testWebViewEditorNonEditable(EditorTest* test)
297 {
298     GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
299     test->loadHtml(selectedSpanHTML.get(), nullptr);
300     test->waitUntilLoadFinished();
301     test->flushEditorState();
302
303     g_assert(!test->isEditable());
304     test->setEditable(true);
305     g_assert(test->isEditable());
306     test->setEditable(false);
307     g_assert(!test->isEditable());
308
309     // Check if view is indeed non-editable.
310     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
311     g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
312 }
313
314 static void testWebViewEditorEditable(EditorTest* test, gconstpointer)
315 {
316     testWebViewEditorNonEditable(test);
317
318     // Reset the editable for next test.
319     test->setEditable(false);
320     g_assert(!test->isEditable());
321
322     loadContentsAndTryToCutSelection(test, true);
323
324     // Reset the editable for next test.
325     test->setEditable(false);
326     g_assert(!test->isEditable());
327
328     loadContentsAndTryToCutSelection(test, false);
329 }
330
331 static void testWebViewEditorEditorStateTypingAttributes(EditorTest* test, gconstpointer)
332 {
333     static const char* typingAttributesHTML =
334         "<html><body>"
335         "normal <b>bold </b><i>italic </i><u>underline </u><strike>strike </strike>"
336         "<b><i>boldanditalic </i></b>"
337         "</body></html>";
338
339     test->loadHtml(typingAttributesHTML, nullptr);
340     test->waitUntilLoadFinished();
341     test->flushEditorState();
342     test->setEditable(true);
343
344     unsigned typingAttributes = test->typingAttributes();
345     g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
346
347     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
348     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
349     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
350     typingAttributes = test->waitUntilTypingAttributesChanged();
351     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
352     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
353     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
354     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
355
356     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
357     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
358     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
359     typingAttributes = test->waitUntilTypingAttributesChanged();
360     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
361     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
362     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
363     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
364
365     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
366     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
367     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
368     typingAttributes = test->waitUntilTypingAttributesChanged();
369     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
370     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
371     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
372     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
373
374     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
375     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
376     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
377     typingAttributes = test->waitUntilTypingAttributesChanged();
378     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
379     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
380     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
381     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
382
383     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
384     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
385     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
386     typingAttributes = test->waitUntilTypingAttributesChanged();
387     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
388     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
389     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
390     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
391
392     // Selections.
393     webkit_web_view_execute_editing_command(test->m_webView, "MoveToBeginningOfDocument");
394     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
395     typingAttributes = test->waitUntilTypingAttributesChanged();
396     g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
397
398     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
399     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
400     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
401     typingAttributes = test->waitUntilTypingAttributesChanged();
402     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
403     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
404     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
405     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
406
407     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
408     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
409     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
410     typingAttributes = test->waitUntilTypingAttributesChanged();
411     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
412     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
413     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
414     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
415
416     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
417     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
418     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
419     typingAttributes = test->waitUntilTypingAttributesChanged();
420     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
421     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
422     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
423     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
424
425     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
426     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
427     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
428     typingAttributes = test->waitUntilTypingAttributesChanged();
429     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
430     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
431     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
432     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
433
434     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
435     webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
436     webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
437     typingAttributes = test->waitUntilTypingAttributesChanged();
438     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
439     g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
440     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
441     g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
442
443     webkit_web_view_execute_editing_command(test->m_webView, "SelectAll");
444     typingAttributes = test->waitUntilTypingAttributesChanged();
445     g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
446 }
447
448 static void testWebViewEditorInsertImage(EditorTest* test, gconstpointer)
449 {
450     test->loadHtml("<html><body></body></html>", "file:///");
451     test->waitUntilLoadFinished();
452     test->flushEditorState();
453     test->setEditable(true);
454
455     GUniquePtr<char> imagePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
456     GUniquePtr<char> imageURI(g_filename_to_uri(imagePath.get(), nullptr, nullptr));
457     webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_INSERT_IMAGE, imageURI.get());
458     GUniqueOutPtr<GError> error;
459     WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('IMG')[0].src", &error.outPtr());
460     g_assert(javascriptResult);
461     g_assert(!error);
462     GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
463     g_assert_cmpstr(resultString.get(), ==, imageURI.get());
464 }
465
466 static void testWebViewEditorCreateLink(EditorTest* test, gconstpointer)
467 {
468     test->loadHtml("<html><body onload=\"document.getSelection().selectAllChildren(document.body);\">webkitgtk.org</body></html>", nullptr);
469     test->waitUntilLoadFinished();
470     test->flushEditorState();
471     test->setEditable(true);
472
473     static const char* webkitGTKURL = "http://www.webkitgtk.org/";
474     webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, webkitGTKURL);
475     GUniqueOutPtr<GError> error;
476     WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[0].href;", &error.outPtr());
477     g_assert(javascriptResult);
478     g_assert(!error);
479     GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
480     g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
481     javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[0].innerText;", &error.outPtr());
482     g_assert(javascriptResult);
483     g_assert(!error);
484     resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
485     g_assert_cmpstr(resultString.get(), ==, "webkitgtk.org");
486
487     // When there isn't text selected, the URL is used as link text.
488     webkit_web_view_execute_editing_command(test->m_webView, "MoveToEndOfLine");
489     webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, webkitGTKURL);
490     javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[1].href;", &error.outPtr());
491     g_assert(javascriptResult);
492     g_assert(!error);
493     resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
494     g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
495     javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[1].innerText;", &error.outPtr());
496     g_assert(javascriptResult);
497     g_assert(!error);
498     resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
499     g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
500 }
501
502 void beforeAll()
503 {
504     EditorTest::add("WebKitWebView", "editable/editable", testWebViewEditorEditable);
505     EditorTest::add("WebKitWebView", "cut-copy-paste/non-editable", testWebViewEditorCutCopyPasteNonEditable);
506     EditorTest::add("WebKitWebView", "cut-copy-paste/editable", testWebViewEditorCutCopyPasteEditable);
507     EditorTest::add("WebKitWebView", "select-all/non-editable", testWebViewEditorSelectAllNonEditable);
508     EditorTest::add("WebKitWebView", "select-all/editable", testWebViewEditorSelectAllEditable);
509     EditorTest::add("WebKitWebView", "editor-state/typing-attributes", testWebViewEditorEditorStateTypingAttributes);
510     EditorTest::add("WebKitWebView", "insert/image", testWebViewEditorInsertImage);
511     EditorTest::add("WebKitWebView", "insert/link", testWebViewEditorCreateLink);
512 }
513
514 void afterAll()
515 {
516 }