Significant changes to use ReactJS extensively.

1. Replace the current layout library wcDocker with ReactJS based rc-dock. #6479
2. Have close buttons on individual panel tabs instead of common. #2821
3. Changes in the context menu on panel tabs - Add close, close all and close others menu items. #5394
4. Allow closing all the tabs, including SQL and Properties. #4733
5. Changes in docking behaviour of different tabs based on user requests and remove lock layout menu.
6. Fix an issue where the scroll position of panels was not remembered on Firefox. #2986
7. Reset layout now will not require page refresh and is done spontaneously.
8. Use the zustand store for storing preferences instead of plain JS objects. This will help reflecting preferences immediately.
9. The above fix incorrect format (no indent) of SQL stored functions/procedures. #6720
10. New version check is moved to an async request now instead of app start to improve startup performance.
11. Remove jQuery and Bootstrap completely.
12. Replace jasmine and karma test runner with jest. Migrate all the JS test cases to jest. This will save time in writing and debugging JS tests.
13. Other important code improvements and cleanup.
This commit is contained in:
Aditya Toshniwal
2023-10-23 17:43:17 +05:30
committed by GitHub
parent 6d555645e9
commit 862f101772
373 changed files with 11149 additions and 14836 deletions

View File

@@ -72,6 +72,7 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
BrowserToolBarLocators.open_query_tool_button_css),
(By.CSS_SELECTOR, BrowserToolBarLocators.query_tool_panel_css)),
'Query tool did not open on clicking Query Tool button.')
self.page.close_query_tool(prompt=False)
def test_view_data_tool_button(self):
@@ -97,7 +98,7 @@ class BrowserToolBarFeatureTest(BaseFeatureTest):
self.assertTrue(self.page.retry_click(
(By.CSS_SELECTOR,
BrowserToolBarLocators.filter_data_button_css),
(By.XPATH, BrowserToolBarLocators.filter_box_css)),
(By.CSS_SELECTOR, BrowserToolBarLocators.filter_box_css)),
'Filter dialogue did not open on clicking filter button.')
self.page.click_modal('Close')
self.page.click_modal('Close', docker=True)
self.page.close_query_tool(prompt=False)

View File

@@ -184,8 +184,8 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
"test_backup", input_keys=True, loose_focus=True)
# Click on the take Backup button
take_bckup = self.page.find_by_xpath(
NavMenuLocators.backup_btn_xpath)
take_bckup = self.page.find_by_css_selector(
NavMenuLocators.backup_btn)
click = True
retry = 3
while click and retry > 0:
@@ -193,8 +193,8 @@ class PGUtilitiesBackupFeatureTest(BaseFeatureTest):
take_bckup.click()
if self.page.wait_for_element_to_disappear(
lambda driver: driver.find_element(
By.XPATH,
"//*[@id='0']/div[contains(text(),'Backup')]")):
By.CSS_SELECTOR,
".dock-fbox div[title^='Backup']")):
click = False
except Exception:
retry -= 1

View File

@@ -79,7 +79,7 @@ class PGUtilitiesMaintenanceFeatureTest(BaseFeatureTest):
def runTest(self):
self._open_maintenance_dialogue()
self.page.click_modal('OK')
self.page.click_modal('OK', docker=True)
self.page.wait_for_element_to_disappear(
lambda driver: driver.find_element(
By.XPATH, NavMenuLocators.maintenance_operation), 10)

View File

