schemadoc_diff/checker/
removed_response_property_check.rs

1use std::cell::RefCell;
2
3use crate::checker::{ValidationIssue, ValidationIssuer};
4use crate::core::{DiffResult, MapDiff};
5use crate::path_pointer::{PathPointer, PointerAncestor};
6use crate::schema_diff::{
7    MayBeRefDiff, MediaTypeDiff, OperationDiff, ResponseDiff, SchemaDiff,
8};
9use crate::visitor::DiffVisitor;
10
11pub struct RemovedResponsePropertyCheck {
12    pointers: RefCell<Vec<PathPointer>>,
13}
14
15impl<'s> DiffVisitor<'s> for RemovedResponsePropertyCheck {
16    fn visit_operation(
17        &self,
18        pointer: &PathPointer,
19        _: &str,
20        _: &'s DiffResult<OperationDiff>,
21    ) -> bool {
22        pointer.is_updated()
23    }
24
25    fn visit_responses(
26        &self,
27        pointer: &PathPointer,
28        _: &'s DiffResult<MapDiff<MayBeRefDiff<ResponseDiff>>>,
29    ) -> bool {
30        pointer.is_updated()
31    }
32
33    fn visit_media_types(
34        &self,
35        pointer: &PathPointer,
36        _: &'s DiffResult<MapDiff<MediaTypeDiff>>,
37    ) -> bool {
38        pointer.is_updated()
39    }
40
41    fn visit_media_type(
42        &self,
43        pointer: &PathPointer,
44        _: &'s DiffResult<MediaTypeDiff>,
45    ) -> bool {
46        pointer.is_updated()
47    }
48
49    fn visit_schema(
50        &self,
51        pointer: &PathPointer,
52        _: &'s DiffResult<SchemaDiff>,
53    ) -> bool {
54        if pointer.ancestor(PointerAncestor::schema()).is_removed() {
55            return false;
56        }
57
58        if pointer
59            .ancestor(PointerAncestor::schema_property())
60            .is_removed()
61        {
62            self.pointers.borrow_mut().push(pointer.clone());
63            return false;
64        }
65
66        pointer.is_updated()
67    }
68}
69
70impl Default for RemovedResponsePropertyCheck {
71    fn default() -> Self {
72        Self {
73            pointers: RefCell::new(vec![]),
74        }
75    }
76}
77
78impl<'s> ValidationIssuer<'s> for RemovedResponsePropertyCheck {
79    fn id(&self) -> &'static str {
80        "removed-response-property"
81    }
82
83    fn visitor(&self) -> &dyn DiffVisitor<'s> {
84        self
85    }
86
87    fn issues(&self) -> Option<Vec<ValidationIssue>> {
88        let pointers = std::mem::take(&mut *self.pointers.borrow_mut());
89
90        let issues = pointers
91            .into_iter()
92            .map(|path| ValidationIssue::new(path, self.id(), true))
93            .collect::<Vec<ValidationIssue>>();
94
95        Some(issues)
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use crate::checker::removed_response_property_check::RemovedResponsePropertyCheck;
102    use crate::checker::ValidationIssuer;
103    use crate::get_schema_diff;
104    use crate::schema::HttpSchema;
105    use crate::schemas::openapi303::schema::OpenApi303;
106
107    #[test]
108    fn test_removed_response_property_check() {
109        let src_schema: HttpSchema = serde_json::from_str::<OpenApi303>(include_str!(
110            "../../data/checks/removed-response-property/schema-with-responses.json"
111        ))
112        .unwrap()
113        .into();
114
115        let tgt_schema: HttpSchema = serde_json::from_str::<OpenApi303>(include_str!(
116            "../../data/checks/removed-response-property/schema-with-responses-altered.json"
117        ))
118        .unwrap()
119        .into();
120
121        let diff = get_schema_diff(src_schema, tgt_schema);
122
123        let checker = RemovedResponsePropertyCheck::default();
124        crate::visitor::dispatch_visitor(diff.get().unwrap(), &checker);
125        let issues = checker.issues().unwrap();
126
127        assert_eq!(issues.len(), 3);
128        // replaced with `shortname` property
129        assert_eq!(
130            issues.get(0).unwrap().path.get_path(),
131            "paths//test/post/responses/200/content/application/json/schema/properties/description",
132        );
133        //removed
134        assert_eq!(
135            issues.get(1).unwrap().path.get_path(),
136            "paths//test/post/responses/200/content/application/json/schema/properties/settings/properties/s2",
137        );
138        // parent schema type changed from "object" to "string"
139        assert_eq!(
140            issues.get(2).unwrap().path.get_path(),
141            "paths//test/put/responses/200/content/application/json/schema/properties/id",
142        );
143    }
144}