Skip to content

S006 Edge Cases

IDScenarioExpected Behavior
S006-EC-001settings key is entirely absent from parity.yamlSettings::fromConfig() uses $config['settings'] ?? [] which yields an empty array. All settings fields receive their defaults: namespaceRoots = {'app': 'App', 'tests': 'Tests'}, sourceExtension = ".php", testSuffix = "Test", testExtension = ".php", namespaceSeparator = "\\". No error is raised.
S006-EC-002parity.yaml file exists but is completely empty (zero bytes)Yaml::parse('') returns null. loadConfig() checks is_array($config) which is false for null, so it returns null. The check command receives null from loadConfig() and returns exit code 1.
S006-EC-003coverage_xml is a string "clover.xml" instead of an arrayresolveCoveragePaths() checks is_array($coverageXml) which is false, so it wraps the string: ['clover.xml']. No error. The single candidate is used for coverage file discovery.
S006-EC-004namespace_roots key is absent from the settings blockDefault ['app' => 'App', 'tests' => 'Tests'] is applied via null coalescing. No error. NamespaceHelper operates with standard PHP/Laravel roots.
S006-EC-005Config contains unknown top-level keys (e.g., plugins: [...], experimental: true)Unknown keys are silently ignored. The system only reads known keys (settings, coverage_xml, min_coverage, min_coverage_global, min_matched_coverage, structure). Forward-compatible -- future config keys do not break older versions.
S006-EC-006A structure entry has paths: {} (empty object, missing source and test)resolvePath() returns (string) ($entry['paths']['source'] ?? '') which is "". The source directory resolves to $projectRoot . '/' which may or may not exist. If it does not exist as a directory, the check command prints Source path does not exist: and skips the entry.
S006-EC-007structure key is present with value [] (empty array)The check command detects $structures === [], prints warning: No structure entries in parity.yaml., and returns exit code 0 (success, since no violations are possible).
S006-EC-008file_map in a structure entry is set to a non-array value (e.g., file_map: true or file_map: null)The check command evaluates isset($entry['file_map']) && is_array($entry['file_map']). For non-array values this is false, so $fileMap defaults to [] (empty array). No error. All files use standard naming.
S006-EC-009min_coverage is provided as a string "80" instead of a number 80The (float) cast in fromConfig() converts the string to 80.0. YAML parsing may also convert unquoted numbers automatically. No error in either case.
S006-EC-010min_coverage is set to a negative value (e.g., -10) or a value above 100 (e.g., 150)The system does not validate coverage threshold ranges. (float) -10 produces -10.0 and (float) 150 produces 150.0. With -10, all files trivially pass the threshold. With 150, all files trivially fail. No error is raised at config parse time.
S006-EC-011A structure entry contains both modern (paths, rules) and legacy (source_path, enforce_attribute) keysThe modern keys take precedence. resolvePath() checks $entry['paths'] first and uses it if present. resolveStructureRules() checks for $entry['rules'] first and uses the modern format if present. Legacy keys are ignored when modern keys exist.
S006-EC-012parity.yaml contains valid YAML that parses to a scalar (e.g., file contains only 42 or "hello")Yaml::parse() returns a non-array value. loadConfig() checks is_array($config) which is false, returns null. The check command receives null and returns exit code 1.
S006-EC-013test_extension is not set but source_extension is set to ".ts"fromConfig() evaluates $settingsBlock['test_extension'] ?? ($settingsBlock['source_extension'] ?? '.php'). Since test_extension is absent, it falls through to source_extension which is ".ts". Result: testExtension = ".ts". The test_extension correctly inherits from source_extension.
S006-EC-014coverage_xml is an array containing non-string elements (e.g., [clover.xml, 42, true, null])resolveCoveragePaths() returns the array as-is without type validation. During coverage file discovery, each candidate is cast to string via (string) $candidate when building the path. 42 becomes "42", true becomes "1", null becomes "". These are unlikely to match real files but no error is raised at config parse time.
S006-EC-015Structure entry has rules: [minimum-coverage: {min: 80}] but no test-exists in the listresolveStructureRules() inspects the rules array, finds that test-exists is not present (checking both string entries and map keys), and auto-prepends it. The resolved rules become [test-exists, minimum-coverage].