diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c1c9304 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,30 @@ +name: Run Python Tests +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + strategy: + fail-fast: false + matrix: + python-version: [3.8] + poetry-version: [1.1.4] + os: [ubuntu-20.04, ubuntu-18.04, macos-latest, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Install Python 3 + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install Poetry + uses: abatilo/actions-poetry@v2.1.0 + with: + poetry-version: ${{ matrix.poetry-version }} + - name: Run tests with pytest + run: poetry run test \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..58fed07 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "python.testing.unittestArgs": [ + "-v", + "-s", + "./tests", + "-p", + "test*.py" + ], + "python.testing.pytestEnabled": false, + "python.testing.nosetestsEnabled": false, + "python.testing.unittestEnabled": true +} \ No newline at end of file diff --git a/spotframework/filter/__init__.py b/spotframework/filter/__init__.py index f59ec22..c22bdeb 100644 --- a/spotframework/filter/__init__.py +++ b/spotframework/filter/__init__.py @@ -22,9 +22,7 @@ def get_track_objects(tracks: List) -> Generator[Tuple[SimplifiedTrack, Union[Si PlayedTrack, LibraryTrack]], None, None]: for track in tracks: - if isinstance(track, SimplifiedTrack): - yield track, track - elif isinstance(track, (PlaylistTrack, PlayedTrack, LibraryTrack)): + if hasattr(track, 'track'): yield track.track, track else: - logger.warning(f'invalid type found for {track} ({type(track)}), discarding') + yield track, track diff --git a/spotframework/model/track.py b/spotframework/model/track.py index 97d7fb4..528ec0d 100644 --- a/spotframework/model/track.py +++ b/spotframework/model/track.py @@ -36,7 +36,7 @@ class SimplifiedTrack: is_local: bool is_playable: bool = None episode: bool = None - track: bool = None + # track: bool = None def __post_init__(self): if isinstance(self.uri, str): diff --git a/tests/test_filter.py b/tests/test_filter.py new file mode 100644 index 0000000..cee8c4c --- /dev/null +++ b/tests/test_filter.py @@ -0,0 +1,66 @@ +import unittest +from unittest.mock import Mock, MagicMock, create_autospec + +from dataclasses import fields + +from util import create_dataclass_mock + +from spotframework.model.track import SimplifiedTrack, TrackFull, PlaylistTrack, PlayedTrack, LibraryTrack +from spotframework.filter import get_track_objects + +complex_track_types = [PlaylistTrack, PlayedTrack, LibraryTrack] + +class TestFilterUtilFunctions(unittest.TestCase): + + def test_simple_track_for_no_track_attr(self): + self.assertFalse('track' in (i.name for i in fields(SimplifiedTrack))) + + def test_high_level_types_for_track_attr(self): + for class_type in complex_track_types: + self.assertTrue('track' in (i.name for i in fields(class_type)), + f'{class_type} does not have a track attribute') + + def test_get_tracks_for_simple_track(self): + mock_track = create_dataclass_mock(SimplifiedTrack) + + self.assertIsInstance(mock_track, SimplifiedTrack) + + self.assertFalse(hasattr(mock_track, 'track')) + + [(item, item_two)] = get_track_objects([mock_track]) + + self.assertEqual(item, mock_track) + self.assertEqual(item_two, mock_track) + + def test_get_tracks_for_complex_track_types(self): + for class_type in complex_track_types: + mock_track = create_dataclass_mock(class_type) + + self.assertIsInstance(mock_track, class_type) + + self.assertTrue(hasattr(mock_track, 'track'), f'{class_type} does not have a track attr') + + [(item, item_two)] = get_track_objects([mock_track]) + + self.assertEqual(item, mock_track.track) + self.assertEqual(item_two, mock_track) + + def test_get_tracks_for_multiple_track_types(self): + tracks = [create_dataclass_mock(class_type) for class_type in [SimplifiedTrack] + complex_track_types] + + self.assertFalse(hasattr(tracks[0], 'track')) + for mock_track in tracks[1:]: + self.assertTrue(hasattr(mock_track, 'track'), f'{mock_track.__class__} does not have a track attr') + + returned_tuples = list(get_track_objects(tracks)) + + item, item_two = returned_tuples[0] + self.assertEqual(item, tracks[0]) + self.assertEqual(item_two, tracks[0]) + for mock_track, (item, item_two) in list(zip(tracks, returned_tuples))[1:]: + self.assertEqual(item, mock_track.track) + self.assertEqual(item_two, mock_track) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/util.py b/tests/util.py new file mode 100644 index 0000000..e4de497 --- /dev/null +++ b/tests/util.py @@ -0,0 +1,5 @@ +from dataclasses import fields +from unittest.mock import Mock + +def create_dataclass_mock(obj): + return Mock(spec=[field.name for field in fields(obj)], __class__ = obj) \ No newline at end of file