Skip to content

Expose whole-document TextPattern formatting in get-property - #847

Merged
Nikola Metulev (nmetulev) merged 7 commits into
mainfrom
nmetulev-textpattern-formatting-properties
Sep 17, 2026
Merged

Nikola Metulev (nmetulev) merged 7 commits into
mainfrom
nmetulev-textpattern-formatting-properties

Conversation

@nmetulev

Copy link
Copy Markdown
Member

Description

Read FontWeight, FontName, FontSize, ForegroundColor, IsItalic, and StrikethroughStyle across the element's whole TextPattern document. Uniform values are invariant strings; UIA's mixed and reserved-not-supported COM tokens become Mixed and NotSupported, while elements without TextPattern return Unavailable. Provider failures retain the existing error contract.

Unknown case-sensitive property names now fail with invalid_arguments before querying the app. Omitting --property includes all six attributes. The published elementId and string-valued properties JSON envelope and existing geometry formats are unchanged.

Usage Example

winapp ui get-property Document -a myapp --property FontWeight --json
# {"elementId":"Document","properties":{"FontWeight":"700"}}
winapp ui get-property Document -a myapp --json

Related Issue

Fixes #822. Independent of #841, #842, and #844. No query predicates, explicit actions, selection/caret/range APIs, batch mode, or persistence.

Type of Change

  • New feature
  • Test update
  • Documentation

Checklist

  • New unit, CLI, and real-provider tests
  • Tested locally on Windows: 26 formatting/property library tests and 28 CLI/property/public-API tests pass
  • scripts/build-cli.ps1 -SkipTests completes NativeAOT x64/arm64 publishing, npm/NuGet/MSIX packaging, and generated docs/schema
  • Canonical UI automation docs and shipped skill/reference updated

Additional Notes

Real-app coverage reads native RichEdit uniform and mixed formatting independently of selection, a Button without TextPattern, and an HWND-based provider returning UIAutomationCore's actual reserved-not-supported token through the repository COM projection. Background fixtures assert they never activate. Unit tests cover invariant conversion, actual COM sentinel identity, unknown names, and provider-error propagation; CLI tests pin string serialization and scrubbed errors.

Pre-human-review gate is pending automated review and CI; this PR is not being merged by the implementation session.

Fixes #822

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings September 15, 2026 03:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Shared validation causes ui wait-for to emit internal_error for unknown property names instead of invalid_arguments.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds whole-document TextPattern formatting to ui get-property, including standardized mixed, unsupported, and unavailable states.

Changes:

  • Adds six text-formatting properties and strict name validation.
  • Preserves string-valued CLI/JSON contracts.
  • Adds unit, real-provider, CLI, and documentation coverage.
File summaries
File Description
src/winapp-npm/src/winapp-commands.ts Updates generated npm API description.
src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.TextAttributes.cs Reads and formats TextPattern attributes.
src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.cs Integrates attributes and validation.
src/winapp-CLI/WinApp.UIAutomation/Models/UiPropertyNames.cs Defines supported property names.
src/winapp-CLI/WinApp.UIAutomation.TestSupport/UiaTestFixture.TextAttributes.cs Adds formatted RichEdit fixtures.
src/winapp-CLI/WinApp.UIAutomation.TestSupport/UiaTestFixture.ReservedTextProvider.cs Adds a real unsupported-value provider.
src/winapp-CLI/WinApp.UIAutomation.TestSupport/UiaTestFixture.cs Supports non-activating fixtures.
src/winapp-CLI/WinApp.UIAutomation.Tests/TextAttributeTests.cs Tests formatting and failure behavior.
src/winapp-CLI/WinApp.UIAutomation.Tests/RealUiAutomationTests.TextAttributes.cs Tests real UIA providers.
src/winapp-CLI/WinApp.UIAutomation.Tests/RealUiAutomationTests.cs Updates unknown-property expectations.
src/winapp-CLI/WinApp.UIAutomation.Tests/RealUiAutomationTests.Coverage.cs Extends property coverage.
src/winapp-CLI/WinApp.Cli/Commands/UiGetPropertyCommand.cs Adds validation and updated help.
src/winapp-CLI/WinApp.Cli.Tests/UiCommandTests.TextAttributes.cs Tests CLI envelopes and errors.
src/winapp-CLI/WinApp.Cli.Tests/PublicApiSurfaceTests.cs Registers the public names API.
plugins/winapp/skills/winapp-ui-automation/SKILL.md Documents formatting usage.
plugins/winapp/skills/winapp-ui-automation/references/ui-json-envelope.md Documents JSON output.
docs/ui-automation.md Adds canonical formatting reference.
docs/npm-usage.md Updates npm documentation.
docs/cli-schema.json Regenerates command description.
Review details
  • Files reviewed: 19/19 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.cs
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The solution builds under NativeAOT and all targeted CLI and real-provider tests passed.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@github-actions

