Add more acceptance tests

This commit is contained in:
Cécile Vuilleumier 2024-10-01 13:33:11 +02:00
parent fe35e23d45
commit 9b290afcc6
No known key found for this signature in database
GPG Key ID: A16CD36473EF733C
31 changed files with 888 additions and 4 deletions

View File

@ -97,4 +97,4 @@ acceptance-tests: build-acceptance
.PHONY: stop-acceptance-tests .PHONY: stop-acceptance-tests
stop-acceptance-tests: build-acceptance stop-acceptance-tests: build-acceptance
(cd compose/ && TAG=$(TAG) GS_USER=$(UID):$(GID) docker compose $(COMPOSE_ACCEPTANCE_DATADIR_OPTIONS) down -v) (cd compose/ && TAG=$(TAG) GS_USER=$(UID):$(GID) docker compose $(COMPOSE_ACCEPTANCE_DATADIR_OPTIONS) down -v)

View File

@ -9,7 +9,9 @@ packages = [{ include = "tests" }]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.10" python = "^3.10"
pytest = "^8.3.3" pytest = "^8.3.3"
psycopg2-binary = "^2.9.9"
geoservercloud = "^0.2.5" geoservercloud = "^0.2.5"
sqlalchemy = "^2.0.35"
[build-system] [build-system]

View File

@ -1,12 +1,60 @@
import os import os
from pathlib import Path
import pytest import pytest
import sqlalchemy
from geoservercloud import GeoServerCloud from geoservercloud import GeoServerCloud
GEOSERVER_URL = os.getenv("GEOSERVER_URL", "http://gateway:8080/geoserver/cloud") GEOSERVER_URL = os.getenv("GEOSERVER_URL", "http://gateway:8080/geoserver/cloud")
RESOURCE_DIR = Path(__file__).parent / "resources"
# Database connection
PGHOST = "geodatabase"
PGPORT = 5432
PGDATABASE = "geodata"
PGUSER = "geodata"
PGPASSWORD = "geodata"
PGSCHEMA = "test1"
WORKSPACE = "test_workspace"
DATASTORE = "test_datastore"
@pytest.fixture(scope="session", autouse=True)
def engine():
yield sqlalchemy.create_engine(
f"postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE}",
)
@pytest.fixture(scope="session", autouse=True)
def db_session(engine):
with engine.connect() as connection:
connection.execute(
sqlalchemy.sql.text(f"CREATE SCHEMA IF NOT EXISTS {PGSCHEMA}")
)
connection.execute(sqlalchemy.sql.text(f"SET SEARCH_PATH = {PGSCHEMA}"))
connection.commit()
yield connection
connection.execute(
sqlalchemy.sql.text(f"DROP SCHEMA IF EXISTS {PGSCHEMA} CASCADE")
)
connection.commit()
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def geoserver(): def geoserver():
yield GeoServerCloud(GEOSERVER_URL) geoserver = GeoServerCloud(GEOSERVER_URL)
geoserver.recreate_workspace(WORKSPACE, set_default_workspace=True)
geoserver.create_pg_datastore(
workspace=WORKSPACE,
datastore=DATASTORE,
pg_host=PGHOST,
pg_port=PGPORT,
pg_db=PGDATABASE,
pg_user=PGUSER,
pg_password=PGPASSWORD,
pg_schema=PGSCHEMA,
set_default_datastore=True,
)
geoserver.publish_workspace(WORKSPACE)
yield geoserver
geoserver.delete_workspace(WORKSPACE)

View File

