Skip to content

Fix five behavioural defects; two need a product decision - #145

Open
roncodes wants to merge 1 commit into
fix/group-b-quick-winsfrom
fix/group-c-behavioural
Open

Fix five behavioural defects; two need a product decision#145
roncodes wants to merge 1 commit into
fix/group-b-quick-winsfrom
fix/group-c-behavioural

Conversation

@roncodes

@roncodes roncodes commented Aug 9, 2026

Copy link
Copy Markdown
Member

Stacked on #144 (which is stacked on #143). Merge those first; the diff here is only Group C.

Group C was the "real behavioural bugs" set — seven items. Five are fixed here. Two turned out to be feature work or a product decision, so I left them alone and explain why below.

Fixed

#146 · filter/multi-option's search, both paths. Now returns its matches, which is what power-select expects.

  • Remote path called this.fetchOptions(...) — a Task object, not a function — and threw TypeError. Now .perform(), and the task returns its options so the promise resolves to the result list.
  • Local path assigned this.options from inside a modifier update: a backtracking assertion, and underneath it a worse bug — the assignment replaced the list with the filtered subset, so every keystroke permanently discarded non-matching options and clearing the query could not bring them back. Now returns the filtered array and leaves the source list alone.

The four tests deleted during the coverage work are restored, including one that types a query and then clears it to prove the full list comes back.

#150 · overlay can be resized vertically. The clamps tested width whatever the position and returned before the horizontal/vertical fork, so a @position="bottom" panel whose width fell outside [560, 900] — which a full-width drawer always does — could never be resized, and every vertical drag silently rewrote its width to the clamp. Now clamps the dimension actually being dragged, with @minResizeHeight/@maxResizeHeight alongside the width pair (defaults 0 and unbounded, so horizontal behaviour is untouched).

#120 · modal @fade={{false}} disables the transitions. @usesTransition('_fade') named a getter, but the decorator reads this.args[prop] — so this.args._fade was always undefined, undefined !== false was always true, and the flag was ignored. Now names the argument.

#148 · the validate* triplet is wired. All three query-builder panels had a validate* action that nothing called, so narrowing the selected columns left the panel sorting, grouping and filtering by columns that were no longer selected — stale state going out to the server. Now driven by {{did-update}} on the column list, matching each action's own doc comment.

#128 · attach/popover's inert isOffset removed. It was never assigned from an argument or anywhere else, so it was permanently false — and the method it guarded, isCursorBetweenTargetAndAttachment, does not exist on the component. Had anything ever set the flag, every mousemove would have thrown. Removing it takes out the landmine; no behaviour changes, because the guarded call could never run.

Not fixed — these are not repairs

#105 · model-select infinite scroll. @infiniteModel is passed this.model, a @tracked field that is declared and never assigned. But the consumer is ember-infinity's <InfinityLoader @infinityModel=…>, which needs a model produced by infinity.model(...) — not a plain array and not an ember-data RecordArray. Making this work means routing option loading through the ember-infinity service instead of this.source.query(...), which changes how every option list in the addon loads. That is a feature with real risk, not a one-line fix. Two sane options: implement it properly as its own piece of work, or drop the @infiniteScroll surface so the component stops advertising something inert.

#98 · layout/resource/panel's save path. The unambiguous half was already fixed during the coverage work (onViewDetails passed a nonexistent this.vendor; resourceType's fallback could never fire). What is left needs your call: the panel's own save task and saveButtonText are a second, redundant implementation of a save button that panel/header-actions.hbs already renders and drives from the caller's @saveTask. Wiring the panel's copy would make a Save button appear in every consumer that currently passes no save task — including read-only panels. Delete the panel's copy, or make it opt-in.

Result

4983 tests pass, 0 skips. Lints clean. The jump is larger than the other groups because fixing search and the vertical resize made whole functions reachable for the first time:

metric after #144 after this
statements 8425 / 9149 = 92.08% 8464 / 9156 = 92.44%
branches 5873 / 6704 = 87.60% 5906 / 6713 = 87.97%
functions 2175 / 2294 = 94.81% 2186 / 2294 = 95.29%
lines 8003 / 8647 = 92.55% 8039 / 8654 = 92.89%

Worth a second opinion

#148 is the one with visible consequences. Narrowing the column list now drops the sorts, groups and conditions that referenced removed columns, and reports the change. That is what the three actions were written to do and their doc comments say so — but if a user temporarily deselects a column they will lose that sort rather than have it come back. If you would rather delete the three actions than wire them, that is one revert of this commit's .hbs changes.

#150 adds two new arguments (@minResizeHeight, @maxResizeHeight). Defaults keep every existing horizontal consumer identical.

Group C of the defect triage. Each fix is pinned by tests that could not
be written before it — three of them were written during the coverage
work, failed against the production code, and had to be deleted.

- filter/multi-option: `search` now RETURNS its matches, as power-select
  expects. The remote path called `this.fetchOptions(...)`, a Task object
  rather than a function, and threw; the local path assigned
  `this.options` from inside a modifier update, which raised a
  backtracking assertion and permanently discarded every non-matching
  option, so clearing the query could not bring them back. The four tests
  deleted for this are restored, including one asserting that clearing
  the query restores the full list.
- overlay: the resize clamps tested WIDTH whatever the position and
  returned before the horizontal/vertical fork, so a top/bottom overlay
  whose width fell outside [min, max] — which a full-width drawer always
  does — could never be resized, and each vertical drag silently rewrote
  its width to the clamp. Clamps the dimension being dragged now, with
  minResizeHeight/maxResizeHeight alongside the width pair.
- modal: `@usesTransition('_fade')` named a getter, but the decorator
  reads `this.args[prop]`, so `this.args._fade` was always undefined and
  `@fade={{false}}` never disabled the transitions. Names the argument.
- query-builder sort-by / group-by / conditions: the three `validate*`
  actions existed but nothing called them, so narrowing the selected
  columns left the panel sorting, grouping and filtering by columns that
  were no longer selected. Wired to `{{did-update}}` on the column list.
- attach/popover: removed the inert `isOffset` flag. It was never
  assigned from an argument or anywhere else, and the method it guarded,
  `isCursorBetweenTargetAndAttachment`, does not exist on the component —
  so had anything ever set it, every mousemove would have thrown.

Left for a product decision, unchanged here: model-select's infinite
scroll (#105) needs the options to come from ember-infinity, which is
feature work, not a repair; layout/resource/panel's redundant save path
(#98) duplicates a button panel/header-actions already renders.

4983 tests pass, 0 skips. Coverage 92.44% statements / 87.97% branches /
95.29% functions / 92.89% lines.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant