fix(ai-context): load custom properties into rule builder filter - #31635
Conversation
…add Service Is regression test The "Custom Properties" field in the AI Context Rule Builder showed an empty "Select field" dropdown because RuleQueryBuilderField never fetched custom properties — only AdvanceSearchProvider did. Fix: fetch getAllCustomProperties() on mount (keyed to entityType), build enriched fields with extension.subfields populated, and pass them to QueryBuilderWidgetV1 via the fields prop. Also adds a Playwright regression test for the fully-completed "Service Is" condition (async-dropdown path) that the existing "Description Contains" test cannot cover, and wires a DatabaseServiceClass fixture for it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
❌ PR checklist incompleteThis PR cannot be merged until the following are addressed on its linked issue:
The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically. Maintainers can bypass this check by adding the |
|
Hi there 👋 Thanks for your contribution! The OpenMetadata team will review the PR shortly! Once it has been labeled as Let us know if you need any help! |
…o PersonaAIContext.spec.ts The two new regression tests belong in the existing PersonaAIContext.spec.ts alongside the other rule-builder tests rather than as additions to PersonaAIContextRules.spec.ts. Removes the DatabaseServiceClass fixture and Service Is test from PersonaAIContextRules.spec.ts (restoring it to the merged state) and adds both tests to PersonaAIContext.spec.ts where the dbService fixture is shared with the full suite. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers 9 previously untested scenarios in PersonaAIContext.spec.ts: - Sections checkbox toggle → payload omits unchecked section - Rule description persisted in POST payload - View in Explore href updates when entity type changes - Preview modal closes via the Close button - STALE cache state badge on settings card - FAILED cache state badge + lastError text - Edit drawer Escape discards unsaved changes - Rule card displays matched asset count from server - Compound OR conditions serialized into queryFilter payload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract PROBE_RULE const — eliminates inline rule object duplication
across cache-state tests, edit-discard test, and matched-count test
- Add overrideAiContextGet helper — replaces 40-line copy-paste in the
stale and failed cache-state tests with a 3-line call each
- Scope all query-builder locators to getByRole('dialog') in the
compound OR test so they never match elements outside the drawer
- Add explicit wait for second condition row (toHaveCount(2)) before
interacting with it in the compound OR test
- Add post-save card assertion to sections, description, and compound OR
tests so each test has a complete pass/fail postcondition
- Fix View in Explore assertion: /\/explore\// → /\/explore\/glossaries/
(SearchClassBase maps GLOSSARY_TERM → ExplorePageTabs.GLOSSARY = 'glossaries')
- Improve matchedCount assertion: '57' → /57.*matched/ to avoid
incidental matches on other '57' text on the page
- Use test.step() in the compound OR test for clearer Playwright reports
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RuleQueryBuilderField.component.tsx: - Fetch getAllCustomProperties() once on mount instead of on every entityType change. The API returns all entity types' properties regardless of selection; only processEntityTypeFields is entity-type- specific. Split into two effects: the first (dep: []) fetches and caches the map in state; the second (dep: [entityType, customProps]) processes it without a network request on each type switch. - Fix no-internal-barrel-imports lint warning: replace the barrel import of DrawerPopupContainerProvider with the direct component file path. - Remove the now-unnecessary useRef/cancelRef because the fetch runs once and there is no longer a stale-update race to guard against. PersonaAIContext.spec.ts: - Guard the Service Is value dropdown against Elasticsearch indexing latency: poll the search API (expect.poll, 30 s timeout) before calling selectOption so the test does not time out with "No data" if the newly created dbService has not yet been indexed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
✅ Playwright Results — workflow succeededValidated commit ✅ 120 passed · ❌ 0 failed · 🟡 0 flaky · ⏭️ 0 skipped · 🧰 0 lifecycle flaky PerformanceBlocking targets: ✅ met · Optimization targets: 🟡 in progress Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting. 🕒 Full workflow signal wall (to summary) 53m 40s ⏱️ Max setup 1m 52s · max shard execution 9m 27s · max shard-job elapsed before upload 14m 14s · reporting 2s 🌐 147.86 requests/attempt · 1.57 app boots/UI scenario · 0.00% common-shard skew Optimization targets still in progress:
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
…ependency The value dropdown for "Service Is" calls /api/v1/search/aggregate with field=service — it aggregates over TABLE documents, not service entities. Because dbService has no tables, its name never appears in the aggregation no matter how long we poll, making the test time out in CI. Replace the ES poll with a direct route mock that returns the service name immediately via the sterms#service bucket, keeping the test fast and deterministic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…keyword EntityFields.SERVICE = 'service.displayName.keyword', so the mock aggregation bucket must use 'sterms#service.displayName.keyword' as the key, not 'sterms#service'. The mismatch caused parseBucketsData to read undefined.buckets, returning no options and leaving the dropdown empty. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…yName.keyword The route condition compared field === 'service' but the actual query param sent by getAggregateFieldOptions is field=service.displayName.keyword (EntityFields.SERVICE). The mismatch caused route.fallback() to run, hitting the real server which returned no buckets (service has no indexed tables), so the dropdown showed "Not found". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ng conjunction Clicking the RAQB 'Or' conjunction button before the second rule exists causes it to prepend a nested OR group rather than just toggling the conjunction. This means .last() targets the original rule_alpha (not a new slot) and overwrites 'alpha' with 'beta', leaving only 'beta' in the serialized query. Fix: add both conditions with the custom add-context-condition button (addRule([]) to the root group) first, then switch the conjunction to OR — which only changes the group operator without any structural change, keeping both alpha and beta in the payload. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…es before conjunction change
- Move toHaveCount(2) assertion to step 1 (after the first addRule — 2 delete
buttons: owners inner rule + new rule)
- Change step 2 toHaveCount assertion to 3 (owners inner + alpha rule + beta rule)
- Press Tab after fill('alpha') and fill('beta') to blur and commit values to
the RAQB immutable tree before the conjunction change fires
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Code Review ✅ Approved 2 resolved / 2 findingsLoads custom properties into the AI Context rule builder and expands Playwright regression test coverage. No issues found. ✅ 2 resolved✅ Performance: Custom properties re-fetched on every entityType change
✅ Quality: Service Is test may be flaky due to ES indexing latency
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source |
) * fix(ai-context): load custom properties into rule builder filter and add Service Is regression test The "Custom Properties" field in the AI Context Rule Builder showed an empty "Select field" dropdown because RuleQueryBuilderField never fetched custom properties — only AdvanceSearchProvider did. Fix: fetch getAllCustomProperties() on mount (keyed to entityType), build enriched fields with extension.subfields populated, and pass them to QueryBuilderWidgetV1 via the fields prop. Also adds a Playwright regression test for the fully-completed "Service Is" condition (async-dropdown path) that the existing "Description Contains" test cannot cover, and wires a DatabaseServiceClass fixture for it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(playwright): move Custom Properties and Service Is tests into PersonaAIContext.spec.ts The two new regression tests belong in the existing PersonaAIContext.spec.ts alongside the other rule-builder tests rather than as additions to PersonaAIContextRules.spec.ts. Removes the DatabaseServiceClass fixture and Service Is test from PersonaAIContextRules.spec.ts (restoring it to the merged state) and adds both tests to PersonaAIContext.spec.ts where the dbService fixture is shared with the full suite. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(playwright): add comprehensive coverage for Persona AI Context Covers 9 previously untested scenarios in PersonaAIContext.spec.ts: - Sections checkbox toggle → payload omits unchecked section - Rule description persisted in POST payload - View in Explore href updates when entity type changes - Preview modal closes via the Close button - STALE cache state badge on settings card - FAILED cache state badge + lastError text - Edit drawer Escape discards unsaved changes - Rule card displays matched asset count from server - Compound OR conditions serialized into queryFilter payload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor(playwright): improve Persona AI Context test quality - Extract PROBE_RULE const — eliminates inline rule object duplication across cache-state tests, edit-discard test, and matched-count test - Add overrideAiContextGet helper — replaces 40-line copy-paste in the stale and failed cache-state tests with a 3-line call each - Scope all query-builder locators to getByRole('dialog') in the compound OR test so they never match elements outside the drawer - Add explicit wait for second condition row (toHaveCount(2)) before interacting with it in the compound OR test - Add post-save card assertion to sections, description, and compound OR tests so each test has a complete pass/fail postcondition - Fix View in Explore assertion: /\/explore\// → /\/explore\/glossaries/ (SearchClassBase maps GLOSSARY_TERM → ExplorePageTabs.GLOSSARY = 'glossaries') - Improve matchedCount assertion: '57' → /57.*matched/ to avoid incidental matches on other '57' text on the page - Use test.step() in the compound OR test for clearer Playwright reports Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(ai-context): address PR review findings RuleQueryBuilderField.component.tsx: - Fetch getAllCustomProperties() once on mount instead of on every entityType change. The API returns all entity types' properties regardless of selection; only processEntityTypeFields is entity-type- specific. Split into two effects: the first (dep: []) fetches and caches the map in state; the second (dep: [entityType, customProps]) processes it without a network request on each type switch. - Fix no-internal-barrel-imports lint warning: replace the barrel import of DrawerPopupContainerProvider with the direct component file path. - Remove the now-unnecessary useRef/cancelRef because the fetch runs once and there is no longer a stale-update race to guard against. PersonaAIContext.spec.ts: - Guard the Service Is value dropdown against Elasticsearch indexing latency: poll the search API (expect.poll, 30 s timeout) before calling selectOption so the test does not time out with "No data" if the newly created dbService has not yet been indexed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(playwright): mock aggregate API in Service Is test to remove ES dependency The value dropdown for "Service Is" calls /api/v1/search/aggregate with field=service — it aggregates over TABLE documents, not service entities. Because dbService has no tables, its name never appears in the aggregation no matter how long we poll, making the test time out in CI. Replace the ES poll with a direct route mock that returns the service name immediately via the sterms#service bucket, keeping the test fast and deterministic. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(playwright): correct aggregate key to sterms#service.displayName.keyword EntityFields.SERVICE = 'service.displayName.keyword', so the mock aggregation bucket must use 'sterms#service.displayName.keyword' as the key, not 'sterms#service'. The mismatch caused parseBucketsData to read undefined.buckets, returning no options and leaving the dropdown empty. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(playwright): fix aggregate field param check — use service.displayName.keyword The route condition compared field === 'service' but the actual query param sent by getAggregateFieldOptions is field=service.displayName.keyword (EntityFields.SERVICE). The mismatch caused route.fallback() to run, hitting the real server which returned no buckets (service has no indexed tables), so the dropdown showed "Not found". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(playwright): fix compound OR test — add both rules before switching conjunction Clicking the RAQB 'Or' conjunction button before the second rule exists causes it to prepend a nested OR group rather than just toggling the conjunction. This means .last() targets the original rule_alpha (not a new slot) and overwrites 'alpha' with 'beta', leaving only 'beta' in the serialized query. Fix: add both conditions with the custom add-context-condition button (addRule([]) to the root group) first, then switch the conjunction to OR — which only changes the group operator without any structural change, keeping both alpha and beta in the payload. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix lint checks * fix(playwright): fix compound OR test count assertion and commit values before conjunction change - Move toHaveCount(2) assertion to step 1 (after the first addRule — 2 delete buttons: owners inner rule + new rule) - Change step 2 toHaveCount assertion to 3 (owners inner + alpha rule + beta rule) - Press Tab after fill('alpha') and fill('beta') to blur and commit values to the RAQB immutable tree before the conjunction change fires Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix lint checks --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> (cherry picked from commit 84197a5)



Summary
RuleQueryBuilderFieldpassed the raw base config (which hasextension.subfields = {}) toQueryBuilderWidgetV1without ever fetching custom properties.AdvanceSearchProviderdoes this fetch but its logic was never wired into the rule builderuseEffectinRuleQueryBuilderFieldthat callsgetAllCustomProperties()on mount (re-runs whenentityTypechanges), builds enriched fields withextension.subfieldspopulated, and passes them toQueryBuilderWidgetV1via thefieldspropPersonaAIContextRules.spec.ts— a gap the existing "Description Contains" plain-text test cannot cover. Uses aDatabaseServiceClassfixture for a deterministic service to selectTest plan
testcof type Enum)PersonaAIContextRules.spec.ts— "fully-completed Service Is condition allows save"🤖 Generated with Claude Code
Greptile Summary
The PR loads entity custom properties into the AI Context rule builder and expands its Playwright regression coverage.
Confidence Score: 5/5
The PR appears safe to merge.
No blocking failure remains.
Important Files Changed
Reviews (13): Last reviewed commit: "Merge branch 'main' into fix/persona-ai-..." | Re-trigger Greptile
Context used: