def test_new_measure_version_not_created_if_script_thinks_it_has_already_created_one(
        self, single_use_app, db_session
    ):
        user = UserFactory(user_type=TypeOfUser.ADMIN_USER, email="*****@*****.**")
        mv = MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.0",
            title="my measure",
            external_edit_summary=None,
            measure__id=1,
            dimensions__guid="dimension-guid-1.0",
            dimensions__title="my dimension",
            uploads=[],
        )
        MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.1",
            title="my measure",
            external_edit_summary=STANDARD_EDIT_SUMMARY,
            measure=mv.measure,
            dimensions__guid="dimension-guid-1.1",
            dimensions__title="my new dimension",
            uploads=[],
        )
        MeasureVersionWithDimensionFactory(
            status="DRAFT",
            version="2.0",
            title="my measure",
            external_edit_summary=None,
            measure=mv.measure,
            dimensions__guid="dimension-guid-2.0",
            dimensions__title="my dimension",
            uploads=[],
        )
        dimension_rows = [["dimension-guid-1.0", "my measure", "my dimension", "my new dimension"]]

        error_count = import_dimension_titles(user_email=user.email, app=single_use_app, dimension_rows=dimension_rows)

        measure = Measure.query.get(1)

        assert error_count == 0
        assert len(measure.versions) == 3
        assert measure.versions[0].version == "2.0"
        assert measure.versions[0].status == "DRAFT"
        assert measure.versions[0].dimensions[0].title == "my dimension"
        assert measure.versions[0].external_edit_summary is None

        assert measure.versions[1].version == "1.1"
        assert measure.versions[1].status == "APPROVED"
        assert measure.versions[1].dimensions[0].title == "my new dimension"
        assert measure.versions[1].external_edit_summary == STANDARD_EDIT_SUMMARY

        assert measure.versions[2].version == "1.0"
        assert measure.versions[2].dimensions[0].title == "my dimension"
    def test_script_creates_new_measure_version_and_updates_dimension_title(self, single_use_app):
        user = UserFactory(user_type=TypeOfUser.ADMIN_USER, email="*****@*****.**")
        MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.0",
            title="my measure",
            measure__id=1,
            dimensions__guid="dimension-guid",
            dimensions__title="my dimension",
            uploads=[],
        )
        dimension_rows = [["dimension-guid", "my measure", "my dimension", "my new dimension"]]

        import_dimension_titles(user_email=user.email, app=single_use_app, dimension_rows=dimension_rows)

        measure = Measure.query.get(1)

        assert len(measure.versions) == 2
        assert measure.versions[0].version == "1.1"
        assert measure.versions[0].status == "APPROVED"
        assert measure.versions[0].dimensions[0].title == "my new dimension"
        assert measure.versions[0].external_edit_summary == STANDARD_EDIT_SUMMARY
        assert measure.versions[0].created_by == "*****@*****.**"
        assert (
            datetime.utcnow() - measure.versions[0].created_at
        ).seconds < 5, "Creation time should be within the last 5 seconds"
        assert measure.versions[0].update_corrects_data_mistake is False
        assert measure.versions[0].published_by == "*****@*****.**"
        assert measure.versions[0].published_at is None
        assert measure.versions[0].last_updated_by == "*****@*****.**"

        assert measure.versions[1].version == "1.0"
        assert measure.versions[1].dimensions[0].title == "my dimension"
    def test_measure_page_download_measure_source_data_link_correct(
            self, test_app_client, logged_in_rdu_user, static_mode,
            expected_url):
        from tests.test_data.chart_and_table import chart, simple_table

        MeasureVersionWithDimensionFactory(
            status="DRAFT",
            version="1.0",
            measure__subtopics__topic__slug="topic",
            measure__subtopics__slug="subtopic",
            measure__slug="measure",
            dimensions__guid="dimension-guid",
            dimensions__dimension_chart__chart_object=chart,
            dimensions__dimension_table__table_object=simple_table(),
            uploads__guid="test-download",
            uploads__title="Test measure page data",
            uploads__file_name="test-measure-page-data.csv",
        )
        resp = test_app_client.get("/topic/subtopic/measure/latest",
                                   follow_redirects=False)
        page = BeautifulSoup(resp.data.decode("utf-8"), "html.parser")
        data_links = page.findAll(
            "a",
            href=True,
            text=re.compile(r"Test measure page data\s+-\s+Spreadsheet"))
        assert len(data_links) == 1
        assert data_links[0].attrs["href"] == expected_url
def test_update_dimension_does_not_call_update_dimension_classification_by_default():
    measure_version = MeasureVersionWithDimensionFactory(
        dimensions__title="test-dimension",
        dimensions__time_period="time_period",
        dimensions__summary="summary",
        dimensions__classification_links__includes_parents=False,
        dimensions__classification_links__includes_all=True,
        dimensions__classification_links__includes_unknown=True,
        dimensions__classification_links__classification__id="my-classification",
    )

    dimension = measure_version.dimensions[0]
    assert measure_version.dimensions.count() == 1
    assert dimension.title == "test-dimension"
    assert dimension.time_period == "time_period"
    assert dimension.summary == "summary"
    assert dimension.dimension_classification.classification_id == "my-classification"
    assert dimension.dimension_classification.includes_parents is False
    assert dimension.dimension_classification.includes_all is True
    assert dimension.dimension_classification.includes_unknown is True

    # When update_dimension() is called without explicitly telling it to reclassify the dimension
    update_data = {"title": "updated-title", "time_period": "updated_time_period"}
    dimension_service.update_dimension(dimension, update_data)

    # Then the dimension classification should not have been overwritten/deleted
    assert dimension.title == "updated-title"
    assert dimension.time_period == "updated_time_period"
    assert dimension.summary == "summary"
    assert dimension.dimension_classification.classification_id == "my-classification"
    assert dimension.dimension_classification.includes_parents is False
    assert dimension.dimension_classification.includes_all is True
    assert dimension.dimension_classification.includes_unknown is True
def test_dept_user_should_not_be_able_to_delete_dimension_if_page_not_shared(
        test_app_client, logged_in_dept_user):
    measure_version = MeasureVersionWithDimensionFactory(
        measure__shared_with=[])

    response = test_app_client.get(
        url_for(
            "cms.edit_measure_version",
            topic_slug=measure_version.measure.subtopic.topic.slug,
            subtopic_slug=measure_version.measure.subtopic.slug,
            measure_slug=measure_version.measure.slug,
            version=measure_version.version,
        ))

    assert response.status_code == 403

    response = test_app_client.post(
        url_for(
            "cms.delete_dimension",
            topic_slug=measure_version.measure.subtopic.topic.slug,
            subtopic_slug=measure_version.measure.subtopic.slug,
            measure_slug=measure_version.measure.slug,
            version=measure_version.version,
            dimension_guid=measure_version.dimensions[0].guid,
        ))

    assert response.status_code == 403
    def test_create_new_version_of_page_duplicates_dimension_categorisations(
            self):
        user = UserFactory(user_type=TypeOfUser.RDU_USER)
        # given an existing page with a dimension with known classification
        measure_version = MeasureVersionWithDimensionFactory(
            dimensions__classification_links__classification__id=
            "my-classification",
            dimensions__classification_links__includes_parents=False,
            dimensions__classification_links__includes_all=True,
            dimensions__classification_links__includes_unknown=True,
        )

        assert measure_version.dimensions[0].classification_links.count() > 0

        # when we copy the page
        new_version = page_service.create_measure_version(
            measure_version, NewVersionType.MINOR_UPDATE, user=user)

        # then
        assert new_version.dimensions.count() > 0
        assert new_version.dimensions[0].classification_links.count() > 0

        new_link = new_version.dimensions[0].classification_links[0]
        assert new_link.dimension_guid == new_version.dimensions[0].guid
        assert new_link.classification_id == "my-classification"
        assert new_link.includes_parents is False
        assert new_link.includes_all is True
        assert new_link.includes_unknown is True
