Example #1
0
    def testPublishLayersDialog(self):
        # test the content of the GUI
        for idx, ws in enumerate(self.cat.get_workspaces()):
            if ws.name == WORKSPACE:
                wsIdx = idx
            if ws.name == WORKSPACEB:
                wsIdxB = idx
        dialog = PublishLayersDialog(self.cat)
        self.assertEquals(5, dialog.table.columnCount())
        self.assertEquals(8, dialog.table.rowCount())

        # test that cancel return an empty list of layer to publish
        dialog = PublishLayersDialog(self.cat)
        cancelWidget = dialog.buttonBox.button(dialog.buttonBox.Cancel)
        QTest.mouseClick(cancelWidget, Qt.LeftButton)
        self.assertIsNone(dialog.topublish)

        # check that returned layers in the correct workspaces
        # step 1: set first two layer to publish
        dialog.table.item(0,0).setCheckState(Qt.Checked)
        dialog.table.item(1,0).setCheckState(Qt.Checked)
        # step 2: set WS where to publish
        dialog.table.cellWidget(0,1).setCurrentIndex(wsIdx)
        dialog.table.cellWidget(1,1).setCurrentIndex(wsIdxB)
        # step 3: press ok
        okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
        QTest.mouseClick(okWidget, Qt.LeftButton)
        # step 4: last check
        self.assertIsNotNone(dialog.topublish)
        self.assertEquals(WORKSPACE, dialog.topublish[0][1].name)
        self.assertEquals(WORKSPACEB, dialog.topublish[1][1].name)
Example #2
0
    def test_full_success(self):
        """Test the full workflow from opening the dialog to requesting geocoding"""

        # need to import here so that there's already an initialized QGIS app
        from quick_api.gui.quick_api_dialog import QuickApiDialog
        from quick_api.core.maptool import PointTool

        # first set up a project
        CRS = QgsCoordinateReferenceSystem.fromEpsgId(3857)
        project = QgsProject.instance()
        CANVAS.setExtent(QgsRectangle(1469703, 6870031, 1506178, 6907693))
        CANVAS.setDestinationCrs(CRS)

        # Create and open the dialog
        dlg = QuickApiDialog(IFACE)
        dlg.open()
        self.assertTrue(dlg.isVisible())

        # Click the map button which should hide the dialog
        map_button: QPushButton = dlg.map_button
        QTest.mouseClick(map_button, Qt.LeftButton)
        self.assertFalse(dlg.isVisible())
        self.assertIsInstance(CANVAS.mapTool(), PointTool)

        # Click in the map canvas, which should return the clicked coord,
        # make the dialog visible again
        map_releases = QgsMapMouseEvent(
            CANVAS,
            QEvent.MouseButtonRelease,
            QPoint(0, 0),
            Qt.LeftButton,
            Qt.LeftButton,
            Qt.NoModifier,
        )
        dlg.point_tool.canvasReleaseEvent(map_releases)
        self.assertRegex(dlg.lineedit_xy.text(), r"^(\d+\.\d+.+\d+\.\d+)$")
        self.assertTrue(dlg.isVisible())

        # Clicking the OK button should load the Nominatim result layer
        QTest.mouseClick(dlg.button_box.button(QDialogButtonBox.Ok),
                         Qt.LeftButton)
        layers = project.mapLayers(validOnly=True)
        self.assertEqual(len(layers), 1)

        result_layer: QgsVectorLayer = list(layers.values())[0]

        # Also should be only one feature
        result_features: QgsFeatureIterator = result_layer.getFeatures()
        feat: QgsFeature = next(result_features)
        self.assertRaises(StopIteration, next, result_features)

        # Test the attributes and geometry
        self.assertIn("Havelland,", feat["address"])
        self.assertIn("OpenStreetMap contributors", feat["license"])
        self.assertAlmostEqual(feat.geometry().asPoint().x(),
                               12.703847,
                               delta=1.0)
        self.assertAlmostEqual(feat.geometry().asPoint().y(),
                               52.590965,
                               delta=1.0)
Example #3
0
    def testPublishLayersDialog(self):
        # test the content of the GUI
        for idx, ws in enumerate(self.cat.get_workspaces()):
            if ws.name == WORKSPACE:
                wsIdx = idx
            if ws.name == WORKSPACEB:
                wsIdxB = idx
        dialog = PublishLayersDialog(self.cat)
        self.assertEquals(5, dialog.table.columnCount())
        self.assertEquals(8, dialog.table.rowCount())

        # test that cancel return an empty list of layer to publish
        dialog = PublishLayersDialog(self.cat)
        cancelWidget = dialog.buttonBox.button(dialog.buttonBox.Cancel)
        QTest.mouseClick(cancelWidget, Qt.LeftButton)
        self.assertIsNone(dialog.topublish)

        # check that returned layers in the correct workspaces
        # step 1: set first two layer to publish
        dialog.table.item(0, 0).setCheckState(Qt.Checked)
        dialog.table.item(1, 0).setCheckState(Qt.Checked)
        # step 2: set WS where to publish
        dialog.table.cellWidget(0, 1).setCurrentIndex(wsIdx)
        dialog.table.cellWidget(1, 1).setCurrentIndex(wsIdxB)
        # step 3: press ok
        okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
        QTest.mouseClick(okWidget, Qt.LeftButton)
        # step 4: last check
        self.assertIsNotNone(dialog.topublish)
        self.assertEquals(WORKSPACE, dialog.topublish[0][1].name)
        self.assertEquals(WORKSPACEB, dialog.topublish[1][1].name)
