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