Пример #7
0
def test_dimension_object_builder_does_build_with_page_level_data_from_grouped_table():
    data_source = DataSourceFactory.build(
        title="DWP Stats", source_url="http://dwp.gov.uk", publisher__name="Department for Work and Pensions"
    )
    measure_version = MeasureVersionWithDimensionFactory(
        title="Test Measure Page",
        area_covered=[UKCountry.ENGLAND],
        data_sources=[data_source],
        dimensions__dimension_table__table_object=grouped_table(),
        measure__slug="test-measure-page-slug",
    )
    # given - a table without a category_caption value
    builder = DimensionObjectBuilder()
    dimension = measure_version.dimensions[0]

    # when we process the object
    dimension_object = builder.build(dimension)

    # then the measure level info should be brought through
    assert dimension_object["context"]["measure"] == "Test Measure Page"
    assert dimension_object["context"]["measure_slug"] == "test-measure-page-slug"
    assert dimension_object["context"]["location"] == "England"
    assert dimension_object["context"]["title"] == "DWP Stats"
    assert dimension_object["context"]["source_url"] == "http://dwp.gov.uk"
    assert dimension_object["context"]["publisher"] == "Department for Work and Pensions"
    def test_measure_page_download_table_tabular_data_link_correct(
            self, test_app_client, logged_in_rdu_user, static_mode,
            expected_url):
        from tests.test_data.chart_and_table import chart, simple_table

        MeasureVersionWithDimensionFactory(
            status="DRAFT",
            version="1.0",
            measure__subtopics__topic__slug="topic",
            measure__subtopics__slug="subtopic",
            measure__slug="measure",
            dimensions__guid="dimension-guid",
            dimensions__title="dimension-title",
            dimensions__dimension_chart__chart_object=chart,
            dimensions__dimension_table__table_object=simple_table(),
            uploads__guid="test-download",
        )

        resp = test_app_client.get(
            f"/topic/subtopic/measure/latest?static_mode={static_mode}",
            follow_redirects=False)
        page = BeautifulSoup(resp.data.decode("utf-8"), "html.parser")

        data_links = page.findAll("a", href=expected_url)
        assert len(data_links) == 1
def test_delete_dimension_from_draft_measure_page():
    measure_version = MeasureVersionWithDimensionFactory(status="DRAFT", dimensions__guid="abc123")

    assert measure_version.dimensions.count() == 1
    assert measure_version.dimensions[0].guid == "abc123"

    dimension_service.delete_dimension(measure_version, "abc123")

    assert measure_version.dimensions.count() == 0
def test_add_table_to_dimension():
    measure_version = MeasureVersionWithDimensionFactory(dimensions__guid="abc123", dimensions__dimension_table=None)
    dimension = measure_version.dimensions[0]
    table = {"table_is_just_a": "dictionary"}

    dimension_service.update_dimension(dimension, {"table": table})

    assert dimension.guid == "abc123"
    assert dimension.dimension_table.table_object == table
def test_add_chart_to_dimension():
    measure_version = MeasureVersionWithDimensionFactory(dimensions__guid="abc123", dimensions__dimension_chart=None)
    dimension = measure_version.dimensions[0]
    chart = {"chart_is_just_a": "dictionary"}

    dimension_service.update_dimension(measure_version.dimensions[0], {"chart": chart})

    assert dimension.guid == "abc123"
    assert dimension.dimension_chart.chart_object == chart
    def test_another_version_created_if_an_updated_version_is_already_approved_with_same_dimension_titles(
        self, single_use_app
    ):
        user = UserFactory(user_type=TypeOfUser.ADMIN_USER, email="*****@*****.**")
        mv_1_0 = MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.0",
            title="my measure",
            measure__id=1,
            dimensions__guid="dimension-guid-1.0",
            dimensions__title="my dimension",
            uploads=[],
        )
        MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.1",
            title="my measure",
            external_edit_summary=None,
            measure=mv_1_0.measure,
            dimensions__guid="dimension-guid-1.1",
            dimensions__title="my dimension",
            uploads=[],
        )
        dimension_rows = [["dimension-guid-1.0", "my measure", "my dimension", "my new dimension"]]

        error_count = import_dimension_titles(user_email=user.email, app=single_use_app, dimension_rows=dimension_rows)

        measure = Measure.query.get(1)

        assert error_count == 0

        assert len(measure.versions) == 3
        assert measure.versions[0].version == "1.2"
        assert measure.versions[0].status == "APPROVED"
        assert measure.versions[0].dimensions[0].title == "my new dimension"
        assert measure.versions[0].external_edit_summary == STANDARD_EDIT_SUMMARY

        assert measure.versions[1].version == "1.1"
        assert measure.versions[1].status == "APPROVED"
        assert measure.versions[1].dimensions[0].title == "my dimension"
        assert measure.versions[1].external_edit_summary is None

        assert measure.versions[2].version == "1.0"
        assert measure.versions[2].dimensions[0].title == "my dimension"
