def setUp(self): """ Setup common conditions for every test case. """ super().setUp() self.event_type = "org.openedx.learning.session.login.completed.v1" self.user_mock = Mock() self.data_attr = { "user": Mock, } self.public_signal = OpenEdxPublicSignal( event_type=self.event_type, data=self.data_attr, )
def create_simple_signal(data_dict): """ Create a basic OpenEdxPublicSignal with init_data = data_dict Arguments: data_dict: Description of attributes passed to the signal """ return OpenEdxPublicSignal(event_type="simple.signal", data=data_dict)
def enable_events_by_type(cls, *event_types): """ Enable specific Open edX Events given their type. Arguments: event_types (list of `str`): types of events to enable. """ for event_type in event_types: try: event = OpenEdxPublicSignal.get_signal_by_type(event_type) except KeyError: all_event_types = sorted( s.event_type for s in OpenEdxPublicSignal.all_events()) err_msg = ( "You tried to enable event '{}', but I don't recognize that " "signal type. Did you mean one of these?: {}") raise ValueError(err_msg.format(event_type, all_event_types)) # pylint: disable=raise-missing-from event.enable()
def allow_send_events_failure(cls, *event_types): """ Allow that send_event method fails for the specified event. This method determines which `send` method to use, send or send_robust. The first, raises receivers exceptions while the latter catches them. Arguments: event_types (list of `str`): types of events to enable. """ for event_type in event_types: try: event = OpenEdxPublicSignal.get_signal_by_type(event_type) except KeyError: all_event_types = sorted( s.event_type for s in OpenEdxPublicSignal.all_events()) err_msg = ( "You tried to enable event '{}', but I don't recognize that " "signal type. Did you mean one of these?: {}") raise ValueError(err_msg.format(event_type, all_event_types)) # pylint: disable=raise-missing-from event.allow_send_event_failure()
class OpenEdxPublicSignalTest(TestCase): """ Test cases for Open edX events base class. """ def setUp(self): """ Setup common conditions for every test case. """ super().setUp() self.event_type = "org.openedx.learning.session.login.completed.v1" self.user_mock = Mock() self.data_attr = { "user": Mock, } self.public_signal = OpenEdxPublicSignal( event_type=self.event_type, data=self.data_attr, ) def test_string_representation(self): """ This methods checks the string representation for events base class. Expected behavior: The representation contains the event_type. """ self.assertIn(self.event_type, str(self.public_signal)) @override_settings(SERVICE_VARIANT="lms") @patch("openedx_events.data.openedx_events") @patch("openedx_events.data.socket") def test_get_signal_metadata(self, socket_mock, events_package_mock): """ This methods tests getting the generated metadata for an event. Expected behavior: Returns the metadata containing information about the event. """ events_package_mock.__version__ = "0.1.0" socket_mock.gethostname.return_value = "edx.devstack.lms" expected_metadata = { "event_type": self.event_type, "minorversion": 0, "source": "openedx/lms/web", "sourcehost": "edx.devstack.lms", "sourcelib": [0, 1, 0], } metadata = self.public_signal.generate_signal_metadata() self.assertDictContainsSubset(expected_metadata, attr.asdict(metadata)) @patch( "openedx_events.tooling.OpenEdxPublicSignal.generate_signal_metadata") @patch("openedx_events.tooling.Signal.send") def test_send_event_successfully(self, send_mock, fake_metadata): """ This method tests the process of sending an event that's allow to fail. Expected behavior: The event is sent as a django signal with send method. """ expected_metadata = Mock(some_data="some_data") fake_metadata.return_value = expected_metadata self.public_signal.allow_send_event_failure() self.public_signal.send_event(user=self.user_mock) send_mock.assert_called_once_with( sender=None, user=self.user_mock, metadata=expected_metadata, ) @patch( "openedx_events.tooling.OpenEdxPublicSignal.generate_signal_metadata") @patch("openedx_events.tooling.Signal.send_robust") def test_send_robust_event_successfully(self, send_robust_mock, fake_metadata): """ This method tests the process of sending an event that won't crash. Expected behavior: The event is sent as a django signal with send_robust method. """ expected_metadata = Mock(some_data="some_data") fake_metadata.return_value = expected_metadata send_robust_mock.return_value.__name__ = "func_name" self.public_signal.send_event(user=self.user_mock) send_robust_mock.assert_called_once_with( sender=None, user=self.user_mock, metadata=expected_metadata, ) @ddt.data( ( { "student": Mock() }, "SenderValidationError org.openedx.learning.session.login.completed.v1: " "Missing required argument 'user'", ), ( { "user": { "student": Mock() } }, "SenderValidationError org.openedx.learning.session.login.completed.v1: " "The argument 'user' is not instance of the Class Attribute 'type'", ), ( { "student": Mock(), "user": Mock() }, "SenderValidationError org.openedx.learning.session.login.completed.v1: " "There's a mismatch between initialization data and send_event arguments", ), ) @ddt.unpack def test_invalid_sender(self, send_arguments, exception_message): """ This method tests sending an event with invalid setup on the sender side. Expected behavior: A SenderValidationError exception is raised. """ with self.assertRaisesMessage(SenderValidationError, exception_message): self.public_signal.send_event(**send_arguments) def test_send_event_with_django(self): """ This method tests sending an event using the `send` built-in Django method. Expected behavior: A warning is showed advicing to use Open edX events custom send_signal method. """ message = "Please, use 'send_event' when triggering an Open edX event." with self.assertWarns(Warning, msg=message): self.public_signal.send(sender=Mock()) def test_send_robust_event_with_django(self): """ This method tests sending an event using the `send` built-in Django method. Expected behavior: A warning is showed advicing to use Open edX events custom send_signal method. """ message = "Please, use 'send_event' with send_robust equals to True when triggering an Open edX event." with self.assertWarns(Warning, msg=message): self.public_signal.send_robust(sender=Mock()) @patch("openedx_events.tooling.Signal.send") def test_send_event_disabled(self, send_mock): """ This method tests sending an event that has been disabled. Expected behavior: The Django Signal associated to the event is not sent. """ self.public_signal.disable() result = self.public_signal.send_event(sender=Mock()) send_mock.assert_not_called() self.assertListEqual([], result)
from openedx_events.learning.data import ( CertificateData, CohortData, CourseDiscussionConfigurationData, CourseEnrollmentData, UserData, ) from openedx_events.tooling import OpenEdxPublicSignal # .. event_type: org.openedx.learning.student.registration.completed.v1 # .. event_name: STUDENT_REGISTRATION_COMPLETED # .. event_description: emitted when the user registration process in the LMS is completed. # .. event_data: UserData STUDENT_REGISTRATION_COMPLETED = OpenEdxPublicSignal( event_type="org.openedx.learning.student.registration.completed.v1", data={ "user": UserData, }) # .. event_type: org.openedx.learning.auth.session.login.completed.v1 # .. event_name: SESSION_LOGIN_COMPLETED # .. event_description: emitted when the user's login process in the LMS is completed. # .. event_data: UserData SESSION_LOGIN_COMPLETED = OpenEdxPublicSignal( event_type="org.openedx.learning.auth.session.login.completed.v1", data={ "user": UserData, }) # .. event_type: org.openedx.learning.course.enrollment.created.v1 # .. event_name: COURSE_ENROLLMENT_CREATED
""" Custom signals definitions that representing the Open edX platform events. All signals defined in this module must follow the name and versioning conventions specified in docs/decisions/0002-events-naming-and-versioning.rst They also must comply with the payload definition specified in docs/decisions/0003-events-payload.rst """ from openedx_events.enterprise.data import SubscriptionLicenseData from openedx_events.tooling import OpenEdxPublicSignal # .. event_type: org.openedx.enterprise.subscription.license.modified.v1 # .. event_name: LICENSE_MODIFIED # .. event_description: emitted when a Subscription License is modified, # where "modified" means created, updated, revoked, etc. # WARNING: This event is being used for event bus prototype purposes and # should not be used, and should not be copied as a fully vetted pattern. # TODO(EventBus): Delete or make production ready post-prototype phase. # We will be splitting different actions into their own events (for created, # updated, revoked, etc.) # See: https://openedx.atlassian.net/browse/ARCHBOM-2008 for more details. # .. event_data: SubscriptionLicenseData SUBSCRIPTION_LICENSE_MODIFIED = OpenEdxPublicSignal( event_type="org.openedx.enterprise.subscription.license.modified.v0", data={ "license": SubscriptionLicenseData, })
def enable_all_events(cls): """ Enable all events Open edX Events from all subdomains. """ for event in OpenEdxPublicSignal.all_events(): event.enable()
""" Signals for discussions """ from openedx_events.tooling import OpenEdxPublicSignal from openedx.core.djangoapps.discussions.data import CourseDiscussionConfigurationData # TODO: This will be moved to openedx_events. It's currently here to simplify the PR. # .. event_type: org.openedx.learning.discussions.configuration.change.v1 # .. event_name: COURSE_DISCUSSIONS_UPDATED # .. event_description: emitted when the configuration for a course's discussions changes in the course # .. event_data: CourseDiscussionConfigurationData COURSE_DISCUSSIONS_UPDATED = OpenEdxPublicSignal( event_type="org.openedx.learning.discussions.configuration.change.v1", data={ "configuration": CourseDiscussionConfigurationData } )