260 lines
9.4 KiB
Python
260 lines
9.4 KiB
Python
import pytest
|
|
import shutil
|
|
import os
|
|
import json
|
|
from pathlib import Path
|
|
from unittest import mock
|
|
from helpers.PlaylistBuilder import PlaylistBuilder
|
|
|
|
@pytest.fixture
|
|
def temp_environment(tmp_path):
|
|
"""
|
|
Fixture to set up a temporary environment for testing.
|
|
Creates temporary directories for covers and output,
|
|
copies the sample cover image, and initializes PlaylistBuilder.
|
|
"""
|
|
# Define paths within the temporary directory
|
|
covers_dir = tmp_path / "covers"
|
|
history_file = tmp_path / "playlist_history.json"
|
|
output_dir = tmp_path / "output"
|
|
|
|
# Create necessary directories
|
|
covers_dir.mkdir(parents=True, exist_ok=True)
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Path to the sample cover image in the repository
|
|
sample_cover_src = Path(__file__).parent / 'assets' / 'sample_cover.jpg'
|
|
|
|
# Ensure the sample cover exists
|
|
assert sample_cover_src.exists(), f"Sample cover not found at {sample_cover_src}"
|
|
|
|
# Copy the sample cover to the covers directory
|
|
shutil.copy(sample_cover_src, covers_dir)
|
|
|
|
# Initialize the PlaylistBuilder with the test paths
|
|
builder = PlaylistBuilder(
|
|
covers_dir=str(covers_dir),
|
|
history_file=str(history_file),
|
|
output_dir=str(output_dir)
|
|
)
|
|
|
|
# Sample song data
|
|
sample_song = {
|
|
"hash": "7c9e0a7c523395c7ef9d79006b9d42dc6ab8b44a",
|
|
"key": "2a44e",
|
|
"levelId": "custom_level_7c9e0a7c523395c7ef9d79006b9d42dc6ab8b44a",
|
|
"songName": "Gleodream",
|
|
"difficulties": [
|
|
{
|
|
"name": "normal",
|
|
"characteristic": "Standard"
|
|
}
|
|
]
|
|
}
|
|
|
|
yield {
|
|
"builder": builder,
|
|
"covers_dir": covers_dir,
|
|
"history_file": history_file,
|
|
"output_dir": output_dir,
|
|
"sample_song": sample_song,
|
|
"sample_cover_src": sample_cover_src
|
|
}
|
|
|
|
# Teardown is handled automatically by pytest's tmp_path fixture
|
|
|
|
def test_create_playlist(temp_environment, caplog):
|
|
"""
|
|
Test the creation of a playlist with a sample song and cover.
|
|
"""
|
|
env = temp_environment
|
|
builder = env["builder"]
|
|
covers_dir = env["covers_dir"]
|
|
history_file = env["history_file"]
|
|
output_dir = env["output_dir"]
|
|
sample_song = env["sample_song"]
|
|
|
|
# Create the playlist
|
|
playlist_title = "Test Playlist"
|
|
playlist_author = "Test Author"
|
|
playlist_path = builder.create_playlist(
|
|
playlist_data=[sample_song],
|
|
playlist_title=playlist_title,
|
|
playlist_author=playlist_author
|
|
)
|
|
|
|
# Verify that the playlist file exists
|
|
assert os.path.exists(playlist_path), "Playlist file was not created."
|
|
|
|
# Load the playlist content
|
|
with open(playlist_path, 'r') as f:
|
|
playlist_content = json.load(f)
|
|
|
|
# Check playlist metadata
|
|
assert playlist_content['playlistTitle'] == playlist_title
|
|
assert playlist_content['playlistAuthor'] == playlist_author
|
|
assert len(playlist_content['songs']) == 1
|
|
|
|
# Verify song details
|
|
song = playlist_content['songs'][0]
|
|
assert song['hash'] == sample_song['hash']
|
|
assert song['key'] == sample_song['key']
|
|
assert song['levelId'] == sample_song['levelId']
|
|
assert song['songName'] == sample_song['songName']
|
|
assert len(song['difficulties']) == 1
|
|
assert song['difficulties'][0]['name'] == 'normal'
|
|
assert song['difficulties'][0]['characteristic'] == 'Standard'
|
|
|
|
# Check that an image is encoded and included
|
|
assert 'image' in playlist_content
|
|
assert playlist_content['image'] is not None, "Image was not encoded in the playlist."
|
|
assert playlist_content['image'].startswith("data:image/png;base64,"), "Image encoding is incorrect."
|
|
|
|
# Verify coverImage path
|
|
assert 'coverImage' in playlist_content
|
|
expected_cover_path = str(covers_dir / 'sample_cover.jpg')
|
|
assert playlist_content['coverImage'] == expected_cover_path
|
|
|
|
# Verify description
|
|
assert 'description' in playlist_content
|
|
assert 'Playlist created by SaberList Tool on' in playlist_content['description']
|
|
|
|
# Check that duplicates are not allowed
|
|
assert not playlist_content['allowDuplicates'], "Duplicates should not be allowed."
|
|
|
|
# Check customData fields are present but None
|
|
assert 'customData' in playlist_content
|
|
assert playlist_content['customData'] is not None
|
|
assert playlist_content['customData']['syncURL'] is None
|
|
assert playlist_content['customData']['owner'] is None
|
|
assert playlist_content['customData']['id'] is None
|
|
assert playlist_content['customData']['hash'] is None
|
|
assert playlist_content['customData']['shared'] is None
|
|
|
|
# Verify that the cover was marked as used in history
|
|
with open(history_file, 'r') as f:
|
|
history = json.load(f)
|
|
assert 'sample_cover.jpg' in history['used_covers'], "Cover image was not marked as used in history."
|
|
|
|
def test_no_available_covers(temp_environment, caplog):
|
|
"""
|
|
Test behavior when no unused cover images are available.
|
|
"""
|
|
env = temp_environment
|
|
builder = env["builder"]
|
|
covers_dir = env["covers_dir"]
|
|
history_file = env["history_file"]
|
|
output_dir = env["output_dir"]
|
|
sample_song = env["sample_song"]
|
|
|
|
# Remove all covers to simulate no available covers
|
|
shutil.rmtree(covers_dir)
|
|
covers_dir.mkdir(parents=True, exist_ok=True) # Recreate covers directory without any covers
|
|
|
|
# Attempt to create a playlist
|
|
playlist_path = builder.create_playlist(
|
|
playlist_data=[sample_song],
|
|
playlist_title="No Cover Playlist",
|
|
playlist_author="Test Author"
|
|
)
|
|
|
|
# Verify that the playlist file exists
|
|
assert os.path.exists(playlist_path), "Playlist file was not created when no covers are available."
|
|
|
|
# Load the playlist content
|
|
with open(playlist_path, 'r') as f:
|
|
playlist_content = json.load(f)
|
|
|
|
# Check that image and coverImage are None or not set
|
|
assert playlist_content['image'] is None, "Image should be None when no covers are available."
|
|
assert playlist_content['coverImage'] is None, "coverImage should be None when no covers are available."
|
|
|
|
# Create another playlist to trigger logging
|
|
builder.create_playlist(
|
|
playlist_data=[sample_song],
|
|
playlist_title="Another No Cover Playlist",
|
|
playlist_author="Test Author"
|
|
)
|
|
|
|
# Verify that a warning was logged
|
|
assert any("No unused cover images available. Using no cover." in message for message in caplog.text.split('\n')), \
|
|
"Expected warning was not logged."
|
|
|
|
def test_history_persistence(temp_environment):
|
|
"""
|
|
Test that the history is persisted correctly across multiple playlist creations.
|
|
"""
|
|
env = temp_environment
|
|
builder = env["builder"]
|
|
covers_dir = env["covers_dir"]
|
|
history_file = env["history_file"]
|
|
sample_song = env["sample_song"]
|
|
|
|
# Create first playlist
|
|
builder.create_playlist(
|
|
playlist_data=[sample_song],
|
|
playlist_title="First Playlist",
|
|
playlist_author="Author A"
|
|
)
|
|
|
|
# Attempt to create a second playlist; since there's only one cover, it should warn and not use any cover
|
|
playlist_path = builder.create_playlist(
|
|
playlist_data=[sample_song],
|
|
playlist_title="Second Playlist",
|
|
playlist_author="Author B"
|
|
)
|
|
|
|
# Load the second playlist
|
|
with open(playlist_path, 'r') as f:
|
|
playlist_content = json.load(f)
|
|
|
|
# Check that no image is set since the cover was already used
|
|
assert playlist_content['image'] is None, "Image should be None when cover is already used."
|
|
assert playlist_content['coverImage'] is None, "coverImage should be None when cover is already used."
|
|
|
|
# Verify history contains the cover
|
|
with open(history_file, 'r') as f:
|
|
history = json.load(f)
|
|
assert 'sample_cover.jpg' in history['used_covers'], "Cover image was not marked as used in history."
|
|
|
|
@mock.patch('saberlist.PlaylistBuilder.random.choice')
|
|
def test_random_cover_selection(mock_choice, temp_environment):
|
|
"""
|
|
Test that a specific cover is selected when random.choice is mocked.
|
|
"""
|
|
env = temp_environment
|
|
builder = env["builder"]
|
|
covers_dir = env["covers_dir"]
|
|
history_file = env["history_file"]
|
|
sample_song = env["sample_song"]
|
|
sample_cover_src = env["sample_cover_src"]
|
|
|
|
# Add another cover to the covers directory
|
|
additional_cover = covers_dir / 'additional_cover.jpg'
|
|
shutil.copy(sample_cover_src, additional_cover)
|
|
|
|
# Mock random.choice to return 'additional_cover.jpg'
|
|
mock_choice.return_value = 'additional_cover.jpg'
|
|
|
|
# Create the playlist
|
|
playlist_path = builder.create_playlist(
|
|
playlist_data=[sample_song],
|
|
playlist_title="Mocked Cover Playlist",
|
|
playlist_author="Mock Author"
|
|
)
|
|
|
|
# Verify that the mocked cover was used by checking 'coverImage'
|
|
expected_cover_path = str(covers_dir / 'additional_cover.jpg')
|
|
with open(playlist_path, 'r') as f:
|
|
playlist_content = json.load(f)
|
|
|
|
assert playlist_content['coverImage'] == expected_cover_path, "The coverImage should point to 'additional_cover.jpg'."
|
|
|
|
# Optionally, verify that 'image' is correctly encoded by checking the data URL prefix
|
|
assert playlist_content['image'].startswith("data:image/png;base64,"), "Image encoding is incorrect."
|
|
|
|
# Verify that the history includes the mocked cover
|
|
with open(history_file, 'r') as f:
|
|
history = json.load(f)
|
|
assert 'additional_cover.jpg' in history['used_covers'], "Cover image was not marked as used in history."
|