Пример #13
0
def test_if_dimension_has_chart_and_table_download_table_source_data(logged_in_rdu_user, test_app_client):
    from tests.test_data.chart_and_table import (
        chart,
        chart_settings_and_source_data,
        table,
        table_settings_and_source_data,
    )

    measure_version = MeasureVersionWithDimensionFactory(
        dimensions__title="Dimension title",
        # Chart
        dimensions__dimension_chart__chart_object=chart,
        dimensions__dimension_chart__settings_and_source_data=chart_settings_and_source_data,
        dimensions__dimension_chart__classification=ClassificationFactory(id="2A"),
        dimensions__dimension_chart__includes_parents=False,
        dimensions__dimension_chart__includes_all=True,
        dimensions__dimension_chart__includes_unknown=False,
        # Table
        dimensions__dimension_table__table_object=table,
        dimensions__dimension_table__settings_and_source_data=table_settings_and_source_data,
        dimensions__dimension_table__classification=ClassificationFactory(id="5A"),
        dimensions__dimension_table__includes_parents=True,
        dimensions__dimension_table__includes_all=False,
        dimensions__dimension_table__includes_unknown=True,
    )

    # GIVEN
    # we have a dimension with table and chart data
    dimension = measure_version.dimensions[0]

    resp = test_app_client.get(
        url_for(
            "static_site.dimension_file_download",
            topic_slug=measure_version.measure.subtopic.topic.slug,
            subtopic_slug=measure_version.measure.subtopic.slug,
            measure_slug=measure_version.measure.slug,
            version=measure_version.version,
            dimension_guid=dimension.guid,
        )
    )

    # WHEN
    # we generate a plain table csv
    d = DimensionObjectBuilder.build(dimension)
    expected_csv = write_dimension_csv(dimension=d)

    # THEN
    # we get a return
    assert resp.status_code == 200
    assert resp.content_type == "text/csv"
    assert resp.headers["Content-Disposition"] == 'attachment; filename="dimension-title.csv"'

    # from the data in the table (not chart)
    actual_data = resp.data.decode("utf-8")
    assert actual_data == expected_csv
    def test_get_measure_page_hierarchy_raises_if_hierarchy_is_bad(self):
        measure_version = MeasureVersionWithDimensionFactory(
            measure__slug="measure-slug")

        with pytest.raises(InvalidPageHierarchy):
            page_service.get_measure_version_hierarchy(
                measure_version.measure.subtopic.topic.slug,
                measure_version.measure.subtopic.slug,
                "not-the-right-slug",
                measure_version.version,
            )
