svg_conform 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rake.yml +15 -0
  3. data/.github/workflows/release.yml +23 -0
  4. data/.github/workflows/svgcheck-compatibility.yml +135 -0
  5. data/.gitignore +12 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +13 -0
  8. data/.rubocop_todo.yml +183 -0
  9. data/CODE_OF_CONDUCT.md +132 -0
  10. data/Gemfile +14 -0
  11. data/README.adoc +1384 -0
  12. data/Rakefile +15 -0
  13. data/config/profiles/base.yml +34 -0
  14. data/config/profiles/lucid_fix.yml +37 -0
  15. data/config/profiles/metanorma.yml +212 -0
  16. data/config/profiles/no_external_css.yml +20 -0
  17. data/config/profiles/svg_1_2_rfc.yml +284 -0
  18. data/config/profiles/svg_1_2_rfc_with_rdf.yml +145 -0
  19. data/config/svgcheck_mapping.yml +180 -0
  20. data/docs/profiles.adoc +547 -0
  21. data/docs/rdf_metadata_support.adoc +212 -0
  22. data/docs/remediation.adoc +732 -0
  23. data/docs/requirements.adoc +709 -0
  24. data/examples/demo.rb +116 -0
  25. data/examples/requirements_demo.rb +240 -0
  26. data/exe/svg_conform +7 -0
  27. data/lib/svg_conform/batch_report.rb +70 -0
  28. data/lib/svg_conform/cli.rb +107 -0
  29. data/lib/svg_conform/commands/check.rb +390 -0
  30. data/lib/svg_conform/commands/profiles.rb +118 -0
  31. data/lib/svg_conform/commands/svgcheck.rb +90 -0
  32. data/lib/svg_conform/commands/svgcheck_compare.rb +92 -0
  33. data/lib/svg_conform/commands/svgcheck_compatibility.rb +43 -0
  34. data/lib/svg_conform/commands/svgcheck_generate.rb +262 -0
  35. data/lib/svg_conform/compatibility/analysis_context.rb +68 -0
  36. data/lib/svg_conform/compatibility/comparison_result.rb +147 -0
  37. data/lib/svg_conform/compatibility/compatibility_analyzer.rb +85 -0
  38. data/lib/svg_conform/compatibility/file_processor.rb +109 -0
  39. data/lib/svg_conform/compatibility/pattern_discovery.rb +319 -0
  40. data/lib/svg_conform/compatibility/report_formatter.rb +359 -0
  41. data/lib/svg_conform/compatibility/svg_analysis_engine.rb +316 -0
  42. data/lib/svg_conform/compatibility/validity_analysis.rb +252 -0
  43. data/lib/svg_conform/compatibility/xml_analysis_engine.rb +198 -0
  44. data/lib/svg_conform/compatibility_analyzer.rb +285 -0
  45. data/lib/svg_conform/conformance_report.rb +267 -0
  46. data/lib/svg_conform/constants.rb +199 -0
  47. data/lib/svg_conform/css_color.rb +262 -0
  48. data/lib/svg_conform/document.rb +203 -0
  49. data/lib/svg_conform/external_checkers/svgcheck/compatibility_engine.rb +166 -0
  50. data/lib/svg_conform/external_checkers/svgcheck/output_generator.rb +101 -0
  51. data/lib/svg_conform/external_checkers/svgcheck/parser.rb +200 -0
  52. data/lib/svg_conform/external_checkers/svgcheck/report_comparator.rb +175 -0
  53. data/lib/svg_conform/external_checkers/svgcheck/report_generator.rb +82 -0
  54. data/lib/svg_conform/external_checkers/svgcheck/validation_pipeline.rb +249 -0
  55. data/lib/svg_conform/external_checkers/svgcheck.rb +56 -0
  56. data/lib/svg_conform/external_checkers.rb +34 -0
  57. data/lib/svg_conform/fixer.rb +56 -0
  58. data/lib/svg_conform/profile.rb +164 -0
  59. data/lib/svg_conform/profiles.rb +60 -0
  60. data/lib/svg_conform/remediation_engine.rb +92 -0
  61. data/lib/svg_conform/remediation_result.rb +36 -0
  62. data/lib/svg_conform/remediation_runner.rb +225 -0
  63. data/lib/svg_conform/remediations/base_remediation.rb +165 -0
  64. data/lib/svg_conform/remediations/color_remediation.rb +226 -0
  65. data/lib/svg_conform/remediations/font_embedding_remediation.rb +145 -0
  66. data/lib/svg_conform/remediations/font_remediation.rb +122 -0
  67. data/lib/svg_conform/remediations/image_embedding_remediation.rb +154 -0
  68. data/lib/svg_conform/remediations/invalid_id_references_remediation.rb +129 -0
  69. data/lib/svg_conform/remediations/namespace_attribute_remediation.rb +244 -0
  70. data/lib/svg_conform/remediations/namespace_remediation.rb +151 -0
  71. data/lib/svg_conform/remediations/no_external_css_remediation.rb +192 -0
  72. data/lib/svg_conform/remediations/style_promotion_remediation.rb +93 -0
  73. data/lib/svg_conform/remediations/viewbox_remediation.rb +127 -0
  74. data/lib/svg_conform/remediations.rb +40 -0
  75. data/lib/svg_conform/report_comparator.rb +772 -0
  76. data/lib/svg_conform/requirements/allowed_elements_requirement.rb +367 -0
  77. data/lib/svg_conform/requirements/base_requirement.rb +98 -0
  78. data/lib/svg_conform/requirements/color_restrictions_requirement.rb +126 -0
  79. data/lib/svg_conform/requirements/element_requirement_config.rb +75 -0
  80. data/lib/svg_conform/requirements/font_family_requirement.rb +133 -0
  81. data/lib/svg_conform/requirements/forbidden_content_requirement.rb +60 -0
  82. data/lib/svg_conform/requirements/id_reference_requirement.rb +133 -0
  83. data/lib/svg_conform/requirements/invalid_id_references_requirement.rb +132 -0
  84. data/lib/svg_conform/requirements/link_validation_requirement.rb +55 -0
  85. data/lib/svg_conform/requirements/namespace_attributes_requirement.rb +211 -0
  86. data/lib/svg_conform/requirements/namespace_requirement.rb +294 -0
  87. data/lib/svg_conform/requirements/no_external_css_requirement.rb +132 -0
  88. data/lib/svg_conform/requirements/no_external_fonts_requirement.rb +121 -0
  89. data/lib/svg_conform/requirements/no_external_images_requirement.rb +91 -0
  90. data/lib/svg_conform/requirements/style_promotion_requirement.rb +72 -0
  91. data/lib/svg_conform/requirements/style_requirement.rb +226 -0
  92. data/lib/svg_conform/requirements/viewbox_required_requirement.rb +96 -0
  93. data/lib/svg_conform/requirements.rb +49 -0
  94. data/lib/svg_conform/semantic_comparator.rb +829 -0
  95. data/lib/svg_conform/validation_context.rb +408 -0
  96. data/lib/svg_conform/validation_result.rb +146 -0
  97. data/lib/svg_conform/validator.rb +91 -0
  98. data/lib/svg_conform/version.rb +5 -0
  99. data/lib/svg_conform.rb +68 -0
  100. data/lib/tasks/fixtures.rake +321 -0
  101. data/lib/tasks/svgcheck.rake +111 -0
  102. data/reference-docs/SVG-1.2-RFC.rnc.txt +1676 -0
  103. data/reference-docs/Scalable Vector Graphics (SVG) 1.1 (Second Edition).html +40764 -0
  104. data/reference-docs/Scalable Vector Graphics (SVG) Tiny 1.2 Specification.html +44591 -0
  105. data/reference-docs/rfc7996.txt +2971 -0
  106. data/sig/svg_conform.rbs +4 -0
  107. data/spec/fixtures/allowed_elements/inputs/basic_violations.svg +21 -0
  108. data/spec/fixtures/allowed_elements/repair/basic_violations.svg +18 -0
  109. data/spec/fixtures/color_restrictions/inputs/basic_violations.svg +23 -0
  110. data/spec/fixtures/color_restrictions/repair/basic_violations.svg +23 -0
  111. data/spec/fixtures/comprehensive/inputs/multiple_violations.svg +21 -0
  112. data/spec/fixtures/comprehensive/repair/multiple_violations.svg +16 -0
  113. data/spec/fixtures/font_family/inputs/basic_violations.svg +17 -0
  114. data/spec/fixtures/font_family/repair/basic_violations.svg +17 -0
  115. data/spec/fixtures/forbidden_content/inputs/basic_violations.svg +27 -0
  116. data/spec/fixtures/forbidden_content/repair/basic_violations.svg +19 -0
  117. data/spec/fixtures/id_reference/inputs/basic_violations.svg +17 -0
  118. data/spec/fixtures/id_reference/repair/basic_violations.svg +15 -0
  119. data/spec/fixtures/link_validation/inputs/basic_violations.svg +20 -0
  120. data/spec/fixtures/link_validation/repair/basic_violations.svg +16 -0
  121. data/spec/fixtures/lucid/inputs/simple.svg +67 -0
  122. data/spec/fixtures/lucid/repair/simple.svg +63 -0
  123. data/spec/fixtures/namespace/inputs/basic_violations.svg +20 -0
  124. data/spec/fixtures/namespace/repair/basic_violations.svg +17 -0
  125. data/spec/fixtures/namespace_attributes/inputs/basic_violations.svg +16 -0
  126. data/spec/fixtures/namespace_attributes/repair/basic_violations.svg +15 -0
  127. data/spec/fixtures/no_external_css/inputs/basic_violations.svg +20 -0
  128. data/spec/fixtures/no_external_css/repair/basic_violations.svg +18 -0
  129. data/spec/fixtures/style/inputs/basic_violations.svg +22 -0
  130. data/spec/fixtures/style/repair/basic_violations.svg +22 -0
  131. data/spec/fixtures/style_promotion/inputs/basic_test.svg +15 -0
  132. data/spec/fixtures/style_promotion/repair/basic_test.svg +15 -0
  133. data/spec/fixtures/svg_1_2_rfc/inputs/allowed_elements_violations.svg +18 -0
  134. data/spec/fixtures/svg_1_2_rfc/inputs/color_restrictions_violations.svg +23 -0
  135. data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.code +1 -0
  136. data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.err +0 -0
  137. data/spec/fixtures/svgcheck/check/DrawBerry-sample-2.svg.out +23 -0
  138. data/spec/fixtures/svgcheck/check/IETF-test.svg.code +1 -0
  139. data/spec/fixtures/svgcheck/check/IETF-test.svg.err +0 -0
  140. data/spec/fixtures/svgcheck/check/IETF-test.svg.out +20 -0
  141. data/spec/fixtures/svgcheck/check/circle.svg.code +1 -0
  142. data/spec/fixtures/svgcheck/check/circle.svg.err +0 -0
  143. data/spec/fixtures/svgcheck/check/circle.svg.out +2 -0
  144. data/spec/fixtures/svgcheck/check/colors.svg.code +1 -0
  145. data/spec/fixtures/svgcheck/check/colors.svg.err +0 -0
  146. data/spec/fixtures/svgcheck/check/colors.svg.out +13 -0
  147. data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.code +1 -0
  148. data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.err +0 -0
  149. data/spec/fixtures/svgcheck/check/dia-sample-svg.svg.out +76 -0
  150. data/spec/fixtures/svgcheck/check/example-dot.svg.code +1 -0
  151. data/spec/fixtures/svgcheck/check/example-dot.svg.err +0 -0
  152. data/spec/fixtures/svgcheck/check/example-dot.svg.out +11 -0
  153. data/spec/fixtures/svgcheck/check/full-tiny.svg.code +1 -0
  154. data/spec/fixtures/svgcheck/check/full-tiny.svg.err +0 -0
  155. data/spec/fixtures/svgcheck/check/full-tiny.svg.out +5835 -0
  156. data/spec/fixtures/svgcheck/check/good.svg.code +1 -0
  157. data/spec/fixtures/svgcheck/check/good.svg.err +0 -0
  158. data/spec/fixtures/svgcheck/check/good.svg.out +1 -0
  159. data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.code +1 -0
  160. data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.err +0 -0
  161. data/spec/fixtures/svgcheck/check/httpbis-proxy20-fig6.svg.out +5 -0
  162. data/spec/fixtures/svgcheck/check/malformed.svg.code +1 -0
  163. data/spec/fixtures/svgcheck/check/malformed.svg.err +0 -0
  164. data/spec/fixtures/svgcheck/check/malformed.svg.out +8 -0
  165. data/spec/fixtures/svgcheck/check/rfc-svg.svg.code +1 -0
  166. data/spec/fixtures/svgcheck/check/rfc-svg.svg.err +0 -0
  167. data/spec/fixtures/svgcheck/check/rfc-svg.svg.out +1 -0
  168. data/spec/fixtures/svgcheck/check/rfc.xml.code +1 -0
  169. data/spec/fixtures/svgcheck/check/rfc.xml.err +0 -0
  170. data/spec/fixtures/svgcheck/check/rfc.xml.out +2 -0
  171. data/spec/fixtures/svgcheck/check/rgb.svg.code +1 -0
  172. data/spec/fixtures/svgcheck/check/rgb.svg.err +0 -0
  173. data/spec/fixtures/svgcheck/check/rgb.svg.out +9 -0
  174. data/spec/fixtures/svgcheck/check/svg-wordle.svg.code +1 -0
  175. data/spec/fixtures/svgcheck/check/svg-wordle.svg.err +0 -0
  176. data/spec/fixtures/svgcheck/check/svg-wordle.svg.out +508 -0
  177. data/spec/fixtures/svgcheck/check/threshold.svg.code +1 -0
  178. data/spec/fixtures/svgcheck/check/threshold.svg.err +0 -0
  179. data/spec/fixtures/svgcheck/check/threshold.svg.out +20 -0
  180. data/spec/fixtures/svgcheck/check/utf8.svg.code +1 -0
  181. data/spec/fixtures/svgcheck/check/utf8.svg.err +0 -0
  182. data/spec/fixtures/svgcheck/check/utf8.svg.out +162 -0
  183. data/spec/fixtures/svgcheck/check/viewBox-both.svg.code +1 -0
  184. data/spec/fixtures/svgcheck/check/viewBox-both.svg.err +0 -0
  185. data/spec/fixtures/svgcheck/check/viewBox-both.svg.out +4 -0
  186. data/spec/fixtures/svgcheck/check/viewBox-height.svg.code +1 -0
  187. data/spec/fixtures/svgcheck/check/viewBox-height.svg.err +0 -0
  188. data/spec/fixtures/svgcheck/check/viewBox-height.svg.out +3 -0
  189. data/spec/fixtures/svgcheck/check/viewBox-none.svg.code +1 -0
  190. data/spec/fixtures/svgcheck/check/viewBox-none.svg.err +0 -0
  191. data/spec/fixtures/svgcheck/check/viewBox-none.svg.out +3 -0
  192. data/spec/fixtures/svgcheck/check/viewBox-width.svg.code +1 -0
  193. data/spec/fixtures/svgcheck/check/viewBox-width.svg.err +0 -0
  194. data/spec/fixtures/svgcheck/check/viewBox-width.svg.out +3 -0
  195. data/spec/fixtures/svgcheck/inputs/DrawBerry-sample-2.svg +28 -0
  196. data/spec/fixtures/svgcheck/inputs/IETF-test.svg +28 -0
  197. data/spec/fixtures/svgcheck/inputs/circle.svg +3 -0
  198. data/spec/fixtures/svgcheck/inputs/colors.svg +18 -0
  199. data/spec/fixtures/svgcheck/inputs/dia-sample-svg.svg +47 -0
  200. data/spec/fixtures/svgcheck/inputs/example-dot.svg +75 -0
  201. data/spec/fixtures/svgcheck/inputs/full-tiny.svg +16194 -0
  202. data/spec/fixtures/svgcheck/inputs/good.svg +19 -0
  203. data/spec/fixtures/svgcheck/inputs/httpbis-proxy20-fig6.svg +2 -0
  204. data/spec/fixtures/svgcheck/inputs/malformed.svg +11 -0
  205. data/spec/fixtures/svgcheck/inputs/rfc-svg.svg +1028 -0
  206. data/spec/fixtures/svgcheck/inputs/rfc.xml +37 -0
  207. data/spec/fixtures/svgcheck/inputs/rgb.svg +9 -0
  208. data/spec/fixtures/svgcheck/inputs/svg-wordle.svg +330 -0
  209. data/spec/fixtures/svgcheck/inputs/threshold.svg +26 -0
  210. data/spec/fixtures/svgcheck/inputs/utf8.svg +448 -0
  211. data/spec/fixtures/svgcheck/inputs/viewBox-both.svg +3 -0
  212. data/spec/fixtures/svgcheck/inputs/viewBox-height.svg +3 -0
  213. data/spec/fixtures/svgcheck/inputs/viewBox-none.svg +3 -0
  214. data/spec/fixtures/svgcheck/inputs/viewBox-width.svg +3 -0
  215. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.code +1 -0
  216. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.err +0 -0
  217. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.file +0 -0
  218. data/spec/fixtures/svgcheck/repair/DrawBerry-sample-2.svg.out +23 -0
  219. data/spec/fixtures/svgcheck/repair/IETF-test.svg.code +1 -0
  220. data/spec/fixtures/svgcheck/repair/IETF-test.svg.err +0 -0
  221. data/spec/fixtures/svgcheck/repair/IETF-test.svg.file +29 -0
  222. data/spec/fixtures/svgcheck/repair/IETF-test.svg.out +20 -0
  223. data/spec/fixtures/svgcheck/repair/circle.svg.code +1 -0
  224. data/spec/fixtures/svgcheck/repair/circle.svg.err +0 -0
  225. data/spec/fixtures/svgcheck/repair/circle.svg.file +4 -0
  226. data/spec/fixtures/svgcheck/repair/circle.svg.out +2 -0
  227. data/spec/fixtures/svgcheck/repair/colors.svg.code +1 -0
  228. data/spec/fixtures/svgcheck/repair/colors.svg.err +0 -0
  229. data/spec/fixtures/svgcheck/repair/colors.svg.file +19 -0
  230. data/spec/fixtures/svgcheck/repair/colors.svg.out +13 -0
  231. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.code +1 -0
  232. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.err +0 -0
  233. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.file +47 -0
  234. data/spec/fixtures/svgcheck/repair/dia-sample-svg.svg.out +76 -0
  235. data/spec/fixtures/svgcheck/repair/example-dot.svg.code +1 -0
  236. data/spec/fixtures/svgcheck/repair/example-dot.svg.err +0 -0
  237. data/spec/fixtures/svgcheck/repair/example-dot.svg.file +69 -0
  238. data/spec/fixtures/svgcheck/repair/example-dot.svg.out +11 -0
  239. data/spec/fixtures/svgcheck/repair/good.svg.code +1 -0
  240. data/spec/fixtures/svgcheck/repair/good.svg.err +0 -0
  241. data/spec/fixtures/svgcheck/repair/good.svg.file +0 -0
  242. data/spec/fixtures/svgcheck/repair/good.svg.out +1 -0
  243. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.code +1 -0
  244. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.err +0 -0
  245. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.file +73 -0
  246. data/spec/fixtures/svgcheck/repair/httpbis-proxy20-fig6.svg.out +5 -0
  247. data/spec/fixtures/svgcheck/repair/malformed.svg.code +1 -0
  248. data/spec/fixtures/svgcheck/repair/malformed.svg.err +0 -0
  249. data/spec/fixtures/svgcheck/repair/malformed.svg.file +9 -0
  250. data/spec/fixtures/svgcheck/repair/malformed.svg.out +8 -0
  251. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.code +1 -0
  252. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.err +0 -0
  253. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.file +0 -0
  254. data/spec/fixtures/svgcheck/repair/rfc-svg.svg.out +1 -0
  255. data/spec/fixtures/svgcheck/repair/rfc.xml.code +1 -0
  256. data/spec/fixtures/svgcheck/repair/rfc.xml.err +0 -0
  257. data/spec/fixtures/svgcheck/repair/rfc.xml.file +37 -0
  258. data/spec/fixtures/svgcheck/repair/rfc.xml.out +2 -0
  259. data/spec/fixtures/svgcheck/repair/rgb.svg.code +1 -0
  260. data/spec/fixtures/svgcheck/repair/rgb.svg.err +0 -0
  261. data/spec/fixtures/svgcheck/repair/rgb.svg.file +10 -0
  262. data/spec/fixtures/svgcheck/repair/rgb.svg.out +9 -0
  263. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.code +1 -0
  264. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.err +0 -0
  265. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.file +112 -0
  266. data/spec/fixtures/svgcheck/repair/svg-wordle.svg.out +508 -0
  267. data/spec/fixtures/svgcheck/repair/threshold.svg.code +1 -0
  268. data/spec/fixtures/svgcheck/repair/threshold.svg.err +0 -0
  269. data/spec/fixtures/svgcheck/repair/threshold.svg.file +27 -0
  270. data/spec/fixtures/svgcheck/repair/threshold.svg.out +20 -0
  271. data/spec/fixtures/svgcheck/repair/utf8.svg.code +1 -0
  272. data/spec/fixtures/svgcheck/repair/utf8.svg.err +0 -0
  273. data/spec/fixtures/svgcheck/repair/utf8.svg.file +381 -0
  274. data/spec/fixtures/svgcheck/repair/utf8.svg.out +162 -0
  275. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.code +1 -0
  276. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.err +0 -0
  277. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.file +4 -0
  278. data/spec/fixtures/svgcheck/repair/viewBox-both.svg.out +4 -0
  279. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.code +1 -0
  280. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.err +0 -0
  281. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.file +4 -0
  282. data/spec/fixtures/svgcheck/repair/viewBox-height.svg.out +3 -0
  283. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.code +1 -0
  284. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.err +0 -0
  285. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.file +4 -0
  286. data/spec/fixtures/svgcheck/repair/viewBox-none.svg.out +3 -0
  287. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.code +1 -0
  288. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.err +0 -0
  289. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.file +4 -0
  290. data/spec/fixtures/svgcheck/repair/viewBox-width.svg.out +3 -0
  291. data/spec/fixtures/viewbox_required/inputs/missing_viewbox.svg +10 -0
  292. data/spec/fixtures/viewbox_required/repair/missing_viewbox.svg +10 -0
  293. data/spec/spec_helper.rb +16 -0
  294. data/spec/svg_conform/batch_report_spec.rb +99 -0
  295. data/spec/svg_conform/commands/check_command_spec.rb +90 -0
  296. data/spec/svg_conform/commands/profiles_command_spec.rb +20 -0
  297. data/spec/svg_conform/commands/svgcheck_compare_command_spec.rb +13 -0
  298. data/spec/svg_conform/commands/svgcheck_compatibility_command_spec.rb +13 -0
  299. data/spec/svg_conform/commands/svgcheck_generate_command_spec.rb +14 -0
  300. data/spec/svg_conform/profiles/base_profile_spec.rb +42 -0
  301. data/spec/svg_conform/profiles/lucid_fix_profile_spec.rb +46 -0
  302. data/spec/svg_conform/profiles/lucid_profile_spec.rb +84 -0
  303. data/spec/svg_conform/profiles/metanorma_profile_spec.rb +62 -0
  304. data/spec/svg_conform/profiles/no_external_css_profile_spec.rb +66 -0
  305. data/spec/svg_conform/profiles/svg_1_2_rfc_profile_spec.rb +200 -0
  306. data/spec/svg_conform/profiles/svg_1_2_rfc_with_rdf_profile_spec.rb +81 -0
  307. data/spec/svg_conform/remediations/color_remediation_spec.rb +95 -0
  308. data/spec/svg_conform/remediations/font_embedding_remediation_spec.rb +20 -0
  309. data/spec/svg_conform/remediations/font_remediation_spec.rb +95 -0
  310. data/spec/svg_conform/remediations/image_embedding_remediation_spec.rb +20 -0
  311. data/spec/svg_conform/remediations/invalid_id_references_remediation_spec.rb +97 -0
  312. data/spec/svg_conform/remediations/namespace_attribute_remediation_spec.rb +97 -0
  313. data/spec/svg_conform/remediations/namespace_remediation_spec.rb +95 -0
  314. data/spec/svg_conform/remediations/no_external_css_remediation_spec.rb +97 -0
  315. data/spec/svg_conform/remediations/style_promotion_remediation_spec.rb +97 -0
  316. data/spec/svg_conform/remediations/viewbox_remediation_spec.rb +95 -0
  317. data/spec/svg_conform/requirements/allowed_elements_requirement_spec.rb +118 -0
  318. data/spec/svg_conform/requirements/color_restrictions_requirement_spec.rb +168 -0
  319. data/spec/svg_conform/requirements/font_family_requirement_spec.rb +188 -0
  320. data/spec/svg_conform/requirements/forbidden_content_requirement_spec.rb +195 -0
  321. data/spec/svg_conform/requirements/id_reference_requirement_spec.rb +78 -0
  322. data/spec/svg_conform/requirements/invalid_id_references_requirement_spec.rb +78 -0
  323. data/spec/svg_conform/requirements/link_validation_requirement_spec.rb +78 -0
  324. data/spec/svg_conform/requirements/namespace_attributes_requirement_spec.rb +86 -0
  325. data/spec/svg_conform/requirements/namespace_requirement_spec.rb +184 -0
  326. data/spec/svg_conform/requirements/no_external_css_requirement_spec.rb +78 -0
  327. data/spec/svg_conform/requirements/no_external_fonts_requirement_spec.rb +20 -0
  328. data/spec/svg_conform/requirements/no_external_images_requirement_spec.rb +20 -0
  329. data/spec/svg_conform/requirements/style_promotion_requirement_spec.rb +78 -0
  330. data/spec/svg_conform/requirements/style_requirement_spec.rb +76 -0
  331. data/spec/svg_conform/requirements/viewbox_required_requirement_spec.rb +165 -0
  332. data/spec/svg_conform_spec.rb +32 -0
  333. data/spec/svgcheck_compatibility_spec.rb +355 -0
  334. data/svg_conform.gemspec +35 -0
  335. metadata +436 -0
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "canon"
5
+ require "tempfile"
6
+
7
+ RSpec.describe "SVG 1.2 RFC Profile" do
8
+ let(:svg_1_2_rfc_profile_path) { "config/profiles/svg_1_2_rfc.yml" }
9
+ let(:fixtures_base_dir) { "spec/fixtures" }
10
+
11
+ describe "profile loading" do
12
+ it "loads the SVG 1.2 RFC profile successfully" do
13
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
14
+ expect(profile).not_to be_nil
15
+ expect(profile.name).to eq("svg_1_2_rfc")
16
+ expect(profile.description).to include("RFC 7996")
17
+ end
18
+
19
+ it "has all expected requirements" do
20
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
21
+ requirement_ids = profile.requirements.map(&:id)
22
+
23
+ expected_requirements = %w[
24
+ allowed_elements
25
+ color_restrictions
26
+ font_family
27
+ style
28
+ namespace_validation
29
+ namespace_attributes
30
+ viewbox_required
31
+ link_validation
32
+ id_references
33
+ forbidden_content
34
+ style_promotion
35
+ ]
36
+
37
+ expect(requirement_ids).to include(*expected_requirements)
38
+ end
39
+
40
+ it "has all expected remediations" do
41
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
42
+ remediation_ids = profile.remediations.map(&:id)
43
+
44
+ expected_remediations = %w[
45
+ color_conversion
46
+ font_family_conversion
47
+ style_promotion
48
+ viewbox_generation
49
+ ]
50
+
51
+ expect(remediation_ids).to include(*expected_remediations)
52
+ end
53
+ end
54
+
55
+ # Test each requirement with its specific fixtures
56
+ REQUIREMENTS_TO_TEST = %w[
57
+ allowed_elements
58
+ color_restrictions
59
+ font_family
60
+ forbidden_content
61
+ id_reference
62
+ link_validation
63
+ namespace_attributes
64
+ namespace
65
+ no_external_css
66
+ style
67
+ style_promotion
68
+ viewbox_required
69
+ ].freeze
70
+
71
+ FIXTURES_BASE_DIR = "spec/fixtures"
72
+
73
+ REQUIREMENTS_TO_TEST.each do |requirement_name|
74
+ fixtures_dir_path = File.join(FIXTURES_BASE_DIR, requirement_name)
75
+
76
+ # Skip if fixture directory doesn't exist
77
+ next unless Dir.exist?(fixtures_dir_path)
78
+
79
+ describe "#{requirement_name} requirement" do
80
+ # Get all fixture files that have both input and expected repair versions
81
+ fixture_files = Dir.glob(File.join(fixtures_dir_path,
82
+ "inputs/*.svg")).select do |input_file|
83
+ basename = File.basename(input_file)
84
+ File.exist?(File.join(fixtures_dir_path, "repair", basename))
85
+ end.map do |f|
86
+ File.basename(f, ".svg")
87
+ end
88
+
89
+ fixture_files.each do |fixture_name|
90
+ describe "fixture: #{fixture_name}" do
91
+ let(:fixtures_dir) { File.join(FIXTURES_BASE_DIR, requirement_name) }
92
+ let(:input_file) do
93
+ File.join(fixtures_dir, "inputs", "#{fixture_name}.svg")
94
+ end
95
+ let(:expected_output_file) do
96
+ File.join(fixtures_dir, "repair", "#{fixture_name}.svg")
97
+ end
98
+
99
+ it "validates input file and identifies violations" do
100
+ skip "Input file not found" unless File.exist?(input_file)
101
+
102
+ document = SvgConform::Document.from_file(input_file)
103
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
104
+
105
+ validation_result = profile.validate(document)
106
+
107
+ # Should have violations for this test case
108
+ expect(validation_result.valid?).to be false
109
+ expect(validation_result.errors.count).to be > 0
110
+
111
+ puts "Found #{validation_result.errors.count} violations in #{fixture_name}"
112
+ end
113
+
114
+ it "applies available remediations successfully" do
115
+ skip "Expected repair file not found" unless File.exist?(expected_output_file)
116
+ skip "Input file not found" unless File.exist?(input_file)
117
+
118
+ # Load the document and apply profile remediations
119
+ document = SvgConform::Document.from_file(input_file)
120
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
121
+
122
+ # Get initial error count
123
+ initial_result = profile.validate(document)
124
+ initial_error_count = initial_result.errors.count
125
+
126
+ # Apply all remediations
127
+ changes = profile.apply_remediations(document)
128
+
129
+ # Get final error count
130
+ final_result = profile.validate(document)
131
+ final_error_count = final_result.errors.count
132
+
133
+ # Show remediation progress
134
+ puts "Remediation results for #{fixture_name}: #{initial_error_count} → #{final_error_count} errors"
135
+ puts " Changes applied: #{changes.count}" if changes.any?
136
+
137
+ # For requirements with implemented remediations, expect fewer errors
138
+ requirements_with_remediations = %w[color_restrictions font_family
139
+ viewbox_required]
140
+
141
+ if requirements_with_remediations.include?(requirement_name)
142
+ expect(final_error_count).to be < initial_error_count
143
+ else
144
+ # For requirements without remediations, document the current state
145
+ puts " Note: No remediations available for #{requirement_name} requirement"
146
+ end
147
+ end
148
+
149
+ it "maintains XML structure integrity after processing" do
150
+ skip "Input file not found" unless File.exist?(input_file)
151
+
152
+ # Load the document and apply profile remediations
153
+ document = SvgConform::Document.from_file(input_file)
154
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
155
+
156
+ # Apply all remediations
157
+ profile.apply_remediations(document)
158
+
159
+ # Should still be valid XML
160
+ expect(document.to_xml).to match(/<svg\s+[^>]*>.*<\/svg>/m)
161
+
162
+ # Should maintain root element structure
163
+ expect(document.root.name).to eq("svg")
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ describe "comprehensive test" do
171
+ let(:comprehensive_input) do
172
+ "spec/fixtures/comprehensive/inputs/multiple_violations.svg"
173
+ end
174
+ let(:comprehensive_expected) do
175
+ "spec/fixtures/comprehensive/repair/multiple_violations.svg"
176
+ end
177
+
178
+ it "handles multiple violations across different requirements" do
179
+ skip "Comprehensive fixtures not found" unless File.exist?(comprehensive_input)
180
+
181
+ document = SvgConform::Document.from_file(comprehensive_input)
182
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_profile_path)
183
+
184
+ # Initial validation should show multiple violations
185
+ initial_result = profile.validate(document)
186
+ expect(initial_result.valid?).to be false
187
+ expect(initial_result.errors.count).to be > 5
188
+
189
+ # Apply remediations
190
+ changes = profile.apply_remediations(document)
191
+ expect(changes).not_to be_empty
192
+
193
+ # Final validation should be much better
194
+ final_result = profile.validate(document)
195
+ expect(final_result.errors.count).to be < initial_result.errors.count
196
+
197
+ puts "Comprehensive test: #{initial_result.errors.count} → #{final_result.errors.count} violations"
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe "SVG 1.2 RFC with RDF Profile" do
6
+ let(:svg_1_2_rfc_with_rdf_profile_path) do
7
+ "config/profiles/svg_1_2_rfc_with_rdf.yml"
8
+ end
9
+
10
+ describe "profile loading" do
11
+ it "loads the SVG 1.2 RFC with RDF profile successfully" do
12
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_with_rdf_profile_path)
13
+ expect(profile).not_to be_nil
14
+ expect(profile.name).to eq("svg_1_2_rfc_with_rdf")
15
+ end
16
+
17
+ it "includes all base RFC 7996 requirements" do
18
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_with_rdf_profile_path)
19
+ requirement_ids = profile.requirements.map(&:id)
20
+
21
+ base_requirements = %w[
22
+ allowed_elements
23
+ color_restrictions
24
+ font_family
25
+ namespace_validation
26
+ viewbox_required
27
+ ]
28
+
29
+ expect(requirement_ids).to include(*base_requirements)
30
+ end
31
+
32
+ it "has description indicating RDF metadata support" do
33
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_with_rdf_profile_path)
34
+ expect(profile.description).to be_a(String)
35
+ expect(profile.description.downcase).to match(/rdf|metadata/)
36
+ end
37
+ end
38
+
39
+ describe "RDF metadata handling" do
40
+ it "allows RDF metadata elements" do
41
+ svg_with_rdf = <<~SVG
42
+ <svg xmlns="http://www.w3.org/2000/svg"
43
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
44
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
45
+ viewBox="0 0 100 100">
46
+ <metadata>
47
+ <rdf:RDF>
48
+ <rdf:Description>
49
+ <dc:title>Test Document</dc:title>
50
+ </rdf:Description>
51
+ </rdf:RDF>
52
+ </metadata>
53
+ <rect x="10" y="10" width="50" height="50" fill="red"/>
54
+ </svg>
55
+ SVG
56
+
57
+ document = SvgConform::Document.from_content(svg_with_rdf)
58
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_with_rdf_profile_path)
59
+
60
+ result = profile.validate(document)
61
+ expect(result).to respond_to(:valid?)
62
+ end
63
+ end
64
+
65
+ describe "validation" do
66
+ it "maintains all SVG 1.2 RFC compliance checks" do
67
+ svg_content = <<~SVG
68
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
69
+ <rect x="10" y="10" width="50" height="50" fill="red"/>
70
+ </svg>
71
+ SVG
72
+
73
+ document = SvgConform::Document.from_content(svg_content)
74
+ profile = SvgConform::Profile.load_from_file(svg_1_2_rfc_with_rdf_profile_path)
75
+
76
+ result = profile.validate(document)
77
+ expect(result).to respond_to(:valid?)
78
+ expect(result).to respond_to(:errors)
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "canon"
5
+
6
+ RSpec.describe SvgConform::Remediations::ColorRemediation do
7
+ let(:fixtures_dir) { "spec/fixtures/color" }
8
+
9
+ # Get all fixture files that have both input and expected repair versions
10
+ fixture_files = Dir.glob("spec/fixtures/color/inputs/*.svg").select do |input_file|
11
+ basename = File.basename(input_file)
12
+ File.exist?("spec/fixtures/color/repair/#{basename}")
13
+ end.map do |f|
14
+ File.basename(f, ".svg")
15
+ end
16
+
17
+ fixture_files.each do |fixture_name|
18
+ describe "fixture: #{fixture_name}" do
19
+ let(:input_file) { "spec/fixtures/color/inputs/#{fixture_name}.svg" }
20
+ let(:expected_output_file) do
21
+ "spec/fixtures/color/repair/#{fixture_name}.svg"
22
+ end
23
+
24
+ it "applies remediation and produces expected output" do
25
+ skip "Input file not found" unless File.exist?(input_file)
26
+ skip "Expected output file not found" unless File.exist?(expected_output_file)
27
+
28
+ document = SvgConform::Document.from_file(input_file)
29
+ remediation = described_class.new(
30
+ id: "color_fix",
31
+ description: "Test color remediation",
32
+ )
33
+
34
+ # Apply the remediation (remediations need context parameter)
35
+ context = SvgConform::ValidationContext.new(document, nil)
36
+ changes = remediation.apply(document, context)
37
+
38
+ # Verify changes were made
39
+ expect(changes).to be_an(Array)
40
+ puts "Applied #{changes.count} changes in #{fixture_name}" if changes.any?
41
+
42
+ # Get the remediated XML
43
+ actual_xml = document.to_xml
44
+ expected_xml = File.read(expected_output_file)
45
+
46
+ # Use canon matcher for XML equivalence
47
+ expect(actual_xml).to be_analogous_with(expected_xml)
48
+ end
49
+
50
+ it "produces valid XML after remediation" do
51
+ skip "Input file not found" unless File.exist?(input_file)
52
+
53
+ document = SvgConform::Document.from_file(input_file)
54
+ remediation = described_class.new(
55
+ id: "color_fix",
56
+ description: "Test color remediation",
57
+ )
58
+
59
+ # Apply the remediation (remediations need context parameter)
60
+ context = SvgConform::ValidationContext.new(document, nil)
61
+ remediation.apply(document, context)
62
+
63
+ # Get the remediated XML
64
+ actual_xml = document.to_xml
65
+
66
+ # Basic XML validity check
67
+ expect(actual_xml).to include("<svg")
68
+ expect(actual_xml).to include("</svg>")
69
+ expect do
70
+ SvgConform::Document.from_content(actual_xml)
71
+ end.not_to raise_error
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "configuration" do
77
+ it "can be instantiated with basic parameters" do
78
+ remediation = described_class.new(
79
+ id: "test_color_fix",
80
+ description: "Test remediation",
81
+ )
82
+
83
+ expect(remediation).to be_a(described_class)
84
+ end
85
+
86
+ it "responds to apply method" do
87
+ remediation = described_class.new(
88
+ id: "test_color_fix",
89
+ description: "Test remediation",
90
+ )
91
+
92
+ expect(remediation).to respond_to(:apply)
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe SvgConform::Remediations::FontEmbeddingRemediation do
6
+ describe "configuration" do
7
+ it "can be instantiated with basic parameters" do
8
+ remediation = described_class.new(
9
+ id: "font_embedding",
10
+ description: "Test",
11
+ )
12
+ expect(remediation).to respond_to(:apply)
13
+ end
14
+
15
+ it "responds to apply method" do
16
+ remediation = described_class.new(id: "test", description: "Test")
17
+ expect(remediation).to respond_to(:apply)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "canon"
5
+
6
+ RSpec.describe SvgConform::Remediations::FontRemediation do
7
+ let(:fixtures_dir) { "spec/fixtures/font" }
8
+
9
+ # Get all fixture files that have both input and expected repair versions
10
+ fixture_files = Dir.glob("spec/fixtures/font/inputs/*.svg").select do |input_file|
11
+ basename = File.basename(input_file)
12
+ File.exist?("spec/fixtures/font/repair/#{basename}")
13
+ end.map do |f|
14
+ File.basename(f, ".svg")
15
+ end
16
+
17
+ fixture_files.each do |fixture_name|
18
+ describe "fixture: #{fixture_name}" do
19
+ let(:input_file) { "spec/fixtures/font/inputs/#{fixture_name}.svg" }
20
+ let(:expected_output_file) do
21
+ "spec/fixtures/font/repair/#{fixture_name}.svg"
22
+ end
23
+
24
+ it "applies remediation and produces expected output" do
25
+ skip "Input file not found" unless File.exist?(input_file)
26
+ skip "Expected output file not found" unless File.exist?(expected_output_file)
27
+
28
+ document = SvgConform::Document.from_file(input_file)
29
+ remediation = described_class.new(
30
+ id: "font_fix",
31
+ description: "Test font remediation",
32
+ )
33
+
34
+ # Apply the remediation
35
+ context = SvgConform::ValidationContext.new(document, nil)
36
+ changes = remediation.apply(document, context)
37
+
38
+ # Verify changes were made
39
+ expect(changes).to be_an(Array)
40
+ puts "Applied #{changes.count} changes in #{fixture_name}" if changes.any?
41
+
42
+ # Get the remediated XML
43
+ actual_xml = document.to_xml
44
+ expected_xml = File.read(expected_output_file)
45
+
46
+ # Use canon matcher for XML equivalence
47
+ expect(actual_xml).to be_analogous_with(expected_xml)
48
+ end
49
+
50
+ it "produces valid XML after remediation" do
51
+ skip "Input file not found" unless File.exist?(input_file)
52
+
53
+ document = SvgConform::Document.from_file(input_file)
54
+ remediation = described_class.new(
55
+ id: "font_fix",
56
+ description: "Test font remediation",
57
+ )
58
+
59
+ # Apply the remediation
60
+ context = SvgConform::ValidationContext.new(document, nil)
61
+ remediation.apply(document, context)
62
+
63
+ # Get the remediated XML
64
+ actual_xml = document.to_xml
65
+
66
+ # Basic XML validity check
67
+ expect(actual_xml).to include("<svg")
68
+ expect(actual_xml).to include("</svg>")
69
+ expect do
70
+ SvgConform::Document.from_content(actual_xml)
71
+ end.not_to raise_error
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "configuration" do
77
+ it "can be instantiated with basic parameters" do
78
+ remediation = described_class.new(
79
+ id: "test_font_fix",
80
+ description: "Test remediation",
81
+ )
82
+
83
+ expect(remediation).to be_a(described_class)
84
+ end
85
+
86
+ it "responds to apply method" do
87
+ remediation = described_class.new(
88
+ id: "test_font_fix",
89
+ description: "Test remediation",
90
+ )
91
+
92
+ expect(remediation).to respond_to(:apply)
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe SvgConform::Remediations::ImageEmbeddingRemediation do
6
+ describe "configuration" do
7
+ it "can be instantiated with basic parameters" do
8
+ remediation = described_class.new(
9
+ id: "image_embedding",
10
+ description: "Test",
11
+ )
12
+ expect(remediation).to respond_to(:apply)
13
+ end
14
+
15
+ it "responds to apply method" do
16
+ remediation = described_class.new(id: "test", description: "Test")
17
+ expect(remediation).to respond_to(:apply)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "canon"
5
+
6
+ RSpec.describe SvgConform::Remediations::InvalidIdReferencesRemediation do
7
+ let(:fixtures_dir) { "spec/fixtures/invalid_id_references" }
8
+
9
+ # Get all fixture files that have both input and expected repair versions
10
+ fixture_files = Dir.glob("spec/fixtures/invalid_id_references/inputs/*.svg").select do |input_file|
11
+ basename = File.basename(input_file)
12
+ File.exist?("spec/fixtures/invalid_id_references/repair/#{basename}")
13
+ end.map do |f|
14
+ File.basename(f, ".svg")
15
+ end
16
+
17
+ fixture_files.each do |fixture_name|
18
+ describe "fixture: #{fixture_name}" do
19
+ let(:input_file) do
20
+ "spec/fixtures/invalid_id_references/inputs/#{fixture_name}.svg"
21
+ end
22
+ let(:expected_output_file) do
23
+ "spec/fixtures/invalid_id_references/repair/#{fixture_name}.svg"
24
+ end
25
+
26
+ it "applies remediation and produces expected output" do
27
+ skip "Input file not found" unless File.exist?(input_file)
28
+ skip "Expected output file not found" unless File.exist?(expected_output_file)
29
+
30
+ document = SvgConform::Document.from_file(input_file)
31
+ remediation = described_class.new(
32
+ id: "invalid_id_references_fix",
33
+ description: "Test invalid id references remediation",
34
+ )
35
+
36
+ # Apply the remediation
37
+ context = SvgConform::ValidationContext.new(document, nil)
38
+ changes = remediation.apply(document, context)
39
+
40
+ # Verify changes were made
41
+ expect(changes).to be_an(Array)
42
+ puts "Applied #{changes.count} changes in #{fixture_name}" if changes.any?
43
+
44
+ # Get the remediated XML
45
+ actual_xml = document.to_xml
46
+ expected_xml = File.read(expected_output_file)
47
+
48
+ # Use canon matcher for XML equivalence
49
+ expect(actual_xml).to be_analogous_with(expected_xml)
50
+ end
51
+
52
+ it "produces valid XML after remediation" do
53
+ skip "Input file not found" unless File.exist?(input_file)
54
+
55
+ document = SvgConform::Document.from_file(input_file)
56
+ remediation = described_class.new(
57
+ id: "invalid_id_references_fix",
58
+ description: "Test invalid id references remediation",
59
+ )
60
+
61
+ # Apply the remediation
62
+ context = SvgConform::ValidationContext.new(document, nil)
63
+ remediation.apply(document, context)
64
+
65
+ # Get the remediated XML
66
+ actual_xml = document.to_xml
67
+
68
+ # Basic XML validity check
69
+ expect(actual_xml).to include("<svg")
70
+ expect(actual_xml).to include("</svg>")
71
+ expect do
72
+ SvgConform::Document.from_content(actual_xml)
73
+ end.not_to raise_error
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "configuration" do
79
+ it "can be instantiated with basic parameters" do
80
+ remediation = described_class.new(
81
+ id: "test_invalid_id_references_fix",
82
+ description: "Test remediation",
83
+ )
84
+
85
+ expect(remediation).to be_a(described_class)
86
+ end
87
+
88
+ it "responds to apply method" do
89
+ remediation = described_class.new(
90
+ id: "test_invalid_id_references_fix",
91
+ description: "Test remediation",
92
+ )
93
+
94
+ expect(remediation).to respond_to(:apply)
95
+ end
96
+ end
97
+ end