songs2slides

A tool that automatically finds song lyrics and creates lyric slideshows
git clone https://git.ashermorgan.net/songs2slides/
Log | Files | Refs | README

commit 2007535abfa861728e1991755e3b761e798631ab
parent b9598631ac414c21636b384ca07b7cd0d7d12da9
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Mon, 26 Feb 2024 16:17:05 -0800

Implement /create/ POST route

Diffstat:
Msongs2slides/routes.py | 22+++++++++++++++++++++-
Asongs2slides/templates/create-step-2.html | 12++++++++++++
Mtests/test_routes.py | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/songs2slides/routes.py b/songs2slides/routes.py @@ -39,8 +39,28 @@ def parse_form(form): def home(): return render_template('home.html') +@bp.post('/create/') +def get_lyrics(): + # Parse form data + songs = parse_form(request.form) + + # Get lyrics + for i in range(len(songs)): + try: + songs[i] = core.get_song_data(songs[i].title, songs[i].artist) + slides = core.parse_song_lyrics(songs[i].lyrics, 4) + songs[i].lyrics = '\n\n'.join(slides) + except: + pass + + # Count missing songs + missing = sum([1 for x in songs if x.lyrics == None]) + + # Return song data + return render_template('create-step-2.html', songs=songs, missing=missing) + @bp.post('/slides/') -def slides(): +def create_slides(): # Parse form data songs = parse_form(request.form) diff --git a/songs2slides/templates/create-step-2.html b/songs2slides/templates/create-step-2.html @@ -0,0 +1,12 @@ +{% extends "layout.html" %} + +{% block main %} +<ol> + {% for song in songs %} + <i>{{ song.title }}</i> + {% if song.artist %} ({{ song.artist }}) {% endif %} + <br> + {{ song.lyrics }} + {% endfor %} +</ol> +{% endblock main %} diff --git a/tests/test_routes.py b/tests/test_routes.py @@ -8,7 +8,75 @@ class TestRoutes(unittest.TestCase): self.app = create_app() self.client = self.app.test_client() - def test_slides_basic(self): + def test_get_lyrics_basic(self): + with patch('songs2slides.core.get_song_data') as mocked_get, \ + patch('songs2slides.core.parse_song_lyrics') as mocked_parse, \ + patch('songs2slides.routes.render_template') as mocked_render: + + # Mock get_song_data and parse_song_lyrics + songs = [ + core.SongData('T1', 'A1', 'L1'), + core.SongData('T2', 'A2', 'L2'), + ] + mocked_get.side_effect = songs + mocked_parse.side_effect = ['L1', 'L2'] + + # Send request + self.client.post('/create/', data={ + 'title-1': 'T1', + 'artist-1': 'A1', + 'title-2': 'T2', + 'artist-2': 'A2', + }) + + # Assert mocks called correctly + mocked_get.assert_has_calls([call('T1', 'A1'), call('T2', 'A2')]) + mocked_parse.assert_has_calls([call('L1', 4), call('L2', 4)]) + mocked_render.assert_called_with('create-step-2.html', songs=songs, missing=0) + + def test_get_lyrics_one_error(self): + with patch('songs2slides.core.get_song_data') as mocked_get, \ + patch('songs2slides.core.parse_song_lyrics') as mocked_parse, \ + patch('songs2slides.routes.render_template') as mocked_render: + + # Mock get_song_data and parse_song_lyrics + songs = [ + core.SongData('T1', 'A1', None), + core.SongData('T2', 'A2', 'L2'), + ] + mocked_get.side_effect = [Exception(), songs[1]] + mocked_parse.side_effect = ['L1', 'L2'] + + # Send request + self.client.post('/create/', data={ + 'title-1': 'T1', + 'artist-1': 'A1', + 'title-2': 'T2', + 'artist-2': 'A2', + }) + + # Assert mocks called correctly + mocked_get.assert_has_calls([call('T1', 'A1'), call('T2', 'A2')]) + mocked_parse.assert_has_calls([call('L2', 4)]) + mocked_render.assert_called_with('create-step-2.html', songs=songs, missing=1) + + def test_get_lyrics_missing_artist(self): + with patch('songs2slides.core.get_song_data') as mocked_get: + + # Send request + res = self.client.post('/create/', data={ + 'title-1': 'T1', + 'title-2': 'T2', + 'artist-2': 'A2', + }) + + # Assert mocks not called + mocked_get.assert_not_called() + + # Assert response has 400 status code + self.assertEqual(res.status_code, 400) + + def test_create_slides_basic(self): with patch('songs2slides.core.assemble_slides') as mocked_assemble, \ patch('songs2slides.core.create_pptx') as mocked_create, \ patch('songs2slides.routes.send_file') as mocked_send: @@ -34,7 +102,7 @@ class TestRoutes(unittest.TestCase): mocked_send.assert_called_with(file, as_attachment=True, download_name='slides.pptx') - def test_slides_mising_artist(self): + def test_create_slides_mising_artist(self): with patch('songs2slides.core.assemble_slides') as mocked_assemble: # Send request