Пример #15
0
def test_table_object_builder_does_build_object_from_simple_table():
    measure_version = MeasureVersionWithDimensionFactory(dimensions__dimension_table__table_object=simple_table())
    # given - a table without a category_caption value
    builder = DimensionObjectBuilder()
    dimension = measure_version.dimensions[0]

    # when we process the object
    table_object = builder.build(dimension)

    # then the header for the returned table should match the ones from the simple table
    assert table_object is not None
    assert table_object.get("table").get("title") == "Title of simple table"
    def test_script_creates_new_minor_version_where_new_major_version_exists(self, single_use_app, new_version_state):
        user = UserFactory(user_type=TypeOfUser.ADMIN_USER, email="*****@*****.**")
        mv_1_0 = MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.0",
            title="my measure",
            measure__id=1,
            dimensions__guid="dimension-guid-1.0",
            dimensions__title="my dimension",
            uploads=[],
        )
        MeasureVersionWithDimensionFactory(
            status=new_version_state,
            version="2.0",
            title="my measure",
            external_edit_summary=None,
            measure=mv_1_0.measure,
            dimensions__guid="dimension-guid-1.1",
            dimensions__title="my dimension",
            uploads=[],
        )
        dimension_rows = [["dimension-guid-1.0", "my measure", "my dimension", "my new dimension"]]

        import_dimension_titles(user_email=user.email, app=single_use_app, dimension_rows=dimension_rows)

        measure = Measure.query.get(1)

        assert len(measure.versions) == 3
        assert measure.versions[0].version == "2.0"
        assert measure.versions[0].status == new_version_state
        assert measure.versions[0].dimensions[0].title == "my dimension"
        assert measure.versions[0].external_edit_summary is None

        assert measure.versions[1].version == "1.1"
        assert measure.versions[1].status == "APPROVED"
        assert measure.versions[1].dimensions[0].title == "my new dimension"
        assert measure.versions[1].external_edit_summary == STANDARD_EDIT_SUMMARY

        assert measure.versions[2].version == "1.0"
        assert measure.versions[2].dimensions[0].title == "my dimension"
