def test_pre_commit_autoinstall(tmp_path: Path, supported_odoo_version: float): """Testea que pre-commit se (des)instala automaticamente en repos alien. Esta prueba es más lenta porque tiene que descargar y construir imágenes OCI y descargar código git, por lo que solo se ejecuta en estas versiones de Odoo: - 10.0 porque es Python 2 y no tiene configuraciones de confirmación previa en OCA. - 13.0 porque es Python 3 y tiene configuraciones de confirmación previa en OCA.. """ if supported_odoo_version not in {10.0, 13.0}: pytest.skip("esta prueba solo se testea con otras versiones de odoo") copy( ".", str(tmp_path), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) with local.cwd(tmp_path): with (tmp_path / "odoo" / "custom" / "src" / "addons.yaml").open("w") as fd: yaml.dump({"server-tools": "*"}, fd) # El usuario puede descargar el código git desde cualquier carpeta with local.cwd(tmp_path / "odoo" / "custom" / "src" / "private"): invoke("git-aggregate") # Check pre-commit está correctamente (des)instalado pre_commit_present = supported_odoo_version >= 13.0 server_tools_git = (tmp_path / "odoo" / "custom" / "src" / "server-tools" / ".git") assert server_tools_git.is_dir() assert (server_tools_git / "hooks" / "pre-commit").is_file() == pre_commit_present # Elimine el código fuente, puede usar mucho espacio en disco rmtree(tmp_path)
def test_v1_5_2_migration(tmp_path: Path, cloned_template: Path, supported_odoo_version: float): """Test migration to v1.5.2.""" auto = tmp_path / "odoo" / "auto" empty = auto / ".empty" # This file existed in doodba-scaffolding with local.cwd(tmp_path): # Copy v1.5.1 copy( src_path=str(cloned_template), vcs_ref="v1.5.1", force=True, data={"odoo_version": supported_odoo_version}, ) auto.mkdir() empty.touch() assert empty.exists() git("add", ".") git("add", "-f", empty) git("commit", "-am", "reformat", retcode=1) git("commit", "-am", "copied from template in v1.5.1") # Update to v1.5.2 copy(vcs_ref="v1.5.2", force=True) assert not empty.exists() assert not auto.exists() invoke("develop") assert auto.exists() assert not empty.exists()
def test_code_workspace_file(tmp_path: Path, cloned_template: Path): """The file is generated as expected.""" copy( str(cloned_template), str(tmp_path), vcs_ref="HEAD", force=True, ) assert (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() (tmp_path / f"doodba.{tmp_path.name}.code-workspace").rename( tmp_path / "doodba.other1.code-workspace" ) with local.cwd(tmp_path): invoke("write-code-workspace-file") assert (tmp_path / "doodba.other1.code-workspace").is_file() assert not (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() # Do a stupid and dirty git clone to check it's sorted fine git("clone", cloned_template, Path("odoo", "custom", "src", "zzz")) invoke("write-code-workspace-file", "-c", "doodba.other2.code-workspace") assert not (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() assert (tmp_path / "doodba.other1.code-workspace").is_file() assert (tmp_path / "doodba.other2.code-workspace").is_file() with (tmp_path / "doodba.other2.code-workspace").open() as fp: workspace_definition = json.load(fp) assert workspace_definition == { "folders": [ {"path": "odoo/custom/src/zzz"}, {"path": "odoo/custom/src/private"}, {"path": "."}, ] }
def test_pre_commit_autoinstall(tmp_path: Path, supported_odoo_version: float): """Test that pre-commit is automatically (un)installed in alien repos. This test is slower because it has to download and build OCI images and download git code, so it's only executed against these Odoo versions: - 10.0 because it's Python 2 and has no pre-commit configurations in OCA. - 13.0 because it's Python 3 and has pre-commit configurations in OCA. """ if supported_odoo_version not in {10.0, 13.0}: pytest.skip("this test is only tested with other odoo versions") copy( ".", str(tmp_path), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) with local.cwd(tmp_path): with (tmp_path / "odoo" / "custom" / "src" / "addons.yaml").open("w") as fd: yaml.dump({"server-tools": "*"}, fd) # User can download git code from any folder with local.cwd(tmp_path / "odoo" / "custom" / "src" / "private"): invoke("git-aggregate") # Check pre-commit is properly (un)installed pre_commit_present = supported_odoo_version >= 13.0 server_tools_git = ( tmp_path / "odoo" / "custom" / "src" / "server-tools" / ".git" ) assert server_tools_git.is_dir() assert ( server_tools_git / "hooks" / "pre-commit" ).is_file() == pre_commit_present # Remove source code, it can use a lot of disk space rmtree(tmp_path)
def test_start( cloned_template: Path, docker: LocalCommand, supported_odoo_version: float, tmp_path: Path, ): """Test the start task. On this test flow, other downsream tasks are also tested: - img-build - git-aggregate - stop --purge """ try: with local.cwd(tmp_path): copy( src_path=str(cloned_template), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) # Imagine the user is in the src subfolder for these tasks with local.cwd(tmp_path / "odoo" / "custom" / "src"): invoke("img-build") invoke("git-aggregate") # Test normal call stdout = invoke("start") print(stdout) assert "Reinitialized existing Git repository" in stdout assert "pre-commit installed" in stdout # Test "--debugpy and wait time call invoke("stop") stdout = invoke("start", "--debugpy") assert socket_is_open("127.0.0.1", int(supported_odoo_version) * 1000 + 899) # Check if auto-reload is disabled container_logs = docker_compose("logs", "odoo") assert "dev=reload" not in container_logs finally: # Imagine the user is in the odoo subrepo for this command with local.cwd(tmp_path / "odoo" / "custom" / "src" / "odoo"): invoke("stop", "--purge")
def test_code_workspace_file(tmp_path: Path, cloned_template: Path): """The file is generated as expected.""" copy( str(cloned_template), str(tmp_path), vcs_ref="HEAD", force=True, ) assert (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() (tmp_path / f"doodba.{tmp_path.name}.code-workspace").rename( tmp_path / "doodba.other1.code-workspace") with local.cwd(tmp_path): invoke("write-code-workspace-file") assert (tmp_path / "doodba.other1.code-workspace").is_file() assert not (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() invoke("write-code-workspace-file", "-c", "doodba.other2.code-workspace") assert not (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() assert (tmp_path / "doodba.other1.code-workspace").is_file() assert (tmp_path / "doodba.other2.code-workspace").is_file()
def test_v1_5_3_migration(tmp_path: Path, cloned_template: Path, supported_odoo_version: float): """Test migration to v1.5.3.""" auto_addons = tmp_path / "odoo" / "auto" / "addons" # This part makes sense only when v1.5.3 is not yet released with local.cwd(cloned_template): if "v1.5.3" not in git("tag").split(): git("tag", "-d", "test") git("tag", "v1.5.3") with local.cwd(tmp_path): # Copy v1.5.2 copy(src_path=str(cloned_template), vcs_ref="v1.5.2", force=True) assert not auto_addons.exists() git("add", ".") git("commit", "-am", "reformat", retcode=1) git("commit", "-am", "copied from template in v1.5.2") # Update to v1.5.3 copy(vcs_ref="v1.5.3", force=True) assert not auto_addons.exists() invoke("develop") assert auto_addons.is_dir() # odoo/auto/addons dir must be writable (auto_addons / "sample").touch()
def test_resetdb( cloned_template: Path, docker: LocalCommand, supported_odoo_version: float, tmp_path: Path, ): """Test the dropdb task. On this test flow, other downsream tasks are also tested: - img-build - git-aggregate - stop --purge """ try: with local.cwd(tmp_path): copy( src_path=str(cloned_template), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) # Imagine the user is in the src subfolder for these tasks with local.cwd(tmp_path / "odoo" / "custom" / "src"): invoke("img-build") invoke("git-aggregate") # No ir_module_module table exists yet with pytest.raises(ProcessExecutionError): _install_status("base") # Imagine the user is in the odoo subrepo for these tasks with local.cwd(tmp_path / "odoo" / "custom" / "src" / "odoo"): # This should install just "base" stdout = invoke("resetdb") assert "Creating database cache" in stdout assert "from template devel" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "uninstalled" assert _install_status("sale") == "uninstalled" # Install "purchase" stdout = invoke("resetdb", "-m", "purchase") assert "Creating database cache" in stdout assert "from template devel" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "installed" assert _install_status("sale") == "uninstalled" # Install "sale" in a separate database stdout = invoke("resetdb", "-m", "sale", "-d", "sale_only") assert "Creating database cache" in stdout assert "from template sale_only" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "installed" assert _install_status("sale") == "uninstalled" assert _install_status("base", "sale_only") == "installed" assert _install_status("purchase", "sale_only") == "uninstalled" assert _install_status("sale", "sale_only") == "installed" # Install "sale" in main database stdout = invoke("resetdb", "-m", "sale") assert "Creating database devel from template cache" in stdout assert "Found matching database template" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "uninstalled" assert _install_status("sale") == "installed" finally: # Imagine the user is in the odoo subrepo for this command with local.cwd(tmp_path / "odoo" / "custom" / "src" / "odoo"): invoke("stop", "--purge")
def test_resetdb( cloned_template: Path, docker: LocalCommand, supported_odoo_version: float, tmp_path: Path, ): """Test the dropdb task. On this test flow, other downsream tasks are also tested: - img-build - git-aggregate - stop --purge - snapshot - restore-snapshot """ try: with local.cwd(tmp_path): copy( src_path=str(cloned_template), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) # Imagine the user is in the src subfolder for these tasks with local.cwd(tmp_path / "odoo" / "custom" / "src"): invoke("img-build") invoke("git-aggregate") # No ir_module_module table exists yet with pytest.raises(ProcessExecutionError): _install_status("base") # Imagine the user is in the odoo subrepo for these tasks with local.cwd(tmp_path / "odoo" / "custom" / "src" / "odoo"): # This should install just "base" stdout = invoke("resetdb", "--no-populate") assert "Creating database cache" in stdout assert "from template devel" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "uninstalled" assert _install_status("sale") == "uninstalled" assert not _get_config_param("report.url") # Install "purchase" stdout = invoke("resetdb", "-m", "purchase") assert "Creating database cache" in stdout assert "from template devel" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "installed" assert _install_status("sale") == "uninstalled" # Install "sale" in a separate database stdout = invoke("resetdb", "-m", "sale", "-d", "sale_only") assert "Creating database cache" in stdout assert "from template sale_only" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "installed" assert _install_status("sale") == "uninstalled" assert _install_status("base", "sale_only") == "installed" assert _install_status("purchase", "sale_only") == "uninstalled" assert _install_status("sale", "sale_only") == "installed" # Install "sale" in main database stdout = invoke("resetdb", "-m", "sale") assert "Creating database devel from template cache" in stdout assert "Found matching database template" in stdout assert _install_status("base") == "installed" assert _install_status("purchase") == "uninstalled" assert _install_status("sale") == "installed" # Snapshot current DB invoke("snapshot", "--destination-db", "db_with_sale") if supported_odoo_version >= 11: invoke("preparedb") assert _get_config_param( "report.url") == "http://localhost:8069" stdout = invoke("resetdb") # --populate default # report.url should be set in the DB assert _get_config_param( "report.url") == "http://localhost:8069" else: invoke( "resetdb" ) # Despite new default --populate, shouldn't introduce error with pytest.raises(ProcessExecutionError): invoke("preparedb") # DB should now be reset assert _install_status("sale") == "uninstalled" # Restore snapshot invoke("restore-snapshot", "--snapshot-name", "db_with_sale") assert _install_status("sale") == "installed" finally: safe_stop_env(tmp_path / "odoo" / "custom" / "src" / "odoo", )
def test_test_tasks( cloned_template: Path, docker: LocalCommand, supported_odoo_version: float, tmp_path: Path, ): """Test the tasks associated with the Odoo test flow. On this test flow, the following tasks are tested: - img-build - git-aggregate - stop --purge - resetdb --dependencies - test [options] This test will be skipped for prereleased versions of Doodba """ try: with local.cwd(tmp_path): copy( src_path=str(cloned_template), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) # Imagine the user is in the src subfolder for these tasks # and the DB is clean with local.cwd(tmp_path / "odoo" / "custom" / "src"): invoke("img-build") invoke("git-aggregate") # Prepare environment with "note" dependencies invoke("resetdb", "-m", "note", "--dependencies") assert _install_status("mail") == "installed" # Test "note" simple call in init mode (default) assert _install_status("note") == "uninstalled" stdout = invoke("test", "-m", "note", retcode=None) # Ensure "note" was installed and tests ran assert _install_status("note") == "installed" _tests_ran(stdout, supported_odoo_version, "note") if supported_odoo_version >= 11: # Prepare environment for all private addons and "test" them with local.cwd(tmp_path / "odoo" / "custom" / "src" / "private"): generate_test_addon("test_module", supported_odoo_version, dependencies='["mail"]') invoke("resetdb", "--private", "--dependencies") assert _install_status("mail") == "installed" # Test "test_module" simple call in init mode (default) assert _install_status("test_module") == "uninstalled" stdout = invoke("test", "--private", retcode=None) # Ensure "test_module" was installed and tests ran assert _install_status("test_module") == "installed" # Prepare environment for OCA addons and test them with local.cwd(tmp_path / "odoo" / "custom" / "src"): build_file_tree({ "addons.yaml": """\ account-invoicing: - account_invoice_refund_link """, }) invoke("git-aggregate") invoke("resetdb", "--extra", "--private", "--dependencies") assert (_install_status("mail") == "installed" ) # dependency of test_module assert (_install_status("account") == "installed" ) # dependency of account_invoice_refund_link # Test "account_invoice_refund_link" assert _install_status("test_module") == "uninstalled" assert (_install_status("account_invoice_refund_link") == "uninstalled") stdout = invoke("test", "--private", "--extra", retcode=None) # Ensure "test_module" and "account_invoice_refund_link" were installed assert _install_status("test_module") == "installed" assert _install_status( "account_invoice_refund_link") == "installed" _tests_ran(stdout, supported_odoo_version, "account_invoice_refund_link") # Test --test-tags if supported_odoo_version >= 12: with local.cwd(tmp_path / "odoo" / "custom" / "src" / "private"): generate_test_addon( "test_module", supported_odoo_version, dependencies='["account_invoice_refund_link"]', ) # Run again but skip tests invoke("resetdb", "--extra", "--private", "--dependencies") stdout = invoke( "test", "--private", "--extra", "--skip", "account_invoice_refund_link", retcode=None, ) assert _install_status("test_module") == "installed" assert _install_status( "account_invoice_refund_link") == "installed" # Tests for account_invoice_refund_link should not run with pytest.raises(AssertionError): _tests_ran( stdout, supported_odoo_version, "account_invoice_refund_link", ) finally: safe_stop_env(tmp_path, )
def test_install_test( cloned_template: Path, docker: LocalCommand, supported_odoo_version: float, tmp_path: Path, ): """Test the install and test tasks. On this test flow, other downsream tasks are also tested: - img-build - git-aggregate - stop --purge """ try: with local.cwd(tmp_path): copy( src_path=str(cloned_template), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) # Imagine the user is in the src subfolder for these tasks # and the DB is clean with local.cwd(tmp_path / "odoo" / "custom" / "src"): invoke("img-build") invoke("git-aggregate") invoke("resetdb") # Install "mail" assert _install_status("mail") == "uninstalled" stdout = invoke("install", "-m", "mail") assert _install_status("mail") == "installed" if supported_odoo_version > 8: assert _install_status("utm") == "uninstalled" # Change to "utm" subfolder and install with local.cwd(tmp_path / "odoo" / "custom" / "src" / "odoo" / "addons" / "utm"): # Install "utm" based on current folder stdout = invoke("install") assert _install_status("mail") == "installed" assert _install_status("utm") == "installed" # Test "note" simple call in init mode (default) assert _install_status("note") == "uninstalled" stdout = invoke("test", "-m", "note", "--mode", "init", retcode=None) # Ensure "note" was installed and tests ran assert _install_status("note") == "installed" _tests_ran(stdout, supported_odoo_version, "note") # Test "note" simple call in update mode stdout = invoke("test", "-m", "note", "--mode", "update", retcode=None) _tests_ran(stdout, supported_odoo_version, "note") # Change to "note" subfolder and test with local.cwd(tmp_path / "odoo" / "custom" / "src" / "odoo" / "addons" / "note"): # Test "note" based on current folder stdout = invoke("test", retcode=None) _tests_ran(stdout, supported_odoo_version, "note") # Test --debugpy and wait time call with safe_stop_env(tmp_path, purge=False) invoke("test", "-m", "note", "--debugpy", retcode=None) assert socket_is_open("127.0.0.1", int(supported_odoo_version) * 1000 + 899) stdout = _wait_for_test_to_start() assert "python -m debugpy" in stdout finally: safe_stop_env(tmp_path, )
def test_transtion_to_copier(tmp_path: Path, cloned_template: Path, any_odoo_version: float): """Test transition from old git-clone-based workflow to new copier-based.""" tag = "v999999.99.99" with local.cwd(cloned_template): git("tag", "--delete", "test") git("tag", "--force", tag) # Emulate user cloning scaffolding using the old workflow git("clone", "https://github.com/Tecnativa/doodba-scaffolding", tmp_path) with local.cwd(tmp_path): # Emulate user modifying some basic variables and committing env_file = tmp_path / ".env" env_contents = env_file.read_text() env_contents = env_contents.replace( "ODOO_MAJOR=11", f"ODOO_MAJOR={int(any_odoo_version)}") env_contents = env_contents.replace( "ODOO_MINOR=11.0", f"ODOO_MINOR={any_odoo_version:.1f}") env_contents = env_contents.replace( "ODOO_IMAGE=docker.io/myuser/myproject-odoo", "ODOO_IMAGE=registry.example.com/custom-team/custom-project-odoo", ) env_file.write_text(env_contents) addons_file = tmp_path / "odoo" / "custom" / "src" / "addons.yaml" addons_file.write_text('server-tools: ["*"]') assert 'server-tools: ["*"]' in addons_file.read_text() answers_file = tmp_path / ".copier-answers.yml" answers_file_contents = answers_file.read_text() answers_file_contents = answers_file_contents.replace( "_src_path: https://github.com/Tecnativa/doodba-copier-template.git", f"_src_path: {cloned_template}", ) answers_file.write_text(answers_file_contents) assert f"_src_path: {cloned_template}" in answers_file.read_text() dep_files = glob( str(tmp_path / "odoo" / "custom" / "dependencies" / "*.txt")) assert len(dep_files) == 5 for dep_file in map(Path, dep_files): with dep_file.open("a") as dep_fd: dep_fd.write("\n# a comment") git("add", ".") git("commit", "-m", "update") # Emulate user upgrading to copier, passing the right variables copy( dst_path=str(tmp_path), force=True, data={ "odoo_version": any_odoo_version, "odoo_oci_image": "registry.example.com/custom-team/custom-project-odoo", }, vcs_ref=tag, ) env_contents = env_file.read_text() assert f"ODOO_MAJOR={int(any_odoo_version)}" in env_contents assert f"ODOO_MINOR={any_odoo_version:.1f}" in env_contents assert (tmp_path / ".copier-answers.yml").is_file() assert 'server-tools: ["*"]' in addons_file.read_text() for dep_file in map(Path, dep_files): assert dep_file.read_text().endswith("\n# a comment") # Check migrations ran fine assert not (tmp_path / ".travis.yml").exists() assert not (tmp_path / ".vscode" / "doodba").exists() assert not (tmp_path / ".vscode" / "doodbasetup.py").exists() assert not (tmp_path / "odoo" / "custom" / "src" / "private" / ".empty").exists() # Ensure migrations are resilient to subproject changes invoke( "--search-root", cloned_template, "--collection", "migrations", "from-doodba-scaffolding-to-copier", )
def test_code_workspace_file(tmp_path: Path, cloned_template: Path, supported_odoo_version: float): """The file is generated as expected.""" copy( str(cloned_template), str(tmp_path), vcs_ref="HEAD", force=True, data={"odoo_version": supported_odoo_version}, ) assert (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() (tmp_path / f"doodba.{tmp_path.name}.code-workspace").rename( tmp_path / "doodba.other1.code-workspace") with local.cwd(tmp_path / "odoo" / "custom" / "src" / "private"): # Generate generic addon path is_py3 = supported_odoo_version >= 11 manifest = "__manifest__" if is_py3 else "__openerp__" build_file_tree({ f"test_module_static/{manifest}.py": f"""\ {"{"} 'name':'test module','license':'AGPL-3', 'version':'{supported_odoo_version}.1.0.0', 'installable': True, 'auto_install': False {"}"} """, "test_module_static/static/index.html": """\ <html> </html> """, }) with local.cwd(tmp_path): invoke("write-code-workspace-file") assert (tmp_path / "doodba.other1.code-workspace").is_file() assert not (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() # Do a stupid and dirty git clone to check it's sorted fine git("clone", cloned_template, Path("odoo", "custom", "src", "zzz")) # "Clone" a couple more repos, including odoo to check order git("clone", cloned_template, Path("odoo", "custom", "src", "aaa")) git("clone", cloned_template, Path("odoo", "custom", "src", "bbb")) git("clone", cloned_template, Path("odoo", "custom", "src", "odoo")) invoke("write-code-workspace-file", "-c", "doodba.other2.code-workspace") assert not (tmp_path / f"doodba.{tmp_path.name}.code-workspace").is_file() assert (tmp_path / "doodba.other1.code-workspace").is_file() assert (tmp_path / "doodba.other2.code-workspace").is_file() with (tmp_path / "doodba.other2.code-workspace").open() as fp: workspace_definition = json.load(fp) # Check workspace folder definition and order assert workspace_definition["folders"] == [ { "path": "odoo/custom/src/aaa" }, { "path": "odoo/custom/src/bbb" }, { "path": "odoo/custom/src/zzz" }, { "path": "odoo/custom/src/odoo" }, { "path": "odoo/custom/src/private" }, { "name": f"doodba.{tmp_path.name}", "path": "." }, ] # Firefox debugger configuration url = f"http://localhost:{supported_odoo_version:.0f}069/test_module_static/static/" path = "${workspaceRoot:private}/test_module_static/static/" firefox_configuration = next( conf for conf in workspace_definition["launch"]["configurations"] if conf["type"] == "firefox") assert { "url": url, "path": path } in firefox_configuration["pathMappings"] # Chrome debugger configuration chrome_configuration = next( conf for conf in workspace_definition["launch"]["configurations"] if conf["type"] == "chrome") assert chrome_configuration["pathMapping"][url] == path
def test_pre_commit_in_template(): """Make sure linters are happy.""" with local.cwd(Path(__file__).parent.parent): invoke("lint")