From d8823b635c4fc759d56b14d41faabbf7f9e88622 Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Tue, 1 Jun 2021 13:14:37 +0200
Subject: [PATCH 1/8] Update tests configuration

---
 .gitlab-ci.yml          |  4 +-
 Makefile                | 17 +++++++--
 docker-compose.test.yml | 83 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+), 5 deletions(-)
 create mode 100644 docker-compose.test.yml

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8b226d9..72161e0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -61,7 +61,7 @@ lint:
     - if: $CI_MERGE_REQUEST_ID
 
 unit_tests:
-  image: docker:19.03.12
+  image: tmaier/docker-compose:latest
   services:
     - docker:dind
   variables:
@@ -74,7 +74,7 @@ unit_tests:
     # defaults to tcp://docker:2376 upon seeing the TLS certificate directory.
     #DOCKER_HOST: tcp://docker:2376/
   stage: Test
-  script: make docker-build ci-test
+  script: make ci-test
   before_script:
     - docker info
     - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
diff --git a/Makefile b/Makefile
index 5b78b5c..08a46ac 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,15 @@
 ##
 ## make setup-env           # sets up the environment
 ## make lint 	            # runs linting tools outside docker
+## make pytest	            # runs tests
 ## make docker-build 	    # builds docker image
+## make docker-build-test   # builds docker image for tests
 ## make ci-lint 	        # runs linting tools inside docker
+## make ci-test             # runs tests inside docker
 ## make docker-build-env    # run docker-compose: creates images, containers, volumes and start the consumer
 ## make docker-rebuild-env  # force create of docker environment
 ## make docker-shell-env    # bash the main container
+## make stop-test           # stops containers, networks, images, and volume
 ## make docker-send-email   # send a email notification to activeMQ
 ## make docker-run          # run a consumer
 ##
@@ -22,19 +26,22 @@ lint:
 .PHONY: lint
 
 pytest:
-	pytest tests -vv
+	docker-compose -f docker-compose.test.yml exec -T notifications-consumer /bin/bash -c "pytest tests -vv;"
 .PHONY: pytest
 
 docker-build:
 	docker build -t notifications-consumer . --no-cache --build-arg build_env=development
 .PHONY: docker-build
 
+docker-build-test:
+	docker-compose -f  docker-compose.test.yml up -d --remove-orphans
+.PHONY: docker-build-test
+
 ci-lint:
 	docker run notifications-consumer make lint
 .PHONY: ci-lint
 
-ci-test:
-	docker run notifications-consumer make pytest
+ci-test: docker-build-test pytest
 .PHONY: ci-test
 
 docker-build-env:
@@ -63,6 +70,10 @@ docker-stop:
 	docker-compose rm -f
 .PHONY: docker-stop
 
+stop-test:
+	docker-compose -f docker-compose.test.yml down --volumes
+.PHONY: stop-test
+
 docker-send-email:
 	python scripts/docker-send-email.py
 .PHONY: docker-send-email