@ -0,0 +1,15 @@
from pathlib import Path
def write_actual_image(response, tag):
file = Path(f"/tmp/{tag}_actual.png")
file.parent.mkdir(parents=True, exist_ok=True)
with open(file, "wb") as fs:
fs.write(response.read())
def compare_images(dir, tag):
actual = f"/tmp/{tag}_actual.png"
expected = f"{dir}/{tag}_expected.png"
with open(actual, "rb") as fs1, open(expected, "rb") as fs2:
assert fs1.read() == fs2.read()

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:se="http://www.opengis.net/se"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NamedLayer>
<Name>localized_labels</Name>
<UserStyle>
<Name>localized_labels</Name>
<FeatureTypeStyle>
<Rule>
<Name>Localized labels</Name>
<TextSymbolizer>
<Label>
<ogc:Function name="Recode">
<ogc:Function name="language"/>
<ogc:Literal/>
<ogc:PropertyName>label_default</ogc:PropertyName>
<ogc:Literal>de</ogc:Literal>
<ogc:PropertyName>label_de</ogc:PropertyName>
<ogc:Literal>fr</ogc:Literal>
<ogc:PropertyName>label_fr</ogc:PropertyName>
</ogc:Function>
</Label>
<Fill>
<CssParameter name="fill">#000000</CssParameter>
</Fill>
</TextSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:se="http://www.opengis.net/se"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NamedLayer>
<Name>localized_style</Name>
<UserStyle>
<Name>localized_no_default</Name>
<FeatureTypeStyle>
<Rule>
<Name>Localized, no default value</Name>
<Title>
<Localized lang="en">English</Localized>
<Localized lang="de">Deutsch</Localized>
<Localized lang="fr">Français</Localized>
<Localized lang="it">Italiano</Localized>
</Title>
<PointSymbolizer>
<Graphic>
<Mark>
<WellKnownName>circle</WellKnownName>
<Fill>
<CssParameter name="fill">#FF0000</CssParameter>
</Fill>
</Mark>
<Size>6</Size>
</Graphic>
</PointSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd"
xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:se="http://www.opengis.net/se"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NamedLayer>
<Name>localized_style</Name>
<UserStyle>
<Name>localized_with_default</Name>
<FeatureTypeStyle>
<Rule>
<Name>Localized, with default value</Name>
<Title>
Default label<Localized lang="en">English</Localized>
<Localized lang="de">Deutsch</Localized>
<Localized lang="fr">Français</Localized>
<Localized lang="it">Italiano</Localized>
</Title>
<PointSymbolizer>
<Graphic>
<Mark>
<WellKnownName>circle</WellKnownName>
<Fill>
<CssParameter name="fill">#FF0000</CssParameter>
</Fill>
</Mark>
<Size>6</Size>
</Graphic>
</PointSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

View File

@ -0,0 +1,16 @@
<Transaction xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd">
<Insert>
<test_wfs xmlns="test_wfs">
<geom>
<Point xmlns="http://www.opengis.net/gml" srsName="EPSG:2056">
<pos srsDimension="2">2600000.0 1200000.0</pos>
</Point>
</geom>
<timestamp>2024-05-13T08:14:48.763Z</timestamp>
<id>10</id>
<title>Title</title>
</test_wfs>
</Insert>
</Transaction>

View File

@ -0,0 +1,24 @@
from conftest import PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD, PGSCHEMA
def test_create_get_and_delete_datastore(geoserver):
workspace = datastore = "test_create_pg_datastore"
geoserver.create_workspace(workspace)
response = geoserver.create_pg_datastore(
workspace=workspace,
datastore=datastore,
pg_host=PGHOST,
pg_port=PGPORT,
pg_db=PGDATABASE,
pg_user=PGUSER,
pg_password=PGPASSWORD,
pg_schema=PGSCHEMA,
set_default_datastore=True,
)
assert response.status_code == 201
response = geoserver.get_request(
f"/rest/workspaces/{workspace}/datastores/{datastore}.json"
)
assert response.status_code == 200
response = geoserver.delete_workspace(workspace)
assert response.status_code == 200

View File

@ -0,0 +1,47 @@
import pytest
WORKSPACE = "test_gwc"
WMTS_STORE = "test_gwc_store"
WMTS_LAYER = "ch.swisstopo.swissimage"
@pytest.fixture(scope="module")
def geoserver_with_gwc_layers(geoserver):
geoserver.create_workspace(WORKSPACE)
geoserver.create_wmts_store(
WORKSPACE,
WMTS_STORE,
capabilities="https://wmts.geo.admin.ch/EPSG/4326/1.0.0/WMTSCapabilities.xml",
)
geoserver.create_wmts_layer(WORKSPACE, WMTS_STORE, WMTS_LAYER)
geoserver.get_request(
f"/rest/workspaces/{WORKSPACE}/wmtsstores/{WMTS_STORE}/layers/{WMTS_LAYER}.json"
)
response = geoserver.publish_gwc_layer(WORKSPACE, WMTS_LAYER)
assert response.status_code == 200
yield geoserver
geoserver.delete_workspace(WORKSPACE)
def test_tile_cache(geoserver_with_gwc_layers):
response = geoserver_with_gwc_layers.get_tile(
format="image/png",
layer=f"{WORKSPACE}:{WMTS_LAYER}",
tile_matrix_set="EPSG:4326",
tile_matrix="EPSG:4326:9",
row=122,
column=534,
)
assert response.info().get("Content-Type") == "image/png"
assert response.info().get("Geowebcache-Cache-Result") == "MISS"
response = geoserver_with_gwc_layers.get_tile(
format="image/png",
layer=f"{WORKSPACE}:{WMTS_LAYER}",
tile_matrix_set="EPSG:4326",
tile_matrix="EPSG:4326:9",
row=122,
column=534,
)
assert response.info().get("Geowebcache-Cache-Result") == "HIT"

View File

