Kotti browser tests
===================

Setup
-----

   >>> from kotti import tests
   >>> from kotti.resources import Node, Document, DBSession

   >>> tools = tests.setUpFunctional()
   >>> browser = tools['Browser']()
   >>> ctrl = browser.getControl
   >>> browser.open(tests.BASE_URL)
   >>> session = DBSession()
   >>> root = session.query(Node).get(1)

Login
-----

Editing is locked down to authenticated users:

  >>> browser.open(tests.BASE_URL + '/edit')
  >>> "Log in" in browser.contents
  True
  >>> ctrl("Username or email").value = "admin"
  >>> ctrl("Password").value = "secret"
  >>> ctrl(name="submitted").click()
  >>> "Welcome, Administrator" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/edit'
  True

Logging out redirects us to the URL we came from and presents us with
the login form:

  >>> browser.getLink("Logout").click()
  >>> "You have been logged out" in browser.contents
  True

Log in again, this time force an error:

  >>> ctrl("Username or email").value = "admin"
  >>> ctrl("Password").value = "funny"
  >>> ctrl(name="submitted").click()
  >>> "Welcome, Adminstrator" in browser.contents
  False
  >>> "Login failed" in browser.contents
  True
  >>> ctrl("Username or email").value = "admin"
  >>> ctrl("Password").value = "secret"
  >>> ctrl(name="submitted").click()
  >>> "Welcome, Administrator" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/edit'
  True

Add a document
--------------

  >>> browser.open(tests.BASE_URL)
  >>> browser.getLink("Edit").click()
  >>> browser.getLink("Add").click()
  >>> ctrl("Title").value = "Child One"
  >>> ctrl("save").click()
  >>> "Successfully added item" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/child-one/edit'
  True

Edit the document
-----------------

  >>> browser.getLink("Edit").click()
  >>> ctrl("Title").value = "First Child"
  >>> ctrl("save").click()
  >>> "Your changes have been saved" in browser.contents
  True
  >>> ctrl("Title").value
  'First Child'
  >>> browser.getLink("View").click()
  >>> "First Child" in browser.contents
  True

And now force a validation error:

  >>> browser.getLink("Edit").click()
  >>> ctrl("Title").value = ""
  >>> ctrl("save").click()
  >>> "There was a problem" in browser.contents
  True
  >>> ctrl("Title").value
  ''
  >>> browser.getLink("View").click()
  >>> "First Child" in browser.contents
  True

Add two more documents, at different levels
-------------------------------------------

  >>> browser.getLink("Edit").click()
  >>> browser.getLink("Add").click()
  >>> ctrl("Add to My Site").selected = True
  >>> ctrl("Continue").click()
  >>> ctrl("Title").value = "Second Child"
  >>> ctrl("save").click()
  >>> "Successfully added item" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/second-child/edit'
  True

  >>> browser.getLink("Add").click()
  >>> ctrl("Add to Second Child").selected = True
  >>> ctrl("Continue").click()
  >>> ctrl("Title").value = "Grandchild"
  >>> ctrl("save").click()
  >>> browser.url == tests.BASE_URL + '/second-child/grandchild/edit'
  True

  >>> browser.getLink("View").click()
  >>> "Grandchild" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/second-child/grandchild/'
  True

Reorder documents
-----------------

  >>> browser.open(tests.BASE_URL)
  >>> index = browser.contents.index
  >>> index("First Child") > index("Second Child")
  False
  >>> browser.getLink("Edit").click()
  >>> browser.getLink("Move").click()
  >>> ctrl("First Child").click()
  >>> "First Child reordered" in browser.contents
  True
  >>> browser.getLink("View").click()
  >>> index = browser.contents.index
  >>> index("First Child") > index("Second Child")
  True

Delete a document
-----------------

  >>> browser.open(tests.BASE_URL + '/second-child/grandchild/move')
  >>> ctrl(name="delete-confirm").displayValue = ['Yes']
  >>> ctrl("delete").click()
  >>> "Grandchild deleted" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/second-child/edit'
  True

Copy and paste
--------------

  >>> browser.open(tests.BASE_URL + '/second-child/move')
  >>> ctrl(name="cut").click()
  >>> "Second Child cut" in browser.contents
  True

  >>> browser.open(tests.BASE_URL + '/child-one/move')
  >>> ctrl(name="paste").click()
  >>> "Second Child pasted" in browser.contents
  True

  >>> browser.open(tests.BASE_URL + '/child-one/second-child/')
  >>> browser.open(tests.BASE_URL + '/second-child/')
  Traceback (most recent call last):
  HTTPError: HTTP Error 404: Not Found

  >>> browser.open(tests.BASE_URL + '/child-one/second-child/move')
  >>> ctrl(name="copy").click()
  >>> "Second Child copied" in browser.contents
  True
  >>> browser.open(tests.BASE_URL + '/move')
  >>> ctrl(name="paste").click()
  >>> "Second Child pasted" in browser.contents
  True

We can paste twice since we copied:

  >>> ctrl(name="paste").click()
  >>> "Second Child pasted" in browser.contents
  True
  >>> browser.open(tests.BASE_URL + '/second-child/')
  >>> "Second Child" in browser.contents
  True
  >>> browser.open(tests.BASE_URL + '/second-child-1/')
  >>> "Second Child" in browser.contents
  True

We can also copy and paste items that contain children, like the whole
site:

  >>> browser.open(tests.BASE_URL + '/move')
  >>> ctrl(name="copy").click()
  >>> "My Site copied" in browser.contents
  True
  >>> browser.open(tests.BASE_URL + '/second-child/move')
  >>> ctrl(name="paste").click()
  >>> "My Site pasted" in browser.contents
  True
  >>> browser.open(tests.BASE_URL + '/second-child/my-site/')
  >>> browser.open(tests.BASE_URL + '/second-child/my-site/second-child/')

And finally cut and paste a tree:

  >>> browser.open(tests.BASE_URL + '/second-child/move')
  >>> ctrl(name="cut").click()
  >>> browser.open(tests.BASE_URL + '/child-one/second-child/move')
  >>> ctrl(name="paste").click()
  >>> "Second Child pasted" in browser.contents
  True
  >>> browser.open(tests.BASE_URL + '/second-child/')
  Traceback (most recent call last):
  HTTPError: HTTP Error 404: Not Found
  >>> browser.open(tests.BASE_URL + '/child-one/second-child/second-child')

Note how we can't cut and paste an item into itself:

  >>> browser.open(tests.BASE_URL + '/child-one/move')
  >>> ctrl(name="cut").click()
  >>> ctrl(name="paste")
  Traceback (most recent call last):
  LookupError: name 'paste'
  >>> browser.open(tests.BASE_URL + '/child-one/second-child/move')
  >>> ctrl(name="paste")
  Traceback (most recent call last):
  LookupError: name 'paste'

Whether we can paste or not also depends on the 'type_info.addable'
property:

  >>> browser.open(tests.BASE_URL + '/child-one/move')
  >>> ctrl(name="copy").click()
  >>> browser.open(tests.BASE_URL + '/child-one/second-child/move')
  >>> ctrl(name="paste")
  <SubmitControl name='paste' type='submitbutton'>
  >>> save_addable = Document.type_info.addable_to
  >>> Document.type_info.addable_to = ()
  >>> browser.reload()
  >>> ctrl(name="paste")
  Traceback (most recent call last):
  LookupError: name 'paste'
  >>> Document.type_info.addable_to = save_addable

We can rename an item:

  >>> browser.open(tests.BASE_URL + '/child-one/second-child/move')
  >>> ctrl("New name").value
  'second-child'
  >>> ctrl("New title").value
  'Second Child'
  >>> ctrl("New name").value = "third-child"
  >>> ctrl("New title").value = "My Third Child"
  >>> ctrl(name="rename").click()
  >>> "Item renamed" in browser.contents
  True
  >>> browser.url == tests.BASE_URL + '/child-one/third-child/move'
  True
  >>> browser.getLink("View").click()
  >>> "My Third Child" in browser.contents
  True

We cannot rename the root:

  >>> browser.open(tests.BASE_URL + '/move')
  >>> ctrl("New name")
  Traceback (most recent call last):
  LookupError: label 'New name'

Share
-----

XXX Add a user called 'Bob' and a group called 'bobsgroup'

  >>> from kotti.security import get_principals
  >>> get_principals()[u'group:bobsgroup'] = {
  ...     'id': u"group:bobsgroup",
  ...     'title': u"Bob's Group",
  ... }
  >>> get_principals()[u'bob'] = {
  ...     'id': u"bob",
  ...     'password': u"secret",
  ...     'title': u"Bob Dabolina",
  ...     'groups': [u'group:bobsgroup'],
  ... }

The Share tab allows us to assign users and groups to roles:

  >>> browser.open(tests.BASE_URL)
  >>> browser.getLink("Edit").click()
  >>> browser.getLink("Share").click()

We can search for users:

  >>> ctrl("Users and groups").value = "Bob"
  >>> ctrl(name="search").click()

Bob and Bob's Group are listed now:

  >>> "Bob Dabolina" in browser.contents
  True
  >>> "Bob's Group" in browser.contents
  True

We add Bob's Group to Owners and Editors before taking away Owners
again:

  >>> ctrl(name="role::group:bobsgroup::role:owner").value = True
  >>> ctrl(name="role::group:bobsgroup::role:editor").value = True
  >>> ctrl(name="apply").click()
  >>> "Your changes have been applied" in browser.contents
  True
  >>> browser.reload()
  >>> ctrl(name="role::group:bobsgroup::role:owner").value
  True
  >>> ctrl(name="role::group:bobsgroup::role:editor").value
  True
  >>> ctrl(name="role::group:bobsgroup::role:owner").value = False
  >>> ctrl(name="apply").click()
  >>> "Your changes have been applied" in browser.contents
  True
  >>> ctrl(name="role::group:bobsgroup::role:owner").value
  False

Not making any changes will give us a different feedback message:

  >>> ctrl(name="apply").click()
  >>> "Your changes have been applied" in browser.contents
  False
  >>> ctrl(name="role::group:bobsgroup::role:owner").value
  False
  >>> ctrl(name="role::group:bobsgroup::role:editor").value
  True

Bob should now have an inherited Editor role, because he's part of
Bob's Group:

  >>> ctrl(name="query").value = "Bob Dabolina"
  >>> ctrl(name="search").click()
  >>> ctrl(name="role::bob::role:editor").value
  True
  >>> ctrl(name="role::bob::role:owner").value
  False
  >>> ctrl(name="role::bob::role:editor").disabled
  True

Lastly, let's take away the remaining Editor role from Bob's Group
again:

  >>> "Bob's Group" in browser.contents
  True
  >>> ctrl(name="role::group:bobsgroup::role:editor").value = False
  >>> ctrl(name="apply").click()
  >>> "Your changes have been applied" in browser.contents
  True
  >>> "Bob's Group" in browser.contents
  False
