=============================
Editing address book entities
=============================

User with the `Administrator` role are able to edit the entities in
the address book.

Set up
======

Create an address book and a browser to access it. Log in as
`Administrator`:

>>> from icemac.addressbook.testing import create_addressbook
>>> from z3c.etestbrowser.wsgi import ExtendedTestBrowser as Browser
>>> ab = create_addressbook()
>>> browser = Browser()
>>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
>>> browser.open('http://localhost/++skin++AddressBook/ab')

The entities can be edited in the master data area:

>>> browser.getLink('Master data').click()
>>> browser.getLink('Entities').click()
>>> edit_entities_url = browser.url
>>> edit_entities_url
'http://localhost/++skin++AddressBook/ab/++attribute++entities'


Add a new field
===============

New fields can only be added to existing entities, so the user has to
select an entity first and then choose the `add field` link:

>>> browser.getLink('Edit fields', index=1).click()
>>> edit_entity_url = browser.url
>>> edit_entity_url
'http://localhost/.../ab/++attribute++entities/icemac.addressbook.person.Person'
>>> browser.getLink('field').click()
>>> add_field_url = browser.url
>>> add_field_url
'http://localhost/.../icemac.addressbook.person.Person/@@addField.html'

Selecting the `choice` type requires values:

>>> from icemac.addressbook.testing import get_messages
>>> browser.getControl('type').displayValue = ['choice']
>>> browser.getControl('title').value = 'foobar'
>>> browser.getControl(name='form.buttons.add').click()
>>> get_messages(browser)
[]
>>> browser.url
'http://localhost/.../icemac.addressbook.person.Person/@@addField.html'
>>> print browser.contents
<!DOCTYPE ...
<div class="error">type "choice" requires at least one field value.</div>...


When all invariants are satisfied, the form gets saved:

>>> browser.getControl('type').displayValue = ['text line']
>>> browser.getControl('title').value = 'baz'
>>> browser.getControl('notes').value = 'the\nbaz\nfield'
>>> browser.getControl(name='form.buttons.add').click()
>>> browser.url
'http://localhost/.../ab/++attribute++entities/icemac.addressbook.person.Person'
>>> print browser.contents
<!DOCTYPE ...
      <tr id="Field-1" class="table-odd-row">
        <td>baz</td>
        <td><a href="http://localhost/++skin++AddressBook/ab/++attribute++entities/icemac.addressbook.person.Person/Field-1/@@delete.html">Delete</a></td>
        <td><a href="http://localhost/++skin++AddressBook/ab/++attribute++entities/icemac.addressbook.person.Person/Field-1">Edit</a></td>
      </tr>
  ...


Edit a field
============

When editing the added field the previously entered values are displayed:

>>> browser.getLink('Edit', index=1).click()
>>> edit_field_url = browser.url
>>> edit_field_url
'http://localhost/...++entities/icemac.addressbook.person.Person/Field-1'
>>> browser.getControl('type').displayValue
['text line']
>>> browser.getControl('title').value
'baz'
>>> print browser.getControl('notes').value
the
baz
field
>>> browser.getControl('title').value = 'foobar'
>>> browser.getControl('Apply').click()
>>> get_messages(browser)
['Data successfully updated.']
>>> browser.url
'http://localhost/...ab/++attribute++entities/icemac.addressbook.person.Person'


Use a field
===========

The previously defined field now shows up when editing the entity it
is assigned to:

Add form
--------

The field shows up on the add form as a text line:

>>> browser.getLink('Person list').click()
>>> browser.url
'http://localhost/++skin++AddressBook/ab/@@index.html'
>>> browser.getLink('person').click()
>>> browser.getControl('last name').value = 'Tester'
>>> browser.getControl('foobar').value
''
>>> browser.getControl('foobar').value = 'monster'
>>> browser.getControl('Add').click()
>>> get_messages(browser)
['"Tester" added.']
>>> browser.url
'http://localhost/++skin++AddressBook/ab'

Edit form
---------

The field also shows up on the edit form and contains the value
assigned in the add form:

>>> browser.getLink('Tester').click()
>>> browser.url
'http://localhost/++skin++AddressBook/ab/Person'
>>> browser.getControl('foobar').value
'monster'
>>> browser.getControl('foobar').value = 'my value'
>>> browser.getControl('Apply').click()
>>> get_messages(browser)
['Data successfully updated.']
>>> browser.url
'http://localhost/++skin++AddressBook/ab'
>>> browser.getLink('Tester').click()
>>> browser.getControl('foobar').value
'my value'
>>> browser.getControl('Cancel').click()
>>> get_messages(browser)
['No changes were applied.']


Editor
======

Users with the role `editor` are not allowed to edit user defined
fields, but they are allowed to use them.

Edit fields
-----------

Users with the `editor` role are not able to edit fields even when
they know the URL.

>>> editor = Browser()
>>> editor.addHeader('Authorization', 'Basic editor:editor')
>>> editor.open('http://localhost/++skin++AddressBook/ab')

There is no edit link at master data:

>>> editor.getLink('Master data').click()
>>> editor.getLink('Entities')
Traceback (most recent call last):
LinkNotFoundError

The URL to edit the entities is not accessable:

>>> editor.open(edit_entities_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

The URL to edit an entity is not accessable:

>>> editor.open(edit_entity_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

The URL to add a field is not accessable:

>>> editor.open(add_field_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

The URL to edit a field is not accessable:

>>> editor.open(edit_field_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

Use user defined fields
-----------------------

The editor is allowed to use previously defined fields both in the add
form and in the edit form.

Edit form of admin created content
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The editor is able to edit content which has user defined fields and
was created by an administrator:

>>> editor.open('http://localhost/++skin++AddressBook/ab')
>>> editor.getLink('Person list').click()
>>> editor.getLink('Tester').click()
>>> editor.url
'http://localhost/++skin++AddressBook/ab/Person'
>>> editor.getControl('foobar').value
'my value'
>>> editor.getControl('foobar').value = 'editor was here'
>>> editor.getControl('Apply').click()
>>> get_messages(editor)
['Data successfully updated.']
>>> editor.url
'http://localhost/++skin++AddressBook/ab'

The entered values get persisted:

>>> editor.getLink('Tester').click()
>>> editor.url
'http://localhost/++skin++AddressBook/ab/Person'
>>> editor.getControl('foobar').value
'editor was here'
>>> editor.getControl('Cancel').click()
>>> get_messages(editor)
['No changes were applied.']
>>> editor.url
'http://localhost/++skin++AddressBook/ab'

Add form
~~~~~~~~

The editor can enter values in user defined fields in the add form:

>>> editor.getLink('person').click()
>>> editor.url
'http://localhost/++skin++AddressBook/ab/@@addPerson.html'
>>> editor.getControl('last name').value = 'Bester'
>>> editor.getControl('foobar').value
''
>>> editor.getControl('foobar').value = 'better'
>>> editor.getControl('Add').click()
>>> get_messages(editor)
['"Bester" added.']
>>> editor.url
'http://localhost/++skin++AddressBook/ab'

Edit form
---------

The editor is also able to edit the values he entered himself:

>>> editor.getLink('Bester').click()
>>> editor.url
'http://localhost/++skin++AddressBook/ab/Person-2'
>>> editor.getControl('foobar').value
'better'
>>> editor.getControl('foobar').value = 'still better'
>>> editor.getControl('Apply').click()
>>> get_messages(editor)
['Data successfully updated.']
>>> editor.url
'http://localhost/++skin++AddressBook/ab'
>>> editor.getLink('Bester').click()
>>> editor.getControl('foobar').value
'still better'
>>> editor.getControl('Cancel').click()
>>> get_messages(editor)
['No changes were applied.']


Visitor
=======

Users with the role `visitor` are not allowed to edit user defined
fields. They are only able to see the field contents a higher privilaged user has entered.

Edit fields
-----------

Users with the `visitor` role are not able to edit fields even when
they know the URL.

>>> visitor = Browser()
>>> visitor.addHeader('Authorization', 'Basic visitor:visitor')
>>> visitor.open('http://localhost/++skin++AddressBook/ab')

There is no edit link at master data:

>>> visitor.getLink('Master data').click()
>>> visitor.getLink('Entities')
Traceback (most recent call last):
LinkNotFoundError

The URL to edit the entities is not accessable:

>>> visitor.open(edit_entities_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

The URL to edit an entity is not accessable:

>>> visitor.open(edit_entity_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

The URL to add a field is not accessable:

>>> visitor.open(add_field_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

The URL to edit a field is not accessable:

>>> visitor.open(edit_field_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden

Use user defined fields
-----------------------

The visitor can only see field contents of predefinded and user defined fields:

>>> from icemac.addressbook.testing import get_all_control_names
>>> visitor.open('http://localhost/++skin++AddressBook/ab')
>>> visitor.getLink('Person list').click()
>>> visitor.getLink('Tester').click()
>>> visitor.url
'http://localhost/++skin++AddressBook/ab/Person'
>>> get_all_control_names(visitor)
['form.buttons.apply', 'form.buttons.cancel']


Delete a user defined field
===========================

Only an administrator can delete a user defined field. This field is
then no longer used in the forms.

>>> browser.getLink('Master data').click()
>>> browser.getLink('Entities').click()
>>> browser.getLink('Edit fields', index=1).click()
>>> browser.url
'http://localhost/.../ab/++attribute++entities/icemac.addressbook.person.Person'
>>> 'foobar' in browser.contents
True
>>> browser.getLink('Delete').click()
>>> delete_field_url = browser.url
>>> delete_field_url
'http://...entities/icemac.addressbook.person.Person/Field-1/@@delete.html'

After choosing to delete a field the user is asked whether he is sure
about the deletion. When choosing cancel the field does not get deleted:

>>> browser.getControl('No, cancel').click()
>>> get_messages(browser)
['Deletion canceled.']
>>> browser.url
'http://localhost/...ab/++attribute++entities/icemac.addressbook.person.Person'

Neither editors nor visitors are able to delete a field even when they
know the url:

>>> editor.open(delete_field_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden
>>> visitor.open(delete_field_url)
Traceback (most recent call last):
HTTPError: HTTP Error 403: Forbidden


When the administrator is sure to delete the field, the field gets deleted:

>>> browser.getLink('Delete').click()
>>> browser.getControl('Yes, delete').click()
>>> get_messages(browser)
['"foobar" deleted.']
>>> browser.url
'http://localhost/...ab/++attribute++entities/icemac.addressbook.person.Person'
>>> browser.open(browser.url)
>>> 'foobar' in browser.contents
False


Field no longer displayed
-------------------------

The field is no longer displayed in the add form and in the edit form:

>>> browser.getLink('Person list').click()
>>> browser.getLink('Tester').click()
>>> browser.getControl('foobar')
Traceback (most recent call last):
LookupError: label 'foobar'
>>> browser.getControl('Cancel').click()
>>> get_messages(browser)
['No changes were applied.']


>>> browser.getLink('person').click()
>>> browser.getControl('foobar')
Traceback (most recent call last):
LookupError: label 'foobar'

The field is not displayed for editors, too:

>>> editor.open('http://localhost/++skin++AddressBook/ab')
>>> editor.getLink('Person list').click()
>>> editor.getLink('Tester').click()
>>> editor.getControl('foobar')
Traceback (most recent call last):
LookupError: label 'foobar'
>>> editor.getControl('Cancel').click()
>>> get_messages(editor)
['No changes were applied.']

>>> editor.getLink('person').click()
>>> editor.getControl('foobar')
Traceback (most recent call last):
LookupError: label 'foobar'

The field is not displayed for visitors, too:

>>> visitor.open('http://localhost/++skin++AddressBook/ab')
>>> visitor.getLink('Person list').click()
>>> visitor.getLink('Tester').click()
>>> 'foobar' in visitor.contents
False

Create new field
----------------

When the administrator creates a new field it gets a unique id, the id
of the previously deleted field is not reused:

>>> browser.getLink('Master data').click()
>>> browser.getLink('Entities').click()
>>> browser.getLink('Edit fields', index=1).click()
>>> browser.getLink('field').click()
>>> browser.getControl('type').displayValue = ['bool']
>>> browser.getControl('title').value = 'really?'
>>> browser.getControl(name='form.buttons.add').click()
>>> get_messages(browser)
['"really?" added.']
>>> browser.url
'http://localhost/...ab/++attribute++entities/icemac.addressbook.person.Person'
>>> browser.getLink('Edit', index=1).url
'http://localhost/...++entities/icemac.addressbook.person.Person/Field-2'
>>> browser.getLink('Edit', index=1).url == edit_field_url
False