1+ package io .jenkins .plugins .casc ;
2+
3+ import static org .hamcrest .MatcherAssert .assertThat ;
4+ import static org .hamcrest .Matchers .containsString ;
5+ import static org .hamcrest .Matchers .equalTo ;
6+ import static org .hamcrest .Matchers .is ;
7+ import static org .junit .jupiter .api .Assertions .assertEquals ;
8+
9+ import io .jenkins .plugins .casc .misc .JenkinsConfiguredWithCodeRule ;
10+ import io .jenkins .plugins .casc .misc .junit .jupiter .WithJenkinsConfiguredWithCode ;
11+ import java .net .URL ;
12+ import java .nio .charset .StandardCharsets ;
13+ import java .text .MessageFormat ;
14+ import net .sf .json .JSONArray ;
15+ import org .htmlunit .HttpMethod ;
16+ import org .htmlunit .WebClient ;
17+ import org .htmlunit .WebRequest ;
18+ import org .htmlunit .WebResponse ;
19+ import org .junit .jupiter .api .Test ;
20+ import org .jvnet .hudson .test .Issue ;
21+
22+ /**
23+ * Tests for YAML validation in the Configuration-as-Code endpoint.
24+ */
25+ @ WithJenkinsConfiguredWithCode
26+ public class YamlValidationTest {
27+
28+ /**
29+ * Tests that valid YAML returns an empty array response.
30+ */
31+ @ Test
32+ void validYaml (JenkinsConfiguredWithCodeRule j ) throws Exception {
33+ // Disable CSRF protection to simplify testing
34+ j .jenkins .setCrumbIssuer (null );
35+
36+ WebResponse response = performYamlValidation (j ,
37+ "jenkins:\n systemMessage: \" Hello from test\" " );
38+
39+ assertThat (response .getStatusCode (), is (200 ));
40+ assertThat (response .getContentType (), is ("application/json" ));
41+
42+ JSONArray jsonResponse = JSONArray .fromObject (response .getContentAsString ());
43+ assertThat (jsonResponse .size (), is (0 ));
44+ }
45+
46+ /**
47+ * Tests that YAML with incorrect indentation returns proper JSON response.
48+ */
49+ @ Test
50+ @ Issue ("2628" )
51+ void invalidIndentation (JenkinsConfiguredWithCodeRule j ) throws Exception {
52+ j .jenkins .setCrumbIssuer (null );
53+
54+ WebResponse response = performYamlValidation (j ,
55+ "jenkins:\n systemMessage: \" Bad indentation\" " );
56+
57+ assertThat (response .getContentType (), is ("application/json" ));
58+
59+ // Verify the response contains valid JSON regardless of status code
60+ String responseString = response .getContentAsString ();
61+ JSONArray jsonResponse = JSONArray .fromObject (responseString );
62+
63+ // The response should be a non-empty JSON array
64+ assertThat ("Should return error details" , jsonResponse .size () > 0 , is (true ));
65+ }
66+
67+ /**
68+ * Tests that YAML with invalid structure returns proper JSON response.
69+ */
70+ @ Test
71+ @ Issue ("2628" )
72+ void invalidStructure (JenkinsConfiguredWithCodeRule j ) throws Exception {
73+ j .jenkins .setCrumbIssuer (null );
74+
75+ WebResponse response = performYamlValidation (j ,
76+ "jenkins:\n numExecutors: {" );
77+
78+ assertThat (response .getContentType (), is ("application/json" ));
79+
80+ // Verify the response contains valid JSON regardless of status code
81+ String responseString = response .getContentAsString ();
82+ JSONArray jsonResponse = JSONArray .fromObject (responseString );
83+
84+ // The response should be a non-empty JSON array
85+ assertThat ("Should return error details" , jsonResponse .size () > 0 , is (true ));
86+ }
87+
88+ /**
89+ * Tests that YAML with unknown property returns proper JSON response.
90+ */
91+ @ Test
92+ @ Issue ("2628" )
93+ void unknownProperty (JenkinsConfiguredWithCodeRule j ) throws Exception {
94+ j .jenkins .setCrumbIssuer (null );
95+
96+ WebResponse response = performYamlValidation (j ,
97+ "jenkins:\n nonExistentProperty: \" This property doesn't exist\" \n systemMessage: \" Valid property\" " );
98+
99+ assertThat (response .getContentType (), is ("application/json" ));
100+
101+ // Verify the response contains valid JSON regardless of status code
102+ String responseString = response .getContentAsString ();
103+ JSONArray jsonResponse = JSONArray .fromObject (responseString );
104+
105+ // The response should be a non-empty JSON array with details about the unknown property
106+ assertThat ("Should return error details" , jsonResponse .size () > 0 , is (true ));
107+ assertThat (responseString , containsString ("nonExistentProperty" ));
108+ }
109+
110+ /**
111+ * Helper method to perform YAML validation.
112+ */
113+ private WebResponse performYamlValidation (JenkinsConfiguredWithCodeRule j , String yamlContent ) throws Exception {
114+ URL apiURL = new URL (MessageFormat .format ("{0}configuration-as-code/check" , j .getURL ().toString ()));
115+ WebRequest request = new WebRequest (apiURL , HttpMethod .POST );
116+ request .setCharset (StandardCharsets .UTF_8 );
117+ request .setRequestBody (yamlContent );
118+
119+ WebClient client = j .createWebClient ();
120+ // Don't throw exceptions for error status codes
121+ client .getOptions ().setThrowExceptionOnFailingStatusCode (false );
122+
123+ return client .getPage (request ).getWebResponse ();
124+ }
125+ }
0 commit comments