Example #4
0
    def test_mouse_drag(self):
        """Test setting extents by dragging works.

        This currently fails as QTest does not properly do the mouse
        interactions with the canvas.

        """
        # Imported here because it is not available in OSX QGIS bundle
        # pylint: disable=redefined-outer-name
        from qgis.PyQt.QtTest import QTest

        # Click the capture button
        QTest.mouseClick(self.dialog.capture_button, Qt.LeftButton)

        # drag a rect on the canvas
        QTest.mousePress(CANVAS, Qt.LeftButton, pos=QPoint(0, 0), delay=500)
        QTest.mouseRelease(
            CANVAS, Qt.LeftButton,
            pos=QPoint(300, 300),
            delay=-1)

        # on drag the extents selector windows should appear again
        QTest.qWaitForWindowExposed(self.dialog)
        # Click ok to dispose of the window again
        ok = self.dialog.button_box.button(QtWidgets.QDialogButtonBox.Ok)
        QTest.mouseClick(ok, Qt.LeftButton)

        # Check the extent emitted on closing teh dialog is correct
        expected_extent = QgsRectangle(10.0, 10.0, 30.0, 20.0)
        self.assertEqual(self.extent.toString(), expected_extent.toString())
Example #5
0
 def testLoginNoPasswordNoEmail(self):
     # Test login without email and without password
     d = DlgSettingsLogin()
     d.email.setText('')
     d.password.setText('')
     okWidget = d.buttonBox.button(d.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertFalse(d.ok)
Example #6
0
 def testSelectAllButton(self):
     dialog = LayerGroupDialog(self.cat)
     QTest.mouseClick(dialog.selectAllButton, Qt.LeftButton)
     for i in range(dialog.table.rowCount()):
         self.assertTrue(dialog.table.cellWidget(i, 0).isChecked())
     QTest.mouseClick(dialog.selectAllButton, Qt.LeftButton)
     for i in range(dialog.table.rowCount()):
         self.assertFalse(dialog.table.cellWidget(i, 0).isChecked())
Example #7
0
 def testSelectAllButton(self):
     dialog = LayerGroupDialog(self.cat)
     QTest.mouseClick(dialog.selectAllButton, Qt.LeftButton)
     for i in range(dialog.table.rowCount()):
         self.assertTrue(dialog.table.cellWidget(i, 0).isChecked())
     QTest.mouseClick(dialog.selectAllButton, Qt.LeftButton)
     for i in range(dialog.table.rowCount()):
         self.assertFalse(dialog.table.cellWidget(i, 0).isChecked())
Example #8
0
    def test_full_failure(self):
        """Test failing request"""

        # need to import here so that there's already an initialized QGIS app
        from quick_api.gui.quick_api_dialog import QuickApiDialog
        from quick_api.core.maptool import PointTool

        # first set up a project
        CRS = QgsCoordinateReferenceSystem.fromEpsgId(3857)
        project = QgsProject.instance()
        project.setCrs(CRS)
        CANVAS.setExtent(QgsRectangle(258889, 7430342, 509995, 7661955))
        CANVAS.setDestinationCrs(CRS)

        # Create and open the dialog
        dlg = QuickApiDialog(IFACE)
        dlg.open()
        self.assertTrue(dlg.isVisible())

        # Click the map button which should hide the dialog
        map_button: QPushButton = dlg.map_button
        QTest.mouseClick(map_button, Qt.LeftButton)
        self.assertFalse(dlg.isVisible())
        self.assertIsInstance(CANVAS.mapTool(), PointTool)

        # Click in the map canvas, which should return the clicked coord,
        # make the dialog visible again
        map_releases = QgsMapMouseEvent(
            CANVAS,
            QEvent.MouseButtonRelease,
            QPoint(0, 0),  # Relative to the canvas' dimensions
            Qt.LeftButton,
            Qt.LeftButton,
            Qt.NoModifier,
        )
        dlg.point_tool.canvasReleaseEvent(map_releases)
        self.assertRegex(dlg.lineedit_xy.text(), r"^(\d+\.\d+.+\d+\.\d+)$")
        self.assertTrue(dlg.isVisible())

        # Clicking the OK button should result in a QMessageBox.critical dialog
        def handle_msgbox():
            msgbox: QMessageBox = QApplication.activeWindow()
            self.assertIsInstance(msgbox, QMessageBox)
            self.assertIn("Unable to geocode", msgbox.text())
            QTest.mouseClick(msgbox.button(QMessageBox.Ok), Qt.LeftButton)

        # Time the MsgBox test to 7000 ms after clicking
        # the OK button (Nominatim rate limiting for ~6 secs..)
        QTimer.singleShot(7000, handle_msgbox)
        QTest.mouseClick(dlg.button_box.button(QDialogButtonBox.Ok),
                         Qt.LeftButton)

        # No layers produced
        layers = project.mapLayers(validOnly=True)
        self.assertEqual(len(layers), 0)
Example #9
0
 def testLoginValid(self):
     #TODO: pass if there is no internet
     # Test valid login
     d = DlgSettingsLogin()
     d.email.setText(regular_keys['email'])
     d.password.setText(regular_keys['password'])
     self.assertEquals(regular_keys['email'], d.email.text())
     self.assertEquals(regular_keys['password'], d.password.text())
     okWidget = d.buttonBox.button(d.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertTrue(d.ok)
Example #10
0
    def test_spinboxes(self):
        """Test validate extent method."""
        self.dialog.x_maximum.clear()
        self.dialog.extent_defined.connect(self.extent_defined)
        QTest.mouseClick(self.dialog.x_maximum, Qt.LeftButton)
        QTest.keyClick(self.dialog.x_maximum, '3')
        QTest.keyClick(self.dialog.x_maximum, '0')
        ok = self.dialog.button_box.button(QtWidgets.QDialogButtonBox.Ok)
        QTest.mouseClick(ok, Qt.LeftButton)

        expected_extent = QgsRectangle(10.0, 10.0, 30.0, 20.0)
        self.assertEqual(self.extent.toString(), expected_extent.toString())
    def testLogin(self):
        # Test valid login
        d = DlgSettingsLogin()
        d.email.setText(regular_keys['email'])
        d.password.setText(regular_keys['password'])
        self.assertEquals(regular_keys['email'], d.email.text())
        self.assertEquals(regular_keys['password'], d.password.text())
        okWidget = d.buttonBox.button(d.buttonBox.Ok)
        QTest.mouseClick(okWidget, Qt.LeftButton)
        self.assertTrue(d.ok)

        # Test login without email
        d = DlgSettingsLogin()
        d.email.setText('')
        d.password.setText(regular_keys['password'])
        okWidget = d.buttonBox.button(d.buttonBox.Ok)
        QTest.mouseClick(okWidget, Qt.LeftButton)
        self.assertFalse(d.ok)

        # Test login without password
        d = DlgSettingsLogin()
        d.email.setText(regular_keys['email'])
        d.password.setText('')
        okWidget = d.buttonBox.button(d.buttonBox.Ok)
        QTest.mouseClick(okWidget, Qt.LeftButton)
        self.assertFalse(d.ok)

        # Test login without email and without password
        d = DlgSettingsLogin()
        d.email.setText('')
        d.password.setText('')
        okWidget = d.buttonBox.button(d.buttonBox.Ok)
        QTest.mouseClick(okWidget, Qt.LeftButton)
        self.assertFalse(d.ok)
Example #12
0
 def testCreateCatalogDialogUsingExistingName(self):
     self.explorer.catalogs()["name"] = self.cat
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     dialog.nameBox.setText("name")
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertEquals("name_2", dialog.name)
     settings = QSettings()
     settings.beginGroup("/GeoServer/Catalogs/name")
     settings.remove("")
     settings.endGroup()
     settings.beginGroup("/GeoServer/Catalogs/name_2")
     settings.remove("")
     settings.endGroup()
     del self.explorer.catalogs()["name"]
Example #13
0
 def testCreateCatalogDialogUsingExistingName(self):
     self.explorer.catalogs()["name"] = self.cat
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     dialog.nameBox.setText("name")
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertEquals("name_2", dialog.name)
     settings = QSettings()
     settings.beginGroup("/GeoServer/Catalogs/name")
     settings.remove("")
     settings.endGroup()
     settings.beginGroup("/GeoServer/Catalogs/name_2")
     settings.remove("")
     settings.endGroup()
     del self.explorer.catalogs()["name"]
Example #14
0
 def testCreateCatalogDialogWithUrlWithoutProtocol(self):
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     dialog.nameBox.setText("name")
     dialog.urlBox.setText(geoserverLocation()+"/geoserver")
     dialog.passwordBox.setText("password")
     dialog.usernameBox.setText("username")
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertTrue(dialog.ok)
     self.assertEquals("username", dialog.username)
     self.assertEquals("password", dialog.password)
     self.assertEquals("name", dialog.name)
     self.assertEquals("http://"+geoserverLocation()+"/geoserver/rest", dialog.url)
     settings = QSettings()
     settings.endGroup()
     settings.beginGroup("/GeoServer/Catalogs/name")
     settings.remove("")
     settings.endGroup()
Example #15
0
 def testCreateCatalogDialogWithUrlWithoutProtocol(self):
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     dialog.nameBox.setText("name")
     dialog.urlBox.setText(geoserverLocation() + "/geoserver")
     dialog.passwordBox.setText("password")
     dialog.usernameBox.setText("username")
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertTrue(dialog.ok)
     self.assertEquals("username", dialog.username)
     self.assertEquals("password", dialog.password)
     self.assertEquals("name", dialog.name)
     self.assertEquals("http://" + geoserverLocation() + "/geoserver/rest",
                       dialog.url)
     settings = QSettings()
     settings.endGroup()
     settings.beginGroup("/GeoServer/Catalogs/name")
     settings.remove("")
     settings.endGroup()
Example #16
0
 def testLastCatalogNameIsShownByDefault(self):
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     dialog.nameBox.setText("catalogname")
     dialog.urlBox.setText("localhost:8081/geoserver")
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertTrue(dialog.ok)
     self.assertEquals("catalogname", dialog.name)
     self.assertEquals("http://localhost:8081/geoserver/rest", dialog.url)
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     self.assertEquals("catalogname", dialog.nameBox.text())
     self.assertEquals("localhost:8081/geoserver", dialog.urlBox.text())
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     settings = QSettings()
     settings.endGroup()
     settings.beginGroup("/GeoServer/Catalogs/catalogname")
     settings.remove("")
     settings.endGroup()
Example #17
0
 def testLastCatalogNameIsShownByDefault(self):
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     dialog.nameBox.setText("catalogname")
     dialog.urlBox.setText("localhost:8081/geoserver")
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     self.assertTrue(dialog.ok)
     self.assertEquals("catalogname", dialog.name)
     self.assertEquals("http://localhost:8081/geoserver/rest", dialog.url)
     dialog = DefineCatalogDialog(self.explorer.catalogs())
     self.assertEquals("catalogname", dialog.nameBox.text())
     self.assertEquals("localhost:8081/geoserver", dialog.urlBox.text())
     okWidget = dialog.buttonBox.button(dialog.buttonBox.Ok)
     QTest.mouseClick(okWidget, Qt.LeftButton)
     settings = QSettings()
     settings.endGroup()
     settings.beginGroup("/GeoServer/Catalogs/catalogname")
     settings.remove("")
     settings.endGroup()
Example #18
0
 def test_can_explore_basemaps(self):
     user, password = get_testing_credentials()
     PlanetClient.getInstance().log_in(user, password)
     current = self.dockwidget.stckdWidgetViews.currentIndex()
     assert current == 1
     self.dockwidget.show_mosaics_panel()
     current = self.dockwidget.tabWidgetResourceType.currentIndex()
     assert current == 1
     assert self.dockwidget.basemaps_widget.mosaicsList.count() == 0
     assert self.dockwidget.basemaps_widget.comboSeriesName.count() > 1
     self.dockwidget.basemaps_widget.comboSeriesName.setCurrentIndex(1)
     mosaicsList = self.dockwidget.basemaps_widget.mosaicsList
     assert mosaicsList.count() > 0
     item = mosaicsList.item(0)
     widget = mosaicsList.itemWidget(item)
     widget.checkBox.setChecked(True)
     assert "1 items" in self.dockwidget.basemaps_widget.btnOrder.text()
     QTest.mouseClick(self.dockwidget.basemaps_widget.btnExplore,
                      Qt.LeftButton)
     layers = QgsProject.instance().mapLayers().values()
     assert len(layers) == 1
Example #19
0
    def test(self):

        # Skip if GDAL python bindings are not available
        try:
            from osgeo import gdal, ogr
        except:
            return

        version_num = int(gdal.VersionInfo('VERSION_NUM'))
        if version_num < GDAL_COMPUTE_VERSION(1, 11, 0):
            return

        dialog = QgsNewGeoPackageLayerDialog()
        dialog.setProperty("hideDialogs", True)

        mDatabase = dialog.findChild(QgsFileWidget, "mDatabase")
        buttonBox = dialog.findChild(QDialogButtonBox, "buttonBox")
        ok_button = buttonBox.button(QDialogButtonBox.Ok)
        mTableNameEdit = dialog.findChild(QLineEdit, "mTableNameEdit")
        mLayerIdentifierEdit = dialog.findChild(QLineEdit,
                                                "mLayerIdentifierEdit")
        mLayerDescriptionEdit = dialog.findChild(QLineEdit,
                                                 "mLayerDescriptionEdit")
        mFeatureIdColumnEdit = dialog.findChild(QLineEdit,
                                                "mFeatureIdColumnEdit")
        mGeometryTypeBox = dialog.findChild(QComboBox, "mGeometryTypeBox")
        mGeometryColumnEdit = dialog.findChild(QLineEdit,
                                               "mGeometryColumnEdit")
        mFieldNameEdit = dialog.findChild(QLineEdit, "mFieldNameEdit")
        mFieldTypeBox = dialog.findChild(QComboBox, "mFieldTypeBox")
        mFieldLengthEdit = dialog.findChild(QLineEdit, "mFieldLengthEdit")
        mAddAttributeButton = dialog.findChild(QToolButton,
                                               "mAddAttributeButton")
        mRemoveAttributeButton = dialog.findChild(QToolButton,
                                                  "mRemoveAttributeButton")
        mAttributeView = dialog.findChild(QTreeWidget, "mAttributeView")
        dialog.accepted.connect(self.accepted_slot)

        mGeometryTypeBox.setCurrentIndex(
            mGeometryTypeBox.findData(ogr.wkbPoint))
        self.assertEqual(mGeometryTypeBox.currentText(), "Point")

        self.assertFalse(ok_button.isEnabled())

        dbname = os.path.join(self.basetestpath, 'test.gpkg')
        mDatabase.setFilePath(dbname)
        self.assertEqual(mTableNameEdit.text(), 'test')
        self.assertEqual(mLayerIdentifierEdit.text(), 'test')
        self.assertTrue(ok_button.isEnabled())

        mGeometryColumnEdit.setText('my_geom')
        mFeatureIdColumnEdit.setText('my_fid')

        self.assertFalse(mAddAttributeButton.isEnabled())
        self.assertFalse(mRemoveAttributeButton.isEnabled())

        mFieldNameEdit.setText('strfield')
        self.assertTrue(mAddAttributeButton.isEnabled())
        mFieldLengthEdit.setText('10')
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('intfield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('integer'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('realfield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('real'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('datefield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('date'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('datetimefield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('datetime'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            mFieldNameEdit.setText('int64field')
            mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('integer64'))
            self.assertFalse(mFieldLengthEdit.isEnabled())
            QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        # Add and remove field
        mFieldNameEdit.setText('dummy')
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        index = mAttributeView.model().index(
            mAttributeView.model().rowCount() - 1, 0)
        mAttributeView.setCurrentIndex(index)

        QTest.mouseClick(mRemoveAttributeButton, Qt.LeftButton)

        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        self.assertTrue(self.accepted)

        layers = QgsProject.instance().mapLayers()
        self.assertEqual(len(layers), 1)
        layer = layers[list(layers.keys())[0]]
        self.assertEqual(layer.name(), 'test')
        self.assertEqual(layer.geometryType(), QgsWkbTypes.PointGeometry)
        QgsProject.instance().removeAllMapLayers()

        ds = ogr.Open(dbname)
        lyr = ds.GetLayer(0)
        self.assertEqual(lyr.GetFIDColumn(), 'my_fid')
        self.assertEqual(lyr.GetGeometryColumn(), 'my_geom')
        self.assertEqual(lyr.GetGeomType(), ogr.wkbPoint)
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldCount(), 6)
        else:
            self.assertEqual(lyr.GetLayerDefn().GetFieldCount(), 5)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(0).GetNameRef(),
                         'strfield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(0).GetType(),
                         ogr.OFTString)
        # Only GDAL 2.0 recognizes string field width
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(0).GetWidth(), 10)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(1).GetNameRef(),
                         'intfield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(1).GetType(),
                         ogr.OFTInteger)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(1).GetWidth(), 0)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(2).GetNameRef(),
                         'realfield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(2).GetType(),
                         ogr.OFTReal)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(2).GetWidth(), 0)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(3).GetNameRef(),
                         'datefield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(3).GetType(),
                         ogr.OFTDate)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(3).GetWidth(), 0)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetNameRef(),
                         'datetimefield')
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetType(),
                             ogr.OFTDateTime)
        else:
            # There's a bug in OGR 1.11. The field is probably declared as DATETIME in SQL
            # but OGR detects it as OFTDate
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetType(),
                             ogr.OFTDate)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetWidth(), 0)
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(5).GetNameRef(),
                             'int64field')
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(5).GetType(),
                             ogr.OFTInteger64)
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(5).GetWidth(), 0)
        ds = None

        # Try re-adding with different table. It should ask if we want to
        # overwrite the DB, and we'll implicitly answer cancel, hence failure
        mTableNameEdit.setText('table2')

        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        self.assertFalse(self.accepted)

        # Retry, and ask to keep the DB
        self.accepted = False
        dialog.setProperty('question_existing_db_answer_add_new_layer', True)
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_add_new_layer', None)
        self.assertTrue(self.accepted)

        QgsProject.instance().removeAllMapLayers()
        ds = ogr.Open(dbname)
        self.assertEqual(ds.GetLayerCount(), 2)
        ds = None

        # Retry, and ask to overwrite the DB
        self.accepted = False
        dialog.setProperty('question_existing_db_answer_overwrite', True)
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_overwrite', None)
        self.assertTrue(self.accepted)

        QgsProject.instance().removeAllMapLayers()
        ds = ogr.Open(dbname)
        self.assertEqual(ds.GetLayerCount(), 1)
        ds = None

        # Try re-adding with same parameters. It should ask if we want to
        # overwrite the layer, and we'll implicitly answer no, hence failure
        # since it already exists with that name
        self.accepted = False
        dialog.setProperty('question_existing_db_answer_add_new_layer', True)
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_add_new_layer', None)
        self.assertFalse(self.accepted)

        # Now answer yes, and change a few things
        mLayerIdentifierEdit.setText('my_identifier')
        mLayerDescriptionEdit.setText('my_description')
        dialog.setProperty('question_existing_db_answer_add_new_layer', True)
        dialog.setProperty('question_existing_layer_answer_overwrite', True)
        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_add_new_layer', None)
        dialog.setProperty('question_existing_layer_answer_overwrite', None)
        self.assertTrue(self.accepted)

        # Only check with OGR 2.0 since the IDENTIFIER and DESCRIPTION creation options don't exist in OGR 1.11
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            layers = QgsProject.instance().mapLayers()
            self.assertEqual(len(layers), 1)
            layer = layers[list(layers.keys())[0]]
            self.assertEqual(layer.name(), 'my_identifier')
            QgsProject.instance().removeAllMapLayers()

            ds = ogr.Open(dbname)
            sql_lyr = ds.ExecuteSQL('SELECT * FROM gpkg_contents')
            self.assertEqual(sql_lyr.GetFeatureCount(), 1)
            f = sql_lyr.GetNextFeature()
            identifier = f.GetField('identifier')
            description = f.GetField('description')
            f = None
            ds.ReleaseResultSet(sql_lyr)
            ds = None
            self.assertEqual(identifier, 'my_identifier')
            self.assertEqual(description, 'my_description')
        else:
            QgsProject.instance().removeAllMapLayers()

        # Try invalid path
        mDatabase.setFilePath('/this/is/invalid/test.gpkg')
        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        self.assertFalse(self.accepted)
    def test(self):

        # This test is quite fragile as it depends on windows manager behavior
        # regarding focus, so not surprising it doesn't pass
        # on other platforms than Linux.
        # if 'TRAVIS_OS_NAME' in os.environ and os.environ['TRAVIS_OS_NAME'] == 'osx':
        #    return

        main_dialog = QgsProviderRegistry.instance().createSelectionWidget(
            "WFS")
        main_dialog.setProperty("hideDialogs", True)

        self.assertIsNotNone(main_dialog)

        # Create new connection
        btnNew = main_dialog.findChild(QWidget, "btnNew")
        self.assertIsNotNone(btnNew)
        QTest.mouseClick(btnNew, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase')
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)
        txtUrl.setText("test_url")
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)
        # Depends on asynchronous signal
        QApplication.processEvents()
        error_box = find_window('WFSCapabilitiesErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()

        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Edit connection
        btnEdit = main_dialog.findChild(QWidget, "btnEdit")
        self.assertIsNotNone(btnEdit)
        QTest.mouseClick(btnEdit, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase', )
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)

        endpoint = self.basetestpath + '/fake_qgis_http_endpoint'
        expected_endpoint = endpoint
        if sys.platform == 'win32' and expected_endpoint[1] == ':':
            expected_endpoint = expected_endpoint[0] + expected_endpoint[2:]
        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0">
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
      <ows:WGS84BoundingBox>
        <ows:LowerCorner>-71.123 66.33</ows:LowerCorner>
        <ows:UpperCorner>-65.32 78.3</ows:UpperCorner>
      </ows:WGS84BoundingBox>
    </FeatureType>
  </FeatureTypeList>
  <fes:Filter_Capabilities>
    <fes:Spatial_Capabilities>
      <fes:GeometryOperands>
        <fes:GeometryOperand name="gml:Envelope"/>
        <fes:GeometryOperand name="gml:Point"/>
        <fes:GeometryOperand name="gml:MultiPoint"/>
        <fes:GeometryOperand name="gml:LineString"/>
        <fes:GeometryOperand name="gml:MultiLineString"/>
        <fes:GeometryOperand name="gml:Polygon"/>
        <fes:GeometryOperand name="gml:MultiPolygon"/>
        <fes:GeometryOperand name="gml:MultiGeometry"/>
      </fes:GeometryOperands>
      <fes:SpatialOperators>
        <fes:SpatialOperator name="Disjoint"/>
        <fes:SpatialOperator name="Equals"/>
        <fes:SpatialOperator name="DWithin"/>
        <fes:SpatialOperator name="Beyond"/>
        <fes:SpatialOperator name="Intersects"/>
        <fes:SpatialOperator name="Touches"/>
        <fes:SpatialOperator name="Crosses"/>
        <fes:SpatialOperator name="Within"/>
        <fes:SpatialOperator name="Contains"/>
        <fes:SpatialOperator name="Overlaps"/>
        <fes:SpatialOperator name="BBOX"/>
      </fes:SpatialOperators>
    </fes:Spatial_Capabilities>
    <fes:Functions>
      <fes:Function name="abs">
        <fes:Returns>xs:int</fes:Returns>
        <fes:Arguments>
          <fes:Argument name="param">
            <fes:Type>xs:int</fes:Type>
          </fes:Argument>
        </fes:Arguments>
      </fes:Function>
    </fes:Functions>
  </fes:Filter_Capabilities>
</wfs:WFS_Capabilities>""".encode('UTF-8'))

        txtUrl.setText("http://" + endpoint)
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)

        buttonAdd = self.get_button_add(main_dialog)
        for i in range(10):
            QApplication.processEvents()
            if buttonAdd.isEnabled():
                break
        self.assertTrue(buttonAdd.isEnabled())

        # Add layer
        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addVectorLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(
            self.addWfsLayer_uri,
            ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\''
            + "http://" + expected_endpoint +
            '\' version=\'auto\' table="" sql=')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')

        # Click on Build Query
        buttonBuildQuery = self.get_button_build_query(main_dialog)
        self.assertTrue(buttonBuildQuery.isEnabled())
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)
        error_box = find_window('WFSFeatureTypeErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()
        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Click again but with valid DescribeFeatureType

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'
                ), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml/3.2"/>
  <xsd:complexType name="typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PolygonPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""".encode('UTF-8'))
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)

        # Check that the combos are properly initialized
        dialog = find_window('QgsSQLComposerDialogBase')
        self.assertIsNotNone(dialog)

        mTablesCombo = dialog.findChild(QComboBox, "mTablesCombo")
        self.assertIsNotNone(mTablesCombo)
        self.assertEqual(mTablesCombo.itemText(1), 'typename (Title)')

        mColumnsCombo = dialog.findChild(QComboBox, "mColumnsCombo")
        self.assertIsNotNone(mColumnsCombo)
        self.assertEqual(mColumnsCombo.itemText(1), 'intfield (int)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 2),
                         'geometryProperty (geometry)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 1),
                         '*')

        mFunctionsCombo = dialog.findChild(QComboBox, "mFunctionsCombo")
        self.assertIsNotNone(mFunctionsCombo)
        self.assertEqual(mFunctionsCombo.itemText(1), 'abs(param: int): int')

        mSpatialPredicatesCombo = dialog.findChild(QComboBox,
                                                   "mSpatialPredicatesCombo")
        self.assertIsNotNone(mSpatialPredicatesCombo)
        self.assertEqual(mSpatialPredicatesCombo.itemText(1),
                         'ST_Disjoint(geometry, geometry): boolean')

        mWhereEditor = dialog.findChild(QTextEdit, "mWhereEditor")
        self.assertIsNotNone(mWhereEditor)
        mWhereEditor.setText('1 = 1')

        dialog.accept()
        # Wait for object to be destroyed
        dialog = self.wait_object_destruction(dialog)

        # Add layer
        buttonAdd = self.get_button_add(main_dialog)
        self.assertTrue(buttonAdd.isEnabled())

        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addVectorLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(
            self.addWfsLayer_uri,
            ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\''
            + "http://" + expected_endpoint +
            '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1'
        )
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
    def test(self):

        # Skip if GDAL python bindings are not available
        try:
            from osgeo import gdal, ogr
        except:
            return

        version_num = int(gdal.VersionInfo('VERSION_NUM'))
        if version_num < GDAL_COMPUTE_VERSION(1, 11, 0):
            return

        dialog = QgsNewGeoPackageLayerDialog()
        dialog.setProperty("hideDialogs", True)

        mDatabase = dialog.findChild(QgsFileWidget, "mDatabase")
        buttonBox = dialog.findChild(QDialogButtonBox, "buttonBox")
        ok_button = buttonBox.button(QDialogButtonBox.Ok)
        mTableNameEdit = dialog.findChild(QLineEdit, "mTableNameEdit")
        mLayerIdentifierEdit = dialog.findChild(QLineEdit, "mLayerIdentifierEdit")
        mLayerDescriptionEdit = dialog.findChild(QLineEdit, "mLayerDescriptionEdit")
        mFeatureIdColumnEdit = dialog.findChild(QLineEdit, "mFeatureIdColumnEdit")
        mGeometryTypeBox = dialog.findChild(QComboBox, "mGeometryTypeBox")
        mGeometryColumnEdit = dialog.findChild(QLineEdit, "mGeometryColumnEdit")
        mFieldNameEdit = dialog.findChild(QLineEdit, "mFieldNameEdit")
        mFieldTypeBox = dialog.findChild(QComboBox, "mFieldTypeBox")
        mFieldLengthEdit = dialog.findChild(QLineEdit, "mFieldLengthEdit")
        mAddAttributeButton = dialog.findChild(QToolButton, "mAddAttributeButton")
        mRemoveAttributeButton = dialog.findChild(QToolButton, "mRemoveAttributeButton")
        mAttributeView = dialog.findChild(QTreeWidget, "mAttributeView")
        dialog.accepted.connect(self.accepted_slot)

        mGeometryTypeBox.setCurrentIndex(mGeometryTypeBox.findData(ogr.wkbPoint))
        self.assertEqual(mGeometryTypeBox.currentText(), "Point")

        self.assertFalse(ok_button.isEnabled())

        dbname = os.path.join(self.basetestpath, 'test.gpkg')
        mDatabase.setFilePath(dbname)
        self.assertEqual(mTableNameEdit.text(), 'test')
        self.assertEqual(mLayerIdentifierEdit.text(), 'test')
        self.assertTrue(ok_button.isEnabled())

        mGeometryColumnEdit.setText('my_geom')
        mFeatureIdColumnEdit.setText('my_fid')

        self.assertFalse(mAddAttributeButton.isEnabled())
        self.assertFalse(mRemoveAttributeButton.isEnabled())

        mFieldNameEdit.setText('strfield')
        self.assertTrue(mAddAttributeButton.isEnabled())
        mFieldLengthEdit.setText('10')
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('intfield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('integer'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('realfield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('real'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('datefield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('date'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        mFieldNameEdit.setText('datetimefield')
        mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('datetime'))
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            mFieldNameEdit.setText('int64field')
            mFieldTypeBox.setCurrentIndex(mFieldTypeBox.findData('integer64'))
            self.assertFalse(mFieldLengthEdit.isEnabled())
            QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        # Add and remove field
        mFieldNameEdit.setText('dummy')
        self.assertFalse(mFieldLengthEdit.isEnabled())
        QTest.mouseClick(mAddAttributeButton, Qt.LeftButton)

        index = mAttributeView.model().index(mAttributeView.model().rowCount() - 1, 0)
        mAttributeView.setCurrentIndex(index)

        QTest.mouseClick(mRemoveAttributeButton, Qt.LeftButton)

        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        self.assertTrue(self.accepted)

        layers = QgsProject.instance().mapLayers()
        self.assertEqual(len(layers), 1)
        layer = layers[list(layers.keys())[0]]
        self.assertEqual(layer.name(), 'test')
        self.assertEqual(layer.geometryType(), QgsWkbTypes.PointGeometry)
        QgsProject.instance().removeAllMapLayers()

        ds = ogr.Open(dbname)
        lyr = ds.GetLayer(0)
        self.assertEqual(lyr.GetFIDColumn(), 'my_fid')
        self.assertEqual(lyr.GetGeometryColumn(), 'my_geom')
        self.assertEqual(lyr.GetGeomType(), ogr.wkbPoint)
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldCount(), 6)
        else:
            self.assertEqual(lyr.GetLayerDefn().GetFieldCount(), 5)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(0).GetNameRef(), 'strfield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(0).GetType(), ogr.OFTString)
        # Only GDAL 2.0 recognizes string field width
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(0).GetWidth(), 10)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(1).GetNameRef(), 'intfield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(1).GetType(), ogr.OFTInteger)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(1).GetWidth(), 0)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(2).GetNameRef(), 'realfield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(2).GetType(), ogr.OFTReal)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(2).GetWidth(), 0)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(3).GetNameRef(), 'datefield')
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(3).GetType(), ogr.OFTDate)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(3).GetWidth(), 0)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetNameRef(), 'datetimefield')
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetType(), ogr.OFTDateTime)
        else:
            # There's a bug in OGR 1.11. The field is probably declared as DATETIME in SQL
            # but OGR detects it as OFTDate
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetType(), ogr.OFTDate)
        self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(4).GetWidth(), 0)
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(5).GetNameRef(), 'int64field')
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(5).GetType(), ogr.OFTInteger64)
            self.assertEqual(lyr.GetLayerDefn().GetFieldDefn(5).GetWidth(), 0)
        ds = None

        # Try re-adding with different table. It should ask if we want to
        # overwrite the DB, and we'll implicitly answer cancel, hence failure
        mTableNameEdit.setText('table2')

        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        self.assertFalse(self.accepted)

        # Retry, and ask to keep the DB
        self.accepted = False
        dialog.setProperty('question_existing_db_answer_add_new_layer', True)
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_add_new_layer', None)
        self.assertTrue(self.accepted)

        QgsProject.instance().removeAllMapLayers()
        ds = ogr.Open(dbname)
        self.assertEqual(ds.GetLayerCount(), 2)
        ds = None

        # Retry, and ask to overwrite the DB
        self.accepted = False
        dialog.setProperty('question_existing_db_answer_overwrite', True)
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_overwrite', None)
        self.assertTrue(self.accepted)

        QgsProject.instance().removeAllMapLayers()
        ds = ogr.Open(dbname)
        self.assertEqual(ds.GetLayerCount(), 1)
        ds = None

        # Try re-adding with same parameters. It should ask if we want to
        # overwrite the layer, and we'll implicitly answer no, hence failure
        # since it already exists with that name
        self.accepted = False
        dialog.setProperty('question_existing_db_answer_add_new_layer', True)
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_add_new_layer', None)
        self.assertFalse(self.accepted)

        # Now answer yes, and change a few things
        mLayerIdentifierEdit.setText('my_identifier')
        mLayerDescriptionEdit.setText('my_description')
        dialog.setProperty('question_existing_db_answer_add_new_layer', True)
        dialog.setProperty('question_existing_layer_answer_overwrite', True)
        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        dialog.setProperty('question_existing_db_answer_add_new_layer', None)
        dialog.setProperty('question_existing_layer_answer_overwrite', None)
        self.assertTrue(self.accepted)

        # Only check with OGR 2.0 since the IDENTIFIER and DESCRIPTION creation options don't exist in OGR 1.11
        if version_num >= GDAL_COMPUTE_VERSION(2, 0, 0):
            layers = QgsProject.instance().mapLayers()
            self.assertEqual(len(layers), 1)
            layer = layers[list(layers.keys())[0]]
            self.assertEqual(layer.name(), 'my_identifier')
            QgsProject.instance().removeAllMapLayers()

            ds = ogr.Open(dbname)
            sql_lyr = ds.ExecuteSQL('SELECT * FROM gpkg_contents')
            self.assertEqual(sql_lyr.GetFeatureCount(), 1)
            f = sql_lyr.GetNextFeature()
            identifier = f.GetField('identifier')
            description = f.GetField('description')
            f = None
            ds.ReleaseResultSet(sql_lyr)
            ds = None
            self.assertEqual(identifier, 'my_identifier')
            self.assertEqual(description, 'my_description')
        else:
            QgsProject.instance().removeAllMapLayers()

        # Try invalid path
        mDatabase.setFilePath('/this/is/invalid/test.gpkg')
        self.accepted = False
        QTest.mouseClick(ok_button, Qt.LeftButton)
        self.assertFalse(self.accepted)
