def test_sub_category_selection(self):
        url = "/g-cloud/search?q=&lot=cloud-software&otherfilter=somevalue&checkboxTreeExample=option+2.2"
        with self.app.test_request_context(url):
            selection = build_lots_and_categories_link_tree(
                self.framework,
                self.framework['lots'],
                self.category_filter_group,
                flask.request,
                flask.request.args,
                g9_builder,
                'services',
                'g-cloud-9',
                Href(flask.url_for('.search_services')),
                self.search_api_client
            )
            assert len(selection) == 5  # all -> software -> option2 -> option2.2; option2 as a parent category filter

            tree_root = selection[0]
            # check that only siblings of the selected sub-category are shown, and other categories
            # have been removed
            lot_filters = tree_root['children']
            selected_lot = next(f for f in lot_filters if f['selected'])
            category_filters = selected_lot['children']
            assert len(category_filters) == 1
            assert category_filters[0]['selected']
            sub_category_filters = category_filters[0]['children']
            assert len(sub_category_filters) == 2

            assert [f for f in selection if f.get('name') == 'parentCategory'] == [
                {'name': 'parentCategory', 'value': 'option 2'}]
    def test_build_lots_and_categories_link_tree_with_lot_and_filter_and_same_named_filter_in_tree(self):
        url = "/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2.1&parentCategory=option+2"

        self.category_filter_group['filters'] += [
            {
                'label': 'Option 7',
                'name': 'checkboxTreeExample',
                'id': 'checkboxTreeExample-option-7',
                'value': 'option 7',
                'children': [
                    {
                        'label': 'Option 2.1',
                        'name': 'checkboxTreeExample',
                        'id': 'checkboxTreeExample-option-2.1',
                        'value': 'option 2.1'
                    }, {
                        'label': 'Option 7.1',
                        'name': 'checkboxTreeExample',
                        'id': 'checkboxTreeExample-option-7.1',
                        'value': 'option 7.1'
                    }
                ]
            }
        ]
        with self.app.test_request_context(url):
            tree = build_lots_and_categories_link_tree(
                self.framework,
                self.framework['lots'],
                self.category_filter_group.copy(),
                flask.request,
                flask.request.args,
                g9_builder,
                'services',
                'g-cloud-9',
                Href(flask.url_for('.search_services')),
                self.search_api_client
            )

        assert tree == self.tree_with_cloud_software__option_2__option_2_1__selected
        assert(
            [(child['id'], child['selected']) for child in tree[0]['children'][0]['children'][0]['children']] ==
            [('checkboxTreeExample-option-2.1', True), ('checkboxTreeExample-option-2.2', False)]
        )

        tree_child_value_lists = [[child.get('id') for child in node.get('children', [])] for node in tree]
        tree_child_values = [item for sublist in tree_child_value_lists for item in sublist]

        assert 'checkboxTreeExample-option-7.1' not in tree_child_values
        assert tree_child_values.count('checkboxTreeExample-option-2.1') == 1
    def test_build_lots_and_categories_link_tree_with_no_categories_or_filters(self):
        url = "/g-cloud/search"
        with self.app.test_request_context(url):
            tree = build_lots_and_categories_link_tree(
                self.framework,
                self.framework['lots'],
                self.category_filter_group,
                flask.request,
                flask.request.args,
                g9_builder,
                'services',
                'g-cloud-9',
                Href(flask.url_for('.search_services')),
                self.search_api_client
            )

            assert tree == [
                {
                    'children': [
                        {
                            'label': 'Cloud hosting',
                            'link': '/g-cloud/search?lot=cloud-hosting',
                            'name': 'lot',
                            'service_count': 500,
                            'value': 'cloud-hosting'
                        },
                        {
                            'label': 'Cloud software',
                            'link': '/g-cloud/search?lot=cloud-software',
                            'name': 'lot',
                            'service_count': 500,
                            'value': 'cloud-software'
                        },
                        {
                            'label': 'Cloud support',
                            'link': '/g-cloud/search?lot=cloud-support',
                            'name': 'lot',
                            'service_count': 500,
                            'value': 'cloud-support'
                        }
                    ],
                    'label': 'All categories',
                    'link': '/g-cloud/search',
                    'selected': True
                }
            ]
    def test_top_level_category_selection(self):
        url = "/g-cloud/search?q=&lot=cloud-software&otherfilter=somevalue&filterExample=option+1" \
              "&checkboxTreeExample=option+1&page=2"
        with self.app.test_request_context(url):
            selection = build_lots_and_categories_link_tree(
                self.framework,
                self.framework['lots'],
                self.category_filter_group,
                flask.request,
                flask.request.args,
                g9_builder,
                'services',
                'g-cloud-9',
                Href(flask.url_for('.search_services')),
                self.search_api_client
            )
            assert len(selection) == 3  # all -> software -> option1

            tree_root = selection[0]
            assert tree_root.get('label') == 'All categories'

            lot_filters = tree_root['children']
            selected_lot = next(f for f in lot_filters if f['selected'])
            assert selected_lot.get('label') == 'Cloud software'
            # there should be a link to the lot without a category, as a category has been selected within it
            assert 'lot=cloud-software' in selected_lot['link']
            assert 'checkboxTreeExample' not in selected_lot['link']

            # check that we have links in place to a search with the relevant category filter applied,
            # except to the currently-selected category
            category_filters = selected_lot['children']
            assert 'link' not in category_filters[0]
            assert not category_filters[0].get('children')
            assert 'checkboxTreeExample=option+2' in category_filters[1]['link']
            sub_category_filters = category_filters[1]['children']
            assert 'checkboxTreeExample=option+2.1' in sub_category_filters[0]['link']
            assert 'checkboxTreeExample=option+2.2' in sub_category_filters[1]['link']

            # ...and also that each link preserves only the values of filters that are valid for the target...
            for f in itertools.chain(category_filters, sub_category_filters):
                if f.get('link'):
                    assert 'filterExample=option+1' in f['link']
                    assert 'otherfilter=somevalue' not in f['link']
                    assert 'page=' not in f['link']
    def test_build_lots_and_categories_link_tree_with_lot_and_filter_selected(self, url):
        with self.app.test_request_context(url):
            tree = build_lots_and_categories_link_tree(
                self.framework,
                self.framework['lots'],
                self.category_filter_group.copy(),
                flask.request,
                flask.request.args,
                g9_builder,
                'services',
                'g-cloud-9',
                Href(flask.url_for('.search_services')),
                self.search_api_client
            )

        assert tree == self.tree_with_cloud_software__option_2__option_2_1__selected
        # Assert, as per the url, that only our specified filter is 'selected' in the output
        assert(
            [(child['id'], child['selected']) for child in tree[0]['children'][0]['children'][0]['children']] ==
            [('checkboxTreeExample-option-2.1', True), ('checkboxTreeExample-option-2.2', False)]
        )
    def test_build_lots_and_categories_link_tree_with_lot(self):
        url = "/g-cloud/search?lot=cloud-software"
        with self.app.test_request_context(url):
            tree = build_lots_and_categories_link_tree(
                self.framework,
                self.framework['lots'],
                self.category_filter_group,
                flask.request,
                flask.request.args,
                g9_builder,
                'services',
                'g-cloud-9',
                Href(flask.url_for('.search_services')),
                self.search_api_client
            )

            assert tree == [
                {
                    'label': 'All categories',
                    'link': '/g-cloud/search',
                    'selected': True,
                    'children': [
                        {
                            'label': 'Cloud software',
                            'name': 'lot',
                            'selected': True,
                            'service_count': 500,
                            'value': 'cloud-software',
                            'children': [
                                {
                                    'id': 'checkboxTreeExample-option-1',
                                    'label': 'Option 1',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+1',
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option 1'
                                },
                                {
                                    'id': 'checkboxTreeExample-option-2',
                                    'label': 'Option 2',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2',
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option 2',
                                    'children': [
                                        {
                                            'id': 'checkboxTreeExample-option-2.1',
                                            'label': 'Option 2.1',
                                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2.1&parentCategory=option+2',  # NOQA
                                            'name': 'checkboxTreeExample',
                                            'selected': False,
                                            'service_count': 0,
                                            'value': 'option 2.1'
                                        },
                                        {
                                            'id': 'checkboxTreeExample-option-2.2',
                                            'label': 'Option 2.2',
                                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2.2&parentCategory=option+2',  # NOQA
                                            'name': 'checkboxTreeExample',
                                            'selected': False,
                                            'service_count': 0,
                                            'value': 'option 2.2'
                                        }
                                    ],
                                },
                                {
                                    'id': 'checkboxTreeExample-option-3-with-comma',
                                    'label': 'Option 3, with comma',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+3+with+comma',  # NOQA
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option 3 with comma'
                                },
                                {
                                    'id': 'checkboxTreeExample-option_4_value',
                                    'label': 'Option 4 has a value',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option_4_value',
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option_4_value'
                                },
                                {
                                    'id': 'checkboxTreeExample-option_5_value',
                                    'label': 'Option 5 filter label',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option_5_value',
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option_5_value'
                                },
                                {
                                    'id': 'checkboxTreeExample-option-6',
                                    'label': 'Option 6 filter label',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+6',
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option 6'
                                }
                            ],
                        }
                    ],
                },
                {
                    'label': 'Cloud software',
                    'name': 'lot',
                    'selected': True,
                    'service_count': 500,
                    'value': 'cloud-software',
                    'children': [
                        {
                            'id': 'checkboxTreeExample-option-1',
                            'label': 'Option 1',
                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+1',
                            'name': 'checkboxTreeExample',
                            'selected': False,
                            'service_count': 0,
                            'value': 'option 1'
                        },
                        {
                            'id': 'checkboxTreeExample-option-2',
                            'label': 'Option 2',
                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2',
                            'name': 'checkboxTreeExample',
                            'selected': False,
                            'service_count': 0,
                            'value': 'option 2',
                            'children': [
                                {
                                    'id': 'checkboxTreeExample-option-2.1',
                                    'label': 'Option 2.1',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2.1&parentCategory=option+2',  # NOQA
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option 2.1'
                                },
                                {
                                    'id': 'checkboxTreeExample-option-2.2',
                                    'label': 'Option 2.2',
                                    'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+2.2&parentCategory=option+2',  # NOQA
                                    'name': 'checkboxTreeExample',
                                    'selected': False,
                                    'service_count': 0,
                                    'value': 'option 2.2'
                                }
                            ],
                        },
                        {
                            'id': 'checkboxTreeExample-option-3-with-comma',
                            'label': 'Option 3, with comma',
                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+3+with+comma',
                            'name': 'checkboxTreeExample',
                            'selected': False,
                            'service_count': 0,
                            'value': 'option 3 with comma'
                        },
                        {
                            'id': 'checkboxTreeExample-option_4_value',
                            'label': 'Option 4 has a value',
                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option_4_value',
                            'name': 'checkboxTreeExample',
                            'selected': False,
                            'service_count': 0,
                            'value': 'option_4_value'
                        },
                        {
                            'id': 'checkboxTreeExample-option_5_value',
                            'label': 'Option 5 filter label',
                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option_5_value',
                            'name': 'checkboxTreeExample',
                            'selected': False,
                            'service_count': 0,
                            'value': 'option_5_value'
                        },
                        {
                            'id': 'checkboxTreeExample-option-6',
                            'label': 'Option 6 filter label',
                            'link': '/g-cloud/search?lot=cloud-software&checkboxTreeExample=option+6',
                            'name': 'checkboxTreeExample',
                            'selected': False,
                            'service_count': 0,
                            'value': 'option 6'
                        }
                    ],
                }
            ]