@ -0,0 +1,417 @@
#!/bin/env python
import pytest
from conftest import RESOURCE_DIR, WORKSPACE
from lib.utils import compare_images, write_actual_image
from requests.exceptions import JSONDecodeError
from sqlalchemy.sql import text
def international_title(default=True, de=True, fr=True, it=True, rm=True):
title = {}
if default:
title["default"] = "Default title"
if de:
title["de"] = "Punkte"
if fr:
title["fr"] = "Points"
if it:
title["it"] = "Punti"
if rm:
title["rm"] = "Puncts"
return title
def assert_legend(geoserver, style, language, expected_label):
response = geoserver.get_legend_graphic(
"i18n_legend",
format="application/json",
language=language,
style=style,
workspace=WORKSPACE,
)
try:
label = response.json()["Legend"][0]["rules"][0]["title"]
assert label == expected_label
except (KeyError, JSONDecodeError):
print(f"Invalid response for language '{language}:'\n{response.content}")
assert False
@pytest.fixture(scope="module")
def geoserver_with_i18n_layers(geoserver):
# Create feature type with all languages
layer1 = "layer_all_languages"
title1 = international_title(default=True, de=True, fr=True, it=True, rm=True)
geoserver.create_feature_type(layer1, title=title1, epsg=2056)
# Create feature type without Rumantsch
layer2 = "layer_no_rumantsch"
title2 = international_title(default=True, de=True, fr=True, it=True, rm=False)
geoserver.create_feature_type(layer2, title=title2, epsg=2056)
# Create feature type without default language nor Rumantsch
layer3 = "layer_no_default_no_rumantsch"
title3 = international_title(default=False, de=True, fr=True, it=True, rm=False)
geoserver.create_feature_type(layer3, title=title3, epsg=2056)
yield geoserver
@pytest.fixture(scope="module")
def geoserver_default_locale_it(geoserver_with_i18n_layers):
geoserver_with_i18n_layers.set_default_locale_for_service(WORKSPACE, "it")
yield geoserver_with_i18n_layers
geoserver_with_i18n_layers.unset_default_locale_for_service(WORKSPACE)
@pytest.fixture(scope="module")
def geoserver_i18n_legend_layer(geoserver):
geoserver.create_workspace(WORKSPACE, set_default_workspace=True)
geoserver.create_feature_type("i18n_legend", epsg=2056)
geoserver.create_style_from_file(
"localized_with_default.sld",
f"{RESOURCE_DIR}/localized_with_default.sld",
workspace=WORKSPACE,
)
geoserver.create_style_from_file(
"localized_no_default.sld",
f"{RESOURCE_DIR}/localized_no_default.sld",
workspace=WORKSPACE,
)
yield geoserver
@pytest.fixture(scope="function")
def geoserver_i18n_legend_layer_and_default_locale_it(geoserver_i18n_legend_layer):
geoserver_i18n_legend_layer.set_default_locale_for_service(WORKSPACE, "it")
yield geoserver_i18n_legend_layer
geoserver_i18n_legend_layer.unset_default_locale_for_service(WORKSPACE)
@pytest.fixture(scope="module")
def geoserver_i18n_label_layer(geoserver, db_session):
feature_type = "i18n_labels"
style = "localized_labels"
file = f"{RESOURCE_DIR}/{style}.sld"
attributes = {
"geom": {"type": "Point", "required": True},
"label_default": {"type": "string", "required": False},
"label_de": {"type": "string", "required": False},
"label_fr": {"type": "string", "required": False},
}
geoserver.create_feature_type(feature_type, attributes=attributes, epsg=2056)
geoserver.create_style_from_file(style, file, workspace=WORKSPACE)
# Feature with labels in German, French and a default value
db_session.execute(
text(
f"INSERT INTO {feature_type} (geom, label_default, label_de, label_fr) VALUES "
"(public.ST_SetSRID(public.ST_MakePoint(2600000, 1200000), 2056), 'Default label', 'Deutsches Label', 'Étiquette française')"
)
)
# Feature with labels in German, French and no default value
db_session.execute(
text(
f"INSERT INTO {feature_type} (geom, label_de, label_fr) VALUES "
"(public.ST_SetSRID(public.ST_MakePoint(2700000, 1300000), 2056), 'Deutsches Label', 'Étiquette française')"
)
)
db_session.commit()
yield geoserver
@pytest.fixture(scope="module")
def geoserver_i18n_label_default_locale_fr(geoserver_i18n_label_layer):
geoserver_i18n_label_layer.set_default_locale_for_service(WORKSPACE, "fr")
yield geoserver_i18n_label_layer
geoserver_i18n_label_layer.unset_default_locale_for_service(WORKSPACE)
@pytest.mark.parametrize(
"language,expected_titles",
[
(
"de",
{
"layer_all_languages": "Punkte",
"layer_no_rumantsch": "Punkte",
"layer_no_default_no_rumantsch": "Punkte",
},
),
(
"de,fr",
{
"layer_all_languages": "Punkte",
"layer_no_rumantsch": "Punkte",
"layer_no_default_no_rumantsch": "Punkte",
},
),
(
"fr,de",
{
"layer_all_languages": "Points",
"layer_no_rumantsch": "Points",
"layer_no_default_no_rumantsch": "Points",
},
),
(
"rm",
{
"layer_all_languages": "Puncts",
"layer_no_rumantsch": "Default title",
"layer_no_default_no_rumantsch": "DID NOT FIND i18n CONTENT FOR THIS ELEMENT",
},
),
(
"en",
{},
),
(
None,
{
"layer_all_languages": "Default title",
"layer_no_rumantsch": "Default title",
"layer_no_default_no_rumantsch": "Punkte",
},
),
(
"foobar",
{},
),
],
)
def test_i18n_layers(geoserver_with_i18n_layers, language, expected_titles):
capabilities = geoserver_with_i18n_layers.get_wms_layers(WORKSPACE, language)
layers = capabilities.get("Layer")
if type(layers) is list:
for expected_layer, expected_title in expected_titles.items():
actual_layer = next(
(layer for layer in layers if layer["Name"] == expected_layer), {}
)
assert actual_layer.get("Title") == expected_title
else:
print(capabilities)
assert expected_titles == {}
assert "ServiceExceptionReport" in capabilities
@pytest.mark.parametrize(
"language,expected_titles",
[
(
"de",
{
"layer_all_languages": "Punkte",
"layer_no_rumantsch": "Punkte",
"layer_no_default_no_rumantsch": "Punkte",
},
),
(
"rm",
{
"layer_all_languages": "Puncts",
"layer_no_rumantsch": "Default title",
"layer_no_default_no_rumantsch": "DID NOT FIND i18n CONTENT FOR THIS ELEMENT",
},
),
(
"en",
{},
),
(
None,
{
"layer_all_languages": "Punti",
"layer_no_rumantsch": "Punti",
"layer_no_default_no_rumantsch": "Punti",
},
),
],
)
@pytest.mark.skip(reason="Default locale is ignored in gs-cloud 1.6.1")
def test_i18n_layers_default_locale(
geoserver_default_locale_it, language, expected_titles
):
layers = geoserver_default_locale_it.get_wms_layers(WORKSPACE, language)
if type(layers) is list:
for expected_layer, expected_title in expected_titles.items():
actual_layer = next(
(layer for layer in layers if layer["Name"] == expected_layer), {}
)
print(actual_layer["Name"])
assert actual_layer.get("Title") == expected_title
else:
print(layers)
assert expected_titles == {}
assert "ServiceExceptionReport" in layers
@pytest.mark.parametrize(
"language,expected_label",
[
("en", "English"),
("de", "Deutsch"),
("fr", "Français"),
("it", "Italiano"),
("rm", "Default label"),
(None, "Default label"),
("ru", "Default label"),
("foobar", "Default label"),
("it,fr,de", "Default label"),
],
)
def test_i18n_legend_with_default_value(
geoserver_i18n_legend_layer, language, expected_label
):
assert_legend(
geoserver_i18n_legend_layer,
"localized_with_default",
language,
expected_label,
)
@pytest.mark.parametrize(
"language,expected_label",
[
("it", "Italiano"),
("rm", ""),
(None, ""),
("ru", ""),
("foobar", ""),
("it,fr,de", ""),
],
)
def test_i18n_legend_no_default_value(
geoserver_i18n_legend_layer, language, expected_label
):
assert_legend(
geoserver_i18n_legend_layer,
"localized_no_default",
language,
expected_label,
)
@pytest.mark.parametrize(
"language,expected_label",
[
("en", "English"),
("de", "Deutsch"),
("fr", "Français"),
("it", "Italiano"),
("rm", "Default label"),
(None, "Default label"),
("ru", "Default label"),
("foobar", "Default label"),
("it,fr,de", "Default label"),
],
)
def test_i18n_legend_with_default_value_and_default_locale(
geoserver_i18n_legend_layer_and_default_locale_it, language, expected_label
):
assert_legend(
geoserver_i18n_legend_layer_and_default_locale_it,
"localized_with_default",
language,
expected_label,
)
@pytest.mark.parametrize(
"language,expected_label",
[
("it", "Italiano"),
("rm", ""),
(None, ""),
("ru", ""),
("foobar", ""),
("it,fr,de", ""),
],
)
def test_i18n_legend_no_default_value_default_locale(
geoserver_i18n_legend_layer_and_default_locale_it, language, expected_label
):
assert_legend(
geoserver_i18n_legend_layer_and_default_locale_it,
"localized_no_default",
language,
expected_label,
)
@pytest.mark.parametrize("language", ["de", "fr", "it", None, ""])
def test_i18n_labels(geoserver_i18n_label_layer, language):
response = geoserver_i18n_label_layer.get_map(
layers=["i18n_labels"],
bbox=(2599999.5, 1199999.5, 2600000.5, 1200000.5),
size=(300, 100),
format="image/png",
transparent=False,
styles=["localized_labels"],
language=language,
)
file_root = f"labels/no_default_locale/default_value/language_{language}"
write_actual_image(response, file_root)
compare_images(RESOURCE_DIR, file_root)
@pytest.mark.parametrize("language", ["it", "", None])
def test_i18n_labels_no_default_value(geoserver_i18n_label_layer, language):
response = geoserver_i18n_label_layer.get_map(
layers=["i18n_labels"],
bbox=(2699999.5, 1299999.5, 2700000.5, 1300000.5),
size=(300, 100),
format="image/png",
transparent=False,
styles=["localized_labels"],
language=language,
)
file_root = f"labels/no_default_locale/no_default_value/language_{language}"
write_actual_image(response, file_root)
compare_images(RESOURCE_DIR, file_root)
@pytest.mark.parametrize("language", ["de", "fr", "it", None, ""])
def test_i18n_labels_default_locale(geoserver_i18n_label_default_locale_fr, language):
response = geoserver_i18n_label_default_locale_fr.get_map(
layers=["i18n_labels"],
bbox=(2599999.5, 1199999.5, 2600000.5, 1200000.5),
size=(300, 100),
format="image/png",
transparent=False,
styles=["localized_labels"],
language=language,
)
file_root = f"labels/default_locale/default_value/language_{language}"
write_actual_image(response, file_root)
compare_images(RESOURCE_DIR, file_root)
@pytest.mark.parametrize("language", ["it", "", None])
def test_i18n_labels_no_default_value_default_locale(
geoserver_i18n_label_default_locale_fr, language
):
response = geoserver_i18n_label_default_locale_fr.get_map(
layers=["i18n_labels"],
bbox=(2699999.5, 1299999.5, 2700000.5, 1300000.5),
size=(300, 100),
format="image/png",
transparent=False,
styles=["localized_labels"],
language=language,
)
file_root = f"labels/default_locale/no_default_value/language_{language}"
write_actual_image(response, file_root)
compare_images(RESOURCE_DIR, file_root)