@@ -169,7 +169,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.page.click_element(editor_input)
self.page.execute_query(self.select_query % self.invalid_table_name)
self.page.click_tab(self.query_history_tab_id, rc_dock=True)
self.page.click_tab("Query History")
self.page.wait_for_query_tool_loading_indicator_to_disappear(
container_id="id-history")
selected_history_entry = self.page.find_by_css_selector(
@@ -211,7 +211,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.assertIn(self.select_query % self.invalid_table_name,
invalid_history_entry.text)
self.page.click_tab(self.query_editor_tab_id, rc_dock=True)
self.page.click_tab("Query")
self.page.clear_query_tool()
self.page.click_element(editor_input)
@@ -223,7 +223,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
QueryToolLocators.btn_execute_query_css).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab(self.query_history_tab_id, rc_dock=True)
self.page.click_tab("Query History")
query_list = self.page.wait_for_elements(
lambda driver: driver.find_elements(
@@ -237,10 +237,10 @@ class QueryToolJourneyTest(BaseFeatureTest):
self._test_toggle_generated_queries()
def _test_history_query_sources(self):
self.page.click_tab(self.query_editor_tab_id, rc_dock=True)
self.page.click_tab("Query")
self._execute_sources_test_queries()
self.page.click_tab(self.query_history_tab_id, rc_dock=True)
self.page.click_tab("Query History")
history_entries_icons = [
'CommitIcon',
@@ -275,7 +275,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
self.assertTrue(self.page.check_if_element_exist_by_xpath(xpath))
def _test_updatable_resultset(self):
self.page.click_tab(self.query_editor_tab_id, rc_dock=True)
self.page.click_tab("Query")
# Select all data
# (contains the primary key -> all columns should be editable)
@@ -309,7 +309,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
def _test_is_editable_columns_icons(self):
if self.driver_version < 2.8:
return
self.page.click_tab(self.query_editor_tab_id, rc_dock=True)
self.page.click_tab("Query")
self.page.clear_query_tool()
query = "SELECT pk_column FROM %s" % self.test_editable_table_name
@@ -404,7 +404,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
retry -= 1
def _insert_data_into_test_editable_table(self):
self.page.click_tab(self.query_editor_tab_id, rc_dock=True)
self.page.click_tab("Query")
self.page.clear_query_tool()
self.page.execute_query(
"INSERT INTO %s VALUES (1, 1), (2, 2);"
@@ -412,7 +412,7 @@ class QueryToolJourneyTest(BaseFeatureTest):
)
def __clear_query_history(self):
self.page.click_tab(self.query_history_tab_id, rc_dock=True)
self.page.click_tab("Query History")
self.page.wait_for_query_tool_loading_indicator_to_disappear(
container_id="id-history")
self.page.click_element(

View File

@@ -257,7 +257,7 @@ SELECT generate_series(1, 1000) as id order by id desc"""
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab(self.data_output_tab_id, rc_dock=True)
self.page.click_tab("Data Output")
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css))
@@ -292,7 +292,7 @@ SELECT generate_series(1, 1000) as id order by id desc"""
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab(self.data_output_tab_id, rc_dock=True)
self.page.click_tab("Data Output")
self.wait.until(EC.presence_of_element_located(
(By.XPATH, QueryToolLocators.output_cell_xpath.format(2, 2)))
@@ -329,7 +329,7 @@ CREATE TABLE public.{}();""".format(table_name)
self.page.click_execute_query_button()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('CREATE TABLE')),
@@ -343,7 +343,7 @@ CREATE TABLE public.{}();""".format(table_name)
-- 4. Check if table is *NOT* created.
ROLLBACK;"""
self.page.execute_query(query)
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('ROLLBACK')),
"ROLLBACK message does not displayed")
@@ -357,7 +357,7 @@ SELECT relname FROM pg_catalog.pg_class
WHERE relkind IN ('r','s','t') and relnamespace = 2200::oid;"""
self.page.execute_query(query)
self.page.click_tab(self.data_output_tab_id, rc_dock=True)
self.page.click_tab("Data Output")
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
@@ -411,7 +411,7 @@ CREATE TABLE public.{}();""".format(table_name)
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('CREATE TABLE')),
self.table_creation_fail_error)
@@ -426,7 +426,7 @@ ROLLBACK;"""
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('ROLLBACK')),
"ROLLBACK message does not displayed")
@@ -441,7 +441,7 @@ SELECT relname FROM pg_catalog.pg_class
WHERE relkind IN ('r','s','t') and relnamespace = 2200::oid;"""
self.page.execute_query(query)
self.page.click_tab(self.data_output_tab_id, rc_dock=True)
self.page.click_tab("Data Output")
self.page.wait_for_query_tool_loading_indicator_to_disappear()
canvas = self.wait.until(EC.presence_of_element_located(
@@ -490,7 +490,7 @@ END;"""
CREATE TABLE public.{}();""".format(table_name)
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('CREATE TABLE')),
self.table_creation_fail_error)
@@ -505,7 +505,7 @@ CREATE TABLE public.{}();""".format(table_name)
SELECT 1/0;"""
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('division by zero')),
"division by zero message does not displayed")
@@ -520,7 +520,7 @@ SELECT 1/0;"""
END;"""
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.
format('Query returned successfully')),
@@ -537,7 +537,7 @@ SELECT relname FROM pg_catalog.pg_class
WHERE relkind IN ('r','s','t') and relnamespace = 2200::oid;"""
self.page.execute_query(query)
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab(self.data_output_tab_id, rc_dock=True)
self.page.click_tab("Data Output")
canvas = self.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, QueryToolLocators.query_output_canvas_css)))
@@ -580,7 +580,7 @@ SELECT 1, pg_sleep(300)"""
self.page.find_by_css_selector(
QueryToolLocators.btn_cancel_query).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(
self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message
@@ -593,7 +593,7 @@ SELECT 1, pg_sleep(300)"""
def _query_tool_notify_statements(self):
print("\n\tListen on an event... ", file=sys.stderr, end="")
self.page.execute_query("LISTEN foo;")
self.page.click_tab('id-messages', rc_dock=True)
self.page.click_tab('Messages')
self.assertTrue(self.page.check_if_element_exist_by_xpath(
QueryToolLocators.sql_editor_message.format('LISTEN')),
@@ -603,7 +603,7 @@ SELECT 1, pg_sleep(300)"""
print("\tNotify event without data... ", file=sys.stderr, end="")
self.page.execute_query("NOTIFY foo;")
self.page.click_tab('id-notifications', rc_dock=True)
self.page.click_tab('Notifications')
self.wait.until(EC.text_to_be_present_in_element(
(By.CSS_SELECTOR, "td[data-label='channel']"), "foo")
)
@@ -612,7 +612,7 @@ SELECT 1, pg_sleep(300)"""
print("\tNotify event with data... ", file=sys.stderr, end="")
self.page.clear_query_tool()
self.page.execute_query("SELECT pg_notify('foo', 'Hello')")
self.page.click_tab('id-notifications', rc_dock=True)
self.page.click_tab('Notifications')
self.wait.until(WaitForAnyElementWithText(
(By.CSS_SELECTOR, "td[data-label='payload']"), "Hello"))
print("OK.", file=sys.stderr)

View File

@@ -171,9 +171,9 @@ CREATE TABLE public.nonintpkey
self._copy_paste_row(config_data_local)
self._update_row(config_data_local)
self.page.click_tab("id-messages", rc_dock=True)
self.page.click_tab("Messages")
self._verify_messsages("")
self.page.click_tab("id-dataoutput", rc_dock=True)
self.page.click_tab("Data Output")
updated_row_data = {
i: config_data_local['update'][i] if i in config_data_local[
'update'] else val
@@ -182,7 +182,7 @@ CREATE TABLE public.nonintpkey
self._verify_row_data(row=1,
config_check_data=updated_row_data)
self.page.close_data_grid()
self.page.close_query_tool(prompt=False)
def _compare_cell_value(self, xpath, value):
# Initialize an instance of WebDriverWait with timeout of 5 seconds

View File

@@ -78,7 +78,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
# Query tool view/edit data
self.page.open_view_data(self.test_db)
self._check_xss_view_data()
self.page.close_data_grid()
self.page.close_query_tool(prompt=False)
# Explain module
self.page.open_query_tool()
@@ -110,7 +110,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
)
# Fetch the inner html & check for escaped characters
source_code = self.page.find_by_xpath(
"//*[@id='tree']"
"//*[@id='id-object-explorer']"
).get_attribute('innerHTML')
self._check_escaped_characters(
@@ -156,10 +156,10 @@ class CheckForXssFeatureTest(BaseFeatureTest):
try:
self.page.click_tab("Dependents")
source_code = \
self.page.find_by_xpath(
"//*[@id='5']/table/tbody/tr/td/div/div/div[2]/div"
"/div[2]/div[1]/div/div/div/div/"
"div/div[2]").get_attribute('innerHTML')
self.page.find_by_css_selector(
"#id-dependents div[role='row']:nth-child(1) "
"div[role='cell']:nth-child(2)"
).get_attribute('innerHTML')
retry = 0
except WebDriverException as e:
print("Exception in dependent tab {0}".format(retry),
@@ -208,7 +208,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
self.page.find_by_css_selector(
QueryToolLocators.btn_execute_query_css).click()
self.page.click_tab('id-history', rc_dock=True)
self.page.click_tab('Query History')
# Check for history entry
history_ele = self.page\
@@ -240,7 +240,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
"Query tool (History Details-Message)"
)
self.page.click_tab('id-query', rc_dock=True)
self.page.click_tab('Query')
def _check_xss_view_data(self):
print(
@@ -272,7 +272,7 @@ class CheckForXssFeatureTest(BaseFeatureTest):
self.page.find_by_css_selector(
QueryToolLocators.btn_explain).click()
self.page.wait_for_query_tool_loading_indicator_to_disappear()
self.page.click_tab('id-explain', rc_dock=True)
self.page.click_tab('Explain')
for idx in range(3):
# Re-try logic

View File

@@ -123,7 +123,7 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
# Only this tab is vulnerable rest are Code Mirror
# control which are already tested in Query tool test case
self.page.click_tab('id-debugger-messages', rc_dock=True)
self.page.click_tab('Messages')
source_code = self.page.find_by_xpath(
"//div[@id='id-debugger-messages'] //div[@id='debugger-msg']"
).get_attribute('innerHTML')
@@ -139,10 +139,9 @@ class CheckDebuggerForXssFeatureTest(BaseFeatureTest):
def _close_debugger(self):
self.page.driver.switch_to.default_content()
self.page.click_element(
self.page.find_by_xpath(
"//*[@id='dockerContainer']/div/div[3]/div/div[2]/div[1]")
)
self.page.find_by_css_selector("div[data-dockid='id-main'] "
".dock-tab.dock-tab-active "
"button[data-label='Close']").click()
def _check_escaped_characters(self, source_code, string_to_find, source):
# For XSS we need to search against element's html code

View File

@@ -80,7 +80,8 @@ class CheckRoleMembershipControlFeatureTest(BaseFeatureTest):
# Fetch the source code for our custom control
source_code = self.page.find_by_xpath(
"//span[contains(@class,'icon-')]/following-sibling::span"
"//div[contains(@role, 'cell')]//span[contains(@class,'icon-')]"
"/following-sibling::span"
).get_attribute('innerHTML')
self._check_escaped_characters(