"""
$Id: __init__.py,v 1.2 2005/02/26 17:56:10 sidnei Exp $
"""

import os, sys
from cStringIO import StringIO

if __name__ == '__main__':
    execfile(os.path.join(sys.path[0], 'framework.py'))

from Testing import ZopeTestCase
from Products.Fate.tests.base import BaseTest
from zope.interface import directlyProvides, directlyProvidedBy
from zope.configuration.exceptions import ConfigurationError

from Products.CMFCore.utils import getToolByName
from Products.Fate.tests.utils import load_string
from Products.Fate.tests.sample import content
from Products.Fate.tests.sample.interfaces import IAdding
from zope.component import queryMultiAdapter
from zope.interface import Interface
from zope.app.publisher.browser import applySkin

class BaseViewTest(BaseTest):
    
    def afterSetUp(self):
        self.request = self.portal.REQUEST
        self.load_string("<browser:layer name='fate_tests' />")
        from zope.app.layers import fate_tests
        applySkin(self.request, fate_tests)
        directlyProvides(self.folder, IAdding, directlyProvidedBy(self.folder))
        qi = getToolByName(self.portal, 'portal_quickinstaller')
        qi.installProduct('Archetypes')

        from Products.Archetypes.public import listTypes
        from Products.Archetypes.Extensions.utils import installTypes
        types = listTypes(content.PROJECTNAME)
        installTypes(self.portal, StringIO(), types, content.PROJECTNAME)

    def load_string(self, s):
        decl = """
        <configure xmlns="http://namespaces.zope.org/zope"
            xmlns:browser="http://namespaces.zope.org/browser"
            xmlns:fate="http://namespaces.plone.org/fate"
            package="Products.Fate.tests.sample">

            %s

        </configure>
        """ % s
        load_string(decl)
        
    def getView(self, obj, name):
        return queryMultiAdapter((obj, self.request), Interface, name, None, None)


class AddFormTest(BaseViewTest):

    def test_invalid_product(self):
        decl = """
        <fate:addform
            name='invalid_product'
            for='*'
            permission='zope2.View'
            layer='fate_tests'
            product='NotAValidProduct'
            meta_type='File'
            />"""
        self.assertRaises(ConfigurationError, self.load_string, decl)


    def test_invalid_meta(self):
        decl = """
        <fate:addform
            name='invalid_meta'
            for='*'
            permission='zope2.View'
            layer='fate_tests'
            product='Fate'
            meta_type='NotAValidType'
            />"""
        self.assertRaises(ConfigurationError, self.load_string, decl)

    
    def test_simple_schema(self):
        decl = """
        <fate:addform
            name='simple_schema'
            for='.interfaces.IAdding'
            permission='zope2.View'
            layer='fate_tests'
            product='Fate'
            meta_type='SimpleSchema'
            />"""
        self.failIfRaises(ConfigurationError, self.load_string, decl)
        view = self.getView(self.folder, 'simple_schema')
        self.assertNotEqual(view, None)
        # XXX call update() to setup view. Some stuff depends on the
        # security being set, which doesn't happen at __init__ time
        # for some reason.
        view.update()
        fields = content.SimpleSchema.schema.fields()
        self.assertEquals(view.fieldsets, ['default'])
        self.assertEquals(view.fieldset, 'default')
        self.assertEquals(view.fields, fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default'])
        self.assertEquals(sch['default'].fields(), fields)
        # XXX schema can't be accessed directly, missing __of__,
        # whatever that means.
        # self.assertEquals(view.schema.keys(), ['f1', 'f2'])
        self.assertEquals(view.fieldNames, ('f1', 'f2'))


    def test_simple_with_id(self):
        decl = """
        <fate:editform
            name='simple_schema_with_id_edit'
            for='.interfaces.ISimpleSchema'
            permission='zope2.View'
            layer='fate_tests'
            />"""
        self.failIfRaises(ConfigurationError, self.load_string, decl)
        self.folder.invokeFactory('SimpleWithId', 'simple_with_id')
        doc = self.folder._getOb('simple_with_id')
        view = self.getView(doc, 'simple_schema_with_id_edit')
        self.assertNotEqual(view, None)
        # XXX call update() to setup view. Some stuff depends on the
        # security being set, which doesn't happen at __init__ time
        # for some reason.
        view.update()
        fields = content.SimpleWithId.schema.fields()
        self.assertEquals(view.fieldsets, ['default'])
        self.assertEquals(view.fieldset, 'default')
        self.assertEquals(view.fields, fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default'])
        self.assertEquals(sch['default'].fields(), fields)
        # XXX schema can't be accessed directly, missing __of__,
        # whatever that means.
        # self.assertEquals(view.schema.keys(), ['f1', 'f2'])
        self.assertEquals(view.fieldNames, ('id', 'f1', 'f2'))

        self.request.form['form.submitted'] = True
        self.request.form['f2'] = 'bla'
        # Submit an empty id, to simulate a user with prefs set to not
        # show id.
        self.request.form['id'] = ''
        view.update()
        # Should have no errors
        self.assertEquals(tuple(view.errors.keys()), ())


    def test_two_schemata(self):
        decl = """
        <fate:addform
            name='two_schemata'
            for='.interfaces.IAdding'
            permission='zope2.View'
            layer='fate_tests'
            product='Fate'
            meta_type='TwoSchemata'
            />"""
        self.failIfRaises(ConfigurationError, self.load_string, decl)
        view = self.getView(self.folder, 'two_schemata')
        self.assertNotEqual(view, None)
        # XXX call update() to setup view. Some stuff depends on the
        # security being set, which doesn't happen at __init__ time
        # for some reason.
        view.update()
        fields = content.TwoSchemata.schema.fields()
        default_fields = [fields[0]]
        second_fields = [fields[1]]
        self.assertEquals(view.fieldsets, ['default', 'second'])
        self.assertEquals(view.fieldset, 'default')
        self.assertEquals(view.fields, default_fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default', 'second'])
        self.assertEquals(sch['default'].fields(), default_fields)
        self.assertEquals(sch['second'].fields(), second_fields)
        self.assertEquals(view.fieldNames, ('f1',))

        # Now, switch to the second schemata and do all the checking again.
        self.request.other['fieldset'] = 'second'
        view.update()
        self.assertEquals(view.fieldsets, ['default', 'second'])
        self.assertEquals(view.fieldset, 'second')
        self.assertEquals(view.fields, second_fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default', 'second'])
        self.assertEquals(view.fieldNames, ('f2',))

        # Now comes the tricky part.  Submitting the form should error
        # out with the 'f2' being required, no matter what is the
        # current fieldset being edited. In addition to that, it
        # should set the fieldset to the first fieldset containing an
        # error.

        self.request.other['form.submitted'] = True
        self.request.other['fieldset'] = 'default'
        view.update()
        # At this point, the current fieldset should be 'second', as
        # the field that failed to pass validation was located there,
        # even if the request explicitly said the fieldset to be
        # displayed was 'default'.
        self.assertEquals(view.fieldsets, ['default', 'second'])
        self.assertEquals(view.fieldset, 'second')
        self.assertEquals(view.fields, second_fields)
        self.assertEquals(view.fieldNames, ('f2',))
        # Errors should have not been reset
        self.failUnless(tuple(view.errors.keys()), ('f2',))


class EditFormTest(BaseViewTest):

    def test_simple_schema(self):
        decl = """
        <fate:editform
            name='simple_schema_edit'
            for='.interfaces.ISimpleSchema'
            permission='zope2.View'
            layer='fate_tests'
            />"""
        self.failIfRaises(ConfigurationError, self.load_string, decl)
        self.folder.invokeFactory('SimpleSchema', 'simple_schema')
        doc = self.folder._getOb('simple_schema')
        view = self.getView(doc, 'simple_schema_edit')
        self.assertNotEqual(view, None)
        # XXX call update() to setup view. Some stuff depends on the
        # security being set, which doesn't happen at __init__ time
        # for some reason.
        view.update()
        fields = content.SimpleSchema.schema.fields()
        self.assertEquals(view.fieldsets, ['default'])
        self.assertEquals(view.fieldset, 'default')
        self.assertEquals(view.fields, fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default'])
        self.assertEquals(sch['default'].fields(), fields)
        # XXX schema can't be accessed directly, missing __of__,
        # whatever that means.
        # self.assertEquals(view.schema.keys(), ['f1', 'f2'])
        self.assertEquals(view.fieldNames, ('f1', 'f2'))


    def test_two_schemata(self):
        decl = """
        <fate:editform
            name='two_schemata_edit'
            for='.interfaces.ITwoSchemata'
            permission='zope2.View'
            layer='fate_tests'
            />"""
        self.failIfRaises(ConfigurationError, self.load_string, decl)
        self.folder.invokeFactory('TwoSchemata', 'two_schemata')
        doc = self.folder._getOb('two_schemata')
        view = self.getView(doc, 'two_schemata_edit')
        self.assertNotEqual(view, None)
        # XXX call update() to setup view. Some stuff depends on the
        # security being set, which doesn't happen at __init__ time
        # for some reason.
        view.update()
        fields = content.TwoSchemata.schema.fields()
        default_fields = [fields[0]]
        second_fields = [fields[1]]
        self.assertEquals(view.fieldsets, ['default', 'second'])
        self.assertEquals(view.fieldset, 'default')
        self.assertEquals(view.fields, default_fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default', 'second'])
        self.assertEquals(sch['default'].fields(), default_fields)
        self.assertEquals(sch['second'].fields(), second_fields)
        self.assertEquals(view.fieldNames, ('f1',))

        # Now, switch to the second schemata and do all the checking again.
        self.request.other['fieldset'] = 'second'
        view.update()
        self.assertEquals(view.fieldsets, ['default', 'second'])
        self.assertEquals(view.fieldset, 'second')
        self.assertEquals(view.fields, second_fields)
        sch = view.schemata
        self.assertEquals(sch.keys(), ['default', 'second'])
        self.assertEquals(view.fieldNames, ('f2',))

        # Now comes the tricky part.  Submitting the form should error
        # out with the 'f2' being required, no matter what is the
        # current fieldset being edited. In addition to that, it
        # should set the fieldset to the first fieldset containing an
        # error.

        self.request.other['form.submitted'] = True
        self.request.other['fieldset'] = 'default'
        view.update()
        # At this point, the current fieldset should be 'second', as
        # the field that failed to pass validation was located there,
        # even if the request explicitly said the fieldset to be
        # displayed was 'default'.
        self.assertEquals(view.fieldsets, ['default', 'second'])
        self.assertEquals(view.fieldset, 'second')
        self.assertEquals(view.fields, second_fields)
        self.assertEquals(view.fieldNames, ('f2',))
        # Errors should have not been reset
        self.failUnless(tuple(view.errors.keys()), ('f2',))


def test_suite():
    import unittest
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(AddFormTest))
    suite.addTest(unittest.makeSuite(EditFormTest))
    return suite

if __name__ == '__main__':
    framework()
