def test_get_playlist(self, _m3u8, get: MagicMock()): service = LocastService(self.config, MagicMock()) service._validate_token = MagicMock() get.return_value = response = MagicMock() service.location = {"latitude": "10.0", "longitude": "-34.5"} get.json.return_value = {"streamUrl": "http://stream_url/foo"} m3u_data = m3u8.loads("""#EXTM3U #EXT-X-VERSION:3 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1600000,RESOLUTION=854x480 ../variant/5fq9TaMBBU9Qp87sj8IRbWh7QK01B4b5PNvMbHHcyCmvY2GoVIpufr0oIGBWuT88ZCWnUERTb3dzCYoeSbzYTBwV9XSQftUljPy3qfRVvAJq.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1024000,RESOLUTION=640x360 ../variant/5fq9TaMBBU9Qp87sj8IRbWh7QK01B4b5PNvMbHHcyCmvY2GoVIpufr0oIGBWuT88YXtZOaPXHcKs0P2wjlxc0oBTepH6VhAy6lODslybGe0z.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2700000,RESOLUTION=1280x720 ../variant/5fq9TaMBBU9Qp87sj8IRbWh7QK01B4b5PNvMbHHcyCmvY2GoVIpufr0oIGBWuT88YgHlZ1zmnMfSC8xXfEy2AvYS1rcvAjmOaxKgKvYM7w7h.m3u8 """.lstrip().rstrip()) _m3u8.load.return_value = m3u_data m3u_data.base_uri = "http://stream_url/foo" result = service.get_station_stream_uri("1000") get.assert_called_once_with(f'{WATCH_URL}/1000/10.0/-34.5', authenticated=True) response.json.assert_called() self.assertEqual( result, "http://stream_url/variant/5fq9TaMBBU9Qp87sj8IRbWh7QK01B4b5PNvMbHHcyCmvY2GoVIpufr0oIGBWuT88YgHlZ1zmnMfSC8xXfEy2AvYS1rcvAjmOaxKgKvYM7w7h.m3u8" )
def test_with_ip(self): service = LocastService(self.config, Geo()) service._set_attrs_from_geo = set_attrs = MagicMock() service._find_location() set_attrs.assert_called_with(IP_URL)
def test_with_zipcode(self): service = LocastService(self.config, Geo("90210")) service._set_attrs_from_geo = set_attrs = MagicMock() service._find_location() url = f"{DMA_URL}/zip/90210" set_attrs.assert_called_with(url)
def test_load_location_data_fail(self): service = LocastService(self.config, MagicMock()) service._find_location = find_location = MagicMock() service.active = False with self.assertRaises(LocationInvalidError): service._load_location_data() find_location.assert_called()
def test_validate_token_invalid(self): service = LocastService(self.config, MagicMock()) service._is_token_valid = validate_token = MagicMock() validate_token.return_value = False service.login = login = MagicMock() service._validate_token() login.assert_called()
def test_unknown_http_error(self, get: MagicMock): get.return_value = response = MagicMock() service = LocastService(self.config, MagicMock()) get.side_effect = HTTPError with self.assertRaises(LocationInvalidError): service._set_attrs_from_geo("geo_url") get.assert_called_with("geo_url")
def test_unknown_geo(self, get: MagicMock): get.return_value = response = MagicMock() service = LocastService(self.config, MagicMock()) response.status_code = 204 with self.assertRaises(LocationInvalidError): service._set_attrs_from_geo("geo_url") get.assert_called_with("geo_url")
def test_validate_user_no_donation(self, get: MagicMock()): LocastService.token = "locast_token" get.return_value = response = MagicMock() response.json.return_value = { "didDonate": False, "donationExpire": 1609480800000 } with self.assertRaises(UserInvalidError): LocastService._validate_user()
def test_get_stations_with_cache(self): self.config.cache_stations = True service = LocastService(self.config, MagicMock()) service._stations = stations = MagicMock() service._get_stations = get_stations = MagicMock() result = service.get_stations() self.assertEqual(result, stations) get_stations.assert_not_called()
def test_start(self, facilities: MagicMock()): service = LocastService(self.config, Geo("90210")) facilities.instance.return_value = instance = MagicMock() service._load_location_data = load_location_data = MagicMock() service._update_cache = update_cache = MagicMock() service.start() self.assertEqual(service._fcc_facilities, instance) load_location_data.assert_called() update_cache.assert_not_called()
def test_get_stations_no_cache(self): self.config.cache_stations = False service = LocastService(self.config, MagicMock()) service._get_stations = get_stations = MagicMock() get_stations.return_value = stations = MagicMock() result = service.get_stations() self.assertEqual(result, stations) get_stations.assert_called()
def test_login_failed(self, validate_user: MagicMock(), requests: MagicMock()): requests.post = post = MagicMock() post.return_value = response = MagicMock() response.raise_for_status.side_effect = HTTPError response.json.return_value = {"token": "specialToken"} with self.assertRaises(UserInvalidError): LocastService.login("my_user", "wrong_password") validate_user.assert_not_called() self.assertEqual(LocastService.token, None)
def test_load_location_data(self): service = LocastService(self.config, MagicMock()) service._find_location = find_location = MagicMock() service.active = True try: service._load_location_data() except LocationInvalidError as e: self.fail(e) find_location.assert_called()
def test_with_coords(self): service = LocastService(self.config, Geo(None, { "longitude": 1.0, "latitude": 2.0 })) service._set_attrs_from_geo = set_attrs = MagicMock() service._find_location() url = f"{DMA_URL}/2.0/1.0" set_attrs.assert_called_with(url)
def test_update_cache(self, timer: MagicMock): timer.return_value = timer_instance = MagicMock() service = LocastService(self.config, MagicMock()) service._get_stations = MagicMock() service._get_stations.return_value = stations = MagicMock() service._update_cache() self.assertEqual(service._stations, stations) timer.assert_called_with(3600, service._update_cache) timer_instance.start.assert_called()
def test_validate_user_successful(self, get: MagicMock()): LocastService.token = "locast_token" get.return_value = response = MagicMock() response.json.return_value = { "didDonate": True, "donationExpire": 1612159200000 } try: LocastService._validate_user() except UserInvalidError as e: self.fail(e) get.assert_called_once_with(USER_URL, authenticated=True)
def testget(self, get: MagicMock()): service = LocastService(self.config, MagicMock()) service._validate_token = MagicMock() LocastService.token = "TOKEN" service.dma = "123" get.return_value = response = MagicMock() response.json.return_value = ["foo", "bar"] result = service._get_locast_stations() get.assert_called_once_with( f'{STATIONS_URL}/123?startTime=2021-01-01T00:00:00-00:00&hours=192', authenticated=True) response.json.assert_called() self.assertEqual(result, ["foo", "bar"])
def test_login_successful(self, validate_user: MagicMock(), requests: MagicMock()): requests.post = post = MagicMock() post.return_value = response = MagicMock() response.json.return_value = {"token": "specialToken"} LocastService.login("my_user", "secret") post.assert_called_once_with( LOGIN_URL, json={ "username": "******", "password": "******" }, headers={'Content-Type': 'application/json'}) response.raise_for_status.assert_called_once() validate_user.assert_called_once() self.assertEqual(LocastService.token, "specialToken")
def test_init(self): service = LocastService(self.config, Geo("90210")) self.assertEqual(service.coords, None) self.assertEqual(service.zipcode, "90210") self.assertEqual(service.config, self.config) self.assertEqual(service.location, None) self.assertEqual(service.active, False) self.assertEqual(service.dma, None) self.assertEqual(service.city, None) self.assertIsInstance(service._channel_lock, type(threading.Lock()))
def test_login_no_credentials(self, validate_user: MagicMock(), requests: MagicMock()): requests.post = post = MagicMock() post.return_value = response = MagicMock() response.json.return_value = {"token": "specialToken"} LocastService.login() post.assert_called_once_with( LOGIN_URL, json={ "username": None, "password": None }, headers={'Content-Type': 'application/json'}) response.raise_for_status.assert_called_once() validate_user.assert_called_once() self.assertEqual(LocastService.username, None) self.assertEqual(LocastService.password, None)
def test_internal_get_stations_simple_case(self): stations = [{"callSign": "2.1 CBS"}] service = LocastService(self.config, MagicMock()) service.city = "Chicago" service.timezone = "America/Chicago" service._get_locast_stations = get_locast_stations = MagicMock() get_locast_stations.return_value = stations result = service._get_stations() expected = [{ "callSign": "2.1 CBS", "channel": "2.1", "city": "Chicago", "timezone": "America/Chicago" }] get_locast_stations.assert_called() self.assertEqual(result, expected)
def testget(self, m3u8, get: MagicMock()): service = LocastService(self.config, MagicMock()) service._validate_token = MagicMock() service.location = {"latitude": "10.0", "longitude": "-34.5"} get.return_value = response = MagicMock() response.json.return_value = {"streamUrl": "stream_url"} m3u8.load.return_value = m3u_data = MagicMock() m3u_data.playlists = [] result = service.get_station_stream_uri("1000") get.assert_called_once_with(f'{WATCH_URL}/1000/10.0/-34.5', authenticated=True) response.json.assert_called() self.assertEqual(result, "stream_url") m3u8.load.assert_called_with("stream_url")
def test_detect_call_sign(self): service = LocastService(self.config, MagicMock()) self.assertEqual(service._detect_callsign("WLTV1"), ("WLTV", "1")) self.assertEqual(service._detect_callsign("KLTV1"), ("KLTV", "1")) self.assertEqual(service._detect_callsign("KLTVAA1"), ("KLTV", "1")) self.assertEqual(service._detect_callsign("KLTV"), ("KLTV", '')) self.assertEqual(service._detect_callsign("FLTV1"), None)
def test_internal_get_stations_facility_lookup(self): stations = [{ "callSign": "CBS", "name": "WLTV1" }, { "callSign": "WLTV2", "name": "NPR" }] service = LocastService(self.config, MagicMock()) service.dma = "123" service.city = "Chicago" service.timezone = "America/Chicago" service._get_locast_stations = get_locast_stations = MagicMock() get_locast_stations.return_value = stations service._detect_callsign = MagicMock() service._detect_callsign.side_effect = [("WLTV", 1), None, ("WLTV", 2)] service._fcc_facilities = MagicMock() service._fcc_facilities.by_dma_and_call_sign.side_effect = [{ "channel": "2", "analog": False }, { "channel": "1", "analog": True }] result = service._get_stations() expected = [{ "callSign": "CBS", "name": "WLTV1", "channel": "2.1", "city": "Chicago", "timezone": "America/Chicago" }, { 'callSign': 'WLTV2', 'name': 'NPR', 'city': 'Chicago', 'channel': '1', "timezone": "America/Chicago" }] get_locast_stations.assert_called() service._fcc_facilities.by_dma_and_call_sign.assert_called_with( "123", "WLTV") self.assertEqual(result, expected)
def test_success(self, get: MagicMock): get.return_value = response = MagicMock() service = LocastService(self.config, MagicMock()) response.status_code = 200 response.json.return_value = { 'latitude': 1.0, 'longitude': 2.0, 'DMA': 123, 'active': True, 'name': 'Chicago' } try: service._set_attrs_from_geo("geo_url") except LocationInvalidError as e: self.fail(e) get.assert_called_with("geo_url") self.assertEqual(service.location, {"latitude": 1.0, "longitude": 2.0}) self.assertEqual(service.dma, "123") self.assertEqual(service.active, True) self.assertEqual(service.city, 'Chicago')
def test_not_authenticated(self, requests: MagicMock()): requests.get.return_value = response = MagicMock() r = LocastService.get("url", authenticated=False) self.assertEqual(r, response) response.raise_for_status.assert_called() requests.get.assert_called_once_with( "url", headers={ 'Content-Type': 'application/json', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36' })
def test_internal_get_stations_no_call_sign(self): stations = [{ "callSign": "CBS", "name": "WLTV1" }, { "callSign": "WLTV2", "name": "NPR" }] service = LocastService(self.config, MagicMock()) service.dma = "123" service.city = "Chicago" service.timezone = "America/Chicago" service._get_locast_stations = get_locast_stations = MagicMock() get_locast_stations.return_value = stations service._detect_callsign = MagicMock() service._detect_callsign.return_value = None result = service._get_stations() expected = [{ "callSign": "CBS", "name": "WLTV1", "channel": "1000", "city": "Chicago", "timezone": "America/Chicago" }, { 'callSign': 'WLTV2', 'name': 'NPR', 'city': 'Chicago', 'channel': '1001', 'timezone': 'America/Chicago' }] get_locast_stations.assert_called() self.assertEqual(result, expected)
def test_is_token_invalid(self): service = LocastService(self.config, MagicMock()) service.last_login = datetime(2021, 1, 1, 2, 30) self.assertFalse(service._is_token_valid())