Repository navigation
Code coverage
| 10.0.236 (before) | 10.0.283 | |
|---|---|---|
| Line coverage | 19.3% (3,655 / 18,929) | 97.1% (18,596 / 19,149) |
| Branch coverage | 12.7% | 89.5% |
| Tests | 497 | 3,592 |
| Components at 100% line coverage | 61 of 113 | |
| Components at 95% or more | 106 of 113 | |
| Components at 90% or more | 111 of 113 | |
| Code units at 100% (components, models, services, extensions) | 212 of 272 |
Measured on the release commit cfc3f9fe with Microsoft.Testing.Extensions.CodeCoverage (cobertura), for the PanoramicData.Blazor assembly only. The suite passes on Windows and on Linux (Ubuntu, TZ=Etc/UTC), with 0 build warnings.
The two components below 90% are PDFormFieldEditor (76%: its Monaco editor paths only run with a live BlazorMonaco editor model) and PDDateTime (85%: the remaining lines are catch blocks around TryParseExact, which cannot throw). Elsewhere, uncovered lines are mostly catch blocks around JS interop teardown and guards the UI makes unreachable.
What changed
- bUnit tests for every component (#154, PR #196), written to test behaviour and to pass reliably under load: every bUnit event is awaited, and timer-driven waits have explicit timeouts.
- Fixes for the defects those tests found, one PR per component group (#205, #207 to #210, #212 to #215, #217, #220), plus the refresh-selection work released in 10.0.236 (#151, #152). Each fix has a regression test that failed before it.
Compatibility
No breaking changes. No public or protected member was removed or had its signature changed (checked against 10.0.239 from the generated XML documentation). Public additions are optional: PDDropDown.ExceptionHandler, FileExplorerPreviewProvider's HttpClient constructor and property, PDCardDeckLoadingIcon.Clock, IAsyncDisposable on PDCardDeck and PDResizePane, and a protected PDComponentBase.HasDefaultId.
Where a correct fix would have changed what existing pages show, it was made opt-in or compatible, and each PR's "Compatibility" section lists what a consumer sees. The ones most worth knowing:
- PDColorPicker:
ColorPickerOptions.DefaultModeis honoured only when set explicitly; pickers that do not set it still open in RGB. - PDMixingDesk:
MinHeightis applied only when set explicitly; existing desks keep their height. - PDToggleSwitch: the width no longer jumps backwards around the text-width threshold; a switch with very short text can be a few pixels narrower.
- PDForm.GetField returns null for an unknown name, as its documentation always said, instead of throwing.
- PDDropDown and PDContextMenu now log (and, for PDDropDown, pass to
ExceptionHandler) errors they used to swallow; nothing new propagates. - PDTable: an empty
SortCriteriakey no longer silently sorts by the first empty-titled column (#211); a survey of Magic Suite's 129 tables found none whose order changes. - Date filters in
DataProviderBaseno longer shift by the server's UTC offset (#193), and US dates without a time zone now parse (#197).
Issues closed (56)
- #151 PDTable: RefreshAsync clears the selection and raises SelectionChanged on every refresh
- #152 PDTree: RefreshAsync collapses the selected path, re-raises SelectionChange, and does nothing when nothing is selected
- #154 bUnit tests for every component, aiming for full coverage
- #155 PDTiles: empty Logos throws, culture-dependent connector points, Tiles changes ignored, #FFF colour throws
- #156 PDGlobalListener: DotNetObjectReference is never disposed
- #157 PDStackedBar: tooltip throws IndexOutOfRangeException when there are more series than values
- #158 PDSection: Id parameter overwritten, aria-expanded wrong, Collapse/Expand/Toggle do not re-render
- #159 PDComponentBase: generated Ids race on the static Sequence (PDGraphViewer, PDGraphControls, PDGraphInfo)
- #160 PDGraphControls: mutates the caller's AvailableDimensions list
- #161 PDTimeline: SetSelection moves an early start to the end, PanTo(Start) ignores the date, disabled timeline still pans
- #162 TimelineScale.IsMajorTick: Seconds and Milliseconds rules look swapped
- #163 PDResizePane: resizing appears to do nothing (JS module never imported)
- #164 PDMixingDesk ignores CssClass and MinHeight
- #165 PDToolbarLinkButton ignores TextCssClass
- #166 PDAudioPad: Linear decay never reports its final inactive event when throttled
- #167 PDFormFieldEditor: a nullable numeric field cannot be cleared or set to null
- #168 PDDashboard: dragging tiles does nothing when edit mode comes from the built-in edit button
- #169 PDDateTime: custom DateFormat is displayed in the current culture but parsed in the invariant culture
- #170 ShortcutKey.IsMatch: a shortcut with an empty Code matches any key event with an empty Code
- #171 ReflectionExtensions.GetPropertyMemberInfo throws for non-member selectors, so a computed PDColumn Field crashes
- #172 PDColumnConfig.Title never reaches the column header
- #173 PDZoomBar: zooming out from a value that is not a step jumps to the smallest step
- #174 PDFileExplorer: PreviewProvider ignored, table drops ignore CanAddItems, case-only tree rename refused, preview details and downloads wrong
- #175 PDCardDeck: a standalone deck (outside a group) never shows its cards
- #176 PDStudio: status stays "Cancelling..." after a cancel completes
- #177 PDColorPicker: ColorPickerOptions.DefaultMode is ignored
- #178 PDSplitter: GutterAlign is not passed to split.js
- #179 PDRange: handles and ticks are drawn in the wrong place when Min is not 0
- #180 PDToolbarDropdown: disabled menu items still fire their click
- #181 PDList: a saved selection restores only its first item when there is no ItemKeyFunction
- #182 PDForm: GetField throws for an unknown name instead of returning null
- #183 PDTree: expanding a node from code does not re-render
- #184 PDDropZone: CancelAsync, ClearAsync and dispose pass the bare Id, so the JS finds nothing
- #185 PDFormMessage: a labelled scale reports the label instead of the chosen number
- #186 PDContextMenu: first right-click opens no menu; missing popper.js error is swallowed
- #187 PDGraph: an async data provider crashes the component; spinner never stops without a provider
- #188 PDToggleSwitch: CalculatedWidth jumps backwards around the text-width threshold
- #189 PDQuestVisualizer: cyclic prerequisites overflow the stack
- #190 PDChat: adding a canvas tab throws; typing indicator marks unread; background tab unread marker lags
- #191 PDFileModal: ShowOpenAsync(folderSelect: true) still lists files when already at the root
- #192 PDTagInput: a null Values from the parent does not clear the tags
- #193 DataProviderBase: date filters shift by the machine's UTC offset
- #194 DefaultDescriptionProvider: Math.Truncate never gets its description (stray bracket in key)
- #195 PDCardDeckLoadingIcon: disposed during its start-up delay, it starts a timer loop that never stops
- #197 Filter: US dates without a time zone never parse (MM/yy/yyyy typo); year, month and hour precision can never be detected
- #198 PDDropDown: exceptions thrown by the consumer's DropDownShown, DropDownHidden and KeyPress callbacks are silently swallowed
- #199 ReflectionExtensions.GetFriendlyTypeName: arrays are not given friendly names; unreachable generic arm
- #200 Dead code found by the coverage work
- #201 PDDateTimeOffset: on Linux with Etc/UTC the time-zone dropdown selects nothing, so it shows the wrong zone
- #202 PDTextArea with DebounceWait wipes the user's typing when the parent re-renders before the debounce fires
- #204 Demo site: the PDCardDeck page never finishes loading (all four examples stuck on Loading Data...)
- #206 PDTimeline JS: four event listeners leak on every dispose, disposed timelines stay in the map, setData calls a missing method
- #211 PDTable: the default empty SortCriteria key matches any column with an empty title, so the table silently sorts by it
- #216 PDCardDeck JS: document-level drop/drag/mouse listeners are never removed, so disposed decks keep handling every drop
- #218 PDChatConversationSidebar: a superseded search whose debounce already elapsed still clears the list and queries the store
- #219 PDAudioPad: a decay superseded by a new press can reset the value to the minimum and report inactive while the new decay runs
Line coverage by component (before, after)
| Component | Lines | 10.0.236 | 10.0.283 |
|---|---|---|---|
| PDAnimation | 58 | 0% | 100% |
| PDAudioButton | 12 | 0% | 91.7% |
| PDAudioChannel | 48 | 0% | 100% |
| PDAudioControl | 78 | 0% | 98.7% |
| PDAudioPad | 106 | 0% | 99.1% |
| PDBlockOverlay | 20 | 0% | 100% |
| PDBusyOverlay | 6 | 0% | 100% |
| PDButton | 64 | 0% | 100% |
| PDCanvas | 4 | 0% | 100% |
| PDCard | 49 | 0% | 100% |
| PDCardDeck | 201 | 0% | 95.5% |
| PDCardDeckGroup | 105 | 0% | 92.4% |
| PDCardDeckLoadingIcon | 31 | 0% | 96.8% |
| PDChat | 606 | 21.1% | 95.9% |
| PDChatContainer | 16 | 0% | 100% |
| PDChatConversationSidebar | 96 | 64.5% | 99% |
| PDCheckboxTree | 29 | 0% | 100% |
| PDClickableImage | 7 | 0% | 100% |
| PDClipboard | 19 | 0% | 100% |
| PDColorPicker | 276 | 43.4% | 97.5% |
| PDColumn | 159 | 40.3% | 100% |
| PDColumnConfig | 1 | 0% | 100% |
| PDColumnGroup | 9 | 0% | 100% |
| PDColumnGrouper | 40 | 0% | 100% |
| PDComboBox | 184 | 0% | 98.4% |
| PDComponentBase | 44 | 0% | 95.5% |
| PDConfirm | 68 | 0% | 95.6% |
| PDContextMenu | 60 | 0% | 95% |
| PDDashboard | 452 | 0% | 98.2% |
| PDDateTime | 41 | 0% | 85.4% |
| PDDateTimeOffset | 136 | 0% | 92.6% |
| PDDragContainer | 7 | 0% | 100% |
| PDDragContext | 1 | 0% | 100% |
| PDDragDropSeparator | 8 | 0% | 100% |
| PDDragPanel | 44 | 0% | 100% |
| PDDropDown | 119 | 0% | 96.6% |
| PDDropZone | 132 | 0% | 97% |
| PDFader | 41 | 0% | 100% |
| PDField | 29 | 0% | 100% |
| PDFileExplorer | 1060 | 0% | 98.3% |
| PDFileModal | 193 | 0% | 96.4% |
| PDFilePreview | 23 | 0% | 100% |
| PDFilter | 186 | 0% | 97.8% |
| PDFlag | 2 | 0% | 100% |
| PDForm | 335 | 0% | 95.2% |
| PDFormBody | 159 | 0% | 97.5% |
| PDFormCheckBox | 15 | 0% | 100% |
| PDFormFieldEditor | 221 | 0% | 76% |
| PDFormFooter | 77 | 0% | 100% |
| PDFormHeader | 32 | 0% | 100% |
| PDFormMessage | 242 | 0% | 98.3% |
| PDGlobalListener | 33 | 0% | 100% |
| PDGraph | 389 | 0% | 98.5% |
| PDGraphControls | 46 | 0% | 100% |
| PDGraphInfo | 60 | 0% | 100% |
| PDGraphSelectionInfo | 29 | 0% | 100% |
| PDGraphViewer | 87 | 0% | 100% |
| PDImage | 7 | 0% | 100% |
| PDKnob | 104 | 0% | 100% |
| PDLabel | 32 | 0% | 100% |
| PDLinkButton | 56 | 0% | 96.4% |
| PDList | 177 | 0% | 97.7% |
| PDLocalStorageStateManager | 39 | 0% | 100% |
| PDLog | 88 | 0% | 97.7% |
| PDMenuItem | 7 | 0% | 100% |
| PDMessage | 329 | 0% | 100% |
| PDMessages | 78 | 69.2% | 97.4% |
| PDMixingDesk | 7 | 0% | 100% |
| PDModal | 128 | 0% | 100% |
| PDModalBase | 15 | 0% | 100% |
| PDMonacoEditor | 116 | 0% | 98.3% |
| PDNavLink | 69 | 0% | 97.1% |
| PDPager | 43 | 0% | 100% |
| PDProgressBar | 7 | 0% | 100% |
| PDQuestVisualizer | 67 | 0% | 100% |
| PDRange | 122 | 0% | 95.9% |
| PDResizePane | 31 | 0% | 100% |
| PDSection | 79 | 0% | 100% |
| PDSplitPanel | 7 | 0% | 100% |
| PDSplitter | 57 | 0% | 100% |
| PDStackedBar | 36 | 0% | 100% |
| PDStatusCascade | 82 | 0% | 98.8% |
| PDStatusRollUp | 100 | 56% | 96% |
| PDStudio | 335 | 0% | 98.5% |
| PDStudioResults | 131 | 0% | 96.9% |
| PDTab | 23 | 94.1% | 100% |
| PDTable | 1530 | 72% | 99.2% |
| PDTableColumnSelector | 48 | 0% | 100% |
| PDTabSet | 120 | 31.9% | 100% |
| PDTagInput | 156 | 0% | 98.7% |
| PDTextArea | 98 | 0% | 98% |
| PDTextBox | 92 | 0% | 97.8% |
| PDTiles | 1367 | 0% | 99.8% |
| PDTilesJavaScript | 142 | 0% | 95.1% |
| PDTimeline | 676 | 2.7% | 98.1% |
| PDTimelineToolbar | 39 | 0% | 97.4% |
| PDToggleSwitch | 106 | 0% | 94.3% |
| PDToolbar | 12 | 0% | 100% |
| PDToolbarButton | 28 | 0% | 100% |
| PDToolbarDropdown | 70 | 0% | 100% |
| PDToolbarLinkButton | 26 | 0% | 100% |
| PDToolbarPlaceholder | 4 | 0% | 100% |
| PDToolbarSeparator | 15 | 0% | 100% |
| PDToolbarTextbox | 33 | 0% | 100% |
| PDTree | 353 | 54.9% | 98% |
| PDTreeMap | 249 | 0% | 93.2% |
| PDTreeNode | 68 | 35.3% | 95.6% |
| PDValidationSummary | 4 | 0% | 100% |
| PDVoiceListener | 90 | 0% | 96.7% |
| PDWidget | 277 | 0% | 99.3% |
| PDWizard | 127 | 0% | 98.4% |
| PDWizardStep | 7 | 0% | 100% |
| PDZoomBar | 51 | 0% | 100% |