def test_lt_compares_alerts_based_on_start_date():
    alert_dict_1 = create_alert_dict()
    alert_dict_2 = create_alert_dict()

    alert_dict_1['starts_at'] = dt_parse('2021-04-21T11:30:00Z')
    alert_dict_2['starts_at'] = dt_parse('2021-04-21T12:30:00Z')

    assert Alert(alert_dict_1) < Alert(alert_dict_2)
def test_get_url_for_alert_skips_non_public_alerts():
    the_days_alerts = [
        create_alert_dict(starts_at=dt_parse('2021-04-21T12:00:00Z'), channel='operator'),
        create_alert_dict(starts_at=dt_parse('2021-04-21T13:00:00Z'), channel='severe'),
    ]

    alerts = Alerts(the_days_alerts)

    # doesn't have the -2 suffix as we skip the operator alert
    assert get_url_for_alert(Alert(the_days_alerts[1]), alerts) == '21-apr-2021'
def test_get_url_for_alert_returns_url_with_count_for_alerts_on_same_day(index, expected_url):
    the_days_alerts = [
        create_alert_dict(id=UUID(int=0), starts_at=dt_parse('2021-04-20T22:59:00Z')),
        create_alert_dict(id=UUID(int=1), starts_at=dt_parse('2021-04-20T23:00:00Z')),
        create_alert_dict(id=UUID(int=2), starts_at=dt_parse('2021-04-21T12:31:00Z')),
        create_alert_dict(id=UUID(int=3), starts_at=dt_parse('2021-04-21T12:31:00Z')),
        create_alert_dict(id=UUID(int=4), starts_at=dt_parse('2021-04-21T23:00:00Z')),
    ]

    alerts = Alerts(the_days_alerts)

    assert get_url_for_alert(Alert(the_days_alerts[index]), alerts) == expected_url
def test_public_alerts_dont_get_listed_as_tests(mocker):
    mocker.patch(__name__ + '.Alert.is_current_and_public', True)
    alerts = Alerts([
        create_alert_dict(),
        create_alert_dict(),
    ])

    assert len(alerts) == 2
    assert len(alerts.current_and_public) == 2
    assert len(alerts.test_alerts_today) == 0
    assert len(alerts.current_and_planned_test_alerts) == 0
    assert alerts.dates_of_current_and_planned_test_alerts == set()
def test_planned_tests_page_with_current_operator_test(
    mocker,
    client_get,
    extra_json_fields,
):
    mocker.patch('app.models.alerts.PlannedTests.from_yaml', return_value=[])
    mocker.patch('app.models.alerts.Alerts.load',
                 return_value=Alerts([
                     create_alert_dict(
                         channel='operator',
                         starts_at=dt_parse('2021-04-21T09:00:00Z'),
                         **extra_json_fields)
                 ]))
    html = client_get("alerts/planned-tests")
    assert [normalize_spaces(h2.text)
            for h2 in html.select('main h2')] == ['Wednesday 21 April 2021']
    assert not html.select('main h3')
    assert [normalize_spaces(p.text) for p in html.select('main p')] == [
        'Some mobile phone networks in the UK will test emergency alerts.',
        'Most phones and tablets will not get a test alert.',
        'Find out more about mobile network operator tests.',
        'The alert will say:',
        ('This is a mobile network operator test of the Emergency Alerts '
         'service. You do not need to take any action. To find out more, '
         'search for gov.uk/alerts'),
    ]
def test_multiple_test_alerts_on_the_same_day_are_aggregated(mocker):
    mocker.patch(__name__ + '.Alert.is_public', False)
    alerts = Alerts([
        create_alert_dict(
            starts_at='2021-01-01T01:01:01Z'
        ),
        create_alert_dict(
            starts_at='2021-01-01T02:02:02Z'
        ),
    ])

    assert len(alerts) == 2
    assert len(alerts.current_and_public) == 0
    assert len(alerts.test_alerts_today) == 1
    assert len(alerts.current_and_planned_test_alerts) == 1
    assert alerts.dates_of_current_and_planned_test_alerts == {
        AlertDate(dt_parse('2021-01-01T12:01:00Z'))
    }
def test_get_url_for_alert_doesnt_return_non_public_alerts():
    alerts = Alerts([
        create_alert_dict(
            channel='operator',
            starts_at=dt_parse('2021-04-21T11:30:00Z'),
        )
    ])

    with pytest.raises(ValueError):
        get_url_for_alert(alerts[0], alerts)
def test_alert_links_to_correct_page_based_on_url_slug(is_expired, client_get,
                                                       mocker):
    mocker.patch('app.models.alert.Alert.is_expired', is_expired)
    mocker.patch(
        'app.models.alerts.Alerts.load',
        return_value=Alerts([
            create_alert_dict(id=uuid4(),
                              content='test 1',
                              starts_at=dt_parse('2021-04-21T11:00:00Z')),
            create_alert_dict(id=uuid4(),
                              content='test 2',
                              starts_at=dt_parse('2021-04-21T12:00:00Z')),
        ]))

    html = client_get('alerts/21-apr-2021-2')
    assert html.select_one('.share-url p').text.strip(
    ) == 'https://www.gov.uk/alerts/21-apr-2021-2'
    assert html.select('p.govuk-body-l')[0].text == 'test 2'
    assert html.select('p.govuk-body')[0].text.strip() == (
        'Sent by the UK government at 1:00pm on Wednesday 21 April 2021')
