.. -*-doctest-*-

========
Criteria
========

We start with a topic.

    >>> foo_topic = self.folder['foo-topic-title']

Open a browser as an anonymous user.

    >>> from Products.Five.testbrowser import Browser
    >>> from Products.PloneTestCase import ptc
    >>> browser = Browser()
    >>> browser.handleErrors = False

Lists
-----

The ListFormCriterion is provided for rendering lists on the search
form.

Add a list criterion for the subject/keywords.

    >>> foo_topic.addCriterion(
    ...     'Subject', 'ListFormCriterion')
    <ListFormCriterion at
    /plone/Members/test_user_1_/foo-topic-title/crit__Subject_ListFormCriterion>

Designate the criterion's field as a form field.

    >>> crit = foo_topic.getCriterion('Subject_ListFormCriterion')
    >>> crit.setFormFields(['value'])
    
The values set on the criterion are the default values checked on the
search form.

    >>> crit.setValue(['bah'])

When viewing the collection in a browser lists will be rendered
for the field with the default values selected.

    >>> browser.open(foo_topic.absolute_url())
    >>> ctrl = browser.getControl(
    ...     name='crit__Subject_ListFormCriterion.value:lines')
    >>> ctrl
    <Control name='crit__Subject_ListFormCriterion.value:lines'
    type='textarea'>
    >>> ctrl.value
    'bah'

By default the criterion values determine the search results.

    >>> browser.getLink('Bar Document Title')
    <Link text='Bar Document Title'
    url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
    >>> browser.getLink('Baz Event Title')
    Traceback (most recent call last):
    LinkNotFoundError

Also note that criteria that use a 'value' field as the primary search
value do not render the label for the value field as it would be
redundant.

    >>> 'Values</label>' in browser.contents
    False
    >>> 'crit__Subject_ListFormCriterion.value_help' in browser.contents
    False

Change the checked values and search

    >>> browser.getControl(
    ...     name='crit__Subject_ListFormCriterion.value:lines'
    ...     ).value = 'quux'
    >>> form = browser.getForm(name="formcriteria_search")
    >>> form.getControl(name='submit').click()

Now the default has been overriden by the submitted query.

    >>> browser.getLink('Bar Document Title')
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Baz Event Title')
    <Link text='Baz Event Title'
    url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

Remove the criterion.

    >>> foo_topic.deleteCriterion(
    ...     'crit__Subject_ListFormCriterion')

Selection Lists
---------------

Three criterion are provided for rendering selection lists on the
search form: SelectionFormCriterion, PortalTypeSelectionFormCriterion,
ReferenceSelectionFormCriterion.

Add a selection criterion for the subject/keywords.

    >>> foo_topic.addCriterion(
    ...     'Subject', 'SelectionFormCriterion')
    <SelectionFormCriterion at
    /plone/Members/test_user_1_/foo-topic-title/crit__Subject_SelectionFormCriterion>

Designate the criterion's field as a form field.

    >>> crit = foo_topic.getCriterion(
    ...     'Subject_SelectionFormCriterion')
    >>> crit.setFormFields(['value'])

The values set on the criterion are the default values selected on the
search form.

    >>> crit.setValue(['bah'])

When viewing the collection in a browser selections will be rendered
for the field with the default values selected.

    >>> browser.open(foo_topic.absolute_url())
    >>> browser.getControl('bah')
    <ItemControl
    name='crit__Subject_SelectionFormCriterion.value:list'
    type='select' optionValue='bah' selected=True>
    >>> browser.getControl('quux')
    <ItemControl
    name='crit__Subject_SelectionFormCriterion.value:list'
    type='select' optionValue='quux' selected=False>

By default the criterion values determine the search results.

    >>> browser.getLink('Bar Document Title')
    <Link text='Bar Document Title'
    url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
    >>> browser.getLink('Baz Event Title')
    Traceback (most recent call last):
    LinkNotFoundError

Change the selected values and search

    >>> browser.getControl('bah').selected = False
    >>> browser.getControl('quux').selected = True
    >>> form = browser.getForm(name="formcriteria_search")
    >>> form.getControl(name='submit').click()

Now the default has been overriden by the submitted query.

    >>> browser.getLink('Bar Document Title')
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Baz Event Title')
    <Link text='Baz Event Title'
    url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

Remove the criterion.

    >>> foo_topic.deleteCriterion(
    ...     'crit__Subject_SelectionFormCriterion')

Checkboxes
----------

Three criterion are provided for rendering checkboxes on the search
form: CheckboxFormCriterion, PortalTypeCheckboxFormCriterion,
ReferenceCheckboxFormCriterion.

Add a checkbox criterion for the portal type.

    >>> foo_topic.addCriterion(
    ...     'Type', 'PortalTypeCheckboxFormCriterion')
    <PortalTypeCheckboxFormCriterion at
    /plone/Members/test_user_1_/foo-topic-title/crit__Type_PortalTypeCheckboxFormCriterion>

Designate the criterion's field as a form field.

    >>> crit = foo_topic.getCriterion(
    ...     'Type_PortalTypeCheckboxFormCriterion')
    >>> crit.setFormFields(['value'])

The values set on the criterion are the default values checked on the
search form.

    >>> crit.setValue(['Page'])

When viewing the collection in a browser checkboxes will be rendered
for the field with the default values selected.

    >>> browser.open(foo_topic.absolute_url())
    >>> browser.getControl('Page')
    <ItemControl
    name='crit__Type_PortalTypeCheckboxFormCriterion.value:list'
    type='checkbox' optionValue='Page' selected=True>
    >>> browser.getControl('Event')
    <ItemControl
    name='crit__Type_PortalTypeCheckboxFormCriterion.value:list'
    type='checkbox' optionValue='Event' selected=False>

The portal type checkbox form criterion doesn't allow using "and" as a
query operator since it wouldn't make any sense.  As such the operator
field isn't rendered on the search form.

    >>> browser.getControl(
    ...     name=
    ...     'crit__Type_PortalTypeCheckboxFormCriterion.operator')
    Traceback (most recent call last):
    LookupError: name
    'crit__Type_PortalTypeCheckboxFormCriterion.operator'

By default the criterion values determine the search results.

    >>> browser.getLink('Bar Document Title')
    <Link text='Bar Document Title'
    url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
    >>> browser.getLink('Baz Event Title')
    Traceback (most recent call last):
    LinkNotFoundError

Change the checked values and search

    >>> browser.getControl('Page').selected = False
    >>> browser.getControl('Event').selected = True
    >>> form = browser.getForm(name="formcriteria_search")
    >>> form.getControl(name='submit').click()

Now the default has been overriden by the submitted query.

    >>> browser.getLink('Bar Document Title')
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Baz Event Title')
    <Link text='Baz Event Title'
    url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

Remove the criterion.

    >>> foo_topic.deleteCriterion(
    ...     'crit__Type_PortalTypeCheckboxFormCriterion')

Date Range
----------

A criterion is provided for rendering two calendar widgets on the
search form to specify two dates for a date range query.

Before a criterion requiring JavaScript or CSS helpers has been added,
the collection view does not include any such helpers.

    >>> 'calendar_stripped.js' in browser.contents
    False
    >>> 'calendar_en.js' in browser.contents
    False
    >>> 'calendar-system.css' in browser.contents
    False

Add a date range criterion for the effective date

    >>> foo_topic.addCriterion(
    ...     'effective', 'DateRangeFormCriterion')
    <DateRangeFormCriterion at
    /plone/Members/test_user_1_/foo-topic-title/crit__effective_DateRangeFormCriterion>

Designate the criterion's field as a form field.

    >>> criterion = foo_topic.getCriterion(
    ...     'effective_DateRangeFormCriterion')
    >>> criterion.setFormFields(['start', 'end'])

The values set on the criterion are the default values on the search
form.

    >>> from collective.formcriteria import testing
    >>> now = testing.formcriteria_layer.now
    >>> criterion.setStart(now-3)
    >>> criterion.setEnd(now-1)

