mirror of https://github.com/snachodog/mybuddy.git
Add missing notes-test (includes tests for tags-feature)
This commit is contained in:
parent
7af66176aa
commit
d0469caed5
|
@ -1,4 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from datetime import datetime
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -602,3 +603,106 @@ class WeightFormsTest(FormsTestCaseBase):
|
||||||
page = self.c.post("/weight/{}/delete/".format(self.weight.id), follow=True)
|
page = self.c.post("/weight/{}/delete/".format(self.weight.id), follow=True)
|
||||||
self.assertEqual(page.status_code, 200)
|
self.assertEqual(page.status_code, 200)
|
||||||
self.assertContains(page, "Weight entry deleted")
|
self.assertContains(page, "Weight entry deleted")
|
||||||
|
|
||||||
|
|
||||||
|
class NotesFormsTest(FormsTestCaseBase):
|
||||||
|
"""
|
||||||
|
Piggy-backs a bunch of tests for the tags-logic.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super(NotesFormsTest, cls).setUpClass()
|
||||||
|
|
||||||
|
cls.note = models.Note.objects.create(
|
||||||
|
child=cls.child,
|
||||||
|
note="Setup note",
|
||||||
|
time=timezone.now() - timezone.timedelta(days=2),
|
||||||
|
)
|
||||||
|
cls.note.tags.add("oldtag")
|
||||||
|
cls.oldtag = models.Tag.objects.filter(slug="oldtag").first()
|
||||||
|
|
||||||
|
def test_add_no_tags(self):
|
||||||
|
params = {
|
||||||
|
"child": self.child.id,
|
||||||
|
"note": "note with no tags",
|
||||||
|
"time": (timezone.now() - timezone.timedelta(minutes=1)).isoformat(),
|
||||||
|
}
|
||||||
|
|
||||||
|
page = self.c.post("/notes/add/", params, follow=True)
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
self.assertContains(page, "note with no tags")
|
||||||
|
|
||||||
|
def test_add_with_tags(self):
|
||||||
|
params = {
|
||||||
|
"child": self.child.id,
|
||||||
|
"note": "this note has tags",
|
||||||
|
"time": (timezone.now() - timezone.timedelta(minutes=1)).isoformat(),
|
||||||
|
"tags": 'A,B,"setup tag"',
|
||||||
|
}
|
||||||
|
|
||||||
|
old_notes = list(models.Note.objects.all())
|
||||||
|
|
||||||
|
page = self.c.post("/notes/add/", params, follow=True)
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
self.assertContains(page, "this note has tags")
|
||||||
|
|
||||||
|
new_notes = list(models.Note.objects.all())
|
||||||
|
|
||||||
|
# Find the new tag and extract its tags
|
||||||
|
old_pks = [n.pk for n in old_notes]
|
||||||
|
new_note = [n for n in new_notes if n.pk not in old_pks][0]
|
||||||
|
new_note_tag_names = [t.name for t in new_note.tags.all()]
|
||||||
|
|
||||||
|
self.assertSetEqual(set(new_note_tag_names), {"A", "B", "setup tag"})
|
||||||
|
|
||||||
|
def test_edit(self):
|
||||||
|
old_tag_last_used = self.oldtag.last_used
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"child": self.note.child.id,
|
||||||
|
"note": "Edited note",
|
||||||
|
"time": self.localdate_string(),
|
||||||
|
"tags": "oldtag,newtag"
|
||||||
|
}
|
||||||
|
page = self.c.post("/notes/{}/".format(self.note.id), params, follow=True)
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
|
||||||
|
self.note.refresh_from_db()
|
||||||
|
self.oldtag.refresh_from_db()
|
||||||
|
self.assertEqual(self.note.note, params["note"])
|
||||||
|
self.assertContains(
|
||||||
|
page, "Note entry for {} updated".format(str(self.note.child))
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertSetEqual(
|
||||||
|
set(t.name for t in self.note.tags.all()),
|
||||||
|
{"oldtag", "newtag"}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Old tag remains old, because it was not added
|
||||||
|
self.assertEqual(old_tag_last_used, self.oldtag.last_used)
|
||||||
|
|
||||||
|
# Second phase: Remove all tags then add "oldtag" through posting
|
||||||
|
# which should update the last_used tag
|
||||||
|
self.note.tags.clear()
|
||||||
|
self.note.save()
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"child": self.note.child.id,
|
||||||
|
"note": "Edited note (2)",
|
||||||
|
"time": self.localdate_string(),
|
||||||
|
"tags": "oldtag"
|
||||||
|
}
|
||||||
|
page = self.c.post("/notes/{}/".format(self.note.id), params, follow=True)
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
|
||||||
|
self.note.refresh_from_db()
|
||||||
|
self.oldtag.refresh_from_db()
|
||||||
|
|
||||||
|
self.assertLess(old_tag_last_used, self.oldtag.last_used)
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
page = self.c.post("/notes/{}/delete/".format(self.note.id), follow=True)
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
self.assertContains(page, "Note entry deleted")
|
||||||
|
|
Binary file not shown.
|
@ -7,22 +7,39 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to compute a high-contrast color from a background color.
|
* Get the contrasting color for any hex color
|
||||||
*
|
*
|
||||||
* (This probably should be researched better because this was
|
* Sourced from: https://vanillajstoolkit.com/helpers/getcontrast/
|
||||||
* hand-crafted ad-hoc.)
|
* - Modified with slightly softer colors
|
||||||
|
* (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com
|
||||||
|
* Derived from work by Brian Suda, https://24ways.org/2010/calculating-color-contrast/
|
||||||
|
* @param {String} A hexcolor value
|
||||||
|
* @return {String} The contrasting color (black or white)
|
||||||
*/
|
*/
|
||||||
function computeComplementaryColor(colorStr) {
|
function computeComplementaryColor(hexcolor) {
|
||||||
let avgColor = 0.0;
|
|
||||||
avgColor += hexParse(colorStr.substring(1, 3)) * -0.5;
|
|
||||||
avgColor += hexParse(colorStr.substring(3, 5)) * 1.5;
|
|
||||||
avgColor += hexParse(colorStr.substring(5, 7)) * 1.0;
|
|
||||||
|
|
||||||
if (avgColor > 200) {
|
// If a leading # is provided, remove it
|
||||||
return "#101010";
|
if (hexcolor.slice(0, 1) === '#') {
|
||||||
} else {
|
hexcolor = hexcolor.slice(1);
|
||||||
return "#E0E0E0";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a three-character hexcode, make six-character
|
||||||
|
if (hexcolor.length === 3) {
|
||||||
|
hexcolor = hexcolor.split('').map(function (hex) {
|
||||||
|
return hex + hex;
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to RGB value
|
||||||
|
let r = parseInt(hexcolor.substr(0,2),16);
|
||||||
|
let g = parseInt(hexcolor.substr(2,2),16);
|
||||||
|
let b = parseInt(hexcolor.substr(4,2),16);
|
||||||
|
|
||||||
|
// Get YIQ ratio
|
||||||
|
let yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||||
|
|
||||||
|
// Check contrast
|
||||||
|
return (yiq >= 128) ? '#101010' : '#EFEFEF';
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSRF token should always be present because it is auto-included with
|
// CSRF token should always be present because it is auto-included with
|
||||||
|
@ -135,7 +152,7 @@
|
||||||
* Handler for the edit field allowing to dynamically create new tags.
|
* Handler for the edit field allowing to dynamically create new tags.
|
||||||
*
|
*
|
||||||
* Handles user inputs for the editor. Calls the 'onInsertNewTag' callback
|
* Handles user inputs for the editor. Calls the 'onInsertNewTag' callback
|
||||||
* when the craetion of a new tag has been requested. All backend handling
|
* when the creation of a new tag has been requested. All backend handling
|
||||||
* like guareteening that the requested tag exists is handled by this class,
|
* like guareteening that the requested tag exists is handled by this class,
|
||||||
* the only task left is to add the new tag to the tags-list when
|
* the only task left is to add the new tag to the tags-list when
|
||||||
* 'onInsertNewTag' is called.
|
* 'onInsertNewTag' is called.
|
Binary file not shown.
|
@ -7,22 +7,39 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to compute a high-contrast color from a background color.
|
* Get the contrasting color for any hex color
|
||||||
*
|
*
|
||||||
* (This probably should be researched better because this was
|
* Sourced from: https://vanillajstoolkit.com/helpers/getcontrast/
|
||||||
* hand-crafted ad-hoc.)
|
* - Modified with slightly softer colors
|
||||||
|
* (c) 2021 Chris Ferdinandi, MIT License, https://gomakethings.com
|
||||||
|
* Derived from work by Brian Suda, https://24ways.org/2010/calculating-color-contrast/
|
||||||
|
* @param {String} A hexcolor value
|
||||||
|
* @return {String} The contrasting color (black or white)
|
||||||
*/
|
*/
|
||||||
function computeComplementaryColor(colorStr) {
|
function computeComplementaryColor(hexcolor) {
|
||||||
let avgColor = 0.0;
|
|
||||||
avgColor += hexParse(colorStr.substring(1, 3)) * -0.5;
|
|
||||||
avgColor += hexParse(colorStr.substring(3, 5)) * 1.5;
|
|
||||||
avgColor += hexParse(colorStr.substring(5, 7)) * 1.0;
|
|
||||||
|
|
||||||
if (avgColor > 200) {
|
// If a leading # is provided, remove it
|
||||||
return "#101010";
|
if (hexcolor.slice(0, 1) === '#') {
|
||||||
} else {
|
hexcolor = hexcolor.slice(1);
|
||||||
return "#E0E0E0";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a three-character hexcode, make six-character
|
||||||
|
if (hexcolor.length === 3) {
|
||||||
|
hexcolor = hexcolor.split('').map(function (hex) {
|
||||||
|
return hex + hex;
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to RGB value
|
||||||
|
let r = parseInt(hexcolor.substr(0,2),16);
|
||||||
|
let g = parseInt(hexcolor.substr(2,2),16);
|
||||||
|
let b = parseInt(hexcolor.substr(4,2),16);
|
||||||
|
|
||||||
|
// Get YIQ ratio
|
||||||
|
let yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||||
|
|
||||||
|
// Check contrast
|
||||||
|
return (yiq >= 128) ? '#101010' : '#EFEFEF';
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSRF token should always be present because it is auto-included with
|
// CSRF token should always be present because it is auto-included with
|
||||||
|
@ -135,7 +152,7 @@
|
||||||
* Handler for the edit field allowing to dynamically create new tags.
|
* Handler for the edit field allowing to dynamically create new tags.
|
||||||
*
|
*
|
||||||
* Handles user inputs for the editor. Calls the 'onInsertNewTag' callback
|
* Handles user inputs for the editor. Calls the 'onInsertNewTag' callback
|
||||||
* when the craetion of a new tag has been requested. All backend handling
|
* when the creation of a new tag has been requested. All backend handling
|
||||||
* like guareteening that the requested tag exists is handled by this class,
|
* like guareteening that the requested tag exists is handled by this class,
|
||||||
* the only task left is to add the new tag to the tags-list when
|
* the only task left is to add the new tag to the tags-list when
|
||||||
* 'onInsertNewTag' is called.
|
* 'onInsertNewTag' is called.
|
||||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue