K2 2.8.0 (JoomlaWorks), vetted clean from live; no version-matching upstream package (getk2/k2 has no 2.8.0 tag) → deployed files. Bundles elFinder (admin file-manager attack surface). Signed-off-by: LÁZÁR Imre <imre@illusion.hu> Assisted-by: claude-code@claude-opus-4-8
420 lines
13 KiB
Python
420 lines
13 KiB
Python
"""Pytest-tesztek a jmap.py Joomla manifest -> deployed-path mapperhez.
|
|
|
|
Minden teszt egy szintetikus, minimál kicsomagolt bővítmény-csomagot épít fel
|
|
tmp_path alatt (manifest-XML + pár dummy forrásfájl), lefuttatja a mappinget,
|
|
és a kapott docroot-fát ellenőrzi a Joomla 3.x installer-szabályok szerint.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
import jmap
|
|
|
|
|
|
def _write(path: Path, content: str = "") -> None:
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(content, encoding="utf-8")
|
|
|
|
|
|
def _run(package_dir: Path, out_dir: Path) -> list[jmap.CopyOp]:
|
|
manifest_path = jmap.find_manifest(package_dir)
|
|
ops = jmap.build_operations(manifest_path, out_dir)
|
|
jmap.execute(ops)
|
|
return ops
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# component: site + admin + media + languages
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_component_site_admin_media_language(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "com_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="component" version="3.9.0" method="upgrade">
|
|
<name>com_hello</name>
|
|
<files folder="sitefiles">
|
|
<filename>helloworld.php</filename>
|
|
<folder>controllers</folder>
|
|
</files>
|
|
<administration>
|
|
<files folder="adminfiles">
|
|
<filename>helloworld.php</filename>
|
|
</files>
|
|
<languages folder="adminlang">
|
|
<language tag="en-GB">en-GB/en-GB.com_hello.sys.ini</language>
|
|
</languages>
|
|
</administration>
|
|
<media destination="com_hello" folder="mediafiles">
|
|
<folder>images</folder>
|
|
</media>
|
|
<languages folder="sitelang">
|
|
<language tag="en-GB">en-GB/en-GB.com_hello.ini</language>
|
|
</languages>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "sitefiles/helloworld.php", "<?php // site")
|
|
_write(pkg / "sitefiles/controllers/foo.php", "<?php // controller")
|
|
_write(pkg / "adminfiles/helloworld.php", "<?php // admin")
|
|
_write(pkg / "mediafiles/images/icon.png", "PNGDATA")
|
|
_write(pkg / "sitelang/en-GB/en-GB.com_hello.ini", "FIELD=Value")
|
|
_write(pkg / "adminlang/en-GB/en-GB.com_hello.sys.ini", "COM_HELLO=Hello")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "components/com_hello/helloworld.php").read_text() == "<?php // site"
|
|
assert (out / "components/com_hello/controllers/foo.php").read_text() == "<?php // controller"
|
|
assert (out / "administrator/components/com_hello/helloworld.php").read_text() == "<?php // admin"
|
|
assert (out / "media/com_hello/images/icon.png").read_text() == "PNGDATA"
|
|
assert (out / "language/en-GB/en-GB.com_hello.ini").read_text() == "FIELD=Value"
|
|
assert (out / "administrator/language/en-GB/en-GB.com_hello.sys.ini").read_text() == "COM_HELLO=Hello"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# module: site files + media
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_module_site_and_media(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "mod_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="module" client="site" method="upgrade">
|
|
<name>mod_hello</name>
|
|
<files folder="modfiles">
|
|
<filename module="mod_hello">mod_hello.php</filename>
|
|
<filename>helper.php</filename>
|
|
</files>
|
|
<media destination="mod_hello" folder="modmedia">
|
|
<folder>images</folder>
|
|
</media>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "modfiles/mod_hello.php", "<?php // module")
|
|
_write(pkg / "modfiles/helper.php", "<?php // helper")
|
|
_write(pkg / "modmedia/images/icon.png", "PNGDATA")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "modules/mod_hello/mod_hello.php").read_text() == "<?php // module"
|
|
assert (out / "modules/mod_hello/helper.php").read_text() == "<?php // helper"
|
|
assert (out / "media/mod_hello/images/icon.png").read_text() == "PNGDATA"
|
|
|
|
|
|
def test_module_administrator_client(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "mod_admhello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="module" client="administrator" method="upgrade">
|
|
<name>mod_admhello</name>
|
|
<files>
|
|
<filename module="mod_admhello">mod_admhello.php</filename>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "mod_admhello.php", "<?php // adm module")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "administrator/modules/mod_admhello/mod_admhello.php").read_text() == "<?php // adm module"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# plugin: group + element (via filename[@plugin])
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_plugin_group_and_element(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "plg_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="plugin" group="content" method="upgrade">
|
|
<name>PLG_CONTENT_HELLO</name>
|
|
<files folder="plgfiles">
|
|
<filename plugin="hello">hello.php</filename>
|
|
<folder>language</folder>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "plgfiles/hello.php", "<?php // plugin")
|
|
_write(pkg / "plgfiles/language/en-GB.plg_content_hello.ini", "PLG=Hello")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "plugins/content/hello/hello.php").read_text() == "<?php // plugin"
|
|
assert (out / "plugins/content/hello/language/en-GB.plg_content_hello.ini").read_text() == "PLG=Hello"
|
|
|
|
|
|
def test_plugin_element_fallback_from_name(tmp_path: Path) -> None:
|
|
"""Ha nincs <filename plugin="...">, a <name> utolsó '_'-tagja adja az elementet."""
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "plg_system_fallback.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="plugin" group="system" method="upgrade">
|
|
<name>PLG_SYSTEM_FALLBACK</name>
|
|
<files>
|
|
<filename>fallback.php</filename>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "fallback.php", "<?php // fallback")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "plugins/system/fallback/fallback.php").read_text() == "<?php // fallback"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# library
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_library(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "lib_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="library" method="upgrade">
|
|
<name>hello</name>
|
|
<files folder="libfiles">
|
|
<filename>hello.php</filename>
|
|
<folder>sub</folder>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "libfiles/hello.php", "<?php // lib")
|
|
_write(pkg / "libfiles/sub/util.php", "<?php // util")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "libraries/hello/hello.php").read_text() == "<?php // lib"
|
|
assert (out / "libraries/hello/sub/util.php").read_text() == "<?php // util"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# template
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_template(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "tpl_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="template" client="site" method="upgrade">
|
|
<name>hello</name>
|
|
<files folder="tplfiles">
|
|
<filename>index.php</filename>
|
|
<folder>css</folder>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "tplfiles/index.php", "<?php // tpl")
|
|
_write(pkg / "tplfiles/css/style.css", "body{}")
|
|
|
|
_run(pkg, out)
|
|
|
|
assert (out / "templates/hello/index.php").read_text() == "<?php // tpl"
|
|
assert (out / "templates/hello/css/style.css").read_text() == "body{}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# package (pkg_): al-bővítmények rekurzív feldolgozása
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_package_with_component_and_plugin_subextensions(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "pkg_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="package" method="upgrade">
|
|
<name>pkg_hello</name>
|
|
<files folder="packages">
|
|
<file type="component" id="com_hello">com_hello</file>
|
|
<file type="plugin" id="plg_hello">plg_hello</file>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
|
|
_write(
|
|
pkg / "packages/com_hello/com_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="component" version="3.9.0" method="upgrade">
|
|
<name>com_hello</name>
|
|
<files folder="site">
|
|
<filename>helloworld.php</filename>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "packages/com_hello/site/helloworld.php", "<?php // pkg component")
|
|
|
|
_write(
|
|
pkg / "packages/plg_hello/plg_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="plugin" group="content" method="upgrade">
|
|
<name>PLG_CONTENT_HELLO</name>
|
|
<files>
|
|
<filename plugin="hello">hello.php</filename>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "packages/plg_hello/hello.php", "<?php // pkg plugin")
|
|
|
|
ops = _run(pkg, out)
|
|
assert len(ops) == 2 # a package saga maga nem másol semmit, csak delegál
|
|
|
|
assert (out / "components/com_hello/helloworld.php").read_text() == "<?php // pkg component"
|
|
assert (out / "plugins/content/hello/hello.php").read_text() == "<?php // pkg plugin"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# hibaesetek
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_missing_manifest_raises(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
pkg.mkdir()
|
|
with pytest.raises(jmap.JoomlaManifestError, match="nem található"):
|
|
jmap.find_manifest(pkg)
|
|
|
|
|
|
def test_multiple_manifests_raises(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
_write(pkg / "a.xml", '<extension type="component"><name>com_a</name></extension>')
|
|
_write(pkg / "b.xml", '<extension type="component"><name>com_b</name></extension>')
|
|
with pytest.raises(jmap.JoomlaManifestError, match="több lehetséges manifest"):
|
|
jmap.find_manifest(pkg)
|
|
|
|
|
|
def test_unsupported_extension_type_raises(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
_write(pkg / "weird.xml", '<extension type="weird"><name>x</name></extension>')
|
|
manifest_path = jmap.find_manifest(pkg)
|
|
with pytest.raises(jmap.JoomlaManifestError, match="nem támogatott extension type"):
|
|
jmap.build_operations(manifest_path, out)
|
|
|
|
|
|
def test_missing_source_file_raises(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
_write(
|
|
pkg / "com_broken.xml",
|
|
"""<extension type="component">
|
|
<name>com_broken</name>
|
|
<files>
|
|
<filename>missing.php</filename>
|
|
</files>
|
|
</extension>""",
|
|
)
|
|
manifest_path = jmap.find_manifest(pkg)
|
|
ops = jmap.build_operations(manifest_path, out)
|
|
with pytest.raises(jmap.JoomlaManifestError, match="nem létezik"):
|
|
jmap.execute(ops)
|
|
|
|
|
|
def test_plugin_missing_group_raises(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
_write(
|
|
pkg / "plg_nogroup.xml",
|
|
"""<extension type="plugin">
|
|
<name>PLG_NOGROUP</name>
|
|
<files><filename plugin="nogroup">nogroup.php</filename></files>
|
|
</extension>""",
|
|
)
|
|
manifest_path = jmap.find_manifest(pkg)
|
|
with pytest.raises(jmap.JoomlaManifestError, match="'group'"):
|
|
jmap.build_operations(manifest_path, out)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# CLI end-to-end (subprocess)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_cli_end_to_end(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "pkg"
|
|
out = tmp_path / "out"
|
|
|
|
_write(
|
|
pkg / "com_hello.xml",
|
|
"""<?xml version="1.0" encoding="utf-8"?>
|
|
<extension type="component" version="3.9.0" method="upgrade">
|
|
<name>com_hello</name>
|
|
<files>
|
|
<filename>helloworld.php</filename>
|
|
</files>
|
|
</extension>
|
|
""",
|
|
)
|
|
_write(pkg / "helloworld.php", "<?php // cli")
|
|
|
|
script = Path(__file__).parent / "jmap.py"
|
|
result = subprocess.run(
|
|
[sys.executable, str(script), "--package", str(pkg), "--out", str(out)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
|
|
assert result.returncode == 0, result.stderr
|
|
assert "kész:" in result.stdout
|
|
assert (out / "components/com_hello/helloworld.php").read_text() == "<?php // cli"
|
|
|
|
|
|
def test_cli_reports_error_exit_code(tmp_path: Path) -> None:
|
|
pkg = tmp_path / "empty_pkg"
|
|
pkg.mkdir()
|
|
out = tmp_path / "out"
|
|
|
|
script = Path(__file__).parent / "jmap.py"
|
|
result = subprocess.run(
|
|
[sys.executable, str(script), "--package", str(pkg), "--out", str(out)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=False,
|
|
)
|
|
|
|
assert result.returncode == 1
|
|
assert "hiba:" in result.stderr
|