When viewing the collection in a browser the date widgets will be rendered
for the index with the default values.

    >>> browser.open(foo_topic.absolute_url())

    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.start_year'
    ...     ).getControl('2009').selected
    True
    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.start_month'
    ...     ).getControl('January').selected
    True
    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.start_day'
    ...     ).getControl('12').selected
    True

    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.end_year'
    ...     ).getControl('2009').selected
    True
    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.end_month'
    ...     ).getControl('January').selected
    True
    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.end_day'
    ...     ).getControl('14').selected
    True

The widget helper JavaScript and CSS will also be included on the page
when the search form is present and fields require it.

    >>> 'calendar_stripped.js' in browser.contents
    True
    >>> 'calendar-en.js' in browser.contents
    True
    >>> 'calendar-system.css' in browser.contents
    True

Though the fields are required for editing criteria, they are not
marked as required on the search form.

    >>> '(Required)' in browser.contents
    False

By default the criterion values determine the search results.

    >>> browser.getLink('Bar Document Title')
    <Link text='Bar Document Title'
    url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
    >>> browser.getLink('Baz Event Title')
    Traceback (most recent call last):
    LinkNotFoundError

Change the date range and search

    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.start_day'
    ...     ).getControl('14').selected = True

    >>> browser.getControl(
    ...     name='crit__effective_DateRangeFormCriterion.end_day'
    ...     ).getControl('16').selected = True

    >>> form = browser.getForm(name="formcriteria_search")
    >>> form.getControl(name='submit').click()

Now the default has been overriden by the submitted query.

    >>> browser.getLink('Bar Document Title')
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Baz Event Title')
    <Link text='Baz Event Title'
    url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

Remove the criterion.

    >>> foo_topic.deleteCriterion(
    ...     'crit__effective_DateRangeFormCriterion')

Comma List
----------

An extension of the list criteria provides a text form input accepting
a comma separated list of keywords.

Add a list criterion for the subject/keywords.

    >>> foo_topic.addCriterion(
    ...     'Subject', 'CommaFormCriterion')
    <CommaFormCriterion at
    /plone/Members/test_user_1_/foo-topic-title/crit__Subject_CommaFormCriterion>

Designate the criterion's field as a form field.

    >>> crit = foo_topic.getCriterion('Subject_CommaFormCriterion')
    >>> crit.setValue(['foobar', 'bax'])
    >>> crit.setFormFields(['value'])

When viewing the collection in a browser lists will be rendered
for the field with the default values selected.

    >>> browser.open(foo_topic.absolute_url())
    >>> ctrl = browser.getControl(
    ...     name='crit__Subject_CommaFormCriterion.value')
    >>> ctrl
    <Control name='crit__Subject_CommaFormCriterion.value'
    type='text'>
    >>> ctrl.value
    'foobar, bax'

By default the criterion values determine the search results.

    >>> browser.getLink('Bar Document Title')
    Traceback (most recent call last):
    LinkNotFoundError
    >>> browser.getLink('Baz Event Title')
    Traceback (most recent call last):
    LinkNotFoundError

Also note that criteria that use a 'value' field as the primary search
value do not render the label for the value field as it would be
redundant.

    >>> 'Values</label>' in browser.contents
    False
    >>> 'crit__Subject_CommaFormCriterion.value_help' in browser.contents
    False

Change the checked values and search

    >>> browser.getControl(
    ...     name='crit__Subject_CommaFormCriterion.value'
    ...     ).value = 'bah, quux'
    >>> form = browser.getForm(name="formcriteria_search")
    >>> form.getControl(name='submit').click()

Now the default has been overriden by the submitted query.

    >>> browser.getLink('Bar Document Title')
    <Link text='Bar Document Title'
    url='http://nohost/plone/Members/test_user_1_/bar-document-title'>
    >>> browser.getLink('Baz Event Title')
    <Link text='Baz Event Title'
    url='http://nohost/plone/Members/test_user_1_/baz-event-title'>

The form reflects the submitted value.

    >>> browser.getControl(
    ...     name='crit__Subject_CommaFormCriterion.value'
    ...     ).value
    'bah, quux'

Remove the criterion.

    >>> foo_topic.deleteCriterion(
    ...     'crit__Subject_CommaFormCriterion')