View File

@ -0,0 +1,76 @@
from conftest import (
PGDATABASE,
PGHOST,
PGPASSWORD,
PGPORT,
PGSCHEMA,
PGUSER,
RESOURCE_DIR,
)
def test_wfs(geoserver):
workspace = datastore = feature_type = "test_wfs"
attributes = {
"geom": {
"type": "Point",
"required": True,
},
"id": {
"type": "integer",
"required": True,
},
"title": {
"type": "string",
"required": False,
},
"timestamp": {
"type": "datetime",
"required": False,
},
}
response = geoserver.create_workspace(workspace, set_default_workspace=True)
assert response.status_code == 201
response = geoserver.create_pg_datastore(
workspace=workspace,
datastore=datastore,
pg_host=PGHOST,
pg_port=PGPORT,
pg_db=PGDATABASE,
pg_user=PGUSER,
pg_password=PGPASSWORD,
pg_schema=PGSCHEMA,
set_default_datastore=True,
)
assert response.status_code == 201
response = geoserver.create_feature_type(
feature_type, attributes=attributes, epsg=2056
)
assert response.status_code == 201
# Post a feature through a WFS request
with open(f"{RESOURCE_DIR}/wfs_payload.xml") as file:
data = file.read()
response = geoserver.post_request(f"/{workspace}/wfs/", data=data)
assert response.status_code == 200
# GetFeature request
feature_collection = geoserver.get_feature(workspace, feature_type)
assert type(feature_collection) is dict
assert type(feature_collection.get("features")) is list
feature = feature_collection["features"][0]
properties = feature.get("properties")
assert properties.get("id") == 10
assert properties.get("title") == "Title"
assert properties.get("timestamp") == "2024-05-13T08:14:48.763Z"
assert feature.get("geometry", {}) == {
"type": "Point",
"coordinates": [2600000, 1200000],
}
assert feature_collection.get("crs") == {
"type": "name",
"properties": {"name": "urn:ogc:def:crs:EPSG::2056"},
}
response = geoserver.delete_workspace(workspace)
assert response.status_code == 200