diff --git a/docker-compose.test.yml b/docker-compose.test.yml
new file mode 100644
index 0000000..b9d7661
--- /dev/null
+++ b/docker-compose.test.yml
@@ -0,0 +1,83 @@
+version: '3.7'
+
+services:
+  notifications-consumer:
+    image: notifications-consumer
+    container_name: notifications-consumer
+    build:
+      context: .
+      dockerfile: Dockerfile
+      args:
+        build_env: development
+    networks:
+      - default
+    volumes:
+      - '.:/opt:delegated'
+      - './docker/activemq/email_publisher.conf:/etc/activemq-publisher-email_publisher.conf'
+      - './docker/activemq/email_consumer.conf:/etc/activemq-consumer-email_consumer.conf'
+      - './docker/activemq/email_gateway_publisher.conf:/etc/activemq-publisher-email_gateway_publisher.conf'
+      - './docker/activemq/email_gateway_consumer.conf:/etc/activemq-consumer-email_gateway_consumer.conf'
+      - './docker/activemq/email_gateway_failure_publisher.conf:/etc/activemq-publisher-email_gateway_failure_publisher.conf'
+      - './docker/activemq/email_gateway_failure_consumer.conf:/etc/activemq-consumer-email_gateway_failure_consumer.conf'
+      - './docker/activemq/webpush_publisher.conf:/etc/activemq-publisher-webpush_publisher.conf'
+      - './docker/activemq/webpush_consumer.conf:/etc/activemq-consumer-webpush_consumer.conf'
+      - './docker/activemq/safaripush_publisher.conf:/etc/activemq-publisher-safaripush_publisher.conf'
+      - './docker/activemq/safaripush_consumer.conf:/etc/activemq-consumer-safaripush_consumer.conf'
+      - './docker/activemq/email_daily_publisher.conf:/etc/activemq-publisher-email_daily_publisher.conf'
+      - './docker/activemq/email_daily_consumer.conf:/etc/activemq-consumer-email_daily_consumer.conf'
+      - './docker/activemq/email_dlq_consumer.conf:/etc/activemq-consumer-email_dlq_consumer.conf'
+      - './docker/activemq/email_daily_dlq_consumer.conf:/etc/activemq-consumer-email_daily_dlq_consumer.conf'
+      - './docker/activemq/email_gateway_failure_dlq_consumer.conf:/etc/activemq-consumer-email_gateway_failure_dlq_consumer.conf'
+      - './docker/activemq/email_gateway_critical_failure_dlq_consumer.conf:/etc/activemq-consumer-email_gateway_critical_failure_dlq_consumer.conf'
+      - './docker/activemq/webpush_dlq_consumer.conf:/etc/activemq-consumer-webpush_dlq_consumer.conf'
+      - './docker/activemq/safaripush_dlq_consumer.conf:/etc/activemq-consumer-safaripush_dlq_consumer.conf'
+
+    ports:
+      - 8080:8080
+    env_file:
+      - .env
+    depends_on:
+      pg_db:
+        condition: service_healthy
+      activemq:
+        condition: service_healthy
+
+  pg_db:
+    image: postgres
+    volumes:
+      - pgsql-data:/var/lib/pgsql/data:rw
+    networks:
+      - default
+    ports:
+      - 5432:5432
+    environment:
+      - POSTGRES_USER
+      - POSTGRES_PASSWORD
+      - POSTGRES_DB
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U test -d push_dev"]
+      interval: 10s
+      timeout: 5s
+      retries: 5
+
+  activemq:
+    build: ./docker/activemq/5.16.0-alpine
+    volumes:
+      - './docker/activemq/conf/activemq.xml:/opt/apache-activemq-5.16.0/conf/activemq.xml'
+    ports:
+      - 61613:61613
+      - 8161:8161
+    networks:
+      - default
+    healthcheck:
+      test: ["CMD", "nc", "-vz", "localhost", "8161"]
+      interval: 5s
+      timeout: 5s
+      retries: 5
+
+volumes:
+  pgsql-data:
+      name: pgsql-data
+
+networks:
+  default:
-- 
GitLab


From 57526bbbbc4d32380ab5344f6abd805d4fa910e7 Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Wed, 2 Jun 2021 17:25:08 +0200
Subject: [PATCH 2/8] Add db integration tests

---
 .../postgres/postgres_data_source.py          |  14 +-
 tests/integration/__init__.py                 |   2 +
 tests/integration/conftest.py                 | 136 ++++++++++++++++++
 .../integration/test_postgres_data_source.py  |  35 +++++
 tests/unit/__init__.py                        |   2 +
 tests/{ => unit}/conftest.py                  |   0
 tests/{ => unit}/test_postgres_data_source.py |   8 +-
 .../test_processors_email_gateway_utils.py    |   0
 .../test_processors_safaripush_utils.py       |   0
 .../test_processors_webpush_utils.py          |   0
 10 files changed, 191 insertions(+), 6 deletions(-)
 create mode 100644 tests/integration/__init__.py
 create mode 100644 tests/integration/conftest.py
 create mode 100644 tests/integration/test_postgres_data_source.py
 create mode 100644 tests/unit/__init__.py
 rename tests/{ => unit}/conftest.py (100%)
 rename tests/{ => unit}/test_postgres_data_source.py (98%)
 rename tests/{ => unit}/test_processors_email_gateway_utils.py (100%)
 rename tests/{ => unit}/test_processors_safaripush_utils.py (100%)
 rename tests/{ => unit}/test_processors_webpush_utils.py (100%)

diff --git a/notifications_consumer/data_source/postgres/postgres_data_source.py b/notifications_consumer/data_source/postgres/postgres_data_source.py
index 9f5d215..fe62f57 100644
--- a/notifications_consumer/data_source/postgres/postgres_data_source.py
+++ b/notifications_consumer/data_source/postgres/postgres_data_source.py
@@ -205,9 +205,19 @@ class Channel(PostgresDataSource.Base):
     ownerId = Column(UUID(as_uuid=True))
     adminGroupId = Column(UUID(as_uuid=True))
     adminGroup = relationship(
-        "Group", primaryjoin="Channel.adminGroupId == Group.id", foreign_keys="Group.id", uselist=False
+        "Group",
+        primaryjoin="Channel.adminGroupId == Group.id",
+        foreign_keys="Group.id",
+        uselist=False,
+        cascade="all,delete, delete-orphan",
+    )
+    owner = relationship(
+        "User",
+        primaryjoin="Channel.ownerId == User.id",
+        foreign_keys="User.id",
+        uselist=False,
+        cascade="all,delete, delete-orphan",
     )