github-actions Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 48.56 MB 48.59 MB 📈 +22.2 KB (+0.04%)
CLI (x64) 48.40 MB 48.42 MB 📈 +21.2 KB (+0.04%)
MSIX (ARM64) 20.00 MB 20.03 MB 📈 +27.5 KB (+0.13%)
MSIX (x64) 21.20 MB 21.20 MB 📈 +2.7 KB (+0.01%)
NPM Package 41.63 MB 41.65 MB 📈 +21.7 KB (+0.05%)
NuGet Package 41.76 MB 41.78 MB 📈 +21.3 KB (+0.05%)

Test Results

7177 passed, 37 skipped out of 7214 tests in 1201.1s (+38 tests, -157.8s vs. baseline)

Test Coverage

85.9% line coverage, 80% branch coverage · ✅ no change vs. baseline

CLI Startup Time

69ms median (x64, winapp --version) · ✅ no change vs. baseline

Try This Build

Installs the MSIX for your architecture, replacing any previously installed build. Needs the GitHub CLI — the command offers to install it and sign you in if it is missing.

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) 847
Switching between builds often?

Put the tool on your PATH once:

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) -AddToPath

Then this build is just:

winapp-pr 847

Run winapp-pr with no arguments to pick from a list of open PRs.


Updated 2026-09-17 06:18:42 UTC · commit 9499221 · workflow run

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation satisfies the issue contract with comprehensive validation, provider coverage, and updated shipping surfaces.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@zateutsch Zach Teutsch (zateutsch) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes — one blocking item. The feature, tests, docs, and packaging surfaces look good and it builds clean; this is the only thing I'd hold the merge on.

All-properties get-property throws away everything when text-attribute enrichment fails

What is wrong: In all-properties mode (--property omitted), AddTextAttributes(comElement, …) runs unconditionally. If the live element can't be re-resolved (comElement is null) it throws InvalidOperationException; likewise any single attribute that returns an unexpected VARIANT type or an unrecognized token throws. Either exception propagates out of GetPropertiesAsync, hits the command's generic catch, and aborts the whole call — discarding the cached basic properties (Name, AutomationId, ControlType, …) that used to come back.

Show me — reproduced by running both branches against the same unresolvable element (s_getRootElement = null):

main (before) this PR
get-property (no --property) returns 7 props (Name, AutomationId, ControlType, ClassName, IsEnabled, IsOffscreen, BoundingRectangle), exit 0 throws InvalidOperationException: Element is stale → generic error, exit 1
get-property --property Name Name = cached value, exit 0 Name = cached value, exit 0

Same element, opposite outcome depending only on whether --property was named. Pre-PR the all-properties path degraded gracefully; now it hard-fails.

Why it matters: This is a regression in the command's default mode. A serialized/stale element that used to yield best-effort cached data now returns nothing with a non-zero exit — and separately, one malformed formatting value from a custom/third-party UIA provider makes an otherwise-useful inspection fail completely. There's an existing test asserting the scalar path still returns cached props on this null-element setup, so graceful degradation here appears to be an intended contract.

Smallest fix: In all-properties mode only, make text-attribute enrichment best-effort — skip it when comElement is null, and isolate per-attribute decode failures so one bad attribute is omitted rather than fatal. Keep an explicit --property <FontWeight|…> request failing loudly as it does today.

Location: src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.cs (the unconditional AddTextAttributes call in GetPropertiesAsync) and src/winapp-CLI/WinApp.UIAutomation/Services/UiAutomationService.TextAttributes.cs (AddTextAttributes null-throw and FormatTextAttribute throw-on-unexpected-type).

Retain cached basics on null live resolution, isolate malformed attribute decoding with warnings, and keep explicit requests and provider errors strict. Integrate current main without overwriting human changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@nmetulev

Copy link
Copy Markdown
Member Author

Addressed the all-properties regression in 95f6898. Before changing the implementation, three new regressions reproduced loss of cached basics on null live resolution and loss of the whole result for VT_I8/foreign-IUnknown formatting values. All-properties mode now keeps cached basics when resolution returns null and omits only an undecodable attribute, logging each omission. Explicit text-property requests still fail; provider calls and strict retained-element resolution remain outside the decode catch. Existing Mixed/NotSupported/Unavailable values remain distinct. Also updated the feature envelope regression to preserve the typed element added by merged main. Validation: 31 library/property/retained tests, 70 CLI/property/wait-for/API tests, NativeAOT/package build, and published real-provider get-all/wait-for checks pass. Please re-review; the changes-requested review has not been dismissed.

…idation

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The solution builds through NativeAOT packaging and its focused unit, real-provider, CLI, and public API tests pass.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two newly added JSON examples omit the always-emitted typed element field, and one duplicates an existing canonical section.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread docs/ui-automation.md Outdated
Comment thread plugins/winapp/skills/winapp-ui-automation/references/ui-json-envelope.md Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The solution builds, publishes under NativeAOT, passes focused tests, and works against real uniform and mixed-format providers.

Review details
  • Files reviewed: 20/20 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@nmetulev
Nikola Metulev (nmetulev) merged commit 66e9426 into main Sep 17, 2026
34 checks passed
@nmetulev
Nikola Metulev (nmetulev) deleted the nmetulev-textpattern-formatting-properties branch September 17, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Expose TextPattern formatting through ui get-property

3 participants