summaryrefslogtreecommitdiff
path: root/src/mailman/workflows/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/mailman/workflows/tests/__init__.py0
-rw-r--r--src/mailman/workflows/tests/test_subscriptions.py (renamed from src/mailman/app/tests/test_subscriptions.py)240
-rw-r--r--src/mailman/workflows/tests/test_unsubscriptions.py (renamed from src/mailman/app/tests/test_unsubscriptions.py)152
-rw-r--r--src/mailman/workflows/tests/test_workflow.py (renamed from src/mailman/app/tests/test_workflow.py)14
4 files changed, 211 insertions, 195 deletions
diff --git a/src/mailman/workflows/tests/__init__.py b/src/mailman/workflows/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/mailman/workflows/tests/__init__.py
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/workflows/tests/test_subscriptions.py
index 0519ec385..65569691b 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/workflows/tests/test_subscriptions.py
@@ -21,17 +21,20 @@ import unittest
from contextlib import suppress
from mailman.app.lifecycle import create_list
-from mailman.app.subscriptions import SubscriptionWorkflow
from mailman.interfaces.bans import IBanManager
-from mailman.interfaces.mailinglist import SubscriptionPolicy
from mailman.interfaces.member import MemberRole, MembershipIsBannedError
from mailman.interfaces.pending import IPendings
-from mailman.interfaces.subscriptions import TokenOwner
+from mailman.interfaces.subscriptions import (
+ SubscriptionPendingError,
+ TokenOwner)
from mailman.interfaces.usermanager import IUserManager
from mailman.testing.helpers import (
LogFileMark, get_queue_messages, set_preferred)
from mailman.testing.layers import ConfigLayer
from mailman.utilities.datetime import now
+from mailman.workflows.subscription import (
+ ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy,
+ ModerationSubscriptionPolicy, OpenSubscriptionPolicy)
from unittest.mock import patch
from zope.component import getUtility
@@ -55,7 +58,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_start_state(self):
# The workflow starts with no tokens or member.
- workflow = SubscriptionWorkflow(self._mlist)
+ workflow = ConfirmSubscriptionPolicy(self._mlist)
self.assertIsNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
self.assertIsNone(workflow.member)
@@ -64,7 +67,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# There is a Pendable associated with the held request, and it has
# some data associated with it.
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
with suppress(StopIteration):
workflow.run_thru('send_confirmation')
self.assertIsNotNone(workflow.token)
@@ -79,14 +82,14 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_user_or_address_required(self):
# The `subscriber` attribute must be a user or address.
- workflow = SubscriptionWorkflow(self._mlist)
+ workflow = ConfirmSubscriptionPolicy(self._mlist)
self.assertRaises(AssertionError, list, workflow)
def test_sanity_checks_address(self):
# Ensure that the sanity check phase, when given an IAddress, ends up
# with a linked user.
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
self.assertIsNotNone(workflow.address)
self.assertIsNone(workflow.user)
workflow.run_thru('sanity_checks')
@@ -99,7 +102,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# preferred address, ends up with an address.
anne = self._user_manager.make_user(self._anne)
address = set_preferred(anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
# The constructor sets workflow.address because the user has a
# preferred address.
self.assertEqual(workflow.address, address)
@@ -113,7 +116,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# preferred address, but with at least one linked address, gets an
# address.
anne = self._user_manager.make_user(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
self.assertIsNone(workflow.address)
self.assertEqual(workflow.user, anne)
workflow.run_thru('sanity_checks')
@@ -127,7 +130,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
anne = self._user_manager.make_user(self._anne)
anne.link(self._user_manager.create_address('anne@example.net'))
anne.link(self._user_manager.create_address('anne@example.org'))
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
self.assertIsNone(workflow.address)
self.assertEqual(workflow.user, anne)
workflow.run_thru('sanity_checks')
@@ -139,29 +142,39 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_sanity_checks_user_without_addresses(self):
# It is an error to try to subscribe a user with no linked addresses.
user = self._user_manager.create_user()
- workflow = SubscriptionWorkflow(self._mlist, user)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, user)
self.assertRaises(AssertionError, workflow.run_thru, 'sanity_checks')
def test_sanity_checks_globally_banned_address(self):
# An exception is raised if the address is globally banned.
anne = self._user_manager.create_address(self._anne)
IBanManager(None).ban(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
self.assertRaises(MembershipIsBannedError, list, workflow)
def test_sanity_checks_banned_address(self):
# An exception is raised if the address is banned by the mailing list.
anne = self._user_manager.create_address(self._anne)
IBanManager(self._mlist).ban(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
self.assertRaises(MembershipIsBannedError, list, workflow)
+ def test_sanity_checks_already_requested(self):
+ # An exception is raised if there is already a subscription request.
+ anne = self._user_manager.create_address(self._anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
+ list(workflow)
+ other_workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
+ self.assertRaises(SubscriptionPendingError, list, other_workflow)
+ # The original workflow token is still in the database.
+ self._expected_pendings_count = 1
+
def test_verification_checks_with_verified_address(self):
# When the address is already verified, we skip straight to the
# confirmation checks.
anne = self._user_manager.create_address(self._anne)
anne.verified_on = now()
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
workflow.run_thru('verification_checks')
with patch.object(workflow, '_step_confirmation_checks') as step:
next(workflow)
@@ -171,7 +184,8 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# When the address is not yet verified, but the pre-verified flag is
# passed to the workflow, we skip to the confirmation checks.
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne,
+ pre_verified=True)
workflow.run_thru('verification_checks')
with patch.object(workflow, '_step_confirmation_checks') as step:
next(workflow)
@@ -184,7 +198,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# A confirmation message must be sent to the user which will also
# verify their address.
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = ConfirmSubscriptionPolicy(self._mlist, anne)
workflow.run_thru('verification_checks')
with patch.object(workflow, '_step_send_confirmation') as step:
next(workflow)
@@ -195,10 +209,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_confirmation_checks_open_list(self):
# A subscription to an open list does not need to be confirmed or
# moderated.
- self._mlist.subscription_policy = SubscriptionPolicy.open
+ self._mlist.subscription_policy = OpenSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
- workflow.run_thru('confirmation_checks')
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
+ workflow.run_thru('verification_checks')
with patch.object(workflow, '_step_do_subscription') as step:
next(workflow)
step.assert_called_once_with()
@@ -206,10 +221,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_confirmation_checks_no_user_confirmation_needed(self):
# A subscription to a list which does not need user confirmation skips
# to the moderation checks.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
- workflow.run_thru('confirmation_checks')
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
+ workflow.run_thru('verification_checks')
with patch.object(workflow, '_step_moderation_checks') as step:
next(workflow)
step.assert_called_once_with()
@@ -218,11 +234,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# The subscription policy requires user confirmation, but their
# subscription is pre-confirmed. Since moderation is not required,
# the user will be immediately subscribed.
- self._mlist.subscription_policy = SubscriptionPolicy.confirm
+ self._mlist.subscription_policy = ConfirmSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True,
+ pre_confirmed=True)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_do_subscription') as step:
next(workflow)
@@ -233,11 +249,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# subscription is pre-confirmed. Since moderation is required, that
# check will be performed.
self._mlist.subscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True,
+ pre_confirmed=True)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_moderation_checks') as step:
next(workflow)
@@ -247,11 +263,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# The subscription policy requires user confirmation and moderation,
# but their subscription is pre-confirmed.
self._mlist.subscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True,
+ pre_confirmed=True)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_moderation_checks') as step:
next(workflow)
@@ -260,9 +276,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_confirmation_checks_confirmation_needed(self):
# The subscription policy requires confirmation and the subscription
# is not pre-confirmed.
- self._mlist.subscription_policy = SubscriptionPolicy.confirm
+ self._mlist.subscription_policy = ConfirmSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_send_confirmation') as step:
next(workflow)
@@ -272,9 +289,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# The subscription policy requires confirmation and moderation, and the
# subscription is not pre-confirmed.
self._mlist.subscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_send_confirmation') as step:
next(workflow)
@@ -282,11 +300,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_moderation_checks_pre_approved(self):
# The subscription is pre-approved by the moderator.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_approved=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True,
+ pre_approved=True)
workflow.run_thru('moderation_checks')
with patch.object(workflow, '_step_do_subscription') as step:
next(workflow)
@@ -294,9 +312,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_moderation_checks_approval_required(self):
# The moderator must approve the subscription.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
workflow.run_thru('moderation_checks')
with patch.object(workflow, '_step_get_moderator_approval') as step:
next(workflow)
@@ -306,9 +325,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# An open subscription policy plus a pre-verified address means the
# user gets subscribed to the mailing list without any further
# confirmations or approvals.
- self._mlist.subscription_policy = SubscriptionPolicy.open
+ self._mlist.subscription_policy = OpenSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Consume the entire state machine.
list(workflow)
# Anne is now a member of the mailing list.
@@ -323,11 +343,11 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# An moderation-requiring subscription policy plus a pre-verified and
# pre-approved address means the user gets subscribed to the mailing
# list without any further confirmations or approvals.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_approved=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True,
+ pre_approved=True)
# Consume the entire state machine.
list(workflow)
# Anne is now a member of the mailing list.
@@ -343,12 +363,12 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# pre-approved address means the user gets subscribed to the mailing
# list without any further confirmations or approvals.
self._mlist.subscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True,
- pre_approved=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True,
+ pre_confirmed=True,
+ pre_approved=True)
# Consume the entire state machine.
list(workflow)
# Anne is now a member of the mailing list.
@@ -362,12 +382,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
def test_do_subscription_cleanups(self):
# Once the user is subscribed, the token, and its associated pending
# database record will be removed from the database.
- self._mlist.subscription_policy = SubscriptionPolicy.open
+ self._mlist.subscription_policy = OpenSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True,
- pre_approved=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Consume the entire state machine.
list(workflow)
# Anne is now a member of the mailing list.
@@ -382,11 +400,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# The workflow runs until moderator approval is required, at which
# point the workflow is saved. Once the moderator approves, the
# workflow resumes and the user is subscribed.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Consume the entire state machine.
list(workflow)
# The user is not currently subscribed to the mailing list.
@@ -399,7 +416,7 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# Create a new workflow with the previous workflow's save token, and
# restore its state. This models an approved subscription and should
# result in the user getting subscribed.
- approved_workflow = SubscriptionWorkflow(self._mlist)
+ approved_workflow = self._mlist.subscription_policy(self._mlist)
approved_workflow.token = workflow.token
approved_workflow.restore()
list(approved_workflow)
@@ -415,11 +432,10 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# When the subscription is held for moderator approval, a message is
# logged.
mark = LogFileMark('mailman.subscribe')
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Consume the entire state machine.
list(workflow)
self.assertIn(
@@ -434,14 +450,13 @@ class TestSubscriptionWorkflow(unittest.TestCase):
# When the subscription is held for moderator approval, and the list
# is so configured, a notification is sent to the list moderators.
self._mlist.admin_immed_notify = True
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
bart = self._user_manager.create_user('bart@example.com', 'Bart User')
address = set_preferred(bart)
self._mlist.subscribe(address, MemberRole.moderator)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Consume the entire state machine.
list(workflow)
# Find the moderator message.
@@ -452,13 +467,13 @@ class TestSubscriptionWorkflow(unittest.TestCase):
else:
raise AssertionError('No moderator email found')
self.assertEqual(
- item.msgdata['recipients'], {'test-owner@example.com'})
+ item.msgdata['recipients'], {'test-owner@example.com'})
message = items[0].msg
self.assertEqual(message['From'], 'test-owner@example.com')
self.assertEqual(message['To'], 'test-owner@example.com')
self.assertEqual(
- message['Subject'],
- 'New subscription request to Test from anne@example.com')
+ message['Subject'],
+ 'New subscription request to Test from anne@example.com')
self.assertEqual(message.get_payload(), """\
Your authorization is required for a mailing list subscription request
approval:
@@ -474,11 +489,10 @@ approval:
# When the subscription is held for moderator approval, and the list
# is so configured, a notification is sent to the list moderators.
self._mlist.admin_immed_notify = False
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne,
- pre_verified=True,
- pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Consume the entire state machine.
list(workflow)
get_queue_messages('virgin', expected_count=0)
@@ -491,14 +505,14 @@ approval:
anne = self._user_manager.create_address(self._anne)
self.assertIsNone(anne.verified_on)
# Run the workflow to model the confirmation step.
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = self._mlist.subscription_policy(self._mlist, anne)
list(workflow)
items = get_queue_messages('virgin', expected_count=1)
message = items[0].msg
token = workflow.token
self.assertEqual(message['Subject'], 'confirm {}'.format(token))
self.assertEqual(
- message['From'], 'test-confirm+{}@example.com'.format(token))
+ message['From'], 'test-confirm+{}@example.com'.format(token))
# The confirmation message is not `Precedence: bulk`.
self.assertIsNone(message['precedence'])
# The state machine stopped at the moderator approval so there will be
@@ -511,15 +525,16 @@ approval:
anne = self._user_manager.create_address(self._anne)
self.assertIsNone(anne.verified_on)
# Run the workflow to model the confirmation step.
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_confirmed=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_confirmed=True)
list(workflow)
items = get_queue_messages('virgin', expected_count=1)
message = items[0].msg
token = workflow.token
self.assertEqual(
- message['Subject'], 'confirm {}'.format(workflow.token))
+ message['Subject'], 'confirm {}'.format(workflow.token))
self.assertEqual(
- message['From'], 'test-confirm+{}@example.com'.format(token))
+ message['From'], 'test-confirm+{}@example.com'.format(token))
# The state machine stopped at the moderator approval so there will be
# one token still in the database.
self._expected_pendings_count = 1
@@ -527,19 +542,20 @@ approval:
def test_send_confirmation_pre_verified(self):
# A confirmation message gets sent even when the address is verified
# when the subscription must be confirmed.
- self._mlist.subscription_policy = SubscriptionPolicy.confirm
+ self._mlist.subscription_policy = ConfirmSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
self.assertIsNone(anne.verified_on)
# Run the workflow to model the confirmation step.
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
list(workflow)
items = get_queue_messages('virgin', expected_count=1)
message = items[0].msg
token = workflow.token
self.assertEqual(
- message['Subject'], 'confirm {}'.format(workflow.token))
+ message['Subject'], 'confirm {}'.format(workflow.token))
self.assertEqual(
- message['From'], 'test-confirm+{}@example.com'.format(token))
+ message['From'], 'test-confirm+{}@example.com'.format(token))
# The state machine stopped at the moderator approval so there will be
# one token still in the database.
self._expected_pendings_count = 1
@@ -551,11 +567,11 @@ approval:
anne = self._user_manager.create_address(self._anne)
self.assertIsNone(anne.verified_on)
# Run the workflow to model the confirmation step.
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = self._mlist.subscription_policy(self._mlist, anne)
list(workflow)
# The address is still not verified.
self.assertIsNone(anne.verified_on)
- confirm_workflow = SubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.subscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
confirm_workflow.run_thru('do_confirm_verify')
@@ -569,11 +585,11 @@ approval:
set_preferred(anne)
# Run the workflow to model the confirmation step. There is no
# subscriber attribute yet.
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = self._mlist.subscription_policy(self._mlist, anne)
list(workflow)
self.assertEqual(workflow.subscriber, anne)
# Do a confirmation workflow, which should now set the subscriber.
- confirm_workflow = SubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.subscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
confirm_workflow.run_thru('do_confirm_verify')
@@ -584,10 +600,10 @@ approval:
# Subscriptions to the mailing list must be confirmed. Once that's
# done, the user's address (which is not initially verified) gets
# subscribed to the mailing list.
- self._mlist.subscription_policy = SubscriptionPolicy.confirm
+ self._mlist.subscription_policy = ConfirmSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
self.assertIsNone(anne.verified_on)
- workflow = SubscriptionWorkflow(self._mlist, anne)
+ workflow = self._mlist.subscription_policy(self._mlist, anne)
list(workflow)
# Anne is not yet a member.
member = self._mlist.regular_members.get_member(self._anne)
@@ -597,7 +613,7 @@ approval:
self.assertIsNotNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
# Confirm.
- confirm_workflow = SubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.subscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
list(confirm_workflow)
@@ -615,9 +631,10 @@ approval:
# the user confirming their subscription, and then the moderator
# approving it, that different tokens are used in these two cases.
self._mlist.subscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
+ ConfirmModerationSubscriptionPolicy)
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
# Run the state machine up to the first confirmation, and cache the
# confirmation token.
list(workflow)
@@ -630,7 +647,7 @@ approval:
self.assertIsNotNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
# The old token will not work for moderator approval.
- moderator_workflow = SubscriptionWorkflow(self._mlist)
+ moderator_workflow = self._mlist.subscription_policy(self._mlist)
moderator_workflow.token = token
moderator_workflow.restore()
list(moderator_workflow)
@@ -641,7 +658,7 @@ approval:
# that there's a new token for the next steps.
self.assertNotEqual(token, moderator_workflow.token)
# The old token won't work.
- final_workflow = SubscriptionWorkflow(self._mlist)
+ final_workflow = self._mlist.subscription_policy(self._mlist)
final_workflow.token = token
self.assertRaises(LookupError, final_workflow.restore)
# Running this workflow will fail.
@@ -666,11 +683,11 @@ approval:
def test_confirmation_needed_and_pre_confirmed(self):
# The subscription policy is 'confirm' but the subscription is
# pre-confirmed so the moderation checks can be skipped.
- self._mlist.subscription_policy = SubscriptionPolicy.confirm
+ self._mlist.subscription_policy = ConfirmSubscriptionPolicy
anne = self._user_manager.create_address(self._anne)
- workflow = SubscriptionWorkflow(
- self._mlist, anne,
- pre_verified=True, pre_confirmed=True, pre_approved=True)
+ workflow = self._mlist.subscription_policy(
+ self._mlist, anne,
+ pre_verified=True, pre_confirmed=True)
list(workflow)
# Anne was subscribed.
self.assertIsNone(workflow.token)
@@ -680,17 +697,18 @@ approval:
def test_restore_user_absorbed(self):
# The subscribing user is absorbed (and thus deleted) before the
# moderator approves the subscription.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_user(self._anne)
bill = self._user_manager.create_user('bill@example.com')
set_preferred(bill)
# anne subscribes.
- workflow = SubscriptionWorkflow(self._mlist, anne, pre_verified=True)
+ workflow = self._mlist.subscription_policy(self._mlist, anne,
+ pre_verified=True)
list(workflow)
# bill absorbs anne.
bill.absorb(anne)
# anne's subscription request is approved.
- approved_workflow = SubscriptionWorkflow(self._mlist)
+ approved_workflow = self._mlist.subscription_policy(self._mlist)
approved_workflow.token = workflow.token
approved_workflow.restore()
self.assertEqual(approved_workflow.user, bill)
@@ -700,19 +718,19 @@ approval:
def test_restore_address_absorbed(self):
# The subscribing user is absorbed (and thus deleted) before the
# moderator approves the subscription.
- self._mlist.subscription_policy = SubscriptionPolicy.moderate
+ self._mlist.subscription_policy = ModerationSubscriptionPolicy
anne = self._user_manager.create_user(self._anne)
anne_address = anne.addresses[0]
bill = self._user_manager.create_user('bill@example.com')
# anne subscribes.
- workflow = SubscriptionWorkflow(
- self._mlist, anne_address, pre_verified=True)
+ workflow = self._mlist.subscription_policy(
+ self._mlist, anne_address, pre_verified=True)
list(workflow)
# bill absorbs anne.
bill.absorb(anne)
self.assertIn(anne_address, bill.addresses)
# anne's subscription request is approved.
- approved_workflow = SubscriptionWorkflow(self._mlist)
+ approved_workflow = self._mlist.subscription_policy(self._mlist)
approved_workflow.token = workflow.token
approved_workflow.restore()
self.assertEqual(approved_workflow.user, bill)
diff --git a/src/mailman/app/tests/test_unsubscriptions.py b/src/mailman/workflows/tests/test_unsubscriptions.py
index 4ca657190..2e210e90b 100644
--- a/src/mailman/app/tests/test_unsubscriptions.py
+++ b/src/mailman/workflows/tests/test_unsubscriptions.py
@@ -21,14 +21,15 @@ import unittest
from contextlib import suppress
from mailman.app.lifecycle import create_list
-from mailman.app.subscriptions import UnSubscriptionWorkflow
-from mailman.interfaces.mailinglist import SubscriptionPolicy
from mailman.interfaces.pending import IPendings
from mailman.interfaces.subscriptions import TokenOwner
from mailman.interfaces.usermanager import IUserManager
from mailman.testing.helpers import LogFileMark, get_queue_messages
from mailman.testing.layers import ConfigLayer
from mailman.utilities.datetime import now
+from mailman.workflows.unsubscription import (
+ ConfirmModerationUnsubscriptionPolicy, ConfirmUnsubscriptionPolicy,
+ ModerationUnsubscriptionPolicy, OpenUnsubscriptionPolicy)
from unittest.mock import patch
from zope.component import getUtility
@@ -40,7 +41,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
self._mlist.admin_immed_notify = False
- self._mlist.unsubscription_policy = SubscriptionPolicy.open
+ self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy
self._mlist.send_welcome_message = False
self._anne = 'anne@example.com'
self._user_manager = getUtility(IUserManager)
@@ -58,7 +59,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def test_start_state(self):
# Test the workflow starts with no tokens or members.
- workflow = UnSubscriptionWorkflow(self._mlist)
+ workflow = self._mlist.unsubscription_policy(self._mlist)
self.assertEqual(workflow.token_owner, TokenOwner.no_one)
self.assertIsNone(workflow.token)
self.assertIsNone(workflow.member)
@@ -67,8 +68,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# Test there is a Pendable object associated with a held
# unsubscription request and it has some valid data associated with
# it.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
with suppress(StopIteration):
workflow.run_thru('send_confirmation')
self.assertIsNotNone(workflow.token)
@@ -84,23 +85,23 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def test_user_or_address_required(self):
# The `subscriber` attribute must be a user or address that is provided
# to the workflow.
- workflow = UnSubscriptionWorkflow(self._mlist)
+ workflow = OpenUnsubscriptionPolicy(self._mlist)
self.assertRaises(AssertionError, list, workflow)
def test_user_is_subscribed_to_unsubscribe(self):
# A user must be subscribed to a list when trying to unsubscribe.
addr = self._user_manager.create_address('aperson@example.org')
addr.verfied_on = now()
- workflow = UnSubscriptionWorkflow(self._mlist, addr)
+ workflow = self._mlist.unsubscription_policy(self._mlist, addr)
self.assertRaises(AssertionError,
workflow.run_thru, 'subscription_checks')
def test_confirmation_checks_open_list(self):
# An unsubscription from an open list does not need to be confirmed or
# moderated.
- self._mlist.unsubscription_policy = SubscriptionPolicy.open
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
- workflow.run_thru('confirmation_checks')
+ self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
+ workflow.run_thru('subscription_checks')
with patch.object(workflow, '_step_do_unsubscription') as step:
next(workflow)
step.assert_called_once_with()
@@ -108,10 +109,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def test_confirmation_checks_no_user_confirmation_needed(self):
# An unsubscription from a list which does not need user confirmation
# skips to the moderation checks.
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
- pre_confirmed=True)
- workflow.run_thru('confirmation_checks')
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
+ workflow.run_thru('subscription_checks')
with patch.object(workflow, '_step_moderation_checks') as step:
next(workflow)
step.assert_called_once_with()
@@ -120,8 +120,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# The unsubscription policy requires user-confirmation, but their
# unsubscription is pre-confirmed. Since moderation is not reuqired,
# the user will be immediately unsubscribed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(
self._mlist, self.anne, pre_confirmed=True)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_do_unsubscription') as step:
@@ -133,19 +133,19 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# unsubscription is pre-confirmed. Since moderation is required, that
# check will be performed.
self._mlist.unsubscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
- workflow = UnSubscriptionWorkflow(
+ ConfirmModerationUnsubscriptionPolicy)
+ workflow = self._mlist.unsubscription_policy(
self._mlist, self.anne, pre_confirmed=True)
workflow.run_thru('confirmation_checks')
- with patch.object(workflow, '_step_do_unsubscription') as step:
+ with patch.object(workflow, '_step_moderation_checks') as step:
next(workflow)
step.assert_called_once_with()
def test_send_confirmation_checks_confirm_list(self):
# The unsubscription policy requires user confirmation and the
# unsubscription is not pre-confirmed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
workflow.run_thru('confirmation_checks')
with patch.object(workflow, '_step_send_confirmation') as step:
next(workflow)
@@ -153,17 +153,17 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def test_moderation_checks_moderated_list(self):
# The unsubscription policy requires moderation.
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
- workflow.run_thru('confirmation_checks')
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
+ workflow.run_thru('subscription_checks')
with patch.object(workflow, '_step_moderation_checks') as step:
next(workflow)
step.assert_called_once_with()
def test_moderation_checks_approval_required(self):
# The moderator must approve the subscription request.
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
workflow.run_thru('moderation_checks')
with patch.object(workflow, '_step_get_moderator_approval') as step:
next(workflow)
@@ -172,8 +172,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def test_do_unsusbcription(self):
# An open unsubscription policy means the user gets unsubscribed to
# the mailing list without any further confirmations or approvals.
- self._mlist.unsubscription_policy = SubscriptionPolicy.open
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
list(workflow)
member = self._mlist.regular_members.get_member(self._anne)
self.assertIsNone(member)
@@ -182,9 +182,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# A moderation-requiring subscription policy plus a pre-approved
# address means the user gets unsubscribed from the mailing list
# without any further confirmation or approvals.
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
- pre_approved=True)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne,
+ pre_approved=True)
list(workflow)
# Anne is now unsubscribed form the mailing list.
member = self._mlist.regular_members.get_member(self._anne)
@@ -198,10 +198,10 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# address means the user gets unsubscribed to the mailing list without
# any further confirmations or approvals.
self._mlist.unsubscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
- pre_approved=True,
- pre_confirmed=True)
+ ConfirmModerationUnsubscriptionPolicy)
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne,
+ pre_approved=True,
+ pre_confirmed=True)
list(workflow)
member = self._mlist.regular_members.get_member(self._anne)
self.assertIsNone(member)
@@ -212,10 +212,8 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
def test_do_unsubscription_cleanups(self):
# Once the user is unsubscribed, the token and its associated pending
# database record will be removed from the database.
- self._mlist.unsubscription_policy = SubscriptionPolicy.open
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne,
- pre_approved=True,
- pre_confirmed=True)
+ self._mlist.unsubscription_policy = OpenUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
# Run the workflow.
list(workflow)
# Anne is now unsubscribed from the list.
@@ -229,9 +227,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# The workflow runs until moderator approval is required, at which
# point the workflow is saved. Once the moderator approves, the
# workflow resumes and the user is unsubscribed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(
- self._mlist, self.anne, pre_confirmed=True)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(
+ self._mlist, self.anne)
# Run the entire workflow.
list(workflow)
# The user is currently subscribed to the mailing list.
@@ -244,7 +242,7 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# Create a new workflow with the previous workflow's save token, and
# restore its state. This models an approved un-sunscription request
# and should result in the user getting subscribed.
- approved_workflow = UnSubscriptionWorkflow(self._mlist)
+ approved_workflow = self._mlist.unsubscription_policy(self._mlist)
approved_workflow.token = workflow.token
approved_workflow.restore()
list(approved_workflow)
@@ -260,9 +258,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# When the unsubscription is held for moderator approval, a message is
# logged.
mark = LogFileMark('mailman.subscribe')
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(
- self._mlist, self.anne, pre_confirmed=True)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(
+ self._mlist, self.anne)
# Run the entire workflow.
list(workflow)
self.assertIn(
@@ -277,9 +275,9 @@ class TestUnSubscriptionWorkflow(unittest.TestCase):
# When the unsubscription is held for moderator approval, and the list
# is so configured, a notification is sent to the list moderators.
self._mlist.admin_immed_notify = True
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(
- self._mlist, self.anne, pre_confirmed=True)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(
+ self._mlist, self.anne)
# Consume the entire state machine.
list(workflow)
items = get_queue_messages('virgin', expected_count=1)
@@ -305,9 +303,9 @@ request approval:
# the list is so configured, a notification is sent to the list
# moderators.
self._mlist.admin_immed_notify = False
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(
- self._mlist, self.anne, pre_confirmed=True)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(
+ self._mlist, self.anne)
# Consume the entire state machine.
list(workflow)
get_queue_messages('virgin', expected_count=0)
@@ -318,9 +316,9 @@ request approval:
def test_send_confirmation(self):
# A confirmation message gets sent when the unsubscription must be
# confirmed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
# Run the workflow to model the confirmation step.
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
list(workflow)
items = get_queue_messages('virgin', expected_count=1)
message = items[0].msg
@@ -336,8 +334,8 @@ request approval:
def test_do_confirmation_unsubscribes_user(self):
# Unsubscriptions to the mailing list must be confirmed. Once that's
# done, the user's address is unsubscribed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
list(workflow)
# Anne is a member.
member = self._mlist.regular_members.get_member(self._anne)
@@ -347,7 +345,7 @@ request approval:
self.assertIsNotNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
# Confirm.
- confirm_workflow = UnSubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.unsubscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
list(confirm_workflow)
@@ -363,8 +361,8 @@ request approval:
# done, the address is unsubscribed.
address = self.anne.register('anne.person@example.com')
self._mlist.subscribe(address)
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(self._mlist, address)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, address)
list(workflow)
# Bart is a member.
member = self._mlist.regular_members.get_member(
@@ -375,7 +373,7 @@ request approval:
self.assertIsNotNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
# Confirm.
- confirm_workflow = UnSubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.unsubscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
list(confirm_workflow)
@@ -390,8 +388,8 @@ request approval:
def test_do_confirmation_nonmember(self):
# Attempt to confirm the unsubscription of a member who has already
# been unsubscribed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
list(workflow)
# Anne is a member.
member = self._mlist.regular_members.get_member(self._anne)
@@ -403,7 +401,7 @@ request approval:
# Unsubscribe Anne out of band.
member.unsubscribe()
# Confirm.
- confirm_workflow = UnSubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.unsubscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
list(confirm_workflow)
@@ -414,8 +412,8 @@ request approval:
def test_do_confirmation_nonmember_final_step(self):
# Attempt to confirm the unsubscription of a member who has already
# been unsubscribed.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
list(workflow)
# Anne is a member.
member = self._mlist.regular_members.get_member(self._anne)
@@ -425,7 +423,7 @@ request approval:
self.assertIsNotNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
# Confirm.
- confirm_workflow = UnSubscriptionWorkflow(self._mlist)
+ confirm_workflow = self._mlist.unsubscription_policy(self._mlist)
confirm_workflow.token = workflow.token
confirm_workflow.restore()
confirm_workflow.run_until('do_unsubscription')
@@ -443,8 +441,8 @@ request approval:
# the user confirming their subscription, and then the moderator
# approving it, that different tokens are used in these two cases.
self._mlist.unsubscription_policy = (
- SubscriptionPolicy.confirm_then_moderate)
- workflow = UnSubscriptionWorkflow(self._mlist, self.anne)
+ ConfirmModerationUnsubscriptionPolicy)
+ workflow = self._mlist.unsubscription_policy(self._mlist, self.anne)
# Run the state machine up to the first confirmation, and cache the
# confirmation token.
list(workflow)
@@ -457,7 +455,7 @@ request approval:
self.assertIsNotNone(workflow.token)
self.assertEqual(workflow.token_owner, TokenOwner.subscriber)
# The old token will not work for moderator approval.
- moderator_workflow = UnSubscriptionWorkflow(self._mlist)
+ moderator_workflow = self._mlist.unsubscription_policy(self._mlist)
moderator_workflow.token = token
moderator_workflow.restore()
list(moderator_workflow)
@@ -468,7 +466,7 @@ request approval:
# that there's a new token for the next steps.
self.assertNotEqual(token, moderator_workflow.token)
# The old token won't work.
- final_workflow = UnSubscriptionWorkflow(self._mlist)
+ final_workflow = self._mlist.unsubscription_policy(self._mlist)
final_workflow.token = token
self.assertRaises(LookupError, final_workflow.restore)
# Running this workflow will fail.
@@ -492,9 +490,9 @@ request approval:
def test_confirmation_needed_and_pre_confirmed(self):
# The subscription policy is 'confirm' but the subscription is
# pre-confirmed so the moderation checks can be skipped.
- self._mlist.unsubscription_policy = SubscriptionPolicy.confirm
- workflow = UnSubscriptionWorkflow(
- self._mlist, self.anne, pre_confirmed=True, pre_approved=True)
+ self._mlist.unsubscription_policy = ConfirmUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(
+ self._mlist, self.anne, pre_confirmed=True)
list(workflow)
# Anne was unsubscribed.
self.assertIsNone(workflow.token)
@@ -504,11 +502,11 @@ request approval:
def test_confirmation_needed_moderator_address(self):
address = self.anne.register('anne.person@example.com')
self._mlist.subscribe(address)
- self._mlist.unsubscription_policy = SubscriptionPolicy.moderate
- workflow = UnSubscriptionWorkflow(self._mlist, address)
+ self._mlist.unsubscription_policy = ModerationUnsubscriptionPolicy
+ workflow = self._mlist.unsubscription_policy(self._mlist, address)
# Get moderator approval.
list(workflow)
- approved_workflow = UnSubscriptionWorkflow(self._mlist)
+ approved_workflow = self._mlist.unsubscription_policy(self._mlist)
approved_workflow.token = workflow.token
approved_workflow.restore()
list(approved_workflow)
diff --git a/src/mailman/app/tests/test_workflow.py b/src/mailman/workflows/tests/test_workflow.py
index e82001540..3e7856b29 100644
--- a/src/mailman/app/tests/test_workflow.py
+++ b/src/mailman/workflows/tests/test_workflow.py
@@ -20,15 +20,15 @@
import json
import unittest
-from mailman.app.workflow import Workflow
-from mailman.interfaces.workflow import IWorkflowStateManager
+from mailman.interfaces.workflows import IWorkflowStateManager
from mailman.testing.layers import ConfigLayer
+from mailman.workflows.base import Workflow
from zope.component import getUtility
class MyWorkflow(Workflow):
- INITIAL_STATE = 'first'
- SAVE_ATTRIBUTES = ('ant', 'bee', 'cat')
+ initial_state = 'first'
+ save_attributes = ('ant', 'bee', 'cat')
def __init__(self):
super().__init__()
@@ -51,7 +51,7 @@ class MyWorkflow(Workflow):
class DependentWorkflow(MyWorkflow):
- SAVE_ATTRIBUTES = ('ant', 'bee', 'cat', 'elf')
+ save_attributes = ('ant', 'bee', 'cat', 'elf')
def __init__(self):
super().__init__()
@@ -136,7 +136,7 @@ class TestWorkflow(unittest.TestCase):
def test_save_and_restore_dependant_attributes(self):
# Attributes must be restored in the order they are declared in
- # SAVE_ATTRIBUTES.
+ # save_attributes.
workflow = iter(DependentWorkflow())
workflow.elf = 6
workflow.save()
@@ -153,7 +153,7 @@ class TestWorkflow(unittest.TestCase):
# Save the state of an old version of the workflow that would not have
# the cat attribute.
state_manager.save(
- self._workflow.token, 'first',
+ self._workflow.token, '["first"]',
json.dumps({'ant': 1, 'bee': 2}))
# Restore in the current version that needs the cat attribute.
new_workflow = MyWorkflow()