-    owner = relationship("User", primaryjoin="Channel.ownerId == User.id", foreign_keys="User.id", uselist=False)
 
 
 class Group(PostgresDataSource.Base):
diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py
new file mode 100644
index 0000000..183a373
--- /dev/null
+++ b/tests/integration/__init__.py
@@ -0,0 +1,2 @@
+"""Initialize Test Package."""
+# FIX for Poetry: https://github.com/python-poetry/poetry/issues/87
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
new file mode 100644
index 0000000..695c03f
--- /dev/null
+++ b/tests/integration/conftest.py
@@ -0,0 +1,136 @@
+"""Package's fixtures."""
+
+import pytest
+from sqlalchemy import create_engine
+from sqlalchemy.schema import CreateSchema
+
+from notifications_consumer.app import configure_logging
+from notifications_consumer.config import Config, load_config
+from notifications_consumer.data_source.postgres.postgres_data_source import (
+    Channel,
+    Group,
+    Notification,
+    PostgresDataSource,
+    SubmissionByEmail,
+    User,
+)
+
+
+@pytest.fixture(scope="module")
+def config():
+    """Set up config."""
+    config = load_config()
+    yield config
+
+
+@pytest.fixture(scope="module")
+def appctx(config):
+    """Set up app context."""
+    configure_logging(config)
+
+
+@pytest.fixture(scope="module")
+def data_source():
+    """Set up data source."""
+    engine = create_engine(Config.SQLALCHEMY_DATABASE_URI)
+    if not engine.dialect.has_schema(engine, Config.DB_SCHEMA):
+        engine.execute(CreateSchema(Config.DB_SCHEMA))
+
+    # PostgresDataSource.Base.prepare(engine)
+    PostgresDataSource.Base.metadata.create_all(engine)
+
+    db = PostgresDataSource()
+    yield db
+
+    PostgresDataSource.Base.metadata.drop_all(bind=engine)
+
+
+@pytest.fixture(scope="function")
+def session(data_source):
+    """Return  database session for test."""
+    with data_source.session() as session:
+        yield session
+
+
+@pytest.fixture(scope="function")
+def user(session):
+    """Insert user to db."""
+    user = User()
+    user.id = "16fd2706-8baf-433b-82eb-8c7fada847da"
+    user.email = "testuser@cern.ch"
+
+    session.add(user)
+    session.commit()
+
+    yield user
+
+    session.delete(user)
+    session.commit()
+
+
+@pytest.fixture(scope="function")
+def group(session):
+    """Insert group to db."""
+    group = Group()
+    group.id = "186d8dfc-2774-43a8-91b5-a887fcb6ba4a"
+    group.groupIdentifier = "test-group"
+
+    session.add(group)
+    session.commit()
+
+    yield group
+
+    session.delete(group)
+    session.commit()
+
+
+@pytest.fixture(scope="function")
+def channel(session, group, user):
+    """Insert channel to db."""
+    channel = Channel()
+    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
+    channel.slug = "test-channel"
+    channel.name = "Test Channel"
+    channel.incomingEmail = "testuser@cern.ch"
+    channel.groups = [group]
+    channel.members = [user]
+    channel.deleteDate = None
+    channel.submissionByEmail = [SubmissionByEmail.EMAIL]
+    channel.ownerId = ("16fd2706-8baf-433b-82eb-8c7fada847da",)
+    channel.adminGroupId = "186d8dfc-2774-43a8-91b5-a887fcb6ba4a"
+    channel.adminGroup = group
+    channel.owner = user
+
+    session.add(channel)
+    session.commit()
+
+    yield channel
+
+    channel.groups = []
+    channel.members = []
+    session.add(channel)
+    session.commit()
+
+    session.delete(channel)
+    session.commit()
+
+
+@pytest.fixture(scope="function")
+def notification(session, channel):
+    """Insert notification to db."""
+    notification = Notification()
+    notification.id = "91be5d26-013c-4646-8809-61274645ea1d"
+    notification.body = "Test"
+    notification.summary = "Test Notification"
+    notification.sender = "dimitra.chatzichrysou@cern.ch"
+    notification.priority = "LOW"
+    notification.targetId = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
+    notification.channel = channel
+
+    session.add(notification)
+    session.commit()
+
+    yield notification
+
+    session.delete(notification)
+    session.commit()
diff --git a/tests/integration/test_postgres_data_source.py b/tests/integration/test_postgres_data_source.py
new file mode 100644
index 0000000..2f09475
--- /dev/null
+++ b/tests/integration/test_postgres_data_source.py
@@ -0,0 +1,35 @@
+"""Integration Tests for PostgresDataSource."""
+
+
+def test_get_channel(appctx, data_source, channel):
+    """Test get channel."""
+    assert data_source.get_channel(channel.slug) == {
+        "id": "c3ccc15b-298f-4dc7-877f-2c8970331caf",
+        "incoming_email": "testuser@cern.ch",
+        "owner_email": "testuser@cern.ch",
+    }
+
+
+def test_can_send_to_channel(appctx, data_source, channel, user):
+    """Test can send to channel when submission by email is set and match."""
+    assert data_source.can_send_to_channel(channel.id, user.email) is True
+
+
+def test_get_channel_notification(appctx, data_source, notification):
+    """Test get channel notifications."""
+    notifications = data_source.get_channel_notifications([str(notification.id)])
+    assert notifications is not None
+
+    for n in notifications:
+        assert str(n.id) == str(notification.id)
+        assert n.body == notification.body
+        assert n.summary == notification.summary
+        assert n.sender == notification.sender
+        assert n.priority == notification.priority
+        assert str(n.targetId) == notification.targetId
+        assert str(n.channel.id) == str(notification.channel.id)
+
+
+def test_get_user_email(appctx, data_source, user):
+    """Test get user email."""
+    assert data_source.get_user_email(user.id) == "testuser@cern.ch"
diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py
new file mode 100644
index 0000000..183a373
--- /dev/null
+++ b/tests/unit/__init__.py
@@ -0,0 +1,2 @@
+"""Initialize Test Package."""
+# FIX for Poetry: https://github.com/python-poetry/poetry/issues/87
diff --git a/tests/conftest.py b/tests/unit/conftest.py
similarity index 100%
rename from tests/conftest.py
rename to tests/unit/conftest.py
diff --git a/tests/test_postgres_data_source.py b/tests/unit/test_postgres_data_source.py
similarity index 98%
rename from tests/test_postgres_data_source.py
rename to tests/unit/test_postgres_data_source.py
index c4c35ec..fc06ac8 100644
--- a/tests/test_postgres_data_source.py
+++ b/tests/unit/test_postgres_data_source.py
@@ -301,7 +301,7 @@ def test_can_send_to_channel_submission_email_none(
     """Tests if submission by email is not set."""
     mock_get_scalar.return_value = channel_no_incoming_email_no_submission_by_email
 
-    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") == False
+    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") is False
     mock_get_scalar.assert_called_once_with(ANY, Channel, id="c3ccc15b-298f-4dc7-877f-2c8970331caf", deleteDate=None)
 
 
@@ -310,7 +310,7 @@ def test_can_send_to_channel_email(mock_get_scalar, db_mock, channel, app):
     """Tests if submission by email is set and match."""
     mock_get_scalar.return_value = channel
 
-    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") == True
+    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") is True
     mock_get_scalar.assert_called_once_with(ANY, Channel, id="c3ccc15b-298f-4dc7-877f-2c8970331caf", deleteDate=None)
 
 
@@ -323,7 +323,7 @@ def test_can_send_to_channel_administrators(
     mock_get_scalar.return_value = channel_with_administrators
     mock_get_group_users_api.return_value = {"data": [{"upn": "testuser", "primaryAccountEmail": "testuser@cern.ch"}]}
 
-    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") == True
+    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") is True
     mock_get_scalar.assert_called_once_with(ANY, Channel, id="c3ccc15b-298f-4dc7-877f-2c8970331caf", deleteDate=None)
 
 
@@ -334,7 +334,7 @@ def test_can_send_to_channel_members(mock_get_scalar, mock_get_group_users_api,
     mock_get_scalar.return_value = channel_with_members
     mock_get_group_users_api.return_value = {"data": [{"upn": "testuser", "primaryAccountEmail": "testuser@cern.ch"}]}
 
-    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") == True
+    assert db_mock.can_send_to_channel("c3ccc15b-298f-4dc7-877f-2c8970331caf", "testuser@cern.ch") is True
     mock_get_scalar.assert_called_once_with(ANY, Channel, id="c3ccc15b-298f-4dc7-877f-2c8970331caf", deleteDate=None)
 
 
diff --git a/tests/test_processors_email_gateway_utils.py b/tests/unit/test_processors_email_gateway_utils.py
similarity index 100%
rename from tests/test_processors_email_gateway_utils.py
rename to tests/unit/test_processors_email_gateway_utils.py
diff --git a/tests/test_processors_safaripush_utils.py b/tests/unit/test_processors_safaripush_utils.py
similarity index 100%
rename from tests/test_processors_safaripush_utils.py
rename to tests/unit/test_processors_safaripush_utils.py
diff --git a/tests/test_processors_webpush_utils.py b/tests/unit/test_processors_webpush_utils.py
similarity index 100%
rename from tests/test_processors_webpush_utils.py
rename to tests/unit/test_processors_webpush_utils.py
-- 
GitLab


From 3a8183ae3116e2c6bba149f3b32e6351f17e249e Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Thu, 3 Jun 2021 17:36:51 +0200
Subject: [PATCH 3/8] Update README

---
 README.md | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/README.md b/README.md
index 6194362..0505c3a 100644
--- a/README.md
+++ b/README.md
@@ -129,6 +129,30 @@ See more on choosing [dependency constrains](https://python-poetry.org/docs/vers
 poetry update requests
 ```
 
+### Creating and Running Unit and Integration Tests
+
+#### Writing tests
+
+The folder ```tests```  contains all test cases and future tests should be placed into this folder.
+Each test file needs to start with the prefix ```test_``` (e.g. ```test_postgres_data_source.py```)
+
+
+Tests functions always start with the prefix ```test_``` e.g.:
+```python
+
+def test_FUNCTION_OPERATION(self):
+    ...
+
+```
+
+#### Execute Pytest Tests
+
+To manually execute the tests use the following command:
+
+```bash
+make ci-test
+```
+
 ### Running against cernmx
 
 Requirements:
-- 
GitLab


From 2ec4739f6c97322068de636a21a736c4eecb4aeb Mon Sep 17 00:00:00 2001
From: Carina Antunes <carina.oliveira.antunes@cern.ch>
Date: Thu, 17 Jun 2021 19:29:06 +0100
Subject: [PATCH 4/8] remove cascade delete

---
 Makefile                                           |  3 +++
 README.md                                          |  9 +++++++--
 .../data_source/postgres/postgres_data_source.py   |  2 --
 tests/integration/conftest.py                      | 14 +++++++-------
 4 files changed, 17 insertions(+), 11 deletions(-)

diff --git a/Makefile b/Makefile
index 08a46ac..bb11a9e 100644
--- a/Makefile
+++ b/Makefile
@@ -44,6 +44,9 @@ ci-lint:
 ci-test: docker-build-test pytest
 .PHONY: ci-test
 
+test: stop-test ci-test
+.PHONY: test
+
 docker-build-env:
 	docker-compose up --remove-orphans
 .PHONY: docker-build-env
diff --git a/README.md b/README.md
index 0505c3a..8ef9c76 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,13 @@ Consume and process messages already pre-processed with notifications-routing.
 
 **Consumers:**
 - Email
-- WebPush
-- SafariPush
+- Email Feed
+- Web Push
+- Safari Push
+- Email Gateway
+- Email Gateway Failure
+- DLQ
+
 
 ## Contribute
 
diff --git a/notifications_consumer/data_source/postgres/postgres_data_source.py b/notifications_consumer/data_source/postgres/postgres_data_source.py
index fe62f57..f45591a 100644
--- a/notifications_consumer/data_source/postgres/postgres_data_source.py
+++ b/notifications_consumer/data_source/postgres/postgres_data_source.py
@@ -209,14 +209,12 @@ class Channel(PostgresDataSource.Base):
         primaryjoin="Channel.adminGroupId == Group.id",
         foreign_keys="Group.id",
         uselist=False,
-        cascade="all,delete, delete-orphan",
     )
     owner = relationship(
         "User",
         primaryjoin="Channel.ownerId == User.id",
         foreign_keys="User.id",
         uselist=False,
-        cascade="all,delete, delete-orphan",
     )
 
 
diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index 695c03f..bf8e877 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -96,19 +96,19 @@ def channel(session, group, user):
     channel.members = [user]
     channel.deleteDate = None
     channel.submissionByEmail = [SubmissionByEmail.EMAIL]
-    channel.ownerId = ("16fd2706-8baf-433b-82eb-8c7fada847da",)
-    channel.adminGroupId = "186d8dfc-2774-43a8-91b5-a887fcb6ba4a"
-    channel.adminGroup = group
-    channel.owner = user
+    channel.ownerId = user.id
+    channel.adminGroupId = group.id
 
     session.add(channel)
     session.commit()
 
     yield channel
 
-    channel.groups = []
-    channel.members = []
-    session.add(channel)
+    # break relationships before deleting to avoid issues with default cascade save-update
+    channel.groups.remove(group)
+    channel.members.remove(user)
+    channel.ownerId = None
+    channel.adminGroupId = None
     session.commit()
 
     session.delete(channel)
-- 
GitLab


From 3c7ed975bccaf8cb8752dc0a4f47ff6dee6d0b2b Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Mon, 21 Jun 2021 09:43:27 +0200
Subject: [PATCH 5/8] Add more test cases for can_send_to_channel method

---
 tests/integration/conftest.py                 | 126 ++++++++++++++++++
 .../integration/test_postgres_data_source.py  |  35 ++++-
 2 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index bf8e877..9242f09 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -115,6 +115,132 @@ def channel(session, group, user):
     session.commit()
 
 
+@pytest.fixture(scope="function")
+def channel_submission_by_egroup(session, group, user):
+    """Insert channel to db."""
+    channel = Channel()
+    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
+    channel.slug = "test-channel"
+    channel.name = "Test Channel"
+    channel.incomingEmail = "testuser@cern.ch"
+    channel.incomingEgroup = "test-group"
+    channel.groups = [group]
+    channel.members = [user]
+    channel.deleteDate = None
+    channel.submissionByEmail = [SubmissionByEmail.EGROUP]
+    channel.ownerId = user.id
+    channel.adminGroupId = group.id
+
+    session.add(channel)
+    session.commit()
+
+    yield channel
+
+    # break relationships before deleting to avoid issues with default cascade save-update
+    channel.groups.remove(group)
+    channel.members.remove(user)
+    channel.ownerId = None
+    channel.adminGroupId = None
+    session.commit()
+
+    session.delete(channel)
+    session.commit()
+
+
+@pytest.fixture(scope="function")
+def channel_submission_by_administrators(session, group, user):
+    """Insert channel to db."""
+    channel = Channel()
+    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
+    channel.slug = "test-channel"
+    channel.name = "Test Channel"
+    channel.incomingEmail = "testuser@cern.ch"
+    channel.incomingEgroup = "test-group"
+    channel.groups = [group]
+    channel.members = [user]
+    channel.deleteDate = None
+    channel.submissionByEmail = [SubmissionByEmail.ADMINISTRATORS]
+    channel.ownerId = user.id
+    channel.adminGroupId = group.id
+
+    session.add(channel)
+    session.commit()
+
+    yield channel
+
+    # break relationships before deleting to avoid issues with default cascade save-update
+    channel.groups.remove(group)
+    channel.members.remove(user)
+    channel.ownerId = None
+    channel.adminGroupId = None
+    session.commit()
+
+    session.delete(channel)
+    session.commit()
+
+
+@pytest.fixture(scope="function")
+def channel_submission_by_members(session, group, user):
+    """Insert channel to db."""
+    channel = Channel()
+    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
+    channel.slug = "test-channel"
+    channel.name = "Test Channel"
+    channel.incomingEmail = "testuser@cern.ch"
+    channel.groups = [group]
+    channel.members = [user]
+    channel.deleteDate = None
+    channel.submissionByEmail = [SubmissionByEmail.MEMBERS]
+    channel.ownerId = user.id
+    channel.adminGroupId = group.id
+
+    session.add(channel)
+    session.commit()
+
+    yield channel
+
+    # break relationships before deleting to avoid issues with default cascade save-update
+    channel.groups.remove(group)
+    channel.members.remove(user)
+    channel.ownerId = None
+    channel.adminGroupId = None
+    session.commit()
+
+    session.delete(channel)
+    session.commit()
+
+
+@pytest.fixture(scope="function")
+def channel_no_submission_by_email(session, group, user):
+    """Insert channel to db."""
+    channel = Channel()
+    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
+    channel.slug = "test-channel"
+    channel.name = "Test Channel"
+    channel.incomingEmail = "testuser@cern.ch"
+    channel.groups = [group]
+    channel.members = [user]
+    channel.deleteDate = None
+    channel.submissionByEmail = None
+    channel.ownerId = user.id
+    channel.adminGroupId = group.id
+
+    session.add(channel)
+    session.commit()
+
+    yield channel
+
+    # break relationships before deleting to avoid issues with default cascade save-update
+    channel.groups.remove(group)
+    channel.members.remove(user)
+    channel.ownerId = None
+    channel.adminGroupId = None
+    session.commit()
+
+    session.delete(channel)
+    session.commit()
+
+
 @pytest.fixture(scope="function")
 def notification(session, channel):
     """Insert notification to db."""
diff --git a/tests/integration/test_postgres_data_source.py b/tests/integration/test_postgres_data_source.py
index 2f09475..e936ae1 100644
--- a/tests/integration/test_postgres_data_source.py
+++ b/tests/integration/test_postgres_data_source.py
@@ -1,5 +1,7 @@
 """Integration Tests for PostgresDataSource."""
 
+from unittest import mock
+
 
 def test_get_channel(appctx, data_source, channel):
     """Test get channel."""
@@ -10,11 +12,42 @@ def test_get_channel(appctx, data_source, channel):
     }
 
 
-def test_can_send_to_channel(appctx, data_source, channel, user):
+def test_can_send_to_channel_no_submission_by_email(appctx, data_source, channel_no_submission_by_email, user):
+    """Test can send to channel when submission by email is not set."""
+    assert data_source.can_send_to_channel(channel_no_submission_by_email.id, user.email) is False
+
+
+def test_can_send_to_channel_by_email(appctx, data_source, channel, user):
     """Test can send to channel when submission by email is set and match."""
     assert data_source.can_send_to_channel(channel.id, user.email) is True
 
 
+def test_can_send_to_channel_by_egroup(appctx, data_source, channel_submission_by_egroup, user, group):
+    """Test can send to channel when submission by egroup is set and match."""
+    assert data_source.can_send_to_channel(channel_submission_by_egroup.id, user.email, group.groupIdentifier) is True
+
+
+@mock.patch("notifications_consumer.data_source.postgres.postgres_data_source.get_group_users_api")
+def test_can_send_to_channel_by_administrators(
+    mock_get_group_users_api, appctx, data_source, channel_submission_by_administrators, user, group
+):
+    """Test can send to channel when submission by administrators is set and match."""
+    mock_get_group_users_api.return_value = {"data": [{"upn": "testuser", "primaryAccountEmail": "testuser@cern.ch"}]}
+    assert (
+        data_source.can_send_to_channel(channel_submission_by_administrators.id, user.email, group.groupIdentifier)
+        is True
+    )
+
+
+@mock.patch("notifications_consumer.data_source.postgres.postgres_data_source.get_group_users_api")
+def test_can_send_to_channel_by_members(
+    mock_get_group_users_api, appctx, data_source, channel_submission_by_members, user, group
+):
+    """Test can send to channel when submission by members is set and match."""
+    mock_get_group_users_api.return_value = {"data": [{"upn": "testuser", "primaryAccountEmail": "testuser@cern.ch"}]}
+    assert data_source.can_send_to_channel(channel_submission_by_members.id, user.email, group.groupIdentifier) is True
+
+
 def test_get_channel_notification(appctx, data_source, notification):
     """Test get channel notifications."""
     notifications = data_source.get_channel_notifications([str(notification.id)])
-- 
GitLab


From df40c93a38bf06cba2f272ae9c42885fcd3385f0 Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Mon, 21 Jun 2021 09:49:25 +0200
Subject: [PATCH 6/8] Improvements

---
 tests/integration/test_postgres_data_source.py | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/tests/integration/test_postgres_data_source.py b/tests/integration/test_postgres_data_source.py
index e936ae1..0105087 100644
--- a/tests/integration/test_postgres_data_source.py
+++ b/tests/integration/test_postgres_data_source.py
@@ -51,16 +51,14 @@ def test_can_send_to_channel_by_members(
 def test_get_channel_notification(appctx, data_source, notification):
     """Test get channel notifications."""
     notifications = data_source.get_channel_notifications([str(notification.id)])
-    assert notifications is not None
-
-    for n in notifications:
-        assert str(n.id) == str(notification.id)
-        assert n.body == notification.body
-        assert n.summary == notification.summary
-        assert n.sender == notification.sender
-        assert n.priority == notification.priority
-        assert str(n.targetId) == notification.targetId
-        assert str(n.channel.id) == str(notification.channel.id)
+    assert len(notifications) == 1
+    assert str(notifications[0].id) == str(notification.id)
+    assert notifications[0].body == notification.body
+    assert notifications[0].summary == notification.summary
+    assert notifications[0].sender == notification.sender
+    assert notifications[0].priority == notification.priority
+    assert str(notifications[0].targetId) == notification.targetId
+    assert str(notifications[0].channel.id) == str(notification.channel.id)
 
 
 def test_get_user_email(appctx, data_source, user):
-- 
GitLab


From 6dc9a6e54ae89f422cd87389a2a9a18d34ec4936 Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Mon, 21 Jun 2021 11:42:44 +0200
Subject: [PATCH 7/8] Refactor fixtures

---
 tests/integration/conftest.py | 99 +++--------------------------------
 1 file changed, 8 insertions(+), 91 deletions(-)

diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index 9242f09..c42e825 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -116,130 +116,47 @@ def channel(session, group, user):
 
 
 @pytest.fixture(scope="function")
-def channel_submission_by_egroup(session, group, user):
-    """Insert channel to db."""
-    channel = Channel()
-    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
-    channel.slug = "test-channel"
-    channel.name = "Test Channel"
-    channel.incomingEmail = "testuser@cern.ch"
+def channel_submission_by_egroup(session, channel):
+    """Update channel with submission by egroup."""
     channel.incomingEgroup = "test-group"
-    channel.groups = [group]
-    channel.members = [user]
-    channel.deleteDate = None
     channel.submissionByEmail = [SubmissionByEmail.EGROUP]
-    channel.ownerId = user.id
-    channel.adminGroupId = group.id
 
     session.add(channel)
     session.commit()
 
     yield channel
 
-    # break relationships before deleting to avoid issues with default cascade save-update
-    channel.groups.remove(group)
-    channel.members.remove(user)
-    channel.ownerId = None
-    channel.adminGroupId = None
-    session.commit()
-
-    session.delete(channel)
-    session.commit()
-
 
 @pytest.fixture(scope="function")
-def channel_submission_by_administrators(session, group, user):
-    """Insert channel to db."""
-    channel = Channel()
-    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
-    channel.slug = "test-channel"
-    channel.name = "Test Channel"
-    channel.incomingEmail = "testuser@cern.ch"
+def channel_submission_by_administrators(session, channel):
+    """Update channel with submission by administrators."""
     channel.incomingEgroup = "test-group"
-    channel.groups = [group]
-    channel.members = [user]
-    channel.deleteDate = None
     channel.submissionByEmail = [SubmissionByEmail.ADMINISTRATORS]
-    channel.ownerId = user.id
-    channel.adminGroupId = group.id
-
-    session.add(channel)
-    session.commit()
 
     yield channel
 
-    # break relationships before deleting to avoid issues with default cascade save-update
-    channel.groups.remove(group)
-    channel.members.remove(user)
-    channel.ownerId = None
-    channel.adminGroupId = None
-    session.commit()
-
-    session.delete(channel)
-    session.commit()
-
 
 @pytest.fixture(scope="function")
-def channel_submission_by_members(session, group, user):
-    """Insert channel to db."""
-    channel = Channel()
-    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
-    channel.slug = "test-channel"
-    channel.name = "Test Channel"
-    channel.incomingEmail = "testuser@cern.ch"
-    channel.groups = [group]
-    channel.members = [user]
-    channel.deleteDate = None
+def channel_submission_by_members(session, channel):
+    """Update channel with submission by members."""
     channel.submissionByEmail = [SubmissionByEmail.MEMBERS]
-    channel.ownerId = user.id
-    channel.adminGroupId = group.id
 
     session.add(channel)
     session.commit()
 
     yield channel
 
-    # break relationships before deleting to avoid issues with default cascade save-update
-    channel.groups.remove(group)
-    channel.members.remove(user)
-    channel.ownerId = None
-    channel.adminGroupId = None
-    session.commit()
-
-    session.delete(channel)
-    session.commit()
-
 
 @pytest.fixture(scope="function")
-def channel_no_submission_by_email(session, group, user):
-    """Insert channel to db."""
-    channel = Channel()
-    channel.id = "c3ccc15b-298f-4dc7-877f-2c8970331caf"
-    channel.slug = "test-channel"
-    channel.name = "Test Channel"
-    channel.incomingEmail = "testuser@cern.ch"
-    channel.groups = [group]
-    channel.members = [user]
-    channel.deleteDate = None
+def channel_no_submission_by_email(session, channel):
+    """Update channel with no submission by email."""
     channel.submissionByEmail = None
-    channel.ownerId = user.id
-    channel.adminGroupId = group.id
 
     session.add(channel)
     session.commit()
 
     yield channel
 
-    # break relationships before deleting to avoid issues with default cascade save-update
-    channel.groups.remove(group)
-    channel.members.remove(user)
-    channel.ownerId = None
-    channel.adminGroupId = None
-    session.commit()
-
-    session.delete(channel)
-    session.commit()
-
 
 @pytest.fixture(scope="function")
 def notification(session, channel):
-- 
GitLab


From 5103259e23e27ec352214a2f9c12273564f4d603 Mon Sep 17 00:00:00 2001
From: Dimitra Chatzichrysou <dimitra.chatzichrysou@cern.ch>
Date: Mon, 21 Jun 2021 14:39:54 +0200
Subject: [PATCH 8/8] Fixes

---
 tests/integration/conftest.py | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py
index c42e825..ed8f2ff 100644
--- a/tests/integration/conftest.py
+++ b/tests/integration/conftest.py
@@ -121,7 +121,6 @@ def channel_submission_by_egroup(session, channel):
     channel.incomingEgroup = "test-group"
     channel.submissionByEmail = [SubmissionByEmail.EGROUP]
 
-    session.add(channel)
     session.commit()
 
     yield channel
@@ -133,6 +132,8 @@ def channel_submission_by_administrators(session, channel):
     channel.incomingEgroup = "test-group"
     channel.submissionByEmail = [SubmissionByEmail.ADMINISTRATORS]
 
+    session.commit()
+
     yield channel
 
 
@@ -141,7 +142,6 @@ def channel_submission_by_members(session, channel):
     """Update channel with submission by members."""
     channel.submissionByEmail = [SubmissionByEmail.MEMBERS]
 
-    session.add(channel)
     session.commit()
 
     yield channel
@@ -152,7 +152,6 @@ def channel_no_submission_by_email(session, channel):
     """Update channel with no submission by email."""
     channel.submissionByEmail = None
 
-    session.add(channel)
     session.commit()
 
     yield channel
-- 
GitLab