mirror of
https://github.com/imarkoff/Marble-shell-theme.git
synced 2025-09-17 08:47:55 -07:00
Covered Theme module with tests
- Extracted `ColorReplacementGenerator`; - Extracted `ColorConverterImpl`; - Added documentation to some classes; - `hex_to_rgba` now supports shorthand hex colors (#fff).
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
import colorsys
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class ColorConverter(ABC):
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def hex_to_rgba(hex_color):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def hsl_to_rgb(hue, saturation, lightness):
|
||||
pass
|
||||
|
||||
|
||||
class ColorConverterImpl(ColorConverter):
|
||||
@staticmethod
|
||||
def hex_to_rgba(hex_color):
|
||||
try:
|
||||
if len(hex_color) in range(6, 10):
|
||||
hex_color = hex_color.lstrip('#') + "ff"
|
||||
# if is convertable
|
||||
int(hex_color[:], 16)
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
except ValueError:
|
||||
raise ValueError(f'Error: Invalid HEX color code: {hex_color}')
|
||||
|
||||
else:
|
||||
return int(hex_color[0:2], 16), \
|
||||
int(hex_color[2:4], 16), \
|
||||
int(hex_color[4:6], 16), \
|
||||
int(hex_color[6:8], 16) / 255
|
||||
|
||||
@staticmethod
|
||||
def hsl_to_rgb(hue, saturation, lightness):
|
||||
# colorsys works in range(0, 1)
|
||||
h = hue / 360
|
||||
red, green, blue = [int(item * 255) for item in colorsys.hls_to_rgb(h, lightness, saturation)]
|
||||
return red, green, blue
|
0
scripts/utils/color_converter/__init__.py
Normal file
0
scripts/utils/color_converter/__init__.py
Normal file
26
scripts/utils/color_converter/color_converter.py
Normal file
26
scripts/utils/color_converter/color_converter.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class ColorConverter(ABC):
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def hex_to_rgba(hex_color):
|
||||
"""
|
||||
Converts a HEX color code to RGBA format.
|
||||
:param hex_color: HEX color code (e.g., '#ff5733' or 'ff5733').
|
||||
:return: Tuple of RGBA values (red, green, blue, alpha).
|
||||
:raises ValueError: If the HEX color code is invalid.
|
||||
"""
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def hsl_to_rgb(hue, saturation, lightness):
|
||||
"""
|
||||
Converts HSL color values to RGB format.
|
||||
:param hue: Hue value (0-360).
|
||||
:param saturation: Saturation value (0-1).
|
||||
:param lightness: Lightness value (0-1).
|
||||
:return: Tuple of RGB values (red, green, blue) in range(0-255).
|
||||
"""
|
||||
pass
|
43
scripts/utils/color_converter/color_converter_impl.py
Normal file
43
scripts/utils/color_converter/color_converter_impl.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import colorsys
|
||||
|
||||
from scripts.utils.color_converter.color_converter import ColorConverter
|
||||
|
||||
|
||||
class ColorConverterImpl(ColorConverter):
|
||||
@staticmethod
|
||||
def hex_to_rgba(hex_color):
|
||||
try:
|
||||
hex_color = hex_color.lstrip('#')
|
||||
|
||||
# Handle shorthand hex colors (e.g., #fff)
|
||||
if len(hex_color) == 3:
|
||||
hex_color = ''.join([char * 2 for char in hex_color])
|
||||
|
||||
# Add alpha channel if missing
|
||||
if len(hex_color) == 6:
|
||||
hex_color += "ff"
|
||||
|
||||
# Validate the hex color
|
||||
int(hex_color, 16)
|
||||
|
||||
except ValueError:
|
||||
raise ValueError(f'Error: Invalid HEX color code: #{hex_color}')
|
||||
|
||||
else:
|
||||
return int(hex_color[0:2], 16), \
|
||||
int(hex_color[2:4], 16), \
|
||||
int(hex_color[4:6], 16), \
|
||||
int(hex_color[6:8], 16) / 255
|
||||
|
||||
@staticmethod
|
||||
def hsl_to_rgb(hue, saturation, lightness):
|
||||
if hue > 360 or hue < 0:
|
||||
raise ValueError(f'Hue must be between 0 and 360, not {hue}')
|
||||
if saturation > 1 or saturation < 0:
|
||||
raise ValueError(f'Saturation must be between 0 and 1, not {saturation}')
|
||||
if lightness > 1 or lightness < 0:
|
||||
raise ValueError(f'Lightness must be between 0 and 1, not {lightness}')
|
||||
|
||||
h = hue / 360
|
||||
red, green, blue = [round(item * 255) for item in colorsys.hls_to_rgb(h, lightness, saturation)]
|
||||
return red, green, blue
|
@@ -7,6 +7,9 @@ def get_version_folders(version, base_path):
|
||||
:param base_path: base path to version folders
|
||||
:return: list of matching version folders
|
||||
"""
|
||||
if not os.path.exists(base_path):
|
||||
return []
|
||||
|
||||
version_folders = os.listdir(base_path)
|
||||
version = int(version.split('.')[0]) # Use only the major version for comparison
|
||||
matching_folders = []
|
||||
|
@@ -1,19 +1,40 @@
|
||||
import os
|
||||
|
||||
from scripts.utils import generate_file
|
||||
|
||||
|
||||
class StyleManager:
|
||||
"""Manages the style files for the theme."""
|
||||
|
||||
def __init__(self, output_file: str):
|
||||
"""
|
||||
:param output_file: The path to the output file where styles will be combined.
|
||||
"""
|
||||
self.output_file = output_file
|
||||
|
||||
def append_content(self, content: str):
|
||||
"""
|
||||
Append content to the output file.
|
||||
:raises FileNotFoundError: if the file does not exist.
|
||||
"""
|
||||
if not os.path.exists(self.output_file):
|
||||
raise FileNotFoundError(f"The file {self.output_file} does not exist.")
|
||||
with open(self.output_file, 'a') as output:
|
||||
output.write(content + '\n')
|
||||
output.write('\n' + content)
|
||||
|
||||
def prepend_content(self, content: str):
|
||||
"""
|
||||
Prepend content to the output file.
|
||||
:raises FileNotFoundError: if the file does not exist.
|
||||
"""
|
||||
with open(self.output_file, 'r') as output:
|
||||
main_content = output.read()
|
||||
with open(self.output_file, 'w') as output:
|
||||
output.write(content + '\n' + main_content)
|
||||
|
||||
def generate_combined_styles(self, sources_location: str, temp_folder: str):
|
||||
"""
|
||||
Generate the combined styles file
|
||||
by merging all styles from the source location.
|
||||
"""
|
||||
generate_file(sources_location, temp_folder, self.output_file)
|
44
scripts/utils/theme/color_replacement_generator.py
Normal file
44
scripts/utils/theme/color_replacement_generator.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import copy
|
||||
|
||||
from scripts.install.colors_definer import ColorsDefiner
|
||||
from scripts.types.installation_color import InstallationMode, InstallationColor
|
||||
from scripts.utils.color_converter.color_converter import ColorConverter
|
||||
|
||||
|
||||
class ColorReplacementGenerator:
|
||||
def __init__(self, colors_provider: ColorsDefiner, color_converter: ColorConverter):
|
||||
self.colors = copy.deepcopy(colors_provider)
|
||||
self.color_converter = color_converter
|
||||
|
||||
def convert(self, mode: InstallationMode, theme_color: InstallationColor) -> list[tuple[str, str]]:
|
||||
"""Generate a list of color replacements for the given theme color and mode"""
|
||||
return [
|
||||
(element, self._create_rgba_value(element, mode, theme_color))
|
||||
for element in self.colors.replacers
|
||||
]
|
||||
|
||||
def _create_rgba_value(self, element: str, mode: str, theme_color: InstallationColor) -> str:
|
||||
"""Create RGBA value for the specified element"""
|
||||
color_def = self._get_color_definition(element, mode)
|
||||
|
||||
lightness = int(color_def["l"]) / 100
|
||||
saturation = int(color_def["s"]) / 100
|
||||
if theme_color.saturation is not None:
|
||||
saturation *= theme_color.saturation / 100
|
||||
alpha = color_def["a"]
|
||||
|
||||
red, green, blue = self.color_converter.hsl_to_rgb(
|
||||
theme_color.hue, saturation, lightness
|
||||
)
|
||||
|
||||
return f"rgba({red}, {green}, {blue}, {alpha})"
|
||||
|
||||
def _get_color_definition(self, element: str, mode: str) -> dict:
|
||||
"""Get color definition for element, handling defaults if needed"""
|
||||
replacer = self.colors.replacers[element]
|
||||
|
||||
if mode not in replacer and replacer["default"]:
|
||||
default_element = replacer["default"]
|
||||
return self.colors.replacers[default_element][mode]
|
||||
|
||||
return replacer[mode]
|
@@ -2,11 +2,12 @@ import os.path
|
||||
|
||||
from scripts import config
|
||||
from scripts.install.colors_definer import ColorsDefiner
|
||||
from scripts.utils.color_converter import ColorConverterImpl
|
||||
from scripts.utils.color_converter.color_converter_impl import ColorConverterImpl
|
||||
from scripts.utils.logger.console import Console
|
||||
from scripts.utils.style_manager import StyleManager
|
||||
from scripts.utils.theme.theme import Theme
|
||||
from scripts.utils.theme.theme_color_applier import ColorReplacementGenerator, ThemeColorApplier
|
||||
from scripts.utils.theme.theme_color_applier import ThemeColorApplier
|
||||
from scripts.utils.theme.color_replacement_generator import ColorReplacementGenerator
|
||||
from scripts.utils.theme.theme_installer import ThemeInstaller
|
||||
from scripts.utils.theme.theme_path_provider import ThemePathProvider
|
||||
from scripts.utils.theme.theme_preparation import ThemePreparation
|
||||
|
@@ -1,16 +1,14 @@
|
||||
import copy
|
||||
import os
|
||||
|
||||
from scripts.install.colors_definer import ColorsDefiner
|
||||
from scripts.types.installation_color import InstallationColor, InstallationMode
|
||||
from scripts.utils import replace_keywords
|
||||
from scripts.utils.color_converter import ColorConverter
|
||||
from scripts.utils.theme.color_replacement_generator import ColorReplacementGenerator
|
||||
|
||||
|
||||
class ThemeColorApplier:
|
||||
"""Class to apply theme colors to files in a directory."""
|
||||
|
||||
def __init__(self, color_replacement_generator: "ColorReplacementGenerator"):
|
||||
def __init__(self, color_replacement_generator: ColorReplacementGenerator):
|
||||
self.color_replacement_generator = color_replacement_generator
|
||||
|
||||
def apply(self, theme_color: InstallationColor, destination: str, mode: InstallationMode):
|
||||
@@ -20,42 +18,3 @@ class ThemeColorApplier:
|
||||
for filename in os.listdir(destination):
|
||||
file_path = os.path.join(destination, filename)
|
||||
replace_keywords(file_path, *replacements)
|
||||
|
||||
|
||||
class ColorReplacementGenerator:
|
||||
def __init__(self, colors_provider: ColorsDefiner, color_converter: ColorConverter):
|
||||
self.colors = copy.deepcopy(colors_provider)
|
||||
self.color_converter = color_converter
|
||||
|
||||
def convert(self, mode: InstallationMode, theme_color: InstallationColor) -> list[tuple[str, str]]:
|
||||
"""Generate a list of color replacements for the given theme color and mode"""
|
||||
return [
|
||||
(element, self._create_rgba_value(element, mode, theme_color))
|
||||
for element in self.colors.replacers
|
||||
]
|
||||
|
||||
def _create_rgba_value(self, element: str, mode: str, theme_color: InstallationColor) -> str:
|
||||
"""Create RGBA value for the specified element"""
|
||||
color_def = self._get_color_definition(element, mode)
|
||||
|
||||
lightness = int(color_def["l"]) / 100
|
||||
saturation = int(color_def["s"]) / 100
|
||||
if theme_color.saturation is not None:
|
||||
saturation *= theme_color.saturation / 100
|
||||
alpha = color_def["a"]
|
||||
|
||||
red, green, blue = self.color_converter.hsl_to_rgb(
|
||||
theme_color.hue, saturation, lightness
|
||||
)
|
||||
|
||||
return f"rgba({red}, {green}, {blue}, {alpha})"
|
||||
|
||||
def _get_color_definition(self, element: str, mode: str) -> dict:
|
||||
"""Get color definition for element, handling defaults if needed"""
|
||||
replacer = self.colors.replacers[element]
|
||||
|
||||
if mode not in replacer and replacer["default"]:
|
||||
default_element = replacer["default"]
|
||||
return self.colors.replacers[default_element][mode]
|
||||
|
||||
return replacer[mode]
|
@@ -1,4 +1,20 @@
|
||||
import os
|
||||
|
||||
|
||||
class ThemePathProvider:
|
||||
@staticmethod
|
||||
def get_theme_path(themes_folder: str, path_name: str, theme_mode: str, theme_type: str) -> str:
|
||||
return f"{themes_folder}/Marble-{path_name}-{theme_mode}/{theme_type}/"
|
||||
def get_theme_path(themes_folder: str, color_name: str, theme_mode: str, theme_type: str) -> str:
|
||||
"""
|
||||
Generates the path for the theme based on the provided parameters.
|
||||
:param themes_folder: The base folder where themes are stored.
|
||||
:param color_name: The name of the color scheme.
|
||||
:param theme_mode: The mode of the theme (e.g., 'light' or 'dark').
|
||||
:param theme_type: The type of the theme (e.g., 'gnome-shell', 'gtk').
|
||||
"""
|
||||
if not themes_folder or not color_name or not theme_mode or not theme_type:
|
||||
raise ValueError("All parameters must be non-empty strings.")
|
||||
|
||||
marble_name = '-'.join(["Marble", color_name, theme_mode])
|
||||
final_path = os.path.join(themes_folder, marble_name, theme_type, "")
|
||||
|
||||
return final_path
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from scripts.utils import replace_keywords
|
||||
from scripts.utils.theme.theme_temp_manager import ThemeTempManager
|
||||
@@ -45,11 +44,10 @@ class ThemePreparation:
|
||||
"""
|
||||
Extract theme from source folder and prepare it for installation.
|
||||
"""
|
||||
self.file_manager.prepare_files(self.sources_location)
|
||||
self.file_manager.copy_to_temp(self.sources_location)
|
||||
self.style_manager.generate_combined_styles(self.sources_location, self.temp_folder)
|
||||
self.file_manager.cleanup()
|
||||
|
||||
@warnings.deprecated
|
||||
def replace_filled_keywords(self):
|
||||
"""
|
||||
Replace keywords in the theme files for filled mode.
|
||||
|
@@ -1,8 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from scripts.utils import copy_files
|
||||
|
||||
|
||||
class ThemeTempManager:
|
||||
"""
|
||||
@@ -10,18 +8,21 @@ class ThemeTempManager:
|
||||
"""
|
||||
def __init__(self, temp_folder: str):
|
||||
self.temp_folder = temp_folder
|
||||
os.makedirs(self.temp_folder, exist_ok=True)
|
||||
|
||||
def copy_to_temp(self, content: str):
|
||||
"""
|
||||
Copy a file or directory to the temporary folder.
|
||||
If the content is a file, it will be copied directly.
|
||||
If the content is a directory, all its contents will be copied to the temp folder.
|
||||
"""
|
||||
if os.path.isfile(content):
|
||||
shutil.copy(content, self.temp_folder)
|
||||
final_path = os.path.join(self.temp_folder, os.path.basename(content))
|
||||
shutil.copy(content, final_path)
|
||||
else:
|
||||
shutil.copytree(content, self.temp_folder)
|
||||
shutil.copytree(content, self.temp_folder, dirs_exist_ok=True)
|
||||
return self
|
||||
|
||||
def prepare_files(self, sources_location: str):
|
||||
"""Prepare files in temp folder"""
|
||||
copy_files(sources_location, self.temp_folder)
|
||||
|
||||
def cleanup(self):
|
||||
"""Remove temporary folders"""
|
||||
shutil.rmtree(f"{self.temp_folder}/.css/", ignore_errors=True)
|
||||
|
0
tests/utils/color_converter/__init__.py
Normal file
0
tests/utils/color_converter/__init__.py
Normal file
64
tests/utils/color_converter/test_color_converter_impl.py
Normal file
64
tests/utils/color_converter/test_color_converter_impl.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import unittest
|
||||
|
||||
from scripts.utils.color_converter.color_converter_impl import ColorConverterImpl
|
||||
|
||||
|
||||
class ColorConverterImplTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.converter = ColorConverterImpl()
|
||||
|
||||
def test_hex_to_rgba_is_valid(self):
|
||||
hex_color = "#ff5733"
|
||||
expected_rgba = (255, 87, 51, 1.0)
|
||||
|
||||
result = self.converter.hex_to_rgba(hex_color)
|
||||
|
||||
self.assertEqual(result, expected_rgba)
|
||||
|
||||
def test_hex_to_rgba_is_invalid(self):
|
||||
hex_color = "#invalid"
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.converter.hex_to_rgba(hex_color)
|
||||
|
||||
def test_hex_to_rgba_with_alpha_is_valid(self):
|
||||
hex_color = "#ff5733ff"
|
||||
expected_rgba = (255, 87, 51, 1.0)
|
||||
|
||||
result = self.converter.hex_to_rgba(hex_color)
|
||||
|
||||
self.assertEqual(result, expected_rgba)
|
||||
|
||||
def test_hex_to_rgba_with_shorthand_is_valid(self):
|
||||
hex_color = "#fff"
|
||||
expected_rgba = (255, 255, 255, 1.0)
|
||||
|
||||
result = self.converter.hex_to_rgba(hex_color)
|
||||
|
||||
self.assertEqual(result, expected_rgba)
|
||||
|
||||
def test_hsl_to_rgb_is_valid(self):
|
||||
hue = 360
|
||||
saturation = 1
|
||||
lightness = 0.5
|
||||
expected_rgb = (255, 0, 0)
|
||||
|
||||
result = self.converter.hsl_to_rgb(hue, saturation, lightness)
|
||||
|
||||
self.assertEqual(result, expected_rgb)
|
||||
|
||||
def test_hsl_to_rgb_with_overflow_hue_is_invalid(self):
|
||||
hue = 400
|
||||
saturation = 1
|
||||
lightness = 0.5
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.converter.hsl_to_rgb(hue, saturation, lightness)
|
||||
|
||||
def test_hsl_to_rgb_with_invalid_saturation_and_lightness_is_invalid(self):
|
||||
hue = 360
|
||||
saturation = 1.5
|
||||
lightness = -2
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.converter.hsl_to_rgb(hue, saturation, lightness)
|
78
tests/utils/test_style_manager.py
Normal file
78
tests/utils/test_style_manager.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
|
||||
from scripts import config
|
||||
from scripts.utils.style_manager import StyleManager
|
||||
from .._helpers import create_dummy_file
|
||||
|
||||
|
||||
class StyleManagerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp_folder = os.path.join(config.temp_tests_folder, "style_manager")
|
||||
os.makedirs(self.temp_folder, exist_ok=True)
|
||||
self.output_file = os.path.join(self.temp_folder, "output.css")
|
||||
self.manager = StyleManager(output_file=self.output_file)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_folder, ignore_errors=True)
|
||||
|
||||
def test_append_content(self):
|
||||
start_css = "body { background-color: blue; }"
|
||||
create_dummy_file(self.output_file, start_css)
|
||||
end_css = "h1 { color: red; }"
|
||||
|
||||
self.manager.append_content(end_css)
|
||||
|
||||
with open(self.output_file, 'r') as f:
|
||||
content = f.read()
|
||||
split_content = content.splitlines()
|
||||
assert split_content[0] == start_css
|
||||
assert split_content[1] == end_css
|
||||
os.remove(self.output_file)
|
||||
|
||||
def test_append_does_not_create_file(self):
|
||||
end_css = "h1 { color: red; }"
|
||||
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
self.manager.append_content(end_css)
|
||||
|
||||
def test_prepend_content(self):
|
||||
start_css = "body { background-color: blue; }"
|
||||
create_dummy_file(self.output_file, start_css)
|
||||
prepend_css = "h1 { color: red; }"
|
||||
|
||||
self.manager.prepend_content(prepend_css)
|
||||
|
||||
with open(self.output_file, 'r') as f:
|
||||
content = f.read()
|
||||
split_content = content.splitlines()
|
||||
assert split_content[0] == prepend_css
|
||||
assert split_content[1] == start_css
|
||||
os.remove(self.output_file)
|
||||
|
||||
def test_prepend_does_not_create_file(self):
|
||||
prepend_css = "h1 { color: red; }"
|
||||
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
self.manager.prepend_content(prepend_css)
|
||||
|
||||
def test_generate_combined_styles(self):
|
||||
source_folder = os.path.join(config.temp_tests_folder, "style_manager_source")
|
||||
source_css_folder = os.path.join(source_folder, ".css")
|
||||
first_file = os.path.join(source_css_folder, "file1.css")
|
||||
second_file = os.path.join(source_css_folder, "file2.css")
|
||||
first_css = "body { background-color: blue; }"
|
||||
second_css = "h1 { color: red; }"
|
||||
create_dummy_file(first_file, first_css)
|
||||
create_dummy_file(second_file, second_css)
|
||||
|
||||
self.manager.generate_combined_styles(source_folder, self.temp_folder)
|
||||
|
||||
with open(self.output_file, 'r') as f:
|
||||
content = f.read()
|
||||
split_content = content.splitlines()
|
||||
assert first_css in split_content
|
||||
assert second_css in split_content
|
||||
os.remove(self.output_file)
|
||||
shutil.rmtree(source_folder, ignore_errors=True)
|
0
tests/utils/theme/__init__.py
Normal file
0
tests/utils/theme/__init__.py
Normal file
72
tests/utils/theme/assets/colors.json
Normal file
72
tests/utils/theme/assets/colors.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"elements": {
|
||||
"BUTTON-COLOR": {
|
||||
"default": "ACCENT-COLOR"
|
||||
},
|
||||
"ACCENT-COLOR": {
|
||||
"light": {
|
||||
"s": 52,
|
||||
"l": 67,
|
||||
"a": 1
|
||||
},
|
||||
"dark": {
|
||||
"s": 42,
|
||||
"l": 26,
|
||||
"a": 1
|
||||
}
|
||||
},
|
||||
"ACCENT_HOVER": {
|
||||
"light": {
|
||||
"s": 50,
|
||||
"l": 60,
|
||||
"a": 0.8
|
||||
},
|
||||
"dark": {
|
||||
"s": 66,
|
||||
"l": 22,
|
||||
"a": 0.4
|
||||
}
|
||||
}
|
||||
},
|
||||
"colors": {
|
||||
"red": {
|
||||
"h": 0
|
||||
},
|
||||
"gray": {
|
||||
"h": 0,
|
||||
"s": 0
|
||||
},
|
||||
"expected": {
|
||||
"BUTTON-COLOR": {
|
||||
"0,100": {
|
||||
"light": "rgba(215, 127, 127, 1)",
|
||||
"dark": "rgba(94, 38, 38, 1)"
|
||||
},
|
||||
"0,0": {
|
||||
"light": "rgba(171, 171, 171, 1)",
|
||||
"dark": "rgba(66, 66, 66, 1)"
|
||||
}
|
||||
},
|
||||
"ACCENT-COLOR": {
|
||||
"0,100": {
|
||||
"light": "rgba(215, 127, 127, 1)",
|
||||
"dark": "rgba(94, 38, 38, 1)"
|
||||
},
|
||||
"0,0": {
|
||||
"light": "rgba(171, 171, 171, 1)",
|
||||
"dark": "rgba(66, 66, 66, 1)"
|
||||
}
|
||||
},
|
||||
"ACCENT_HOVER": {
|
||||
"0,100": {
|
||||
"light": "rgba(204, 102, 102, 0.8)",
|
||||
"dark": "rgba(93, 19, 19, 0.4)"
|
||||
},
|
||||
"0,0": {
|
||||
"light": "rgba(153, 153, 153, 0.8)",
|
||||
"dark": "rgba(56, 56, 56, 0.4)"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
64
tests/utils/theme/test_color_replacement_generator.py
Normal file
64
tests/utils/theme/test_color_replacement_generator.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import os.path
|
||||
import unittest
|
||||
|
||||
from scripts.install.colors_definer import ColorsDefiner
|
||||
from scripts.types.installation_color import InstallationColor, InstallationMode
|
||||
from scripts.utils.color_converter.color_converter_impl import ColorConverterImpl
|
||||
from scripts.utils.theme.color_replacement_generator import ColorReplacementGenerator
|
||||
|
||||
class ColorReplacementGeneratorTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
colors_location = os.path.join(os.path.dirname(__file__), "assets", "colors.json")
|
||||
self.colors_provider = ColorsDefiner(colors_location)
|
||||
self.color_converter = ColorConverterImpl()
|
||||
self.generator = ColorReplacementGenerator(self.colors_provider, self.color_converter)
|
||||
|
||||
def test_convert_red_color_in_dark_mode_generates_correct_rgba(self):
|
||||
theme_color = InstallationColor(hue=0, saturation=None, modes=[])
|
||||
mode: InstallationMode = "dark"
|
||||
expected_output = self._get_expected_output(theme_color, mode)
|
||||
|
||||
actual_output = self.generator.convert(mode, theme_color)
|
||||
|
||||
self._assert_expected_and_actual_replacers_match(expected_output, actual_output)
|
||||
|
||||
def test_convert_gray_color_in_light_mode_generates_correct_rgba(self):
|
||||
theme_color = InstallationColor(hue=0, saturation=0, modes=[])
|
||||
mode: InstallationMode = "light"
|
||||
expected_output = self._get_expected_output(theme_color, mode)
|
||||
|
||||
actual_output = self.generator.convert(mode, theme_color)
|
||||
|
||||
self._assert_expected_and_actual_replacers_match(expected_output, actual_output)
|
||||
|
||||
def test_convert_not_existent_mode_raises_key_error(self):
|
||||
theme_color = InstallationColor(hue=0, saturation=0, modes=[])
|
||||
mode = "not_existent_mode"
|
||||
|
||||
with self.assertRaises(KeyError):
|
||||
# noinspection PyTypeChecker
|
||||
self.generator.convert(mode, theme_color)
|
||||
|
||||
def _get_expected_output(self, theme_color: InstallationColor, mode: str):
|
||||
return [
|
||||
("ACCENT-COLOR", self._get_rgba("ACCENT-COLOR", theme_color, mode)),
|
||||
("ACCENT_HOVER", self._get_rgba("ACCENT_HOVER", theme_color, mode)),
|
||||
("BUTTON-COLOR", self._get_rgba("BUTTON-COLOR", theme_color, mode)),
|
||||
]
|
||||
|
||||
def _get_rgba(self, replacer_name: str, theme_color: InstallationColor, mode: str):
|
||||
expected_colors: dict = self.colors_provider.colors.get("expected")
|
||||
replacer_colors = expected_colors.get(replacer_name)
|
||||
saturation = theme_color.saturation if theme_color.saturation is not None else 100
|
||||
variant_colors = replacer_colors.get(f"{theme_color.hue},{saturation}")
|
||||
expected_rgba = variant_colors.get(mode)
|
||||
return expected_rgba
|
||||
|
||||
@staticmethod
|
||||
def _assert_expected_and_actual_replacers_match(expected: list, actual: list):
|
||||
for expected_element, expected_rgba in expected:
|
||||
actual_rgba = next(
|
||||
(rgba for element, rgba in actual if element == expected_element), None
|
||||
)
|
||||
assert actual_rgba is not None
|
||||
assert expected_rgba == actual_rgba
|
76
tests/utils/theme/test_gnome_shell_theme_builder.py
Normal file
76
tests/utils/theme/test_gnome_shell_theme_builder.py
Normal file
@@ -0,0 +1,76 @@
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
import os
|
||||
|
||||
from scripts.utils.theme.gnome_shell_theme_builder import GnomeShellThemeBuilder
|
||||
|
||||
|
||||
class GnomeShellThemeBuilderTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.colors_provider = Mock()
|
||||
self.builder = GnomeShellThemeBuilder(self.colors_provider)
|
||||
|
||||
def test_builder_method_chaining_works_correctly(self):
|
||||
result = (self.builder.with_theme_name("test-theme")
|
||||
.with_mode("dark")
|
||||
.filled()
|
||||
.with_temp_folder("/tmp/test"))
|
||||
|
||||
self.assertIs(result, self.builder)
|
||||
self.assertEqual("test-theme", self.builder.theme_name)
|
||||
self.assertEqual("dark", self.builder.mode)
|
||||
self.assertTrue(self.builder.is_filled)
|
||||
self.assertEqual("/tmp/test", self.builder._base_temp_folder)
|
||||
|
||||
def test_paths_update_when_base_folder_changes(self):
|
||||
self.builder.with_temp_folder("/custom/temp")
|
||||
|
||||
expected_temp_folder = os.path.join("/custom/temp", self.builder.theme_name)
|
||||
expected_main_styles = os.path.join(expected_temp_folder, f"{self.builder.theme_name}.css")
|
||||
|
||||
self.assertEqual(expected_temp_folder, self.builder.temp_folder)
|
||||
self.assertEqual(expected_main_styles, self.builder.main_styles)
|
||||
|
||||
def test_paths_update_when_theme_name_changes(self):
|
||||
original_temp_folder = self.builder.temp_folder
|
||||
original_main_styles = self.builder.main_styles
|
||||
|
||||
self.builder.with_theme_name("custom-theme")
|
||||
|
||||
self.assertNotEqual(original_temp_folder, self.builder.temp_folder)
|
||||
self.assertNotEqual(original_main_styles, self.builder.main_styles)
|
||||
self.assertEqual(os.path.join(self.builder._base_temp_folder, "custom-theme"), self.builder.temp_folder)
|
||||
self.assertEqual(os.path.join(self.builder.temp_folder, "custom-theme.css"), self.builder.main_styles)
|
||||
|
||||
def test_default_values_are_set_properly(self):
|
||||
builder = GnomeShellThemeBuilder(self.colors_provider)
|
||||
|
||||
self.assertEqual("gnome-shell", builder.theme_name)
|
||||
self.assertIsNone(builder.mode)
|
||||
self.assertFalse(builder.is_filled)
|
||||
self.assertIsNone(builder.preparation)
|
||||
self.assertIsNone(builder.installer)
|
||||
|
||||
def test_build_correctly_resolves_dependencies(self):
|
||||
self.builder.build()
|
||||
|
||||
self.assertIsNotNone(self.builder.preparation)
|
||||
self.assertIsNotNone(self.builder.installer)
|
||||
|
||||
def test_build_correctly_creates_theme(self):
|
||||
self.builder.with_mode("light").filled()
|
||||
|
||||
theme = self.builder.build()
|
||||
|
||||
self.assertEqual(theme._preparation, self.builder.preparation)
|
||||
self.assertEqual(theme._installer, self.builder.installer)
|
||||
self.assertTrue(theme.is_filled)
|
||||
self.assertTrue(len(theme.modes) == 1)
|
||||
self.assertEqual(theme.modes[0], "light")
|
||||
|
||||
def test_filled_method_with_parameter(self):
|
||||
self.builder.filled(False)
|
||||
self.assertFalse(self.builder.is_filled)
|
||||
|
||||
self.builder.filled(True)
|
||||
self.assertTrue(self.builder.is_filled)
|
90
tests/utils/theme/test_theme.py
Normal file
90
tests/utils/theme/test_theme.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import os.path
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from scripts import config
|
||||
from scripts.types.installation_color import InstallationColor
|
||||
from scripts.utils.theme.theme import Theme
|
||||
|
||||
|
||||
class ThemeTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.mock_preparation = MagicMock()
|
||||
self.mock_installer = MagicMock()
|
||||
|
||||
temp_folder = os.path.join(config.temp_tests_folder, "theme_temp")
|
||||
destination_folder = os.path.join(temp_folder, "theme_destination")
|
||||
|
||||
self.mock_preparation.temp_folder = temp_folder
|
||||
self.mock_preparation.combined_styles_location = os.path.join(temp_folder, "styles.css")
|
||||
self.mock_installer.destination_folder = destination_folder
|
||||
self.mock_installer.theme_type = "gtk"
|
||||
|
||||
self.theme = Theme(self.mock_preparation, self.mock_installer)
|
||||
|
||||
def test_default_initialization_works_correctly(self):
|
||||
self.assertEqual(self.theme.modes, ['light', 'dark'])
|
||||
self.assertFalse(self.theme.is_filled)
|
||||
|
||||
def test_initialization_with_specific_mode_works_correctly(self):
|
||||
theme_light = Theme(self.mock_preparation, self.mock_installer, mode='light')
|
||||
self.assertEqual(theme_light.modes, ['light'])
|
||||
|
||||
def test_initialization_with_is_filled_works_correctly(self):
|
||||
theme_filled = Theme(self.mock_preparation, self.mock_installer, is_filled=True)
|
||||
self.assertTrue(theme_filled.is_filled)
|
||||
|
||||
def test_properties_fetch_values_correctly(self):
|
||||
temp_folder = os.path.join(config.temp_tests_folder, "theme_temp")
|
||||
destination_folder = os.path.join(temp_folder, "theme_destination")
|
||||
|
||||
self.assertEqual(self.theme.temp_folder, temp_folder)
|
||||
self.assertEqual(self.theme.destination_folder, destination_folder)
|
||||
self.assertEqual(self.theme.main_styles, os.path.join(temp_folder, "styles.css"))
|
||||
self.assertEqual(self.theme.theme_name, "gtk")
|
||||
|
||||
def test_add_operator_called_once_and_return_value(self):
|
||||
result = self.theme + "additional styles"
|
||||
|
||||
self.mock_preparation.__iadd__.assert_called_once_with("additional styles")
|
||||
self.assertEqual(result, self.theme)
|
||||
|
||||
def test_mul_operator_called_once_and_return_value(self):
|
||||
result = self.theme * "/path/to/file"
|
||||
|
||||
self.mock_preparation.__imul__.assert_called_once_with("/path/to/file")
|
||||
self.assertEqual(result, self.theme)
|
||||
|
||||
def test_add_to_start_called_once_and_return_value(self):
|
||||
result = self.theme.add_to_start("starting content")
|
||||
|
||||
self.mock_preparation.add_to_start.assert_called_once_with("starting content")
|
||||
self.assertEqual(result, self.theme)
|
||||
|
||||
def test_prepare_called_once(self):
|
||||
self.theme.prepare()
|
||||
|
||||
self.mock_preparation.prepare.assert_called_once()
|
||||
|
||||
def test_install_without_optional_params_called_correctly(self):
|
||||
self.theme.install(200, "Green")
|
||||
|
||||
args = self.mock_installer.install.call_args[0]
|
||||
self.assertEqual(args[0].hue, 200)
|
||||
self.assertIsNone(args[0].saturation)
|
||||
self.assertEqual(args[1], "Green")
|
||||
self.assertIsNone(args[2])
|
||||
|
||||
def test_install_with_optional_params_called_correctly(self):
|
||||
self.theme.install(hue=180, name="Blue", sat=0.5, destination="/custom/dest")
|
||||
|
||||
self.mock_installer.install.assert_called_once()
|
||||
args = self.mock_installer.install.call_args[0]
|
||||
|
||||
theme_color = args[0]
|
||||
self.assertIsInstance(theme_color, InstallationColor)
|
||||
self.assertEqual(theme_color.hue, 180)
|
||||
self.assertEqual(theme_color.saturation, 0.5)
|
||||
self.assertEqual(theme_color.modes, ['light', 'dark'])
|
||||
self.assertEqual(args[1], "Blue")
|
||||
self.assertEqual(args[2], "/custom/dest")
|
52
tests/utils/theme/test_theme_color_applier.py
Normal file
52
tests/utils/theme/test_theme_color_applier.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import os.path
|
||||
import shutil
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
|
||||
from scripts import config
|
||||
from scripts.utils.theme.theme_color_applier import ThemeColorApplier
|
||||
from ..._helpers import create_dummy_file
|
||||
|
||||
|
||||
class ThemeColorApplierTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
color_replacement_generator = Mock()
|
||||
color_replacement_generator.convert.return_value = [
|
||||
("ACCENT-COLOR", "rgba(255, 0, 0, 1)"),
|
||||
("ACCENT_HOVER", "rgba(255, 0, 0, 0.8)"),
|
||||
("BACKGROUND-COLOR", "rgba(0, 0, 0, 1)")
|
||||
]
|
||||
|
||||
self.temp_folder = os.path.join(config.temp_tests_folder, "color_applier")
|
||||
self._setup_temp_folder()
|
||||
|
||||
self.color_applier = ThemeColorApplier(color_replacement_generator)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_folder, ignore_errors=True)
|
||||
|
||||
def _setup_temp_folder(self):
|
||||
self.first_file = os.path.join(self.temp_folder, "file1.css")
|
||||
self.second_file = os.path.join(self.temp_folder, "file2.css")
|
||||
self.first_css = "body { background-color: ACCENT-COLOR; color: ACCENT_HOVER; }"
|
||||
self.second_css = "body { background-color: BACKGROUND-COLOR; }"
|
||||
create_dummy_file(self.first_file, self.first_css)
|
||||
create_dummy_file(self.second_file, self.second_css)
|
||||
|
||||
def test_colors_in_files_are_replaced_correctly(self):
|
||||
theme_color = Mock()
|
||||
|
||||
self.color_applier.apply(theme_color, self.temp_folder, "dark")
|
||||
|
||||
with open(self.first_file, "r") as file:
|
||||
content = file.read()
|
||||
replaced = self.first_css
|
||||
replaced = replaced.replace("ACCENT-COLOR", "rgba(255, 0, 0, 1)")
|
||||
replaced = replaced.replace("ACCENT_HOVER", "rgba(255, 0, 0, 0.8)")
|
||||
assert content == replaced
|
||||
|
||||
with open(self.second_file, "r") as file:
|
||||
content = file.read()
|
||||
replaced = self.second_css
|
||||
replaced = replaced.replace("BACKGROUND-COLOR", "rgba(0, 0, 0, 1)")
|
||||
assert content == replaced
|
109
tests/utils/theme/test_theme_installer.py
Normal file
109
tests/utils/theme/test_theme_installer.py
Normal file
@@ -0,0 +1,109 @@
|
||||
import os
|
||||
import shutil
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
|
||||
from scripts import config
|
||||
from scripts.utils.theme.theme_installer import ThemeInstaller
|
||||
from scripts.utils.theme.theme_path_provider import ThemePathProvider
|
||||
from ..._helpers import create_dummy_file
|
||||
|
||||
|
||||
class ThemeInstallerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.theme_type = "gnome-shell"
|
||||
self.source_folder = os.path.join(config.temp_tests_folder, "theme_installer_source")
|
||||
self.destination_folder = os.path.join(config.temp_tests_folder, "theme_installer_destination")
|
||||
self.custom_destination_folder = os.path.join(config.temp_tests_folder, "theme_installer_custom_destination")
|
||||
|
||||
self.logger_factory = Mock()
|
||||
self.color_applier = Mock()
|
||||
self.path_provider = ThemePathProvider()
|
||||
self.path_provider.get_theme_path = Mock(return_value=self.destination_folder)
|
||||
|
||||
self.theme_installer = ThemeInstaller(
|
||||
theme_type=self.theme_type,
|
||||
source_folder=self.source_folder,
|
||||
destination_folder=self.destination_folder,
|
||||
logger_factory=self.logger_factory,
|
||||
color_applier=self.color_applier,
|
||||
path_provider=self.path_provider,
|
||||
)
|
||||
|
||||
self._setup_source_folder()
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.source_folder, ignore_errors=True)
|
||||
shutil.rmtree(self.destination_folder, ignore_errors=True)
|
||||
shutil.rmtree(self.custom_destination_folder, ignore_errors=True)
|
||||
|
||||
def _setup_source_folder(self):
|
||||
os.makedirs(self.source_folder, exist_ok=True)
|
||||
first_file = os.path.join(self.source_folder, "file1.css")
|
||||
second_file = os.path.join(self.source_folder, "file2.css")
|
||||
first_css = "body { background-color: ACCENT-COLOR; color: ACCENT_HOVER; }"
|
||||
second_css = "body { background-color: BACKGROUND-COLOR; }"
|
||||
create_dummy_file(first_file, first_css)
|
||||
create_dummy_file(second_file, second_css)
|
||||
|
||||
def test_install_calls_get_theme_path_and_apply_methods_with_correct_parameters(self):
|
||||
theme_color = Mock()
|
||||
theme_color.modes = ["light"]
|
||||
name = "test-theme"
|
||||
|
||||
self.theme_installer.install(theme_color, name)
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.path_provider.get_theme_path.assert_called_once_with(
|
||||
self.destination_folder, name, "light", self.theme_type
|
||||
)
|
||||
self.color_applier.apply.assert_called_once_with(theme_color, self.destination_folder, "light")
|
||||
|
||||
def test_install_with_custom_destination_calls_get_theme_path_and_apply_methods_with_correct_parameters(self):
|
||||
theme_color = Mock()
|
||||
theme_color.modes = ["light"]
|
||||
name = "test-theme"
|
||||
os.makedirs(self.custom_destination_folder, exist_ok=True)
|
||||
|
||||
self.theme_installer.install(theme_color, name, self.custom_destination_folder)
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.path_provider.get_theme_path.assert_not_called()
|
||||
self.color_applier.apply.assert_called_once_with(theme_color, self.custom_destination_folder, "light")
|
||||
|
||||
def test_install_with_multiple_modes_calls_get_theme_path_and_apply_methods_for_each_mode(self):
|
||||
theme_color = Mock()
|
||||
theme_color.modes = ["light", "dark"]
|
||||
name = "test-theme"
|
||||
|
||||
self.theme_installer.install(theme_color, name)
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.assertEqual(self.path_provider.get_theme_path.call_count, 2)
|
||||
self.assertEqual(self.color_applier.apply.call_count, 2)
|
||||
|
||||
def test_install_raises_exception_and_logs_error(self):
|
||||
theme_color = Mock()
|
||||
theme_color.modes = ["light"]
|
||||
name = "test-theme"
|
||||
self.color_applier.apply.side_effect = Exception("Test error")
|
||||
|
||||
with self.assertRaises(Exception):
|
||||
self.theme_installer.install(theme_color, name)
|
||||
|
||||
logger_mock = self.logger_factory.create_logger.return_value
|
||||
self.assertTrue(logger_mock.error.called)
|
||||
|
||||
def test_install_copies_files_to_destination(self):
|
||||
theme_color = Mock()
|
||||
theme_color.modes = ["light"]
|
||||
name = "test-theme"
|
||||
destination = os.path.join(self.destination_folder, "actual_destination")
|
||||
self.path_provider.get_theme_path.return_value = destination
|
||||
|
||||
self.theme_installer.install(theme_color, name)
|
||||
|
||||
first_file_exists = os.path.exists(os.path.join(destination, "file1.css"))
|
||||
second_file_exists = os.path.exists(os.path.join(destination, "file2.css"))
|
||||
self.assertTrue(first_file_exists)
|
||||
self.assertTrue(second_file_exists)
|
28
tests/utils/theme/test_theme_path_provider.py
Normal file
28
tests/utils/theme/test_theme_path_provider.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import unittest
|
||||
|
||||
from scripts.utils.theme.theme_path_provider import ThemePathProvider
|
||||
|
||||
|
||||
class ThemePathProviderTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.theme_path_provider = ThemePathProvider()
|
||||
|
||||
def test_get_theme_path_with_valid_values_returns_correct_path(self):
|
||||
themes_folder = "/usr/share/themes"
|
||||
color_name = "Marble"
|
||||
theme_mode = "dark"
|
||||
theme_type = "gnome-shell"
|
||||
|
||||
expected_path = f"{themes_folder}/Marble-{color_name}-{theme_mode}/{theme_type}/"
|
||||
actual_path = self.theme_path_provider.get_theme_path(themes_folder, color_name, theme_mode, theme_type)
|
||||
|
||||
assert expected_path == actual_path
|
||||
|
||||
def test_get_theme_path_with_empty_values_raises_exception(self):
|
||||
themes_folder = ""
|
||||
color_name = ""
|
||||
theme_mode = ""
|
||||
theme_type = ""
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
self.theme_path_provider.get_theme_path(themes_folder, color_name, theme_mode, theme_type)
|
71
tests/utils/theme/test_theme_temp_manager.py
Normal file
71
tests/utils/theme/test_theme_temp_manager.py
Normal file
@@ -0,0 +1,71 @@
|
||||
import os.path
|
||||
import shutil
|
||||
import unittest
|
||||
|
||||
from scripts import config
|
||||
from scripts.utils.theme.theme_temp_manager import ThemeTempManager
|
||||
from ..._helpers import create_dummy_file
|
||||
|
||||
|
||||
class ThemeTempManagerTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.source_folder = os.path.join(config.temp_tests_folder, "theme_temp_manager_source")
|
||||
self.temp_folder = os.path.join(config.temp_tests_folder, "theme_temp_manager")
|
||||
self.manager = ThemeTempManager(temp_folder=self.temp_folder)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_folder, ignore_errors=True)
|
||||
shutil.rmtree(self.source_folder, ignore_errors=True)
|
||||
|
||||
@staticmethod
|
||||
def _verify_file_copied(source, destination):
|
||||
assert os.path.exists(destination)
|
||||
assert os.path.getsize(destination) == os.path.getsize(source)
|
||||
assert open(destination).read() == open(source).read()
|
||||
|
||||
def test_file_copies_correctly_to_temp(self):
|
||||
test_file_name = "test_file.txt"
|
||||
test_file_location = os.path.join(self.source_folder, test_file_name)
|
||||
create_dummy_file(test_file_location)
|
||||
|
||||
self.manager.copy_to_temp(test_file_location)
|
||||
|
||||
final_file_location = os.path.join(self.temp_folder, test_file_name)
|
||||
self._verify_file_copied(test_file_location, final_file_location)
|
||||
os.remove(final_file_location)
|
||||
|
||||
def test_directory_content_copies_correctly_to_temp(self):
|
||||
test_dir_name = "test_dir"
|
||||
test_dir_location = os.path.join(self.source_folder, test_dir_name)
|
||||
os.makedirs(test_dir_location, exist_ok=True)
|
||||
|
||||
test_file_name = "test_file.txt"
|
||||
test_file_location = os.path.join(test_dir_location, test_file_name)
|
||||
create_dummy_file(test_file_location)
|
||||
|
||||
self.manager.copy_to_temp(test_dir_location)
|
||||
|
||||
final_file_location = os.path.join(self.temp_folder, test_file_name)
|
||||
self._verify_file_copied(test_file_location, final_file_location)
|
||||
os.remove(final_file_location)
|
||||
|
||||
def test_cleanup_removes_temp_folders(self):
|
||||
css_folder = os.path.join(self.temp_folder, ".css")
|
||||
versions_folder = os.path.join(self.temp_folder, ".versions")
|
||||
os.makedirs(css_folder, exist_ok=True)
|
||||
os.makedirs(versions_folder, exist_ok=True)
|
||||
|
||||
self.manager.cleanup()
|
||||
|
||||
assert not os.path.exists(css_folder)
|
||||
assert not os.path.exists(versions_folder)
|
||||
|
||||
def test_cleanup_non_existent_folders_do_not_raise_error(self):
|
||||
css_folder = os.path.join(self.temp_folder, ".css")
|
||||
versions_folder = os.path.join(self.temp_folder, ".versions")
|
||||
|
||||
self.manager.cleanup()
|
||||
|
||||
# Check that no error is raised and the method completes successfully
|
||||
assert not os.path.exists(css_folder)
|
||||
assert not os.path.exists(versions_folder)
|
@@ -1,5 +1,5 @@
|
||||
from scripts import config
|
||||
from scripts.utils.color_converter import ColorConverterImpl
|
||||
from scripts.utils.color_converter.color_converter_impl import ColorConverterImpl
|
||||
|
||||
panel_folder = f"{config.tweaks_folder}/panel"
|
||||
|
||||
|
Reference in New Issue
Block a user