Example #22
0
    def test(self):

        # This test is quite fragile as it depends on windows manager behaviour
        # regarding focus, so not surprising it doesn't pass
        # on other platforms than Linux.
        #if 'TRAVIS_OS_NAME' in os.environ and os.environ['TRAVIS_OS_NAME'] == 'osx':
        #    return

        main_dialog = QgsProviderRegistry.instance().selectWidget("WFS")
        main_dialog.setProperty("hideDialogs", True)

        self.assertIsNotNone(main_dialog)

        # Create new connection
        btnNew = main_dialog.findChild(QWidget, "btnNew")
        self.assertIsNotNone(btnNew)
        QTest.mouseClick(btnNew, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase')
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)
        txtUrl.setText("test_url")
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)
        # Depends on asynchronous signal
        QApplication.processEvents()
        error_box = find_window('WFSCapabilitiesErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()

        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Edit connection
        btnEdit = main_dialog.findChild(QWidget, "btnEdit")
        self.assertIsNotNone(btnEdit)
        QTest.mouseClick(btnEdit, Qt.LeftButton)
        new_conn = find_window('QgsNewHttpConnectionBase',)
        self.assertIsNotNone(new_conn)
        txtName = new_conn.findChild(QLineEdit, "txtName")
        self.assertIsNotNone(txtName)
        txtName.setText("test_connection")
        txtUrl = new_conn.findChild(QLineEdit, "txtUrl")
        self.assertIsNotNone(txtUrl)

        endpoint = self.basetestpath + '/fake_qgis_http_endpoint'
        expected_endpoint = endpoint
        if sys.platform == 'win32' and expected_endpoint[1] == ':':
            expected_endpoint = expected_endpoint[0] + expected_endpoint[2:]
        with open(sanitize(endpoint, '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'), 'wb') as f:
            f.write("""
<wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0">
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
      <ows:WGS84BoundingBox>
        <ows:LowerCorner>-71.123 66.33</ows:LowerCorner>
        <ows:UpperCorner>-65.32 78.3</ows:UpperCorner>
      </ows:WGS84BoundingBox>
    </FeatureType>
  </FeatureTypeList>
  <fes:Filter_Capabilities>
    <fes:Spatial_Capabilities>
      <fes:GeometryOperands>
        <fes:GeometryOperand name="gml:Envelope"/>
        <fes:GeometryOperand name="gml:Point"/>
        <fes:GeometryOperand name="gml:MultiPoint"/>
        <fes:GeometryOperand name="gml:LineString"/>
        <fes:GeometryOperand name="gml:MultiLineString"/>
        <fes:GeometryOperand name="gml:Polygon"/>
        <fes:GeometryOperand name="gml:MultiPolygon"/>
        <fes:GeometryOperand name="gml:MultiGeometry"/>
      </fes:GeometryOperands>
      <fes:SpatialOperators>
        <fes:SpatialOperator name="Disjoint"/>
        <fes:SpatialOperator name="Equals"/>
        <fes:SpatialOperator name="DWithin"/>
        <fes:SpatialOperator name="Beyond"/>
        <fes:SpatialOperator name="Intersects"/>
        <fes:SpatialOperator name="Touches"/>
        <fes:SpatialOperator name="Crosses"/>
        <fes:SpatialOperator name="Within"/>
        <fes:SpatialOperator name="Contains"/>
        <fes:SpatialOperator name="Overlaps"/>
        <fes:SpatialOperator name="BBOX"/>
      </fes:SpatialOperators>
    </fes:Spatial_Capabilities>
    <fes:Functions>
      <fes:Function name="abs">
        <fes:Returns>xs:int</fes:Returns>
        <fes:Arguments>
          <fes:Argument name="param">
            <fes:Type>xs:int</fes:Type>
          </fes:Argument>
        </fes:Arguments>
      </fes:Function>
    </fes:Functions>
  </fes:Filter_Capabilities>
</wfs:WFS_Capabilities>""".encode('UTF-8'))

        txtUrl.setText("http://" + endpoint)
        new_conn.accept()

        # Wait for object to be destroyed
        new_conn = self.wait_object_destruction(new_conn)

        # Try to connect
        btnConnect = main_dialog.findChild(QWidget, "btnConnect")
        self.assertIsNotNone(btnConnect)
        QTest.mouseClick(btnConnect, Qt.LeftButton)

        buttonAdd = self.get_button_add(main_dialog)
        for i in range(10):
            QApplication.processEvents()
            if buttonAdd.isEnabled():
                break
        self.assertTrue(buttonAdd.isEnabled())

        # Add layer
        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')

        # Click on Build Query
        buttonBuildQuery = self.get_button_build_query(main_dialog)
        self.assertTrue(buttonBuildQuery.isEnabled())
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)
        error_box = find_window('WFSFeatureTypeErrorBox')
        self.assertIsNotNone(error_box)
        # Close error box
        error_box.accept()
        # Wait for object to be destroyed
        error_box = self.wait_object_destruction(error_box)

        # Click again but with valid DescribeFeatureType

        with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml/3.2"/>
  <xsd:complexType name="typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PolygonPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""".encode('UTF-8'))
        QTest.mouseClick(buttonBuildQuery, Qt.LeftButton)

        # Check that the combos are properly initialized
        dialog = find_window('QgsSQLComposerDialogBase')
        self.assertIsNotNone(dialog)

        mTablesCombo = dialog.findChild(QComboBox, "mTablesCombo")
        self.assertIsNotNone(mTablesCombo)
        self.assertEqual(mTablesCombo.itemText(1), 'typename (Title)')

        mColumnsCombo = dialog.findChild(QComboBox, "mColumnsCombo")
        self.assertIsNotNone(mColumnsCombo)
        self.assertEqual(mColumnsCombo.itemText(1), 'intfield (int)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 2), 'geometryProperty (geometry)')
        self.assertEqual(mColumnsCombo.itemText(mColumnsCombo.count() - 1), '*')

        mFunctionsCombo = dialog.findChild(QComboBox, "mFunctionsCombo")
        self.assertIsNotNone(mFunctionsCombo)
        self.assertEqual(mFunctionsCombo.itemText(1), 'abs(param: int): int')

        mSpatialPredicatesCombo = dialog.findChild(QComboBox, "mSpatialPredicatesCombo")
        self.assertIsNotNone(mSpatialPredicatesCombo)
        self.assertEqual(mSpatialPredicatesCombo.itemText(1), 'ST_Disjoint(geometry, geometry): boolean')

        mWhereEditor = dialog.findChild(QTextEdit, "mWhereEditor")
        self.assertIsNotNone(mWhereEditor)
        mWhereEditor.setText('1 = 1')

        dialog.accept()
        # Wait for object to be destroyed
        dialog = self.wait_object_destruction(dialog)

        # Add layer
        buttonAdd = self.get_button_add(main_dialog)
        self.assertTrue(buttonAdd.isEnabled())

        self.addWfsLayer_uri = None
        self.addWfsLayer_layer_name = None
        main_dialog.addWfsLayer.connect(self.slotAddWfsLayer)
        QTest.mouseClick(buttonAdd, Qt.LeftButton)
        self.assertEqual(self.addWfsLayer_uri, ' restrictToRequestBBOX=\'1\' srsname=\'EPSG:4326\' typename=\'my:typename\' url=\'' + "http://" + expected_endpoint + '\' version=\'auto\' table="" sql=SELECT * FROM typename WHERE 1 = 1')
        self.assertEqual(self.addWfsLayer_layer_name, 'my:typename')
Example #23
0
 def handle_msgbox():
     msgbox: QMessageBox = QApplication.activeWindow()
     self.assertIsInstance(msgbox, QMessageBox)
     self.assertIn("Unable to geocode", msgbox.text())
     QTest.mouseClick(msgbox.button(QMessageBox.Ok), Qt.LeftButton)