@@ -260,6 +260,82 @@ class APICoreModelTestCase extends RESTAPI\Core\TestCase {
260260 $ test_model ->validate ();
261261 }
262262
263+ /**
264+ * Checks that validate() throws MODEL_MISSING_REQUIRED_PACKAGE when the -devel variant is installed but
265+ * the `allow_development_packages` setting is disabled (default).
266+ */
267+ public function test_model_validate_packages_devel_not_allowed_by_default (): void {
268+ # Ensure the allow_development_packages setting is disabled
269+ $ settings = new RESTAPI \Models \RESTAPISettings ();
270+ $ settings ->from_internal ();
271+ $ original = $ settings ->allow_development_packages ->value ;
272+
273+ if ($ original ) {
274+ $ settings ->allow_development_packages ->value = false ;
275+ $ settings ->update (apply: false );
276+ }
277+
278+ # A package that ends with -devel that is not installed should still fail without the setting enabled
279+ $ this ->assert_throws_response (
280+ response_id: 'MODEL_MISSING_REQUIRED_PACKAGE ' ,
281+ code: 404 ,
282+ callable: function () {
283+ $ test_model = new Test ();
284+ $ test_model ->packages = ['pfSense-pkg-some_package_we_dont_have ' ];
285+ $ test_model ->validate ();
286+ },
287+ );
288+ }
289+
290+ /**
291+ * Checks that when `allow_development_packages` is enabled in RESTAPISettings, a Model whose required package
292+ * is not installed but whose -devel counterpart IS installed passes validation. Since we cannot install arbitrary
293+ * packages in tests, we verify the inverse: that a package whose -devel name also doesn't exist still fails.
294+ */
295+ public function test_model_validate_packages_devel_variant_still_fails_when_neither_installed (): void {
296+ # Enable the allow_development_packages setting
297+ $ settings = new RESTAPI \Models \RESTAPISettings ();
298+ $ settings ->from_internal ();
299+ $ settings ->allow_development_packages ->value = true ;
300+ $ settings ->update (apply: false );
301+
302+ # Even with the setting on, if neither the base package nor the -devel variant is installed, it should fail
303+ $ this ->assert_throws_response (
304+ response_id: 'MODEL_MISSING_REQUIRED_PACKAGE ' ,
305+ code: 404 ,
306+ callable: function () {
307+ $ test_model = new Test ();
308+ $ test_model ->packages = ['pfSense-pkg-some_package_we_dont_have ' ];
309+ $ test_model ->validate ();
310+ },
311+ );
312+
313+ # Restore the setting to its original value
314+ $ settings ->allow_development_packages ->value = false ;
315+ $ settings ->update (apply: false );
316+ }
317+
318+ /**
319+ * Checks that when `allow_development_packages` is enabled, a Model whose required package matches an installed
320+ * package (using pfSense-pkg-RESTAPI as a proxy for the base package) still passes validation normally.
321+ */
322+ public function test_model_validate_packages_base_package_still_accepted_when_devel_enabled (): void {
323+ # Enable the allow_development_packages setting
324+ $ settings = new RESTAPI \Models \RESTAPISettings ();
325+ $ settings ->from_internal ();
326+ $ settings ->allow_development_packages ->value = true ;
327+ $ settings ->update (apply: false );
328+
329+ # The base package (pfSense-pkg-RESTAPI) is installed; validation should still pass
330+ $ test_model = new Test ();
331+ $ test_model ->packages = ['pfSense-pkg-RESTAPI ' ];
332+ $ test_model ->validate ();
333+
334+ # Restore the setting to its original value
335+ $ settings ->allow_development_packages ->value = false ;
336+ $ settings ->update (apply: false );
337+ }
338+
263339 /**
264340 * Checks to ensure the validate() method properly throws an error if we cannot include a required package include
265341 * file because it is not found in the PHP path.
0 commit comments