@@ -68,39 +68,75 @@ public class AppConfigTest {
6868 "}" ;
6969
7070 // -------------------------------------------------------------------------
71- // parseProviderConfig — unit tests on the static method directly
71+ // Real-world JSON format from the dotAI Apps config (formatted, 3 sections)
72+ // API key matches the actual structure: sk-proj-<164 chars>
7273 // -------------------------------------------------------------------------
7374
75+ private static final String REAL_API_KEY =
76+ "sk-proj-EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" +
77+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" ;
78+
79+ /** Exact format the user pastes into the Apps UI textarea (pretty-printed, 3 sections). */
80+ private static final String REAL_WORLD_FORMATTED_CONFIG =
81+ "{\n " +
82+ " \" chat\" :{\n " +
83+ " \" provider\" :\" openai\" ,\n " +
84+ " \" apiKey\" :\" " + REAL_API_KEY + "\" ,\n " +
85+ " \" model\" :\" o4-mini\" ,\n " +
86+ " \" maxCompletionTokens\" :16384,\n " +
87+ " \" temperature\" :1.0,\n " +
88+ " \" maxRetries\" :3\n " +
89+ " },\n " +
90+ " \" embeddings\" :{\n " +
91+ " \" provider\" :\" openai\" ,\n " +
92+ " \" apiKey\" :\" " + REAL_API_KEY + "\" ,\n " +
93+ " \" model\" :\" text-embedding-3-small\" \n " +
94+ " },\n " +
95+ " \" image\" :{\n " +
96+ " \" provider\" :\" openai\" ,\n " +
97+ " \" apiKey\" :\" " + REAL_API_KEY + "\" ,\n " +
98+ " \" model\" :\" gpt-image-1\" ,\n " +
99+ " \" size\" :\" 1024x1024\" \n " +
100+ " }\n " +
101+ "}" ;
102+
74103 @ Test
75- public void test_parseProviderConfig_cleanJson_parsesModelNames () {
76- final JsonNode root = AppConfig .parseProviderConfig (CLEAN_PROVIDER_CONFIG );
104+ public void test_parseProviderConfig_realWorldFormattedJson_parsesAllSections () {
105+ final JsonNode root = AppConfig .parseProviderConfig (REAL_WORLD_FORMATTED_CONFIG );
77106
78- assertFalse ("Parse should not return empty node for valid JSON" , root .isEmpty ());
79- assertEquals ("gpt-4o-mini" , root .path ("chat" ).path ("model" ).asText ());
80- assertEquals ("text-embedding-ada-002" , root .path ("embeddings" ).path ("model" ).asText ());
107+ assertFalse ("Formatted JSON should parse successfully" , root .isEmpty ());
108+ assertEquals ("o4-mini" , root .path ("chat" ).path ("model" ).asText ());
109+ assertEquals ("text-embedding-3-small" , root .path ("embeddings" ).path ("model" ).asText ());
110+ assertEquals ("gpt-image-1" , root .path ("image" ).path ("model" ).asText ());
81111 }
82112
83113 @ Test
84- public void test_parseProviderConfig_embeddedNewlines_parsesModelNames () {
85- // This is the real-world failure scenario: apiKey contains a literal \n
86- final JsonNode root = AppConfig .parseProviderConfig (WRAPPED_PROVIDER_CONFIG );
114+ public void test_appConfig_realWorldFormattedJson_isEnabled_allModelsSet () {
115+ final AppConfig config = buildAppConfig (REAL_WORLD_FORMATTED_CONFIG );
87116
88- assertFalse ("Parse should succeed even with embedded newlines in string values" , root .isEmpty ());
89- assertEquals ("gpt-4o-mini" , root .path ("chat" ).path ("model" ).asText ());
90- assertEquals ("text-embedding-ada-002" , root .path ("embeddings" ).path ("model" ).asText ());
117+ assertTrue ("AppConfig should be enabled with real-world formatted providerConfig" , config .isEnabled ());
118+ assertEquals ("o4-mini" , config .getModel ().getCurrentModel ());
119+ assertEquals ("text-embedding-3-small" , config .getEmbeddingsModel ().getCurrentModel ());
120+ assertEquals ("gpt-image-1" , config .getImageModel ().getCurrentModel ());
91121 }
92122
93- @ Test
94- public void test_parseProviderConfig_windowsLineEndings_parsesModelNames () {
95- // Windows-style \r\n in the apiKey values
96- final String crlfJson = WRAPPED_PROVIDER_CONFIG .replace ("\n " , "\r \n " );
123+ // -------------------------------------------------------------------------
124+ // parseProviderConfig — unit tests on the static method directly
125+ // -------------------------------------------------------------------------
97126
98- final JsonNode root = AppConfig .parseProviderConfig (crlfJson );
127+ @ Test
128+ public void test_parseProviderConfig_cleanJson_parsesModelNames () {
129+ final JsonNode root = AppConfig .parseProviderConfig (CLEAN_PROVIDER_CONFIG );
99130
100- assertFalse (root .isEmpty ());
101- assertEquals ("gpt-4o-mini" , root .path ("chat" ).path ("model" ).asText ());
131+ assertFalse ("Parse should not return empty node for valid JSON" , root .isEmpty ());
132+ assertEquals ("gpt-4o-mini" , root .path ("chat" ).path ("model" ).asText ());
133+ assertEquals ("text-embedding-ada-002" , root .path ("embeddings" ).path ("model" ).asText ());
102134 }
103135
136+ // Note: parseProviderConfig receives already-sanitized JSON (sanitization happens in the
137+ // constructor before calling this method). Embedded-newline scenarios are covered by
138+ // test_appConfig_withWrappedProviderConfig_isEnabled below.
139+
104140 @ Test
105141 public void test_parseProviderConfig_null_returnsEmptyObjectNode () {
106142 final JsonNode root = AppConfig .parseProviderConfig (null );
0 commit comments