Tests for QuickInstaller installation
=====================================

First we need to install quickinstaller itself:

  >>> self.setRoles(['Manager'])
  >>> self.addProfile('Products.CMFQuickInstallerTool:CMFQuickInstallerTool')

  >>> from zope.component import getSiteManager
  >>> from Products.CMFQuickInstallerTool.interfaces import IQuickInstallerTool
  >>> from Products.CMFCalendar.interfaces import ICalendarTool
  >>> from Products.CMFCore.utils import getToolByName

Now set three convenience variables for later use:

  >>> portal = self.app.cmf
  >>> portal
  <CMFSite at /cmf>

  >>> qi = getattr(portal, 'portal_quickinstaller', None)
  >>> qi
  <QuickInstallerTool at /cmf/portal_quickinstaller>

  >>> types_tool = portal.portal_types
  >>> types_tool
  <TypesTool at /cmf/portal_types>

And register the QI tool as a utility:

  >>> sm = getSiteManager()
  >>> sm.registerUtility(qi, IQuickInstallerTool)

Install a product through an external method
--------------------------------------------

Before installing CMFCalendar as an example lets make sure none of the
installed objects are already present:

  >>> 'Event' in types_tool.objectIds()
  False

  >>> 'portal_calendar' in portal.objectIds()
  False

And we have no InstalledProduct instance in the QI tool:

  >>> 'CMFCalendar' in qi.objectIds()
  False

After checking that the product is not installed yet, we do install it:

  >>> qi.installProducts(products=['CMFCalendar'])
  '...Installed Products...CMFCalendar:ok:...'

Make sure the calendar tool and the Event type are added:

  >>> 'portal_calendar' in portal.objectIds()
  True

  >>> 'Event' in portal.portal_types.objectIds()
  True

  >>> getToolByName(portal, 'portal_calendar')
  <CalendarTool at .../portal_calendar>

And we have an InstalledProduct instance in the QI tool:

  >>> 'CMFCalendar' in qi.objectIds()
  True

  >>> cal = qi['CMFCalendar']
  >>> cal.isInstalled()
  True


Uninstall the product again
---------------------------

  >>> qi.uninstallProducts(products=['CMFCalendar'])

Verify that all added entries were removed again:

  >>> 'Event' in types_tool.objectIds()
  False

  >>> 'portal_calendar' in portal.objectIds()
  False

And we have an InstalledProduct instance in the QI tool which says the product
is not installed anymore:

  >>> 'CMFCalendar' in qi.objectIds()
  True
  
  >>> cal = qi['CMFCalendar']
  >>> cal.isInstalled()
  False

  >>> setup = getToolByName(portal, 'portal_setup')
  >>> logs = [i for i in setup.objectIds() if 'CMFCalendar' in i]
  >>> for i in logs:
  ...     setup._delObject(i)

Install a product through an extension profile
----------------------------------------------

>>> qi.installProducts(products=['CMFCalendar'], forceProfile=True, omitSnapshots=True)
'...Installed Products...CMFCalendar:ok:...'

Make sure the calendar tool and the Event type are added:

  >>> 'portal_calendar' in portal.objectIds()
  True

  >>> getToolByName(portal, 'portal_calendar')
  <CalendarTool at .../portal_calendar>

  >>> 'Event' in portal.portal_types.objectIds()
  True

And we have an InstalledProduct instance in the QI tool which says the product
is installed again:

  >>> 'CMFCalendar' in qi.objectIds()
  True
  
  >>> cal = qi['CMFCalendar']
  >>> cal.isInstalled()
  True

Uninstall the product again
---------------------------

  >>> qi.uninstallProducts(products=['CMFCalendar'])

Verify that all added entries were removed again:

  >>> 'Event' in types_tool.objectIds()
  False

  >>> 'portal_calendar' in portal.objectIds()
  False

And we have an InstalledProduct instance in the QI tool which says the product
is not installed anymore again:

  >>> 'CMFCalendar' in qi.objectIds()
  True
  
  >>> cal = qi['CMFCalendar']
  >>> cal.isInstalled()
  False

Install a product which has a GenericSetup dependency
-----------------------------------------------------

There was a bug where if you installed a product which depends on another
product, and then uninstalled it, the dependency's entries would be
removed. Let's make sure that doesn't happen!

First we need to fake a product that depends on CMFCalendar:
  >>> import sys
  >>> from Products.CMFQuickInstallerTool import tests
  >>> sys.modules['Products.TestCMFCalendar'] = tests
  >>> from Products.GenericSetup.registry import _profile_registry
  >>> _profile_registry.registerProfile('default', 'Test',
  ...     '', tests.__path__[0], 'TestCMFCalendar', 2)

Now we install our fake product:

  >>> qi.installProducts(products=['TestCMFCalendar'], omitSnapshots=True)
  '...Installed Products...TestCMFCalendar:ok:...'

And confirm that CMFCalendar stuff was installed:

  >>> 'portal_calendar' in portal.objectIds()
  True

And remove it:

  >>> qi.uninstallProducts(products=['TestCMFCalendar'])

The CMFCalendar stuff should still be present:

  >>> 'portal_calendar' in portal.objectIds()
  True


Install and Reinstall without deleting custom content
-----------------------------------------------------

Custom products can add content items (especially folders) to the root 
of a plone site. We want to be sure NOT to delete these "non-tool"
items. To emulate this we can install any product, add some content, 
and then fudge the snapshot to make it seem like it was added by the 
install of the product.
  
  >>> before = qi.snapshotPortal(portal)
  
Generic Setup does not like so many installs and needs to fix its timestamp
for logging. For now lets artificially time it

  >>> import time;time.sleep(1)
  
  >>> qi.installProducts(products=['CMFCalendar'])
  '...Installed Products...CMFCalendar:ok:...'
  
Add a folder to the root - this should remain after uninstall
  
  >>> portal.manage_addFolder("test", title="Test")
  >>> 'test' in portal.objectIds()
  True
  
Fudge the snapshot
  
  >>> after = qi.snapshotPortal(portal)
  >>> settings = qi.deriveSettingsFromSnapshots(before, after)
  >>> p = qi['CMFCalendar']
  >>> p.update(settings=settings)
  
Uninstall the product and confirm the content is still there
  
  >>> qi.uninstallProducts(products=['CMFCalendar'])
  >>> 'test' in portal.objectIds()
  True
