def test_no_passwords_anywhere(tmp_path, password_source, monkeypatch): """Checks that the password is applied, depending on the source. If source is 'None' - no password is supplied anywhere and validation fails.""" config_file = mk_tmp_file(tmp_path, key_to_pop="auth.password") if password_source is None: result = runner.invoke(app, ["--config", str(config_file), "validate"]) else: if password_source == "cmdline": result = runner.invoke( app, [ "--config", str(config_file), "--password", password_source, "validate", ], ) elif password_source == "environment": monkeypatch.setenv("CONFLUENCE_PASSWORD", password_source) result = runner.invoke( app, ["--config", str(config_file), "validate"]) else: config_file = mk_tmp_file(tmp_path, key_to_update="auth.password", value_to_update=password_source) result = runner.invoke( app, ["--config", str(config_file), "validate"]) if password_source is None: assert result.exit_code == 1 assert "Password is not specified" in result.stdout else: assert result.exit_code == 0 assert state.confluence_instance.password == password_source
def test_multiple_xdg_config_dirs(tmp_path, setup_xdg_dirs, monkeypatch): """Checks that the value from leftmost XDG_CONFIG_DIRS is the applied one""" my_xdg_config_dirs, _ = setup_xdg_dirs monkeypatch.setenv("XDG_CONFIG_DIRS", my_xdg_config_dirs) my_xdg_config_dirs = my_xdg_config_dirs.split(":") repo_config = toml.load(repo_config_path) global_config = { key: repo_config["auth"][key] for key in repo_config["auth"].keys() } global_config_file_1 = Path( f"{my_xdg_config_dirs[0]}/confluence_poster/config.toml") global_config_file_2 = Path( f"{my_xdg_config_dirs[1]}/confluence_poster/config.toml") global_config.update({"username": "******"}) global_config_file_1.write_text(toml.dumps({"auth": global_config})) global_config.update({"username": "******"}) global_config_file_2.write_text(toml.dumps({"auth": global_config})) config_file = mk_tmp_file(tmp_path=tmp_path, key_to_pop="auth") _ = load_config(local_config=config_file) config_file = mk_tmp_file(tmp_path=tmp_path, key_to_update="auth.username", value_to_update="user1") assert Config(config_file) == _
def test_one_page_no_name(tmp_path): """Tests that page's name can be none for one page case""" config_file = mk_tmp_file(tmp_path, key_to_pop=f"pages.page1.page_title") config_file = mk_tmp_file( tmp_path, config_to_clone=config_file, key_to_pop=f"pages.page2" ) _ = Config(config_file) assert _.pages[0].page_title is None
def test_one_page_no_title_in_config(tmp_path): """Checks that script runs correctly if no name is specified in config, but one is provided in cmdline""" page_title = "test_page" config_file = mk_tmp_file(tmp_path, key_to_pop="pages.page1.page_title") config_file = mk_tmp_file(tmp_path, config_to_clone=config_file, key_to_pop="pages.page2") _ = runner.invoke( app, ["--page-title", page_title, "--config", str(config_file), "validate"]) assert state.config.pages[0].page_title == page_title
def test_bad_auth_mandatory_params(tmp_path): """Checks for proper error if one of the mandatory parameters is missing in auth """ for param in ["confluence_url", "username", "is_cloud"]: config_file = mk_tmp_file(tmp_path, filename=param, key_to_pop=f"auth.{param}") with pytest.raises(KeyError) as e: _ = Config(config_file) assert e.value.args[0] == f"{param} not in auth section"
def test_default_page_space_not_str(tmp_path): config_file = mk_tmp_file( tmp_path, key_to_update="pages.default.page_space", value_to_update=1 ) with pytest.raises(ValueError) as e: _ = Config(config_file) assert "should be a string" in e.value.args[0]
def _set_page_to_overwrite(config_file, page_no, tmp_path): return mk_tmp_file( config_to_clone=config_file, tmp_path=tmp_path, key_to_update=f"pages.page{page_no}.force_overwrite", value_to_update=True, )
def test_two_pages_same_name_same_space(tmp_path): """Tests that the config properly alerts if there are more than 1 page with the same name and space""" config_file = mk_tmp_file(tmp_path) config = Config(config_file) config_file = mk_tmp_file( tmp_path, config_to_clone=config_file, key_to_update="pages.page2", value_to_update={ "page_title": config.pages[0].page_title, "page_file": "", "page_space": config.pages[0].page_space, }, ) with pytest.raises(ValueError) as e: _ = Config(config_file) assert "more than 1 page called" in e.value.args[0]
def test_author_name_bad_value(tmp_path, author_name): """Checks that exception is thrown if author is not a string or is a bad one""" config_file = mk_tmp_file( tmp_path, key_to_update="author", value_to_update=author_name ) with pytest.raises(ValueError): _ = Config(config_file)
def test_page_definition_not_str(tmp_path): """Defines each field one by one as a non-str and tests that exception is thrown""" for page_def in [_.name for _ in fields(Page) if _.name != "force_overwrite"]: config_file = mk_tmp_file( tmp_path, key_to_update=f"pages.page1.{page_def}", value_to_update=1 ) with pytest.raises(ValueError) as e: _ = Config(config_file) assert f"{page_def} property of a page is not a string" in e.value.args[0]
def test_two_pages_same_name_different_space(tmp_path): """Tests that the config does not alert if there are more than 1 page with the same name and space""" config_file = mk_tmp_file(tmp_path) config = Config(config_file) config_file = mk_tmp_file( tmp_path, config_to_clone=config_file, key_to_update="pages.page2", value_to_update={ "page_title": config.pages[0].page_title, "page_file": "", "page_space": "", }, ) _ = Config(config_file) assert len(_.pages) == 2 for page in _.pages: assert page.page_title == config.pages[0].page_title
def test_more_pages_no_name(tmp_path): config_file = mk_tmp_file( tmp_path, key_to_pop="pages.page1.page_title", key_to_update="pages.page2", value_to_update={"page_title": "Page2", "page_file": ""}, ) with pytest.raises(ValueError) as e: _ = Config(config_file) assert "more than 1 page" in e.value.args[0]
def test_page_parent_specified(tmp_path): """Tests that the page parent is applied from the config file""" parent_title = "Some parent title" config_file = mk_tmp_file( tmp_path, key_to_update="pages.page1.page_parent_title", value_to_update=parent_title, ) config = Config(config_file) assert config.pages[0].parent_page_title == parent_title
def test_default_space_multiple_pages_default(tmp_path): """Checks that the default space is applied if there are two pages with no space specified - default is applied""" config_file = mk_tmp_file( tmp_path, key_to_pop="pages.page1.page_space", key_to_update="pages.page2", value_to_update={"page_title": "Page2", "page_file": ""}, ) _ = Config(config_file) for page in _.pages: assert page.page_space == "DEFAULT_SPACE_KEY"
def test_cloud_api(tmp_path, is_cloud): """Checks that the logic to handle what version of Atlassian API is to be used works well""" config = mk_tmp_file(tmp_path, key_to_update="auth.is_cloud", value_to_update=is_cloud) result = runner.invoke(app, ["--config", str(config), "validate"]) assert result.exit_code == 0 if is_cloud: assert state.confluence_instance.api_version == "cloud" else: assert state.confluence_instance.api_version == "latest"
def test_warn_user_could_not_guess_file(tmp_path, make_one_page_config): config_file, config = make_one_page_config config_file = mk_tmp_file( tmp_path=tmp_path, config_to_clone=config_file, key_to_update="pages.page1.page_file", value_to_update="filename_no_extension", ) result: Result = run_with_config( config_file=config_file, input=create_single_page_input, ) assert "--help" in result.stdout assert result.exit_code == 1
def test_config_construct(tmp_path, setup_xdg_dirs, monkeypatch, dir_undefined): """Creates all XDG_CONFIG_ dirs for the test and checks that relevant keys are constructed""" my_xdg_config_dirs, my_xdg_config_home = setup_xdg_dirs global_config = Path( f"{my_xdg_config_dirs.split(':')[0]}/confluence_poster/config.toml") home_config = Path(f"{my_xdg_config_home}/confluence_poster/config.toml") repo_config = toml.load(repo_config_path) # Strip repo config into parts if dir_undefined == "home": global_config_part = { key: repo_config["auth"][key] for key in repo_config["auth"].keys() } my_xdg_config_home = None else: global_config_part = { key: repo_config["auth"][key] for key in repo_config["auth"].keys() & {"confluence_url", "is_cloud"} } global_config.write_text(toml.dumps({"auth": global_config_part})) if dir_undefined == "dirs": home_config_part = { key: repo_config["auth"][key] for key in repo_config["auth"].keys() } my_xdg_config_dirs = None else: home_config_part = { key: repo_config["auth"][key] for key in repo_config["auth"].keys() & {"username", "password"} } home_config.write_text(toml.dumps({"auth": home_config_part})) # Set up dirs and files for test config_file = mk_tmp_file(tmp_path=tmp_path, key_to_pop="auth") monkeypatch.setenv("XDG_CONFIG_HOME", str(my_xdg_config_home)) monkeypatch.setenv("XDG_CONFIG_DIRS", str(my_xdg_config_dirs)) _ = load_config(local_config=config_file) repo_config = Config(repo_config_path) assert repo_config == _
def test_default_space(tmp_path): """Tests that space definition is applied from default section and it does not override specific definition from page""" config_file = mk_tmp_file( tmp_path, key_to_pop="pages.page1.page_space", key_to_update="pages.page2", value_to_update={ "page_title": "Page2", "page_file": "", "page_space": "some_space_key", }, ) _ = Config(config_file) # check if the default value was applied for page without full definition assert _.pages[0].page_space == "DEFAULT_SPACE_KEY" # make sure the fully defined page definition is not overwritten assert _.pages[1].page_space == "some_space_key"
def test_different_config(tmp_path, config_file): """Tests that if the script reads from a specific config, not the default one If the config is None - nonexistent file is provided""" new_page_name = "different config" if config_file is not None: _config_file = mk_tmp_file( tmp_path, key_to_update="pages.page1.page_title", value_to_update=new_page_name, ) else: _config_file = "nonexistent_config" result = runner.invoke(app, ["--config", str(_config_file), "validate"]) if config_file is not None: assert result.exit_code == 0 else: assert result.exit_code == 1 assert ("create-config" in result.stdout ), "User should be prompted to create config through wizard" assert type(result.exception) is FileNotFoundError
def test_page_title_specified_two_pages(tmp_path, param): """For parameters that require that only one page is in config - make sure exception is raised if there are more pages in the config""" config_file = mk_tmp_file( tmp_path, key_to_update="pages.page2", value_to_update={ "page_title": "Page2", "page_file": "page2.txt" }, ) _ = runner.invoke( app, [ "--config", str(config_file), f"--{param.replace('_', '-')}", "Default name", "validate", ], ) assert _.exit_code == 1 assert "Please specify them in the config." in _.stdout
def test_no_author_use_from_auth(tmp_path): """In case author was not specified at all - use authentication username for checking who last updated pages""" config_file = mk_tmp_file(tmp_path, key_to_pop=f"author") _ = Config(config_file) assert _.author == _.auth.username
def test_no_auth(tmp_path): """Checks for error if there is no auth section at all""" config_file = mk_tmp_file(tmp_path=tmp_path, key_to_pop="auth") with pytest.raises(KeyError): _ = Config(config_file)
def test_page_section_not_dict(tmp_path): config_file = mk_tmp_file(tmp_path, key_to_update="pages.page1", value_to_update=1) with pytest.raises(ValueError) as e: _ = Config(config_file) assert "Pages section is malformed" in e.value.args[0]
def test_auth_no_password_ok(tmp_path): """Passwords may come from environment or option to the main file. This test ensures that there is no exception in this case""" config_file = mk_tmp_file(tmp_path, key_to_pop=f"auth.password") _ = Config(config_file) assert _.auth.password is None
def test_page_no_name_or_path(tmp_path, param_to_pop): """Checks that lack of mandatory Page definition is handled with an exception""" config_file = mk_tmp_file(tmp_path, key_to_pop=f"pages.page1.{param_to_pop}") with pytest.raises(KeyError): _ = Config(config_file)