Пример #17
0
def test_dashboard_pages_return_200(test_app_client, logged_in_rdu_user,
                                    dashboard_url):
    MeasureVersionWithDimensionFactory(
        status="APPROVED",
        published_at=datetime.now().date(),
        dimensions__classification_links__includes_parents=False,
        dimensions__classification_links__includes_all=True,
        dimensions__classification_links__includes_unknown=True,
        dimensions__classification_links__classification__id="5A",
    )
    refresh_materialized_views()

    resp = test_app_client.get(dashboard_url)
    assert resp.status_code == 200, f"Failed to load dashboards '{dashboard_url}'"
    def test_error_count_returned_if_new_version_exists_with_different_dimension_titles(self, single_use_app):
        user = UserFactory(user_type=TypeOfUser.ADMIN_USER, email="*****@*****.**")
        mv_1_0 = MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.0",
            title="my measure",
            measure__id=1,
            dimensions__guid="dimension-guid-1.0",
            dimensions__title="my 1.0 dimension",
            uploads=[],
        )
        MeasureVersionWithDimensionFactory(
            status="APPROVED",
            version="1.1",
            title="my measure",
            external_edit_summary=None,
            measure=mv_1_0.measure,
            dimensions__guid="dimension-guid-1.1",
            dimensions__title="my 1.1 dimension",
            uploads=[],
        )
        dimension_rows = [["dimension-guid-1.0", "my measure", "my 1.0 dimension", "my new 1.0 dimension"]]

        error_count = import_dimension_titles(user_email=user.email, app=single_use_app, dimension_rows=dimension_rows)

        measure = Measure.query.get(1)

        assert error_count == 1

        assert len(measure.versions) == 2
        assert measure.versions[0].version == "1.1"
        assert measure.versions[0].status == "APPROVED"
        assert measure.versions[0].dimensions[0].title == "my 1.1 dimension"
        assert measure.versions[0].external_edit_summary is None

        assert measure.versions[1].version == "1.0"
        assert measure.versions[1].dimensions[0].title == "my 1.0 dimension"
    def test_custom_classification_select_populates_with_known_classification(
            self, test_app_client, logged_in_rdu_user):
        measure_version = MeasureVersionWithDimensionFactory(version="1.0")
        response = test_app_client.get(self.builder_url(measure_version))

        assert response.status_code == 200
        page = BeautifulSoup(response.data.decode("utf-8"), "html.parser")
        classification_select = page.find(
            "select", {"id": "custom_classification__selector"})
        classification_options = classification_select.find_all("option")
        assert len(classification_options) == 29
        assert {
            option.get_text(strip=True)
            for option in classification_options
        } == {
            "4 - Asian, Black, White, Other inc Mixed",
            "4 - Black, Mixed, White, Other inc Asian",
            "5 - Asian, Black, White British, White other, Other inc Mixed",
            "6 - Asian, Black African, Black Caribbean, Black other, White, Other",
            "6 - Asian, Black African, Black Caribbean, Black other, White, Other - Aggregates",
            "6 - Asian, Black, Mixed, White British, White other, Other",
            "6 - Asian, Black, Mixed, White British, White other, Other - Aggregates",
            "6 - Indian, Pakistani and Bangladeshi, Black, Mixed, White, Other",
            "7 - Asian, Black, Chinese, Mixed, White British, White other, Other",
            "7 - Asian, Black, Chinese, Mixed, White British, White other, Other - Aggregates",
            "8 - Indian, Pakistani and Bangladeshi, Asian other, Black, Mixed, White British, White other, Other",
            "8 - Indian, Pakistani and Bangladeshi, Asian other, Black, Mixed, White "
            "British, White other, Other - Aggregates",
            "APS detailed - 13",
            "APS detailed - 13 - Aggregates",
            "Annual population survey - 9",
            "DfE - 18+1",
            "DfE - 6+1",
            "Family resources survey - 10",
            "Longitudinal education outcomes - 10",
            "Longitudinal education outcomes - 10 - Aggregates",
            "Not applicable",
            "ONS 2001 - 16+1",
            "ONS 2001 - 5+1",
            "ONS 2011 - 18+1",
            "ONS 2011 - 5+1",
            "Please select",
            "Well-being survey - 12",
            "White British and Other",
            "White and Other",
        }  # TODO: Fix to use definitions/lookups from `test_data: https://trello.com/c/fwYpIWkD
    def test_create_new_version_of_page_duplicates_dimensions(self):
        user = UserFactory(user_type=TypeOfUser.RDU_USER)
        measure_version = MeasureVersionWithDimensionFactory(latest=True)

        assert measure_version.latest
        assert measure_version.dimensions.count() > 0
        old_dimension = measure_version.dimensions[0]
        old_dimension_guid = old_dimension.guid

        new_version = page_service.create_measure_version(
            measure_version, NewVersionType.MINOR_UPDATE, user=user)

        assert new_version.dimensions.count() > 0
        new_dimension = new_version.dimensions[0]

        assert old_dimension.title == new_dimension.title
        assert old_dimension_guid != new_dimension.guid
        assert measure_version is not new_dimension.measure_version
Пример #21
0
def test_table_object_builder_does_build_with_dimension_level_data_from_grouped_table():
    measure_version = MeasureVersionWithDimensionFactory(
        dimensions__title="Dimension title",
        dimensions__guid="dimension-guid",
        dimensions__time_period="dimension-time-period",
        dimensions__dimension_table__table_object=grouped_table(),
    )
    # given - a table without a category_caption value
    builder = DimensionObjectBuilder()
    dimension = measure_version.dimensions[0]

    # when we process the object
    dimension_object = builder.build(dimension)

    # then the dimension level info should be brought through
    assert dimension_object["context"]["dimension"] == "Dimension title"
    assert dimension_object["context"]["guid"] == "dimension-guid"
    assert dimension_object["context"]["time_period"] == "dimension-time-period"
def test_update_dimension_does_call_update_dimension_classification_if_told_to():
    measure_version = MeasureVersionWithDimensionFactory(
        dimensions__title="test-dimension",
        dimensions__time_period="time_period",
        dimensions__summary="summary",
        dimensions__dimension_chart=None,
        dimensions__dimension_table=None,
    )

    dimension = measure_version.dimensions[0]
    assert measure_version.dimensions.count() == 1
    assert dimension.dimension_classification is not None

    # When update_dimension() is called without explicitly telling it to reclassify the dimension
    update_data = {"title": "updated-title", "time_period": "updated_time_period"}
    dimension_service.update_dimension(dimension, update_data, update_classification=True)

    # Then the dimension classification should have been overwritten/deleted
    # (in this case deleted as there is no associated chart or table object)
    assert dimension.dimension_classification is None