def test_planned_tests_page_with_previous_days_operator_test(
    mocker,
    client_get,
):
    mocker.patch('app.models.alerts.PlannedTests.from_yaml', return_value=[])
    mocker.patch('app.models.alerts.Alerts.load',
                 return_value=Alerts([
                     create_alert_dict(
                         channel='operator',
                         starts_at=dt_parse('2021-04-20T09:00:00Z'),
                     )
                 ]))
    html = client_get("alerts/planned-tests")
    assert normalize_spaces(html.select_one('main p').text) == (
        'There are currently no planned tests of emergency alerts.')
def test_alert_says_active_alert_is_active(client_get, mocker):
    mocker.patch('app.models.alerts.Alerts.load',
                 return_value=Alerts([
                     create_alert_dict(
                         id=uuid4(),
                         content='test 1',
                         starts_at=dt_parse('2021-04-21T11:00:00Z'),
                         cancelled_at=None,
                         finishes_at=dt_parse('2021-04-21T15:00:00Z'),
                     )
                 ]))

    html = client_get('alerts/21-apr-2021')
    # no "Stopped sending at ..." h2
    assert html.find('main h2') is None
def test_alert_says_expired_alert_stopped(client_get, mocker):
    mocker.patch('app.models.alerts.Alerts.load',
                 return_value=Alerts([
                     create_alert_dict(
                         id=uuid4(),
                         content='test 1',
                         starts_at=dt_parse('2021-04-21T11:00:00Z'),
                         cancelled_at=None,
                         finishes_at=dt_parse('2021-04-21T15:00:00Z'),
                     )
                 ]))

    html = client_get('alerts/21-apr-2021')
    assert html.select_one('main h2').text.strip(
    ) == 'Stopped sending at 4:00pm on Wednesday 21 April 2021'
def test_get_alerts_ignores_blank_timestamps(mocker):
    response = {
        'alerts': [
            create_alert_dict(
                approved_at='2020-01-01T01:01:00Z',
                finishes_at='2020-01-01T01:01:00Z',
                starts_at='2020-01-01T01:01:00Z',
                cancelled_at=None,
            )
        ]
    }

    client = AlertsApiClient()
    mocker.patch.object(client, 'get', return_value=response)

    alert_dicts = client.get_alerts()
    assert alert_dicts[0]['cancelled_at'] is None
def test_get_url_for_alert_consistently_sorts_by_id():
    # all have the same start time
    the_days_alerts = [
        create_alert_dict(id=UUID(int=0)),
        create_alert_dict(id=UUID(int=1)),
        create_alert_dict(id=UUID(int=2)),
        create_alert_dict(id=UUID(int=3)),
        create_alert_dict(id=UUID(int=4)),
        create_alert_dict(id=UUID(int=5)),
        create_alert_dict(id=UUID(int=6)),
    ]

    # shuffle to make sure the order that alerts go in doesn't affect anything
    alerts = Alerts(random.sample(the_days_alerts, len(the_days_alerts)))

    assert get_url_for_alert(Alert(the_days_alerts[0]), alerts) == '21-apr-2021'
    assert get_url_for_alert(Alert(the_days_alerts[3]), alerts) == '21-apr-2021-4'
    assert get_url_for_alert(Alert(the_days_alerts[6]), alerts) == '21-apr-2021-7'
def test_past_alerts_page_groups_by_date(
    mocker,
    client_get,
):
    alerts = [
        create_alert_dict(id=UUID(int=1),
                          content='Something 1',
                          starts_at=dt_parse('2021-04-21T11:00:00Z')),
        create_alert_dict(id=UUID(int=2),
                          content='Something 1',
                          starts_at=dt_parse('2021-04-21T11:00:00Z')),
        create_alert_dict(id=UUID(int=3),
                          content='Something 2',
                          starts_at=dt_parse('2021-04-22T00:00:00Z')),
        create_alert_dict(id=UUID(int=4),
                          content='Something 3',
                          starts_at=dt_parse('2021-04-22T22:59:00Z')),
        create_alert_dict(id=UUID(int=5),
                          channel='operator',
                          starts_at=dt_parse('2021-04-21T11:00:00Z'),
                          content='Operator test'),  # noqa
        create_alert_dict(id=UUID(int=6),
                          channel='operator',
                          starts_at=dt_parse('2021-04-21T11:00:00Z'),
                          content='Operator test'),  # noqa
    ]
    # set all alerts to cancelled so they show in past alerts
    for alert in alerts:
        alert['cancelled_at'] = alert['starts_at']

    mocker.patch('app.models.alerts.Alerts.load', return_value=Alerts(alerts))

    html = client_get("alerts/past-alerts")
    titles_and_paragraphs = html.select(
        'main h2.govuk-heading-m, main p.govuk-body-l')
    assert [element.text.strip() for element in titles_and_paragraphs] == [
        'Thursday 22 April 2021',
        'Something 3',
        'Something 2',
        'Wednesday 21 April 2021',
        # Multiple non-public alerts on the same day are combined into one
        'Operator test',
        # Multiple public alerts are shown individually
        'Something 1',
        'Something 1',
    ]
def test_get_alerts(mocker):
    response = {
        'alerts': [
            create_alert_dict(
                approved_at='2020-01-01T01:01:00Z',
                cancelled_at='2020-01-01T01:01:00Z',
                finishes_at='2020-01-01T01:01:00Z',
                starts_at='2020-01-01T01:01:00Z',
            )
        ]
    }

    client = AlertsApiClient()
    mock_get = mocker.patch.object(client, 'get', return_value=response)

    alert_dicts = client.get_alerts()
    mock_get.assert_called_with(url='/govuk-alerts')

    assert len(alert_dicts) == 1
    assert isinstance(alert_dicts[0]['approved_at'], datetime)
    assert isinstance(alert_dicts[0]['finishes_at'], datetime)
    assert isinstance(alert_dicts[0]['cancelled_at'], datetime)
    assert isinstance(alert_dicts[0]['starts_at'], datetime)