[#97] The tests that ckanext-spatial deserves
Completely reviewed and refactored tests to support both CKAN 2.2/2.3, geoalchemy 1/2 and PostGIS 1/2 (TODO test on PostGIS 1.5) Removed all references to legacy ckan tests, and removed old or incomplete tests.
This commit is contained in:
parent
a23ec96b2b
commit
50df9130cf
|
@ -76,7 +76,7 @@ class GeminiHarvester(SpatialHarvester):
|
|||
self._save_object_error('Error importing Gemini document.', harvest_object, 'Import')
|
||||
else:
|
||||
self._save_object_error('Error importing Gemini document: %s' % str(e), harvest_object, 'Import')
|
||||
|
||||
raise
|
||||
if debug_exception_mode:
|
||||
raise
|
||||
|
||||
|
@ -356,10 +356,6 @@ class GeminiHarvester(SpatialHarvester):
|
|||
self.obj.current = True
|
||||
self.obj.save()
|
||||
|
||||
|
||||
assert gemini_guid == [e['value'] for e in package['extras'] if e['key'] == 'guid'][0]
|
||||
assert self.obj.id == [e['value'] for e in package['extras'] if e['key'] == 'harvest_object_id'][0]
|
||||
|
||||
return package
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -126,6 +126,7 @@ class SpatialMetadata(p.SingletonPlugin):
|
|||
error_dict = {'spatial':[u'Error creating geometry: %s' % str(e)]}
|
||||
raise p.toolkit.ValidationError(error_dict, error_summary=package_error_summary(error_dict))
|
||||
except Exception, e:
|
||||
raise
|
||||
if bool(os.getenv('DEBUG')):
|
||||
raise
|
||||
error_dict = {'spatial':[u'Error: %s' % str(e)]}
|
||||
|
|
|
@ -5,27 +5,10 @@ from sqlalchemy import Table
|
|||
from nose.plugins.skip import SkipTest
|
||||
|
||||
from ckan.model import Session, repo, meta, engine_is_sqlite
|
||||
from ckanext.spatial.model.package_extent import setup as spatial_db_setup, define_spatial_tables
|
||||
from ckanext.spatial.model.package_extent import setup as spatial_db_setup
|
||||
from ckanext.harvest.model import setup as harvest_model_setup
|
||||
|
||||
def setup_postgis_tables():
|
||||
|
||||
conn = Session.connection()
|
||||
script_path = os.path.join(os.path.dirname(os.path.abspath( __file__ )), 'scripts', 'postgis.sql')
|
||||
script = open(script_path,'r').read()
|
||||
for cmd in script.split(';'):
|
||||
cmd = re.sub(r'--(.*)|[\n\t]','',cmd)
|
||||
if len(cmd):
|
||||
conn.execute(cmd)
|
||||
|
||||
Session.commit()
|
||||
|
||||
|
||||
class SpatialTestBase:
|
||||
|
||||
db_srid = 4326
|
||||
|
||||
geojson_examples = {
|
||||
geojson_examples = {
|
||||
'point':'{"type":"Point","coordinates":[100.0,0.0]}',
|
||||
'point_2':'{"type":"Point","coordinates":[20,10]}',
|
||||
'line':'{"type":"LineString","coordinates":[[100.0,0.0],[101.0,1.0]]}',
|
||||
|
@ -35,16 +18,59 @@ class SpatialTestBase:
|
|||
'multiline':'{"type":"MultiLineString","coordinates":[[[100.0,0.0],[101.0,1.0]],[[102.0,2.0],[103.0,3.0]]]}',
|
||||
'multipolygon':'{"type":"MultiPolygon","coordinates":[[[[102.0,2.0],[103.0,2.0],[103.0,3.0],[102.0,3.0],[102.0,2.0]]],[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]],[[100.2,0.2],[100.8,0.2],[100.8,0.8],[100.2,0.8],[100.2,0.2]]]]}'}
|
||||
|
||||
|
||||
def postgis_version():
|
||||
|
||||
result = Session.execute('SELECT postgis_lib_version()')
|
||||
|
||||
return result.scalar()
|
||||
|
||||
|
||||
def _execute_script(script_path):
|
||||
|
||||
conn = Session.connection()
|
||||
script = open(script_path, 'r').read()
|
||||
for cmd in script.split(';'):
|
||||
cmd = re.sub(r'--(.*)|[\n\t]', '', cmd)
|
||||
if len(cmd):
|
||||
conn.execute(cmd)
|
||||
|
||||
Session.commit()
|
||||
|
||||
|
||||
def create_postgis_tables():
|
||||
scripts_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
'scripts')
|
||||
if postgis_version()[:1] == '1':
|
||||
_execute_script(os.path.join(scripts_path, 'spatial_ref_sys.sql'))
|
||||
_execute_script(os.path.join(scripts_path, 'geometry_columns.sql'))
|
||||
else:
|
||||
_execute_script(os.path.join(scripts_path, 'spatial_ref_sys.sql'))
|
||||
|
||||
|
||||
class SpatialTestBase(object):
|
||||
|
||||
db_srid = 4326
|
||||
|
||||
geojson_examples = geojson_examples
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
if engine_is_sqlite():
|
||||
raise SkipTest("PostGIS is required for this test")
|
||||
|
||||
|
||||
# This will create the PostGIS tables (geometry_columns and
|
||||
# spatial_ref_sys) which were deleted when rebuilding the database
|
||||
table = Table('geometry_columns', meta.metadata)
|
||||
table = Table('spatial_ref_sys', meta.metadata)
|
||||
if not table.exists():
|
||||
setup_postgis_tables()
|
||||
create_postgis_tables()
|
||||
|
||||
# When running the tests with the --reset-db option for some
|
||||
# reason the metadata holds a reference to the `package_extent`
|
||||
# table after being deleted, causing an InvalidRequestError
|
||||
# exception when trying to recreate it further on
|
||||
if 'package_extent' in meta.metadata.tables:
|
||||
meta.metadata.remove(meta.metadata.tables['package_extent'])
|
||||
|
||||
spatial_db_setup()
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import logging
|
||||
from pprint import pprint
|
||||
|
||||
from ckan.model import Package, Session
|
||||
from ckan import model
|
||||
from ckan.lib.helpers import url_for,json
|
||||
|
||||
from ckan.tests import CreateTestData
|
||||
from ckan.tests.functional.base import FunctionalTestCase
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestDatasetMap(FunctionalTestCase,SpatialTestBase):
|
||||
def setup(self):
|
||||
CreateTestData.create()
|
||||
|
||||
def teardown(self):
|
||||
model.repo.rebuild_db()
|
||||
|
||||
def test_map_shown(self):
|
||||
extra_environ = {'REMOTE_USER': 'annafan'}
|
||||
name = 'annakarenina'
|
||||
|
||||
offset = url_for(controller='package', action='edit',id=name)
|
||||
res = self.app.get(offset, extra_environ=extra_environ)
|
||||
assert 'Edit - Datasets' in res
|
||||
fv = res.forms['dataset-edit']
|
||||
prefix = ''
|
||||
fv[prefix+'extras__1__key'] = u'spatial'
|
||||
fv[prefix+'extras__1__value'] = self.geojson_examples['point']
|
||||
|
||||
res = fv.submit('save', extra_environ=extra_environ)
|
||||
assert not 'Error' in res, res
|
||||
|
||||
# Load the dataset page and check if the libraries have been loaded
|
||||
offset = url_for(controller='package', action='read',id=name)
|
||||
res = self.app.get(offset)
|
||||
|
||||
assert '<div class="dataset-map subsection">' in res, res
|
||||
assert '<script type="text/javascript" src="/ckanext/spatial/js/dataset_map.js"></script>' in res
|
||||
assert self.geojson_examples['point'] in res
|
|
@ -1,141 +1,143 @@
|
|||
import logging
|
||||
from pprint import pprint
|
||||
import json
|
||||
from nose.tools import assert_equals
|
||||
|
||||
from ckan.model import Package, Session
|
||||
from ckan.lib.helpers import url_for,json
|
||||
from ckan.model import Session
|
||||
from ckan.lib.helpers import url_for
|
||||
|
||||
import ckan.new_tests.helpers as helpers
|
||||
import ckan.new_tests.factories as factories
|
||||
|
||||
from ckan.tests import CreateTestData
|
||||
from ckan.tests.functional.base import FunctionalTestCase
|
||||
from ckanext.spatial.model import PackageExtent
|
||||
|
||||
from ckanext.spatial.geoalchemy_common import legacy_geoalchemy
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class TestSpatialExtra(SpatialTestBase, helpers.FunctionalTestBase):
|
||||
|
||||
class TestPackageController(FunctionalTestCase,SpatialTestBase):
|
||||
def test_spatial_extra(self):
|
||||
app = self._get_test_app()
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
SpatialTestBase.setup_class()
|
||||
cls.extra_environ = {'REMOTE_USER': 'annafan'}
|
||||
user = factories.User()
|
||||
env = {'REMOTE_USER': user['name'].encode('ascii')}
|
||||
dataset = factories.Dataset(user=user)
|
||||
|
||||
def setup(self):
|
||||
CreateTestData.create()
|
||||
offset = url_for(controller='package', action='edit', id=dataset['id'])
|
||||
res = app.get(offset, extra_environ=env)
|
||||
|
||||
def teardown(self):
|
||||
CreateTestData.delete()
|
||||
form = res.forms[1]
|
||||
form['extras__0__key'] = u'spatial'
|
||||
form['extras__0__value'] = self.geojson_examples['point']
|
||||
|
||||
def test_new(self):
|
||||
name = 'test-spatial-dataset-1'
|
||||
res = helpers.submit_and_follow(app, form, env, 'save')
|
||||
|
||||
offset = url_for(controller='package', action='new')
|
||||
res = self.app.get(offset, extra_environ=self.extra_environ)
|
||||
assert 'Add - Datasets' in res
|
||||
fv = res.forms['dataset-edit']
|
||||
prefix = ''
|
||||
fv[prefix + 'name'] = name
|
||||
fv[prefix+'extras__0__key'] = u'spatial'
|
||||
fv[prefix+'extras__0__value'] = self.geojson_examples['point']
|
||||
assert 'Error' not in res, res
|
||||
|
||||
res = fv.submit('save', extra_environ=self.extra_environ)
|
||||
assert not 'Error' in res, res
|
||||
|
||||
package = Package.get(name)
|
||||
|
||||
# Check that a PackageExtent object has been created
|
||||
package_extent = Session.query(PackageExtent).filter(PackageExtent.package_id==package.id).first()
|
||||
package_extent = Session.query(PackageExtent) \
|
||||
.filter(PackageExtent.package_id == dataset['id']).first()
|
||||
|
||||
geojson = json.loads(self.geojson_examples['point'])
|
||||
|
||||
assert package_extent
|
||||
assert package_extent.package_id == package.id
|
||||
assert Session.scalar(package_extent.the_geom.x) == geojson['coordinates'][0]
|
||||
assert Session.scalar(package_extent.the_geom.y) == geojson['coordinates'][1]
|
||||
assert Session.scalar(package_extent.the_geom.srid) == self.db_srid
|
||||
assert_equals(package_extent.package_id, dataset['id'])
|
||||
if legacy_geoalchemy:
|
||||
assert_equals(Session.scalar(package_extent.the_geom.x),
|
||||
geojson['coordinates'][0])
|
||||
assert_equals(Session.scalar(package_extent.the_geom.y),
|
||||
geojson['coordinates'][1])
|
||||
assert_equals(Session.scalar(package_extent.the_geom.srid),
|
||||
self.db_srid)
|
||||
else:
|
||||
from sqlalchemy import func
|
||||
assert_equals(
|
||||
Session.query(func.ST_X(package_extent.the_geom)).first()[0],
|
||||
geojson['coordinates'][0])
|
||||
assert_equals(
|
||||
Session.query(func.ST_Y(package_extent.the_geom)).first()[0],
|
||||
geojson['coordinates'][1])
|
||||
assert_equals(package_extent.the_geom.srid, self.db_srid)
|
||||
|
||||
def test_new_bad_json(self):
|
||||
name = 'test-spatial-dataset-2'
|
||||
def test_spatial_extra_edit(self):
|
||||
app = self._get_test_app()
|
||||
|
||||
offset = url_for(controller='package', action='new')
|
||||
res = self.app.get(offset, extra_environ=self.extra_environ)
|
||||
assert 'Add - Datasets' in res
|
||||
fv = res.forms['dataset-edit']
|
||||
prefix = ''
|
||||
fv[prefix + 'name'] = name
|
||||
fv[prefix+'extras__0__key'] = u'spatial'
|
||||
fv[prefix+'extras__0__value'] = u'{"Type":Bad Json]'
|
||||
user = factories.User()
|
||||
env = {'REMOTE_USER': user['name'].encode('ascii')}
|
||||
dataset = factories.Dataset(user=user)
|
||||
|
||||
offset = url_for(controller='package', action='edit', id=dataset['id'])
|
||||
res = app.get(offset, extra_environ=env)
|
||||
|
||||
form = res.forms[1]
|
||||
form['extras__0__key'] = u'spatial'
|
||||
form['extras__0__value'] = self.geojson_examples['point']
|
||||
|
||||
res = helpers.submit_and_follow(app, form, env, 'save')
|
||||
|
||||
assert 'Error' not in res, res
|
||||
|
||||
res = app.get(offset, extra_environ=env)
|
||||
|
||||
form = res.forms[1]
|
||||
form['extras__0__key'] = u'spatial'
|
||||
form['extras__0__value'] = self.geojson_examples['polygon']
|
||||
|
||||
res = helpers.submit_and_follow(app, form, env, 'save')
|
||||
|
||||
assert 'Error' not in res, res
|
||||
|
||||
package_extent = Session.query(PackageExtent) \
|
||||
.filter(PackageExtent.package_id == dataset['id']).first()
|
||||
|
||||
assert_equals(package_extent.package_id, dataset['id'])
|
||||
if legacy_geoalchemy:
|
||||
assert_equals(
|
||||
Session.scalar(package_extent.the_geom.geometry_type),
|
||||
'ST_Polygon')
|
||||
assert_equals(
|
||||
Session.scalar(package_extent.the_geom.srid),
|
||||
self.db_srid)
|
||||
else:
|
||||
from sqlalchemy import func
|
||||
assert_equals(
|
||||
Session.query(
|
||||
func.ST_GeometryType(package_extent.the_geom)).first()[0],
|
||||
'ST_Polygon')
|
||||
assert_equals(package_extent.the_geom.srid, self.db_srid)
|
||||
|
||||
def test_spatial_extra_bad_json(self):
|
||||
app = self._get_test_app()
|
||||
|
||||
user = factories.User()
|
||||
env = {'REMOTE_USER': user['name'].encode('ascii')}
|
||||
dataset = factories.Dataset(user=user)
|
||||
|
||||
offset = url_for(controller='package', action='edit', id=dataset['id'])
|
||||
res = app.get(offset, extra_environ=env)
|
||||
|
||||
form = res.forms[1]
|
||||
form['extras__0__key'] = u'spatial'
|
||||
form['extras__0__value'] = u'{"Type":Bad Json]'
|
||||
|
||||
res = helpers.webtest_submit(form, extra_environ=env, name='save')
|
||||
|
||||
res = fv.submit('save', extra_environ=self.extra_environ)
|
||||
assert 'Error' in res, res
|
||||
assert 'Spatial' in res
|
||||
assert 'Error decoding JSON object' in res
|
||||
|
||||
# Check that package was not created
|
||||
assert not Package.get(name)
|
||||
def test_spatial_extra_bad_geojson(self):
|
||||
app = self._get_test_app()
|
||||
|
||||
def test_new_bad_geojson(self):
|
||||
name = 'test-spatial-dataset-3'
|
||||
user = factories.User()
|
||||
env = {'REMOTE_USER': user['name'].encode('ascii')}
|
||||
dataset = factories.Dataset(user=user)
|
||||
|
||||
offset = url_for(controller='package', action='new')
|
||||
res = self.app.get(offset, extra_environ=self.extra_environ)
|
||||
assert 'Add - Datasets' in res
|
||||
fv = res.forms['dataset-edit']
|
||||
prefix = ''
|
||||
fv[prefix + 'name'] = name
|
||||
fv[prefix+'extras__0__key'] = u'spatial'
|
||||
fv[prefix+'extras__0__value'] = u'{"Type":"Bad_GeoJSON","a":2}'
|
||||
offset = url_for(controller='package', action='edit', id=dataset['id'])
|
||||
res = app.get(offset, extra_environ=env)
|
||||
|
||||
form = res.forms[1]
|
||||
form['extras__0__key'] = u'spatial'
|
||||
form['extras__0__value'] = u'{"Type":"Bad_GeoJSON","a":2}'
|
||||
|
||||
res = helpers.webtest_submit(form, extra_environ=env, name='save')
|
||||
|
||||
res = fv.submit('save', extra_environ=self.extra_environ)
|
||||
assert 'Error' in res, res
|
||||
assert 'Spatial' in res
|
||||
assert 'Error creating geometry' in res
|
||||
|
||||
# Check that package was not created
|
||||
assert not Package.get(name)
|
||||
|
||||
def test_edit(self):
|
||||
|
||||
name = 'annakarenina'
|
||||
|
||||
offset = url_for(controller='package', action='edit',id=name)
|
||||
res = self.app.get(offset, extra_environ=self.extra_environ)
|
||||
assert 'Edit - Datasets' in res
|
||||
fv = res.forms['dataset-edit']
|
||||
prefix = ''
|
||||
fv[prefix+'extras__1__key'] = u'spatial'
|
||||
fv[prefix+'extras__1__value'] = self.geojson_examples['point']
|
||||
|
||||
res = fv.submit('save', extra_environ=self.extra_environ)
|
||||
assert not 'Error' in res, res
|
||||
|
||||
package = Package.get(name)
|
||||
|
||||
# Check that a PackageExtent object has been created
|
||||
package_extent = Session.query(PackageExtent).filter(PackageExtent.package_id==package.id).first()
|
||||
geojson = json.loads(self.geojson_examples['point'])
|
||||
|
||||
assert package_extent
|
||||
assert package_extent.package_id == package.id
|
||||
assert Session.scalar(package_extent.the_geom.x) == geojson['coordinates'][0]
|
||||
assert Session.scalar(package_extent.the_geom.y) == geojson['coordinates'][1]
|
||||
assert Session.scalar(package_extent.the_geom.srid) == self.db_srid
|
||||
|
||||
# Update the spatial extra
|
||||
offset = url_for(controller='package', action='edit',id=name)
|
||||
res = self.app.get(offset, extra_environ=self.extra_environ)
|
||||
assert 'Edit - Datasets' in res
|
||||
fv = res.forms['dataset-edit']
|
||||
prefix = ''
|
||||
fv[prefix+'extras__1__value'] = self.geojson_examples['polygon']
|
||||
|
||||
res = fv.submit('save', extra_environ=self.extra_environ)
|
||||
assert not 'Error' in res, res
|
||||
|
||||
# Check that the PackageExtent object has been updated
|
||||
package_extent = Session.query(PackageExtent).filter(PackageExtent.package_id==package.id).first()
|
||||
assert package_extent
|
||||
assert package_extent.package_id == package.id
|
||||
assert Session.scalar(package_extent.the_geom.geometry_type) == 'ST_Polygon'
|
||||
assert Session.scalar(package_extent.the_geom.srid) == self.db_srid
|
||||
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import logging
|
||||
from pylons import config
|
||||
|
||||
from ckan.lib.helpers import url_for
|
||||
|
||||
from ckan.tests.functional.base import FunctionalTestCase
|
||||
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestSpatialQueryWidget(FunctionalTestCase,SpatialTestBase):
|
||||
|
||||
def test_widget_shown(self):
|
||||
# Load the dataset search page and check if the libraries have been loaded
|
||||
offset = url_for(controller='package', action='search')
|
||||
res = self.app.get(offset)
|
||||
|
||||
assert '<div id="spatial-search-container">' in res, res
|
||||
assert '<script type="text/javascript" src="/ckanext/spatial/js/spatial_search_form.js"></script>' in res
|
||||
assert config.get('ckan.spatial.default_extent') in res
|
|
@ -0,0 +1,34 @@
|
|||
from ckan.lib.helpers import url_for
|
||||
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
import ckan.new_tests.helpers as helpers
|
||||
import ckan.new_tests.factories as factories
|
||||
|
||||
|
||||
class TestSpatialWidgets(SpatialTestBase, helpers.FunctionalTestBase):
|
||||
|
||||
def test_dataset_map(self):
|
||||
app = self._get_test_app()
|
||||
|
||||
user = factories.User()
|
||||
dataset = factories.Dataset(
|
||||
user=user,
|
||||
extras=[{'key': 'spatial',
|
||||
'value': self.geojson_examples['point']}]
|
||||
)
|
||||
offset = url_for(controller='package', action='read', id=dataset['id'])
|
||||
res = app.get(offset)
|
||||
|
||||
assert 'data-module="dataset-map"' in res
|
||||
assert 'dataset_map.js' in res
|
||||
|
||||
def test_spatial_search_widget(self):
|
||||
|
||||
app = self._get_test_app()
|
||||
|
||||
offset = url_for(controller='package', action='search')
|
||||
res = app.get(offset)
|
||||
|
||||
assert 'data-module="spatial-query"' in res
|
||||
assert 'spatial_query.js' in res
|
|
@ -1,65 +0,0 @@
|
|||
import logging
|
||||
from pprint import pprint
|
||||
from ckan import model
|
||||
from ckan.model import Package, Resource
|
||||
from ckan.lib.helpers import url_for,json
|
||||
|
||||
from ckan.tests import CreateTestData
|
||||
from ckan.tests.functional.base import FunctionalTestCase
|
||||
from ckanext.harvest.model import setup as harvest_model_setup
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TestWMSPreview(FunctionalTestCase,SpatialTestBase):
|
||||
|
||||
def setup(self):
|
||||
CreateTestData.create()
|
||||
|
||||
def teardown(self):
|
||||
model.repo.rebuild_db()
|
||||
|
||||
def test_link_and_map_shown(self):
|
||||
from nose.plugins.skip import SkipTest
|
||||
raise SkipTest('TODO: Need to update this to use logic functions')
|
||||
|
||||
name = u'annakarenina'
|
||||
|
||||
wms_url = 'http://maps.bgs.ac.uk/ArcGIS/services/BGS_Detailed_Geology/MapServer/WMSServer?'
|
||||
rev = model.repo.new_revision()
|
||||
pkg = Package.get(name)
|
||||
pr = Resource(url=wms_url,format='WMS')
|
||||
pkg.resources.append(pr)
|
||||
pkg.save()
|
||||
model.repo.commit_and_remove()
|
||||
# Load the dataset page and check if link appears
|
||||
offset = url_for(controller='package', action='read',id=name)
|
||||
res = self.app.get(offset)
|
||||
|
||||
assert 'View available WMS layers' in res, res
|
||||
|
||||
# Load the dataset map preview page and check if libraries are loaded
|
||||
offset = '/dataset/%s/map' % name
|
||||
res = self.app.get(offset)
|
||||
assert '<script type="text/javascript" src="/ckanext/spatial/js/wms_preview.js"></script>' in res, res
|
||||
assert 'CKAN.WMSPreview.setup("%s");' % wms_url.split('?')[0] in res
|
||||
|
||||
def test_link_and_map_not_shown(self):
|
||||
|
||||
name = 'annakarenina'
|
||||
|
||||
offset = url_for(controller='package', action='read',id=name)
|
||||
|
||||
# Load the dataset page and check that link does not appear
|
||||
offset = url_for(controller='package', action='read',id=name)
|
||||
res = self.app.get(offset)
|
||||
|
||||
assert not 'View available WMS layers' in res, res
|
||||
|
||||
# Load the dataset map preview page and check that libraries are not loaded
|
||||
offset = '/dataset/%s/map' % name
|
||||
res = self.app.get(offset, status=400)
|
||||
assert '400 Bad Request' in res, res
|
||||
assert 'This dataset does not have a WMS resource' in res
|
||||
assert not '<script type="text/javascript" src="/ckanext/spatial/js/wms_preview.js"></script>' in res
|
|
@ -1,61 +1,87 @@
|
|||
import logging
|
||||
from pprint import pprint
|
||||
|
||||
from geoalchemy import WKTSpatialElement
|
||||
|
||||
from nose.tools import assert_equals
|
||||
from shapely.geometry import asShape
|
||||
from ckan.model import Session, Package
|
||||
from ckan import model
|
||||
|
||||
from ckan.model import Session
|
||||
from ckan.lib.helpers import json
|
||||
from ckan.tests import CreateTestData
|
||||
from ckan.new_tests import factories
|
||||
|
||||
from ckanext.spatial.model import PackageExtent
|
||||
|
||||
from ckanext.spatial.geoalchemy_common import WKTElement, legacy_geoalchemy
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
||||
class TestPackageExtent(SpatialTestBase):
|
||||
def setup(self):
|
||||
CreateTestData.create()
|
||||
|
||||
def teardown(self):
|
||||
model.repo.rebuild_db()
|
||||
|
||||
def test_create_extent(self):
|
||||
package = Package.get('annakarenina')
|
||||
assert package
|
||||
|
||||
package = factories.Dataset()
|
||||
|
||||
geojson = json.loads(self.geojson_examples['point'])
|
||||
|
||||
shape = asShape(geojson)
|
||||
package_extent = PackageExtent(package_id=package.id,the_geom=WKTSpatialElement(shape.wkt, self.db_srid))
|
||||
package_extent = PackageExtent(package_id=package['id'],
|
||||
the_geom=WKTElement(shape.wkt,
|
||||
self.db_srid))
|
||||
package_extent.save()
|
||||
|
||||
assert package_extent.package_id == package.id
|
||||
assert Session.scalar(package_extent.the_geom.x) == geojson['coordinates'][0]
|
||||
assert Session.scalar(package_extent.the_geom.y) == geojson['coordinates'][1]
|
||||
assert Session.scalar(package_extent.the_geom.srid) == self.db_srid
|
||||
assert_equals(package_extent.package_id, package['id'])
|
||||
if legacy_geoalchemy:
|
||||
assert_equals(Session.scalar(package_extent.the_geom.x),
|
||||
geojson['coordinates'][0])
|
||||
assert_equals(Session.scalar(package_extent.the_geom.y),
|
||||
geojson['coordinates'][1])
|
||||
assert_equals(Session.scalar(package_extent.the_geom.srid),
|
||||
self.db_srid)
|
||||
else:
|
||||
from sqlalchemy import func
|
||||
assert_equals(
|
||||
Session.query(func.ST_X(package_extent.the_geom)).first()[0],
|
||||
geojson['coordinates'][0])
|
||||
assert_equals(
|
||||
Session.query(func.ST_Y(package_extent.the_geom)).first()[0],
|
||||
geojson['coordinates'][1])
|
||||
assert_equals(package_extent.the_geom.srid, self.db_srid)
|
||||
|
||||
def test_update_extent(self):
|
||||
|
||||
package = Package.get('annakarenina')
|
||||
package = factories.Dataset()
|
||||
|
||||
geojson = json.loads(self.geojson_examples['point'])
|
||||
|
||||
shape = asShape(geojson)
|
||||
package_extent = PackageExtent(package_id=package.id,the_geom=WKTSpatialElement(shape.wkt, self.db_srid))
|
||||
package_extent = PackageExtent(package_id=package['id'],
|
||||
the_geom=WKTElement(shape.wkt,
|
||||
self.db_srid))
|
||||
package_extent.save()
|
||||
assert Session.scalar(package_extent.the_geom.geometry_type) == 'ST_Point'
|
||||
if legacy_geoalchemy:
|
||||
assert_equals(
|
||||
Session.scalar(package_extent.the_geom.geometry_type),
|
||||
'ST_Point')
|
||||
else:
|
||||
from sqlalchemy import func
|
||||
assert_equals(
|
||||
Session.query(
|
||||
func.ST_GeometryType(package_extent.the_geom)).first()[0],
|
||||
'ST_Point')
|
||||
|
||||
# Update the geometry (Point -> Polygon)
|
||||
geojson = json.loads(self.geojson_examples['polygon'])
|
||||
|
||||
shape = asShape(geojson)
|
||||
package_extent.the_geom=WKTSpatialElement(shape.wkt, self.db_srid)
|
||||
package_extent.the_geom = WKTElement(shape.wkt, self.db_srid)
|
||||
package_extent.save()
|
||||
|
||||
assert package_extent.package_id == package.id
|
||||
assert Session.scalar(package_extent.the_geom.geometry_type) == 'ST_Polygon'
|
||||
assert Session.scalar(package_extent.the_geom.srid) == self.db_srid
|
||||
assert_equals(package_extent.package_id, package['id'])
|
||||
if legacy_geoalchemy:
|
||||
assert_equals(
|
||||
Session.scalar(package_extent.the_geom.geometry_type),
|
||||
'ST_Polygon')
|
||||
assert_equals(
|
||||
Session.scalar(package_extent.the_geom.srid),
|
||||
self.db_srid)
|
||||
else:
|
||||
assert_equals(
|
||||
Session.query(
|
||||
func.ST_GeometryType(package_extent.the_geom)).first()[0],
|
||||
'ST_Polygon')
|
||||
assert_equals(package_extent.the_geom.srid, self.db_srid)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
-------------------------------------------------------------------
|
||||
-- WARNING: This is probably NOT the file you are looking for.
|
||||
-- This file is intended to be used only during tests, you won't
|
||||
-- get a functional PostGIS database executing it. Please install
|
||||
-- PostGIS as described in the README.
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- GEOMETRY_COLUMNS
|
||||
-------------------------------------------------------------------
|
||||
CREATE TABLE geometry_columns (
|
||||
f_table_catalog varchar(256) not null,
|
||||
f_table_schema varchar(256) not null,
|
||||
f_table_name varchar(256) not null,
|
||||
f_geometry_column varchar(256) not null,
|
||||
coord_dimension integer not null,
|
||||
srid integer not null,
|
||||
type varchar(30) not null,
|
||||
CONSTRAINT geometry_columns_pk primary key (
|
||||
f_table_catalog,
|
||||
f_table_schema,
|
||||
f_table_name,
|
||||
f_geometry_column )
|
||||
) WITH OIDS;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
-------------------------------------------------------------------
|
||||
-- WARNING: This is probably NOT the file you are looking for.
|
||||
-- This file is intended to be used only during tests, you won't
|
||||
-- get a functional PostGIS database executing it. Please install
|
||||
-- PostGIS as described in the README.
|
||||
-------------------------------------------------------------------
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- SPATIAL_REF_SYS
|
||||
-------------------------------------------------------------------
|
||||
CREATE TABLE spatial_ref_sys (
|
||||
srid integer not null primary key,
|
||||
auth_name varchar(256),
|
||||
auth_srid integer,
|
||||
srtext varchar(2048),
|
||||
proj4text varchar(2048)
|
||||
);
|
||||
|
||||
---
|
||||
--- EPSG 4326 : WGS 84
|
||||
---
|
||||
INSERT INTO "spatial_ref_sys" ("srid","auth_name","auth_srid","srtext","proj4text") VALUES (4326,'EPSG',4326,'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ');
|
||||
|
|
@ -1,217 +1,147 @@
|
|||
import logging
|
||||
import json
|
||||
from pprint import pprint
|
||||
from nose.plugins.skip import SkipTest
|
||||
from nose.tools import assert_equal, assert_raises
|
||||
from ckan.logic.action.create import package_create
|
||||
from ckan.logic.action.delete import package_delete
|
||||
from ckan.logic.schema import default_create_package_schema
|
||||
from ckan import model
|
||||
from nose.tools import assert_equals, assert_raises
|
||||
|
||||
from ckan.model import Session
|
||||
from ckan.lib.search import SearchError
|
||||
import ckan.new_tests.helpers as helpers
|
||||
import ckan.new_tests.factories as factories
|
||||
|
||||
from ckan.model import Package, Session
|
||||
import ckan.lib.search as search
|
||||
from ckan.tests import CreateTestData, setup_test_search_index,WsgiAppCase
|
||||
from ckan.tests.functional.api.base import ApiTestCase
|
||||
from ckan.tests import TestController as ControllerTestCase
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class TestAction(SpatialTestBase):
|
||||
|
||||
def test_spatial_query(self):
|
||||
|
||||
dataset = factories.Dataset(
|
||||
extras=[{'key': 'spatial',
|
||||
'value': self.geojson_examples['point']}]
|
||||
)
|
||||
|
||||
result = helpers.call_action(
|
||||
'package_search',
|
||||
extras={'ext_bbox': '-180,-90,180,90'})
|
||||
|
||||
assert_equals(result['count'], 1)
|
||||
assert_equals(result['results'][0]['title'], dataset['title'])
|
||||
|
||||
def test_spatial_query_outside_bbox(self):
|
||||
|
||||
factories.Dataset(
|
||||
extras=[{'key': 'spatial',
|
||||
'value': self.geojson_examples['point']}]
|
||||
)
|
||||
|
||||
result = helpers.call_action(
|
||||
'package_search',
|
||||
extras={'ext_bbox': '-10,-20,10,20'})
|
||||
|
||||
assert_equals(result['count'], 0)
|
||||
|
||||
def test_spatial_query_wrong_bbox(self):
|
||||
|
||||
assert_raises(SearchError, helpers.call_action,
|
||||
'package_search', extras={'ext_bbox': '-10,-20,10,a'})
|
||||
|
||||
|
||||
class TestHarvestedMetadataAPI(SpatialTestBase, helpers.FunctionalTestBase):
|
||||
|
||||
class TestSpatialApi(ApiTestCase,SpatialTestBase,ControllerTestCase):
|
||||
|
||||
api_version = '2'
|
||||
|
||||
@classmethod
|
||||
def setup_class(self):
|
||||
super(TestSpatialApi,self).setup_class()
|
||||
setup_test_search_index()
|
||||
CreateTestData.create_test_user()
|
||||
self.package_fixture_data = {
|
||||
'name' : u'test-spatial-dataset-search-point',
|
||||
'title': 'Some Title',
|
||||
'extras': [{'key':'spatial','value':self.geojson_examples['point']}]
|
||||
}
|
||||
self.base_url = self.offset('/search/dataset/geo')
|
||||
|
||||
def _offset_with_bbox(self,minx=-180,miny=-90,maxx=180,maxy=90,crs=None):
|
||||
offset = self.base_url + '?bbox=%s,%s,%s,%s' % (minx,miny,maxx,maxy)
|
||||
if crs:
|
||||
offset = offset + '&crs=%s' % crs
|
||||
return offset
|
||||
|
||||
def test_basic_query(self):
|
||||
schema = default_create_package_schema()
|
||||
context = {'model':model,'session':Session,'user':'tester','extras_as_string':True,'schema':schema,'api_version':2}
|
||||
package_dict = package_create(context,self.package_fixture_data)
|
||||
package_id = context.get('id')
|
||||
|
||||
# Point inside bbox
|
||||
offset = self._offset_with_bbox()
|
||||
|
||||
res = self.app.get(offset, status=200)
|
||||
res_dict = self.data_from_res(res)
|
||||
|
||||
assert res_dict['count'] == 1
|
||||
assert res_dict['results'][0] == package_id
|
||||
|
||||
# Point outside bbox
|
||||
offset = self._offset_with_bbox(-10,10,-20,20)
|
||||
|
||||
res = self.app.get(offset, status=200)
|
||||
res_dict = self.data_from_res(res)
|
||||
|
||||
assert res_dict['count'] == 0
|
||||
assert res_dict['results'] == []
|
||||
|
||||
# Delete the package and ensure it does not come up on
|
||||
# search results
|
||||
package_delete(context,{'id':package_id})
|
||||
offset = self._offset_with_bbox()
|
||||
|
||||
res = self.app.get(offset, status=200)
|
||||
res_dict = self.data_from_res(res)
|
||||
|
||||
assert res_dict['count'] == 0
|
||||
assert res_dict['results'] == []
|
||||
|
||||
|
||||
|
||||
class TestActionPackageSearch(SpatialTestBase,WsgiAppCase):
|
||||
|
||||
@classmethod
|
||||
def setup_class(self):
|
||||
super(TestActionPackageSearch,self).setup_class()
|
||||
setup_test_search_index()
|
||||
self.package_fixture_data_1 = {
|
||||
'name' : u'test-spatial-dataset-search-point-1',
|
||||
'title': 'Some Title 1',
|
||||
'extras': [{'key':'spatial','value':self.geojson_examples['point']}]
|
||||
}
|
||||
self.package_fixture_data_2 = {
|
||||
'name' : u'test-spatial-dataset-search-point-2',
|
||||
'title': 'Some Title 2',
|
||||
'extras': [{'key':'spatial','value':self.geojson_examples['point_2']}]
|
||||
}
|
||||
|
||||
CreateTestData.create()
|
||||
|
||||
@classmethod
|
||||
def teardown_class(self):
|
||||
model.repo.rebuild_db()
|
||||
|
||||
def test_1_basic(self):
|
||||
schema = default_create_package_schema()
|
||||
context = {'model':model,'session':Session,'user':'tester','extras_as_string':True,'schema':schema,'api_version':2}
|
||||
package_dict_1 = package_create(context,self.package_fixture_data_1)
|
||||
del context['package']
|
||||
package_dict_2 = package_create(context,self.package_fixture_data_2)
|
||||
|
||||
postparams = '%s=1' % json.dumps({
|
||||
'q': 'test',
|
||||
'facet.field': ('groups', 'tags', 'res_format', 'license'),
|
||||
'rows': 20,
|
||||
'start': 0,
|
||||
'extras': {
|
||||
'ext_bbox': '%s,%s,%s,%s' % (10,10,40,40)
|
||||
}
|
||||
})
|
||||
res = self.app.post('/api/action/package_search', params=postparams)
|
||||
res = json.loads(res.body)
|
||||
result = res['result']
|
||||
|
||||
# Only one dataset returned
|
||||
assert_equal(res['success'], True)
|
||||
assert_equal(result['count'], 1)
|
||||
assert_equal(result['results'][0]['name'], 'test-spatial-dataset-search-point-2')
|
||||
|
||||
|
||||
class TestHarvestedMetadataAPI(WsgiAppCase):
|
||||
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
def test_api(self):
|
||||
try:
|
||||
from ckanext.harvest.model import HarvestObject, HarvestJob, HarvestSource, HarvestObjectExtra
|
||||
from ckanext.harvest.model import (HarvestObject, HarvestJob,
|
||||
HarvestSource,
|
||||
HarvestObjectExtra)
|
||||
except ImportError:
|
||||
raise SkipTest('The harvester extension is needed for these tests')
|
||||
|
||||
cls.content1 = '<xml>Content 1</xml>'
|
||||
ho1 = HarvestObject(guid='test-ho-1',
|
||||
job=HarvestJob(source=HarvestSource(url='http://', type='xx')),
|
||||
content=cls.content1)
|
||||
content1 = '<xml>Content 1</xml>'
|
||||
ho1 = HarvestObject(
|
||||
guid='test-ho-1',
|
||||
job=HarvestJob(source=HarvestSource(url='http://', type='xx')),
|
||||
content=content1)
|
||||
|
||||
cls.content2 = '<xml>Content 2</xml>'
|
||||
cls.original_content2 = '<xml>Original Content 2</xml>'
|
||||
ho2 = HarvestObject(guid='test-ho-2',
|
||||
job=HarvestJob(source=HarvestSource(url='http://', type='xx')),
|
||||
content=cls.content2)
|
||||
content2 = '<xml>Content 2</xml>'
|
||||
original_content2 = '<xml>Original Content 2</xml>'
|
||||
ho2 = HarvestObject(
|
||||
guid='test-ho-2',
|
||||
job=HarvestJob(source=HarvestSource(url='http://', type='xx')),
|
||||
content=content2)
|
||||
|
||||
hoe = HarvestObjectExtra(key='original_document',
|
||||
value=cls.original_content2,
|
||||
object=ho2)
|
||||
hoe = HarvestObjectExtra(
|
||||
key='original_document',
|
||||
value=original_content2,
|
||||
object=ho2)
|
||||
|
||||
Session.add(ho1)
|
||||
Session.add(ho2)
|
||||
Session.add(hoe)
|
||||
Session.commit()
|
||||
|
||||
cls.object_id_1 = ho1.id
|
||||
cls.object_id_2 = ho2.id
|
||||
object_id_1 = ho1.id
|
||||
object_id_2 = ho2.id
|
||||
|
||||
|
||||
def test_api(self):
|
||||
app = self._get_test_app()
|
||||
|
||||
# Test redirects for old URLs
|
||||
url = '/api/2/rest/harvestobject/{0}/xml'.format(self.object_id_1)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 301
|
||||
assert '/harvest/object/{0}'.format(self.object_id_1) in r.header_dict['Location']
|
||||
|
||||
url = '/api/2/rest/harvestobject/{0}/html'.format(self.object_id_1)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 301
|
||||
assert '/harvest/object/{0}/html'.format(self.object_id_1) in r.header_dict['Location']
|
||||
url = '/api/2/rest/harvestobject/{0}/xml'.format(object_id_1)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 301)
|
||||
assert ('/harvest/object/{0}'.format(object_id_1)
|
||||
in r.headers['Location'])
|
||||
|
||||
url = '/api/2/rest/harvestobject/{0}/html'.format(object_id_1)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 301)
|
||||
assert ('/harvest/object/{0}/html'.format(object_id_1)
|
||||
in r.headers['Location'])
|
||||
|
||||
# Access object content
|
||||
url = '/harvest/object/{0}'.format(self.object_id_1)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 200
|
||||
assert r.header_dict['Content-Type'] == 'application/xml; charset=utf-8'
|
||||
assert r.body == self.content1
|
||||
url = '/harvest/object/{0}'.format(object_id_1)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 200)
|
||||
assert_equals(r.headers['Content-Type'],
|
||||
'application/xml; charset=utf-8')
|
||||
assert_equals(
|
||||
r.body,
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n<xml>Content 1</xml>')
|
||||
|
||||
# Access original content in object extra (if present)
|
||||
url = '/harvest/object/{0}/original'.format(self.object_id_1)
|
||||
r = self.app.get(url, status=404)
|
||||
assert r.status == 404
|
||||
url = '/harvest/object/{0}/original'.format(object_id_1)
|
||||
r = app.get(url, status=404)
|
||||
assert_equals(r.status_int, 404)
|
||||
|
||||
url = '/harvest/object/{0}/original'.format(self.object_id_2)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 200
|
||||
assert r.header_dict['Content-Type'] == 'application/xml; charset=utf-8'
|
||||
assert r.body == self.original_content2
|
||||
url = '/harvest/object/{0}/original'.format(object_id_2)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 200)
|
||||
assert_equals(r.headers['Content-Type'],
|
||||
'application/xml; charset=utf-8')
|
||||
assert_equals(
|
||||
r.body,
|
||||
'<?xml version="1.0" encoding="UTF-8"?>\n'
|
||||
+ '<xml>Original Content 2</xml>')
|
||||
|
||||
# Access HTML transformation
|
||||
url = '/harvest/object/{0}/html'.format(self.object_id_1)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 200
|
||||
assert r.header_dict['Content-Type'] == 'text/html; charset=utf-8'
|
||||
url = '/harvest/object/{0}/html'.format(object_id_1)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 200)
|
||||
assert_equals(r.headers['Content-Type'],
|
||||
'text/html; charset=utf-8')
|
||||
assert 'GEMINI record about' in r.body
|
||||
|
||||
url = '/harvest/object/{0}/html/original'.format(self.object_id_1)
|
||||
r = self.app.get(url, status=404)
|
||||
assert r.status == 404
|
||||
url = '/harvest/object/{0}/html/original'.format(object_id_1)
|
||||
r = app.get(url, status=404)
|
||||
assert_equals(r.status_int, 404)
|
||||
|
||||
url = '/harvest/object/{0}/html'.format(self.object_id_2)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 200
|
||||
assert r.header_dict['Content-Type'] == 'text/html; charset=utf-8'
|
||||
url = '/harvest/object/{0}/html'.format(object_id_2)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 200)
|
||||
assert_equals(r.headers['Content-Type'],
|
||||
'text/html; charset=utf-8')
|
||||
assert 'GEMINI record about' in r.body
|
||||
|
||||
url = '/harvest/object/{0}/html/original'.format(self.object_id_2)
|
||||
r = self.app.get(url)
|
||||
assert r.status == 200
|
||||
assert r.header_dict['Content-Type'] == 'text/html; charset=utf-8'
|
||||
url = '/harvest/object/{0}/html/original'.format(object_id_2)
|
||||
r = app.get(url)
|
||||
assert_equals(r.status_int, 200)
|
||||
assert_equals(r.headers['Content-Type'],
|
||||
'text/html; charset=utf-8')
|
||||
assert 'GEMINI record about' in r.body
|
||||
|
|
|
@ -9,7 +9,6 @@ from owslib.iso import MD_Metadata
|
|||
from pylons import config
|
||||
from nose.plugins.skip import SkipTest
|
||||
|
||||
#from ckan.tests import CkanServerCase
|
||||
from ckan.model import engine_is_sqlite
|
||||
|
||||
service = "http://ogcdev.bgs.ac.uk/geonetwork/srv/en/csw"
|
||||
|
|
|
@ -3,20 +3,17 @@ import lxml
|
|||
from nose.plugins.skip import SkipTest
|
||||
from nose.tools import assert_equal, assert_in, assert_raises
|
||||
|
||||
from ckan import plugins
|
||||
from ckan.lib.base import config
|
||||
from ckan import model
|
||||
from ckan.model import Session,Package
|
||||
from ckan.model import Session, Package
|
||||
from ckan.logic.schema import default_update_package_schema
|
||||
from ckan.logic import get_action
|
||||
from ckanext.harvest.model import (setup as harvest_model_setup,
|
||||
HarvestSource, HarvestJob, HarvestObject)
|
||||
from ckanext.spatial.validation import Validators, SchematronValidator
|
||||
from ckanext.harvest.model import (HarvestSource, HarvestJob, HarvestObject)
|
||||
from ckanext.spatial.validation import Validators
|
||||
from ckanext.spatial.harvesters.gemini import (GeminiDocHarvester,
|
||||
GeminiWafHarvester,
|
||||
GeminiHarvester)
|
||||
GeminiWafHarvester,
|
||||
GeminiHarvester)
|
||||
from ckanext.spatial.harvesters.base import SpatialHarvester
|
||||
from ckanext.spatial.model.package_extent import setup as spatial_db_setup
|
||||
from ckanext.spatial.tests.base import SpatialTestBase
|
||||
|
||||
from xml_file_server import serve
|
||||
|
@ -24,11 +21,8 @@ from xml_file_server import serve
|
|||
# Start simple HTTP server that serves XML test files
|
||||
serve()
|
||||
|
||||
class HarvestFixtureBase(SpatialTestBase):
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
SpatialTestBase.setup_class()
|
||||
class HarvestFixtureBase(SpatialTestBase):
|
||||
|
||||
def setup(self):
|
||||
# Add sysadmin user
|
||||
|
@ -117,8 +111,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1-waf/index.html',
|
||||
'source_type': u'gemini-waf'
|
||||
}
|
||||
|
@ -142,7 +136,7 @@ class TestHarvest(HarvestFixtureBase):
|
|||
objects.append(obj)
|
||||
harvester.import_stage(obj)
|
||||
|
||||
pkgs = Session.query(Package).filter(Package.type!=u'harvest_source').all()
|
||||
pkgs = Session.query(Package).filter(Package.type!=u'harvest').all()
|
||||
|
||||
assert_equal(len(pkgs), 2)
|
||||
|
||||
|
@ -156,8 +150,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/service1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -218,7 +212,7 @@ class TestHarvest(HarvestFixtureBase):
|
|||
'bbox-north-lat': u'61.0243',
|
||||
'bbox-south-lat': u'54.4764484375',
|
||||
'bbox-west-long': u'-9.099786875',
|
||||
'spatial': u'{"type": "Polygon", "coordinates": [[[0.5242365625, 54.4764484375], [0.5242365625, 61.0243], [-9.099786875, 61.0243], [-9.099786875, 54.4764484375], [0.5242365625, 54.4764484375]]]}',
|
||||
'spatial': u'{"type": "Polygon", "coordinates": [[[0.5242365625, 54.4764484375], [-9.099786875, 54.4764484375], [-9.099786875, 61.0243], [0.5242365625, 61.0243], [0.5242365625, 54.4764484375]]]}',
|
||||
# Other
|
||||
'coupled-resource': u'[{"href": ["http://scotgovsdi.edina.ac.uk/srv/en/csw?service=CSW&request=GetRecordById&version=2.0.2&outputSchema=http://www.isotc211.org/2005/gmd&elementSetName=full&id=250ea276-48e2-4189-8a89-fcc4ca92d652"], "uuid": ["250ea276-48e2-4189-8a89-fcc4ca92d652"], "title": []}]',
|
||||
'dataset-reference-date': u'[{"type": "publication", "value": "2011-09-08"}]',
|
||||
|
@ -244,7 +238,6 @@ class TestHarvest(HarvestFixtureBase):
|
|||
expected_resource = {
|
||||
'ckan_recommended_wms_preview': 'True',
|
||||
'description': 'Link to the GetCapabilities request for this service',
|
||||
'format': 'wms', # Newer CKAN versions lower case resource formats
|
||||
'name': 'Web Map Service (WMS)',
|
||||
'resource_locator_function': 'download',
|
||||
'resource_locator_protocol': 'OGC:WMS-1.3.0-http-get-capabilities',
|
||||
|
@ -260,13 +253,14 @@ class TestHarvest(HarvestFixtureBase):
|
|||
raise AssertionError('Unexpected value in resource for %s: %s (was expecting %s)' % \
|
||||
(key, resource[key], value))
|
||||
assert datetime.strptime(resource['verified_date'],'%Y-%m-%dT%H:%M:%S.%f').date() == date.today()
|
||||
assert resource['format'].lower() == 'wms'
|
||||
|
||||
def test_harvest_fields_dataset(self):
|
||||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/dataset1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -326,7 +320,7 @@ class TestHarvest(HarvestFixtureBase):
|
|||
'bbox-north-lat': u'61.06066944',
|
||||
'bbox-south-lat': u'54.529947158',
|
||||
'bbox-west-long': u'-8.97114288',
|
||||
'spatial': u'{"type": "Polygon", "coordinates": [[[0.205857204, 54.529947158], [0.205857204, 61.06066944], [-8.97114288, 61.06066944], [-8.97114288, 54.529947158], [0.205857204, 54.529947158]]]}',
|
||||
'spatial': u'{"type": "Polygon", "coordinates": [[[0.205857204, 54.529947158], [-8.97114288, 54.529947158], [-8.97114288, 61.06066944], [0.205857204, 61.06066944], [0.205857204, 54.529947158]]]}',
|
||||
# Other
|
||||
'coupled-resource': u'[]',
|
||||
'dataset-reference-date': u'[{"type": "creation", "value": "2004-02"}, {"type": "revision", "value": "2006-07-03"}]',
|
||||
|
@ -368,8 +362,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
def test_harvest_error_bad_xml(self):
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/error_bad_xml.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -394,8 +388,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
def test_harvest_error_404(self):
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/not_there.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -416,8 +410,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/error_validation.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -459,8 +453,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/dataset1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -525,8 +519,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/service1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -598,8 +592,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source1
|
||||
source1_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/source1/same_dataset.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -620,8 +614,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
# (As of https://github.com/okfn/ckanext-inspire/commit/9fb67
|
||||
# we are no longer throwing an exception when this happens)
|
||||
source2_fixture = {
|
||||
'title': 'Test Source 2',
|
||||
'name': 'test-source-2',
|
||||
'title': 'Test Source 2',
|
||||
'name': 'test-source-2',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/source2/same_dataset.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -667,8 +661,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source1
|
||||
source1_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/source1/same_dataset.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -690,8 +684,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Harvest the same document, unchanged, from another source
|
||||
source2_fixture = {
|
||||
'title': 'Test Source 2',
|
||||
'name': 'test-source-2',
|
||||
'title': 'Test Source 2',
|
||||
'name': 'test-source-2',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/source2/same_dataset.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -714,8 +708,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source1
|
||||
source1_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/service1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -733,8 +727,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Harvest the same document GUID but with a newer date, from another source.
|
||||
source2_fixture = {
|
||||
'title': 'Test Source 2',
|
||||
'name': 'test-source-2',
|
||||
'title': 'Test Source 2',
|
||||
'name': 'test-source-2',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/service1_newer.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -760,8 +754,8 @@ class TestHarvest(HarvestFixtureBase):
|
|||
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/dataset1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -823,8 +817,8 @@ class TestGatherMethods(HarvestFixtureBase):
|
|||
HarvestFixtureBase.setup(self)
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/dataset1.xml',
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
@ -941,6 +935,7 @@ class TestImportStageTools:
|
|||
assert_equal(GeminiHarvester._process_responsible_organisation(responsible_organisation),
|
||||
('', []))
|
||||
|
||||
|
||||
class TestValidation(HarvestFixtureBase):
|
||||
|
||||
@classmethod
|
||||
|
@ -955,8 +950,8 @@ class TestValidation(HarvestFixtureBase):
|
|||
def get_validation_errors(self, validation_test_filename):
|
||||
# Create source
|
||||
source_fixture = {
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'title': 'Test Source',
|
||||
'name': 'test-source',
|
||||
'url': u'http://127.0.0.1:8999/gemini2.1/validation/%s' % validation_test_filename,
|
||||
'source_type': u'gemini-single'
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# this is a namespace package
|
||||
try:
|
||||
import pkg_resources
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
except ImportError:
|
||||
import pkgutil
|
||||
__path__ = pkgutil.extend_path(__path__, __name__)
|
|
@ -0,0 +1,9 @@
|
|||
from ckan import plugins as p
|
||||
|
||||
|
||||
class TestSpatialPlugin(p.SingletonPlugin):
|
||||
|
||||
p.implements(p.IConfigurer, inherit=True)
|
||||
|
||||
def update_config(self, config):
|
||||
p.toolkit.add_template_directory(config, 'templates')
|
|
@ -0,0 +1,11 @@
|
|||
{% ckan_extends %}
|
||||
|
||||
{% block secondary_content %}
|
||||
{{ super() }}
|
||||
|
||||
{% set dataset_extent = h.get_pkg_dict_extra(c.pkg_dict, 'spatial', '') %}
|
||||
{% if dataset_extent %}
|
||||
{% snippet "spatial/snippets/dataset_map_sidebar.html", extent=dataset_extent %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% ckan_extends %}
|
||||
|
||||
{% block secondary_content %}
|
||||
|
||||
{% snippet "spatial/snippets/spatial_query.html" %}
|
||||
|
||||
{{ super() }}
|
||||
|
||||
{% endblock %}
|
4
setup.py
4
setup.py
|
@ -48,5 +48,9 @@ setup(
|
|||
spatial=ckanext.spatial.commands.spatial:Spatial
|
||||
ckan-pycsw=ckanext.spatial.commands.csw:Pycsw
|
||||
validation=ckanext.spatial.commands.validation:Validation
|
||||
|
||||
[ckan.test_plugins]
|
||||
test_spatial_plugin = ckanext.spatial.tests.test_plugin.plugin:TestSpatialPlugin
|
||||
|
||||
""",
|
||||
)
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
[DEFAULT]
|
||||
debug = true
|
||||
# Uncomment and replace with the address which should receive any error reports
|
||||
#email_to = you@yourdomain.com
|
||||
smtp_server = localhost
|
||||
error_email_from = paste@localhost
|
||||
|
||||
[server:main]
|
||||
use = egg:Paste#http
|
||||
host = 0.0.0.0
|
||||
port = 5000
|
||||
|
||||
|
||||
[app:main]
|
||||
use = config:../ckan/test-core.ini
|
||||
# Here we hard-code the database and a flag to make default tests
|
||||
# run fast.
|
||||
ckan.plugins = harvest spatial_metadata spatial_query spatial_query_widget dataset_extent_map wms_preview spatial_harvest_metadata_api synchronous_search gemini_csw_harvester gemini_doc_harvester gemini_waf_harvester cswserver
|
||||
ckan.spatial.srid = 4326
|
||||
ckan.spatial.default_map_extent=-6.88,49.74,0.50,59.2
|
||||
ckan.spatial.testing = true
|
||||
ckan.spatial.validator.profiles = iso19139,constraints,gemini2
|
||||
# NB: other test configuration should go in test-core.ini, which is
|
||||
# what the postgres tests use.
|
||||
|
||||
|
||||
# Logging configuration
|
||||
[loggers]
|
||||
keys = root, ckan, sqlalchemy
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
||||
[formatters]
|
||||
keys = generic
|
||||
|
||||
[logger_root]
|
||||
level = WARN
|
||||
handlers = console
|
||||
|
||||
[logger_ckan]
|
||||
qualname = ckan
|
||||
handlers =
|
||||
level = INFO
|
||||
|
||||
[logger_sqlalchemy]
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
level = WARN
|
||||
|
||||
[handler_console]
|
||||
class = StreamHandler
|
||||
args = (sys.stdout,)
|
||||
level = NOTSET
|
||||
formatter = generic
|
||||
|
||||
[formatter_generic]
|
||||
format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s
|
25
test.ini
25
test.ini
|
@ -12,18 +12,20 @@ port = 5000
|
|||
|
||||
|
||||
[app:main]
|
||||
use = config:test-core.ini
|
||||
# Here we hard-code the database and a flag to make default tests
|
||||
# run fast.
|
||||
faster_db_test_hacks = True
|
||||
sqlalchemy.url = sqlite:///
|
||||
use = config:../ckan/test-core.ini
|
||||
ckan.legacy_templates = false
|
||||
ckan.plugins = test_spatial_plugin harvest spatial_metadata spatial_query spatial_query_widget dataset_extent_map wms_preview spatial_harvest_metadata_api synchronous_search gemini_csw_harvester gemini_doc_harvester gemini_waf_harvester cswserver
|
||||
ckan.spatial.srid = 4326
|
||||
ckan.spatial.default_map_extent=-6.88,49.74,0.50,59.2
|
||||
ckan.spatial.testing = true
|
||||
ckan.spatial.validator.profiles = iso19139,constraints,gemini2
|
||||
# NB: other test configuration should go in test-core.ini, which is
|
||||
# what the postgres tests use.
|
||||
|
||||
|
||||
# Logging configuration
|
||||
[loggers]
|
||||
keys = root, ckan, ckanext, sqlalchemy
|
||||
keys = root, ckan, sqlalchemy
|
||||
|
||||
[handlers]
|
||||
keys = console
|
||||
|
@ -37,18 +39,11 @@ handlers = console
|
|||
|
||||
[logger_ckan]
|
||||
qualname = ckan
|
||||
handlers = console
|
||||
handlers =
|
||||
level = INFO
|
||||
propagate = 0
|
||||
|
||||
[logger_ckanext]
|
||||
qualname = ckanext
|
||||
handlers = console
|
||||
level = DEBUG
|
||||
propagate = 0
|
||||
|
||||
[logger_sqlalchemy]
|
||||
handlers = console
|
||||
handlers =
|
||||
qualname = sqlalchemy.engine
|
||||
level = WARN
|
||||
|
||||
|
|
Loading…
Reference in New Issue