1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! What:
//! Controls on this repository's own `cli-git.config.jsonc`, read through the real loader.
//! Why:
//! The native wrapper runs the four optional policies only when the file lists them, and reads the private rules
//! file only when `rulesFile` names it.
//! A line dropped from the file would silently stop a policy the incumbent enforced,
//! so the file the repository
//! ships is checked here instead of an inline copy of it.
//!
//! In TS you'd write (pseudocode):
//! ```ts
//! // const { config } = await loadRepositoryConfig(repositoryRoot);
//! // expect(config.policies['mono/dependent-version-bump'].explicit).toBe(true);
//! ```
/// Import the loader and the settings it produces.
use super::{CONFIG_FILE_NAME, LoadedConfig, load_repository_config};
use crate::config_schema::{ForbiddenStringsOptions, MarkdownAutofixOptions, MarkdownRule, PolicySetting};
use crate::policy_registry::{PolicyId, Severity};
use std::path::PathBuf;
/// What:
/// The repository top level:
/// this crate sits at `package/git-policy/cli`,
/// three directories below it.
/// `env!` reads a Cargo-provided variable at build time.
/// Why:
/// The gate image copies the file to the same relative place,
/// so one expression serves the host and the image.
///
/// In TS you'd write (pseudocode):
/// ```ts
/// const repositoryRoot = resolve(packageDirectory, '../../..');
/// ```
fn repository_root() -> PathBuf {
return PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../..");
}
/// Load the shipped file;
/// a missing or invalid file fails the test with the path and the loader's words.
fn load_shipped() -> LoadedConfig {
let root: PathBuf = repository_root();
return load_repository_config(root.as_path()).unwrap_or_else(|error| {
panic!(
"the repository's {CONFIG_FILE_NAME} under {} must load: {}",
root.display(),
error.message
)
});
}
/// The file the loader read is the repository's JSONC file,
/// not a default.
#[test]
fn the_repository_ships_a_configuration_file() {
let loaded: LoadedConfig = load_shipped();
assert_eq!(
loaded.source,
Some(repository_root().join(CONFIG_FILE_NAME))
);
}
/// All four optional policies are listed,
/// at the severities the incumbent enforced.
/// An unlisted optional policy is off,
/// so an unlisted one fails this test.
#[test]
fn the_repository_configuration_lists_all_four_optional_policies() {
let loaded: LoadedConfig = load_shipped();
for (id, severity) in [
(PolicyId::MarkdownAutofix, Severity::Warn),
(PolicyId::ForbiddenRootContext, Severity::Error),
(PolicyId::DependentVersionBump, Severity::Error),
(PolicyId::ForbiddenStrings, Severity::Error),
] {
assert_eq!(
loaded.config.policies.setting(id),
PolicySetting {
id,
severity,
explicit: true
},
"{id:?} must be listed in the repository configuration at the incumbent's severity"
);
}
}
/// The scanner reads the rules file the repository generates,
/// without depending on an environment variable,
/// and loads the embedded baseline.
#[test]
fn the_repository_configuration_sets_rules_file() {
let loaded: LoadedConfig = load_shipped();
assert_eq!(
loaded.config.policies.forbidden_strings,
ForbiddenStringsOptions {
builtin_rules: true,
rules_file: Some(String::from(".cache/forbidden-strings.rules.txt")),
}
);
}
/// The Markdown policy keeps the rule and the exclusion the incumbent configuration states.
#[test]
fn the_repository_configuration_keeps_the_markdown_options() {
let loaded: LoadedConfig = load_shipped();
assert_eq!(
loaded.config.policies.markdown_autofix,
MarkdownAutofixOptions {
rules: vec![MarkdownRule::LfsImageUrl],
exclude: vec![String::from("package/ssg/")],
}
);
}