Пример #23
0
def test_table_object_builder_does_build_with_dimension_level_data_from_simple_table():
    measure_version = MeasureVersionWithDimensionFactory(
        title="Test Measure Page",
        area_covered=[UKCountry.ENGLAND],
        dimensions__title="Dimension title",
        dimensions__guid="dimension-guid",
        dimensions__time_period="dimension-time-period",
        dimensions__dimension_table__table_object=simple_table(),
        measure__slug="test-measure-page-slug",
    )
    # given - a table without a category_caption value
    builder = DimensionObjectBuilder()
    dimension = measure_version.dimensions[0]

    # when we process the object
    dimension_object = builder.build(dimension)

    # then the dimension level info should be brought through
    assert dimension_object["context"]["dimension"] == "Dimension title"
    assert dimension_object["context"]["guid"] == "dimension-guid"
    assert dimension_object["context"]["time_period"] == "dimension-time-period"
def test_update_dimension():
    measure_version = MeasureVersionWithDimensionFactory(
        dimensions__title="test dimension", dimensions__time_period="time period", dimensions__summary="summary"
    )
    dimension = measure_version.dimensions[0]

    update_data = {"title": "updated-title", "time_period": "updated_time_period"}

    dimension_service.update_dimension(dimension, update_data)

    updated_dimension = measure_version.dimensions[0]
    assert dimension.guid == updated_dimension.guid
    assert updated_dimension.title == "updated-title"
    assert updated_dimension.time_period == "updated_time_period"

    assert (
        updated_dimension.updated_at != updated_dimension.created_at
    ), "Update time should now be different from creation time"

    assert (
        datetime.utcnow() - updated_dimension.updated_at
    ).seconds < 5, "Update time should be within the last 5 seconds"
    def test_get_measure_page_hierarchy_gets_if_hierarchy_is_good(self):
        measure_version = MeasureVersionWithDimensionFactory()

        assert list(
            page_service.get_measure_version_hierarchy(
                measure_version.measure.subtopic.topic.slug,
                measure_version.measure.subtopic.slug,
                measure_version.measure.slug,
                measure_version.version,
            )) == [
                measure_version.measure.subtopic.topic,
                measure_version.measure.subtopic,
                measure_version.measure,
                measure_version,
            ]

        assert list(
            page_service.get_measure_version_hierarchy(
                measure_version.measure.subtopic.topic.slug,
                measure_version.measure.subtopic.slug,
                measure_version.measure.slug,
                measure_version.version,
                dimension_guid=measure_version.dimensions[0].guid,
            )) == [
                measure_version.measure.subtopic.topic,
                measure_version.measure.subtopic,
                measure_version.measure,
                measure_version,
                measure_version.dimensions[0],
            ]

        assert list(
            page_service.get_measure_version_hierarchy(
                measure_version.measure.subtopic.topic.slug,
                measure_version.measure.subtopic.slug,
                measure_version.measure.slug,
                measure_version.version,
                upload_guid=measure_version.uploads[0].guid,
            )) == [
                measure_version.measure.subtopic.topic,
                measure_version.measure.subtopic,
                measure_version.measure,
                measure_version,
                measure_version.uploads[0],
            ]

        assert list(
            page_service.get_measure_version_hierarchy(
                measure_version.measure.subtopic.topic.slug,
                measure_version.measure.subtopic.slug,
                measure_version.measure.slug,
                measure_version.version,
                dimension_guid=measure_version.dimensions[0].guid,
                upload_guid=measure_version.uploads[0].guid,
            )) == [
                measure_version.measure.subtopic.topic,
                measure_version.measure.subtopic,
                measure_version.measure,
                measure_version,
                measure_version.dimensions[0],
                measure_version.uploads[0],
            ]
