-
Notifications
You must be signed in to change notification settings - Fork 0
Fix image alt text and word css contracts #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
HassanAkbar
wants to merge
4
commits into
main
Choose a base branch
from
fix/todo-02-spec-doubles
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
cc3da62
fix image alt text and word css contracts
HassanAkbar 6bfa6c7
strip alt text so length checks ignore padding
HassanAkbar 6749c7f
describe todo work as numbered items not prs
HassanAkbar b7382f1
Converge remaining ST_OnOff sites and extract yaml writer
HassanAkbar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,45 +1,162 @@ | ||
| # 18 — Reduce spec doubles (69 sites) | ||
| # 18 — Reduce spec doubles | ||
|
|
||
| **Priority:** Medium (spec quality) | ||
| **Files:** Multiple spec files, worst offenders: | ||
| - `spec/uniword/accessibility/rules/image_alt_text_rule_spec.rb` (~20) | ||
| - `spec/uniword/accessibility/rules_integration_spec.rb` (~10) | ||
| - `spec/uniword/accessibility/accessibility_checker_spec.rb` (~7) | ||
| - `spec/uniword/math_equation_spec.rb` (~6) | ||
| **Status:** PRs 1-3 done. PR 4 outstanding. Count went 59 → 30 (29 | ||
| addressed). Both contract defects are fixed: `ImageAltTextRule` now reads | ||
| `wp:docPr/@descr`, and `WordCss` now speaks `Wordprocessingml::Style`'s | ||
| real API (`id`, `font_family`, `alignment.value`, plus a new `Style#italic`). | ||
|
|
||
| ## Problem | ||
| What remains, by file: | ||
|
|
||
| | file | sites | why | | ||
| | --- | --- | --- | | ||
| | `spec/uniword/math_equation_spec.rb` | 10 (7 `double`, 3 `class_double`) | Plurimath — out of scope | | ||
| | `spec/uniword/math/plurimath_adapter_spec.rb` | 7 | Plurimath — out of scope | | ||
| | `spec/uniword/accessibility/rules_integration_spec.rb` | 5 | table/heading rules — PR 4 | | ||
| | `spec/uniword/accessibility/accessibility_checker_spec.rb` | 2 (1 `double`, 1 `instance_double`) | PR 4 | | ||
| | 6 single-site files | 6 | PR 4, fold in opportunistically | | ||
|
|
||
| **Priority:** Medium (spec quality), but PR 1 and PR 2 are correctness | ||
| **Files:** see PR breakdown below | ||
|
|
||
| ## Status of the original note | ||
|
|
||
| Project rule: never use `double()` in specs. Use real model instances or | ||
| `Struct.new(...).new(...)` for plain data. | ||
| Stale. It claimed 69 sites. Actual today, counting all RSpec double | ||
| constructs: **59** — 55 plain `double(...)`, 3 `class_double`, 1 | ||
| `instance_double`. Its named worst offenders are no longer the worst. | ||
| Distribution of plain doubles: | ||
|
|
||
| 69 `double()` callsites across spec/. Worst offenders use doubles to | ||
| mock out complex model behavior, which means the tests verify that | ||
| methods are called rather than that the actual behavior is correct. | ||
| | file | sites | | ||
| | --- | --- | | ||
| | `spec/uniword/mhtml/word_css_spec.rb` | 14 | | ||
| | `spec/uniword/accessibility/rules/image_alt_text_rule_spec.rb` | 12 | | ||
| | `spec/uniword/math_equation_spec.rb` | 7 | | ||
| | `spec/uniword/math/plurimath_adapter_spec.rb` | 7 | | ||
| | `spec/uniword/accessibility/rules_integration_spec.rb` | 7 | | ||
| | `spec/uniword/accessibility/accessibility_checker_spec.rb` | 2 (+1 `instance_double`) | | ||
| | 6 other files | 1 each | | ||
|
|
||
| ## Fix | ||
| The original fix section also said to use `Struct` for data-only | ||
| doubles. `CLAUDE.md` says never use `Struct` or `OpenStruct`. Follow | ||
| CLAUDE.md; this note predates the rule. Two `Struct.new` sites already | ||
| exist in `spec/` — either violations to clean up or a rule needing a | ||
| written exception. Do not add a third. | ||
|
|
||
| For each spec: | ||
| 1. Identify what the double is mocking | ||
| 2. Replace with a real model instance constructed with the required | ||
| attributes | ||
| 3. If the model is hard to set up, build a small test factory | ||
| 4. Verify the test still asserts the same observable behavior | ||
| ## Problem | ||
|
|
||
| The doubles are not lazy tests. Two of them are hiding broken production | ||
| code, and that has to be fixed before the cleanup can even run. | ||
|
|
||
| For data-only doubles (no behavior), use `Struct`: | ||
| ```ruby | ||
| # Before | ||
| let(:doc) { double("Doc", paragraphs: [...]) } | ||
| ### `ImageAltTextRule` crashes on any real document with an image | ||
|
|
||
| # After | ||
| DocumentStub = Struct.new(:paragraphs) | ||
| let(:doc) { DocumentStub.new([...]) } | ||
| ``` | ||
| document.images => [Uniword::Wordprocessingml::Drawing] | ||
| Drawing responds to alt_text? => false | ||
| rule.check(doc) => NoMethodError: | ||
| undefined method 'alt_text' for | ||
| an instance of Wordprocessingml::Drawing | ||
| ``` | ||
|
|
||
| `DocumentRoot#images` (`document_root.rb:299`) is documented | ||
| `@return [Array<Drawing>]`. `ImageAltTextRule#check` calls | ||
| `image.alt_text` (`image_alt_text_rule.rb:21`). `alt_text` exists only on | ||
| `Uniword::Image` (`image.rb:28`), a different flat model that `#images` | ||
| never returns. The 12 doubles inject `alt_text` and paper over the crash. | ||
|
|
||
| ### `WordCss` expects an API the real objects do not have | ||
|
|
||
| The doubles invent `style_id`, `font` and `italic`. Real | ||
| `Wordprocessingml::Style` exposes `id` (`style.rb:130`) and | ||
| `font_family` (`style.rb:200`), and has no `italic` reader. | ||
| `Mhtml::StylesConfiguration#styles` is declared | ||
| `attribute :styles, :hash` (`styles_configuration.rb:15`), not an | ||
| enumerable of style objects. | ||
|
|
||
| So "replace the double with a real instance" cannot be done for these | ||
| two without fixing production first. | ||
|
|
||
| ## PR 1 — repair the accessibility contract (prerequisite) | ||
|
|
||
| Decide what `ImageAltTextRule` operates on. Most likely real OOXML | ||
| drawings, reading the description off `wp:docPr/@descr`, not a phantom | ||
| `alt_text` on `Drawing`. Then replace the 12 doubles in | ||
| `image_alt_text_rule_spec.rb` and the dependent doubles in | ||
| `rules_integration_spec.rb` and `accessibility_checker_spec.rb`. | ||
|
|
||
| Regression test must be a parsed document containing a real drawing, and | ||
| must fail before the fix. | ||
|
|
||
| ## PR 2 — repair the WordCss contract (prerequisite) | ||
|
|
||
| For doubles that mock method calls, refactor the test to assert on | ||
| observable output (return values, side effects) rather than on | ||
| method-call counts. | ||
| Decide whether `WordCss` consumes WordprocessingML styles or MHTML style | ||
| hashes, then make the code and the type agree. Replace the 7 style-side | ||
| doubles (5 `Style`, 2 `StylesConfiguration`). | ||
|
|
||
| The namespace is **not** ambiguous, despite two classes sharing the name: | ||
| `word_css.rb:36` does `styles_config.styles.map` and then calls style-object | ||
| methods, while `Mhtml::StylesConfiguration#styles` is a plain `:hash` of CSS | ||
| properties. So `WordCss` consumes the **WordprocessingML** configuration. State | ||
| that as the contract. | ||
|
|
||
| The real work is adapting `WordCss` to `Wordprocessingml::Style`'s actual API: | ||
| it exposes `id` (`style.rb:130`) and `font_family` (`style.rb:200`), has a | ||
| wrapper-backed `alignment`, and has no `italic` reader at all — whereas the | ||
| doubles invent `style_id`, `font` and `italic`. | ||
|
|
||
| ## PR 3 — WordCss numbering doubles | ||
|
|
||
| The other 7 doubles in that file are 5 `NumberingInstance` and 2 | ||
| `NumberingConfiguration`. | ||
|
|
||
| **This is independent of PR 2 and can ship on its own.** `word_css.rb:50` calls | ||
| `numbering_config.instances`, and only `Wordprocessingml::NumberingConfiguration` | ||
| declares `instances` (`numbering_configuration.rb:16`); the MHTML one does not. | ||
| So the namespace is settled by the call itself, and a real | ||
| `NumberingConfiguration` plus `NumberingInstance` drops straight in. | ||
|
|
||
| Two earlier revisions got this wrong in both directions — first calling it | ||
| unblocked without checking, then calling it blocked on a namespace ambiguity | ||
| that does not exist. The call site resolves it. | ||
|
|
||
| ## PR 4 — the remainder | ||
|
|
||
| Whatever is left after PRs 1-3, largest file first, one file per PR. | ||
| For each double: name the real class, construct it the way production | ||
| does, keep the assertion on observable behavior rather than call counts. | ||
|
|
||
| If a model turns out to be awkward to construct, that awkwardness is a | ||
| finding about the model's API. Record it. Do not paper over it with | ||
| another double. | ||
|
|
||
| ## Verification | ||
|
|
||
| `grep -rn "double(" spec/uniword/ | wc -l` should trend toward 0. | ||
| Tests pass. | ||
| - Per file: `bundle exec rspec <file>` green **and proven able to fail**. | ||
| Break the behavior under test once and watch it go red. Given what PRs | ||
| 1 and 2 uncovered, a green double-free spec that cannot fail is the | ||
| main risk here. | ||
| - The count drops from 59 by the number actually addressed. Count all three | ||
| constructs (`double`, `class_double`, `instance_double`), not just plain | ||
| `double(` — an earlier revision of this note undercounted by missing | ||
| `class_double`. **Do not state a target of zero.** List what remains | ||
| explicitly. | ||
| - `bundle exec rubocop <touched files>` | ||
|
|
||
| ## Out of scope | ||
|
|
||
| - `plurimath_adapter_spec.rb` and the Plurimath parts of | ||
| `math_equation_spec.rb` (14 sites). These stand in for an external | ||
| gem, so replacing them is a dependency-contract question, not spec | ||
| hygiene. Needs `/dependency-contract-check` against Plurimath first. | ||
| Should become its own TODO. | ||
| - The 6 single-site files. Fold in only if the file is already open for | ||
| another reason. | ||
|
|
||
| ## Expected outcome, stated honestly | ||
|
|
||
| This will not reduce the count much on its own. Its real output is the two | ||
| contract defects in PRs 1 and 2. | ||
|
|
||
| Severity differs between them. `ImageAltTextRule` is reachable and crashes on a | ||
| real document. `WordCss.generate_style_css` / `generate_list_css` have **no | ||
| caller under `lib/`** — only their specs call them — so they are broken public | ||
| helpers rather than a demonstrated downstream failure. Fix both, but do not | ||
| describe WordCss as a live production bug. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.