| /* |
| * Copyright (C) 2017 Igalia S.L. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2,1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| #include "WebViewTest.h" |
| |
| #include <wtf/RunLoop.h> |
| |
| class OptionMenuTest : public WebViewTest { |
| public: |
| MAKE_GLIB_TEST_FIXTURE(OptionMenuTest); |
| |
| OptionMenuTest() |
| { |
| g_signal_connect(m_webView, "show-option-menu", G_CALLBACK(showOptionMenuCallback), this); |
| } |
| |
| ~OptionMenuTest() |
| { |
| g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); |
| if (m_menu) |
| close(); |
| } |
| |
| void destroyMenu() |
| { |
| if (!m_menu) |
| return; |
| |
| g_signal_handlers_disconnect_matched(m_menu.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); |
| m_menu = nullptr; |
| } |
| |
| static gboolean showOptionMenuCallback(WebKitWebView* webView, WebKitOptionMenu* menu, GdkEvent* event, GdkRectangle* rect, OptionMenuTest* test) |
| { |
| g_assert_true(test->m_webView == webView); |
| g_assert_nonnull(rect); |
| g_assert_true(WEBKIT_IS_OPTION_MENU(menu)); |
| test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(menu)); |
| test->showOptionMenu(menu, rect); |
| return TRUE; |
| } |
| |
| static void menuCloseCallback(WebKitOptionMenu* menu, OptionMenuTest* test) |
| { |
| g_assert_true(test->m_menu.get() == menu); |
| test->destroyMenu(); |
| } |
| |
| void showOptionMenu(WebKitOptionMenu* menu, GdkRectangle* rect) |
| { |
| m_rectangle = *rect; |
| m_menu = menu; |
| g_signal_connect(m_menu.get(), "close", G_CALLBACK(menuCloseCallback), this); |
| g_main_loop_quit(m_mainLoop); |
| } |
| |
| void clickAtPositionAndWaitUntilOptionMenuShown(int x, int y) |
| { |
| m_menu = nullptr; |
| RunLoop::main().dispatch([this, x, y] { clickMouseButton(x, y); }); |
| g_main_loop_run(m_mainLoop); |
| } |
| |
| void close() |
| { |
| g_assert_nonnull(m_menu.get()); |
| webkit_option_menu_close(m_menu.get()); |
| g_assert_null(m_menu.get()); |
| } |
| |
| void activateItem(unsigned item) |
| { |
| g_assert_nonnull(m_menu.get()); |
| webkit_option_menu_activate_item(m_menu.get(), item); |
| g_assert_nonnull(m_menu.get()); |
| } |
| |
| void selectItem(unsigned item) |
| { |
| g_assert_nonnull(m_menu.get()); |
| webkit_option_menu_select_item(m_menu.get(), item); |
| g_assert_nonnull(m_menu.get()); |
| } |
| |
| GRefPtr<WebKitOptionMenu> m_menu; |
| GdkRectangle m_rectangle; |
| }; |
| |
| static void testOptionMenuSimple(OptionMenuTest* test, gconstpointer) |
| { |
| static const char html[] = |
| "<html><body>" |
| " <select style='position:absolute; left:1; top:10'>" |
| " <option title='The Foo Option'>Foo</option>" |
| " <option selected>Bar</option>" |
| " <option disabled>Baz</option>" |
| " </select></body></html>"; |
| test->showInWindowAndWaitUntilMapped(); |
| test->loadHtml(html, nullptr); |
| test->waitUntilLoadFinished(); |
| |
| test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
| g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
| g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 3); |
| auto* item = webkit_option_menu_get_item(test->m_menu.get(), 0); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Foo"); |
| g_assert_cmpstr(webkit_option_menu_item_get_tooltip(item), ==, "The Foo Option"); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 1); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Bar"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_true(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 2); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Baz"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_false(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| |
| test->close(); |
| g_assert_null(test->m_menu.get()); |
| } |
| |
| static void testOptionMenuGroups(OptionMenuTest* test, gconstpointer) |
| { |
| static const char html[] = |
| "<html><body>" |
| " <select style='position:absolute; left:1; top:10'>" |
| " <option>Root</option>" |
| " <optgroup label='Group 1'>" |
| " <option>Child 1-1</option>" |
| " <option disabled>Child 1-2</option>" |
| " </optgroup>" |
| " <optgroup label='Group 2'>" |
| " <option selected>Child 2-1</option>" |
| " <option>Child 2-2</option>" |
| " </optgroup>" |
| " <option>Tail</option>" |
| " </select></body></html>"; |
| test->showInWindowAndWaitUntilMapped(); |
| test->loadHtml(html, nullptr); |
| test->waitUntilLoadFinished(); |
| |
| test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
| g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
| g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 8); |
| auto* item = webkit_option_menu_get_item(test->m_menu.get(), 0); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Root"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 1); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Group 1"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_true(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_false(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 2); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 1-1"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_true(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 3); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 1-2"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_true(webkit_option_menu_item_is_group_child(item)); |
| g_assert_false(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 4); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Group 2"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_true(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_false(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 5); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 2-1"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_true(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_true(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 6); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Child 2-2"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_true(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| item = webkit_option_menu_get_item(test->m_menu.get(), 7); |
| g_assert_cmpstr(webkit_option_menu_item_get_label(item), ==, "Tail"); |
| g_assert_null(webkit_option_menu_item_get_tooltip(item)); |
| g_assert_false(webkit_option_menu_item_is_group_label(item)); |
| g_assert_false(webkit_option_menu_item_is_group_child(item)); |
| g_assert_true(webkit_option_menu_item_is_enabled(item)); |
| g_assert_false(webkit_option_menu_item_is_selected(item)); |
| } |
| |
| static void testOptionMenuActivate(OptionMenuTest* test, gconstpointer) |
| { |
| static const char html[] = |
| "<html><body>" |
| " <select id='combo' style='position:absolute; left:1; top:10'>" |
| " <option>Foo</option>" |
| " <option>Bar</option>" |
| " <option>Baz</option>" |
| " </select></body></html>"; |
| test->showInWindowAndWaitUntilMapped(); |
| test->loadHtml(html, nullptr); |
| test->waitUntilLoadFinished(); |
| |
| test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
| g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
| g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 3); |
| test->activateItem(1); |
| auto* result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex", nullptr); |
| g_assert_nonnull(result); |
| g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 1); |
| |
| // We should close the menu after activate, further activates will be ignored. |
| test->activateItem(2); |
| result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex", nullptr); |
| g_assert_nonnull(result); |
| g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 1); |
| |
| test->close(); |
| } |
| |
| static void testOptionMenuSelect(OptionMenuTest* test, gconstpointer) |
| { |
| static const char html[] = |
| "<html><body>" |
| " <select id='combo' style='position:absolute; left:1; top:10'>" |
| " <option>Foo</option>" |
| " <option>Bar</option>" |
| " <option>Baz</option>" |
| " </select></body></html>"; |
| test->showInWindowAndWaitUntilMapped(); |
| test->loadHtml(html, nullptr); |
| test->waitUntilLoadFinished(); |
| |
| test->clickAtPositionAndWaitUntilOptionMenuShown(5, 15); |
| g_assert_true(WEBKIT_IS_OPTION_MENU(test->m_menu.get())); |
| g_assert_cmpint(webkit_option_menu_get_n_items(test->m_menu.get()), ==, 3); |
| |
| // Select item changes the combo text, but not the currently selected item. |
| test->selectItem(2); |
| auto* result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex", nullptr); |
| g_assert_nonnull(result); |
| g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 0); |
| |
| // It can be called multiple times. |
| test->selectItem(1); |
| result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex", nullptr); |
| g_assert_nonnull(result); |
| g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 0); |
| |
| // And closing the menu activates the currently selected item. |
| test->close(); |
| result = test->runJavaScriptAndWaitUntilFinished("document.getElementById('combo').selectedIndex", nullptr); |
| g_assert_nonnull(result); |
| g_assert_cmpfloat(WebViewTest::javascriptResultToNumber(result), ==, 1); |
| } |
| |
| void beforeAll() |
| { |
| OptionMenuTest::add("WebKitWebView", "option-menu-simple", testOptionMenuSimple); |
| OptionMenuTest::add("WebKitWebView", "option-menu-groups", testOptionMenuGroups); |
| OptionMenuTest::add("WebKitWebView", "option-menu-activate", testOptionMenuActivate); |
| OptionMenuTest::add("WebKitWebView", "option-menu-select", testOptionMenuSelect); |
| } |
| |
| void afterAll() |
| { |
| } |