Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Debian New Member Process
nm.debian.org
Commits
9a5de9cd
Commit
9a5de9cd
authored
Jun 02, 2016
by
Enrico Zini
Browse files
Initial test for process_show
parent
4e579e95
Changes
8
Hide whitespace changes
Inline
Side-by-side
backend/unittest.py
View file @
9a5de9cd
...
@@ -180,6 +180,28 @@ class TestBase(object):
...
@@ -180,6 +180,28 @@ class TestBase(object):
if
match
.
search
(
errmsg
):
return
if
match
.
search
(
errmsg
):
return
self
.
fail
(
"{} dit not match any in {}"
.
format
(
regex
,
repr
(
errors
)))
self
.
fail
(
"{} dit not match any in {}"
.
format
(
regex
,
repr
(
errors
)))
def
assertContainsElements
(
self
,
response
,
elements
,
*
names
):
"""
Check that the response contains only the elements in `names` from PageElements `elements`
"""
want
=
set
(
names
)
extras
=
want
-
set
(
elements
.
keys
())
if
extras
:
raise
RuntimeError
(
"Wanted elements not found in the list of possible ones: {}"
.
format
(
", "
.
join
(
extras
)))
should_have
=
[]
should_not_have
=
[]
content
=
response
.
content
.
decode
(
"utf-8"
)
for
name
,
regex
in
elements
.
items
():
if
name
in
want
:
if
not
regex
.
search
(
content
):
should_have
.
append
(
name
)
else
:
if
regex
.
search
(
content
):
should_not_have
.
append
(
name
)
if
should_have
or
should_not_have
:
msg
=
[]
if
should_have
:
msg
.
append
(
"should have element(s) {}"
.
format
(
", "
.
join
(
should_have
)))
if
should_not_have
:
msg
.
append
(
"should not have element(s) {}"
.
format
(
", "
.
join
(
should_not_have
)))
self
.
fail
(
"page "
+
" and "
.
join
(
msg
))
class
BaseFixtureMixin
(
TestBase
):
class
BaseFixtureMixin
(
TestBase
):
@
classmethod
@
classmethod
...
...
process/models.py
View file @
9a5de9cd
...
@@ -105,42 +105,40 @@ class RequirementVisitorPermissions(ProcessVisitorPermissions):
...
@@ -105,42 +105,40 @@ class RequirementVisitorPermissions(ProcessVisitorPermissions):
class
ProcessManager
(
models
.
Manager
):
class
ProcessManager
(
models
.
Manager
):
def
compute_requirements
(
self
,
person
,
applying_for
):
def
compute_requirements
(
self
,
status
,
applying_for
):
"""
"""
Compute the process requirements for person applying for applying_for
Compute the process requirements for person applying for applying_for
"""
"""
if
person
.
status
==
applying_for
:
if
status
==
applying_for
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
person
.
status
))
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
status
))
if
person
.
pending
:
if
status
==
const
.
STATUS_DD_U
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person whose account is still pending"
.
format
(
applying_for
))
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
status
))
if
person
.
status
==
const
.
STATUS_DD_U
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
person
.
status
))
requirements
=
[
"intent"
,
"sc_dmup"
]
requirements
=
[
"intent"
,
"sc_dmup"
]
if
applying_for
==
const
.
STATUS_DC_GA
:
if
applying_for
==
const
.
STATUS_DC_GA
:
if
person
.
status
!=
const
.
STATUS_DC
:
if
status
!=
const
.
STATUS_DC
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
person
.
status
))
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
status
))
requirements
.
append
(
"advocate"
)
requirements
.
append
(
"advocate"
)
elif
applying_for
==
const
.
STATUS_DM
:
elif
applying_for
==
const
.
STATUS_DM
:
if
person
.
status
!=
const
.
STATUS_DC
:
if
status
!=
const
.
STATUS_DC
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
person
.
status
))
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
status
))
requirements
.
append
(
"advocate"
)
requirements
.
append
(
"advocate"
)
requirements
.
append
(
"keycheck"
)
requirements
.
append
(
"keycheck"
)
elif
applying_for
==
const
.
STATUS_DM_GA
:
elif
applying_for
==
const
.
STATUS_DM_GA
:
if
person
.
status
==
const
.
STATUS_DC_GA
:
if
status
==
const
.
STATUS_DC_GA
:
requirements
.
append
(
"advocate"
)
requirements
.
append
(
"advocate"
)
requirements
.
append
(
"keycheck"
)
requirements
.
append
(
"keycheck"
)
elif
person
.
status
==
const
.
STATUS_DM
:
elif
status
==
const
.
STATUS_DM
:
# No extra requirement: the declaration of intents is
# No extra requirement: the declaration of intents is
# sufficient
# sufficient
pass
pass
else
:
else
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
person
.
status
))
raise
RuntimeError
(
"Invalid applying_for value {} for a person with status {}"
.
format
(
applying_for
,
status
))
elif
applying_for
in
(
const
.
STATUS_DD_U
,
const
.
STATUS_DD_NU
):
elif
applying_for
in
(
const
.
STATUS_DD_U
,
const
.
STATUS_DD_NU
):
if
person
.
status
!=
const
.
STATUS_DD_NU
:
if
status
!=
const
.
STATUS_DD_NU
:
requirements
.
append
(
"keycheck"
)
requirements
.
append
(
"keycheck"
)
requirements
.
append
(
"am_ok"
)
requirements
.
append
(
"am_ok"
)
if
person
.
status
not
in
(
const
.
STATUS_EMERITUS_DD
,
const
.
STATUS_REMOVED_DD
):
if
status
not
in
(
const
.
STATUS_EMERITUS_DD
,
const
.
STATUS_REMOVED_DD
):
requirements
.
append
(
"advocate"
)
requirements
.
append
(
"advocate"
)
else
:
else
:
raise
RuntimeError
(
"Invalid applying_for value {}"
.
format
(
applying_for
))
raise
RuntimeError
(
"Invalid applying_for value {}"
.
format
(
applying_for
))
...
@@ -152,12 +150,16 @@ class ProcessManager(models.Manager):
...
@@ -152,12 +150,16 @@ class ProcessManager(models.Manager):
"""
"""
Create a new process and all its requirements
Create a new process and all its requirements
"""
"""
# Forbid pending persons to start processes
if
person
.
pending
:
raise
RuntimeError
(
"Invalid applying_for value {} for a person whose account is still pending"
.
format
(
applying_for
))
# Check that no active process of the same kind exists
# Check that no active process of the same kind exists
if
self
.
filter
(
person
=
person
,
applying_for
=
applying_for
,
closed__isnull
=
True
).
exists
():
if
self
.
filter
(
person
=
person
,
applying_for
=
applying_for
,
closed__isnull
=
True
).
exists
():
raise
RuntimeError
(
"there is already an active process for {} to become {}"
.
format
(
person
,
applying_for
))
raise
RuntimeError
(
"there is already an active process for {} to become {}"
.
format
(
person
,
applying_for
))
# Compute requirements
# Compute requirements
requirements
=
self
.
compute_requirements
(
person
,
applying_for
)
requirements
=
self
.
compute_requirements
(
person
.
status
,
applying_for
)
# Create the new process
# Create the new process
res
=
self
.
model
(
person
=
person
,
applying_for
=
applying_for
)
res
=
self
.
model
(
person
=
person
,
applying_for
=
applying_for
)
...
@@ -231,13 +233,15 @@ class Process(models.Model):
...
@@ -231,13 +233,15 @@ class Process(models.Model):
for
s
in
adv
.
statements
.
all
():
for
s
in
adv
.
statements
.
all
():
advocates
.
add
(
s
.
uploaded_by
)
advocates
.
add
(
s
.
uploaded_by
)
log
=
self
.
log
.
order_by
(
"logdate"
)
return
{
return
{
"requirements"
:
requirements
,
"requirements"
:
requirements
,
"requirements_sorted"
:
sorted
(
requirements
.
values
(),
key
=
lambda
x
:
REQUIREMENT_TYPES_DICT
[
x
.
type
].
sort_order
),
"requirements_sorted"
:
sorted
(
requirements
.
values
(),
key
=
lambda
x
:
REQUIREMENT_TYPES_DICT
[
x
.
type
].
sort_order
),
"requirements_ok"
:
sorted
(
rok
,
key
=
lambda
x
:
REQUIREMENT_TYPES_DICT
[
x
.
type
].
sort_order
),
"requirements_ok"
:
sorted
(
rok
,
key
=
lambda
x
:
REQUIREMENT_TYPES_DICT
[
x
.
type
].
sort_order
),
"requirements_missing"
:
sorted
(
rnok
,
key
=
lambda
x
:
REQUIREMENT_TYPES_DICT
[
x
.
type
].
sort_order
),
"requirements_missing"
:
sorted
(
rnok
,
key
=
lambda
x
:
REQUIREMENT_TYPES_DICT
[
x
.
type
].
sort_order
),
"log_first"
:
self
.
log
.
order_by
(
"logdate"
)[
0
]
,
"log_first"
:
log
[
0
]
if
log
else
None
,
"log_last"
:
self
.
log
.
order_by
(
"-logdate"
)[
0
]
,
"log_last"
:
log
[
-
1
]
if
log
else
None
,
"advocates"
:
sorted
(
advocates
),
"advocates"
:
sorted
(
advocates
),
}
}
...
...
process/templates/process/log_widget.html
View file @
9a5de9cd
...
@@ -10,27 +10,27 @@
...
@@ -10,27 +10,27 @@
<br/>
<br/>
<textarea
name=
"logtext"
rows=
"3"
cols=
"80"
placeholder=
"vacation notice / remark about the process / status update / ..."
></textarea>
<textarea
name=
"logtext"
rows=
"3"
cols=
"80"
placeholder=
"vacation notice / remark about the process / status update / ..."
></textarea>
<br/>
<br/>
<button
type=
"submit"
name=
"add_action"
value=
"log_public"
>
Comment
</button>
<button
id=
"log_public"
type=
"submit"
name=
"add_action"
value=
"log_public"
>
Comment
</button>
<button
type=
"submit"
name=
"add_action"
value=
"log_private"
>
Comment (confidential)
</button>
<button
id=
"log_private"
type=
"submit"
name=
"add_action"
value=
"log_private"
>
Comment (confidential)
</button>
{% if requirement %}
{% if requirement %}
{% if requirement.approved_by %}
{% if requirement.approved_by %}
<button
type=
"submit"
name=
"add_action"
value=
"req_unapprove"
>
Unapprove
</button>
<button
id=
"req_unapprove"
type=
"submit"
name=
"add_action"
value=
"req_unapprove"
>
Unapprove
</button>
{% else %}
{% else %}
<button
type=
"submit"
name=
"add_action"
value=
"req_approve"
>
Approve
</button>
<button
id=
"req_approve"
type=
"submit"
name=
"add_action"
value=
"req_approve"
>
Approve
</button>
{% endif %}
{% endif %}
{% else %}
{% else %}
{% if not process.frozen_by %}
{% if not process.frozen_by %}
{% if not process.approved_by %}
{% if not process.approved_by %}
<button
type=
"submit"
name=
"add_action"
value=
"proc_freeze"
>
Freeze for review
</button>
<button
id=
"proc_freeze"
type=
"submit"
name=
"add_action"
value=
"proc_freeze"
>
Freeze for review
</button>
{% else %}
{% else %}
{# no button to show here: this case should not happen and should get a warning by nightly maintenance #}
{# no button to show here: this case should not happen and should get a warning by nightly maintenance #}
{% endif %}
{% endif %}
{% else %}
{% else %}
{% if not process.approved_by %}
{% if not process.approved_by %}
<button
type=
"submit"
name=
"add_action"
value=
"proc_unfreeze"
>
Unfreeze for further work
</button>
<button
id=
"proc_unfreeze"
type=
"submit"
name=
"add_action"
value=
"proc_unfreeze"
>
Unfreeze for further work
</button>
<button
type=
"submit"
name=
"add_action"
value=
"proc_approve"
>
Approve process
</button>
<button
id=
"proc_approve"
type=
"submit"
name=
"add_action"
value=
"proc_approve"
>
Approve process
</button>
{% else %}
{% else %}
<button
type=
"submit"
name=
"add_action"
value=
"proc_unapprove"
>
Unapprove process
</button>
<button
id=
"proc_unapprove"
type=
"submit"
name=
"add_action"
value=
"proc_unapprove"
>
Unapprove process
</button>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
...
...
process/templates/process/show.html
View file @
9a5de9cd
...
@@ -103,11 +103,11 @@
...
@@ -103,11 +103,11 @@
</tr>
</tr>
{% if visitor.is_admin and process.fd_comment %}
{% if visitor.is_admin and process.fd_comment %}
<tr><th>
FD comments
</th><td>
{{process.fd_comment}}
</td></tr>
<tr
id=
"view_fd_comment"
><th>
FD comments
</th><td>
{{process.fd_comment}}
</td></tr>
{% endif %}
{% endif %}
{% if "view_mbox" in visit_perms %}
{% if "view_mbox" in visit_perms %}
<tr>
<tr
id=
"view_mbox"
>
<th>
Mail archive
</th>
<th>
Mail archive
</th>
<td>
<td>
<tt><a
href=
"mailto:{{process.archive_email}}"
>
{{process.archive_email}}
</a></tt>
<tt><a
href=
"mailto:{{process.archive_email}}"
>
{{process.archive_email}}
</a></tt>
...
...
process/tests/common.py
View file @
9a5de9cd
...
@@ -61,7 +61,7 @@ def get_all_process_types():
...
@@ -61,7 +61,7 @@ def get_all_process_types():
Generate all valid (source_status, applying_for) pairs for all possible
Generate all valid (source_status, applying_for) pairs for all possible
processes.
processes.
"""
"""
for
src
,
tgts
in
bmodels
.
P
rocess
.
_new_status_table
:
for
src
,
tgts
in
bmodels
.
P
erson
.
_new_status_table
.
items
()
:
for
tgt
in
tgts
:
for
tgt
in
tgts
:
yield
src
,
tgt
yield
src
,
tgt
...
...
process/tests/test_backend.py
View file @
9a5de9cd
...
@@ -10,21 +10,17 @@ from process import models as pmodels
...
@@ -10,21 +10,17 @@ from process import models as pmodels
from
backend.unittest
import
BaseFixtureMixin
,
PersonFixtureMixin
from
backend.unittest
import
BaseFixtureMixin
,
PersonFixtureMixin
class
TestRequirements
(
PersonFixtureMixin
,
TestCase
):
class
TestRequirements
(
PersonFixtureMixin
,
TestCase
):
def
assertRequirements
(
self
,
person
,
applying_for
,
expected
):
def
assertRequirements
(
self
,
status
,
applying_for
,
expected
):
computed
=
pmodels
.
Process
.
objects
.
compute_requirements
(
s
elf
.
persons
[
person
]
,
applying_for
)
computed
=
pmodels
.
Process
.
objects
.
compute_requirements
(
s
tatus
,
applying_for
)
self
.
assertItemsEqual
(
computed
,
expected
)
self
.
assertItemsEqual
(
computed
,
expected
)
def
assertInvalid
(
self
,
person
,
applying_for
):
def
assertInvalid
(
self
,
status
,
applying_for
):
with
self
.
assertRaises
(
RuntimeError
)
as
re
:
with
self
.
assertRaises
(
RuntimeError
)
as
re
:
pmodels
.
Process
.
objects
.
compute_requirements
(
s
elf
.
persons
[
person
]
,
applying_for
)
pmodels
.
Process
.
objects
.
compute_requirements
(
s
tatus
,
applying_for
)
def
test_requirements
(
self
):
def
test_requirements
(
self
):
all_statuses
=
{
s
.
tag
for
s
in
const
.
ALL_STATUS
}
all_statuses
=
{
s
.
tag
for
s
in
const
.
ALL_STATUS
}
# Pending users cannot apply for anything yet
for
dest
in
all_statuses
:
self
.
assertInvalid
(
"pending"
,
dest
)
for
dest
in
all_statuses
-
{
const
.
STATUS_DC_GA
,
const
.
STATUS_DM
,
const
.
STATUS_DD_NU
,
const
.
STATUS_DD_U
}:
for
dest
in
all_statuses
-
{
const
.
STATUS_DC_GA
,
const
.
STATUS_DM
,
const
.
STATUS_DD_NU
,
const
.
STATUS_DD_U
}:
self
.
assertInvalid
(
"dc"
,
dest
)
self
.
assertInvalid
(
"dc"
,
dest
)
self
.
assertRequirements
(
"dc"
,
const
.
STATUS_DC_GA
,
[
"intent"
,
"sc_dmup"
,
"advocate"
])
self
.
assertRequirements
(
"dc"
,
const
.
STATUS_DC_GA
,
[
"intent"
,
"sc_dmup"
,
"advocate"
])
...
...
process/tests/test_perms.py
View file @
9a5de9cd
...
@@ -8,7 +8,7 @@ from django.core.urlresolvers import reverse
...
@@ -8,7 +8,7 @@ from django.core.urlresolvers import reverse
from
django.utils.timezone
import
now
from
django.utils.timezone
import
now
from
backend
import
const
from
backend
import
const
from
backend
import
models
as
bmodels
from
backend
import
models
as
bmodels
from
backend.unittest
import
BaseFixtureMixin
,
PersonFixtureMixin
,
ExpectedSets
,
NamedObjects
,
TestSet
from
backend.unittest
import
PersonFixtureMixin
,
ExpectedSets
,
TestSet
import
process.models
as
pmodels
import
process.models
as
pmodels
from
.common
import
ProcessFixtureMixin
from
.common
import
ProcessFixtureMixin
...
...
process/tests/test_process_show.py
0 → 100644
View file @
9a5de9cd
# coding: utf8
from
__future__
import
print_function
from
__future__
import
absolute_import
from
__future__
import
division
from
__future__
import
unicode_literals
from
django.test
import
TestCase
from
django.core.urlresolvers
import
reverse
from
django.utils.timezone
import
now
from
backend
import
const
from
backend
import
models
as
bmodels
from
backend.unittest
import
PersonFixtureMixin
,
ExpectedSets
,
TestSet
,
PageElements
import
process.models
as
pmodels
from
.common
import
ProcessFixtureMixin
,
get_all_process_types
class
TestProcessShow
(
ProcessFixtureMixin
,
TestCase
):
@
classmethod
def
__add_extra_tests__
(
cls
):
for
src
,
tgt
in
get_all_process_types
():
want_am
=
"am_ok"
in
pmodels
.
Process
.
objects
.
compute_requirements
(
src
,
tgt
)
visitors
=
[
None
,
"pending"
,
"dc"
,
"dc_ga"
,
"dm"
,
"dm_ga"
,
"dd_nu"
,
"dd_u"
,
"dd_e"
,
"dd_r"
,
"activeam"
,
"fd"
,
"dam"
,
"app"
]
if
want_am
:
visitors
.
append
(
"am"
)
for
visitor
in
visitors
:
if
want_am
:
cls
.
_add_method
(
cls
.
_test_perms
,
src
,
tgt
,
visitor
,
am
=
"dd_nu"
)
cls
.
_add_method
(
cls
.
_test_perms
,
src
,
tgt
,
visitor
,
am
=
"dd_u"
)
else
:
cls
.
_add_method
(
cls
.
_test_perms
,
src
,
tgt
,
visitor
)
@
classmethod
def
setUpClass
(
cls
):
super
(
TestProcessShow
,
cls
).
setUpClass
()
cls
.
page_elements
=
PageElements
()
cls
.
page_elements
.
add_id
(
"view_fd_comment"
)
cls
.
page_elements
.
add_id
(
"view_mbox"
)
cls
.
page_elements
.
add_id
(
"log_public"
)
cls
.
page_elements
.
add_id
(
"log_private"
)
cls
.
page_elements
.
add_id
(
"proc_freeze"
)
cls
.
page_elements
.
add_id
(
"proc_unfreeze"
)
cls
.
page_elements
.
add_id
(
"proc_approve"
)
cls
.
page_elements
.
add_id
(
"proc_unapprove"
)
def
assertPageElements
(
self
,
response
,
visit_perms
):
# Check page elements based on visit_perms
wanted
=
[]
if
visit_perms
.
visitor
.
is_admin
:
wanted
.
append
(
"view_fd_comment"
)
if
"add_log"
in
visit_perms
:
wanted
+=
[
"log_public"
,
"log_private"
]
for
el
in
(
"view_mbox"
,
"proc_freeze"
,
"proc_unfreeze"
,
"proc_approve"
,
"proc_unapprove"
):
if
el
in
visit_perms
:
wanted
.
append
(
el
)
self
.
assertContainsElements
(
response
,
self
.
page_elements
,
*
wanted
)
def
_test_perms
(
self
,
src
,
tgt
,
visitor
,
am
=
None
):
self
.
persons
.
create
(
"app"
,
status
=
src
)
self
.
processes
.
create
(
"app"
,
person
=
self
.
persons
.
app
,
applying_for
=
tgt
)
if
am
is
not
None
:
self
.
persons
.
create
(
"am"
,
status
=
am
)
self
.
ams
.
create
(
"am"
,
person
=
self
.
persons
.
am
)
client
=
self
.
make_test_client
(
visitor
)
response
=
client
.
get
(
reverse
(
"process_show"
,
args
=
[
self
.
processes
.
app
.
pk
]))
self
.
assertEqual
(
response
.
status_code
,
200
)
visit_perms
=
self
.
processes
.
app
.
permissions_of
(
self
.
persons
[
visitor
])
self
.
assertPageElements
(
response
,
visit_perms
)
# Assign am and repeat visit
if
am
:
pmodels
.
AMAssignment
.
objects
.
create
(
process
=
self
.
processes
.
app
,
am
=
self
.
ams
.
am
,
assigned_by
=
self
.
persons
[
"fd"
],
assigned_time
=
now
())
response
=
client
.
get
(
reverse
(
"process_show"
,
args
=
[
self
.
processes
.
app
.
pk
]))
self
.
assertEqual
(
response
.
status_code
,
200
)
visit_perms
=
self
.
processes
.
app
.
permissions_of
(
self
.
persons
[
visitor
])
self
.
assertPageElements
(
response
,
visit_perms
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment