improve test coverage and results
This commit is contained in:
parent
ded4a60408
commit
3955461dc0
|
@ -0,0 +1,30 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('potatoe', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='task',
|
||||
name='assignee',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='task',
|
||||
name='creator',
|
||||
field=models.ForeignKey(null=True, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='task',
|
||||
name='priority',
|
||||
field=models.CharField(null=True, max_length=1),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('potatoe', '0002_auto_20150925_1410'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='task',
|
||||
name='completed',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('potatoe', '0003_task_completed'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='task',
|
||||
name='completion_date',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('potatoe', '0004_task_completion_date'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='task',
|
||||
name='deadline',
|
||||
field=models.DateField(null=True),
|
||||
),
|
||||
]
|
|
@ -1,30 +1,101 @@
|
|||
from datetime import date
|
||||
import re
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class Project(models.Model):
|
||||
"""
|
||||
Describes a project (just a `thing` with a name).
|
||||
"""
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Context(models.Model):
|
||||
"""
|
||||
Describes a context (just a `thing` with a name).
|
||||
"""
|
||||
|
||||
name = models.CharField(max_length=255)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Task(models.Model):
|
||||
"""
|
||||
Describes something that has to be done.
|
||||
"""
|
||||
|
||||
description = models.CharField(max_length=2000)
|
||||
projects = models.ManyToManyField('Project')
|
||||
contexts = models.ManyToManyField('Context')
|
||||
priority = models.CharField(max_length=1, null=True)
|
||||
assignee = models.ForeignKey(User)
|
||||
deadline = models.DateField(null=True)
|
||||
creator = models.ForeignKey(User, null=True)
|
||||
completed = models.BooleanField(default=False)
|
||||
completion_date = models.DateTimeField(null=True)
|
||||
|
||||
def getPriority(self):
|
||||
return self.description[1] if len(self.description) and self.description.startswith('(') else None
|
||||
@property
|
||||
def iscomplete(self):
|
||||
"""
|
||||
Checks that the description is completed
|
||||
"""
|
||||
return self.description.startswith('x ')
|
||||
|
||||
@staticmethod
|
||||
def create(description):
|
||||
"""
|
||||
Create a new task based on the description.
|
||||
"""
|
||||
|
||||
t = Task()
|
||||
t.description = description
|
||||
t.priority = t.__buildpriority()
|
||||
t.date = t.__builddate()
|
||||
t.completed = t.iscomplete
|
||||
t.save()
|
||||
|
||||
for project_name in t.buildprojects():
|
||||
p, insert_result = Project.objects.get_or_create(name=project_name)
|
||||
t.projects.add(p)
|
||||
|
||||
for context_name in t.buildcontexts():
|
||||
c, insert_result = Context.objects.get_or_create(name=context_name)
|
||||
t.contexts.add(c)
|
||||
|
||||
return t
|
||||
|
||||
def complete(self, adddate=False):
|
||||
if not self.iscomplete:
|
||||
if adddate:
|
||||
today = date.today().strftime('%Y-%m-%d') + ' '
|
||||
self.description = 'x ' + today + self.description
|
||||
else:
|
||||
self.description = 'x ' + self.description
|
||||
self.completed = True
|
||||
self.save()
|
||||
|
||||
def __builddate(self):
|
||||
"""
|
||||
Fetch the current date in the description.
|
||||
"""
|
||||
return None
|
||||
|
||||
def __buildpriority(self):
|
||||
"""
|
||||
Returns the priority based on the description of the task.
|
||||
"""
|
||||
re_result = re.findall(r'^\([A-Z]\) ', self.description)
|
||||
if re_result:
|
||||
return re_result[0].strip()
|
||||
|
||||
return None
|
||||
|
||||
def __builddate(self):
|
||||
return None
|
||||
|
||||
def __str__(self):
|
||||
return self.description
|
||||
|
@ -41,8 +112,8 @@ class Task(models.Model):
|
|||
"""
|
||||
return [x[1:] for x in re.findall(r'[%s]\w+' % (char,), self.description)]
|
||||
|
||||
def buildProjects(self):
|
||||
def buildprojects(self):
|
||||
return self.__buildvars('+')
|
||||
|
||||
def buildContexts(self):
|
||||
def buildcontexts(self):
|
||||
return self.__buildvars('@')
|
||||
|
|
|
@ -1,37 +1,28 @@
|
|||
from datetime import datetime
|
||||
from datetime import date
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from potatoe.models import Task
|
||||
|
||||
class TaskTestCase(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
def test_build_task_projects(self):
|
||||
""" Fetch projects list from the task description """
|
||||
t = Task()
|
||||
t.description = "(A) Todo rps blablab +RPS +SharePoint"
|
||||
projects = t.buildProjects()
|
||||
|
||||
t = Task.create("(A) Todo rps blablab +RPS +SharePoint")
|
||||
projects = [str(p) for p in t.projects.all()]
|
||||
self.assertIn('RPS', projects)
|
||||
self.assertIn('SharePoint', projects)
|
||||
|
||||
def test_build_task_contexts(self):
|
||||
""" Fetch contexts list from the task description """
|
||||
t = Task()
|
||||
t.description = "(B) Todo bidule @brol @machin +RPS"
|
||||
|
||||
contexts = t.buildContexts()
|
||||
|
||||
t = Task.create("(B) Todo bidule @brol @machin +RPS")
|
||||
contexts = [str(c) for c in t.contexts.all()]
|
||||
self.assertIn('brol', contexts)
|
||||
self.assertIn('machin', contexts)
|
||||
|
||||
def test_contexts_and_projects(self):
|
||||
"""
|
||||
Rule 3: Contexts and Projects may appear anywhere in the line after priority/prepended date.
|
||||
"""
|
||||
pass
|
||||
self.assertNotIn('RPS', contexts)
|
||||
|
||||
def test_priorities(self):
|
||||
"""
|
||||
|
@ -39,16 +30,14 @@ class TaskTestCase(TestCase):
|
|||
|
||||
The priority is an uppercase character from A-Z enclosed in parentheses and followed by a space.
|
||||
"""
|
||||
t = Task()
|
||||
t = Task.create("Really gotta call Mom (A) @phone @someday")
|
||||
self.assertIsNone(t.priority)
|
||||
|
||||
t.description = "Really gotta call Mom (A) @phone @someday"
|
||||
self.assertIsNone(t.getPriority())
|
||||
t = Task.create("(b) Get back to the boss")
|
||||
self.assertIsNone(t.priority)
|
||||
|
||||
t.description = "(b) Get back to the boss"
|
||||
self.assertIsNone(t.getPriority())
|
||||
|
||||
t.description = "(B)->Submit TPS report"
|
||||
self.assertIsNone(t.getPriority())
|
||||
t = Task.create("(B)->Submit TPS report")
|
||||
self.assertIsNone(t.priority)
|
||||
|
||||
def test_dates(self):
|
||||
"""
|
||||
|
@ -57,16 +46,29 @@ class TaskTestCase(TestCase):
|
|||
If there is no priority, the creation date appears first. If the creation date exists, it should be in the format YYYY-MM-DD.
|
||||
"""
|
||||
|
||||
t = Task()
|
||||
|
||||
t.description = "2011-03-02 Document +TodoTxt task format"
|
||||
self.assertEqual(t.getDate(), datetime(2011, 3, 2))
|
||||
t = Task.create("2011-03-02 Document +TodoTxt task format")
|
||||
self.assertEqual(t.deadline, date(2011, 3, 2))
|
||||
|
||||
t.description = "(A) 2011-03-02 Call Mom"
|
||||
self.assertEqual(t.getdate(), datetime(2011, 3, 2))
|
||||
self.assertEqual(t.deadline, date(2011, 3, 2))
|
||||
|
||||
t.description = "(A) Call Mom 2011-03-02"
|
||||
self.assertIsNone(t.getdate(), None)
|
||||
self.assertIsNone(t.deadline, None)
|
||||
|
||||
def test_contexts_and_projects(self):
|
||||
"""
|
||||
Rule 3: Contexts and Projects may appear anywhere in the line after priority/prepended date.
|
||||
"""
|
||||
t = Task.create("(A) Todo rps blablab +RPS +SharePoint")
|
||||
projects = [str(p) for p in t.projects.all()]
|
||||
|
||||
self.assertIn('RPS', projects)
|
||||
self.assertIn('SharePoint', projects)
|
||||
|
||||
t = Task.create("(A) Todo rps blablab @phone @email")
|
||||
contexts = [str(c) for c in t.contexts.all()]
|
||||
self.assertIn('phone', contexts)
|
||||
self.assertIn('email', contexts)
|
||||
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
@ -79,28 +81,25 @@ class TestCompleteTasks(TestCase):
|
|||
pass
|
||||
|
||||
def test_complete_without_date(self):
|
||||
t = Task()
|
||||
|
||||
t.description = "Some task @machin @brol #chose"
|
||||
t = Task.create("Some task @machin @brol +chose")
|
||||
t.complete()
|
||||
|
||||
self.assertTrue(t.iscomplete)
|
||||
self.assertTrue(t.description.startswith('x'))
|
||||
|
||||
|
||||
t.description = "xylophone lesson"
|
||||
self.assertFalse(t.isComplete())
|
||||
t = Task.create("xylophone lesson")
|
||||
self.assertFalse(t.iscomplete)
|
||||
|
||||
t.description = "X 2012-01-01 Make resolutions"
|
||||
self.assertFalse(t.isComplete())
|
||||
self.assertFalse(t.iscomplete)
|
||||
|
||||
t.description = "(A) x Find ticket prices"
|
||||
self.assertFalse(t.isComplete())
|
||||
self.assertFalse(t.iscomplete)
|
||||
|
||||
def test_complete_with_date(self):
|
||||
t = Task()
|
||||
|
||||
t.description = "Some task @machin @brol #chose"
|
||||
t = Task.create("Some task @machin @brol #chose")
|
||||
t.complete(True)
|
||||
|
||||
self.assertTrue(t.description.startswith('x 2015-09-24'))
|
||||
value = 'x ' + date.today().strftime('%Y-%m-%d')
|
||||
beginstr = t.description[0:12]
|
||||
|
||||
self.assertEqual(value, beginstr)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
{% if form.errors %}
|
||||
<p>Your username and password didn't match. Please try again.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if next %}
|
||||
{% if user.is_authenticated %}
|
||||
<p>Your account doesn't have access to this page. To proceed,
|
||||
please login with an account that has access.</p>
|
||||
{% else %}
|
||||
<p>Please login to see this page.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ form.username.label_tag }}</td>
|
||||
<td>{{ form.username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.password.label_tag }}</td>
|
||||
<td>{{ form.password }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<input type="submit" value="login" />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</form>
|
||||
|
||||
{# Assumes you setup the password_reset view in your URLconf #}
|
||||
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
|
Loading…
Reference in New Issue