class TestLandCoverService(TestWithFullModelRun):
    def setUp(self):
        dap_client_factory = DapClientFactory()
        dap_client_factory.get_land_cover_dap_client = self._mock_get_land_cover_dap_client
        dap_client_factory.get_soil_properties_dap_client = self._mock_get_soil_properties_dap_client
        self.land_cover_service = LandCoverService(dap_client_factory=dap_client_factory)
        self.model_run_service = ModelRunService()
        self.dataset_service = DatasetService()
        self.parameter_service = ParameterService()
        self.clean_database()
        self.user = self.login()
        self.create_model_run_ready_for_submit()

    @staticmethod
    def _mock_get_land_cover_dap_client(url, key):
        return MockLandCoverDapClient(url, key)

    @staticmethod
    def _mock_get_soil_properties_dap_client(url):
        return MockSoilPropertiesDapClient(url)

    def test_GIVEN_land_cover_regions_exist_WHEN_get_land_cover_region_by_id_THEN_land_cover_region_returned(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        id = land_cover_region.id

        returned_region = self.land_cover_service.get_land_cover_region_by_id(id)
        assert_that(returned_region.id, is_(id))
        assert_that(returned_region.name, is_("Wales"))

    def test_GIVEN_land_cover_categories_WHEN_get_land_cover_region_THEN_returned_region_has_category_loaded(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        id = land_cover_region.id

        with session_scope() as session:
            land_cover_cat = LandCoverRegionCategory()
            land_cover_cat.name = "River Catchments"
            land_cover_cat.driving_dataset_id = model_run.driving_dataset_id
            session.add(land_cover_cat)

        returned_region = self.land_cover_service.get_land_cover_region_by_id(id)
        assert_that(returned_region.category.name, is_("Countries"))

    def test_GIVEN_land_cover_values_WHEN_get_land_cover_values_THEN_land_cover_values_returned(self):
        lc_values = self.land_cover_service.get_land_cover_values(None)
        assert_that(len(lc_values), is_(9))
        names = [lc_value.name for lc_value in lc_values]
        assert 'Urban' in names
        assert constants.FRACTIONAL_ICE_NAME in names

    def test_GIVEN_return_no_ice_WHEN_get_land_cover_values_THEN_land_cover_values_returned(self):
        lc_values = self.land_cover_service.get_land_cover_values(None, return_ice=False)
        assert_that(len(lc_values), is_(8))
        names = [lc_value.name for lc_value in lc_values]
        assert 'Urban' in names
        assert constants.FRACTIONAL_ICE_NAME not in names

    def test_GIVEN_multiple_land_cover_categories_WHEN_get_categories_THEN_correct_categories_returned(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        datasets = self.dataset_service.get_driving_datasets(self.user)

        with session_scope() as session:
            cat1 = LandCoverRegionCategory()
            cat1.name = "Countries"
            cat1.driving_dataset_id = model_run.driving_dataset_id

            region1 = LandCoverRegion()
            region1.mask_file = "filepath"
            region1.name = "Wales"
            region1.category = cat1

            cat2 = LandCoverRegionCategory()
            cat2.name = "Rivers"
            cat2.driving_dataset_id = datasets[1].id

            region2 = LandCoverRegion()
            region2.mask_file = "filepath2"
            region2.name = "Thames"
            region2.category = cat2

            session.add_all([region1, region2])

        categories = self.land_cover_service.get_land_cover_categories(model_run.driving_dataset_id)
        assert_that(len(categories), is_(1))
        assert_that(categories[0].name, is_("Countries"))

    def test_GIVEN_categories_have_land_cover_regions_WHEN_get_categories_THEN_category_has_regions_loaded(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        with session_scope() as session:
            cat1 = LandCoverRegionCategory()
            cat1.name = "Countries"
            cat1.driving_dataset_id = model_run.driving_dataset_id

            region1 = LandCoverRegion()
            region1.mask_file = "filepath"
            region1.name = "Wales"
            region1.category = cat1

            cat2 = LandCoverRegionCategory()
            cat2.name = "Rivers"
            cat2.driving_dataset_id = model_run.driving_dataset_id

            region2 = LandCoverRegion()
            region2.mask_file = "filepath2"
            region2.name = "Thames"
            region2.category = cat2

            session.add_all([region1, region2])

        categories = self.land_cover_service.get_land_cover_categories(model_run.driving_dataset_id)
        assert_that(len(categories[0].regions), is_(1))
        assert_that(categories[0].regions[0].name, is_("Wales"))

    def test_GIVEN_land_cover_actions_WHEN_save_land_cover_actions_THEN_land_cover_actions_saved(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        self.add_land_cover_actions(land_cover_region, model_run, [(1, 1), (2, 3)], self.land_cover_service)

        with session_scope() as session:
            model_run = self.model_run_service._get_model_run_being_created(session, self.user)
        actions = model_run.land_cover_actions
        assert_that(len(actions), is_(2))

    def test_GIVEN_existing_land_cover_actions_WHEN_save_land_cover_actions_THEN_land_cover_actions_overwritten(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        self.add_land_cover_actions(land_cover_region, model_run, [(1, 1), (2, 3)], self.land_cover_service)

        self.add_land_cover_actions(land_cover_region, model_run, [(2, 4)], self.land_cover_service)

        with session_scope() as session:
            model_run = self.model_run_service._get_model_run_being_created(session, self.user)
        actions = model_run.land_cover_actions
        assert_that(len(actions), is_(1))
        assert_that(actions[0].value_id, is_(2))
        assert_that(actions[0].order, is_(4))

    def test_GIVEN_no_land_cover_actions_WHEN_save_land_cover_actions_THEN_all_land_cover_actions_removed(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        self.add_land_cover_actions(land_cover_region, model_run, [(1, 1), (2, 3)], self.land_cover_service)

        self.add_land_cover_actions(land_cover_region, model_run, [], self.land_cover_service)

        with session_scope() as session:
            model_run = self.model_run_service._get_model_run_being_created(session, self.user)
        actions = model_run.land_cover_actions
        assert_that(len(actions), is_(0))

    def test_GIVEN_land_cover_actions_saved_on_model_run_WHEN_get_land_cover_actions_THEN_actions_returned(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        self.add_land_cover_actions(land_cover_region, model_run, [(1, 1), (2, 3)], self.land_cover_service)

        actions = self.land_cover_service.get_land_cover_actions_for_model(model_run)
        assert_that(len(actions), is_(2))
        assert_that(actions[0].value_id, is_(1))
        assert_that(actions[0].order, is_(1))
        assert_that(actions[1].value_id, is_(2))
        assert_that(actions[1].order, is_(3))

    def test_GIVEN_land_cover_actions_saved_WHEN_get_actions_THEN_actions_have_regions_and_categories_loaded(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        self.add_land_cover_actions(land_cover_region, model_run, [(1, 1)], self.land_cover_service)

        action = self.land_cover_service.get_land_cover_actions_for_model(model_run)[0]
        assert_that(action.region.name, is_("Wales"))
        assert_that(action.region.category.name, is_("Countries"))

    def test_GIVEN_land_cover_actions_saved_WHEN_get_actions_THEN_actions_have_values_loaded(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)

        land_cover_region = self.add_land_cover_region(model_run)
        self.add_land_cover_actions(land_cover_region, model_run, [(1, 1)], self.land_cover_service)

        action = self.land_cover_service.get_land_cover_actions_for_model(model_run)[0]
        assert_that(action.value.name, is_("Broad-leaved Tree"))

    def test_GIVEN_fractional_string_WHEN_save_fractional_land_cover_for_model_THEN_fractional_cover_saved(self):
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        assert_that(model_run.land_cover_frac, is_(None))

        fractional_string = "0\t0\t0\t0\t0\t0\t0\t0\t1"
        self.land_cover_service.save_fractional_land_cover_for_model(model_run, fractional_string)

        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        assert_that(model_run.land_cover_frac, is_(fractional_string))

    def test_GIVEN_user_uploaded_driving_data_WHEN_get_default_fractional_cover_THEN_fractional_cover_returned(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_with_user_uploaded_driving_data()

        model_run = self.set_model_run_latlon(self.user, 70, 0)

        fractional_vals = self.land_cover_service.get_default_fractional_cover(model_run, self.user)
        assert_that(fractional_vals, is_([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]))

    def test_GIVEN_two_matching_datasets_WHEN_get_default_cover_THEN_higher_priority_fractional_cover_returned(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_with_user_uploaded_driving_data()

        model_run = self.set_model_run_latlon(self.user, 0, 0)
        fractional_vals = self.land_cover_service.get_default_fractional_cover(model_run, self.user)
        assert_that(fractional_vals, is_([0.02, 0.11, 0.02, 0.05, 0.35, 0.19, 0.22, 0.04, 0.0]))

    def test_GIVEN_no_matching_datasets_WHEN_get_default_cover_THEN_zeros_returned(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_with_user_uploaded_driving_data()

        model_run = self.set_model_run_latlon(self.user, 88, 0)
        fractional_vals = self.land_cover_service.get_default_fractional_cover(model_run, self.user)
        assert_that(fractional_vals, is_([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]))

    def test_GIVEN_thredds_not_working_WHEN_get_default_cover_THEN_zeros_returned(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_with_user_uploaded_driving_data()

        def _get_broken_dap_client(url, key):
            return MockLandCoverDapClient("broken_url", key)

        dap_client_factory = DapClientFactory()
        dap_client_factory.get_land_cover_dap_client = _get_broken_dap_client
        self.land_cover_service = LandCoverService(dap_client_factory=dap_client_factory)

        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        fractional_vals = self.land_cover_service.get_default_fractional_cover(model_run, self.user)
        assert_that(fractional_vals, is_([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]))

    def test_GIVEN_using_provided_driving_data_WHEN_get_default_fractional_cover_THEN_fractional_cover_returned(self):
        self.clean_database()
        self.user = self.login()
        self.create_alternate_model_run()

        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        fractional_vals = self.land_cover_service.get_default_fractional_cover(model_run, self.user)
        assert_that(fractional_vals, is_([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]))

    def test_GIVEN_multicell_model_run_WHEN_get_default_fractional_cover_THEN_ServiceException_raised(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_ready_for_submit()

        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        with self.assertRaises(ServiceException):
            self.land_cover_service.get_default_fractional_cover(model_run, self.user)

    def test_GIVEN_user_uploaded_driving_data_WHEN_set_default_soil_properties_THEN_soil_cover_set(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_with_user_uploaded_driving_data()

        model_run = self.set_model_run_latlon(self.user, 51, 0)

        self.land_cover_service.save_default_soil_properties(model_run, self.user)

        #self._land_cover_service.dap_client_factory.get_soil_properties_dap_client = _mock_get_soil_props_client
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        nvars = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_NVARS)
        var = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_VAR, is_list=True)
        use_file = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_USE_FILE, is_list=True)
        const_val = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_CONST_VAL, is_list=True)

        assert_that(nvars, is_(9))
        assert_that(var, is_(['b', 'sathh', 'satcon', 'sm_sat', 'sm_crit', 'sm_wilt', 'hcap', 'hcon', 'albsoil']))
        assert_that(use_file, is_(9 * [False]))
        assert_that(const_val, is_([0.9, 0.0, 0.0, 50.0, 275.0, 278.0, 10.0, 0.0, 0.5]))

    def test_GIVEN_no_appropriate_driving_data_WHEN_set_default_soil_properties_THEN_values_not_set(self):
        self.clean_database()
        self.user = self.login()
        self.create_model_run_with_user_uploaded_driving_data()

        model_run = self.set_model_run_latlon(self.user, 90, 0)

        self.land_cover_service.save_default_soil_properties(model_run, self.user)

        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        nvars = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_NVARS)
        var = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_VAR)
        use_file = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_USE_FILE, is_list=True)
        const_val = model_run.get_python_parameter_value(constants.JULES_PARAM_SOIL_PROPS_CONST_VAL, is_list=True)

        assert_that(nvars, is_(None))
        assert_that(var, is_(None))
        assert_that(use_file, is_(None))
        assert_that(const_val, is_(None))

    def set_model_run_latlon(self, user, lat, lon):
        params_to_save = [[constants.JULES_PARAM_POINTS_FILE, [lat, lon]]]
        params_to_del = constants.JULES_PARAM_POINTS_FILE
        self.parameter_service.save_new_parameters(params_to_save, params_to_del, user.id)

        return self.model_run_service.get_model_being_created_with_non_default_parameter_values(user)
class TestModelRunLandCoverSingleCell(TestController):
    def setUp(self):
        self.model_run_service = ModelRunService()
        self.land_cover_service = LandCoverService()

    def set_up_single_cell_model_run(self):
        self.clean_database()
        self.user = self.login()
        self.create_two_driving_datasets()
        user_upload_id = DatasetService().get_id_for_user_upload_driving_dataset()
        with session_scope(Session) as session:
            self.model_run = ModelRun()
            self.model_run.name = "MR1"
            self.model_run.status = self._status(MODEL_RUN_STATUS_CREATED)
            self.model_run.driving_dataset_id = user_upload_id
            self.model_run.user = self.user
            self.model_run.driving_data_lat = 51.75
            self.model_run.driving_data_lon = -0.25
            self.model_run.driving_data_rows = 248

            param1 = self.model_run_service.get_parameter_by_constant(JULES_PARAM_DRIVE_INTERP)
            pv1 = ParameterValue()
            pv1.parameter_id = param1.id
            pv1.set_value_from_python(8 * ['nf'])

            param2 = self.model_run_service.get_parameter_by_constant(JULES_PARAM_DRIVE_DATA_PERIOD)
            pv2 = ParameterValue()
            pv2.parameter_id = param2.id
            pv2.set_value_from_python(60 * 60)

            param3 = self.model_run_service.get_parameter_by_constant(JULES_PARAM_DRIVE_DATA_START)
            pv3 = ParameterValue()
            pv3.parameter_id = param3.id
            pv3.value = "'1901-01-01 00:00:00'"

            param4 = self.model_run_service.get_parameter_by_constant(JULES_PARAM_DRIVE_DATA_END)
            pv4 = ParameterValue()
            pv4.parameter_id = param4.id
            pv4.value = "'1901-01-31 21:00:00'"

            param5 = self.model_run_service.get_parameter_by_constant(JULES_PARAM_LATLON_REGION)
            pv5 = ParameterValue()
            pv5.parameter_id = param5.id
            pv5.value = ".false."

            param6 = self.model_run_service.get_parameter_by_constant(JULES_PARAM_POINTS_FILE)
            pv6 = ParameterValue()
            pv6.parameter_id = param6.id
            pv6.value = "51.75 -0.25"

            self.model_run.parameter_values = [pv1, pv2, pv3, pv4, pv5, pv6]
            session.add(self.model_run)

    def test_GIVEN_single_cell_run_WHEN_page_get_THEN_fractional_cover_page_shown(self):
        self.set_up_single_cell_model_run()
        response = self.app.get(url(controller='model_run', action='land_cover'))
        assert_that(response.normal_body, contains_string("Fractional Land Cover"))

    def test_GIVEN_land_cover_values_WHEN_page_get_THEN_land_cover_type_names_rendered(self):
        self.set_up_single_cell_model_run()
        response = self.app.get(url(controller='model_run', action='land_cover'))
        lc_vals = self.land_cover_service.get_land_cover_values(None)
        del lc_vals[-1]  # Remove the ice
        names = [str(val.name) for val in lc_vals]
        assert_that(response.normal_body, string_contains_in_order(*names))

    def test_GIVEN_available_driving_datasets_WHEN_page_get_THEN_default_fractional_cover_rendered(self):
        self.set_up_single_cell_model_run()
        response = self.app.get(url(controller='model_run', action='land_cover'))
        lc_vals = self.land_cover_service.get_land_cover_values(None)
        del lc_vals[-1]  # Remove the ice
        string_names_values = []
        for val in lc_vals:
            string_names_values.append(str(val.name))
            string_names_values.append('12.5')
        assert_that(response.normal_body, string_contains_in_order(*string_names_values))

    def test_GIVEN_saved_land_cover_frac_WHEN_page_get_THEN_saved_values_rendered(self):
        self.set_up_single_cell_model_run()
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        frac_string = "0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.72 0.0"
        self.land_cover_service.save_fractional_land_cover_for_model(model_run, frac_string)

        response = self.app.get(url(controller='model_run', action='land_cover'))

        lc_vals = self.land_cover_service.get_land_cover_values(None)
        del lc_vals[-1]  # Remove the ice

        string_names_values = []
        for i in range(len(lc_vals)):
            string_names_values.append(str(lc_vals[i].name))
            string_names_values.append(str(100 * float(frac_string.split()[i])))
        assert_that(response.normal_body, string_contains_in_order(*string_names_values))

    def test_GIVEN_saved_land_cover_with_too_few_types_WHEN_page_get_THEN_available_values_rendered(self):
        self.set_up_single_cell_model_run()
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        frac_string = "0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.72"
        self.land_cover_service.save_fractional_land_cover_for_model(model_run, frac_string)

        response = self.app.get(url(controller='model_run', action='land_cover'))

        lc_vals = self.land_cover_service.get_land_cover_values(None)
        del lc_vals[-1]  # Remove the ice

        string_names_values = []
        for i in range(len(lc_vals)):
            string_names_values.append(str(lc_vals[i].name))
            string_names_values.append(str(100 * float(frac_string.split()[i])))
        assert_that(response.normal_body, string_contains_in_order(*string_names_values))

    def test_GIVEN_saved_land_cover_with_too_many_types_WHEN_page_get_THEN_some_values_rendered(self):
        self.set_up_single_cell_model_run()
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        frac_string = "0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.72 0.0 0.0"
        self.land_cover_service.save_fractional_land_cover_for_model(model_run, frac_string)

        response = self.app.get(url(controller='model_run', action='land_cover'))

        lc_vals = self.land_cover_service.get_land_cover_values(None)
        del lc_vals[-1]  # Remove the ice

        string_names_values = []
        for i in range(len(lc_vals)):
            string_names_values.append(str(lc_vals[i].name))
            string_names_values.append(str(100 * float(frac_string.split()[i])))
        assert_that(response.normal_body, string_contains_in_order(*string_names_values))

    def test_GIVEN_valid_fractional_cover_WHEN_post_THEN_values_saved(self):
        self.set_up_single_cell_model_run()
        self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_value_1': u'20',
                    'land_cover_value_2': u'25',
                    'land_cover_value_3': u'5',
                    'land_cover_value_4': u'10',
                    'land_cover_value_5': u'10',
                    'land_cover_value_6': u'5',
                    'land_cover_value_7': u'10',
                    'land_cover_value_8': u'15'})
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        assert_that(model_run.land_cover_frac, is_("0.2\t0.25\t0.05\t0.1\t0.1\t0.05\t0.1\t0.15\t0"))

    def test_GIVEN_valid_fractional_cover_WHEN_post_THEN_default_soil_props_saved(self):
        self.set_up_single_cell_model_run()
        self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_value_1': u'20',
                    'land_cover_value_2': u'25',
                    'land_cover_value_3': u'5',
                    'land_cover_value_4': u'10',
                    'land_cover_value_5': u'10',
                    'land_cover_value_6': u'5',
                    'land_cover_value_7': u'10',
                    'land_cover_value_8': u'15'})
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        soil_props = model_run.get_python_parameter_value(JULES_PARAM_SOIL_PROPS_CONST_VAL, is_list=True)
        assert_that(soil_props, is_([0.9, 0.0, 0.0, 50.0, 275.0, 300.0, 10.0, 0.0, 0.5]))

    def test_GIVEN_ice_fractional_cover_WHEN_post_THEN_values_saved(self):
        self.set_up_single_cell_model_run()
        self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_ice': u'1'})
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        assert_that(model_run.land_cover_frac, is_("0\t0\t0\t0\t0\t0\t0\t0\t1"))

    def test_GIVEN_valid_fractional_cover_WHEN_post_THEN_moved_to_next_page(self):
        self.set_up_single_cell_model_run()
        response = self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_value_1': u'20',
                    'land_cover_value_2': u'25',
                    'land_cover_value_3': u'5',
                    'land_cover_value_4': u'10',
                    'land_cover_value_5': u'10',
                    'land_cover_value_6': u'5',
                    'land_cover_value_7': u'10',
                    'land_cover_value_8': u'15'})
        assert_that(response.status_code, is_(302), "Response is redirect")
        assert_that(urlparse(response.response.location).path,
                    is_(url(controller='model_run', action='output')), "url")

    def test_GIVEN_fractional_cover_saved_WHEN_reset_THEN_cover_reset(self):
        self.set_up_single_cell_model_run()
        self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_value_1': u'20',
                    'land_cover_value_2': u'25',
                    'land_cover_value_3': u'5',
                    'land_cover_value_4': u'10',
                    'land_cover_value_5': u'10',
                    'land_cover_value_6': u'5',
                    'land_cover_value_7': u'10',
                    'land_cover_value_8': u'15'})
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        initial_cover = model_run.land_cover_frac
        assert initial_cover is not None
        response = self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'reset_fractional_cover': u'1'})
        assert_that(response.status_code, is_(302), "Response is redirect")
        assert_that(urlparse(response.response.location).path,
                    is_(url(controller='model_run', action='land_cover')), "url")
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        final_cover = model_run.land_cover_frac
        assert_that(final_cover, is_(None))

    def test_GIVEN_values_dont_add_up_WHEN_post_THEN_errors_returned_and_values_not_saved(self):
        self.set_up_single_cell_model_run()
        response = self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_value_1': u'40',
                    'land_cover_value_2': u'25',
                    'land_cover_value_3': u'5',
                    'land_cover_value_4': u'10',
                    'land_cover_value_5': u'10',
                    'land_cover_value_6': u'5',
                    'land_cover_value_7': u'10',
                    'land_cover_value_8': u'15'})
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        assert_that(model_run.land_cover_frac, is_(None))
        assert_that(response.normal_body, contains_string("The sum of all the land cover fractions must be 100%"))
        assert_that(response.normal_body, contains_string("Fractional Land Cover"))

    def test_GIVEN_values_dont_add_up_WHEN_post_THEN_values_still_present_on_page(self):
        self.set_up_single_cell_model_run()
        response = self.app.post(
            url(controller='model_run', action='land_cover'),
            params={'submit': u'Next',
                    'fractional_cover': u'1',
                    'land_cover_value_1': u'40',
                    'land_cover_value_2': u'25',
                    'land_cover_value_3': u'5',
                    'land_cover_value_4': u'10',
                    'land_cover_value_5': u'10',
                    'land_cover_value_6': u'5',
                    'land_cover_value_7': u'10',
                    'land_cover_value_8': u'15'})

        lc_vals = self.land_cover_service.get_land_cover_values(None)
        del lc_vals[-1]  # Remove the ice
        frac_vals = ['40', '25', '5', '10', '10', '5', '10', '15']
        string_names_values = []
        for i in range(len(lc_vals)):
            string_names_values.append(str(lc_vals[i].name))
            string_names_values.append(str(frac_vals[i]))
        assert_that(response.normal_body, string_contains_in_order(*string_names_values))

    def test_GIVEN_no_extents_selected_WHEN_page_get_THEN_redirect(self):
        self.set_up_single_cell_model_run()
        param = self.model_run_service.get_parameter_by_constant(JULES_PARAM_POINTS_FILE)
        model_run = self.model_run_service.get_model_being_created_with_non_default_parameter_values(self.user)
        with session_scope() as session:
            session.query(ParameterValue) \
                .filter(ParameterValue.parameter_id == param.id) \
                .filter(ParameterValue.model_run_id == model_run.id) \
                .delete()

        response = self.app.get(url(controller='model_run', action='land_cover'))
        assert_that(response.status_code, is_(302), "Response is redirect")
        assert_that(urlparse(response.response.location).path,
                    is_(url(controller='model_run', action='extents')), "url")