import os import re import pytest from src.backend import constants from tests_backend.conftest import PROJECT_ROOT # Path of the JavaScript file containing the FLAGS object (e.g. "flags.js") FLAGS_FILE_PATH = os.path.join(PROJECT_ROOT, "src/frontend/static/js/flags.js") @pytest.fixture(scope="session") def flag_obj_unique_keys() -> set[str]: """Parse the FLAGS object in the JavaScript file and return the unique keys.""" with open(FLAGS_FILE_PATH, "r") as f: match = re.search(r"const FLAGS = {.*?};", f.read(), re.DOTALL) if not match: raise ValueError(f"No FLAGS object found in the {f.name} file!") js_content = match.group(0) js_content = js_content.replace("const FLAGS = ", "").strip().rstrip(";") matches = re.findall(r"[A-Z_]+(?=:\s*{)", js_content) return set(matches) @pytest.fixture(scope="session") def defined_flags(): return set(constants.Flags.__members__.values()) @pytest.fixture(scope="session") def defined_resolutions(): return set(constants.FlagResolutions.__members__.values()) def test_all_flags_and_flag_resolutions_are_defined( flag_obj_unique_keys, defined_flags, defined_resolutions ): """Test that all flags and resolutions in the FLAGS object are defined in the constants module. The FLAGS object is a JavaScript object containing flags and resolutions. This is the master list of flags and resolutions used in the application. Because it is defined in JavaScript, we need to ensure that all flags and resolutions are defined in the Python constants module. This test compares the keys in the FLAGS object with the values in the Flags and FlagResolutions enums in the constants module and will fail if there are any missing flags or resolutions in the Python constants module. """ missing = flag_obj_unique_keys - (defined_flags | defined_resolutions) assert ( not missing ), f"FLAGS out of sync! Missing flags or resolutions: {[str(s) for s in missing]}" def test_flags_and_flag_resolutions_are_in_js_flags_object( flag_obj_unique_keys, defined_flags, defined_resolutions ): """Test that all currently defined flags and resolutions are present in the FLAGS object in the JavaScript file. To avoid Python dev confusion, we want to ensure that there's no discrepancy between the Python and JavaScript definitions. """ # TODO: Skip for now assert True # only_in_python = (defined_flags | defined_resolutions) - flag_obj_unique_keys # assert not only_in_python, ( # f"FLAGS out of sync! The following flags/resolutions are defined in Python " # f"but not in the JavaScript FLAGS object: {[str(s) for s in only_in_python]}" # )