schemadoc_diff/checker/
removed_schema_enum_value_check.rs1use std::cell::RefCell;
2
3use crate::core::{DiffResult, MapDiff, VecDiff};
4use crate::path_pointer::PathPointer;
5
6use crate::checker::{ValidationIssue, ValidationIssuer};
7use crate::schema_diff::{
8 MayBeRefDiff, MediaTypeDiff, OperationDiff, ParameterDiff,
9 RequestBodyDiff, ResponseDiff, SchemaDiff,
10};
11use crate::visitor::DiffVisitor;
12
13pub struct RemovedSchemaEnumValueCheck {
14 pointers: RefCell<Vec<PathPointer>>,
15}
16
17impl<'s> DiffVisitor<'s> for RemovedSchemaEnumValueCheck {
18 fn visit_operation(
19 &self,
20 pointer: &PathPointer,
21 _: &str,
22 _: &'s DiffResult<OperationDiff>,
23 ) -> bool {
24 pointer.is_updated()
25 }
26
27 fn visit_request_body(
28 &self,
29 pointer: &PathPointer,
30 _: &'s DiffResult<RequestBodyDiff>,
31 ) -> bool {
32 pointer.is_updated()
33 }
34
35 fn visit_responses(
36 &self,
37 pointer: &PathPointer,
38 _: &'s DiffResult<MapDiff<MayBeRefDiff<ResponseDiff>>>,
39 ) -> bool {
40 pointer.is_updated()
41 }
42
43 fn visit_media_types(
44 &self,
45 pointer: &PathPointer,
46 _: &'s DiffResult<MapDiff<MediaTypeDiff>>,
47 ) -> bool {
48 pointer.is_updated()
49 }
50
51 fn visit_media_type(
52 &self,
53 pointer: &PathPointer,
54 _: &'s DiffResult<MediaTypeDiff>,
55 ) -> bool {
56 pointer.is_updated()
57 }
58
59 fn visit_parameters(
60 &self,
61 pointer: &PathPointer,
62 _: &'s DiffResult<VecDiff<MayBeRefDiff<ParameterDiff>>>,
63 ) -> bool {
64 pointer.is_updated()
65 }
66
67 fn visit_parameter(
68 &self,
69 pointer: &PathPointer,
70 _: &'s DiffResult<ParameterDiff>,
71 ) -> bool {
72 pointer.is_updated()
73 }
74
75 fn visit_schema(
76 &self,
77 pointer: &PathPointer,
78 schema_diff_result: &'s DiffResult<SchemaDiff>,
79 ) -> bool {
80 if !pointer.is_updated() {
81 return false;
82 }
83
84 let Some(schema) = schema_diff_result.get() else {
85 return false;
86 };
87
88 if schema.r#enum.is_updated() {
89 let has_removed = match schema.r#enum.get() {
90 None => false,
91 Some(values) => values.iter().any(|v| v.is_removed()),
92 };
93 if has_removed {
94 self.pointers.borrow_mut().push(pointer.add_component(
95 &schema.r#enum,
96 Some("enum"),
97 None,
98 ))
99 }
100 }
101
102 true
103 }
104}
105
106impl Default for RemovedSchemaEnumValueCheck {
107 fn default() -> Self {
108 Self {
109 pointers: RefCell::new(vec![]),
110 }
111 }
112}
113
114impl<'s> ValidationIssuer<'s> for RemovedSchemaEnumValueCheck {
115 fn id(&self) -> &'static str {
116 "removed-schema-enum-value"
117 }
118
119 fn visitor(&self) -> &dyn DiffVisitor<'s> {
120 self
121 }
122
123 fn issues(&self) -> Option<Vec<ValidationIssue>> {
124 let pointers = std::mem::take(&mut *self.pointers.borrow_mut());
125
126 let issues = pointers
127 .into_iter()
128 .map(|path| ValidationIssue::new(path, self.id(), true))
129 .collect::<Vec<ValidationIssue>>();
130
131 Some(issues)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use crate::checker::removed_schema_enum_value_check::RemovedSchemaEnumValueCheck;
138 use crate::checker::ValidationIssuer;
139 use crate::get_schema_diff;
140 use crate::schema::HttpSchema;
141 use crate::schemas::openapi303::schema::OpenApi303;
142
143 #[test]
144 fn test_removed_schema_enum_value_check() {
145 let src_schema: HttpSchema = serde_json::from_str::<OpenApi303>(include_str!(
146 "../../data/checks/removed-schema-enum-value/schema-with-enums.json"
147 ))
148 .unwrap()
149 .into();
150
151 let tgt_schema: HttpSchema = serde_json::from_str::<OpenApi303>(include_str!(
152 "../../data/checks/removed-schema-enum-value/schema-with-enums-altered.json"
153 ))
154 .unwrap()
155 .into();
156
157 let diff = get_schema_diff(src_schema, tgt_schema);
158
159 let checker = RemovedSchemaEnumValueCheck::default();
160 crate::visitor::dispatch_visitor(diff.get().unwrap(), &checker);
161 let issues = checker.issues().unwrap();
162
163 assert_eq!(issues.len(), 2);
164 assert_eq!(
165 issues.get(0).unwrap().path.get_path(),
166 "paths//test/post/requestBody/content/application/json/schema/enum",
167 );
168 assert_eq!(
169 issues.get(1).unwrap().path.get_path(),
170 "paths//test/post/responses/200/content/application/json/schema/properties/prop1/enum",
171 );
172 }
173}