import datetime from unittest.mock import Mock, patch import freezegun import pytest from click.testing import CliRunner from main import cli, get_configuration, parse_duration @pytest.fixture(name="with_sample_config", autouse=True) def fixture_with_sample_config(tmp_path): config_path = tmp_path / "config.yml" config_path.write_text( """ token: abc presets: test: text: abc emoji: ":tada:" duration: "1d" """ ) @freezegun.freeze_time("2012-01-01") @pytest.mark.parametrize( ["duration", "delta"], [ ["1d", datetime.timedelta(days=1)], ["1h", datetime.timedelta(hours=1)], ["1m", datetime.timedelta(minutes=1)], ["1d1m", datetime.timedelta(days=1, minutes=1)], ["1d1h", datetime.timedelta(days=1, hours=1)], ["1d1h1m", datetime.timedelta(days=1, hours=1, minutes=1)], ], ) def test_get_parse_duration(duration, delta): expected_time = (datetime.datetime.now() + delta).timestamp() actual_time = parse_duration(duration) assert expected_time == actual_time def test_get_configuration_raises_if_noexist(): with pytest.raises(RuntimeError): get_configuration("not/a/path.yml") def test_get_configuration_returns_configuration_obj(tmp_path): config_path = tmp_path / "config.yml" config_path.write_text( """ token: abc presets: test: text: abc emoji: ":tada:" """ ) conf = get_configuration(config_path) assert conf.token == "abc" assert "test" in conf.presets assert conf.presets["test"].text == "abc" assert conf.presets["test"].emoji == ":tada:" def test_cli_requires_text_or_preset_input(tmp_path): runner = CliRunner() result = runner.invoke(cli, ["--config", tmp_path / "config.yml"]) assert isinstance(result.exception, RuntimeError) assert ( str(result.exception) == "Must specify either status text via --text/-t or a preset via --preset/-p." ) def test_cli_overrides_preset_with_text_input(tmp_path): runner = CliRunner() mock_client = Mock() mock_client.users_profile_set = Mock() with patch("main.get_client", autospec=True, return_value=mock_client): result = runner.invoke( cli, [ "--text", "testtext", "--preset", "test", "--config", tmp_path / "config.yml", ], ) call_args = mock_client.users_profile_set.call_args assert result.exit_code == 0 assert call_args.kwargs["profile"]["status_text"] == "testtext" assert call_args.kwargs["profile"]["status_emoji"] == ":tada:" def test_cli_overrides_preset_with_emoji_input(tmp_path): runner = CliRunner() mock_client = Mock() mock_client.users_profile_set = Mock() with patch("main.get_client", autospec=True, return_value=mock_client): result = runner.invoke( cli, [ "--emoji", ":skull:", "--preset", "test", "--config", tmp_path / "config.yml", ], ) call_args = mock_client.users_profile_set.call_args assert result.exit_code == 0 assert call_args.kwargs["profile"]["status_text"] == "abc" assert call_args.kwargs["profile"]["status_emoji"] == ":skull:" @freezegun.freeze_time("2012-01-01") def test_cli_overrides_preset_with_exp_input(tmp_path): runner = CliRunner() mock_client = Mock() mock_client.users_profile_set = Mock() with patch("main.get_client", autospec=True, return_value=mock_client): result = runner.invoke( cli, [ "--duration", "1h", "--preset", "test", "--config", tmp_path / "config.yml", ], ) call_args = mock_client.users_profile_set.call_args assert result.exit_code == 0 assert call_args.kwargs["profile"]["status_text"] == "abc" assert call_args.kwargs["profile"]["status_emoji"] == ":tada:" assert ( call_args.kwargs["profile"]["status_expiration"] == (datetime.datetime.now() + datetime.timedelta(hours=1)).timestamp() ) def test_cli_raises_if_noexist_preset(tmp_path): runner = CliRunner() mock_client = Mock() mock_client.users_profile_set = Mock() with patch("main.get_client", autospec=True, return_value=mock_client): result = runner.invoke( cli, ["--preset", "not-a-preset", "--config", tmp_path / "config.yml"] ) assert result.exit_code == 1 assert str(result.exception) == "Unknown preset: not-a-preset" def test_cli_sends_request_to_slack(tmp_path): runner = CliRunner() mock_client = Mock() mock_client.users_profile_set = Mock() with patch("main.get_client", autospec=True, return_value=mock_client): runner.invoke( cli, [ "--emoji", ":skull:", "--preset", "test", "--config", tmp_path / "config.yml", ], ) mock_client.users_profile_set.assert_called() def test_cli_raises_if_api_error(tmp_path): runner = CliRunner() mock_client = Mock() mock_client.users_profile_set = Mock(return_value={"ok": False}) with patch("main.get_client", autospec=True, return_value=mock_client): result = runner.invoke( cli, [ "--emoji", ":skull:", "--preset", "test", "--config", tmp_path / "config.yml", ], ) assert result.exit_code == 1 assert str(result.exception) == "Failed to set status!"