BareGit
"""Source-construction tests for constrained DOM JavaScript."""

from __future__ import annotations

import json
import unittest

from src import page_scripts


class PageScriptsTest(unittest.TestCase):
    """Verify dynamic values remain encoded JSON literals."""

    def test_hostile_values_are_json_encoded(self) -> None:
        values = [
            "'); window.pwned = true; ('",
            "line\nquote\"backslash\\",
            "😀 </script>",
        ]
        for value in values:
            encoded = json.dumps(
                value,
                ensure_ascii=False,
                separators=(",", ":"),
            )
            scripts = (
                page_scripts.describeElement(value),
                page_scripts.fill(value, value, False),
                page_scripts.appendCharacter(value, value),
                page_scripts.waitCondition("selector", value, "present"),
            )
            for script in scripts:
                self.assertIn(encoded, script)
            navigation_value = "https://example.test/" + value
            navigation_literal = json.dumps(
                navigation_value,
                ensure_ascii=False,
                separators=(",", ":"),
            )
            self.assertIn(
                navigation_literal,
                page_scripts.navigate(navigation_value),
            )

    def test_snapshot_omits_password_value(self) -> None:
        script = page_scripts.snapshot(10, 100)
        self.assertIn("element.type === 'password' ? null", script)
        self.assertIn("CSS.escape", script)
        self.assertNotIn("innerHTML", script)

    def test_wait_condition_has_balanced_result_envelope(self) -> None:
        script = page_scripts.waitCondition(
            "url_contains",
            "fixture.html",
            "present",
        )
        self.assertIn(
            "present,url:location.href}});",
            script,
        )
        self.assertNotIn("present,url:location.href}}});", script)

    def test_upload_chunks_decode_without_submitting(self) -> None:
        script = page_scripts.uploadAssign("test-key")
        self.assertIn("stage.chunks[index].map", script)
        self.assertIn("new File(parts", script)
        self.assertNotIn("requestSubmit", script)
        self.assertNotIn("form.submit", script)

    def test_javascript_source_does_not_require_dynamic_compilation(
        self,
    ) -> None:
        script = page_scripts.runJavaScript("document.title")
        self.assertIn("const result = await (\ndocument.title\n);", script)
        self.assertNotIn("Function", script)
        self.assertIn("result_type:resultType", script)
        self.assertIn("code:'javascript_error'", script)
        self.assertTrue(script.startswith("(async () =>"))

    def test_javascript_statement_body_runs_in_an_async_function(self) -> None:
        script = page_scripts.runJavaScript(
            "return document.title;",
            statement_body=True,
        )
        self.assertIn(
            "const result = await (async () => {\n"
            "return document.title;\n})()",
            script,
        )


if __name__ == "__main__":
    unittest.main()