Skip to content

Commit

Permalink
Fix/only call post create signal once (#3)
Browse files Browse the repository at this point in the history
* Updates create function in BulkTrackerQuerySet

* Adds testcases

* Updates version

* Updates CHANGELOG.md
  • Loading branch information
MrAghyad authored Jul 6, 2023
1 parent 43f5c11 commit ebf2172
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

All notable changes to this project will be documented in this file.

## 0.0.7 (2023-07-06)
- A fix where `send_post_create_signal()` was being called twice when creating an object through `BulkTrackerQuerySet.create()`

## 0.0.6 (2023-05-28)
- Inheriting from BulkTrackerQuerySet is no longer mandatory.
- If you don't have a custom Manager/QuerySet, You can just make your model inherit BulkTrackerModel.
Expand Down
2 changes: 1 addition & 1 deletion bulk_tracker/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.0.6"
__version__ = "0.0.7"
3 changes: 2 additions & 1 deletion bulk_tracker/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ def create(self, *, tracking_info_: TrackingInfo | None = None, **kwargs):
Create a new object with the given kwargs, saving it to the database
and returning the created object.
"""

# NOTE: send_post_create_signal is called after 'create' gets executed, where model.save is called
obj = super().create(**kwargs)
send_post_create_signal([obj], model=self.model, tracking_info_=tracking_info_)
return obj

# This function is just copied from django core, with minor modification to accept TrackingInfo
Expand Down
73 changes: 73 additions & 0 deletions tests/test_create_signal.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from unittest.mock import patch

from django.test import TestCase

from bulk_tracker.helper_objects import ModifiedObject, TrackingInfo
Expand Down Expand Up @@ -109,3 +111,74 @@ def post_create_receiver(
self.assertEqual("1998-01-08", modified_objects[0].instance.publish_date)
self.assertEqual(self.author_john, modified_objects[0].instance.author)
self.assertEqual({}, modified_objects[0].changed_values)

@patch('bulk_tracker.signals.post_create_signal.send')
def test_model_save_should_only_emit_post_create_signal_once(self, mocked_signal):
# Arrange
signal_called_with = {}

def post_create_receiver(
sender,
objects: list[ModifiedObject[Post]],
tracking_info_: TrackingInfo | None = None,
**kwargs,
):
signal_called_with["objects"] = objects
signal_called_with["tracking_info_"] = tracking_info_

post_create_signal.connect(post_create_receiver, sender=Post)

# Act
Post(title="Sound of Winter", publish_date="1998-01-08", author=self.author_john).save()

# Assert
self.assertEqual(mocked_signal.call_count, 1, msg="The signal wasn't called once")

@patch('bulk_tracker.signals.post_create_signal.send')
def test_model_create_should_only_emit_post_create_signal_once(self, mocked_signal):
# Arrange
signal_called_with = {}

def post_create_receiver(
sender,
objects: list[ModifiedObject[Post]],
tracking_info_: TrackingInfo | None = None,
**kwargs,
):
signal_called_with["objects"] = objects
signal_called_with["tracking_info_"] = tracking_info_

post_create_signal.connect(post_create_receiver, sender=Post)

# Act
Post.objects.create(title="Sound of Winter", publish_date="1998-03-08", author=self.author_john)

# Assert
self.assertEqual(mocked_signal.call_count, 1, msg="The signal wasn't called once")

@patch('bulk_tracker.signals.post_create_signal.send')
def test_model_bulk_create_should_only_emit_post_create_signal_once(self, mocked_signal):
# Arrange
signal_called_with = {}

def post_create_receiver(
sender,
objects: list[ModifiedObject[Post]],
tracking_info_: TrackingInfo | None = None,
**kwargs,
):
signal_called_with["objects"] = objects
signal_called_with["tracking_info_"] = tracking_info_

post_create_signal.connect(post_create_receiver, sender=Post)

posts = [
Post(title="Sound of Winter", publish_date="1998-01-08", author=self.author_john),
Post(title="Sound of Summer", publish_date="1998-06-08", author=self.author_john),
]

# Act
Post.objects.bulk_create(posts)

# Assert
self.assertEqual(mocked_signal.call_count, 1, msg="The signal wasn't called once")

0 comments on commit ebf2172

Please sign in to comment.