blob: 57c1c9d32793817eb3464eab297c2e45893c8ef1 [file] [log] [blame]
/*
* 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()
{
}