diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9b11b07c..9f3d72a4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,8 +4,8 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: '3.10' - name: Install requirements @@ -17,16 +17,16 @@ jobs: needs: lint strategy: matrix: - ckan-version: ["2.10", 2.9] + ckan-version: ["2.11", "2.10", 2.9] fail-fast: false name: CKAN ${{ matrix.ckan-version }} runs-on: ubuntu-latest container: - image: openknowledge/ckan-dev:${{ matrix.ckan-version }} + image: ckan/ckan-dev:${{ matrix.ckan-version }} services: solr: - image: ckan/ckan-solr:${{ matrix.ckan-version }} + image: ckan/ckan-solr:${{ matrix.ckan-version }}-solr9 postgres: image: ckan/ckan-postgres-dev:${{ matrix.ckan-version }} env: @@ -44,7 +44,7 @@ jobs: CKAN_REDIS_URL: redis://redis:6379/1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install requirements run: | pip install -r requirements.txt @@ -56,8 +56,5 @@ jobs: run: | ckan -c test.ini db init - name: Run tests - run: pytest --ckan-ini=test.ini --cov=ckanext.showcase --cov-report=xml --cov-append --disable-warnings ckanext/showcase/tests - - name: Upload coverage report to codecov - uses: codecov/codecov-action@v1 - with: - file: ./coverage.xml + run: pytest --ckan-ini=test.ini --cov=ckanext.showcase --cov-report=term-missing --cov-append --disable-warnings ckanext/showcase/tests + diff --git a/README.rst b/README.rst index b54f22e7..d7325e5b 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,7 @@ ckanext-showcase is intended to be a more powerful replacement for the Requirements ------------ -Tested on CKAN 2.9 and 2.10. +Tested on CKAN 2.9 to 2.11. Note: Use `1.5.2` for older CKAN versions (2.7 and 2.8). @@ -56,11 +56,13 @@ To install ckanext-showcase: config file (by default the config file is located at ``/etc/ckan/default/production.ini``). -4. Restart CKAN. For example if you've deployed CKAN with Apache on Ubuntu:: +4. Create the database tables:: - sudo service apache2 reload + ckan db upgrade -p showcase +5. Restart CKAN. + ------------------------ Development Installation ------------------------ diff --git a/ckanext/showcase/migration/showcase/README b/ckanext/showcase/migration/showcase/README new file mode 100644 index 00000000..98e4f9c4 --- /dev/null +++ b/ckanext/showcase/migration/showcase/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/ckanext/showcase/migration/showcase/alembic.ini b/ckanext/showcase/migration/showcase/alembic.ini new file mode 100644 index 00000000..bf93ad50 --- /dev/null +++ b/ckanext/showcase/migration/showcase/alembic.ini @@ -0,0 +1,74 @@ +# A generic, single database configuration. + +[alembic] +# path to migration scripts +script_location = %(here)s + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# timezone to use when rendering the date +# within the migration file as well as the filename. +# string value is passed to dateutil.tz.gettz() +# leave blank for localtime +# timezone = + +# max length of characters to apply to the +# "slug" field +#truncate_slug_length = 40 + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +# set to 'true' to allow .pyc and .pyo files without +# a source .py file to be detected as revisions in the +# versions/ directory +# sourceless = false + +# version location specification; this defaults +# to /home/adria/dev/pyenvs/ckan-211/ckanext-showcase/ckanext/showcase/migration/showcase/versions. When using multiple version +# directories, initial revisions must be specified with --version-path +# version_locations = %(here)s/bar %(here)s/bat /home/adria/dev/pyenvs/ckan-211/ckanext-showcase/ckanext/showcase/migration/showcase/versions + +# the output encoding used when revision files +# are written from script.py.mako +# output_encoding = utf-8 + +sqlalchemy.url = driver://user:pass@localhost/dbname + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/ckanext/showcase/migration/showcase/env.py b/ckanext/showcase/migration/showcase/env.py new file mode 100644 index 00000000..bb2fcd41 --- /dev/null +++ b/ckanext/showcase/migration/showcase/env.py @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement +from alembic import context +from sqlalchemy import engine_from_config, pool +from logging.config import fileConfig +from ckan.model.meta import metadata + +import os + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +target_metadata = metadata + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + +name = os.path.basename(os.path.dirname(__file__)) + + +def include_object(object, object_name, type_, reflected, compare_to): + if type_ == "table": + return object_name.startswith(name) + return True + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + + url = config.get_main_option(u"sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True, + version_table=u'{}_alembic_version'.format(name), + include_object=include_object, + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix=u'sqlalchemy.', + poolclass=pool.NullPool) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata, + version_table=u'{}_alembic_version'.format(name), + include_object=include_object, + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/ckanext/showcase/migration/showcase/script.py.mako b/ckanext/showcase/migration/showcase/script.py.mako new file mode 100644 index 00000000..2c015630 --- /dev/null +++ b/ckanext/showcase/migration/showcase/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/ckanext/showcase/migration/showcase/versions/02b006cb222c_add_ckanext_showcase_tables.py b/ckanext/showcase/migration/showcase/versions/02b006cb222c_add_ckanext_showcase_tables.py new file mode 100644 index 00000000..d82a90d5 --- /dev/null +++ b/ckanext/showcase/migration/showcase/versions/02b006cb222c_add_ckanext_showcase_tables.py @@ -0,0 +1,56 @@ +"""Add ckanext-showcase tables + +Revision ID: 02b006cb222c +Revises: +Create Date: 2024-07-12 12:04:18.803072 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "02b006cb222c" +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + engine = op.get_bind() + inspector = sa.inspect(engine) + tables = inspector.get_table_names() + if "showcase_package_association" not in tables: + op.create_table( + "showcase_package_association", + sa.Column( + "package_id", + sa.UnicodeText, + sa.ForeignKey("package.id", ondelete="CASCADE", onupdate="CASCADE"), + primary_key=True, + nullable=False, + ), + sa.Column( + "showcase_id", + sa.UnicodeText, + sa.ForeignKey("package.id", ondelete="CASCADE", onupdate="CASCADE"), + primary_key=True, + nullable=False, + ), + ) + if "showcase_package_association" not in tables: + op.create_table( + "showcase_admin", + sa.Column( + "user_id", + sa.UnicodeText, + sa.ForeignKey("user.id", ondelete="CASCADE", onupdate="CASCADE"), + primary_key=True, + nullable=False, + ), + ) + + +def downgrade(): + op.drop_table("showcase_package_association") + op.drop_table("showcase_admin") diff --git a/ckanext/showcase/model/__init__.py b/ckanext/showcase/model/__init__.py index 854475ea..120a1ad0 100644 --- a/ckanext/showcase/model/__init__.py +++ b/ckanext/showcase/model/__init__.py @@ -1,48 +1,20 @@ -from sqlalchemy import Table -from sqlalchemy import Column -from sqlalchemy import ForeignKey -from sqlalchemy import types +from sqlalchemy import Column, ForeignKey, types from ckan.model.domain_object import DomainObject -from ckan.model.meta import metadata, mapper, Session -from ckan import model +from ckan.model.meta import Session import logging -log = logging.getLogger(__name__) - - -showcase_package_assocation_table = None -showcase_admin_table = None +try: + from ckan.plugins.toolkit import BaseModel +except ImportError: + # CKAN <= 2.9 + from ckan.model.meta import metadata + from sqlalchemy.ext.declarative import declarative_base -def setup(): - # setup showcase_package_assocation_table - if showcase_package_assocation_table is None: - define_showcase_package_association_table() - log.debug('ShowcasePackageAssociation table defined in memory') + BaseModel = declarative_base(metadata=metadata) - if model.package_table.exists(): - if not showcase_package_assocation_table.exists(): - showcase_package_assocation_table.create() - log.debug('ShowcasePackageAssociation table create') - else: - log.debug('ShowcasePackageAssociation table already exists') - else: - log.debug('ShowcasePackageAssociation table creation deferred') - - # setup showcase_admin_table - if showcase_admin_table is None: - define_showcase_admin_table() - log.debug('ShowcaseAdmin table defined in memory') - - if model.user_table.exists(): - if not showcase_admin_table.exists(): - showcase_admin_table.create() - log.debug('ShowcaseAdmin table create') - else: - log.debug('ShowcaseAdmin table already exists') - else: - log.debug('ShowcaseAdmin table creation deferred') +log = logging.getLogger(__name__) class ShowcaseBaseModel(DomainObject): @@ -70,75 +42,65 @@ def create(cls, **kwargs): return instance.as_dict() -class ShowcasePackageAssociation(ShowcaseBaseModel): +class ShowcasePackageAssociation(ShowcaseBaseModel, BaseModel): + + __tablename__ = "showcase_package_association" + + package_id = Column( + types.UnicodeText, + ForeignKey("package.id", ondelete="CASCADE", onupdate="CASCADE"), + primary_key=True, + nullable=False, + ) + showcase_id = Column( + types.UnicodeText, + ForeignKey("package.id", ondelete="CASCADE", onupdate="CASCADE"), + primary_key=True, + nullable=False, + ) @classmethod def get_package_ids_for_showcase(cls, showcase_id): - ''' + """ Return a list of package ids associated with the passed showcase_id. - ''' - showcase_package_association_list = \ - Session.query(cls.package_id).filter_by( - showcase_id=showcase_id).all() + """ + showcase_package_association_list = ( + Session.query(cls.package_id).filter_by(showcase_id=showcase_id).all() + ) return showcase_package_association_list @classmethod def get_showcase_ids_for_package(cls, package_id): - ''' + """ Return a list of showcase ids associated with the passed package_id. - ''' - showcase_package_association_list = \ - Session.query(cls.showcase_id).filter_by( - package_id=package_id).all() + """ + showcase_package_association_list = ( + Session.query(cls.showcase_id).filter_by(package_id=package_id).all() + ) return showcase_package_association_list -def define_showcase_package_association_table(): - global showcase_package_assocation_table - - showcase_package_assocation_table = Table( - 'showcase_package_association', metadata, - Column('package_id', types.UnicodeText, - ForeignKey('package.id', - ondelete='CASCADE', - onupdate='CASCADE'), - primary_key=True, nullable=False), - Column('showcase_id', types.UnicodeText, - ForeignKey('package.id', - ondelete='CASCADE', - onupdate='CASCADE'), - primary_key=True, nullable=False) - ) - - mapper(ShowcasePackageAssociation, showcase_package_assocation_table) +class ShowcaseAdmin(ShowcaseBaseModel, BaseModel): + __tablename__ = "showcase_admin" - -class ShowcaseAdmin(ShowcaseBaseModel): + user_id = Column( + types.UnicodeText, + ForeignKey("user.id", ondelete="CASCADE", onupdate="CASCADE"), + primary_key=True, + nullable=False, + ) @classmethod def get_showcase_admin_ids(cls): - ''' + """ Return a list of showcase admin user ids. - ''' - id_list = [i for (i, ) in Session.query(cls.user_id).all()] + """ + id_list = [i for (i,) in Session.query(cls.user_id).all()] return id_list @classmethod def is_user_showcase_admin(cls, user): - ''' + """ Determine whether passed user is in the showcase admin list. - ''' - return (user.id in cls.get_showcase_admin_ids()) - - -def define_showcase_admin_table(): - global showcase_admin_table - - showcase_admin_table = Table('showcase_admin', metadata, - Column('user_id', types.UnicodeText, - ForeignKey('user.id', - ondelete='CASCADE', - onupdate='CASCADE'), - primary_key=True, nullable=False)) - - mapper(ShowcaseAdmin, showcase_admin_table) + """ + return user.id in cls.get_showcase_admin_ids() diff --git a/ckanext/showcase/plugin.py b/ckanext/showcase/plugin.py index 44fde860..5797acbd 100644 --- a/ckanext/showcase/plugin.py +++ b/ckanext/showcase/plugin.py @@ -15,7 +15,6 @@ from ckanext.showcase import utils from ckanext.showcase import views from ckanext.showcase.logic import auth, action -from ckanext.showcase.model import setup as model_setup import ckanext.showcase.logic.schema as showcase_schema import ckanext.showcase.logic.helpers as showcase_helpers @@ -28,7 +27,6 @@ class ShowcasePlugin(plugins.SingletonPlugin, lib_plugins.DefaultDatasetForm): - plugins.implements(plugins.IConfigurable) plugins.implements(plugins.IConfigurer) plugins.implements(plugins.IDatasetForm) plugins.implements(plugins.IFacets, inherit=True) @@ -56,12 +54,6 @@ def update_config(self, config): tk.add_template_directory(config, 'templates') tk.add_public_directory(config, 'public') tk.add_resource('assets', 'showcase') - tk.add_ckan_admin_tab(config, 'showcase_blueprint.admins', 'Showcase Config') - - # IConfigurable - - def configure(self, config): - model_setup() # IDatasetForm diff --git a/ckanext/showcase/templates/admin/base.html b/ckanext/showcase/templates/admin/base.html new file mode 100644 index 00000000..eca21e2c --- /dev/null +++ b/ckanext/showcase/templates/admin/base.html @@ -0,0 +1,6 @@ +{% ckan_extends %} + +{% block content_primary_nav %} + {{ super() }} + {{ h.build_nav_icon('showcase_blueprint.admins', _('Showcase Config'), icon='trophy') }} +{% endblock %} diff --git a/ckanext/showcase/tests/action/test_create.py b/ckanext/showcase/tests/action/test_create.py index 7e931080..3010e9c4 100644 --- a/ckanext/showcase/tests/action/test_create.py +++ b/ckanext/showcase/tests/action/test_create.py @@ -10,7 +10,7 @@ from ckanext.showcase.model import ShowcasePackageAssociation, ShowcaseAdmin -@pytest.mark.usefixtures("clean_db", "showcase_setup", "clean_session") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_session") class TestCreateShowcase(object): def test_showcase_create_no_args(self): """ @@ -97,7 +97,7 @@ def test_showcase_create_with_existing_name(self): ) -@pytest.mark.usefixtures("clean_db", "showcase_setup", "clean_session") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_session") class TestCreateShowcasePackageAssociation(object): def test_association_create_no_args(self): """ @@ -204,7 +204,7 @@ def test_association_create_existing(self): ) -@pytest.mark.usefixtures("clean_db", "showcase_setup", "clean_session") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_session") class TestCreateShowcaseAdmin(object): def test_showcase_admin_add_creates_showcase_admin_user(self): """ diff --git a/ckanext/showcase/tests/action/test_delete.py b/ckanext/showcase/tests/action/test_delete.py index cc2ec8b2..05c99aa0 100644 --- a/ckanext/showcase/tests/action/test_delete.py +++ b/ckanext/showcase/tests/action/test_delete.py @@ -9,7 +9,7 @@ from ckan.model.package import Package -@pytest.mark.usefixtures("clean_db") +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestDeleteShowcase(object): def test_showcase_delete_no_args(self): """ @@ -121,7 +121,7 @@ def test_showcase_delete_removes_associations(self): assert model.Session.query(ShowcasePackageAssociation).count() == 0 -@pytest.mark.usefixtures("clean_db") +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestDeletePackage(object): def test_package_delete_retains_associations(self): """ @@ -192,7 +192,7 @@ def test_package_purge_deletes_associations(self): assert model.Session.query(ShowcasePackageAssociation).count() == 1 -@pytest.mark.usefixtures("clean_db") +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestDeleteShowcasePackageAssociation(object): def test_association_delete_no_args(self): """ @@ -328,7 +328,7 @@ def test_association_delete_retains_packages(self): ) -@pytest.mark.usefixtures("clean_db") +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestRemoveShowcaseAdmin(object): def test_showcase_admin_remove_deletes_showcase_admin_user(self): """ diff --git a/ckanext/showcase/tests/action/test_get.py b/ckanext/showcase/tests/action/test_get.py index b4748abc..324d24c5 100644 --- a/ckanext/showcase/tests/action/test_get.py +++ b/ckanext/showcase/tests/action/test_get.py @@ -6,7 +6,7 @@ import ckan.plugins.toolkit as toolkit -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseShow(object): def test_showcase_show_no_args(self): """ @@ -201,7 +201,7 @@ def test_showcase_anon_user_can_see_package_list_when_showcase_association_was_d app.get("/dataset", status=200) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseList(object): def test_showcase_list(self): """Showcase list action returns names of showcases in site.""" @@ -254,7 +254,7 @@ def test_showcase_list_no_datasets(self): ) not in showcase_list_name_id -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcasePackageList(object): """Tests for ckanext_showcase_package_list""" @@ -437,7 +437,7 @@ def test_showcase_package_list_package_isnot_a_showcase(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestPackageShowcaseList(object): """Tests for ckanext_package_showcase_list""" @@ -567,7 +567,7 @@ def test_package_showcase_list_package_isnot_a_showcase(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAdminList(object): """Tests for ckanext_showcase_admin_list""" @@ -644,7 +644,7 @@ def test_showcase_admin_only_lists_admin_users(self): } not in showcase_admin_list -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestPackageSearchBeforeSearch(object): """ @@ -693,7 +693,7 @@ def test_package_search_filter_include_showcase(self): assert "dataset" not in types -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestUserShowBeforeSearch(object): """ diff --git a/ckanext/showcase/tests/fixtures.py b/ckanext/showcase/tests/fixtures.py index 91403283..4f588e59 100644 --- a/ckanext/showcase/tests/fixtures.py +++ b/ckanext/showcase/tests/fixtures.py @@ -3,14 +3,15 @@ import ckan.model as model from ckan.plugins import toolkit -from ckanext.showcase.model import setup as model_setup @pytest.fixture -def showcase_setup(): - model_setup() +def clean_db(reset_db, migrate_db_for): + reset_db() + migrate_db_for("showcase") + @pytest.fixture def clean_session(): - if toolkit.check_ckan_version(max_version='2.9.0'): - if hasattr(model.Session, 'revision'): + if toolkit.check_ckan_version(max_version="2.9.0"): + if hasattr(model.Session, "revision"): model.Session.revision = None diff --git a/ckanext/showcase/tests/test_auth.py b/ckanext/showcase/tests/test_auth.py index e37f87b8..e4fc6150 100644 --- a/ckanext/showcase/tests/test_auth.py +++ b/ckanext/showcase/tests/test_auth.py @@ -22,7 +22,7 @@ def _get_request(app, url, status): app.get(url, status=status) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAuthIndex(object): def test_auth_anon_user_can_view_showcase_index(self, app): """An anon (not logged in) user can view the Showcases index.""" @@ -88,7 +88,7 @@ def test_auth_sysadmin_can_see_add_showcase_button(self, app): assert "/showcase/new" in response.body -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAuthDetails(object): def test_auth_anon_user_can_view_showcase_details(self, app): """ @@ -216,7 +216,7 @@ def test_auth_showcase_show_sysadmin_can_access(self, app): assert json_response["success"] -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAuthCreate(object): def test_auth_anon_user_cant_view_create_showcase(self, app): """ @@ -251,7 +251,7 @@ def test_auth_sysadmin_can_view_create_showcase_page(self, app): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAuthList(object): def test_auth_showcase_list_anon_can_access(self, app): """ @@ -303,7 +303,7 @@ def test_auth_showcase_list_sysadmin_can_access(self, app): assert json_response["success"] -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAuthEdit(object): def test_auth_anon_user_cant_view_edit_showcase_page(self, app): """ @@ -574,7 +574,7 @@ def test_auth_showcase_admin_can_view_addtoshowcase_dropdown_dataset_showcase_li assert "showcase-add" in showcase_list_response.body -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcasePackageAssociationCreate(object): def test_showcase_package_association_create_no_user(self): """ @@ -631,7 +631,7 @@ def test_showcase_package_association_create_unauthorized_creds(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcasePackageAssociationDelete(object): def test_showcase_package_association_delete_no_user(self): """ @@ -688,7 +688,7 @@ def test_showcase_package_association_delete_unauthorized_creds(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAdminAddAuth(object): def test_showcase_admin_add_no_user(self): """ @@ -723,7 +723,7 @@ def test_showcase_admin_add_unauthorized_creds(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAdminRemoveAuth(object): def test_showcase_admin_remove_no_user(self): """ @@ -758,7 +758,7 @@ def test_showcase_admin_remove_unauthorized_creds(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAdminListAuth(object): def test_showcase_admin_list_no_user(self): """ @@ -793,7 +793,7 @@ def test_showcase_admin_list_unauthorized_creds(self): ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseAuthManageShowcaseAdmins(object): def test_auth_anon_user_cant_view_showcase_admin_manage_page(self, app): """ diff --git a/ckanext/showcase/tests/test_converters.py b/ckanext/showcase/tests/test_converters.py index acec18e0..339d5c50 100644 --- a/ckanext/showcase/tests/test_converters.py +++ b/ckanext/showcase/tests/test_converters.py @@ -1,3 +1,5 @@ +import uuid + import pytest import ckan.model as model @@ -10,14 +12,15 @@ ) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestNameOrIdToTitleConverter(object): def test_name_to_title(self): """ Package correctly returns title. """ + my_id = str(uuid.uuid4()) context = {"session": model.Session} - factories.Dataset(id="my-id", title="My Title", name="my-name") + factories.Dataset(id=my_id, title="My Title", name="my-name") result = convert_package_name_or_id_to_title_or_name( "my-name", context @@ -28,8 +31,10 @@ def test_name_to_name(self): """ Package with no title correctly returns name. """ + + my_id = str(uuid.uuid4()) context = {"session": model.Session} - factories.Dataset(id="my-id", title="", name="my-name") + factories.Dataset(id=my_id, title="", name="my-name") result = convert_package_name_or_id_to_title_or_name( "my-name", context @@ -40,20 +45,24 @@ def test_id_to_title(self): """ Package correctly returns title. """ + + my_id = str(uuid.uuid4()) context = {"session": model.Session} - factories.Dataset(id="my-id", title="My Title", name="my-name") + factories.Dataset(id=my_id, title="My Title", name="my-name") - result = convert_package_name_or_id_to_title_or_name("my-id", context) + result = convert_package_name_or_id_to_title_or_name(my_id, context) assert "My Title" == result def test_id_to_name(self): """ Package with no title correctly returns name. """ + + my_id = str(uuid.uuid4()) context = {"session": model.Session} - factories.Dataset(id="my-id", title="", name="my-name") + factories.Dataset(id=my_id, title="", name="my-name") - result = convert_package_name_or_id_to_title_or_name("my-id", context) + result = convert_package_name_or_id_to_title_or_name(my_id, context) assert "my-name" == result def test_with_no_package_id_exists(self): diff --git a/ckanext/showcase/tests/test_helpers.py b/ckanext/showcase/tests/test_helpers.py index 98a41917..021615f5 100644 --- a/ckanext/showcase/tests/test_helpers.py +++ b/ckanext/showcase/tests/test_helpers.py @@ -7,7 +7,7 @@ import ckanext.showcase.logic.helpers as showcase_helpers -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestGetSiteStatistics(object): def test_dataset_count_no_datasets(self): """ diff --git a/ckanext/showcase/tests/test_plugin.py b/ckanext/showcase/tests/test_plugin.py index 6a1b2271..3f9f1737 100644 --- a/ckanext/showcase/tests/test_plugin.py +++ b/ckanext/showcase/tests/test_plugin.py @@ -16,7 +16,7 @@ log = logging.getLogger(__name__) -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseIndex(object): def test_showcase_listed_on_index(self, app): """ @@ -30,7 +30,7 @@ def test_showcase_listed_on_index(self, app): assert "my-showcase" in response.body -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseNewView(object): def test_showcase_create_form_renders(self, app): @@ -83,7 +83,7 @@ def test_create_showcase(self, app): -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestShowcaseEditView(object): def test_showcase_edit_form_renders(self, app): """ @@ -145,7 +145,7 @@ def test_edit_showcase(self, app): assert "My new description!" in res.body -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestDatasetView(object): """Plugin adds a new showcases view for datasets.""" @@ -322,7 +322,7 @@ def test_dataset_showcase_page_remove_showcase_button_submit(self, app): assert model.Session.query(ShowcasePackageAssociation).count() == 0 -@pytest.mark.usefixtures("clean_db") +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestShowcaseAdminManageView(object): """Plugin adds a showcase admin management page to ckan-admin section.""" @@ -392,7 +392,7 @@ def test_showcase_admin_manage_page_no_admins_message(self, app): assert "There are currently no Showcase Admins" in response -@pytest.mark.usefixtures("clean_db", "clean_index") +@pytest.mark.usefixtures("with_plugins", "clean_db", "clean_index") class TestSearch(object): def test_search_with_nonascii_filter_query(self, app): """ @@ -407,7 +407,7 @@ def test_search_with_nonascii_filter_query(self, app): assert result["count"] == 1 -@pytest.mark.usefixtures('clean_db') +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestCKEditor(object): @pytest.mark.ckan_config("ckanext.showcase.editor", "ckeditor") def test_rich_text_editor_is_shown_when_configured(self, app): diff --git a/ckanext/showcase/tests/test_utils.py b/ckanext/showcase/tests/test_utils.py index 89e4f897..6a8147a1 100644 --- a/ckanext/showcase/tests/test_utils.py +++ b/ckanext/showcase/tests/test_utils.py @@ -8,7 +8,7 @@ from ckanext.showcase.utils import markdown_to_html -@pytest.mark.usefixtures("clean_db") +@pytest.mark.usefixtures("with_plugins", "clean_db") class TestUtils(object): def test_markdown_to_html(self):