def test_static_site_build(db_session, single_use_app):
    """
    A basic test for the core flow of the static site builder. This patches/mocks a few of the key integrations to
    help prevent calling out to external services accidentally, and where possible, includes two levels of failsafes.
    1) We change the application config to not push/deploy the site
    2) We mock out the push_site, so that even if the config setting fails, this test will raise an error.

    Unfortunately, due to circular dependencies between build/build_service, it's not easy to mock out `deploy_site`.
    So we mock out the S3FileSystem, which is initialized within `deploy_site`. This will throw an error if invoked.

    `create_versioned_assets` is mocked out because that function is only needed to generate css/js, which is tested
    in a separate step outside of pytest.

    `write_html` is mocked out so that we don't need to be able to write to a filesystem.

    We should look at expanding test coverage of the static site builder eventually, but such a task should probably
    also include refactoring the site builder to be more modular, less tightly-coupled, and more easy to test.
    """
    with patch.dict(single_use_app.config):
        with patch(
                "application.sitebuilder.build.push_site") as push_site_patch:
            with patch("application.sitebuilder.build.pull_current_site"
                       ) as pull_current_site_patch:
                with patch("application.sitebuilder.build_service.S3FileSystem"
                           ) as s3_fs_patch:
                    with patch(
                            "application.dashboard.data_helpers.trello_service"
                    ) as trello_service_patch:
                        with patch(
                                "application.sitebuilder.build.create_versioned_assets"
                        ):
                            with patch(
                                    "application.sitebuilder.build.write_html"
                            ):
                                single_use_app.config["PUSH_SITE"] = False
                                single_use_app.config["DEPLOY_SITE"] = False
                                pull_current_site_patch.side_effect = UnexpectedMockInvocationException
                                push_site_patch.side_effect = UnexpectedMockInvocationException
                                s3_fs_patch.side_effect = UnexpectedMockInvocationException
                                trello_service_patch.get_measure_cards.return_value = []

                                from tests.test_data.chart_and_table import chart, simple_table

                                # Including these three versioned pages ensures the build test exercises the logic to
                                # build multiple page versions
                                measure = MeasureFactory()
                                # Outdated version
                                MeasureVersionWithDimensionFactory(
                                    measure=measure,
                                    status="APPROVED",
                                    latest=False,
                                    published_at=datetime.now().date(),
                                    version="1.0",
                                    dimensions__dimension_chart=None,
                                    dimensions__dimension_table__table_object=
                                    simple_table(),
                                )
                                # Latest published version
                                MeasureVersionWithDimensionFactory(
                                    measure=measure,
                                    status="APPROVED",
                                    latest=False,
                                    published_at=datetime.now().date(),
                                    version="2.0",
                                    dimensions__dimension_chart=None,
                                    dimensions__dimension_table__table_object=
                                    simple_table(),
                                )
                                # Newer draft version
                                MeasureVersionWithDimensionFactory(
                                    measure=measure,
                                    status="DRAFT",
                                    published_at=None,
                                    latest=True,
                                    version="2.1",
                                    dimensions__dimension_chart=None,
                                    dimensions__dimension_table=None,
                                )

                                # Publish another page with dimension, chart and table to ensure there's an item for
                                # each of the dashboard views
                                MeasureVersionWithDimensionFactory(
                                    status="APPROVED",
                                    latest=True,
                                    published_at=datetime.now().date() -
                                    timedelta(weeks=1),
                                    version="1.0",
                                    measure__subtopics__topic__slug="topic",
                                    measure__subtopics__slug="subtopic",
                                    measure__slug="measure",
                                    dimensions__guid="dimension-guid",
                                    dimensions__dimension_chart__chart_object=
                                    chart,
                                    dimensions__dimension_table__table_object=
                                    simple_table(),
                                    uploads__guid="test-download",
                                    uploads__title="Test measure page data",
                                    uploads__file_name=
                                    "test-measure-page-data.csv",
                                )

                                # Materialized views are initially empty - populate them with our fixture page data
                                refresh_materialized_views()

                                do_it(single_use_app, request_build())