-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add search day-care functionality to dog-owner homepage. #89
base: main
Are you sure you want to change the base?
Conversation
320fec9
to
408ddb7
Compare
408ddb7
to
2dcf8d7
Compare
b5ebfcd
to
8b32e15
Compare
8b32e15
to
d573c3f
Compare
daycare/test_image.py
Outdated
def test_daycare_has_default_profile_image(self, create_daycare_user): | ||
daycare_profile_image = create_daycare_user.get_daycare_primary_image_url() | ||
assert daycare_profile_image == DEFAULT_DAYCARE_PROFILE_URL | ||
assert daycare_profile_image is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this test is redundant , if profile_image = default so obviously its not None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please note that this comment related to #67
main/tests.py
Outdated
client.force_login(user=create_dog_owner_user.user) | ||
response = client.get("/homepage/") | ||
day_care_queryset = response.context['day_care_queryset'] | ||
assert day_care_queryset.count() == DayCare.objects.all().count() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe instead of count use set(day_care_queryset) == set(daycare.objects.all) because if the count is the same we are not sure we presenting all daycares, maybe we present the same one 30 times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im not sure I fully understand , but in this test we want to check that day_care_queryset contain all Daycare objects when we are entering to dog_owner homepage.
Since every user is unique it is promise that every object in the queryset is diffrent from the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's right for the right side of the assert (daycare.objects), what about what is presented in HTML (daycare_queryset), how can you be sure that they are unique and don't have dups, for example, daycare shown twice in HTML or things like that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And anyway it just seems weird to conclude equality between sets by their size, even if all the values are unique
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The HTML running for loop and create a card for each daycare in day_care queryset,I think in this case we should test what this queryset contatin .
Thanks for the advice I fixed it to use set(day_care_queryset) == set(daycare.objects.all) and it is seems better !
main/tests.py
Outdated
for day_care in DayCare.objects.all(): | ||
if day_care.price_per_day <= 800 and day_care.area.lower() == 'center'\ | ||
and day_care.city.lower() == 'tel aviv': | ||
assert day_care in day_care_queryset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe also check that all day_care_queryset is in filter range,
your test checks that all filtered daycares are shown, maybe add a test that all daycares in day_care_queryset are the correct ones.
Easy hit append all daycares in the for to list, then assert equality between this list to day_care_queryset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You right . We can deal with it in the same way of #89 (comment)
6d6b01a
to
981fa2f
Compare
@tamirmatok this PR is ready for review? notice that the PR is on draft |
86f6365
to
ba9bee6
Compare
Now it is (: |
The idea about making the area a choice box is great! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens in the case that after filtering the daycares, there were no daycares that match the selection of the user? I think in that case we should write to the user something like:
There were no daycares found that match the filtering that was selected
We have a generic sentence for all the search results : "Found %d results for your dog" . How does it sound ? @ErezCohenn |
2175321
to
48c3373
Compare
Sounds good :) |
Hi @OfirMatasas, I think you right and that issue appeared in my head as well. I think the right approch to deal with this issue is kind of "preapre the ground" for supporting in user-registration, with django-cities(see https://pypi.org/project/django-cities/), it looks better to me because of the benefits of global support or even local but with more percise data. |
I think you're right. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
daycare/forms.py
Outdated
|
||
class DayCareSearchForm(forms.Form): | ||
min_price = DayCare.objects.all().aggregate(Min('price_per_day')).get('price_per_day__min') | ||
max_price = DayCare.objects.all().aggregate(Max('price_per_day')).get('price_per_day__max') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure the user should be aware of the min\max values a daycare can use for his pricing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you right ,Fixed.
|
||
area = forms.ChoiceField(required=False, label='Area', | ||
choices=(Area.choices + [('', 'All'), ]), initial="") | ||
city = forms.CharField(required=False, label='City') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we have a list of cities? a free-text would be tough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see #89 (comment) and let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you sum it up? I'm not sure I'm following. Anyway free-text can lead to issues (e.g: פתח-תקוה, פתח תקווה, פתח-תקווה, פתח תקוה)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List of cities seems to me good solution for static-users ,but because all users are static we can control the cities input and just avoid mistakes like that.
If we will want to support registration in the future it might limit us .
I saw django-cities(see https://pypi.org/project/django-cities/), it seems to have benefits of global support or even local but with more percise data.
I have no problem to create list of cities just want to know your opinion about it . @Omeramsc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UI is an entry point for this app and as such it should perform validation on the input,
regardless if the users are static or not.
Nothing prevents for the next dev to create another static user and enter non valid city name, right?
If this is a lot of work you can do it on a follow up PR and write in the PR description about it.
class DayCare(models.Model): | ||
user = models.OneToOneField(User, on_delete=models.CASCADE, default=None, blank=True, null=False, editable=True) | ||
name = models.CharField(max_length=20, blank=True, unique=True, validators=[MaxLengthValidator]) | ||
description = models.TextField(blank=True, null=True) | ||
price_per_day = models.IntegerField(blank=False, null=False, default=0) | ||
capacity = models.IntegerField(null=False, blank=True) | ||
area = models.CharField(max_length=20, blank=True, validators=[MaxLengthValidator]) | ||
area = models.CharField(max_length=20, blank=True, validators=[MaxLengthValidator], choices=Area.choices) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we include that in some of the daycare fixtures?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Area field in create_day_care_user from the confest been updated.
dogowner/views.py
Outdated
form['end_date'].value()) | ||
day_care_queryset = filter_day_cares.intersection(available_day_cares) | ||
|
||
context = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to include it twice; since both use the same parameters, just include it once after the conditional statements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You right NP, fixed.
main/tests.py
Outdated
@pytest.mark.django_db | ||
class TestDogOwnerHomePageView: | ||
def test_search_daycare_present_only_available_daycares_on_specific_dates(self, client, create_dog_owner_user): | ||
test_day_care = DayCare.create(username='testuser', email='[email protected]', password='test_password', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
didn't we add a bunch of fixtures to conftest so we won't need this anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I didnt use the fixture from the confest file is because it is easier to test this case through day-care with capcity=1.
Let me know if you think that it deserve a place in the confest file .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference? how much more work do you need to do if you use the fixture?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one for loop for decreasing the capcity from 50 to 0 (that means to create 50 orders to fulfill the capacity )
Another option is to change the capacity in the fixture . @Omeramsc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
main/tests.py
Outdated
filters_day_cares = DayCare.objects.filter(area__startswith='C', | ||
city__icontains="tel aviv", | ||
price_per_day__lte=800) | ||
assert set(day_care_queryset) == set(available_day_cares.intersection(filters_day_cares)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we test the functionality of the filter? I mean: do we expect specific search results? what are the day cares that exists during this test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The day-cares that exists during this test are the static day-cares from the migration file .
In this test I considered the filters queryset as the expected results and make sure that the 'day_care_queryset' from the response is the same .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test should verify the functionality would work in any case, and not only a specific one we carefully created.
what is intersection
? what does it provide? This proves the usefulness of declaring the variables before asserting them...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP I will make it more clear .Since we want to filter by capacity of day-care in specific dates we have to create a query set that contain all day-cares avaible in dates , and the other queryset, with the other fields of the search.
The intersection between those querysets will give us all day-cares avaible in specific dates that fit with the other filters .
Do you have an idea how can I make this test more general like you mention ?
Because if I will try all the combination of the filters we won't get out of it. @Omeramsc
main/tests.py
Outdated
response = client.post('/homepage/', search_form, follow=True) | ||
day_care_queryset = response.context['day_care_queryset'] | ||
assert test_day_care in day_care_queryset | ||
Order.create(dog_owner_id=DogOwner.objects.get(id=1), daycare_id=test_day_care, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
belong in a different test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain ? Do you think that create day-care with capcity=0, and test that it doesn't appear in the queryset is better approch ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on the first assertion you check that a daycare with capacity is available,
in the second one you check that a daycare with no capacity is not available.
those are two different cases.
BUT, on second thought, I think it can keep it like this. but put spaces between different parts of the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and change the name of the test. it doesn't check that the daycare is available on specific dates. it checks that a daycare is not available after its capacity been reduced to 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You right thanks for making it clear, Fixed.
@@ -76,4 +78,59 @@ def test_dog_owner_homepage_is_visible_for_dog_owner(self, client, create_dog_ow | |||
client.force_login(user=create_dog_owner_user.user) | |||
response = client.get("/homepage/") | |||
assert response.status_code == 200 | |||
assert list(response.context['daycares']) == list(DayCare.objects.all()) | |||
assert set(response.context['day_care_queryset']) == set(DayCare.objects.all()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this test is ensuring that the page will have a list of all the day cares, maybe it should be mentioned in its name. or in a different test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP , Fixed by changing the name to " test_dog_owner_homepage_present_all_daycares"
Adding area choices for make the data model compatible, which will improve search for day care by area results. Signed-off-by: tamirmatok <[email protected]>
48c3373
to
f6d788a
Compare
The dog-owner user can search for day-care that relevant for him. If the user didnt search for day-care he will see all Day-Cares in the application. Signed-off-by: tamirmatok <[email protected]>
f6d788a
to
3a06865
Compare
Capacity dates check for show only available daycares in dates range. "get_capacity_of_daycare_in_dates_range" function took from redhat-beyond#95 . waiting for approval. Signed-off-by: tamirmatok <[email protected]>
3a06865
to
eea8053
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Tamir,
Note that there is no need to add .
at the end of a commit message title, please remove them.
There is typo at second commit title funconallity
instead of functionality
.
Please see my inline comments
@@ -76,7 +76,7 @@ def daycare_data(): | |||
pytest.DESCRIPTION = "This is the first daycare test" | |||
pytest.PRICE_PER_DAY = 10 | |||
pytest.CAPACITY = 50 | |||
pytest.AREA = "Merkaz" | |||
pytest.AREA = "C" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Why not using the full name? 🙂
|
||
area = forms.ChoiceField(required=False, label='Area', | ||
choices=(Area.choices + [('', 'All'), ]), initial="") | ||
city = forms.CharField(required=False, label='City') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UI is an entry point for this app and as such it should perform validation on the input,
regardless if the users are static or not.
Nothing prevents for the next dev to create another static user and enter non valid city name, right?
If this is a lot of work you can do it on a follow up PR and write in the PR description about it.
client.force_login(user=create_dog_owner_user.user) | ||
response = client.post('/homepage/', search_form, follow=True) | ||
day_care_queryset = response.context['day_care_queryset'] | ||
assert daycare_user in day_care_queryset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make the test look nicer if the assertion would be separated with newline from the test setup logic (all over this file).
expected_queryset = available_day_cares.intersection(filter_day_cares) | ||
assert set(day_care_queryset) == set(expected_queryset) | ||
|
||
def test_search_for_day_care_with_start_date_greater_than_end_date_show_error_and_present_all_daycares( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By mentioning with_start_date_greater_than_end_date
it makes me think this is the only case all daycares will show.
Would it make sense to rename this test to something like:
test_dog_owner_page_view_presents_all_daycares_when_search_results_is_empty
?
In other words, would all daycare show in case of a search error?
Conflicts preventing this from merging. Sorry, It probably won't be able to get in for the demo. |
Desired Outcome
The dog-owner user will search for day-care that relevant for him.
If the user didnt search for day-care he will see all Day-Cares in dog-owner homepage.
Implemented Changes
Connected Issue/Story
depends on #95
Closes #90
Test coverage
changes
Documentation
README
s) were updated in this PR