From ab968f225bc18cc91ef1c7ef9c981254ddee6bd7 Mon Sep 17 00:00:00 2001 From: smilerz Date: Wed, 8 Dec 2021 16:41:20 -0600 Subject: [PATCH] test recent shopping list --- cookbook/tests/api/test_api_meal_plan.py | 6 +- .../api/test_api_shopping_list_entryv2.py | 70 +++++++++++++++++-- cookbook/views/api.py | 2 +- vue/package-lock.json | 6 +- vue/package.json | 4 +- .../ShoppingListView/ShoppingListView.vue | 10 ++- vue/src/components/ShoppingLineItem.vue | 13 +++- vue/src/locales/en.json | 3 +- 8 files changed, 95 insertions(+), 19 deletions(-) diff --git a/cookbook/tests/api/test_api_meal_plan.py b/cookbook/tests/api/test_api_meal_plan.py index 37b52e88..bda00563 100644 --- a/cookbook/tests/api/test_api_meal_plan.py +++ b/cookbook/tests/api/test_api_meal_plan.py @@ -106,7 +106,7 @@ def test_add(arg, request, u1_s2, recipe_1_s1, meal_type): r = c.post( reverse(LIST_URL), {'recipe': {'id': recipe_1_s1.id, 'name': recipe_1_s1.name, 'keywords': []}, 'meal_type': {'id': meal_type.id, 'name': meal_type.name}, - 'date': (datetime.now()).strftime("%Y-%m-%d"), 'servings': 1, 'title': 'test','shared':[]}, + 'date': (datetime.now()).strftime("%Y-%m-%d"), 'servings': 1, 'title': 'test', 'shared': []}, content_type='application/json' ) response = json.loads(r.content) @@ -139,3 +139,7 @@ def test_delete(u1_s1, u1_s2, obj_1): assert r.status_code == 204 with scopes_disabled(): assert MealPlan.objects.count() == 0 + + +# TODO test auto creating shopping list from meal plan +# TODO test excluding on-hand when auto creating shopping list diff --git a/cookbook/tests/api/test_api_shopping_list_entryv2.py b/cookbook/tests/api/test_api_shopping_list_entryv2.py index e0e77df7..7efddac9 100644 --- a/cookbook/tests/api/test_api_shopping_list_entryv2.py +++ b/cookbook/tests/api/test_api_shopping_list_entryv2.py @@ -1,10 +1,12 @@ import json +from datetime import timedelta import factory import pytest from django.contrib import auth from django.forms import model_to_dict from django.urls import reverse +from django.utils import timezone from django_scopes import scopes_disabled from pytest_factoryboy import LazyFixture, register @@ -155,15 +157,73 @@ def test_sharing(request, shared, count, sle_2, sle, u1_s1): assert len(json.loads(r.content)) == count -# TODO test completed entries still visible if today, but not yesterday +def test_completed(sle, u1_s1): + # check 1 entry + # + u1_s1.patch( + reverse(DETAIL_URL, args={sle[0].id}), + {'checked': True}, + content_type='application/json' + ) + r = json.loads(u1_s1.get(reverse(LIST_URL)).content) + assert len(r) == 10 + # count unchecked entries + assert [x['checked'] for x in r].count(False) == 9 + # confirm completed_at is populated + assert [(x['completed_at'] != None) for x in r if x['checked']].count(True) == 1 + + assert len(json.loads(u1_s1.get(f'{reverse(LIST_URL)}?checked=0').content)) == 9 + assert len(json.loads(u1_s1.get(f'{reverse(LIST_URL)}?checked=1').content)) == 1 + + # uncheck entry + u1_s1.patch( + reverse(DETAIL_URL, args={sle[0].id}), + {'checked': False}, + content_type='application/json' + ) + r = json.loads(u1_s1.get(reverse(LIST_URL)).content) + assert [x['checked'] for x in r].count(False) == 10 + # confirm completed_at value cleared + assert [(x['completed_at'] != None) for x in r if x['checked']].count(True) == 0 + + +def test_recent(sle, u1_s1): + user = auth.get_user(u1_s1) + today_start = timezone.now().replace(hour=0, minute=0, second=0) + + # past_date within recent_days threshold + past_date = today_start - timedelta(days=user.userpreference.shopping_recent_days - 1) + sle[0].checked = True + sle[0].completed_at = past_date + sle[0].save() + + r = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?recent=1').content) + assert len(r) == 10 + assert [x['checked'] for x in r].count(False) == 9 + + # past_date outside recent_days threshold + past_date = today_start - timedelta(days=user.userpreference.shopping_recent_days + 2) + sle[0].completed_at = past_date + sle[0].save() + + r = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?recent=1').content) + assert len(r) == 9 + assert [x['checked'] for x in r].count(False) == 9 + + # user preference moved to include entry again + user.userpreference.shopping_recent_days = user.userpreference.shopping_recent_days + 4 + user.userpreference.save() + + r = json.loads(u1_s1.get(f'{reverse(LIST_URL)}?recent=1').content) + assert len(r) == 10 + assert [x['checked'] for x in r].count(False) == 9 + + # TODO test create shopping list from recipe # TODO test delete shopping list from recipe - include created by, shared with and not shared with # TODO test create shopping list from food # TODO test delete shopping list from food - include created by, shared with and not shared with # TODO test create shopping list from mealplan # TODO test create shopping list from recipe, excluding ingredients -# TODO test auto creating shopping list from meal plan -# TODO test excluding on-hand when auto creating shopping list + # test delay -# test completed_at when checked -# test completed_at cleared when unchecked diff --git a/cookbook/views/api.py b/cookbook/views/api.py index 68e3cea9..ae0c6cab 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -716,7 +716,7 @@ class ShoppingListEntryViewSet(viewsets.ModelViewSet): if pk := self.request.query_params.getlist('id', []): self.queryset = self.queryset.filter(food__id__in=[int(i) for i in pk]) - if bool(int(self.request.query_params.get('recent', False))): + if 'checked' in self.request.query_params or 'recent' in self.request.query_params: return shopping_helper(self.queryset, self.request) # TODO once old shopping list is removed this needs updated to sharing users in preferences diff --git a/vue/package-lock.json b/vue/package-lock.json index 76e4a954..3e863a97 100644 --- a/vue/package-lock.json +++ b/vue/package-lock.json @@ -13193,9 +13193,9 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", + "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", "dev": true }, "uc.micro": { diff --git a/vue/package.json b/vue/package.json index 8b275715..669bac46 100644 --- a/vue/package.json +++ b/vue/package.json @@ -49,8 +49,8 @@ "@vue/eslint-config-typescript": "^9.1.0", "babel-eslint": "^10.1.0", "eslint": "^7.28.0", - "eslint-plugin-vue": "^8.2.0", - "typescript": "~4.4.4", + "eslint-plugin-vue": "^8.0.3", + "typescript": "~4.5.2", "vue-cli-plugin-i18n": "^2.1.1", "webpack-bundle-tracker": "1.4.0", "workbox-expiration": "^6.3.0", diff --git a/vue/src/apps/ShoppingListView/ShoppingListView.vue b/vue/src/apps/ShoppingListView/ShoppingListView.vue index b5aa632c..49368c98 100644 --- a/vue/src/apps/ShoppingListView/ShoppingListView.vue +++ b/vue/src/apps/ShoppingListView/ShoppingListView.vue @@ -436,7 +436,7 @@ delayThis(contextData) " > - + @@ -550,7 +550,7 @@ export default { // filter out list items that are delayed if (!this.show_delay && shopping_list) { - shopping_list = shopping_list.filter((x) => !x.delay_until || !Date.parse(x?.delay_until) > new Date(Date.now())) + shopping_list = shopping_list.filter((x) => !x.delay_until || !Date.parse(x?.delay_until) < new Date(Date.now())) } // if a supermarket is selected and filtered to only supermarket categories filter out everything else @@ -671,6 +671,9 @@ export default { } }, this.settings.shopping_auto_sync * 1000) }, + "settings.default_delay": function (newVal, oldVal) { + this.delay = Number(newVal) + }, }, mounted() { this.getShoppingList() @@ -678,7 +681,8 @@ export default { this.getShoppingCategories() this.settings = getUserPreference() - this.delay = this.settings.default_delay || 4 + this.delay = Number(this.settings.default_delay || 4) + console.log(this.delay) this.supermarket_categories_only = this.settings.filter_to_supermarket if (this.settings.shopping_auto_sync) { window.addEventListener("online", this.updateOnlineStatus) diff --git a/vue/src/components/ShoppingLineItem.vue b/vue/src/components/ShoppingLineItem.vue index 68830d26..5478b521 100644 --- a/vue/src/components/ShoppingLineItem.vue +++ b/vue/src/components/ShoppingLineItem.vue @@ -55,7 +55,8 @@
{{ formatOneCreatedBy(e) }}
-
{{ formatOneCompletedAt(e) }}
+
{{ formatOneCompletedAt(e) }}
+
{{ formatOneDelayUntil(e) }}
@@ -210,7 +211,7 @@ export default { }, formatOneCompletedAt: function (item) { if (!item.completed_at) { - return "" + return false } return [this.$t("Completed"), "@", this.formatDate(item.completed_at)].join(" ") }, @@ -220,6 +221,12 @@ export default { formatOneChecked: function (item) { return item.checked }, + formatOneDelayUntil: function (item) { + if (!item.delay_until && item.checked) { + return false + } + return [this.$t("DelayUntil"), "-", this.formatDate(item.delay_until)].join(" ") + }, formatOneMealPlan: function (item) { return item?.recipe_mealplan?.name }, @@ -233,7 +240,7 @@ export default { return [item?.recipe_mealplan?.mealplan_note, item?.ingredient_note].filter(String) }, formatOneCreatedBy: function (item) { - return [item?.created_by.username, "@", this.formatDate(item.created_at)].join(" ") + return [this.$t("Added_by"), item?.created_by.username, "@", this.formatDate(item.created_at)].join(" ") }, openRecipeCard: function (e, item) { this.genericAPI(this.Models.RECIPE, this.Actions.FETCH, { id: item.recipe_mealplan.recipe }).then((result) => { diff --git a/vue/src/locales/en.json b/vue/src/locales/en.json index a7e1eed4..3c05bf82 100644 --- a/vue/src/locales/en.json +++ b/vue/src/locales/en.json @@ -275,5 +275,6 @@ "csv_prefix_help": "Prefix to add when copying list to the clipboard.", "csv_prefix_label": "List Prefix", "copy_markdown_table": "Copy as Markdown Table", - "in_shopping": "In Shopping List" + "in_shopping": "In Shopping List", + "DelayUntil": "Delay Until" }