View File

@ -0,0 +1,128 @@
import json
from conftest import (
PGDATABASE,
PGHOST,
PGPASSWORD,
PGPORT,
PGSCHEMA,
PGUSER,
RESOURCE_DIR,
)
from lib.utils import compare_images, write_actual_image
from sqlalchemy.sql import text
def test_create_and_feature_type_and_get_map(db_session, geoserver):
workspace = datastore = feature_type = "test_create_feature_type"
geoserver.create_workspace(workspace, set_default_workspace=True)
geoserver.create_pg_datastore(
workspace=workspace,
datastore=datastore,
pg_host=PGHOST,
pg_port=PGPORT,
pg_db=PGDATABASE,
pg_user=PGUSER,
pg_password=PGPASSWORD,
pg_schema=PGSCHEMA,
set_default_datastore=True,
)
response = geoserver.create_feature_type(
feature_type,
epsg=2056,
)
assert response.status_code == 201
# Create feature
db_session.execute(
text(
f"INSERT INTO {feature_type} (geom) VALUES (public.ST_SetSRID(public.ST_MakePoint(2600000, 1200000), 2056))"
)
)
db_session.commit()
# GetMap request
response = geoserver.get_map(
layers=[feature_type],
bbox=(2599999.5, 1199999.5, 2600000.5, 1200000.5),
size=(40, 40),
format="image/png",
transparent=False,
)
file_root = f"getmap"
write_actual_image(response, file_root)
compare_images(RESOURCE_DIR, file_root)
geoserver.delete_workspace(workspace)
def test_get_feature_info(db_session, geoserver):
workspace = datastore = feature_type = "test_get_feature_info"
attributes = {
"geom": {
"type": "Point",
"required": True,
},
"label": {
"type": "string",
"required": False,
},
}
response = geoserver.create_workspace(workspace, set_default_workspace=True)
assert response.status_code == 201
response = geoserver.create_pg_datastore(
workspace=workspace,
datastore=datastore,
pg_host=PGHOST,
pg_port=PGPORT,
pg_db=PGDATABASE,
pg_user=PGUSER,
pg_password=PGPASSWORD,
pg_schema=PGSCHEMA,
set_default_datastore=True,
)
assert response.status_code == 201
response = geoserver.create_feature_type(
feature_type, attributes=attributes, epsg=2056
)
assert response.status_code == 201
# Create feature
db_session.execute(
text(
f"INSERT INTO {feature_type} (geom, label) VALUES "
"(public.ST_SetSRID(public.ST_MakePoint(2600000, 1200000), 2056), 'Label')"
)
)
db_session.commit()
# Test that layer is published
response = geoserver.get_request(f"/rest/layers/{workspace}:{feature_type}.json")
assert response.status_code == 200
# GetFeatureInfo request
response = geoserver.get_feature_info(
layers=[feature_type],
bbox=(2599999.5, 1199999.5, 2600000.5, 1200000.5),
size=(40, 40),
info_format="application/json",
xy=(20, 20),
)
data = json.loads(response.read().decode("utf-8"))
feature = data.get("features", [])[0]
assert feature
assert feature.get("properties").get("label") == "Label"
assert feature.get("geometry") == {
"type": "Point",
"coordinates": [2600000, 1200000],
}
assert data.get("crs") == {
"type": "name",
"properties": {"name": "urn:ogc:def:crs:EPSG::2056"},
}
response = geoserver.delete_workspace(workspace)
assert response.status_code == 200

View File

@ -1,3 +1,4 @@
\c geodata \c geodata
CREATE SCHEMA IF NOT EXISTS test1; CREATE SCHEMA IF NOT EXISTS test1;
CREATE SCHEMA IF NOT EXISTS test2; CREATE SCHEMA IF NOT EXISTS test2;
CREATE EXTENSION IF NOT EXISTS postgis;