diff --git a/web/pgadmin/feature_tests/datatype_test.json b/web/pgadmin/feature_tests/datatype_test.json new file mode 100644 index 0000000..49556b0 --- /dev/null +++ b/web/pgadmin/feature_tests/datatype_test.json @@ -0,0 +1,173 @@ +[ + { + "datatype": [ + "smallint", + "smallint", + "integer", + "integer", + "bigint", + "bigint", + "decimal", + "decimal", + "numeric", + "numeric", + "float[]", + "float[]", + "real", + "real[]", + "bytea", + "bytea[]" + ], + "input":[ + "-32767", + "32767", + "-2147483647", + "2147483647", + "-9223372036854775807", + "9223372036854775807", + "922337203685.4775807", + "92203685.477", + "922337203685.922337203685", + "-92233720368547758.08", + "ARRAY[1, 2, 3]", + "ARRAY['nan', 'nan', 'nan']", + "'Infinity'", + "'{Infinity}'", + "'E\\\\xDEADBEEF'", + "ARRAY['E\\\\xDEADBEEF', 'E\\\\xDEADBEEF']" + ], + "output":[ + "-32767", + "32767", + "-2147483647", + "2147483647", + "-9223372036854775807", + "9223372036854775807", + "922337203685.4775807", + "92203685.477", + "922337203685.922337203685", + "-92233720368547758.08", + "{1,2,3}", + "{NaN,NaN,NaN}", + "Infinity", + "{Infinity}", + "[binary data]", + "[binary data[]]" + ] + }, + { + "datatype": [ + "int4range", + "int8range", + "numrange", + "daterange", + "tsrange", + "tstzrange", + "int4range[]", + "int8range[]", + "numrange[]", + "daterange[]", + "tsrange[]", + "tstzrange[]", + "int8range[]", + "daterange[]", + "tstzrange[]", + "", + "" + ], + "input":[ + "'(1,2147483647)'", + "'(2,9223372036854775807)'", + "'(3,922337203685.922337203685]'", + "'(2010-01-01, 2010-02-01]'", + "'[2010-01-01 14:00, 2010-04-01 15:00)'", + "'[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)'", + "'{\"(1,2147483647)\", \"(2,2147483647)\"}'", + "'{\"(2,9223372036854775807)\", \"(2,9223372036854775807)\"}'", + "'{\"(3,922337203685.922337203685]\", \"(5,922337203685.922337203685]\"}'", + "'{\"(2010-01-01, 2010-02-01]\", \"(2010-01-01, 2010-02-01]\"}'", + "'{\"[2010-01-01 14:00, 2010-04-01 15:00)\", \"[2010-01-01 14:00, 2010-04-01 15:00)\"}'", + "'{\"[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)\", \"[2017-12-12 14:00:00+05:30, 2017-12-30 15:00:00+05:30)\"}'", + "'{{\"(2,9223372036854775807)\", \"(2,9223372036854775807)\"},{\"(2,9223372036854775807)\", \"(2,9223372036854775807)\"}}'", + "'{{\"(2010-01-01, 2010-02-01]\", \"(2010-01-01, 2010-02-01]\"},{\"(2010-01-01, 2010-02-01]\", \"(2010-01-01, 2010-02-01]\"}}'", + "'{{\"[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)\", \"[2017-12-12 14:00:00+05:30, 2017-12-30 15:00:00+05:30)\"}, {\"[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)\", \"[2017-12-12 14:00:00+05:30, 2017-12-30 15:00:00+05:30)\"}}'", + "enum_range(NULL::rainbow)", + "ARRAY[enum_range(NULL::rainbow), enum_range(NULL::rainbow)]" + ], + "output":[ + "[2,2147483647)", + "[3,9223372036854775807)", + "(3,922337203685.922337203685]", + "[2010-01-02,2010-02-02)", + "[\"2010-01-01 14:00:00\",\"2010-04-01 15:00:00\")", + "[\"2010-01-01 14:00:00+05:30\",\"2010-06-01 15:00:00+05:30\")", + "{\"[2,2147483647)\",\"[3,2147483647)\"}", + "{\"[3,9223372036854775807)\",\"[3,9223372036854775807)\"}", + "{\"(3,922337203685.922337203685]\",\"(5,922337203685.922337203685]\"}", + "{\"[2010-01-02,2010-02-02)\",\"[2010-01-02,2010-02-02)\"}", + "{\"[\\\"2010-01-01 14:00:00\\\",\\\"2010-04-01 15:00:00\\\")\",\"[\\\"2010-01-01 14:00:00\\\",\\\"2010-04-01 15:00:00\\\")\"}", + "{\"[\\\"2010-01-01 14:00:00+05:30\\\",\\\"2010-06-01 15:00:00+05:30\\\")\",\"[\\\"2017-12-12 14:00:00+05:30\\\",\\\"2017-12-30 15:00:00+05:30\\\")\"}", + "{{\"[3,9223372036854775807)\",\"[3,9223372036854775807)\"},{\"[3,9223372036854775807)\",\"[3,9223372036854775807)\"}}", + "{{\"[2010-01-02,2010-02-02)\",\"[2010-01-02,2010-02-02)\"},{\"[2010-01-02,2010-02-02)\",\"[2010-01-02,2010-02-02)\"}}", + "{{\"[\\\"2010-01-01 14:00:00+05:30\\\",\\\"2010-06-01 15:00:00+05:30\\\")\",\"[\\\"2017-12-12 14:00:00+05:30\\\",\\\"2017-12-30 15:00:00+05:30\\\")\"},{\"[\\\"2010-01-01 14:00:00+05:30\\\",\\\"2010-06-01 15:00:00+05:30\\\")\",\"[\\\"2017-12-12 14:00:00+05:30\\\",\\\"2017-12-30 15:00:00+05:30\\\")\"}}", + "{red,orange,yellow,green,blue,purple}", + "{{red,orange,yellow,green,blue,purple},{red,orange,yellow,green,blue,purple}}" + ] + }, + { + "datatype": [ + "inet", + "inet[]", + "inet[]", + "cidr", + "cidr[]", + "cidr[]", + "uuid", + "uuid[]", + "xml", + "xml[]", + "bit", + "bit[]", + "varbit", + "varbit[]", + "macaddr", + "macaddr[]" + ], + "input":[ + "'::2'", + "'{\"::2\",\"192.168.1.1/16\",\"FFF0:0:007a::\"}'", + "'{{\"::2\",\"192.168.1.1/16\",\"FFF0:0:007a::\"},{\"::2\",\"192.168.1.1/16\",\"FFF0:0:007a::\"}}'", + "'::1'", + "'{\"::1\", \"192.168.100.128/25\", \"FFF0:0:007a::\"}'", + "'{{\"::1\", \"192.168.100.128/25\", \"FFF0:0:007a::\"},{\"::1\", \"192.168.100.128/25\", \"FFF0:0:007a::\"}}'", + "'e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c'", + "'{55f8e502-e0b4-11e7-80c1-9a214cf093ae, e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c}'", + "'pgAdmin 4'", + "'{\"pgAdmin 4\", \"pgAdmin 4\"}'", + "'1'", + "'{0,1}'", + "'1001'", + "'{10010,1011}'", + "'08:00:2b:01:02:03'", + "'{08:00:2b:01:02:03, 08-00-2b-01-02-03, 08002b:010203, 08002b-010203, 0800.2b01.0203, 0800-2b01-0203, 08002b010203}'" + ], + "output":[ + "::2", + "{::2,192.168.1.1/16,fff0:0:7a::}", + "{{::2,192.168.1.1/16,fff0:0:7a::},{::2,192.168.1.1/16,fff0:0:7a::}}", + "::1/128", + "{::1/128,192.168.100.128/25,fff0:0:7a::/128}", + "{{::1/128,192.168.100.128/25,fff0:0:7a::/128},{::1/128,192.168.100.128/25,fff0:0:7a::/128}}", + "e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c", + "{55f8e502-e0b4-11e7-80c1-9a214cf093ae,e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c}", + "pgAdmin 4", + "{\"pgAdmin 4\",\"pgAdmin 4\"}", + "1", + "{0,1}", + "1001", + "{10010,1011}", + "08:00:2b:01:02:03", + "{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}" + ] + } +] \ No newline at end of file diff --git a/web/pgadmin/feature_tests/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py index 75993a4..70fd6cd 100644 --- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py +++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py @@ -7,14 +7,26 @@ # ########################################################################## +import os +import json from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By +from selenium.webdriver import ActionChains from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest +CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) + +try: + with open(CURRENT_PATH + '/datatype_test.json') as data_file: + config_data = json.load(data_file) +except Exception as e: + print(str(e)) + + class PGDataypeFeatureTest(BaseFeatureTest): """ This feature test will test the different Postgres @@ -35,6 +47,55 @@ class PGDataypeFeatureTest(BaseFeatureTest): test_utils.drop_database(connection, "acceptance_test_db") test_utils.create_database(self.server, "acceptance_test_db") + # For this test case we need to set "Insert bracket pairs?" + # SQL Editor preference to 'false' to avoid codemirror + # to add matching closing bracket by it self. + self._update_preferences() + + def _update_preferences(self): + self.page.find_by_id("mnu_file").click() + self.page.find_by_id("mnu_preferences").click() + wait = WebDriverWait(self.page.driver, 10) + + wait.until(EC.presence_of_element_located( + (By.XPATH, "//*[contains(string(), 'Show system objects?')]")) + ) + + self.page.find_by_css_selector(".ajs-maximize").click() + + sql_editor = self.page.find_by_xpath( + "//*[contains(@class,'aciTreeLi') and contains(.,'SQL Editor')]") + + sql_editor.find_element_by_xpath( + "//*[contains(@class,'aciTreeText') and contains(.,'Options')]")\ + .click() + + insert_bracket_pairs_control= self.page.find_by_xpath( + "//div[contains(@class,'pgadmin-control-group') and contains(.,'Insert bracket pairs?')]") + + switch_btn = insert_bracket_pairs_control.\ + find_element_by_class_name('bootstrap-switch') + + # check if switch is on then only toggle. + if 'bootstrap-switch-on' in switch_btn.get_attribute('class'): + switch_btn.click() + + # save and close the preference dialog. + self.page.find_by_xpath( + "//*[contains(@class,'btn-primary') and contains(.,'OK')]").click() + + self.page.wait_for_element_to_disappear( + lambda driver: driver.find_element_by_css_selector(".ajs-modal") + ) + + def _create_enum_type(self): + query = """CREATE TYPE public.rainbow AS ENUM ('red', 'orange', + 'yellow','green','blue','purple'); + """ + self.page.fill_codemirror_area_with(query) + self.page.find_by_id("btn-flash").click() + self._clear_query_tool() + def runTest(self): self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) @@ -60,59 +121,79 @@ class PGDataypeFeatureTest(BaseFeatureTest): self.page.toggle_open_tree_item('acceptance_test_db') def _check_datatype(self): - query = r"SELECT -32767::smallint, 32767::smallint," \ - r"-2147483647::integer, 2147483647::integer," \ - r"9223372036854775807::bigint, 9223372036854775807::bigint," \ - r"922337203685.4775807::decimal, 92203685.477::decimal," \ - r"922337203685.922337203685::numeric, " \ - r"-92233720368547758.08::numeric," \ - r"ARRAY[1, 2, 3]::float[], ARRAY['nan', 'nan', 'nan']::float[]," \ - r"'Infinity'::real, '{Infinity}'::real[]," \ - r"E'\\xDEADBEEF'::bytea, ARRAY[E'\\xDEADBEEF', E'\\xDEADBEEF']::bytea[];" - - expected_output = [ - '-32767', '32767', '-2147483647', '2147483647', - '9223372036854775807', '9223372036854775807', - '922337203685.4775807', '92203685.477', - '922337203685.922337203685', '-92233720368547758.08', - '{1,2,3}', '{NaN,NaN,NaN}', - 'Infinity', '{Infinity}', - 'binary data', 'binary data[]' - ] - + # Slick grid does not render all the column if viewport is not enough + # wide. So execute test as batch of queries. self.page.open_query_tool() - self.page.fill_codemirror_area_with(query) - self.page.find_by_id("btn-flash").click() - wait = WebDriverWait(self.page.driver, 5) + self._create_enum_type() + for batch in config_data: + query = self.construct_select_query(batch) + self.page.fill_codemirror_area_with(query) + self.page.find_by_id("btn-flash").click() + wait = WebDriverWait(self.page.driver, 5) + + wait.until(EC.presence_of_element_located( + (By.XPATH, + "//*[contains(@class,'column-type') and contains(.,'{}')]".format(batch['datatype'][0]) + )) + ) - canvas = wait.until(EC.presence_of_element_located( - (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) - ) + canvas = wait.until(EC.presence_of_element_located( + (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) + ) - # For every sample data-type value, check the expected output. - cnt = 2 - cells = canvas.find_elements_by_css_selector('.slick-cell') - # remove first element as it is row number. - cells.pop(0) - for val, cell in zip(expected_output, cells): - try: - source_code = cell.text - - PGDataypeFeatureTest.check_result( - source_code, - expected_output[cnt - 2] - ) - cnt += 1 - except TimeoutException: - assert False, "{0} does not match with {1}".format( - val, expected_output[cnt] - ) + # For every sample data-type value, check the expected output. + cnt = 2 + cells = canvas.find_elements_by_css_selector('.slick-cell') + # remove first element as it is row number. + cells.pop(0) + for val, cell, datatype in zip(batch['output'], cells, batch['datatype']): + try: + source_code = cell.text + PGDataypeFeatureTest.check_result( + datatype, + source_code, + batch['output'][cnt - 2] + ) + cnt += 1 + except TimeoutException: + assert False,\ + "for datatype {0}\n{1} does not match with {2}".format( + datatype, val, batch['output'][cnt] + ) + self._clear_query_tool() @staticmethod - def check_result(source_code, string_to_find): - assert source_code.find(string_to_find) != -1,\ - "{0} does not match with {1}".format( - source_code, string_to_find - ) + def construct_select_query(batch): + query = 'SELECT ' + first = True + for datatype, input in zip(batch['datatype'], batch['input']): + if datatype != '': + dataformatter = '{}::{}' + else: + dataformatter = '{}' + + if first: + query += dataformatter.format(input, datatype) + else: + query += ','+dataformatter.format(input, datatype) + first = False + return query + ';' + @staticmethod + def check_result(datatype, source_code, string_to_find): + assert source_code == string_to_find,\ + "for datatype {0}\n{1} does not match with {2}".format( + datatype, source_code, string_to_find + ) + def _clear_query_tool(self): + self.page.click_element( + self.page.find_by_xpath("//*[@id='btn-clear-dropdown']") + ) + ActionChains(self.driver)\ + .move_to_element(self.page.find_by_xpath("//*[@id='btn-clear']"))\ + .perform() + self.page.click_element( + self.page.find_by_xpath("//*[@id='btn-clear']") + ) + self.page.click_modal('Yes') diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py index 26e10cd..255842f 100644 --- a/web/regression/feature_utils/pgadmin_page.py +++ b/web/regression/feature_utils/pgadmin_page.py @@ -226,6 +226,19 @@ class PgadminPage: return self._wait_for("element to exist", element_if_it_exists) + def wait_for_element_to_disappear(self, find_method_with_args): + def element_if_it_disappears(driver): + try: + element = find_method_with_args(driver) + if element.is_displayed() and element.is_enabled(): + return False + + return True + except NoSuchElementException: + return True + + return self._wait_for("element to disappear", element_if_it_disappears) + def wait_for_reloading_indicator_to_disappear(self): def reloading_indicator_has_disappeared(driver): try: