Esempio n. 1
0
    def testSalesforceAdapterOnSuccessFor1ToNObjects(self):
        """Ensure that 1:N -- well actually 2 here :) -- Salesforce Adapter mapped objects
           find their way into the appropriate Salesforce.com instance.  
        """
        # create multiple action adapters
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'account_adapter')
        
        # disable mailer adapter
        self.ff1.setActionAdapter(('contact_adapter','account_adapter',))
        
        # configure our contact_adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.contact_adapter.setTitle('Salesforce Contact Action Adapter')
        self.ff1.contact_adapter.setSFObjectType('Contact')
        self.ff1.contact_adapter.setFieldMap((
            {'field_path': 'replyto', 'form_field': 'Your E-Mail Address', 'sf_field': 'Email'},
            {'field_path': 'comments', 'form_field': 'Comments', 'sf_field': 'LastName'}))
        
        # configure our account_adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.account_adapter.setTitle('Salesforce Account Action Adapter')
        self.ff1.account_adapter.setSFObjectType('Account')
        self.ff1.account_adapter.setFieldMap((
            {'field_path':'comments', 'form_field': 'Comments', 'sf_field': 'Name'},))
        
        # build the request and submit the form for both adapters
        fields = self.ff1._getFieldObjects()
        request = base.FakeRequest(replyto = '*****@*****.**', # mapped to Email (see above) 
                              comments='PloneTestCase1ToN')            # mapped to LastName (see above)
        request.SESSION = {}
        
        # we only call onSuccess for our last SF adapter in the form
        # which calculates the need order and executes all SF adapters in 
        # the appropriate sequence
        self.ff1.account_adapter.onSuccess(fields, request)        
        
        # direct query of Salesforce to get the id of the newly created contact
        contact_res = self.salesforce.query(
            "SELECT Id FROM %s WHERE Email='%s' AND LastName='%s'" % (
                self.ff1.contact_adapter.getSFObjectType(),
                '*****@*****.**',
                'PloneTestCase1ToN')
            )
        # in case we fail, stock up our to delete list for tear down
        self._todelete.append(contact_res['records'][0]['Id'])
        
        # direct query of Salesforce to get the id of the newly created account
        account_res = self.salesforce.query(
            "SELECT Id FROM %s WHERE Name='%s'" % (
                self.ff1.account_adapter.getSFObjectType(),
                'PloneTestCase1ToN')
            )

        # in case we fail, stock up our to delete list for tear down
        self._todelete.append(account_res['records'][0]['Id'])
        
        # assert that our newly created Contact was found
        self.assertEqual(1, contact_res['size'])
        self.assertEqual(1, account_res['size'])
Esempio n. 2
0
    def testEmptyFormDateFieldIsntPushedUpstreamAsInvalidXSDDateTime(self):
        """Assuming we survive a test for issue (i.e. empty string isn't 
           cast to DateTime causing a syntax error): 
           http://plone.org/products/salesforcepfgadapter/issues/5
       
           We also want to make sure this isn't added to sObject and therefore
           failing upon an attempt to create the object in Salesforce due to
           a SoapFaultError of invalid value for the type xsd:dateTime. See:
           http://plone.org/products/salesforcepfgadapter/issues/6
        """
        # create a attachmetn action adapter
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')

        # disable mailer adapter
        self.ff1.setActionAdapter(('contact_adapter', ))

        # configure our contact_adapter to create an Attachment on submission
        self.ff1.contact_adapter.setTitle('Salesforce Contact Action Adapter')
        self.ff1.contact_adapter.setSFObjectType('Contact')

        # bogus mapping to meet Contact creation reqs,
        # we optionally ask for the Birtdate in the form
        self.ff1.contact_adapter.setFieldMap((
            {
                'field_path': 'comments',
                'form_field': 'Comments',
                'sf_field': 'LastName'
            },
            {
                'field_path': 'date',
                'form_field': 'date',
                'sf_field': 'Birthdate'
            },
        ))

        # build the request and submit the form for both adapters
        fields = self.ff1._getFieldObjects()
        # assuming there was a FormDateField that was not filled out, it would
        # look like the following in the request:
        request = base.FakeRequest(comments='PloneTestCaseEmptyDateField',
                                   date='')
        request.SESSION = {}

        # call onSuccess
        self.ff1.contact_adapter.onSuccess(fields, request)

        # query for our attachment
        contact_res = self.salesforce.query(
            "SELECt Id, Birthdate FROM Contact WHERE LastName='PloneTestCaseEmptyDateField'"
        )

        # in case we fail, stock up our to delete list for tear down
        self._todelete.append(contact_res['records'][0]['Id'])

        # make our assertions
        self.failIf(contact_res['records'][0]['Birthdate'])
Esempio n. 3
0
 def testFieldsetContainedFieldsCorrectlyPushedToSalesforceObject(self):
     """As a follow-up to ensuring our fieldset fields can be mapped,
        we ensure their values are appropriately pushed to Salesforce.com
        See: http://plone.org/products/salesforcepfgadapter/issues/2
     """
     # create a new fieldset within the form
     self.ff1.invokeFactory('FieldsetFolder', 'subform')
     self.ff1.subform.setTitle("Subform Fieldset")
     # create a field local to the fieldset
     self.ff1.subform.invokeFactory('FormStringField', 'subformfield')
     self.ff1.subform.subformfield.setTitle("Subform Field")
     
     # create a contact action adapters
     self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')
     
     # disable mailer adapter
     self.ff1.setActionAdapter(('contact_adapter',))
     
     # configure our contact_adapter to create a contact on submission
     # last name is the lone required field, but we map a few others 
     # and our fieldset field ...
     self.ff1.contact_adapter.setTitle('Salesforce Contact Action Adapter')
     self.ff1.contact_adapter.setSFObjectType('Contact')
     self.ff1.contact_adapter.setFieldMap((
         {'field_path': 'replyto', 'form_field': 'Your E-Mail Address', 'sf_field': 'Email'},
         {'field_path': 'comments', 'form_field': 'Comments', 'sf_field': 'LastName'},
         {'field_path': 'subform,subformfield', 'form_field': 'Subform Fieldset --> Subform Field', 'sf_field': 'FirstName'},
     ))
     
     # build the request and submit the form for both adapters
     fields = self.ff1._getFieldObjects()
     request = base.FakeRequest(replyto = '*****@*****.**', # mapped to Email (see above) 
                           comments='PloneTestCaseFieldsetFields',            # mapped to LastName (see above)
                           subformfield='PloneTestCaseFieldsetSubField',)     # mapped to FirstName (see above)
     request.SESSION = {}
     
     # we only call onSuccess for our last SF adapter in the form
     # which calculates the need order and executes all SF adapters in 
     # the appropriate sequence
     self.ff1.contact_adapter.onSuccess(fields, request)        
     
     # direct query of Salesforce to get the id of the newly created contact
     contact_res = self.salesforce.query(
         "SELECT Id, FirstName FROM %s WHERE LastName='%s'" % (
             self.ff1.contact_adapter.getSFObjectType(),
             'PloneTestCaseFieldsetFields')
         )
     # in case we fail, stock up our to delete list for tear down
     self._todelete.append(contact_res['records'][0]['Id'])
     
     # assert that our newly created Contact was found
     self.assertEqual(request.form['subformfield'], contact_res['records'][0]['FirstName'])
Esempio n. 4
0
    def testEmptyIntegerFieldIsntPushedUpstreamAsInvalidXSDIntDouble(self):
        """A correctly configured form may ask for an optional "on a scale
           of 1-5" type question that is left blank.  The build object for
           creation code shouldn't assume too much about this and turn it
           into something it's not, like a string.  We use lead creation and
           and the NumberOfEmployees field as an example below. See:
           http://plone.org/products/salesforcepfgadapter/issues/8
        """
        # create a attachmetn action adapter
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'lead_adapter')
        
        # disable mailer adapter
        self.ff1.setActionAdapter(('lead_adapter',))
        
        # configure our contact_adapter to create an Attachment on submission
        self.ff1.lead_adapter.setTitle('Salesforce Lead Action Adapter')
        self.ff1.lead_adapter.setSFObjectType('Lead')
        
        self.ff1.invokeFactory('FormIntegerField', 'num')
        self.ff1.num.setTitle('num')
        
        # bogus mapping to meet Contact creation reqs,
        # we optionally ask for the Birtdate in the form
        self.ff1.lead_adapter.setFieldMap((
            {'field_path': 'comments', 'form_field': 'Comments', 'sf_field': 'LastName'},
            {'field_path': 'topic', 'form_field': 'Subject', 'sf_field': 'Company'},
            {'field_path': 'num', 'form_field': 'num', 'sf_field': 'NumberOfEmployees'},
        ))
        
        # build the request and submit the form for both adapters
        fields = self.ff1._getFieldObjects()
        # assuming there was a FormIntegerField that was not filled out, it would
        # look like the following in the request:
        request = base.FakeRequest(comments = 'PloneTestCaseEmptyIntegerField', 
                                   topic = 'PloneTestCaseEmptyIntegerFieldCompany')
        request.SESSION = {}

        # call onSuccess
        self.ff1.lead_adapter.onSuccess(fields, request)  
        
        # query for our attachment
        lead_res = self.salesforce.query(
            "SELECT Id, NumberOfEmployees FROM Lead WHERE LastName='%s'" % (
                'PloneTestCaseEmptyIntegerField')
            )

        # in case we fail, stock up our to delete list for tear down
        self._todelete.append(lead_res['records'][0]['Id'])

        # make our assertions
        self.failIf(lead_res['records'][0]['NumberOfEmployees'])
 def _createTestContact(self):
     # first create a new contact - build the request and submit the form
     self.ff1.contact_adapter.setCreationMode('create')
     fields = self.ff1._getFieldObjects()
     request = base.FakeRequest(replyto = '*****@*****.**', # mapped to Email (see above) 
                                comments='PloneTestCase')            # mapped to LastName (see above)
     request.SESSION = {}
     self.ff1.contact_adapter.onSuccess(fields, request)
     
     # direct query of Salesforce to get the id of the newly created contact
     res = self.salesforce.query(['Id',],self.ff1.contact_adapter.getSFObjectType(),
                                 "Email='*****@*****.**' and LastName='PloneTestCase'")
     self._todelete.append(res['records'][0]['Id'])
     
     # assert that our newly created Contact was found
     self.assertEqual(1, res['size'])
     
     self.ff1.contact_adapter.setCreationMode('update')
Esempio n. 6
0
    def testEmptyFormDateFieldDoesntFailDateTimeConversion(self):
        """We don't want to try and cast an empty FormDateField value
           to an appropriately formatted DateTime. See: 
           http://plone.org/products/salesforcepfgadapter/issues/5
        """

        # assuming there was a FormDateField that was not filled out, it would
        # look like the following in the request:
        request = base.FakeRequest(topic='test subject',
                                   replyto='*****@*****.**',
                                   date='')

        fields = [self.ff1.date]

        # attempt to build the object which would trigger
        # SyntaxError: Unable to parse (' GMT+0',), {}
        # if the date came through as '' and we tried to coerce to DateTime
        sObject = self.ff1.salesforce._buildSObjectFromForm(fields,
                                                            REQUEST=request)
        self.failIf(sObject.has_key('date'))
Esempio n. 7
0
    def testSalesforceAdapterOnSuccess(self):
        """Ensure that our Salesforce Adapter mapped objects
           find their way into the appropriate Salesforce.com
           instance.
        """
        # create our action adapter
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')
        
        # disable mailer adapter
        self.ff1.setActionAdapter(('contact_adapter',))
        
        # configure our action adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.contact_adapter.setTitle('Salesforce Action Adapter')
        self.ff1.contact_adapter.setSFObjectType('Contact')
        self.ff1.contact_adapter.setFieldMap((
            {'field_path': 'replyto', 'form_field': 'Your E-Mail Address', 'sf_field': 'Email'},
            ))
        self.ff1.contact_adapter.setPresetValueMap((
            {'value': 'PloneTestCase', 'sf_field': 'LastName'},
            ))

        # build the request and submit the form
        fields = self.ff1._getFieldObjects()
        request = base.FakeRequest(replyto = '*****@*****.**') # mapped to Email (see above) 
        request.SESSION = {}
        
        self.ff1.contact_adapter.onSuccess(fields, request)
        
        # direct query of Salesforce to get the id of the newly created contact
        res = self.salesforce.query(
            "SELECT Id FROM %s WHERE Email='%s' AND LastName='%s'" % (
                self.ff1.contact_adapter.getSFObjectType(),
                '*****@*****.**',
                'PloneTestCase')
            )
        self._todelete.append(res['records'][0]['Id'])
        
        # assert that our newly created Contact was found
        self.assertEqual(1, res['size'])
Esempio n. 8
0
    def testDateFieldConvertedToSalesforceFormat(self):
        """ Prove that DateField values get converted to the format
            expected by Salesforce (mm/dd/yyyy).
        """
        from DateTime import DateTime
        now = DateTime()
        now_plone = now.strftime('%m-%d-%Y %H:%M')

        request = base.FakeRequest(topic='test subject',
                                   replyto='*****@*****.**',
                                   date=now_plone)
        fields = [self.ff1.date]
        sObject = self.ff1.salesforce._buildSObjectFromForm(fields,
                                                            REQUEST=request)

        from time import strptime
        try:
            strptime(sObject['date'], '%Y-%m-%dT%H:%M:%SZ')
        except ValueError:
            self.fail(
                "Doesn't look like the date was converted to Salesforce format properly."
            )
Esempio n. 9
0
 def testPresetValueMapExpressions(self):
     """Ensure that our Salesforce Adapter mapped objects
        find their way into the appropriate Salesforce.com
        instance.
     """
     # create our action adapter
     self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')
     # disable mailer adapter
     self.ff1.setActionAdapter(('contact_adapter',))
     # configure our action adapter to create a contact on submission,
     # exercising various expression formats
     self.ff1.contact_adapter.setTitle('Salesforce Action Adapter')
     self.ff1.contact_adapter.setSFObjectType('Contact')
     self.ff1.contact_adapter.setPresetValueMap((
         {'value': 'PloneTestCase', 'sf_field': 'LastName'},
         {'value': 'path:object/portal_url', 'sf_field': 'Description'},
         {'value': 'python:now', 'sf_field': 'Birthdate'},
         ))
     # build the request and submit the form
     fields = self.ff1._getFieldObjects()
     request = base.FakeRequest()
     request.SESSION = {}
     self.ff1.contact_adapter.onSuccess(fields, request)
     
     # direct query of Salesforce to get the id of the newly created contact
     res = self.salesforce.query(
         "SELECT Id, LastName, Description, Birthdate FROM %s WHERE LastName='%s'" % (
             self.ff1.contact_adapter.getSFObjectType(),
             'PloneTestCase')
         )
     self._todelete.append(res['records'][0]['Id'])
     
     # check the stored values
     self.assertEqual(1, res['size'])
     self.assertEqual('PloneTestCase', res[0].LastName)
     self.failUnless(res[0].Description.startswith('http://'))
     self.failUnless(isinstance(res[0].Birthdate, datetime.date))
    def testChainedDependenciesInsertCorrectly(self):
        # create multiple action adapters
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'account_adapter')

        # disable mailer adapter
        self.ff1.setActionAdapter((
            'contact_adapter',
            'account_adapter',
        ))

        # configure our contact_adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.contact_adapter.setTitle('Salesforce Contact Action Adapter')
        self.ff1.contact_adapter.setSFObjectType('Contact')
        self.ff1.contact_adapter.setFieldMap(({
            'field_path': 'replyto',
            'form_field': 'Your E-Mail Address',
            'sf_field': 'Email'
        }, {
            'field_path': 'comments',
            'form_field': 'Comments',
            'sf_field': 'LastName'
        }))

        # configure our account_adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.account_adapter.setTitle('Salesforce Account Action Adapter')
        self.ff1.account_adapter.setSFObjectType('Account')
        self.ff1.account_adapter.setFieldMap(({
            'field_path': 'topic',
            'form_field': 'Subject',
            'sf_field': 'Name'
        }, ))

        # set up dependencies
        self.ff1.contact_adapter.setDependencyMap(({
            'adapter_id': 'account_adapter',
            'adapter_name': 'Salesforce Account Action Adapter',
            'sf_field': 'AccountId'
        }, ))
        request = base.FakeRequest(
            topic="testChainedDependenciesInsertCorrectly",
            replyto='*****@*****.**',
            comments='testChainedDependenciesInsertCorrectly')
        request.SESSION = {}

        # call onSuccess on last SF adapter in form
        fields = self.ff1._getFieldObjects()
        self.ff1.account_adapter.onSuccess(fields, request)

        # salesforce queries and cleanup
        contact_res = self.salesforce.query(
            "SELECT Id, AccountId FROM Contact WHERE LastName='%s' AND Email='%s'"
            % ('testChainedDependenciesInsertCorrectly',
               '*****@*****.**'))
        self._todelete.append(contact_res['records'][0]['Id'])  # for clean-up

        account_res = self.salesforce.query(
            "SELECT Id FROM Account WHERE Name = 'testChainedDependenciesInsertCorrectly'"
        )
        account_id = account_res['records'][0]['Id']
        self._todelete.append(account_id)  # for clean-up

        # assertions
        self.assertEqual(1, contact_res['size'])
        self.assertEqual(1, account_res['size'])
        self.assertEqual(account_id, contact_res['records'][0]['AccountId'])
    def testChainedAdaptersAccountsForNonexecutingAdapters(self):
        """We delegate the creation of all Salesforce objects for
           each adapter to the final adapter.  This final adapter,
           however, must be an adapter that's enabled (i.e. present
           in the getActionAdapter list). Here we ensure that all
           active adapters are successfully run (this would be done
           by the final active adapter -- but that is an unimportant
           implementation detail.)
        """
        # create multiple action adapters
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'contact_adapter')
        self.ff1.invokeFactory('SalesforcePFGAdapter', 'account_adapter')

        # disable mailer adapter
        self.ff1.setActionAdapter((
            'contact_adapter',
            'account_adapter',
        ))

        # configure our contact_adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.contact_adapter.setTitle('Salesforce Contact Action Adapter')
        self.ff1.contact_adapter.setSFObjectType('Contact')
        # ... but configure a totally bogus execution
        # condition that could never be true
        self.ff1.contact_adapter.setFieldMap(({
            'field_path': 'replyto',
            'form_field': 'Your E-Mail Address',
            'sf_field': 'Email'
        }, {
            'field_path': 'comments',
            'form_field': 'Comments',
            'sf_field': 'LastName'
        }))

        # configure our account_adapter to create a contact on submission
        # last name is the lone required field
        self.ff1.account_adapter.setTitle('Salesforce Account Action Adapter')
        self.ff1.account_adapter.setSFObjectType('Account')
        self.ff1.account_adapter.setExecCondition('python:1 == 0')
        self.ff1.account_adapter.setFieldMap(({
            'field_path': 'topic',
            'form_field': 'Subject',
            'sf_field': 'Name'
        }, ))

        # set up dependencies
        self.ff1.contact_adapter.setDependencyMap(({
            'adapter_id': 'account_adapter',
            'adapter_name': 'Salesforce Account Action Adapter',
            'sf_field': 'AccountId'
        }, ))
        request = base.FakeRequest(
            topic="testChainedRespectNonexecutableFinalAdapters",
            replyto='*****@*****.**',
            comments='testChainedRespectNonexecutableFinalAdapters')
        request.SESSION = {}
        fields = self.ff1._getFieldObjects()

        # call onSuccess on last *executable* SF adapter in form
        self.ff1.contact_adapter.onSuccess(fields, request)

        # salesforce queries and cleanup
        contact_res = self.salesforce.query(
            "SELECT Id, AccountId FROM Contact WHERE LastName='%s' AND Email='%s'"
            % ('testChainedRespectNonexecutableFinalAdapters',
               '*****@*****.**'))
        self._todelete.append(contact_res['records'][0]['Id'])  # for clean-up

        account_res = self.salesforce.query(
            "SELECT Id FROM Account WHERE Name = 'testChainedRespectNonexecutableFinalAdapters'"
        )

        # assertions
        self.assertEqual(1, contact_res['size'])
        self.assertEqual(0, account_res['size'])
        self.failIf(contact_res['records'][0]['AccountId'])
Esempio n. 12
0
 def testFileFieldsSavedToSalesforce(self):
     """There may be other use cases, but the Attachment
        type in Salesforce can be associated with any other
        type and is where binary data, as stored on the Body
        field, is typically associated with a record. Here
        we confirm that a binary file can be mapped and
        is succesfully posted to Salesforce.com via PloneFormGen's
        FormFileField type.
     """
     def _createBinaryFile():
         from cgi import FieldStorage
         from ZPublisher.HTTPRequest import FileUpload
         from tempfile import TemporaryFile
         fp = TemporaryFile('w+b')
         fp.write('\x00' + 'x' * (1 << 19))
         fp.seek(0)
         env = {'REQUEST_METHOD':'PUT'}
         headers = {'content-type':'application/msword',
                    'content-length': 1 << 19,
                    'content-disposition':'attachment; filename=test.doc'}
         fs = FieldStorage(fp=fp, environ=env, headers=headers)
         return FileUpload(fs)
     
     # add a file field to our standard form
     self.ff1.invokeFactory('FormFileField','filefield')
     self.ff1.filefield.setTitle("File")
     
     # directly create a contact for association, since we need
     # a valid parent id and don't care about related objects here
     sObject = dict(type='Contact')
     sObject['LastName'] = 'testFileFieldsSavedToSalesforce'
     contact_create_res = self.salesforce.create(sObject)
     
     # get ready to cleanup regardless of test case success
     self._todelete.append(contact_create_res[0]['id'])
     
     # create a attachment action adapter
     self.ff1.invokeFactory('SalesforcePFGAdapter', 'attachment_adapter')
     
     # disable mailer adapter
     self.ff1.setActionAdapter(('attachment_adapter',))
     
     # configure our attachment_adapter to create an Attachment on submission
     self.ff1.attachment_adapter.setTitle('Salesforce Attachment Action Adapter')
     self.ff1.attachment_adapter.setSFObjectType('Attachment')
     
     # bogus mapping to meet Attachment reqs
     self.ff1.attachment_adapter.setFieldMap((
         {'field_path': 'replyto', 'form_field': 'Your E-Mail Address', 'sf_field': 'ParentId'},
         {'field_path': 'filefield', 'form_field': 'File', 'sf_field': 'Body'},
         {'field_path': 'filefield,mimetype', 'form_field': 'File Mimetype', 'sf_field': 'ContentType'},
         {'field_path': 'filefield,filename', 'form_field': 'File Filename', 'sf_field': 'Name'},
     ))
     
     # build the request and submit the form for both adapters
     fields = self.ff1._getFieldObjects()
     request = base.FakeRequest(replyto = contact_create_res[0]['id'], # mapped to ParentId (see above) 
                           filefield_file=_createBinaryFile(),)     # mapped to FirstName (see above)
     request.SESSION = {}
     
     # call onSuccess 
     self.ff1.attachment_adapter.onSuccess(fields, request)  
     
     # query for our attachment
     attach_res = self.salesforce.query(
         "SELECT Id, Name, ContentType, BodyLength FROM Attachment WHERE ParentId='%s'" % (
             contact_create_res[0]['id'])
         )
     # in case we fail, stock up our to delete list for tear down
     self._todelete.append(attach_res['records'][0]['Id'])
     
     # make our assertions
     self.assertEqual('test.doc', attach_res['records'][0]['Name'])
     self.assertEqual('application/msword', attach_res['records'][0]['ContentType'])
     self.failUnless(attach_res['records'][0]['BodyLength'] > 0)