@cardstack/boxel-cli 0.9.0 → 0.10.0-unstable.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/bundled-test-harness/assets/account-switch-failed-GCSVbJML.js +23 -0
- package/bundled-test-harness/assets/account-switch-failed-GsWni_Gk.css +18 -0
- package/bundled-test-harness/assets/account-switch-failed-test-CdZWNths.js +45 -0
- package/bundled-test-harness/assets/add-workspace-c7L50Gx8.js +141 -0
- package/bundled-test-harness/assets/add-workspace-test-BZxHa6Pe.js +72 -0
- package/bundled-test-harness/assets/advanced-color-picker-0pGF-3WG.js +504 -0
- package/bundled-test-harness/assets/advanced-color-picker-pbO4HWc_.js +2 -0
- package/bundled-test-harness/assets/ai-assistant-test-Dnm4o9vK.js +2211 -0
- package/bundled-test-harness/assets/ai-module-creation-test-C6253CMt.js +151 -0
- package/bundled-test-harness/assets/aibot-message-miKyGeKk.js +278 -0
- package/bundled-test-harness/assets/app-i8pGdQkw.js +22855 -0
- package/bundled-test-harness/assets/app-zC7o6PyQ.css +2718 -0
- package/bundled-test-harness/assets/audio-file-def-DHnydP0t.js +133 -0
- package/bundled-test-harness/assets/auth-container-BP2gSoo4.css +51 -0
- package/bundled-test-harness/assets/auth-container-DN94iVfX.js +24 -0
- package/bundled-test-harness/assets/avif-meta-extractor-Bo5zRX1V.js +162 -0
- package/bundled-test-harness/assets/base64-image-B0RYxzHT.js +2 -0
- package/bundled-test-harness/assets/base64-image-Bxjqdwew.js +262 -0
- package/bundled-test-harness/assets/big-integer-7RLj5_7H.js +89 -0
- package/bundled-test-harness/assets/big-integer-C9sJxKVy.js +2 -0
- package/bundled-test-harness/assets/binary-upload-dedupe-test-DZo3EaV0.js +308 -0
- package/bundled-test-harness/assets/boolean-CcKPYUph.js +94 -0
- package/bundled-test-harness/assets/boolean-DvsSmtM7.js +2 -0
- package/bundled-test-harness/assets/brand-functional-palette-KpVSY2Sa.js +137 -0
- package/bundled-test-harness/assets/brand-logo-DDiOec0t.js +295 -0
- package/bundled-test-harness/assets/broken-link-template-test-DAngUbFJ.js +192 -0
- package/bundled-test-harness/assets/bundled-base-C_lumba6.js +254 -0
- package/bundled-test-harness/assets/bundled-base-modules-test-CSF7Rl4Z.js +54 -0
- package/bundled-test-harness/assets/buried-stack-item-scroll-test-B0J_EP88.js +236 -0
- package/bundled-test-harness/assets/bxl-expression-test-Dej7WgI6.js +250 -0
- package/bundled-test-harness/assets/can-invoke-test-elyUcOKT.js +401 -0
- package/bundled-test-harness/assets/card-api-CjWXCkqh.js +8 -0
- package/bundled-test-harness/assets/card-api-Dzje0smT.js +4393 -0
- package/bundled-test-harness/assets/card-api-test-DA8d4Ooc.js +198 -0
- package/bundled-test-harness/assets/card-basics-test-mp1Odo-l.js +5364 -0
- package/bundled-test-harness/assets/card-chooser-paging-test-y8OfboYd.js +235 -0
- package/bundled-test-harness/assets/card-chooser-test-nmg2zkDj.js +393 -0
- package/bundled-test-harness/assets/card-collection-BXiO3i7R.js +118 -0
- package/bundled-test-harness/assets/card-context-search-results-Dbhn7lvW.js +30 -0
- package/bundled-test-harness/assets/card-context-search-results-test-DVXT-YC5.js +184 -0
- package/bundled-test-harness/assets/card-def-field-def-relationships-test-mX4rxrtO.js +562 -0
- package/bundled-test-harness/assets/card-delete-test-BxFsqFnX.js +466 -0
- package/bundled-test-harness/assets/card-error-C-7hjxu9.js +72 -0
- package/bundled-test-harness/assets/card-error-awaiting-index-test-BvfY2eaW.js +53 -0
- package/bundled-test-harness/assets/card-error-detail-nMwopDir.js +271 -0
- package/bundled-test-harness/assets/card-info-CTFxdohf.js +2 -0
- package/bundled-test-harness/assets/card-list-B9QrkJ97.js +2 -0
- package/bundled-test-harness/assets/card-list-XbwLCXZS.js +202 -0
- package/bundled-test-harness/assets/card-resource-JGLjQUy6.js +86 -0
- package/bundled-test-harness/assets/cards-grid-CWG41hZE.js +344 -0
- package/bundled-test-harness/assets/cards-grid-DSpX99p6.js +2 -0
- package/bundled-test-harness/assets/cards-grid-layout-Bht0LwZy.js +2 -0
- package/bundled-test-harness/assets/cards-grid-layout-CdpKlHUb.js +111 -0
- package/bundled-test-harness/assets/check-correctness-test-C4BrUeKA.js +554 -0
- package/bundled-test-harness/assets/clip-BEVvLrXx.js +2 -0
- package/bundled-test-harness/assets/clip-CoB714qX.js +92 -0
- package/bundled-test-harness/assets/code-ref-C2uguisI.js +2 -0
- package/bundled-test-harness/assets/code-ref-Cy7sV5a4.js +138 -0
- package/bundled-test-harness/assets/code-submode-availability-test-BsA_Ul01.js +198 -0
- package/bundled-test-harness/assets/code-submode-test-DkBhpEPB.js +1839 -0
- package/bundled-test-harness/assets/codeblocks-test-B1eZ2_JF.js +418 -0
- package/bundled-test-harness/assets/codemirror-editor-C6pxSm5y.js +2 -0
- package/bundled-test-harness/assets/codemirror-editor-DzM46Cd8.js +701 -0
- package/bundled-test-harness/assets/codemirror-embed-toolbar-test-BemP-ZdG.js +366 -0
- package/bundled-test-harness/assets/color-C-jGNFWZ.js +2 -0
- package/bundled-test-harness/assets/color-field-test-DPIRaBec.js +212 -0
- package/bundled-test-harness/assets/color-picker-field-Bv4IjS-d.js +139 -0
- package/bundled-test-harness/assets/color-picker-field-D1bYCQIg.js +2 -0
- package/bundled-test-harness/assets/color-wheel-picker-IIaCQplL.js +283 -0
- package/bundled-test-harness/assets/color-wheel-picker-Kw-UN3kV.js +2 -0
- package/bundled-test-harness/assets/color-zzCBneih.js +65 -0
- package/bundled-test-harness/assets/command-data-BMBtjT1E.js +95 -0
- package/bundled-test-harness/assets/command-data-BXC5Z0oA.js +2 -0
- package/bundled-test-harness/assets/compaction-test-CxUKnxlQ.js +150 -0
- package/bundled-test-harness/assets/components-Ct_agx0G.js +14294 -0
- package/bundled-test-harness/assets/computed-test-C-lpGQQ3.js +1320 -0
- package/bundled-test-harness/assets/container-BdPu8rvc.css +5565 -0
- package/bundled-test-harness/assets/container-Dj-5prh9.js +11288 -0
- package/bundled-test-harness/assets/contains-many-component-CAWqzX8W.js +2 -0
- package/bundled-test-harness/assets/contrast-checker-addon-BTLD7oMx.js +2 -0
- package/bundled-test-harness/assets/contrast-checker-addon-DBzizR04.js +71 -0
- package/bundled-test-harness/assets/convert-to-class-name-test-zZuKxYvF.js +17 -0
- package/bundled-test-harness/assets/coordinate-Bw8va6tO.js +48 -0
- package/bundled-test-harness/assets/copy-file-to-realm-test-DtCKPzqj.js +148 -0
- package/bundled-test-harness/assets/country-B_tWpLlO.js +199 -0
- package/bundled-test-harness/assets/create-file-modal-D-VPyEYp.js +570 -0
- package/bundled-test-harness/assets/create-listing-modal-test-hyLkQY0u.js +273 -0
- package/bundled-test-harness/assets/create-listing-pr-request-test-rjWFA_5S.js +117 -0
- package/bundled-test-harness/assets/create-spec-test-HKIxZGxK.js +256 -0
- package/bundled-test-harness/assets/create-specs-9-ELVyJP.js +215 -0
- package/bundled-test-harness/assets/create-submission-workflow-test-DNZrbRX8.js +132 -0
- package/bundled-test-harness/assets/credential-fields-test-xPEdA911.js +157 -0
- package/bundled-test-harness/assets/css-value-Du3HL39X.js +48 -0
- package/bundled-test-harness/assets/csv-file-def-EHRmilrp.js +277 -0
- package/bundled-test-harness/assets/currency-y6ZCHIqG.js +134 -0
- package/bundled-test-harness/assets/date-B27PrSFT.js +183 -0
- package/bundled-test-harness/assets/date-CiP5Eb9i.js +2 -0
- package/bundled-test-harness/assets/date-time-fields-test-Clf5vxRW.js +359 -0
- package/bundled-test-harness/assets/datetime-BEbR9YgU.js +201 -0
- package/bundled-test-harness/assets/datetime-DPnrt1wl.js +2 -0
- package/bundled-test-harness/assets/datetime-stamp-AuT7F7qn.js +2 -0
- package/bundled-test-harness/assets/datetime-stamp-CGwP2P3f.js +81 -0
- package/bundled-test-harness/assets/day-BFLxZ9bQ.js +2 -0
- package/bundled-test-harness/assets/day-CQoEkqgE.js +113 -0
- package/bundled-test-harness/assets/debug-message-test-CzgOpfcI.js +117 -0
- package/bundled-test-harness/assets/dist-B-fYvxfL.js +389 -0
- package/bundled-test-harness/assets/dist-C2IXvIKX.js +323 -0
- package/bundled-test-harness/assets/dist-CdNZu43l.js +1710 -0
- package/bundled-test-harness/assets/docx-file-def-BQMw460_.js +60 -0
- package/bundled-test-harness/assets/docx-meta-extractor-DBlmH_kV.js +60 -0
- package/bundled-test-harness/assets/docx-meta-extractor-Dw4gZ0ae.js +2 -0
- package/bundled-test-harness/assets/duration-B0SnEiw1.js +184 -0
- package/bundled-test-harness/assets/duration-DbjJTFeA.js +2 -0
- package/bundled-test-harness/assets/email-C-8cyWiQ.js +80 -0
- package/bundled-test-harness/assets/email-field-test-BOBmvQqx.js +75 -0
- package/bundled-test-harness/assets/email-xUgCst-p.js +2 -0
- package/bundled-test-harness/assets/enum-BWiCyJlu.js +167 -0
- package/bundled-test-harness/assets/enum-CzYjivhO.js +2 -0
- package/bundled-test-harness/assets/enum-field-test-Bea9EsQR.js +953 -0
- package/bundled-test-harness/assets/error-display-test-Cbl2D_0c.js +343 -0
- package/bundled-test-harness/assets/ethereum-address-Bw_J05bD.js +78 -0
- package/bundled-test-harness/assets/ethereum-address-C9wHMBt3.js +2 -0
- package/bundled-test-harness/assets/expiration-warning-BHcJEjZt.js +90 -0
- package/bundled-test-harness/assets/expiration-warning-_G8SKZd0.js +2 -0
- package/bundled-test-harness/assets/externals-CKblKBo1.js +4393 -0
- package/bundled-test-harness/assets/fallback-banner-BqCrvTDt.js +24 -0
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-D_AYMvf6.js +207 -0
- package/bundled-test-harness/assets/fallback-banner-test-B8Ne9a5g.js +225 -0
- package/bundled-test-harness/assets/fallback-banner-test-C7oaSxd1.js +53 -0
- package/bundled-test-harness/assets/fallback-models-test-DY-PvU9k.js +161 -0
- package/bundled-test-harness/assets/field-component-Bj8YthPE.js +2 -0
- package/bundled-test-harness/assets/field-configuration-test-B5LztQ47.js +548 -0
- package/bundled-test-harness/assets/field-edit-Cx_haspD.js +36 -0
- package/bundled-test-harness/assets/field-edit-DQZWUz3F.js +2 -0
- package/bundled-test-harness/assets/field-markdown-domain-test-DnqK3CrE.js +616 -0
- package/bundled-test-harness/assets/field-markdown-oversize-test-BEpbXIvl.js +88 -0
- package/bundled-test-harness/assets/field-markdown-primitives-test-BDORWoOk.js +365 -0
- package/bundled-test-harness/assets/field-markdown-specialized-test-BmIzadYq.js +534 -0
- package/bundled-test-harness/assets/field-test-helpers-CRF9-jFw.js +45 -0
- package/bundled-test-harness/assets/file-api-DPMJghBY.js +7 -0
- package/bundled-test-harness/assets/file-attachment-test-DFLXg3xV.js +796 -0
- package/bundled-test-harness/assets/file-chooser-panel-test-B4DzCWkt.js +153 -0
- package/bundled-test-harness/assets/file-chooser-test-DpjOWgpB.js +504 -0
- package/bundled-test-harness/assets/file-def-edit-Bstl7Kkl.js +2 -0
- package/bundled-test-harness/assets/file-def-edit-C1dzJxmQ.js +26 -0
- package/bundled-test-harness/assets/file-def-embedded-CUy4G7Vc.js +2 -0
- package/bundled-test-harness/assets/file-def-embedded-DJs6P5t0.js +38 -0
- package/bundled-test-harness/assets/file-def-fitted-BlrBFfLh.js +38 -0
- package/bundled-test-harness/assets/file-def-fitted-Bo5Qfkyf.js +2 -0
- package/bundled-test-harness/assets/file-def-isolated-BsHydanv.js +38 -0
- package/bundled-test-harness/assets/file-def-isolated-Dp-Lc99-.js +2 -0
- package/bundled-test-harness/assets/file-def-serialization-test-CISKpt_o.js +89 -0
- package/bundled-test-harness/assets/file-menu-items-7_ltrFZq.js +117 -0
- package/bundled-test-harness/assets/file-menu-items-BnRG9ydE.js +2 -0
- package/bundled-test-harness/assets/file-preview-stage-CV3qZpiK.js +72 -0
- package/bundled-test-harness/assets/file-preview-stage-DTA5X8rX.js +2 -0
- package/bundled-test-harness/assets/file-shell-embedded-BpmiVzIG.js +2 -0
- package/bundled-test-harness/assets/file-shell-embedded-CEv0-6OE.js +68 -0
- package/bundled-test-harness/assets/file-shell-fitted-C6k3GnMc.js +2 -0
- package/bundled-test-harness/assets/file-shell-fitted-iSTg3PJa.js +98 -0
- package/bundled-test-harness/assets/file-shell-isolated-C-pEod2J.js +195 -0
- package/bundled-test-harness/assets/file-shell-isolated-DI9oU7ix.js +2 -0
- package/bundled-test-harness/assets/file-tree-from-index-BtOOMqnb.js +151 -0
- package/bundled-test-harness/assets/file-tree-from-index-test-T8w3hPw_.js +96 -0
- package/bundled-test-harness/assets/film-5n9_gRqZ.js +4074 -0
- package/bundled-test-harness/assets/film-Ca2Vzlfu.js +13 -0
- package/bundled-test-harness/assets/film-DEvhBbBu.js +2 -0
- package/bundled-test-harness/assets/fitted-6OGuHgoU.js +2 -0
- package/bundled-test-harness/assets/fitted-B2l1jlSp.js +34 -0
- package/bundled-test-harness/assets/flac-meta-extractor-BoJqvmDC.js +99 -0
- package/bundled-test-harness/assets/font-file-def-Czzt5paT.js +64 -0
- package/bundled-test-harness/assets/font-meta-extractor-DQYT_e5b.js +2 -0
- package/bundled-test-harness/assets/font-meta-extractor-IHD-pG8V.js +303 -0
- package/bundled-test-harness/assets/formatted-aibot-message-test-Djsl8RzE.js +109 -0
- package/bundled-test-harness/assets/from-elsewhere-BXcLYxxu.js +131 -0
- package/bundled-test-harness/assets/frontmatter-field-CciolgL3.js +41 -0
- package/bundled-test-harness/assets/garbage-collection-test-BTOLAfB6.js +403 -0
- package/bundled-test-harness/assets/gauge-C1loqGq3.js +2 -0
- package/bundled-test-harness/assets/gauge-u8dxl90d.js +106 -0
- package/bundled-test-harness/assets/general-test-Cd5WtVvd.js +926 -0
- package/bundled-test-harness/assets/get-relationship-membership-state-test-DJAuhOVM.js +1308 -0
- package/bundled-test-harness/assets/gif-meta-extractor-tSaPtuYW.js +114 -0
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-DNSy5l59.js +160 -0
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-B6BbQxYq.js +74 -0
- package/bundled-test-harness/assets/helper-m6jA5HmU.js +478 -0
- package/bundled-test-harness/assets/host-submode-test-CsgdksBi.js +1243 -0
- package/bundled-test-harness/assets/html-file-def-yKtdMSa-.js +82 -0
- package/bundled-test-harness/assets/hydratable-card-CxNfbqly.js +147 -0
- package/bundled-test-harness/assets/hydratable-card-test-NJ4CI4ey.js +426 -0
- package/bundled-test-harness/assets/icons-B3SAtRoj.js +894 -0
- package/bundled-test-harness/assets/image-file-def-B0rpS3Yy.js +3 -0
- package/bundled-test-harness/assets/image-file-def-DUFmjNL8.js +65 -0
- package/bundled-test-harness/assets/image-olOUqgMQ.js +47 -0
- package/bundled-test-harness/assets/index-changes-test-D7OE-99k.js +367 -0
- package/bundled-test-harness/assets/index-query-engine-test-BBKqgSmg.js +2593 -0
- package/bundled-test-harness/assets/inspector-test-DV6Ms2uz.js +1930 -0
- package/bundled-test-harness/assets/instance-filter-matcher-test-Bs4kf7E8.js +788 -0
- package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DIfgRhIN.js +475 -0
- package/bundled-test-harness/assets/interact-submode-setup-D4M_e580.js +566 -0
- package/bundled-test-harness/assets/is-component-declaration-test-jPGRTVh1.js +50 -0
- package/bundled-test-harness/assets/iso-bmff-DHtkSbQM.js +205 -0
- package/bundled-test-harness/assets/iso-bmff-zmOHoSVg.js +2 -0
- package/bundled-test-harness/assets/isolated-and-edit-BAnwcK1T.js +2 -0
- package/bundled-test-harness/assets/job-priority-header-test-7j2f3Dtl.js +81 -0
- package/bundled-test-harness/assets/job-scoped-instance-residency-test-DPzVQUL3.js +103 -0
- package/bundled-test-harness/assets/join-the-community-Ft5fjeIA.js +86 -0
- package/bundled-test-harness/assets/jpg-meta-extractor-Dsq6rZ8F.js +88 -0
- package/bundled-test-harness/assets/json-field-CxOZvp3k.js +19 -0
- package/bundled-test-harness/assets/json-field-ojdwGD6T.js +2 -0
- package/bundled-test-harness/assets/json-file-def-Da_5-zSM.js +298 -0
- package/bundled-test-harness/assets/last-modified-date-BnyJsc04.js +43 -0
- package/bundled-test-harness/assets/last-modified-date-test-DFl2mo1B.js +28 -0
- package/bundled-test-harness/assets/links-to-editor-DO24-71w.js +2 -0
- package/bundled-test-harness/assets/links-to-many-component-C7DabwAY.js +2 -0
- package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-D4lDhvnQ.js +398 -0
- package/bundled-test-harness/assets/linksto-error-sentinel-test-oWgDz00K.js +238 -0
- package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-CpSl7zJ7.js +354 -0
- package/bundled-test-harness/assets/linksto-many-per-slot-access-test-DJY3J8Xl.js +303 -0
- package/bundled-test-harness/assets/linksto-sentinel-reload-test-BxzfoONe.js +197 -0
- package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-DyE99km_.js +260 -0
- package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-dcWAAgxt.js +196 -0
- package/bundled-test-harness/assets/llm-model-DrswiczZ.js +64 -0
- package/bundled-test-harness/assets/login-C-EIG0-Q.css +543 -0
- package/bundled-test-harness/assets/login-CNeL-9IC.js +408 -0
- package/bundled-test-harness/assets/login-error-text-test-CEH2tjNP.js +51 -0
- package/bundled-test-harness/assets/login-test-BpMx7qwV.js +246 -0
- package/bundled-test-harness/assets/m4a-meta-extractor-BJkMHUIK.js +204 -0
- package/bundled-test-harness/assets/main-BaUgfpPE.js +5 -0
- package/bundled-test-harness/assets/markdown-ByEGbwov.js +7 -0
- package/bundled-test-harness/assets/markdown-KJzgTg-A.js +2 -0
- package/bundled-test-harness/assets/markdown-editor-mode-select-BUGPXaSE.js +2 -0
- package/bundled-test-harness/assets/markdown-editor-mode-select-DBk8dG0O.js +54 -0
- package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-BIlEmna9.js +470 -0
- package/bundled-test-harness/assets/markdown-embed-preview-pane-test-B6rscKpk.js +447 -0
- package/bundled-test-harness/assets/markdown-embed-preview-test-CTQw1wq-.js +368 -0
- package/bundled-test-harness/assets/markdown-fallback-BVsco6gJ.js +2 -0
- package/bundled-test-harness/assets/markdown-fallback-test-C_CIFEzH.js +316 -0
- package/bundled-test-harness/assets/markdown-highlighting-test-D6YvywF5.js +244 -0
- package/bundled-test-harness/assets/markdown-preview-1TSMSUv0.js +64 -0
- package/bundled-test-harness/assets/markdown-preview-jbuUjLoD.js +72 -0
- package/bundled-test-harness/assets/markdown-preview-test-zuU5uoA_.js +238 -0
- package/bundled-test-harness/assets/markdown-skill-frontmatter-test-CoicGRkb.js +146 -0
- package/bundled-test-harness/assets/menu-items-DZ_uOoYu.js +2 -0
- package/bundled-test-harness/assets/message-tool-test-K6LgTq5d.js +33 -0
- package/bundled-test-harness/assets/metadata-fields-WiOuUCDl.js +1415 -0
- package/bundled-test-harness/assets/metadata-fields-iu5AfQp3.js +2 -0
- package/bundled-test-harness/assets/midi-audio-def-CD2-4Wjx.js +52 -0
- package/bundled-test-harness/assets/midi-meta-extractor-CE3sLiEV.js +284 -0
- package/bundled-test-harness/assets/midi-meta-extractor-O7c8LHYV.js +2 -0
- package/bundled-test-harness/assets/migrate-skill-test-Beh-AeSN.js +161 -0
- package/bundled-test-harness/assets/mini-BNXINKKF.js +85 -0
- package/bundled-test-harness/assets/mini-C43Q4BWp.js +1519 -0
- package/bundled-test-harness/assets/mini-card-chooser-test-B1GMp-31.js +272 -0
- package/bundled-test-harness/assets/mini-file-chooser-test-CbI1vrQn.js +201 -0
- package/bundled-test-harness/assets/missing-template-BPhJRbDs.js +48 -0
- package/bundled-test-harness/assets/missing-template-DP-Pi-HQ.js +2 -0
- package/bundled-test-harness/assets/modal-KpPz2f8x.js +322 -0
- package/bundled-test-harness/assets/modal-container-0Efz_h2z.js +40 -0
- package/bundled-test-harness/assets/model-cost-tier-test-D-5VSjh6.js +173 -0
- package/bundled-test-harness/assets/module-contents-service-BRkTETb6.js +256 -0
- package/bundled-test-harness/assets/moment-Cln59YUK.js +3474 -0
- package/bundled-test-harness/assets/monaco-AbHCoDJY.js +143 -0
- package/bundled-test-harness/assets/monaco-test-DCPi18sy.js +100 -0
- package/bundled-test-harness/assets/monaco-test-waiter-lvFEYpFj.js +190 -0
- package/bundled-test-harness/assets/month-1eUIsvWN.js +2 -0
- package/bundled-test-harness/assets/month-BeUdWMWQ.js +123 -0
- package/bundled-test-harness/assets/month-day-Bbsd8YbR.js +192 -0
- package/bundled-test-harness/assets/month-day-Dks5STJu.js +2 -0
- package/bundled-test-harness/assets/month-year-pL_rpUhX.js +2 -0
- package/bundled-test-harness/assets/month-year-wH_YnYgL.js +93 -0
- package/bundled-test-harness/assets/mp3-meta-extractor-C3u34UHM.js +476 -0
- package/bundled-test-harness/assets/mp4-meta-extractor-Bj3F7dxs.js +188 -0
- package/bundled-test-harness/assets/multiple-stacks-test-mkNdTUMI.js +208 -0
- package/bundled-test-harness/assets/nested-query-field-render-test-BQLn3wg9.js +249 -0
- package/bundled-test-harness/assets/no-stacks-test-DpwZQAJ-.js +48 -0
- package/bundled-test-harness/assets/number-DZa-fHpu.js +151 -0
- package/bundled-test-harness/assets/number-Dvua76YP.js +3 -0
- package/bundled-test-harness/assets/number-field-test-BiaH2eaB.js +184 -0
- package/bundled-test-harness/assets/number-input-D5nDYDkK.js +82 -0
- package/bundled-test-harness/assets/office-extract-JzYva33g.js +27 -0
- package/bundled-test-harness/assets/office-extract-XMpsyYRh.js +2 -0
- package/bundled-test-harness/assets/ogg-meta-extractor-DJosZ9LA.js +225 -0
- package/bundled-test-harness/assets/on-key-BBVkS8Bi.js +472 -0
- package/bundled-test-harness/assets/ooxml-BlAE2w4d.js +172 -0
- package/bundled-test-harness/assets/ooxml-D-p8OmuM.js +2 -0
- package/bundled-test-harness/assets/open-image-in-new-tab-test-DWBU5pw9.js +52 -0
- package/bundled-test-harness/assets/operation-lowering-test-nzqprueU.js +2812 -0
- package/bundled-test-harness/assets/operations-CPvfTuY3.js +766 -0
- package/bundled-test-harness/assets/operations-invocation-test-C75T6zn3.js +523 -0
- package/bundled-test-harness/assets/operations-query-test-BoCszQEW.js +459 -0
- package/bundled-test-harness/assets/operations-test-79ipSnpM.js +2518 -0
- package/bundled-test-harness/assets/operations-x3Aw2Nky.js +3 -0
- package/bundled-test-harness/assets/operator-mode-acceptance-test-jjsYtt96.js +1188 -0
- package/bundled-test-harness/assets/operator-mode-card-chooser-test-hZP9gEQK.js +1036 -0
- package/bundled-test-harness/assets/operator-mode-links-test-DN16SuIx.js +793 -0
- package/bundled-test-harness/assets/operator-mode-state-service-gwiTSiWX.js +1275 -0
- package/bundled-test-harness/assets/operator-mode-state-service-test-Dt2qnKKP.js +206 -0
- package/bundled-test-harness/assets/operator-mode-test-BZnnxO9q.js +683 -0
- package/bundled-test-harness/assets/operator-mode-ui-test-O--qEo-y.js +1027 -0
- package/bundled-test-harness/assets/overlay-menu-items-test-Bl2k0aAa.js +317 -0
- package/bundled-test-harness/assets/overlays-CdN_JokA.js +270 -0
- package/bundled-test-harness/assets/overlays-clip-test-DpbR1ZTz.js +91 -0
- package/bundled-test-harness/assets/overlays-detached-element-test-cLgEGvMs.js +56 -0
- package/bundled-test-harness/assets/pane-PYdezM7g.js +330 -0
- package/bundled-test-harness/assets/panel-7FDqkxrr.js +474 -0
- package/bundled-test-harness/assets/panel-C3E0s49q.js +3540 -0
- package/bundled-test-harness/assets/past-sessions-test-BsjEeoze.js +321 -0
- package/bundled-test-harness/assets/patch-fields-test-CsixJmSr.js +1014 -0
- package/bundled-test-harness/assets/patch-instance-test-CBDgTi0L.js +348 -0
- package/bundled-test-harness/assets/pdf-file-def-9VNjnqDa.js +76 -0
- package/bundled-test-harness/assets/pdf-meta-extractor-BF4e5kMR.js +156 -0
- package/bundled-test-harness/assets/pdf-meta-extractor-D8Bxh2cc.js +2 -0
- package/bundled-test-harness/assets/pdf-viewer-Bu413sN8.js +112 -0
- package/bundled-test-harness/assets/pdf-viewer-GKDi_xmf.js +2 -0
- package/bundled-test-harness/assets/percentage-TOr6qK2T.js +84 -0
- package/bundled-test-harness/assets/permission-checking-realm-test-BRNVYszm.js +306 -0
- package/bundled-test-harness/assets/phone-number-D5SR8nWu.js +236 -0
- package/bundled-test-harness/assets/phone-number-field-test-DffwtqGd.js +73 -0
- package/bundled-test-harness/assets/phone-number-hf_xIVGQ.js +2 -0
- package/bundled-test-harness/assets/plate-Vojc88hM.js +41 -0
- package/bundled-test-harness/assets/plate-dTUzEMj5.js +2 -0
- package/bundled-test-harness/assets/player-CmRw0uM5.js +82 -0
- package/bundled-test-harness/assets/player-Dt85lPZl.js +2 -0
- package/bundled-test-harness/assets/plural-field-components-test-DNpGuH1D.js +198 -0
- package/bundled-test-harness/assets/png-image-def-GY7gjqya.js +48 -0
- package/bundled-test-harness/assets/png-meta-extractor-4pI611re.js +2 -0
- package/bundled-test-harness/assets/png-meta-extractor-CHp_rpAi.js +111 -0
- package/bundled-test-harness/assets/policy-scoped-search-test-CipPu7tY.js +339 -0
- package/bundled-test-harness/assets/pptx-file-def-lBBiebvn.js +60 -0
- package/bundled-test-harness/assets/pptx-meta-extractor-BjJYWiOJ.js +77 -0
- package/bundled-test-harness/assets/pptx-meta-extractor-DbT-dPRg.js +2 -0
- package/bundled-test-harness/assets/prerender-persistence-block-test-ClHMVvJt.js +124 -0
- package/bundled-test-harness/assets/prerender-serialize-cycle-test-LdqaMTK8.js +134 -0
- package/bundled-test-harness/assets/preview-CYlam_aW.js +74 -0
- package/bundled-test-harness/assets/preview-format-CiSo4kEa.js +41 -0
- package/bundled-test-harness/assets/preview-format-test-MsB1TOLB.js +103 -0
- package/bundled-test-harness/assets/process-card-B3xBGkv1.js +2 -0
- package/bundled-test-harness/assets/process-card-DumVcx9E.js +114 -0
- package/bundled-test-harness/assets/process-card-test-C44H8yVy.js +94 -0
- package/bundled-test-harness/assets/profile-settings-modal-ipYzrVTz.js +708 -0
- package/bundled-test-harness/assets/progress-circle-DJ6WSO2E.js +95 -0
- package/bundled-test-harness/assets/progress-circle-q358_9Sn.js +2 -0
- package/bundled-test-harness/assets/quarter-BjO5DlU2.js +2 -0
- package/bundled-test-harness/assets/quarter-_D72FwfS.js +168 -0
- package/bundled-test-harness/assets/query-field-membership-status-test-CzDyfK49.js +323 -0
- package/bundled-test-harness/assets/query-field-page-optin-test-B-x3vsmC.js +126 -0
- package/bundled-test-harness/assets/query-field-schema-test-DFw6KuYv.js +231 -0
- package/bundled-test-harness/assets/query-field-stale-prerender-test-DSQ-cv_O.js +152 -0
- package/bundled-test-harness/assets/query-fields-test-DQiMFRCe.js +535 -0
- package/bundled-test-harness/assets/rail-CNspDFyn.js +44 -0
- package/bundled-test-harness/assets/rail-D2YcQ0VP.js +2 -0
- package/bundled-test-harness/assets/realm-82Z5RUM_.js +95 -0
- package/bundled-test-harness/assets/realm-config-SgrwqjRu.js +844 -0
- package/bundled-test-harness/assets/realm-config-policy-standing-test-C6sQNk2u.js +290 -0
- package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-DcYXBlvi.js +274 -0
- package/bundled-test-harness/assets/realm-config-settings-test-DblJv06X.js +187 -0
- package/bundled-test-harness/assets/realm-dropdown-CDvL8k3B.js +560 -0
- package/bundled-test-harness/assets/realm-et890flh.js +2 -0
- package/bundled-test-harness/assets/realm-field-test-pBK_x-Xw.js +100 -0
- package/bundled-test-harness/assets/realm-indexing-test-DSFn2F8F.js +4380 -0
- package/bundled-test-harness/assets/realm-policy-test-DYnLqzTS.js +1141 -0
- package/bundled-test-harness/assets/realm-test-DOZT2EG5.js +2363 -0
- package/bundled-test-harness/assets/realm-url-tooltip-qaXTjRb-.js +56 -0
- package/bundled-test-harness/assets/realm-url-tooltip-test-DGTEeLH9.js +78 -0
- package/bundled-test-harness/assets/reasoning-test-BRkhvYjr.js +234 -0
- package/bundled-test-harness/assets/recent-colors-addon-BreXcpg8.js +2 -0
- package/bundled-test-harness/assets/recent-colors-addon-CmCkbJ2_.js +61 -0
- package/bundled-test-harness/assets/relationship-loading-state-test-B6UGYKzG.js +290 -0
- package/bundled-test-harness/assets/relative-time-BjHvL023.js +2 -0
- package/bundled-test-harness/assets/relative-time-ChYKOMIM.js +129 -0
- package/bundled-test-harness/assets/remix-card-test-CpV0kKfq.js +58 -0
- package/bundled-test-harness/assets/rendered-markdown-CJa7IzCC.js +263 -0
- package/bundled-test-harness/assets/rendered-markdown-test-CVKsHS4P.js +587 -0
- package/bundled-test-harness/assets/resident-instance-reuse-test-jQfW1NMn.js +82 -0
- package/bundled-test-harness/assets/response-field-B2-daCl2.js +38 -0
- package/bundled-test-harness/assets/result-tile-BSg4mzbc.js +140 -0
- package/bundled-test-harness/assets/rich-markdown-BtP1yamM.js +2 -0
- package/bundled-test-harness/assets/rich-markdown-C6rQUngb.js +218 -0
- package/bundled-test-harness/assets/rich-markdown-field-test-9yB6ykCe.js +1647 -0
- package/bundled-test-harness/assets/room-C7tKd02X.js +1008 -0
- package/bundled-test-harness/assets/room-message-test-DsMmRYpV.js +445 -0
- package/bundled-test-harness/assets/room-test-golI1H61.js +95 -0
- package/bundled-test-harness/assets/run-realm-code-CbXk6bnK.js +1600 -0
- package/bundled-test-harness/assets/run-realm-code-test-B9JeesaW.js +2468 -0
- package/bundled-test-harness/assets/schema-generation-test-uLLGm5Vh.js +28 -0
- package/bundled-test-harness/assets/score-BQhCQdUP.js +2 -0
- package/bundled-test-harness/assets/score-CoWEzENH.js +100 -0
- package/bundled-test-harness/assets/scrolling-test-WHWEkKeZ.js +384 -0
- package/bundled-test-harness/assets/search-BkQYpQDY.js +605 -0
- package/bundled-test-harness/assets/search-adorn-test-CW92JPOk.js +136 -0
- package/bundled-test-harness/assets/search-entries-BU4w6Ymc.js +472 -0
- package/bundled-test-harness/assets/search-entries-result-test-9eydsDtD.js +234 -0
- package/bundled-test-harness/assets/search-entries-test-ByUREx0G.js +1486 -0
- package/bundled-test-harness/assets/search-result-header-UFkdo0Bx.js +128 -0
- package/bundled-test-harness/assets/search-results-DrHTuVRZ.js +266 -0
- package/bundled-test-harness/assets/search-results-test-krtQQM57.js +578 -0
- package/bundled-test-harness/assets/search-selection-menu-test-DoqSbez7.js +108 -0
- package/bundled-test-harness/assets/search-sheet-persistence-test-4ZPaEY-y.js +131 -0
- package/bundled-test-harness/assets/search-test-BYpq32RM.js +2241 -0
- package/bundled-test-harness/assets/searchable-BXw4T11q.js +192 -0
- package/bundled-test-harness/assets/searchable-CVvPDA3Q.js +2 -0
- package/bundled-test-harness/assets/searchable-option-test-BhLFI4ei.js +322 -0
- package/bundled-test-harness/assets/searchable-search-doc-test-DrNLCF73.js +1271 -0
- package/bundled-test-harness/assets/secure-sign-in-VNQhe0ae.js +130 -0
- package/bundled-test-harness/assets/secure-sign-in-Za8PX9cD.css +24 -0
- package/bundled-test-harness/assets/secure-sign-in-aunWHCrB.js +73 -0
- package/bundled-test-harness/assets/secure-sign-in-test-BcY1TcNd.js +32 -0
- package/bundled-test-harness/assets/secure-sign-in-test-DRdz89BT.js +245 -0
- package/bundled-test-harness/assets/sending-test-mbHpGZUu.js +576 -0
- package/bundled-test-harness/assets/serialization-rri-form-audit-test-nypV9J82.js +136 -0
- package/bundled-test-harness/assets/serialization-test-aLwrFv4d.js +8758 -0
- package/bundled-test-harness/assets/setup-Dgn0s6Zk.js +772 -0
- package/bundled-test-harness/assets/shared-link-target-reuse-test-D9MR2UNc.js +207 -0
- package/bundled-test-harness/assets/show-card-Dwfk332M.js +67 -0
- package/bundled-test-harness/assets/show-card-test-CRPwwJvc.js +365 -0
- package/bundled-test-harness/assets/show-file-DLdFPHMR.js +34 -0
- package/bundled-test-harness/assets/signed-capture-DUR9PohQ.js +204 -0
- package/bundled-test-harness/assets/signed-capture-link-test-DfTAB6OT.js +132 -0
- package/bundled-test-harness/assets/single-stack-test-Crr_8nti.js +652 -0
- package/bundled-test-harness/assets/skill-DQ00VonZ.js +3 -0
- package/bundled-test-harness/assets/skill-reference-LEitQV9i.js +112 -0
- package/bundled-test-harness/assets/skill-yZXS1VHQ.js +76 -0
- package/bundled-test-harness/assets/skills-test-D3-C-Dbm.js +648 -0
- package/bundled-test-harness/assets/slider-picker-B6AxKL2j.js +245 -0
- package/bundled-test-harness/assets/slider-picker-C4Tc5o-s.js +2 -0
- package/bundled-test-harness/assets/spec-Cl_LB6nC.js +602 -0
- package/bundled-test-harness/assets/spinner-BHFM7zcR.js +39 -0
- package/bundled-test-harness/assets/spinner-DvAvsyDT.css +21 -0
- package/bundled-test-harness/assets/store-BV6WX8oV.js +2205 -0
- package/bundled-test-harness/assets/store-module-rebuild-test-HyphFJiF.js +454 -0
- package/bundled-test-harness/assets/store-search-test-nUeJ5opb.js +175 -0
- package/bundled-test-harness/assets/store-test-BebUIJAg.js +3460 -0
- package/bundled-test-harness/assets/string-BHZZwNlZ.js +9 -0
- package/bundled-test-harness/assets/submode-switcher-D-U9cXo0.js +169 -0
- package/bundled-test-harness/assets/svg-meta-extractor-BsG4w2nX.js +42 -0
- package/bundled-test-harness/assets/swatches-picker-4vFztxHo.js +33 -0
- package/bundled-test-harness/assets/swatches-picker-C7RE7uJ8.js +2 -0
- package/bundled-test-harness/assets/switch-submode-CuA0Zfjn.js +79 -0
- package/bundled-test-harness/assets/switch-submode-test-i1Qic_Cp.js +168 -0
- package/bundled-test-harness/assets/tag-CZNs3DPN.js +105 -0
- package/bundled-test-harness/assets/tests-BneuP252.js +3523 -0
- package/bundled-test-harness/assets/text-area-DAShQQBe.js +9 -0
- package/bundled-test-harness/assets/text-file-def-D2Rs6nS1.js +151 -0
- package/bundled-test-harness/assets/text-input-validator-test-C9IG-1GZ.js +156 -0
- package/bundled-test-harness/assets/theme-Dm8LWaRK.js +9 -0
- package/bundled-test-harness/assets/theme-card-test-Cbb6tAap.js +621 -0
- package/bundled-test-harness/assets/theme-scheme-island-test-DOVLakx3.js +264 -0
- package/bundled-test-harness/assets/three-d-model-def-DWSPQGgD.js +70 -0
- package/bundled-test-harness/assets/time--_Txqya1.js +126 -0
- package/bundled-test-harness/assets/time-DKD7Bdjd.js +2 -0
- package/bundled-test-harness/assets/time-slots-BZaugjq_.js +2 -0
- package/bundled-test-harness/assets/time-slots-C85M0rWl.js +85 -0
- package/bundled-test-harness/assets/timeline-B3KGDm3M.js +2 -0
- package/bundled-test-harness/assets/timeline-BMwgaZZu.js +59 -0
- package/bundled-test-harness/assets/to-device-streaming-test-CMp5bFiz.js +163 -0
- package/bundled-test-harness/assets/token-usage-test-CXA0b8Ep.js +166 -0
- package/bundled-test-harness/assets/tool-field-BGLelnsr.js +94 -0
- package/bundled-test-harness/assets/tool-field-BOFuDDt3.js +2 -0
- package/bundled-test-harness/assets/tools-CTjy7Aub.js +725 -0
- package/bundled-test-harness/assets/tools-calling-test--JR-7AK7.js +200 -0
- package/bundled-test-harness/assets/tools-test-6yAW3W5I.js +2820 -0
- package/bundled-test-harness/assets/tools-test-DhpMUQkz.js +1624 -0
- package/bundled-test-harness/assets/ts-file-def-CDbf8aw2.js +159 -0
- package/bundled-test-harness/assets/update-room-skills-test-DoKsS_1C.js +240 -0
- package/bundled-test-harness/assets/url-D0ooeJxC.js +2 -0
- package/bundled-test-harness/assets/url-mFskVPSX.js +96 -0
- package/bundled-test-harness/assets/video-file-def-AcmWqzev.js +76 -0
- package/bundled-test-harness/assets/wav-meta-extractor-CbTLruQf.js +368 -0
- package/bundled-test-harness/assets/webm-meta-extractor-C9JH-CMX.js +178 -0
- package/bundled-test-harness/assets/webp-meta-extractor-C6sHm4J7.js +98 -0
- package/bundled-test-harness/assets/website-Bxuk_OmR.js +92 -0
- package/bundled-test-harness/assets/week-Bxssxce7.js +2 -0
- package/bundled-test-harness/assets/week-DQLj9974.js +111 -0
- package/bundled-test-harness/assets/welcome-to-boxel-BH82RsW5.js +172 -0
- package/bundled-test-harness/assets/workspace-DJ_s2x4g.js +614 -0
- package/bundled-test-harness/assets/workspace-a11y-test-BJbZNgoP.js +197 -0
- package/bundled-test-harness/assets/workspace-behavior-test-BLBARTfb.js +200 -0
- package/bundled-test-harness/assets/workspace-chooser-BpmlVrVn.js +2219 -0
- package/bundled-test-harness/assets/workspace-chooser-CqLR2Dzh.css +1296 -0
- package/bundled-test-harness/assets/workspace-chooser-catalog-order-test-CmAVNAWC.js +36 -0
- package/bundled-test-harness/assets/workspace-chooser-unreachable-notice-test-DEfG7Uh9.js +60 -0
- package/bundled-test-harness/assets/workspace-delete-multiple-test-DE7Z8ooj.js +212 -0
- package/bundled-test-harness/assets/workspace-delete-summary-test-CwtG_zLH.js +63 -0
- package/bundled-test-harness/assets/workspace-timestamp-labels-test-DFAaRmJW.js +58 -0
- package/bundled-test-harness/assets/xlsx-file-def-DcvaRYnZ.js +60 -0
- package/bundled-test-harness/assets/xlsx-meta-extractor-0RlViVaf.js +101 -0
- package/bundled-test-harness/assets/xlsx-meta-extractor-BH30Vuem.js +2 -0
- package/bundled-test-harness/assets/year-B_MBk_hE.js +78 -0
- package/bundled-test-harness/assets/year-hSpccI9L.js +2 -0
- package/bundled-test-harness/assets/zip-file-def-c84iddi9.js +288 -0
- package/bundled-test-harness/index.html +78 -68
- package/bundled-test-harness/tests/index.html +78 -68
- package/bundled-types/host-app/components/matrix/account-switch-failed.gts +2 -2
- package/bundled-types/host-app/components/matrix/auth.gts +2 -2
- package/bundled-types/host-app/components/matrix/cli-auth.gts +7 -6
- package/bundled-types/host-app/components/matrix/forgot-password.gts +43 -129
- package/bundled-types/host-app/components/matrix/login.gts +15 -118
- package/bundled-types/host-app/components/matrix/register-user.gts +45 -226
- package/bundled-types/host-app/components/matrix/secure-sign-in.gts +235 -0
- package/bundled-types/host-app/components/operator-mode/container.gts +13 -1
- package/bundled-types/host-app/components/operator-mode/profile-info-popover.gts +1 -1
- package/bundled-types/host-app/config/environment.ts +1 -1
- package/bundled-types/host-app/lib/secure-sign-in.ts +130 -0
- package/bundled-types/host-app/services/matrix-service.ts +46 -0
- package/bundled-types/host-app/services/monaco-service.ts +0 -5
- package/bundled-types/host-app/utils/login-token.ts +23 -10
- package/dist/api.js +1 -1
- package/dist/index.js +289 -285
- package/package.json +1 -1
- package/src/build-program.ts +6 -2
- package/src/commands/profile.ts +72 -3
- package/src/lib/profile-manager.ts +5 -1
- package/src/lib/secure-session.ts +29 -0
- package/src/lib/sso-login.ts +94 -15
- package/bundled-test-harness/assets/account-switch-failed-B3pr_iC3.js +0 -32
- package/bundled-test-harness/assets/account-switch-failed-DTGZZo-G.css +0 -61
- package/bundled-test-harness/assets/account-switch-failed-test-9ENVgvlx.js +0 -45
- package/bundled-test-harness/assets/add-workspace-BAbk0250.js +0 -141
- package/bundled-test-harness/assets/add-workspace-test-ChAja_t-.js +0 -72
- package/bundled-test-harness/assets/advanced-color-picker-C-xBFJ2S.js +0 -504
- package/bundled-test-harness/assets/advanced-color-picker-bWAmCT-8.js +0 -2
- package/bundled-test-harness/assets/ai-assistant-test-BJ9yetuC.js +0 -2211
- package/bundled-test-harness/assets/ai-module-creation-test-Bw3TKS9d.js +0 -151
- package/bundled-test-harness/assets/aibot-message-DkgHT6eJ.js +0 -465
- package/bundled-test-harness/assets/app-DW5QjtRp.js +0 -22816
- package/bundled-test-harness/assets/app-yCDjO4mk.css +0 -2718
- package/bundled-test-harness/assets/audio-file-def-bJ3cXVmC.js +0 -133
- package/bundled-test-harness/assets/avif-meta-extractor-CrSDfYEt.js +0 -162
- package/bundled-test-harness/assets/base64-image-C7UBjK5W.js +0 -262
- package/bundled-test-harness/assets/base64-image-CjWpxROT.js +0 -2
- package/bundled-test-harness/assets/big-integer-BBql7oGZ.js +0 -89
- package/bundled-test-harness/assets/big-integer-B_TrzRy_.js +0 -2
- package/bundled-test-harness/assets/binary-upload-dedupe-test-BiX8kS7D.js +0 -308
- package/bundled-test-harness/assets/boolean-9LNUUTfw.js +0 -2
- package/bundled-test-harness/assets/boolean-BAmK01TF.js +0 -94
- package/bundled-test-harness/assets/brand-functional-palette-CFuoS-LS.js +0 -137
- package/bundled-test-harness/assets/brand-logo-By89eknI.js +0 -295
- package/bundled-test-harness/assets/broken-link-template-test-odBriDSP.js +0 -192
- package/bundled-test-harness/assets/bundled-base-CLQkkmN4.js +0 -254
- package/bundled-test-harness/assets/bundled-base-modules-test-BYrTaTwa.js +0 -54
- package/bundled-test-harness/assets/buried-stack-item-scroll-test-DU4bM5nd.js +0 -236
- package/bundled-test-harness/assets/bxl-expression-test-Cs9JaZbC.js +0 -250
- package/bundled-test-harness/assets/can-invoke-test-ccMc06BU.js +0 -401
- package/bundled-test-harness/assets/card-api-Bn65NUT0.js +0 -8
- package/bundled-test-harness/assets/card-api-test-COrFXu2i.js +0 -198
- package/bundled-test-harness/assets/card-api-u1pOrwS6.js +0 -4393
- package/bundled-test-harness/assets/card-basics-test-D4rn3iN-.js +0 -5364
- package/bundled-test-harness/assets/card-chooser-paging-test-bZhdrUXt.js +0 -235
- package/bundled-test-harness/assets/card-chooser-test-D9w1duob.js +0 -393
- package/bundled-test-harness/assets/card-collection-ClCV-__1.js +0 -118
- package/bundled-test-harness/assets/card-context-search-results-H_rN3Upz.js +0 -30
- package/bundled-test-harness/assets/card-context-search-results-test-jciyaouV.js +0 -184
- package/bundled-test-harness/assets/card-def-field-def-relationships-test-BVZoQzM8.js +0 -562
- package/bundled-test-harness/assets/card-delete-test-CuLcZFnY.js +0 -466
- package/bundled-test-harness/assets/card-error-DIOivSkD.js +0 -72
- package/bundled-test-harness/assets/card-error-awaiting-index-test-JMwcRONq.js +0 -53
- package/bundled-test-harness/assets/card-error-detail-96jWBx6B.js +0 -271
- package/bundled-test-harness/assets/card-info-BxPtwG1h.js +0 -2
- package/bundled-test-harness/assets/card-list-B34qY3io.js +0 -2
- package/bundled-test-harness/assets/card-list-BpCaKkZJ.js +0 -202
- package/bundled-test-harness/assets/card-resource-DcPbIwH9.js +0 -86
- package/bundled-test-harness/assets/cards-grid-CTN8nBT_.js +0 -344
- package/bundled-test-harness/assets/cards-grid-Cx44vL-M.js +0 -2
- package/bundled-test-harness/assets/cards-grid-layout-BdL0Uzxl.js +0 -111
- package/bundled-test-harness/assets/cards-grid-layout-Dn8Yb4ma.js +0 -2
- package/bundled-test-harness/assets/check-correctness-test-BfMV-MC0.js +0 -554
- package/bundled-test-harness/assets/clip-CK6mVuyN.js +0 -92
- package/bundled-test-harness/assets/clip-CfXD1JTr.js +0 -2
- package/bundled-test-harness/assets/code-ref-85Bih6Zl.js +0 -138
- package/bundled-test-harness/assets/code-ref-DATHaoyt.js +0 -2
- package/bundled-test-harness/assets/code-submode-availability-test-DLYlx0wo.js +0 -198
- package/bundled-test-harness/assets/code-submode-test-CDIi7MjD.js +0 -1824
- package/bundled-test-harness/assets/codeblocks-test-CNPyTvuv.js +0 -418
- package/bundled-test-harness/assets/codemirror-editor-BPOPTR-f.js +0 -2
- package/bundled-test-harness/assets/codemirror-editor-DPhG0pec.js +0 -701
- package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Dk5lFOUq.js +0 -366
- package/bundled-test-harness/assets/color-BxN5gRSg.js +0 -65
- package/bundled-test-harness/assets/color-CrunRcis.js +0 -2
- package/bundled-test-harness/assets/color-field-test-COjFIpXV.js +0 -212
- package/bundled-test-harness/assets/color-picker-field-C-GS1CIw.js +0 -139
- package/bundled-test-harness/assets/color-picker-field-D3RXhbCK.js +0 -2
- package/bundled-test-harness/assets/color-wheel-picker-Bz8cBmf4.js +0 -283
- package/bundled-test-harness/assets/color-wheel-picker-DrwPrB8B.js +0 -2
- package/bundled-test-harness/assets/command-data-BxXgtNBf.js +0 -2
- package/bundled-test-harness/assets/command-data-ZdkcpEgG.js +0 -95
- package/bundled-test-harness/assets/compaction-test-DS7DTGT_.js +0 -150
- package/bundled-test-harness/assets/components-CbCTWAON.js +0 -17777
- package/bundled-test-harness/assets/computed-test-D_OrXDtR.js +0 -1320
- package/bundled-test-harness/assets/container-DDolu1gk.js +0 -11109
- package/bundled-test-harness/assets/container-DndcCIMv.css +0 -5169
- package/bundled-test-harness/assets/contains-many-component-BtgnAXih.js +0 -2
- package/bundled-test-harness/assets/contrast-checker-addon-kwtLKWdL.js +0 -2
- package/bundled-test-harness/assets/contrast-checker-addon-zFY5cen1.js +0 -71
- package/bundled-test-harness/assets/convert-to-class-name-test-BcGWl2K1.js +0 -17
- package/bundled-test-harness/assets/coordinate-D72EF1Pl.js +0 -48
- package/bundled-test-harness/assets/copy-file-to-realm-test-CYoDX4YV.js +0 -148
- package/bundled-test-harness/assets/country-B-iIe5v8.js +0 -199
- package/bundled-test-harness/assets/create-file-modal-PpvMksjR.js +0 -570
- package/bundled-test-harness/assets/create-listing-modal-test-CQtEf_UD.js +0 -273
- package/bundled-test-harness/assets/create-listing-pr-request-test-CDtKWyfk.js +0 -117
- package/bundled-test-harness/assets/create-spec-test-Cbqk8I9T.js +0 -256
- package/bundled-test-harness/assets/create-specs-CZg2cpnh.js +0 -215
- package/bundled-test-harness/assets/create-submission-workflow-test-CYrxF7bg.js +0 -132
- package/bundled-test-harness/assets/credential-fields-test-Di4jCJgU.js +0 -157
- package/bundled-test-harness/assets/css-value-CceJyI5o.js +0 -48
- package/bundled-test-harness/assets/csv-file-def-DJL2aZI9.js +0 -277
- package/bundled-test-harness/assets/currency-Bn5WIqzF.js +0 -134
- package/bundled-test-harness/assets/date-XI2CVYA2.js +0 -2
- package/bundled-test-harness/assets/date-h83UJcFR.js +0 -183
- package/bundled-test-harness/assets/date-time-fields-test-Cterr2mj.js +0 -359
- package/bundled-test-harness/assets/datetime-DadI80tC.js +0 -201
- package/bundled-test-harness/assets/datetime-Dpb_Sejj.js +0 -2
- package/bundled-test-harness/assets/datetime-stamp-C4vv397u.js +0 -81
- package/bundled-test-harness/assets/datetime-stamp-DIsJdQux.js +0 -2
- package/bundled-test-harness/assets/day-C4pZoGNM.js +0 -113
- package/bundled-test-harness/assets/day-D0goBhKb.js +0 -2
- package/bundled-test-harness/assets/debug-message-test-CV0sj-fl.js +0 -117
- package/bundled-test-harness/assets/dist-CAIttNZm.js +0 -1710
- package/bundled-test-harness/assets/dist-CLbqnmnm.js +0 -389
- package/bundled-test-harness/assets/dist-qkBOmIQy.js +0 -323
- package/bundled-test-harness/assets/docx-file-def-hz2tVQKf.js +0 -60
- package/bundled-test-harness/assets/docx-meta-extractor-CeRshlxL.js +0 -60
- package/bundled-test-harness/assets/docx-meta-extractor-muK5CKF3.js +0 -2
- package/bundled-test-harness/assets/duration-BYx1dLfm.js +0 -2
- package/bundled-test-harness/assets/duration-FAmTFeUa.js +0 -184
- package/bundled-test-harness/assets/email-D-bFy_C1.js +0 -80
- package/bundled-test-harness/assets/email-field-test-CY9K2zur.js +0 -75
- package/bundled-test-harness/assets/email-j4DZNH2-.js +0 -2
- package/bundled-test-harness/assets/enum-B7_baAn_.js +0 -167
- package/bundled-test-harness/assets/enum-BQqNzVQS.js +0 -2
- package/bundled-test-harness/assets/enum-field-test-BJ9Epz15.js +0 -953
- package/bundled-test-harness/assets/error-display-test-CbDWjJ2F.js +0 -343
- package/bundled-test-harness/assets/ethereum-address-BOLEnKsm.js +0 -78
- package/bundled-test-harness/assets/ethereum-address-s3Kvb2wG.js +0 -2
- package/bundled-test-harness/assets/expiration-warning-BaIP1MOZ.js +0 -2
- package/bundled-test-harness/assets/expiration-warning-gjEtxPk0.js +0 -90
- package/bundled-test-harness/assets/externals-Bih8ejPS.js +0 -4393
- package/bundled-test-harness/assets/fallback-banner-MlImHjSD.js +0 -24
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-Bm7IKXPf.js +0 -207
- package/bundled-test-harness/assets/fallback-banner-test-C7TGA0Ob.js +0 -53
- package/bundled-test-harness/assets/fallback-banner-test-lvuaVRXu.js +0 -225
- package/bundled-test-harness/assets/fallback-models-test-Dy7iIKUS.js +0 -161
- package/bundled-test-harness/assets/field-component-DBoOxTke.js +0 -2
- package/bundled-test-harness/assets/field-configuration-test-DnAnzyC-.js +0 -548
- package/bundled-test-harness/assets/field-edit-DdJ8Akso.js +0 -2
- package/bundled-test-harness/assets/field-edit-XAop92l8.js +0 -36
- package/bundled-test-harness/assets/field-markdown-domain-test-cZCqbcjj.js +0 -616
- package/bundled-test-harness/assets/field-markdown-oversize-test-BuATetVz.js +0 -88
- package/bundled-test-harness/assets/field-markdown-primitives-test-BsubQfhv.js +0 -365
- package/bundled-test-harness/assets/field-markdown-specialized-test-4eNLiYpF.js +0 -534
- package/bundled-test-harness/assets/field-test-helpers-9I7cHnaU.js +0 -45
- package/bundled-test-harness/assets/file-api-CC86I7Er.js +0 -7
- package/bundled-test-harness/assets/file-attachment-test-o9191GMb.js +0 -796
- package/bundled-test-harness/assets/file-chooser-panel-test-C8aZuJlk.js +0 -153
- package/bundled-test-harness/assets/file-chooser-test-B0Tn8CCR.js +0 -504
- package/bundled-test-harness/assets/file-def-edit-BSiF2Lje.js +0 -2
- package/bundled-test-harness/assets/file-def-edit-C5TYBp_q.js +0 -26
- package/bundled-test-harness/assets/file-def-embedded-BLVTCiVB.js +0 -2
- package/bundled-test-harness/assets/file-def-embedded-Bep4iD6s.js +0 -38
- package/bundled-test-harness/assets/file-def-fitted-BTs-AS78.js +0 -2
- package/bundled-test-harness/assets/file-def-fitted-DcPitdYu.js +0 -38
- package/bundled-test-harness/assets/file-def-isolated-Kg1YVhm-.js +0 -38
- package/bundled-test-harness/assets/file-def-isolated-tK5JWCam.js +0 -2
- package/bundled-test-harness/assets/file-def-serialization-test-D4wnd5XK.js +0 -89
- package/bundled-test-harness/assets/file-menu-items-CH4-naSK.js +0 -117
- package/bundled-test-harness/assets/file-menu-items-emUxx3ZI.js +0 -2
- package/bundled-test-harness/assets/file-preview-stage-B1McIWwu.js +0 -2
- package/bundled-test-harness/assets/file-preview-stage-BgZLNMN4.js +0 -72
- package/bundled-test-harness/assets/file-shell-embedded-BmfuwWfU.js +0 -2
- package/bundled-test-harness/assets/file-shell-embedded-zh8CJanA.js +0 -68
- package/bundled-test-harness/assets/file-shell-fitted-DSFUNRGJ.js +0 -2
- package/bundled-test-harness/assets/file-shell-fitted-DXKDH0fn.js +0 -98
- package/bundled-test-harness/assets/file-shell-isolated-0F1MFv4q.js +0 -2
- package/bundled-test-harness/assets/file-shell-isolated-DduZZzmi.js +0 -195
- package/bundled-test-harness/assets/file-tree-from-index-BzDvvUHy.js +0 -151
- package/bundled-test-harness/assets/file-tree-from-index-test-D0hfI4a1.js +0 -96
- package/bundled-test-harness/assets/film-BN_HVXBU.js +0 -13
- package/bundled-test-harness/assets/film-CKkbUi0L.js +0 -2
- package/bundled-test-harness/assets/film-CMNJITZ-.js +0 -4074
- package/bundled-test-harness/assets/fitted-CAvdcKpu.js +0 -34
- package/bundled-test-harness/assets/fitted-CbKOwd1u.js +0 -2
- package/bundled-test-harness/assets/flac-meta-extractor-e8qajPSl.js +0 -99
- package/bundled-test-harness/assets/font-file-def-9atde5W8.js +0 -64
- package/bundled-test-harness/assets/font-meta-extractor-IralDC8M.js +0 -303
- package/bundled-test-harness/assets/font-meta-extractor-zPBVOfoR.js +0 -2
- package/bundled-test-harness/assets/formatted-aibot-message-test-CWOiZUng.js +0 -109
- package/bundled-test-harness/assets/from-elsewhere-ChxbtsBa.js +0 -131
- package/bundled-test-harness/assets/frontmatter-field-cdig7KR9.js +0 -41
- package/bundled-test-harness/assets/garbage-collection-test-Dg-ww_Sb.js +0 -403
- package/bundled-test-harness/assets/gauge-B45nLOGe.js +0 -106
- package/bundled-test-harness/assets/gauge-BK-768BM.js +0 -2
- package/bundled-test-harness/assets/general-test-D7cn7PUr.js +0 -926
- package/bundled-test-harness/assets/get-relationship-membership-state-test-Skmj9V6y.js +0 -1308
- package/bundled-test-harness/assets/gif-meta-extractor-BychhK9q.js +0 -114
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-C09YUmk4.js +0 -160
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-DYskx_Kk.js +0 -74
- package/bundled-test-harness/assets/helper-BHX0HLF2.js +0 -478
- package/bundled-test-harness/assets/host-submode-test-Clw_QnvF.js +0 -1243
- package/bundled-test-harness/assets/html-file-def-C0P9giwU.js +0 -82
- package/bundled-test-harness/assets/hydratable-card-DnjrxKsT.js +0 -147
- package/bundled-test-harness/assets/hydratable-card-test-BAmWHfv1.js +0 -426
- package/bundled-test-harness/assets/icons-DBXBZgLe.js +0 -894
- package/bundled-test-harness/assets/image-Cip6ojDd.js +0 -47
- package/bundled-test-harness/assets/image-file-def-BdQxjZcN.js +0 -65
- package/bundled-test-harness/assets/image-file-def-DP4aqWcS.js +0 -3
- package/bundled-test-harness/assets/index-changes-test-D8b_56Ke.js +0 -367
- package/bundled-test-harness/assets/index-query-engine-test-CCyaUwMX.js +0 -2593
- package/bundled-test-harness/assets/inspector-test-BJTVGdOO.js +0 -1930
- package/bundled-test-harness/assets/instance-filter-matcher-test-DjsPrXL7.js +0 -788
- package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DSqM0vxh.js +0 -475
- package/bundled-test-harness/assets/interact-submode-setup-DF31UMX-.js +0 -566
- package/bundled-test-harness/assets/is-component-declaration-test-Did47eG9.js +0 -50
- package/bundled-test-harness/assets/iso-bmff-LuWkGL__.js +0 -205
- package/bundled-test-harness/assets/iso-bmff-_flO6c20.js +0 -2
- package/bundled-test-harness/assets/isolated-and-edit-frocLHin.js +0 -2
- package/bundled-test-harness/assets/job-priority-header-test-DHLAXfp7.js +0 -81
- package/bundled-test-harness/assets/job-scoped-instance-residency-test-C1Bt5j98.js +0 -103
- package/bundled-test-harness/assets/join-the-community-BBUSO2cs.js +0 -86
- package/bundled-test-harness/assets/jpg-meta-extractor-CoybO4Hq.js +0 -88
- package/bundled-test-harness/assets/json-field-8sdH5RQb.js +0 -2
- package/bundled-test-harness/assets/json-field-BDD3iTUh.js +0 -19
- package/bundled-test-harness/assets/json-file-def-BKibsfc6.js +0 -298
- package/bundled-test-harness/assets/last-modified-date-CR5jru2m.js +0 -43
- package/bundled-test-harness/assets/last-modified-date-test-jJ00YdTm.js +0 -28
- package/bundled-test-harness/assets/links-to-editor-rDoCYaN-.js +0 -2
- package/bundled-test-harness/assets/links-to-many-component-BqZT88Fb.js +0 -2
- package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-Cp1Eb_4U.js +0 -398
- package/bundled-test-harness/assets/linksto-error-sentinel-test-Bddavnh_.js +0 -238
- package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-c5WegXnR.js +0 -354
- package/bundled-test-harness/assets/linksto-many-per-slot-access-test-CWskzfGW.js +0 -303
- package/bundled-test-harness/assets/linksto-sentinel-reload-test-ByeVNhr8.js +0 -197
- package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-DP26i6Gb.js +0 -260
- package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-fDUXx8tO.js +0 -196
- package/bundled-test-harness/assets/llm-model-BcLEkTV7.js +0 -64
- package/bundled-test-harness/assets/login-CeuuNVvU.css +0 -139
- package/bundled-test-harness/assets/login-DV0WlJv-.js +0 -348
- package/bundled-test-harness/assets/login-error-text-test-BMGY_9gW.js +0 -51
- package/bundled-test-harness/assets/login-test-CL9YpMH5.js +0 -246
- package/bundled-test-harness/assets/m4a-meta-extractor-CHO1JQtb.js +0 -204
- package/bundled-test-harness/assets/main-CPLT8JNu.js +0 -5
- package/bundled-test-harness/assets/markdown-BvBALLGh.js +0 -7
- package/bundled-test-harness/assets/markdown-DFezmrFD.js +0 -2
- package/bundled-test-harness/assets/markdown-editor-mode-select-Au64bcIO.js +0 -2
- package/bundled-test-harness/assets/markdown-editor-mode-select-rK9PP8rv.js +0 -54
- package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-CIxizf5k.js +0 -470
- package/bundled-test-harness/assets/markdown-embed-preview-pane-test-C7GoNN7l.js +0 -447
- package/bundled-test-harness/assets/markdown-embed-preview-test-CDnj4uhd.js +0 -368
- package/bundled-test-harness/assets/markdown-fallback-n7PsLNmO.js +0 -2
- package/bundled-test-harness/assets/markdown-fallback-test-DTHT6OwQ.js +0 -316
- package/bundled-test-harness/assets/markdown-highlighting-test-DJ-4WSE_.js +0 -244
- package/bundled-test-harness/assets/markdown-preview-Ccelx5W-.js +0 -64
- package/bundled-test-harness/assets/markdown-preview-JXuMC_ve.js +0 -72
- package/bundled-test-harness/assets/markdown-preview-test-ByZqrpPk.js +0 -238
- package/bundled-test-harness/assets/markdown-skill-frontmatter-test-DAHGeL4K.js +0 -146
- package/bundled-test-harness/assets/menu-items-DzJm9H_H.js +0 -2
- package/bundled-test-harness/assets/message-tool-test-lmdrIEdY.js +0 -33
- package/bundled-test-harness/assets/metadata-fields-BZZr4Qe5.js +0 -2
- package/bundled-test-harness/assets/metadata-fields-BtdjGsKE.js +0 -1415
- package/bundled-test-harness/assets/midi-audio-def-uYbYFmFi.js +0 -52
- package/bundled-test-harness/assets/midi-meta-extractor-DNI5gc1q.js +0 -284
- package/bundled-test-harness/assets/midi-meta-extractor-DbKZ4fMG.js +0 -2
- package/bundled-test-harness/assets/migrate-skill-test-DI1xceiL.js +0 -161
- package/bundled-test-harness/assets/mini-CNoDyHqG.js +0 -1519
- package/bundled-test-harness/assets/mini-DexlIeKK.js +0 -85
- package/bundled-test-harness/assets/mini-card-chooser-test-DT5eIf1_.js +0 -272
- package/bundled-test-harness/assets/mini-file-chooser-test-DTQnKTZJ.js +0 -201
- package/bundled-test-harness/assets/missing-template-DL2mwddM.js +0 -2
- package/bundled-test-harness/assets/missing-template-ltqlJ4JC.js +0 -48
- package/bundled-test-harness/assets/modal-container-DRnt95-S.js +0 -40
- package/bundled-test-harness/assets/modal-zE95eEFp.js +0 -322
- package/bundled-test-harness/assets/model-cost-tier-test-CcFz7hcv.js +0 -173
- package/bundled-test-harness/assets/module-contents-service-Dk_zWt-V.js +0 -256
- package/bundled-test-harness/assets/month-BqReBYWo.js +0 -2
- package/bundled-test-harness/assets/month-RhvmIp40.js +0 -123
- package/bundled-test-harness/assets/month-day-XFAQA72z.js +0 -2
- package/bundled-test-harness/assets/month-day-XzKpk6nz.js +0 -192
- package/bundled-test-harness/assets/month-year-BeuNr2Cl.js +0 -2
- package/bundled-test-harness/assets/month-year-DhU7hATV.js +0 -93
- package/bundled-test-harness/assets/mp3-meta-extractor-Dx2RnJc5.js +0 -476
- package/bundled-test-harness/assets/mp4-meta-extractor--k0m8KsT.js +0 -188
- package/bundled-test-harness/assets/multiple-stacks-test-bC24IWcJ.js +0 -208
- package/bundled-test-harness/assets/nested-query-field-render-test-qxElXx1e.js +0 -249
- package/bundled-test-harness/assets/no-stacks-test-Br7IGAgV.js +0 -48
- package/bundled-test-harness/assets/number-73SsCMEF.js +0 -3
- package/bundled-test-harness/assets/number-CicTBWQd.js +0 -151
- package/bundled-test-harness/assets/number-field-test-kV5zXo1J.js +0 -184
- package/bundled-test-harness/assets/number-input-CQy4xUeA.js +0 -82
- package/bundled-test-harness/assets/office-extract-Bo8sbNkK.js +0 -27
- package/bundled-test-harness/assets/office-extract-CfBaoRMD.js +0 -2
- package/bundled-test-harness/assets/ogg-meta-extractor-aIf5q_Rq.js +0 -225
- package/bundled-test-harness/assets/on-key-C8acaldQ.js +0 -472
- package/bundled-test-harness/assets/ooxml-Bu3iZezv.js +0 -172
- package/bundled-test-harness/assets/ooxml-jQPBQK25.js +0 -2
- package/bundled-test-harness/assets/open-image-in-new-tab-test-CP7q3kMm.js +0 -52
- package/bundled-test-harness/assets/operation-lowering-test-9Mdr0hRT.js +0 -2812
- package/bundled-test-harness/assets/operations-R9b661Qn.js +0 -3
- package/bundled-test-harness/assets/operations-Zv_V3Api.js +0 -766
- package/bundled-test-harness/assets/operations-invocation-test-BJPpWb2H.js +0 -523
- package/bundled-test-harness/assets/operations-query-test-DufdmPQF.js +0 -459
- package/bundled-test-harness/assets/operations-test-CzT051YH.js +0 -2518
- package/bundled-test-harness/assets/operator-mode-acceptance-test-ByOIOcD0.js +0 -1188
- package/bundled-test-harness/assets/operator-mode-card-chooser-test-CNhR9mvv.js +0 -1036
- package/bundled-test-harness/assets/operator-mode-links-test-CuxSVTPR.js +0 -793
- package/bundled-test-harness/assets/operator-mode-state-service-CCeHt5SH.js +0 -1275
- package/bundled-test-harness/assets/operator-mode-state-service-test-C8TI9WWg.js +0 -206
- package/bundled-test-harness/assets/operator-mode-test-DG-mG8Tn.js +0 -683
- package/bundled-test-harness/assets/operator-mode-ui-test-DB7xhjS0.js +0 -1027
- package/bundled-test-harness/assets/overlay-menu-items-test-C6rcdF_S.js +0 -317
- package/bundled-test-harness/assets/overlays-D2zmPxzK.js +0 -270
- package/bundled-test-harness/assets/overlays-clip-test-Clpq3JzQ.js +0 -91
- package/bundled-test-harness/assets/overlays-detached-element-test-BtsTeJch.js +0 -56
- package/bundled-test-harness/assets/pane-f-IYhcWT.js +0 -330
- package/bundled-test-harness/assets/panel-B3PCSBbf.js +0 -3540
- package/bundled-test-harness/assets/panel-Ban7zCBP.js +0 -474
- package/bundled-test-harness/assets/past-sessions-test-uM2m-oKV.js +0 -321
- package/bundled-test-harness/assets/patch-fields-test-COPjDhnt.js +0 -1014
- package/bundled-test-harness/assets/patch-instance-test-CRb3dfby.js +0 -348
- package/bundled-test-harness/assets/pdf-file-def-J_yOUU8_.js +0 -76
- package/bundled-test-harness/assets/pdf-meta-extractor-83T5Bdo7.js +0 -156
- package/bundled-test-harness/assets/pdf-meta-extractor-INFIklMy.js +0 -2
- package/bundled-test-harness/assets/pdf-viewer-B4rRluWA.js +0 -2
- package/bundled-test-harness/assets/pdf-viewer-vYem8ozk.js +0 -112
- package/bundled-test-harness/assets/percentage-ChagfNRG.js +0 -84
- package/bundled-test-harness/assets/permission-checking-realm-test-Dmb2a428.js +0 -306
- package/bundled-test-harness/assets/phone-number-BiD2eaSd.js +0 -236
- package/bundled-test-harness/assets/phone-number-C-wt4_UK.js +0 -2
- package/bundled-test-harness/assets/phone-number-field-test-BHzAmuBP.js +0 -73
- package/bundled-test-harness/assets/plate-CqN2nM6P.js +0 -41
- package/bundled-test-harness/assets/plate-DaIfpORN.js +0 -2
- package/bundled-test-harness/assets/player-CGt5fTd5.js +0 -2
- package/bundled-test-harness/assets/player-CN0l44LK.js +0 -82
- package/bundled-test-harness/assets/plural-field-components-test-CO2g2opW.js +0 -198
- package/bundled-test-harness/assets/png-image-def-B_oou2wS.js +0 -48
- package/bundled-test-harness/assets/png-meta-extractor-BfPz1qP_.js +0 -2
- package/bundled-test-harness/assets/png-meta-extractor-C8ai8sPw.js +0 -111
- package/bundled-test-harness/assets/policy-scoped-search-test-BRRp2a1A.js +0 -339
- package/bundled-test-harness/assets/pptx-file-def-C3qYEHDM.js +0 -60
- package/bundled-test-harness/assets/pptx-meta-extractor-8IuoBq4I.js +0 -77
- package/bundled-test-harness/assets/pptx-meta-extractor-BPhy9RMM.js +0 -2
- package/bundled-test-harness/assets/prerender-persistence-block-test-Cteb_Rs_.js +0 -124
- package/bundled-test-harness/assets/prerender-serialize-cycle-test-CH7b6Ra9.js +0 -134
- package/bundled-test-harness/assets/preview-CmERZpI6.js +0 -74
- package/bundled-test-harness/assets/preview-format-BPMlCSbb.js +0 -41
- package/bundled-test-harness/assets/preview-format-test-B7sA8fbZ.js +0 -103
- package/bundled-test-harness/assets/process-card-CtDzDB-_.js +0 -2
- package/bundled-test-harness/assets/process-card-erbWKY5h.js +0 -114
- package/bundled-test-harness/assets/process-card-test-DXOt1jDW.js +0 -94
- package/bundled-test-harness/assets/profile-settings-modal-11BrR058.js +0 -708
- package/bundled-test-harness/assets/progress-circle-Cd79Zqh2.js +0 -2
- package/bundled-test-harness/assets/progress-circle-sc-W5aUl.js +0 -95
- package/bundled-test-harness/assets/quarter-B61kCpcD.js +0 -168
- package/bundled-test-harness/assets/quarter-d5jkTzcz.js +0 -2
- package/bundled-test-harness/assets/query-field-membership-status-test-BmpVfohw.js +0 -323
- package/bundled-test-harness/assets/query-field-page-optin-test-9_Cce-OJ.js +0 -126
- package/bundled-test-harness/assets/query-field-schema-test-CwV7xanX.js +0 -231
- package/bundled-test-harness/assets/query-field-stale-prerender-test-RkdnZ-VV.js +0 -152
- package/bundled-test-harness/assets/query-fields-test-BLxYkTAM.js +0 -535
- package/bundled-test-harness/assets/rail-CFPU0tFe.js +0 -2
- package/bundled-test-harness/assets/rail-CQ53Dakr.js +0 -44
- package/bundled-test-harness/assets/realm-DdVH9lSZ.js +0 -95
- package/bundled-test-harness/assets/realm-DdsFw3b-.js +0 -2
- package/bundled-test-harness/assets/realm-config-DIslxoB7.js +0 -844
- package/bundled-test-harness/assets/realm-config-policy-standing-test-b4WxNDor.js +0 -290
- package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-C-rcvkkD.js +0 -274
- package/bundled-test-harness/assets/realm-config-settings-test-DDUkM3zw.js +0 -187
- package/bundled-test-harness/assets/realm-dropdown-1j55Dy-1.js +0 -560
- package/bundled-test-harness/assets/realm-field-test-D-uEtFKO.js +0 -100
- package/bundled-test-harness/assets/realm-indexing-test-U9m0epR-.js +0 -4380
- package/bundled-test-harness/assets/realm-policy-test-DhKabhlk.js +0 -1141
- package/bundled-test-harness/assets/realm-test-BX6C9SS5.js +0 -2363
- package/bundled-test-harness/assets/realm-url-tooltip-BjjcKqBx.js +0 -56
- package/bundled-test-harness/assets/realm-url-tooltip-test-DW0ZwEEE.js +0 -78
- package/bundled-test-harness/assets/reasoning-test-BWT94KXG.js +0 -234
- package/bundled-test-harness/assets/recent-colors-addon-CfgmgilF.js +0 -61
- package/bundled-test-harness/assets/recent-colors-addon-D--Ry3Pf.js +0 -2
- package/bundled-test-harness/assets/relationship-loading-state-test-C5R6jao_.js +0 -290
- package/bundled-test-harness/assets/relative-time-Bq7pqums.js +0 -2
- package/bundled-test-harness/assets/relative-time-D0QyW4ig.js +0 -129
- package/bundled-test-harness/assets/remix-card-test-Cy0h3Xdf.js +0 -58
- package/bundled-test-harness/assets/rendered-markdown-Hw_EF8SO.js +0 -263
- package/bundled-test-harness/assets/rendered-markdown-test-CqeF-UZd.js +0 -587
- package/bundled-test-harness/assets/resident-instance-reuse-test-BiI6L40n.js +0 -82
- package/bundled-test-harness/assets/response-field-BCxG5phG.js +0 -38
- package/bundled-test-harness/assets/result-tile-DMzRnTP8.js +0 -140
- package/bundled-test-harness/assets/rich-markdown-C4RUl7L0.js +0 -2
- package/bundled-test-harness/assets/rich-markdown-DxQSCg-o.js +0 -218
- package/bundled-test-harness/assets/rich-markdown-field-test-B7wpedKs.js +0 -1647
- package/bundled-test-harness/assets/room-D0M0Zwrs.js +0 -1008
- package/bundled-test-harness/assets/room-message-test-BWWd4xC8.js +0 -445
- package/bundled-test-harness/assets/room-test-DFH-nOwi.js +0 -95
- package/bundled-test-harness/assets/run-realm-code-DyVyEDBl.js +0 -1600
- package/bundled-test-harness/assets/run-realm-code-test-BpxF-tOz.js +0 -2468
- package/bundled-test-harness/assets/schema-generation-test-DjaJqpYP.js +0 -28
- package/bundled-test-harness/assets/score-Cfp34BE7.js +0 -2
- package/bundled-test-harness/assets/score-DIWWpeyf.js +0 -100
- package/bundled-test-harness/assets/scrolling-test-hA_uBwBg.js +0 -384
- package/bundled-test-harness/assets/search-C0-b7dJI.js +0 -605
- package/bundled-test-harness/assets/search-adorn-test-C6KP3AwA.js +0 -136
- package/bundled-test-harness/assets/search-entries-BfPq5sPS.js +0 -472
- package/bundled-test-harness/assets/search-entries-result-test-Bl9u_BOD.js +0 -234
- package/bundled-test-harness/assets/search-entries-test-BDC_lS43.js +0 -1486
- package/bundled-test-harness/assets/search-result-header-DCAze_cg.js +0 -128
- package/bundled-test-harness/assets/search-results-Dd0enVun.js +0 -266
- package/bundled-test-harness/assets/search-results-test-T5KEEII4.js +0 -578
- package/bundled-test-harness/assets/search-selection-menu-test-CCssnBq1.js +0 -108
- package/bundled-test-harness/assets/search-sheet-persistence-test-BzQiO-FK.js +0 -131
- package/bundled-test-harness/assets/search-test-fyCWb24m.js +0 -2241
- package/bundled-test-harness/assets/searchable-BkgeKQMl.js +0 -2
- package/bundled-test-harness/assets/searchable-D_6p6fyb.js +0 -192
- package/bundled-test-harness/assets/searchable-option-test-CnCUYGaq.js +0 -322
- package/bundled-test-harness/assets/searchable-search-doc-test-B8Q0D98v.js +0 -1271
- package/bundled-test-harness/assets/sending-test-D5PGBDys.js +0 -576
- package/bundled-test-harness/assets/serialization-rri-form-audit-test-BRJ1cJ31.js +0 -136
- package/bundled-test-harness/assets/serialization-test-DM6hK258.js +0 -8758
- package/bundled-test-harness/assets/setup-C_GgVgzM.js +0 -772
- package/bundled-test-harness/assets/shared-link-target-reuse-test-Be-lSKib.js +0 -207
- package/bundled-test-harness/assets/show-card-BFG6KR1m.js +0 -67
- package/bundled-test-harness/assets/show-card-test-l0wMrfZq.js +0 -365
- package/bundled-test-harness/assets/show-file-B8-FRVHj.js +0 -34
- package/bundled-test-harness/assets/signed-capture-D_Q44TQ7.js +0 -204
- package/bundled-test-harness/assets/signed-capture-link-test-DOS5xpYv.js +0 -132
- package/bundled-test-harness/assets/single-stack-test-BIEtzHVS.js +0 -652
- package/bundled-test-harness/assets/skill-BUTGmSsm.js +0 -76
- package/bundled-test-harness/assets/skill-Bo7R_2Ud.js +0 -3
- package/bundled-test-harness/assets/skill-reference-Cs64py3k.js +0 -112
- package/bundled-test-harness/assets/skills-test-CXxSIkYa.js +0 -648
- package/bundled-test-harness/assets/slider-picker-C81errGI.js +0 -245
- package/bundled-test-harness/assets/slider-picker-mvKsy6cR.js +0 -2
- package/bundled-test-harness/assets/spec-B55lJurX.js +0 -602
- package/bundled-test-harness/assets/store-DyQ0KiyI.js +0 -2205
- package/bundled-test-harness/assets/store-module-rebuild-test-C7532_bS.js +0 -454
- package/bundled-test-harness/assets/store-search-test-80NMJuoW.js +0 -175
- package/bundled-test-harness/assets/store-test-dHiWXXMs.js +0 -3460
- package/bundled-test-harness/assets/string-DHlQEHYm.js +0 -9
- package/bundled-test-harness/assets/submode-switcher-DQv-CD6G.js +0 -169
- package/bundled-test-harness/assets/svg-meta-extractor-Uw_EJytF.js +0 -42
- package/bundled-test-harness/assets/swatches-picker-CaEoibN1.js +0 -33
- package/bundled-test-harness/assets/swatches-picker-gPl50JbP.js +0 -2
- package/bundled-test-harness/assets/switch-submode-BKDnJd4m.js +0 -79
- package/bundled-test-harness/assets/switch-submode-test-_E2mVk4z.js +0 -168
- package/bundled-test-harness/assets/tag-B60lDr-j.js +0 -105
- package/bundled-test-harness/assets/tests-BBBgPBB6.js +0 -3520
- package/bundled-test-harness/assets/text-area-CJjWmwpi.js +0 -9
- package/bundled-test-harness/assets/text-file-def-u_dl0i2z.js +0 -151
- package/bundled-test-harness/assets/text-input-validator-test-BTwnkSS2.js +0 -156
- package/bundled-test-harness/assets/theme-BK-fAHVn.js +0 -9
- package/bundled-test-harness/assets/theme-card-test-BQmT7rqr.js +0 -621
- package/bundled-test-harness/assets/theme-scheme-island-test-Oi3aeyp1.js +0 -264
- package/bundled-test-harness/assets/three-d-model-def-B4KckPVC.js +0 -70
- package/bundled-test-harness/assets/time-BcuaSkHg.js +0 -126
- package/bundled-test-harness/assets/time-f7Irg7Z7.js +0 -2
- package/bundled-test-harness/assets/time-slots-ClYIZN53.js +0 -2
- package/bundled-test-harness/assets/time-slots-TI1aaqRN.js +0 -85
- package/bundled-test-harness/assets/timeline-Cof9eyq0.js +0 -59
- package/bundled-test-harness/assets/timeline-DFWQtCWE.js +0 -2
- package/bundled-test-harness/assets/to-device-streaming-test-BDrUUlOt.js +0 -163
- package/bundled-test-harness/assets/token-usage-test-CiZo03fY.js +0 -166
- package/bundled-test-harness/assets/tool-field-BXHr9r0w.js +0 -94
- package/bundled-test-harness/assets/tool-field-CoRO5C4R.js +0 -2
- package/bundled-test-harness/assets/tools-CmVaYDIS.js +0 -725
- package/bundled-test-harness/assets/tools-calling-test-B454__XF.js +0 -200
- package/bundled-test-harness/assets/tools-test-CLu51dJO.js +0 -1624
- package/bundled-test-harness/assets/tools-test-XGRAvVug.js +0 -2820
- package/bundled-test-harness/assets/ts-file-def-C05BDwdg.js +0 -159
- package/bundled-test-harness/assets/update-room-skills-test-jOvP14JX.js +0 -240
- package/bundled-test-harness/assets/url-BFf2CNo-.js +0 -2
- package/bundled-test-harness/assets/url-CYm-CeXp.js +0 -96
- package/bundled-test-harness/assets/video-file-def-B2UIrOFS.js +0 -76
- package/bundled-test-harness/assets/wav-meta-extractor-BNkv7e2f.js +0 -368
- package/bundled-test-harness/assets/webm-meta-extractor-C933kYyc.js +0 -178
- package/bundled-test-harness/assets/webp-meta-extractor-BLz0z1pZ.js +0 -98
- package/bundled-test-harness/assets/website-BuOMUW1v.js +0 -92
- package/bundled-test-harness/assets/week-Bo0666ji.js +0 -111
- package/bundled-test-harness/assets/week-CaVFA8Vc.js +0 -2
- package/bundled-test-harness/assets/welcome-to-boxel-PWard7GF.js +0 -172
- package/bundled-test-harness/assets/workspace-KXfFTQNV.js +0 -614
- package/bundled-test-harness/assets/workspace-a11y-test-Buwb-rfO.js +0 -197
- package/bundled-test-harness/assets/workspace-behavior-test-CbgFUOOo.js +0 -200
- package/bundled-test-harness/assets/workspace-chooser-BmQvhhrl.js +0 -2248
- package/bundled-test-harness/assets/workspace-chooser-Cu84Gd_E.css +0 -1317
- package/bundled-test-harness/assets/workspace-chooser-catalog-order-test-rcRw6sni.js +0 -36
- package/bundled-test-harness/assets/workspace-chooser-unreachable-notice-test-DUXnBIdY.js +0 -60
- package/bundled-test-harness/assets/workspace-delete-multiple-test-DjRKhZ2g.js +0 -212
- package/bundled-test-harness/assets/workspace-delete-summary-test-CvkLVYyN.js +0 -63
- package/bundled-test-harness/assets/workspace-timestamp-labels-test-AYJT4inv.js +0 -58
- package/bundled-test-harness/assets/xlsx-file-def-DuKdbGrJ.js +0 -60
- package/bundled-test-harness/assets/xlsx-meta-extractor-Bz-C2JWP.js +0 -101
- package/bundled-test-harness/assets/xlsx-meta-extractor-ClwwgABg.js +0 -2
- package/bundled-test-harness/assets/year-B6ctHikl.js +0 -2
- package/bundled-test-harness/assets/year-C11uAQE6.js +0 -78
- package/bundled-test-harness/assets/zip-file-def-B8XN-OS_.js +0 -288
- package/bundled-types/host-app/components/matrix/auth-button.gts +0 -39
- package/bundled-types/host-app/components/matrix/auth-container.gts +0 -69
- package/bundled-types/host-app/components/matrix/auth-form-field.gts +0 -43
|
@@ -0,0 +1,2241 @@
|
|
|
1
|
+
import { s as __toESM } from "./chunk-Rp0pCe6z.js";
|
|
2
|
+
import { r as initializeDeferredDecorator, t as decorateFieldV2 } from "./runtime--fcdnjmJ-BoCBNIsz.js";
|
|
3
|
+
import { Ar as testRealmURL, Dr as testRRI, Ro as isFileDefInstance, Sc as Deferred, _t as buildQuerySearchURL, ai as SEARCH_CONCURRENCY_CAP, ii as QUERY_FIELD_SEARCH_CONCURRENCY_CAP, oi as SearchBoundError } from "./runtime-common-ClpqhbwG.js";
|
|
4
|
+
import { y as rri } from "./paths-BYHDgqsT.js";
|
|
5
|
+
import { D as baseRealm, E as baseRRI } from "./constants-CqKWhRfY.js";
|
|
6
|
+
import { t as config } from "./environment-DIUJgBKt.js";
|
|
7
|
+
import { r as setOwner } from "./owner-CP0__uFm.js";
|
|
8
|
+
import { t as getOwner } from "./owner-BT6cj890.js";
|
|
9
|
+
import { Tn as destroy } from "./cache-DtDz7X5V-Wn8jRDfL.js";
|
|
10
|
+
import { ht as run } from "./service-LFpJ8EEP.js";
|
|
11
|
+
import "./destroyable-mdLYRn_o.js";
|
|
12
|
+
import { l as RealmService } from "./card-prerender-Dke537bN.js";
|
|
13
|
+
import { t as SearchResource } from "./search-BkQYpQDY.js";
|
|
14
|
+
import { M as waitUntil, T as settled } from "./dist-BOAdzfkP.js";
|
|
15
|
+
import { t as require_qunit } from "./qunit-C-Foo4Nd.js";
|
|
16
|
+
import { F as setupLocalIndexing, L as setupRealmCacheTeardown, P as setupIntegrationTestRealm, Z as withCachedRealmSetup, lt as setupRenderingTest, t as setupMockMatrix } from "./mock-matrix-DPQ0j2MD.js";
|
|
17
|
+
import { r as getService } from "./dist-CPfIHBla.js";
|
|
18
|
+
//#region tests/integration/resources/search-test.ts
|
|
19
|
+
var import_qunit = /* @__PURE__ */ __toESM(require_qunit());
|
|
20
|
+
var StubRealmService = class extends RealmService {
|
|
21
|
+
realmOf(_input) {
|
|
22
|
+
return testRealmURL;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
function getSearchResourceForTest(owner, args) {
|
|
26
|
+
return SearchResource.from(owner, args);
|
|
27
|
+
}
|
|
28
|
+
(0, import_qunit.module)(`Integration | search resource`, function(hooks) {
|
|
29
|
+
let loader;
|
|
30
|
+
let loaderService;
|
|
31
|
+
let storeService;
|
|
32
|
+
let realm;
|
|
33
|
+
let cardApi;
|
|
34
|
+
let string;
|
|
35
|
+
setupRenderingTest(hooks);
|
|
36
|
+
hooks.beforeEach(function() {
|
|
37
|
+
getOwner(this).register("service:realm", StubRealmService);
|
|
38
|
+
loaderService = getService("loader-service");
|
|
39
|
+
loader = loaderService.loader;
|
|
40
|
+
storeService = getService("store");
|
|
41
|
+
});
|
|
42
|
+
setupLocalIndexing(hooks);
|
|
43
|
+
setupRealmCacheTeardown(hooks);
|
|
44
|
+
let mockMatrixUtils = setupMockMatrix(hooks, {
|
|
45
|
+
loggedInAs: "@testuser:localhost",
|
|
46
|
+
activeRealms: [baseRealm.url, testRealmURL],
|
|
47
|
+
autostart: true
|
|
48
|
+
});
|
|
49
|
+
hooks.beforeEach(async function() {
|
|
50
|
+
cardApi = await loader.import("@cardstack/base/card-api");
|
|
51
|
+
string = await loader.import("@cardstack/base/string");
|
|
52
|
+
let { contains, field, CardDef, FieldDef, linksTo } = cardApi;
|
|
53
|
+
let { default: StringField } = string;
|
|
54
|
+
class PersonField extends FieldDef {
|
|
55
|
+
static {
|
|
56
|
+
decorateFieldV2(this.prototype, "firstName", [field], function() {
|
|
57
|
+
return contains(StringField);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
#firstName = (initializeDeferredDecorator(this, "firstName"), void 0);
|
|
61
|
+
static {
|
|
62
|
+
decorateFieldV2(this.prototype, "lastName", [field], function() {
|
|
63
|
+
return contains(StringField);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
#lastName = (initializeDeferredDecorator(this, "lastName"), void 0);
|
|
67
|
+
}
|
|
68
|
+
class Article extends CardDef {
|
|
69
|
+
static displayName = "Article";
|
|
70
|
+
static {
|
|
71
|
+
decorateFieldV2(this.prototype, "author", [field], function() {
|
|
72
|
+
return contains(PersonField);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
#author = (initializeDeferredDecorator(this, "author"), void 0);
|
|
76
|
+
}
|
|
77
|
+
class Post extends CardDef {
|
|
78
|
+
static displayName = "Post";
|
|
79
|
+
static {
|
|
80
|
+
decorateFieldV2(this.prototype, "article", [field], function() {
|
|
81
|
+
return linksTo(Article);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
#article = (initializeDeferredDecorator(this, "article"), void 0);
|
|
85
|
+
static {
|
|
86
|
+
decorateFieldV2(this.prototype, "cardTitle", [field], function() {
|
|
87
|
+
return contains(StringField);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
#cardTitle = (initializeDeferredDecorator(this, "cardTitle"), void 0);
|
|
91
|
+
}
|
|
92
|
+
class BlogPost extends Post {
|
|
93
|
+
static displayName = "BlogPost";
|
|
94
|
+
static {
|
|
95
|
+
decorateFieldV2(this.prototype, "article", [field], function() {
|
|
96
|
+
return linksTo(Article);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
#article = (initializeDeferredDecorator(this, "article"), void 0);
|
|
100
|
+
}
|
|
101
|
+
class Book extends CardDef {
|
|
102
|
+
static displayName = "Book";
|
|
103
|
+
static {
|
|
104
|
+
decorateFieldV2(this.prototype, "author", [field], function() {
|
|
105
|
+
return contains(PersonField);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
#author = (initializeDeferredDecorator(this, "author"), void 0);
|
|
109
|
+
}
|
|
110
|
+
const sampleCards = {
|
|
111
|
+
"card-1.json": { data: {
|
|
112
|
+
type: "card",
|
|
113
|
+
attributes: {
|
|
114
|
+
cardTitle: "Card 1",
|
|
115
|
+
cardDescription: "Sample post",
|
|
116
|
+
author: {
|
|
117
|
+
firstName: "Cardy",
|
|
118
|
+
lastName: "Stackington Jr. III"
|
|
119
|
+
},
|
|
120
|
+
views: 0
|
|
121
|
+
},
|
|
122
|
+
meta: { adoptsFrom: {
|
|
123
|
+
module: testRRI("article"),
|
|
124
|
+
name: "Article"
|
|
125
|
+
} }
|
|
126
|
+
} },
|
|
127
|
+
"card-2.json": { data: {
|
|
128
|
+
type: "card",
|
|
129
|
+
attributes: {
|
|
130
|
+
author: {
|
|
131
|
+
firstName: "Cardy",
|
|
132
|
+
lastName: "Jones"
|
|
133
|
+
},
|
|
134
|
+
editions: 1,
|
|
135
|
+
pubDate: "2023-09-01"
|
|
136
|
+
},
|
|
137
|
+
meta: { adoptsFrom: {
|
|
138
|
+
module: testRRI("book"),
|
|
139
|
+
name: "Book"
|
|
140
|
+
} }
|
|
141
|
+
} },
|
|
142
|
+
"cards/1.json": { data: {
|
|
143
|
+
type: "card",
|
|
144
|
+
attributes: {
|
|
145
|
+
cardTitle: "Card 1",
|
|
146
|
+
cardDescription: "Sample post",
|
|
147
|
+
author: {
|
|
148
|
+
firstName: "Carl",
|
|
149
|
+
lastName: "Stack",
|
|
150
|
+
posts: 1
|
|
151
|
+
},
|
|
152
|
+
createdAt: new Date(2022, 7, 1),
|
|
153
|
+
views: 10
|
|
154
|
+
},
|
|
155
|
+
meta: { adoptsFrom: {
|
|
156
|
+
module: testRRI("post"),
|
|
157
|
+
name: "Post"
|
|
158
|
+
} }
|
|
159
|
+
} },
|
|
160
|
+
"cards/2.json": { data: {
|
|
161
|
+
type: "card",
|
|
162
|
+
attributes: {
|
|
163
|
+
cardTitle: "Card 2",
|
|
164
|
+
cardDescription: "Sample post",
|
|
165
|
+
author: {
|
|
166
|
+
firstName: "Carl",
|
|
167
|
+
lastName: "Deck",
|
|
168
|
+
posts: 3
|
|
169
|
+
},
|
|
170
|
+
createdAt: new Date(2022, 7, 22),
|
|
171
|
+
views: 5
|
|
172
|
+
},
|
|
173
|
+
meta: { adoptsFrom: {
|
|
174
|
+
module: testRRI("article"),
|
|
175
|
+
name: "Article"
|
|
176
|
+
} }
|
|
177
|
+
} },
|
|
178
|
+
"books/1.json": { data: {
|
|
179
|
+
type: "card",
|
|
180
|
+
attributes: {
|
|
181
|
+
author: {
|
|
182
|
+
firstName: "Mango",
|
|
183
|
+
lastName: "Abdel-Rahman"
|
|
184
|
+
},
|
|
185
|
+
editions: 1,
|
|
186
|
+
pubDate: "2022-07-01"
|
|
187
|
+
},
|
|
188
|
+
meta: { adoptsFrom: {
|
|
189
|
+
module: testRRI("book"),
|
|
190
|
+
name: "Book"
|
|
191
|
+
} }
|
|
192
|
+
} },
|
|
193
|
+
"books/2.json": { data: {
|
|
194
|
+
type: "card",
|
|
195
|
+
attributes: {
|
|
196
|
+
author: {
|
|
197
|
+
firstName: "Van Gogh",
|
|
198
|
+
lastName: "Abdel-Rahman"
|
|
199
|
+
},
|
|
200
|
+
editions: 0,
|
|
201
|
+
pubDate: "2023-08-01"
|
|
202
|
+
},
|
|
203
|
+
meta: { adoptsFrom: {
|
|
204
|
+
module: testRRI("book"),
|
|
205
|
+
name: "Book"
|
|
206
|
+
} }
|
|
207
|
+
} },
|
|
208
|
+
"books/3.json": { data: {
|
|
209
|
+
type: "card",
|
|
210
|
+
attributes: {
|
|
211
|
+
author: {
|
|
212
|
+
firstName: "Jackie",
|
|
213
|
+
lastName: "Aguilar"
|
|
214
|
+
},
|
|
215
|
+
editions: 2,
|
|
216
|
+
pubDate: "2022-08-01"
|
|
217
|
+
},
|
|
218
|
+
meta: { adoptsFrom: {
|
|
219
|
+
module: testRRI("book"),
|
|
220
|
+
name: "Book"
|
|
221
|
+
} }
|
|
222
|
+
} },
|
|
223
|
+
"spec-1.json": { data: {
|
|
224
|
+
type: "card",
|
|
225
|
+
attributes: {
|
|
226
|
+
cardTitle: "Post",
|
|
227
|
+
cardDescription: "A card that represents a blog post",
|
|
228
|
+
specType: "card",
|
|
229
|
+
ref: {
|
|
230
|
+
module: testRRI("post"),
|
|
231
|
+
name: "Post"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
meta: { adoptsFrom: {
|
|
235
|
+
module: baseRRI("spec"),
|
|
236
|
+
name: "Spec"
|
|
237
|
+
} }
|
|
238
|
+
} },
|
|
239
|
+
"spec-2.json": { data: {
|
|
240
|
+
type: "card",
|
|
241
|
+
attributes: {
|
|
242
|
+
cardTitle: "Article",
|
|
243
|
+
cardDescription: "A card that represents an online article ",
|
|
244
|
+
specType: "card",
|
|
245
|
+
ref: {
|
|
246
|
+
module: testRRI("article"),
|
|
247
|
+
name: "Article"
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
meta: { adoptsFrom: {
|
|
251
|
+
module: baseRRI("spec"),
|
|
252
|
+
name: "Spec"
|
|
253
|
+
} }
|
|
254
|
+
} }
|
|
255
|
+
};
|
|
256
|
+
await withCachedRealmSetup(async () => {
|
|
257
|
+
({realm} = await setupIntegrationTestRealm({
|
|
258
|
+
mockMatrixUtils,
|
|
259
|
+
contents: {
|
|
260
|
+
"person-field.gts": { PersonField },
|
|
261
|
+
"article.gts": { Article },
|
|
262
|
+
"blog-post.gts": { BlogPost },
|
|
263
|
+
"book.gts": { Book },
|
|
264
|
+
"post.gts": { Post },
|
|
265
|
+
...sampleCards,
|
|
266
|
+
"files/hello.txt": "Hello world",
|
|
267
|
+
"files/notes.txt": "Some notes"
|
|
268
|
+
}
|
|
269
|
+
}));
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
(0, import_qunit.test)(`can search for card instances by using the 'eq' filter`, async function(assert) {
|
|
273
|
+
let query = { filter: {
|
|
274
|
+
on: {
|
|
275
|
+
module: testRRI("book"),
|
|
276
|
+
name: "Book"
|
|
277
|
+
},
|
|
278
|
+
eq: { "author.lastName": "Jones" }
|
|
279
|
+
} };
|
|
280
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
281
|
+
query,
|
|
282
|
+
realms: [testRealmURL],
|
|
283
|
+
isLive: false,
|
|
284
|
+
isAutoSaved: false,
|
|
285
|
+
storeService,
|
|
286
|
+
owner: this.owner
|
|
287
|
+
} }));
|
|
288
|
+
await search.loaded;
|
|
289
|
+
assert.strictEqual(search.instances[0].id, `${testRealmURL}card-2`);
|
|
290
|
+
assert.strictEqual(search.instances[0].constructor.name, "Book");
|
|
291
|
+
});
|
|
292
|
+
(0, import_qunit.test)(`search is not re-run when query and realms are unchanged`, async function(assert) {
|
|
293
|
+
let realmServer = getService("realm-server");
|
|
294
|
+
let fetchCalls = 0;
|
|
295
|
+
let originalMaybeAuthedFetchForRealms = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
296
|
+
realmServer.maybeAuthedFetchForRealms = async (...args) => {
|
|
297
|
+
fetchCalls++;
|
|
298
|
+
return await originalMaybeAuthedFetchForRealms(...args);
|
|
299
|
+
};
|
|
300
|
+
try {
|
|
301
|
+
let args = {
|
|
302
|
+
query: { filter: {
|
|
303
|
+
on: {
|
|
304
|
+
module: testRRI("book"),
|
|
305
|
+
name: "Book"
|
|
306
|
+
},
|
|
307
|
+
eq: { "author.lastName": "Jones" }
|
|
308
|
+
} },
|
|
309
|
+
realms: [testRealmURL],
|
|
310
|
+
isLive: false,
|
|
311
|
+
isAutoSaved: false,
|
|
312
|
+
storeService,
|
|
313
|
+
owner: this.owner
|
|
314
|
+
};
|
|
315
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: args }));
|
|
316
|
+
await search.loaded;
|
|
317
|
+
assert.strictEqual(fetchCalls, 1, "initial search performed once");
|
|
318
|
+
search.modify([], args);
|
|
319
|
+
await settled();
|
|
320
|
+
assert.strictEqual(fetchCalls, 1, "search is not invoked again when query/realms are unchanged");
|
|
321
|
+
} finally {
|
|
322
|
+
realmServer.maybeAuthedFetchForRealms = originalMaybeAuthedFetchForRealms;
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
(0, import_qunit.test)(`a search the realm server sheds with 429 is retried after Retry-After`, async function(assert) {
|
|
326
|
+
let realmServer = getService("realm-server");
|
|
327
|
+
let fetchCalls = 0;
|
|
328
|
+
let originalMaybeAuthedFetchForRealms = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
329
|
+
realmServer.maybeAuthedFetchForRealms = async (...args) => {
|
|
330
|
+
fetchCalls++;
|
|
331
|
+
if (fetchCalls === 1) return new Response(JSON.stringify({ errors: [{
|
|
332
|
+
status: "429",
|
|
333
|
+
title: "Too Many Requests",
|
|
334
|
+
message: "shed"
|
|
335
|
+
}] }), {
|
|
336
|
+
status: 429,
|
|
337
|
+
headers: {
|
|
338
|
+
"content-type": "application/vnd.card+json",
|
|
339
|
+
"retry-after": "0"
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
return await originalMaybeAuthedFetchForRealms(...args);
|
|
343
|
+
};
|
|
344
|
+
try {
|
|
345
|
+
let query = { filter: {
|
|
346
|
+
on: {
|
|
347
|
+
module: testRRI("book"),
|
|
348
|
+
name: "Book"
|
|
349
|
+
},
|
|
350
|
+
eq: { "author.lastName": "Jones" }
|
|
351
|
+
} };
|
|
352
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
353
|
+
query,
|
|
354
|
+
realms: [testRealmURL],
|
|
355
|
+
isLive: false,
|
|
356
|
+
isAutoSaved: false,
|
|
357
|
+
storeService,
|
|
358
|
+
owner: this.owner
|
|
359
|
+
} }));
|
|
360
|
+
await search.loaded;
|
|
361
|
+
assert.strictEqual(fetchCalls, 2, "the shed search was sent again");
|
|
362
|
+
assert.strictEqual(search.instances[0].id, `${testRealmURL}card-2`, "and the retry produced the result");
|
|
363
|
+
} finally {
|
|
364
|
+
realmServer.maybeAuthedFetchForRealms = originalMaybeAuthedFetchForRealms;
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
(0, import_qunit.test)(`a search the realm server answers with 401 is reauthenticated and replayed once`, async function(assert) {
|
|
368
|
+
let realmServer = getService("realm-server");
|
|
369
|
+
let network = getService("network");
|
|
370
|
+
await realmServer.login();
|
|
371
|
+
let rejectedToken = realmServer.token;
|
|
372
|
+
assert.ok(rejectedToken, "the search starts with a realm-server session");
|
|
373
|
+
let attempts = [];
|
|
374
|
+
let gate = async (request) => {
|
|
375
|
+
if (!new URL(request.url).pathname.endsWith("/_federated-search")) return null;
|
|
376
|
+
attempts.push(request.headers.get("Authorization"));
|
|
377
|
+
if (attempts.length === 1) return new Response(JSON.stringify({ errors: ["Unauthorized Request"] }), {
|
|
378
|
+
status: 401,
|
|
379
|
+
headers: { "content-type": "application/vnd.card+json" }
|
|
380
|
+
});
|
|
381
|
+
return null;
|
|
382
|
+
};
|
|
383
|
+
network.virtualNetwork.mount(gate, { prepend: true });
|
|
384
|
+
let reauthCalls = 0;
|
|
385
|
+
let reauthedFor = [];
|
|
386
|
+
let sessionDuringMint = [];
|
|
387
|
+
let originalReauthenticate = realmServer.reauthenticateRealmServer.bind(realmServer);
|
|
388
|
+
realmServer.reauthenticateRealmServer = async (rejectedToken) => {
|
|
389
|
+
reauthCalls++;
|
|
390
|
+
reauthedFor.push(rejectedToken);
|
|
391
|
+
let pending = originalReauthenticate(rejectedToken);
|
|
392
|
+
sessionDuringMint.push(realmServer.token);
|
|
393
|
+
return await pending;
|
|
394
|
+
};
|
|
395
|
+
try {
|
|
396
|
+
let query = { filter: {
|
|
397
|
+
on: {
|
|
398
|
+
module: testRRI("book"),
|
|
399
|
+
name: "Book"
|
|
400
|
+
},
|
|
401
|
+
eq: { "author.lastName": "Jones" }
|
|
402
|
+
} };
|
|
403
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
404
|
+
query,
|
|
405
|
+
realms: [testRealmURL],
|
|
406
|
+
isLive: false,
|
|
407
|
+
isAutoSaved: false,
|
|
408
|
+
storeService,
|
|
409
|
+
owner: this.owner
|
|
410
|
+
} }));
|
|
411
|
+
await search.loaded;
|
|
412
|
+
assert.strictEqual(attempts.length, 2, "the rejected search was sent again");
|
|
413
|
+
assert.strictEqual(reauthCalls, 1, "and exactly one session was minted to send it with");
|
|
414
|
+
assert.strictEqual(attempts[0], `Bearer ${rejectedToken}`, "the first attempt carried the token the server rejected");
|
|
415
|
+
assert.strictEqual(attempts[1], `Bearer ${realmServer.token}`, "and the replay carried the session the service now holds");
|
|
416
|
+
assert.deepEqual(reauthedFor, [rejectedToken], "the mint was told which session the server refused");
|
|
417
|
+
assert.deepEqual(sessionDuringMint, [rejectedToken], "and the service stayed logged in for the length of the mint, so a concurrent caller never sees an anonymous session");
|
|
418
|
+
assert.strictEqual(search.instances[0].id, `${testRealmURL}card-2`, "and the replay produced the result");
|
|
419
|
+
} finally {
|
|
420
|
+
realmServer.reauthenticateRealmServer = originalReauthenticate;
|
|
421
|
+
network.virtualNetwork.unmount(gate);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
(0, import_qunit.test)(`a 401 the realm server repeats is surfaced rather than replayed forever`, async function(assert) {
|
|
425
|
+
let realmServer = getService("realm-server");
|
|
426
|
+
let network = getService("network");
|
|
427
|
+
await realmServer.login();
|
|
428
|
+
let attempts = 0;
|
|
429
|
+
let gate = async (request) => {
|
|
430
|
+
if (!new URL(request.url).pathname.endsWith("/_federated-search")) return null;
|
|
431
|
+
attempts++;
|
|
432
|
+
return new Response(JSON.stringify({ errors: ["Unauthorized Request"] }), {
|
|
433
|
+
status: 401,
|
|
434
|
+
headers: { "content-type": "application/vnd.card+json" }
|
|
435
|
+
});
|
|
436
|
+
};
|
|
437
|
+
network.virtualNetwork.mount(gate, { prepend: true });
|
|
438
|
+
try {
|
|
439
|
+
let query = { filter: {
|
|
440
|
+
on: {
|
|
441
|
+
module: testRRI("book"),
|
|
442
|
+
name: "Book"
|
|
443
|
+
},
|
|
444
|
+
eq: { "author.lastName": "Jones" }
|
|
445
|
+
} };
|
|
446
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
447
|
+
query,
|
|
448
|
+
realms: [testRealmURL],
|
|
449
|
+
isLive: false,
|
|
450
|
+
isAutoSaved: false,
|
|
451
|
+
storeService,
|
|
452
|
+
owner: this.owner
|
|
453
|
+
} }));
|
|
454
|
+
await search.loaded;
|
|
455
|
+
assert.strictEqual(attempts, 2, "the search was replayed once and then left alone");
|
|
456
|
+
assert.strictEqual(search.instances.length, 0, "and the still-refused search yields no results");
|
|
457
|
+
} finally {
|
|
458
|
+
network.virtualNetwork.unmount(gate);
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
(0, import_qunit.test)(`can perform a live search for cards`, async function(assert) {
|
|
462
|
+
let query = { filter: {
|
|
463
|
+
on: {
|
|
464
|
+
module: testRRI("book"),
|
|
465
|
+
name: "Book"
|
|
466
|
+
},
|
|
467
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
468
|
+
} };
|
|
469
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
470
|
+
query,
|
|
471
|
+
realms: [testRealmURL],
|
|
472
|
+
isLive: true,
|
|
473
|
+
isAutoSaved: false,
|
|
474
|
+
storeService,
|
|
475
|
+
owner: this.owner
|
|
476
|
+
} }));
|
|
477
|
+
await search.loaded;
|
|
478
|
+
assert.strictEqual(search.instances.length, 2);
|
|
479
|
+
assert.strictEqual(search.instances[0].id, `${testRealmURL}books/1`);
|
|
480
|
+
assert.strictEqual(search.instances[1].id, `${testRealmURL}books/2`);
|
|
481
|
+
await realm.write("books/3.json", JSON.stringify({ data: {
|
|
482
|
+
type: "card",
|
|
483
|
+
attributes: {
|
|
484
|
+
author: {
|
|
485
|
+
firstName: "Paper",
|
|
486
|
+
lastName: "Abdel-Rahman"
|
|
487
|
+
},
|
|
488
|
+
editions: 0,
|
|
489
|
+
pubDate: "2023-08-01"
|
|
490
|
+
},
|
|
491
|
+
meta: { adoptsFrom: {
|
|
492
|
+
module: testRRI("book"),
|
|
493
|
+
name: "Book"
|
|
494
|
+
} }
|
|
495
|
+
} }));
|
|
496
|
+
await waitUntil(() => search.instances.length === 3);
|
|
497
|
+
assert.strictEqual(search.instances.length, 3);
|
|
498
|
+
assert.strictEqual(search.instances[0].id, `${testRealmURL}books/1`);
|
|
499
|
+
assert.strictEqual(search.instances[1].id, `${testRealmURL}books/2`);
|
|
500
|
+
assert.strictEqual(search.instances[2].id, `${testRealmURL}books/3`);
|
|
501
|
+
});
|
|
502
|
+
(0, import_qunit.test)(`a live search of a realm named by a registered prefix re-runs on that realm's events`, async function(assert) {
|
|
503
|
+
let { virtualNetwork } = getService("network");
|
|
504
|
+
virtualNetwork.addRealmMapping("@test/mapped/", testRealmURL);
|
|
505
|
+
let messageService = getService("message-service");
|
|
506
|
+
let originalSubscribe = messageService.subscribe.bind(messageService);
|
|
507
|
+
let subscribedTo = [];
|
|
508
|
+
messageService.subscribe = (realmURL, cb) => {
|
|
509
|
+
subscribedTo.push(realmURL);
|
|
510
|
+
return originalSubscribe(realmURL, cb);
|
|
511
|
+
};
|
|
512
|
+
let originalSearchWithMeta = storeService.searchWithMeta.bind(storeService);
|
|
513
|
+
let searchedRealms = [];
|
|
514
|
+
storeService.searchWithMeta = async (query, realms, opts) => {
|
|
515
|
+
searchedRealms.push([...realms ?? []]);
|
|
516
|
+
return await originalSearchWithMeta(query, realms, opts);
|
|
517
|
+
};
|
|
518
|
+
try {
|
|
519
|
+
await getSearchResourceForTest(loaderService, () => ({ named: {
|
|
520
|
+
query: {},
|
|
521
|
+
realms: ["@test/mapped/"],
|
|
522
|
+
isLive: true,
|
|
523
|
+
isAutoSaved: false,
|
|
524
|
+
storeService,
|
|
525
|
+
owner: this.owner
|
|
526
|
+
} })).loaded;
|
|
527
|
+
assert.true(subscribedTo.includes("@test/mapped/"), "the search subscribes by the spelling the caller used");
|
|
528
|
+
let runsBefore = searchedRealms.length;
|
|
529
|
+
assert.deepEqual(searchedRealms[runsBefore - 1], ["@test/mapped/"], "the search itself keeps the caller spelling");
|
|
530
|
+
await realm.write("books/3.json", JSON.stringify({ data: {
|
|
531
|
+
type: "card",
|
|
532
|
+
attributes: { author: {
|
|
533
|
+
firstName: "Paper",
|
|
534
|
+
lastName: "Abdel-Rahman"
|
|
535
|
+
} },
|
|
536
|
+
meta: { adoptsFrom: {
|
|
537
|
+
module: testRRI("book"),
|
|
538
|
+
name: "Book"
|
|
539
|
+
} }
|
|
540
|
+
} }));
|
|
541
|
+
await waitUntil(() => searchedRealms.length > runsBefore, { timeout: 1e4 });
|
|
542
|
+
assert.ok(true, "the realm's event re-ran the search");
|
|
543
|
+
} finally {
|
|
544
|
+
messageService.subscribe = originalSubscribe;
|
|
545
|
+
storeService.searchWithMeta = originalSearchWithMeta;
|
|
546
|
+
virtualNetwork.removeRealmMapping("@test/mapped/");
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
(0, import_qunit.test)(`a base realm card is merged and grouped whichever spelling names the base realm`, async function(assert) {
|
|
550
|
+
let spellings = [
|
|
551
|
+
baseRealm.url,
|
|
552
|
+
new URL(config.resolvedBaseRealmURL).href,
|
|
553
|
+
"@cardstack/base/"
|
|
554
|
+
];
|
|
555
|
+
for (let [index, spelling] of spellings.entries()) {
|
|
556
|
+
let title = `local-base-${index}-${Date.now()}`;
|
|
557
|
+
let query = { filter: {
|
|
558
|
+
on: {
|
|
559
|
+
module: baseRRI("card-api"),
|
|
560
|
+
name: "CardDef"
|
|
561
|
+
},
|
|
562
|
+
eq: { "cardInfo.name": title }
|
|
563
|
+
} };
|
|
564
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
565
|
+
query,
|
|
566
|
+
realms: [spelling],
|
|
567
|
+
isLive: true,
|
|
568
|
+
isAutoSaved: false,
|
|
569
|
+
storeService,
|
|
570
|
+
owner: this.owner
|
|
571
|
+
} }));
|
|
572
|
+
await search.loaded;
|
|
573
|
+
await settled();
|
|
574
|
+
assert.deepEqual(search.instances, [], `${spelling}: the server returns nothing for the title`);
|
|
575
|
+
let local = await storeService.addWithoutPersisting({ data: {
|
|
576
|
+
type: "card",
|
|
577
|
+
id: `${baseRealm.url}cards/${title}`,
|
|
578
|
+
attributes: { cardInfo: { name: title } },
|
|
579
|
+
meta: { adoptsFrom: {
|
|
580
|
+
module: baseRRI("card-api"),
|
|
581
|
+
name: "CardDef"
|
|
582
|
+
} }
|
|
583
|
+
} });
|
|
584
|
+
await settled();
|
|
585
|
+
assert.strictEqual(String(local.id), `@cardstack/base/cards/${title}`, `${spelling}: the store names the card by prefix`);
|
|
586
|
+
assert.deepEqual(search.instances.map((instance) => instance.id), [local.id], `${spelling}: the local base card is merged`);
|
|
587
|
+
assert.deepEqual(search.instancesByRealm.map((group) => [group.realm, group.cards.map((card) => card.id)]), [[spelling, [local.id]]], `${spelling}: it is grouped under the realm as the caller named it`);
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
(0, import_qunit.test)(`a seed older than an event's generation is declined for a realm named by a registered prefix`, async function(assert) {
|
|
591
|
+
let { virtualNetwork } = getService("network");
|
|
592
|
+
virtualNetwork.addRealmMapping("@test/mapped/", testRealmURL);
|
|
593
|
+
let originalSearchWithMeta = storeService.searchWithMeta.bind(storeService);
|
|
594
|
+
let runs = 0;
|
|
595
|
+
storeService.searchWithMeta = async (query, realms, opts) => {
|
|
596
|
+
let result = await originalSearchWithMeta(query, realms, opts);
|
|
597
|
+
runs++;
|
|
598
|
+
return result;
|
|
599
|
+
};
|
|
600
|
+
try {
|
|
601
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
602
|
+
query: {},
|
|
603
|
+
realms: ["@test/mapped/"],
|
|
604
|
+
isLive: true,
|
|
605
|
+
isAutoSaved: false,
|
|
606
|
+
storeService,
|
|
607
|
+
owner: this.owner
|
|
608
|
+
} }));
|
|
609
|
+
await search.loaded;
|
|
610
|
+
let runsBefore = runs;
|
|
611
|
+
getService("message-service").relayRealmEvent({
|
|
612
|
+
eventName: "index",
|
|
613
|
+
indexType: "incremental",
|
|
614
|
+
invalidations: [`${testRealmURL}books/1.json`],
|
|
615
|
+
generation: 10,
|
|
616
|
+
realmURL: testRealmURL
|
|
617
|
+
});
|
|
618
|
+
await waitUntil(() => runs > runsBefore, { timeout: 1e4 });
|
|
619
|
+
await settled();
|
|
620
|
+
let held = search.instances.map((instance) => instance.id);
|
|
621
|
+
let stale = await storeService.addWithoutPersisting(new cardApi.CardDef({ cardTitle: "Stale" }));
|
|
622
|
+
search.reseed({
|
|
623
|
+
cards: [stale],
|
|
624
|
+
identity: "stale-seed",
|
|
625
|
+
generation: 5,
|
|
626
|
+
realm: testRealmURL
|
|
627
|
+
});
|
|
628
|
+
await settled();
|
|
629
|
+
assert.deepEqual(search.instances.map((instance) => instance.id), held, "the stale seed does not replace the set the event refreshed");
|
|
630
|
+
} finally {
|
|
631
|
+
storeService.searchWithMeta = originalSearchWithMeta;
|
|
632
|
+
virtualNetwork.removeRealmMapping("@test/mapped/");
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
(0, import_qunit.test)(`a burst of realm events coalesces into a single live re-run`, async function(assert) {
|
|
636
|
+
let realmServer = getService("realm-server");
|
|
637
|
+
let fetchCalls = 0;
|
|
638
|
+
let originalMaybeAuthedFetchForRealms = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
639
|
+
realmServer.maybeAuthedFetchForRealms = async (...args) => {
|
|
640
|
+
fetchCalls++;
|
|
641
|
+
return await originalMaybeAuthedFetchForRealms(...args);
|
|
642
|
+
};
|
|
643
|
+
try {
|
|
644
|
+
let query = { filter: {
|
|
645
|
+
on: {
|
|
646
|
+
module: testRRI("book"),
|
|
647
|
+
name: "Book"
|
|
648
|
+
},
|
|
649
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
650
|
+
} };
|
|
651
|
+
await getSearchResourceForTest(loaderService, () => ({ named: {
|
|
652
|
+
query,
|
|
653
|
+
realms: [testRealmURL],
|
|
654
|
+
isLive: true,
|
|
655
|
+
isAutoSaved: false,
|
|
656
|
+
storeService,
|
|
657
|
+
owner: this.owner
|
|
658
|
+
} })).loaded;
|
|
659
|
+
let baseline = fetchCalls;
|
|
660
|
+
let messageService = getService("message-service");
|
|
661
|
+
for (let generation = 1; generation <= 5; generation++) messageService.relayRealmEvent({
|
|
662
|
+
eventName: "index",
|
|
663
|
+
indexType: "incremental",
|
|
664
|
+
invalidations: [`${testRealmURL}books/1.json`],
|
|
665
|
+
generation,
|
|
666
|
+
realmURL: testRealmURL
|
|
667
|
+
});
|
|
668
|
+
await settled();
|
|
669
|
+
assert.strictEqual(fetchCalls, baseline + 1, "five index events inside one window produce one search fetch");
|
|
670
|
+
messageService.relayRealmEvent({
|
|
671
|
+
eventName: "index",
|
|
672
|
+
indexType: "incremental",
|
|
673
|
+
invalidations: [`${testRealmURL}books/1.json`],
|
|
674
|
+
generation: 6,
|
|
675
|
+
realmURL: testRealmURL
|
|
676
|
+
});
|
|
677
|
+
await settled();
|
|
678
|
+
assert.strictEqual(fetchCalls, baseline + 2, "an event after the flush schedules its own re-run");
|
|
679
|
+
} finally {
|
|
680
|
+
realmServer.maybeAuthedFetchForRealms = originalMaybeAuthedFetchForRealms;
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
(0, import_qunit.test)(`a query change inside the window folds the pending re-run into it`, async function(assert) {
|
|
684
|
+
let realmServer = getService("realm-server");
|
|
685
|
+
let fetchCalls = 0;
|
|
686
|
+
let originalMaybeAuthedFetchForRealms = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
687
|
+
realmServer.maybeAuthedFetchForRealms = async (...args) => {
|
|
688
|
+
fetchCalls++;
|
|
689
|
+
return await originalMaybeAuthedFetchForRealms(...args);
|
|
690
|
+
};
|
|
691
|
+
try {
|
|
692
|
+
let args = {
|
|
693
|
+
query: { filter: {
|
|
694
|
+
on: {
|
|
695
|
+
module: testRRI("book"),
|
|
696
|
+
name: "Book"
|
|
697
|
+
},
|
|
698
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
699
|
+
} },
|
|
700
|
+
realms: [testRealmURL],
|
|
701
|
+
isLive: true,
|
|
702
|
+
isAutoSaved: false,
|
|
703
|
+
storeService,
|
|
704
|
+
owner: this.owner
|
|
705
|
+
};
|
|
706
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: args }));
|
|
707
|
+
await search.loaded;
|
|
708
|
+
let baseline = fetchCalls;
|
|
709
|
+
getService("message-service").relayRealmEvent({
|
|
710
|
+
eventName: "index",
|
|
711
|
+
indexType: "incremental",
|
|
712
|
+
invalidations: [`${testRealmURL}books/1.json`],
|
|
713
|
+
generation: 1,
|
|
714
|
+
realmURL: testRealmURL
|
|
715
|
+
});
|
|
716
|
+
search.modify([], {
|
|
717
|
+
...args,
|
|
718
|
+
query: { filter: {
|
|
719
|
+
on: {
|
|
720
|
+
module: testRRI("book"),
|
|
721
|
+
name: "Book"
|
|
722
|
+
},
|
|
723
|
+
eq: { "author.lastName": "Jones" }
|
|
724
|
+
} }
|
|
725
|
+
});
|
|
726
|
+
await settled();
|
|
727
|
+
assert.strictEqual(fetchCalls, baseline + 1, "the query change folds the armed flush into its own run; no redundant second search fires");
|
|
728
|
+
} finally {
|
|
729
|
+
realmServer.maybeAuthedFetchForRealms = originalMaybeAuthedFetchForRealms;
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
(0, import_qunit.module)("realm event type gating", function() {
|
|
733
|
+
const unrelatedType = `${testRealmURL}observation/Observation`;
|
|
734
|
+
const unrelatedURL = `${testRealmURL}observations/1`;
|
|
735
|
+
const unrelatedFileURL = `${unrelatedURL}.json`;
|
|
736
|
+
const bookType = `${testRealmURL}book/Book`;
|
|
737
|
+
const postType = `${testRealmURL}post/Post`;
|
|
738
|
+
const blogPostType = `${testRealmURL}blog-post/BlogPost`;
|
|
739
|
+
function relayIndexEvent(invalidatedTypes, invalidations = [unrelatedURL]) {
|
|
740
|
+
getService("message-service").relayRealmEvent({
|
|
741
|
+
eventName: "index",
|
|
742
|
+
indexType: "incremental",
|
|
743
|
+
invalidations,
|
|
744
|
+
...invalidatedTypes !== void 0 ? { invalidatedTypes } : {},
|
|
745
|
+
realmURL: testRealmURL
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
function relayPrerenderHtmlEvent(invalidations = [unrelatedFileURL], generation = 1) {
|
|
749
|
+
getService("message-service").relayRealmEvent({
|
|
750
|
+
eventName: "prerender_html",
|
|
751
|
+
invalidations,
|
|
752
|
+
generation,
|
|
753
|
+
realmURL: testRealmURL
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
function countingFetch() {
|
|
757
|
+
let realmServer = getService("realm-server");
|
|
758
|
+
let fetchCalls = 0;
|
|
759
|
+
let original = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
760
|
+
realmServer.maybeAuthedFetchForRealms = async (...args) => {
|
|
761
|
+
fetchCalls++;
|
|
762
|
+
return await original(...args);
|
|
763
|
+
};
|
|
764
|
+
return {
|
|
765
|
+
count: () => fetchCalls,
|
|
766
|
+
restore: () => {
|
|
767
|
+
realmServer.maybeAuthedFetchForRealms = original;
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
function liveSearch(owner, query) {
|
|
772
|
+
return getSearchResourceForTest(loaderService, () => ({ named: {
|
|
773
|
+
query,
|
|
774
|
+
realms: [testRealmURL],
|
|
775
|
+
isLive: true,
|
|
776
|
+
isAutoSaved: false,
|
|
777
|
+
storeService,
|
|
778
|
+
owner
|
|
779
|
+
} }));
|
|
780
|
+
}
|
|
781
|
+
(0, import_qunit.test)("an index event that touched no anchored type does not re-run the query", async function(assert) {
|
|
782
|
+
let fetch = countingFetch();
|
|
783
|
+
try {
|
|
784
|
+
await liveSearch(this.owner, { filter: {
|
|
785
|
+
on: {
|
|
786
|
+
module: testRRI("book"),
|
|
787
|
+
name: "Book"
|
|
788
|
+
},
|
|
789
|
+
eq: {}
|
|
790
|
+
} }).loaded;
|
|
791
|
+
let baseline = fetch.count();
|
|
792
|
+
relayIndexEvent([unrelatedType]);
|
|
793
|
+
await settled();
|
|
794
|
+
assert.strictEqual(fetch.count(), baseline + 1, "the first typed event re-runs while the anchors resolve");
|
|
795
|
+
relayIndexEvent([unrelatedType]);
|
|
796
|
+
await settled();
|
|
797
|
+
assert.strictEqual(fetch.count(), baseline + 1, "a write to a type the query is not anchored on is skipped");
|
|
798
|
+
relayIndexEvent([unrelatedType, bookType]);
|
|
799
|
+
await settled();
|
|
800
|
+
assert.strictEqual(fetch.count(), baseline + 2, "an event naming the anchored type re-runs the query");
|
|
801
|
+
relayIndexEvent(void 0);
|
|
802
|
+
await settled();
|
|
803
|
+
assert.strictEqual(fetch.count(), baseline + 3, "an event carrying no type information re-runs the query");
|
|
804
|
+
} finally {
|
|
805
|
+
fetch.restore();
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
(0, import_qunit.test)("a write to a subtype wakes a query anchored on its ancestor", async function(assert) {
|
|
809
|
+
let fetch = countingFetch();
|
|
810
|
+
try {
|
|
811
|
+
await liveSearch(this.owner, { filter: {
|
|
812
|
+
on: {
|
|
813
|
+
module: testRRI("post"),
|
|
814
|
+
name: "Post"
|
|
815
|
+
},
|
|
816
|
+
eq: {}
|
|
817
|
+
} }).loaded;
|
|
818
|
+
let baseline = fetch.count();
|
|
819
|
+
relayIndexEvent([unrelatedType]);
|
|
820
|
+
await settled();
|
|
821
|
+
relayIndexEvent([unrelatedType]);
|
|
822
|
+
await settled();
|
|
823
|
+
assert.strictEqual(fetch.count(), baseline + 1, "the anchors resolve and the second unrelated event is skipped");
|
|
824
|
+
relayIndexEvent([blogPostType, postType]);
|
|
825
|
+
await settled();
|
|
826
|
+
assert.strictEqual(fetch.count(), baseline + 2, "a subtype write names the ancestor in its chain, so the query re-runs");
|
|
827
|
+
} finally {
|
|
828
|
+
fetch.restore();
|
|
829
|
+
}
|
|
830
|
+
});
|
|
831
|
+
(0, import_qunit.test)("a prerender_html event over rows an index event judged unrelated is skipped", async function(assert) {
|
|
832
|
+
let fetch = countingFetch();
|
|
833
|
+
try {
|
|
834
|
+
await liveSearch(this.owner, { filter: {
|
|
835
|
+
on: {
|
|
836
|
+
module: testRRI("book"),
|
|
837
|
+
name: "Book"
|
|
838
|
+
},
|
|
839
|
+
eq: {}
|
|
840
|
+
} }).loaded;
|
|
841
|
+
let baseline = fetch.count();
|
|
842
|
+
relayIndexEvent([unrelatedType]);
|
|
843
|
+
await settled();
|
|
844
|
+
relayIndexEvent([unrelatedType]);
|
|
845
|
+
await settled();
|
|
846
|
+
assert.strictEqual(fetch.count(), baseline + 1, "the index channel is gated once the anchors resolve");
|
|
847
|
+
relayPrerenderHtmlEvent([unrelatedFileURL]);
|
|
848
|
+
await settled();
|
|
849
|
+
assert.strictEqual(fetch.count(), baseline + 1, "the render of a row no index event tied to this query is skipped");
|
|
850
|
+
relayPrerenderHtmlEvent([`${testRealmURL}books/1.json`]);
|
|
851
|
+
await settled();
|
|
852
|
+
assert.strictEqual(fetch.count(), baseline + 2, "a render this query holds no verdict for re-runs it");
|
|
853
|
+
} finally {
|
|
854
|
+
fetch.restore();
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
(0, import_qunit.test)("an index event that could move a member withdraws its rows from the render gate", async function(assert) {
|
|
858
|
+
let fetch = countingFetch();
|
|
859
|
+
try {
|
|
860
|
+
await liveSearch(this.owner, { filter: {
|
|
861
|
+
on: {
|
|
862
|
+
module: testRRI("book"),
|
|
863
|
+
name: "Book"
|
|
864
|
+
},
|
|
865
|
+
eq: {}
|
|
866
|
+
} }).loaded;
|
|
867
|
+
let baseline = fetch.count();
|
|
868
|
+
relayIndexEvent([unrelatedType]);
|
|
869
|
+
await settled();
|
|
870
|
+
relayIndexEvent([unrelatedType]);
|
|
871
|
+
await settled();
|
|
872
|
+
relayPrerenderHtmlEvent([unrelatedFileURL]);
|
|
873
|
+
await settled();
|
|
874
|
+
assert.strictEqual(fetch.count(), baseline + 1, "both channels are gated for a row judged unrelated");
|
|
875
|
+
relayIndexEvent([bookType], [unrelatedURL]);
|
|
876
|
+
await settled();
|
|
877
|
+
assert.strictEqual(fetch.count(), baseline + 2, "the re-typed row re-runs the query on the index channel");
|
|
878
|
+
relayPrerenderHtmlEvent([unrelatedFileURL]);
|
|
879
|
+
await settled();
|
|
880
|
+
assert.strictEqual(fetch.count(), baseline + 3, "and its render is no longer skipped");
|
|
881
|
+
} finally {
|
|
882
|
+
fetch.restore();
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
(0, import_qunit.test)("a query that admits a card of any type re-runs on every event", async function(assert) {
|
|
886
|
+
let fetch = countingFetch();
|
|
887
|
+
try {
|
|
888
|
+
await liveSearch(this.owner, { filter: { eq: { "author.lastName": "Abdel-Rahman" } } }).loaded;
|
|
889
|
+
let baseline = fetch.count();
|
|
890
|
+
relayIndexEvent([unrelatedType]);
|
|
891
|
+
await settled();
|
|
892
|
+
relayIndexEvent([unrelatedType]);
|
|
893
|
+
await settled();
|
|
894
|
+
assert.strictEqual(fetch.count(), baseline + 2, "an unanchored filter can gain a member of any type, so nothing is skipped");
|
|
895
|
+
relayPrerenderHtmlEvent([unrelatedFileURL]);
|
|
896
|
+
await settled();
|
|
897
|
+
assert.strictEqual(fetch.count(), baseline + 3, "and its renders are not skipped either");
|
|
898
|
+
} finally {
|
|
899
|
+
fetch.restore();
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
(0, import_qunit.test)("a query change re-resolves the anchors before they gate again", async function(assert) {
|
|
903
|
+
let fetch = countingFetch();
|
|
904
|
+
try {
|
|
905
|
+
let args = {
|
|
906
|
+
query: { filter: {
|
|
907
|
+
on: {
|
|
908
|
+
module: testRRI("book"),
|
|
909
|
+
name: "Book"
|
|
910
|
+
},
|
|
911
|
+
eq: {}
|
|
912
|
+
} },
|
|
913
|
+
realms: [testRealmURL],
|
|
914
|
+
isLive: true,
|
|
915
|
+
isAutoSaved: false,
|
|
916
|
+
storeService,
|
|
917
|
+
owner: this.owner
|
|
918
|
+
};
|
|
919
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: args }));
|
|
920
|
+
await search.loaded;
|
|
921
|
+
let baseline = fetch.count();
|
|
922
|
+
relayIndexEvent([unrelatedType]);
|
|
923
|
+
await settled();
|
|
924
|
+
relayIndexEvent([unrelatedType]);
|
|
925
|
+
await settled();
|
|
926
|
+
assert.strictEqual(fetch.count(), baseline + 1, "the anchors resolve and the second event is skipped");
|
|
927
|
+
search.modify([], {
|
|
928
|
+
...args,
|
|
929
|
+
query: { filter: {
|
|
930
|
+
on: {
|
|
931
|
+
module: testRRI("post"),
|
|
932
|
+
name: "Post"
|
|
933
|
+
},
|
|
934
|
+
eq: {}
|
|
935
|
+
} }
|
|
936
|
+
});
|
|
937
|
+
await settled();
|
|
938
|
+
let afterChange = fetch.count();
|
|
939
|
+
relayIndexEvent([unrelatedType]);
|
|
940
|
+
await settled();
|
|
941
|
+
assert.strictEqual(fetch.count(), afterChange + 1, "the first event after the change re-runs while the anchors re-resolve");
|
|
942
|
+
relayIndexEvent([unrelatedType]);
|
|
943
|
+
await settled();
|
|
944
|
+
assert.strictEqual(fetch.count(), afterChange + 1, "the re-resolved anchors gate again");
|
|
945
|
+
relayIndexEvent([postType]);
|
|
946
|
+
await settled();
|
|
947
|
+
assert.strictEqual(fetch.count(), afterChange + 2, "and they gate against the new query, not the old one");
|
|
948
|
+
} finally {
|
|
949
|
+
fetch.restore();
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
});
|
|
953
|
+
(0, import_qunit.test)(`cards in search results live update`, async function(assert) {
|
|
954
|
+
let query = { filter: {
|
|
955
|
+
on: {
|
|
956
|
+
module: testRRI("book"),
|
|
957
|
+
name: "Book"
|
|
958
|
+
},
|
|
959
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
960
|
+
} };
|
|
961
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
962
|
+
query,
|
|
963
|
+
realms: [testRealmURL],
|
|
964
|
+
isLive: true,
|
|
965
|
+
isAutoSaved: false,
|
|
966
|
+
storeService,
|
|
967
|
+
owner: this.owner
|
|
968
|
+
} }));
|
|
969
|
+
await search.loaded;
|
|
970
|
+
assert.strictEqual(search.instances.length, 2);
|
|
971
|
+
assert.strictEqual(search.instances[0].author.firstName, `Mango`);
|
|
972
|
+
await realm.write("books/1.json", JSON.stringify({ data: {
|
|
973
|
+
type: "card",
|
|
974
|
+
attributes: {
|
|
975
|
+
author: {
|
|
976
|
+
firstName: "Mang Mang",
|
|
977
|
+
lastName: "Abdel-Rahman"
|
|
978
|
+
},
|
|
979
|
+
editions: 0,
|
|
980
|
+
pubDate: "2023-08-01"
|
|
981
|
+
},
|
|
982
|
+
meta: { adoptsFrom: {
|
|
983
|
+
module: testRRI("book"),
|
|
984
|
+
name: "Book"
|
|
985
|
+
} }
|
|
986
|
+
} }));
|
|
987
|
+
await search.loaded;
|
|
988
|
+
await settled();
|
|
989
|
+
assert.strictEqual(search.instances.length, 2);
|
|
990
|
+
assert.strictEqual(search.instances[0].author.firstName, `Mang Mang`);
|
|
991
|
+
});
|
|
992
|
+
(0, import_qunit.test)(`can paginate search results and returns correct meta.page.total`, async function(assert) {
|
|
993
|
+
let query = {
|
|
994
|
+
filter: { type: {
|
|
995
|
+
module: testRRI("book"),
|
|
996
|
+
name: "Book"
|
|
997
|
+
} },
|
|
998
|
+
page: {
|
|
999
|
+
number: 0,
|
|
1000
|
+
size: 2
|
|
1001
|
+
},
|
|
1002
|
+
sort: [{
|
|
1003
|
+
by: "author.firstName",
|
|
1004
|
+
on: {
|
|
1005
|
+
module: testRRI("book"),
|
|
1006
|
+
name: "Book"
|
|
1007
|
+
},
|
|
1008
|
+
direction: "asc"
|
|
1009
|
+
}]
|
|
1010
|
+
};
|
|
1011
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1012
|
+
query,
|
|
1013
|
+
realms: [testRealmURL],
|
|
1014
|
+
isLive: false,
|
|
1015
|
+
isAutoSaved: false,
|
|
1016
|
+
storeService,
|
|
1017
|
+
owner: this.owner
|
|
1018
|
+
} }));
|
|
1019
|
+
await search.loaded;
|
|
1020
|
+
assert.strictEqual(search.instances.length, 2);
|
|
1021
|
+
assert.strictEqual(search.meta.page?.total, 4, "meta.page.total shows total count across all pages");
|
|
1022
|
+
query.page = {
|
|
1023
|
+
number: 1,
|
|
1024
|
+
size: 2
|
|
1025
|
+
};
|
|
1026
|
+
search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1027
|
+
query,
|
|
1028
|
+
realms: [testRealmURL],
|
|
1029
|
+
isLive: false,
|
|
1030
|
+
isAutoSaved: false,
|
|
1031
|
+
storeService,
|
|
1032
|
+
owner: this.owner
|
|
1033
|
+
} }));
|
|
1034
|
+
await search.loaded;
|
|
1035
|
+
assert.strictEqual(search.instances.length, 2);
|
|
1036
|
+
assert.strictEqual(search.meta.page?.total, 4, "meta.page.total consistent across pages");
|
|
1037
|
+
query.page = {
|
|
1038
|
+
number: 2,
|
|
1039
|
+
size: 2
|
|
1040
|
+
};
|
|
1041
|
+
search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1042
|
+
query,
|
|
1043
|
+
realms: [testRealmURL],
|
|
1044
|
+
isLive: false,
|
|
1045
|
+
isAutoSaved: false,
|
|
1046
|
+
storeService,
|
|
1047
|
+
owner: this.owner
|
|
1048
|
+
} }));
|
|
1049
|
+
await search.loaded;
|
|
1050
|
+
assert.strictEqual(search.instances.length, 0);
|
|
1051
|
+
assert.strictEqual(search.meta.page?.total, 4, "meta.page.total remains correct on empty page");
|
|
1052
|
+
});
|
|
1053
|
+
(0, import_qunit.test)(`can search for file-meta instances using SearchResource`, async function(assert) {
|
|
1054
|
+
let query = { filter: { type: {
|
|
1055
|
+
module: baseRRI("card-api"),
|
|
1056
|
+
name: "FileDef"
|
|
1057
|
+
} } };
|
|
1058
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1059
|
+
query,
|
|
1060
|
+
realms: [testRealmURL],
|
|
1061
|
+
isLive: false,
|
|
1062
|
+
isAutoSaved: false,
|
|
1063
|
+
storeService,
|
|
1064
|
+
owner: this.owner
|
|
1065
|
+
} }));
|
|
1066
|
+
await search.loaded;
|
|
1067
|
+
assert.ok(search.instances.length >= 2, "returns file-meta instances");
|
|
1068
|
+
let ids = search.instances.map((i) => i.id);
|
|
1069
|
+
assert.ok(ids.includes(rri(`${testRealmURL}files/hello.txt`)), "hello.txt is in results");
|
|
1070
|
+
assert.ok(ids.includes(rri(`${testRealmURL}files/notes.txt`)), "notes.txt is in results");
|
|
1071
|
+
for (let instance of search.instances) assert.ok(isFileDefInstance(instance), `${instance.id} is a FileDef instance`);
|
|
1072
|
+
});
|
|
1073
|
+
(0, import_qunit.test)(`can perform a live search for file-meta instances`, async function(assert) {
|
|
1074
|
+
let query = { filter: { type: {
|
|
1075
|
+
module: baseRRI("card-api"),
|
|
1076
|
+
name: "FileDef"
|
|
1077
|
+
} } };
|
|
1078
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1079
|
+
query,
|
|
1080
|
+
realms: [testRealmURL],
|
|
1081
|
+
isLive: true,
|
|
1082
|
+
isAutoSaved: false,
|
|
1083
|
+
storeService,
|
|
1084
|
+
owner: this.owner
|
|
1085
|
+
} }));
|
|
1086
|
+
await search.loaded;
|
|
1087
|
+
let initialCount = search.instances.length;
|
|
1088
|
+
assert.ok(initialCount >= 2, "initial results include file-meta instances");
|
|
1089
|
+
await realm.write("files/new-file.txt", "New content");
|
|
1090
|
+
await waitUntil(() => search.instances.length > initialCount);
|
|
1091
|
+
let ids = search.instances.map((i) => i.id);
|
|
1092
|
+
assert.ok(ids.includes(rri(`${testRealmURL}files/new-file.txt`)), "new file appears in live search results");
|
|
1093
|
+
assert.ok(isFileDefInstance(search.instances.find((i) => i.id === `${testRealmURL}files/new-file.txt`)), "new file is a FileDef instance");
|
|
1094
|
+
});
|
|
1095
|
+
(0, import_qunit.module)(`in-flight search dedup`, function(innerHooks) {
|
|
1096
|
+
let releaseFetch;
|
|
1097
|
+
let fetchCalls;
|
|
1098
|
+
let restoreFetch;
|
|
1099
|
+
innerHooks.beforeEach(function() {
|
|
1100
|
+
releaseFetch = new Deferred();
|
|
1101
|
+
fetchCalls = 0;
|
|
1102
|
+
let realmServer = getService("realm-server");
|
|
1103
|
+
let original = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
1104
|
+
realmServer.maybeAuthedFetchForRealms = async (url, ...args) => {
|
|
1105
|
+
if (typeof url === "string" && url.includes("_federated-search")) {
|
|
1106
|
+
fetchCalls++;
|
|
1107
|
+
await releaseFetch.promise;
|
|
1108
|
+
}
|
|
1109
|
+
return await original(url, ...args);
|
|
1110
|
+
};
|
|
1111
|
+
restoreFetch = () => {
|
|
1112
|
+
realmServer.maybeAuthedFetchForRealms = original;
|
|
1113
|
+
};
|
|
1114
|
+
});
|
|
1115
|
+
innerHooks.afterEach(function() {
|
|
1116
|
+
try {
|
|
1117
|
+
releaseFetch.fulfill();
|
|
1118
|
+
} catch {}
|
|
1119
|
+
restoreFetch?.();
|
|
1120
|
+
restoreFetch = void 0;
|
|
1121
|
+
globalThis.__boxelRenderContext = void 0;
|
|
1122
|
+
storeService.clearInFlightSearch();
|
|
1123
|
+
});
|
|
1124
|
+
let bookQuery = { filter: {
|
|
1125
|
+
on: {
|
|
1126
|
+
module: testRRI("book"),
|
|
1127
|
+
name: "Book"
|
|
1128
|
+
},
|
|
1129
|
+
eq: { "author.lastName": "Jones" }
|
|
1130
|
+
} };
|
|
1131
|
+
(0, import_qunit.test)(`concurrent same-key store.search calls share a single fetch when inside a prerender`, async function(assert) {
|
|
1132
|
+
globalThis.__boxelRenderContext = true;
|
|
1133
|
+
let p1 = storeService.search(bookQuery, [testRealmURL]);
|
|
1134
|
+
let p2 = storeService.search(bookQuery, [testRealmURL]);
|
|
1135
|
+
assert.strictEqual(fetchCalls, 1, "second caller coalesces onto first in-flight fetch");
|
|
1136
|
+
releaseFetch.fulfill();
|
|
1137
|
+
let [r1, r2] = await Promise.all([p1, p2]);
|
|
1138
|
+
assert.deepEqual(r1.map((i) => i.id ?? null), r2.map((i) => i.id ?? null), "both callers receive the same resolved instances");
|
|
1139
|
+
});
|
|
1140
|
+
(0, import_qunit.test)(`a realm named by a registered prefix coalesces with the same realm named by URL`, async function(assert) {
|
|
1141
|
+
globalThis.__boxelRenderContext = true;
|
|
1142
|
+
let { virtualNetwork } = getService("network");
|
|
1143
|
+
virtualNetwork.addRealmMapping("@test/mapped/", testRealmURL);
|
|
1144
|
+
try {
|
|
1145
|
+
let p1 = storeService.search(bookQuery, ["@test/mapped/"]);
|
|
1146
|
+
let p2 = storeService.search(bookQuery, [testRealmURL, "@test/mapped/"]);
|
|
1147
|
+
assert.strictEqual(fetchCalls, 1, "both spellings key one in-flight fetch");
|
|
1148
|
+
releaseFetch.fulfill();
|
|
1149
|
+
await Promise.all([p1, p2]);
|
|
1150
|
+
} finally {
|
|
1151
|
+
virtualNetwork.removeRealmMapping("@test/mapped/");
|
|
1152
|
+
}
|
|
1153
|
+
});
|
|
1154
|
+
(0, import_qunit.test)(`concurrent same-key store.search calls do NOT coalesce outside a prerender`, async function(assert) {
|
|
1155
|
+
let p1 = storeService.search(bookQuery, [testRealmURL]);
|
|
1156
|
+
let p2 = storeService.search(bookQuery, [testRealmURL]);
|
|
1157
|
+
assert.strictEqual(fetchCalls, 2, "both callers fire their own fetch outside the prerender gate");
|
|
1158
|
+
releaseFetch.fulfill();
|
|
1159
|
+
await Promise.all([p1, p2]);
|
|
1160
|
+
});
|
|
1161
|
+
(0, import_qunit.test)(`different queries produce different keys and run independently inside a prerender`, async function(assert) {
|
|
1162
|
+
globalThis.__boxelRenderContext = true;
|
|
1163
|
+
let otherQuery = { filter: {
|
|
1164
|
+
on: {
|
|
1165
|
+
module: testRRI("book"),
|
|
1166
|
+
name: "Book"
|
|
1167
|
+
},
|
|
1168
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
1169
|
+
} };
|
|
1170
|
+
let p1 = storeService.search(bookQuery, [testRealmURL]);
|
|
1171
|
+
let p2 = storeService.search(otherQuery, [testRealmURL]);
|
|
1172
|
+
assert.strictEqual(fetchCalls, 2, "different filters do not coalesce even inside a prerender");
|
|
1173
|
+
releaseFetch.fulfill();
|
|
1174
|
+
await Promise.all([p1, p2]);
|
|
1175
|
+
});
|
|
1176
|
+
(0, import_qunit.test)(`sequential same-key calls fall through after the first resolves (in-flight only, no resolved-doc cache)`, async function(assert) {
|
|
1177
|
+
globalThis.__boxelRenderContext = true;
|
|
1178
|
+
releaseFetch.fulfill();
|
|
1179
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1180
|
+
assert.strictEqual(fetchCalls, 1, "first call fetches once");
|
|
1181
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1182
|
+
assert.strictEqual(fetchCalls, 2, "sequential same-key call re-fetches after the first resolves");
|
|
1183
|
+
});
|
|
1184
|
+
(0, import_qunit.test)(`clearInFlightSearch drops pending entries so new same-key callers re-fetch`, async function(assert) {
|
|
1185
|
+
globalThis.__boxelRenderContext = true;
|
|
1186
|
+
let p1 = storeService.search(bookQuery, [testRealmURL]);
|
|
1187
|
+
assert.strictEqual(fetchCalls, 1, "first fetch in-flight");
|
|
1188
|
+
storeService.clearInFlightSearch();
|
|
1189
|
+
let p2 = storeService.search(bookQuery, [testRealmURL]);
|
|
1190
|
+
assert.strictEqual(fetchCalls, 2, "post-clear same-key caller fires a fresh fetch");
|
|
1191
|
+
releaseFetch.fulfill();
|
|
1192
|
+
await Promise.all([p1, p2]);
|
|
1193
|
+
});
|
|
1194
|
+
});
|
|
1195
|
+
(0, import_qunit.module)(`job-scoped resolved-doc search cache`, function(innerHooks) {
|
|
1196
|
+
let releaseFetch;
|
|
1197
|
+
let fetchCalls;
|
|
1198
|
+
let restoreFetch;
|
|
1199
|
+
innerHooks.beforeEach(function() {
|
|
1200
|
+
releaseFetch = new Deferred();
|
|
1201
|
+
fetchCalls = 0;
|
|
1202
|
+
let realmServer = getService("realm-server");
|
|
1203
|
+
let original = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
1204
|
+
realmServer.maybeAuthedFetchForRealms = async (url, ...args) => {
|
|
1205
|
+
if (typeof url === "string" && url.includes("_federated-search")) {
|
|
1206
|
+
fetchCalls++;
|
|
1207
|
+
await releaseFetch.promise;
|
|
1208
|
+
}
|
|
1209
|
+
return await original(url, ...args);
|
|
1210
|
+
};
|
|
1211
|
+
restoreFetch = () => {
|
|
1212
|
+
realmServer.maybeAuthedFetchForRealms = original;
|
|
1213
|
+
};
|
|
1214
|
+
});
|
|
1215
|
+
innerHooks.afterEach(function() {
|
|
1216
|
+
try {
|
|
1217
|
+
releaseFetch.fulfill();
|
|
1218
|
+
} catch {}
|
|
1219
|
+
restoreFetch?.();
|
|
1220
|
+
restoreFetch = void 0;
|
|
1221
|
+
let g = globalThis;
|
|
1222
|
+
g.__boxelRenderContext = void 0;
|
|
1223
|
+
g.__boxelJobId = void 0;
|
|
1224
|
+
g.__boxelRenderScope = void 0;
|
|
1225
|
+
g.__boxelConsumingRealm = void 0;
|
|
1226
|
+
storeService.clearInFlightSearch();
|
|
1227
|
+
storeService.clearSearchCache();
|
|
1228
|
+
});
|
|
1229
|
+
let bookQuery = { filter: {
|
|
1230
|
+
on: {
|
|
1231
|
+
module: testRRI("book"),
|
|
1232
|
+
name: "Book"
|
|
1233
|
+
},
|
|
1234
|
+
eq: { "author.lastName": "Jones" }
|
|
1235
|
+
} };
|
|
1236
|
+
function enterPrerender(jobId, consumingRealm) {
|
|
1237
|
+
let g = globalThis;
|
|
1238
|
+
g.__boxelRenderContext = true;
|
|
1239
|
+
g.__boxelJobId = jobId;
|
|
1240
|
+
g.__boxelConsumingRealm = consumingRealm;
|
|
1241
|
+
}
|
|
1242
|
+
(0, import_qunit.test)(`sequential same-key store.search calls hit the resolved-doc cache (one fetch total)`, async function(assert) {
|
|
1243
|
+
enterPrerender("job-1", testRealmURL);
|
|
1244
|
+
releaseFetch.fulfill();
|
|
1245
|
+
let r1 = await storeService.search(bookQuery, [testRealmURL]);
|
|
1246
|
+
assert.strictEqual(fetchCalls, 1, "first call populates cache");
|
|
1247
|
+
let r2 = await storeService.search(bookQuery, [testRealmURL]);
|
|
1248
|
+
assert.strictEqual(fetchCalls, 1, "second sequential same-key call serves from cache, no network");
|
|
1249
|
+
assert.deepEqual(r1.map((i) => i.id ?? null), r2.map((i) => i.id ?? null), "cached doc returns the same instance set");
|
|
1250
|
+
});
|
|
1251
|
+
(0, import_qunit.test)(`a realm named by a registered prefix hits the same-realm cache of its URL`, async function(assert) {
|
|
1252
|
+
enterPrerender("job-1", testRealmURL);
|
|
1253
|
+
releaseFetch.fulfill();
|
|
1254
|
+
let { virtualNetwork } = getService("network");
|
|
1255
|
+
virtualNetwork.addRealmMapping("@test/mapped/", testRealmURL);
|
|
1256
|
+
try {
|
|
1257
|
+
await storeService.search(bookQuery, ["@test/mapped/"]);
|
|
1258
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1259
|
+
assert.strictEqual(fetchCalls, 1, "the second spelling is served from the first one's cache entry");
|
|
1260
|
+
} finally {
|
|
1261
|
+
virtualNetwork.removeRealmMapping("@test/mapped/");
|
|
1262
|
+
}
|
|
1263
|
+
});
|
|
1264
|
+
(0, import_qunit.test)(`base named by its prefix hits the same-realm cache when the consuming realm is its alias`, async function(assert) {
|
|
1265
|
+
enterPrerender("job-1", baseRealm.url);
|
|
1266
|
+
releaseFetch.fulfill();
|
|
1267
|
+
await storeService.search(bookQuery, ["@cardstack/base/"]);
|
|
1268
|
+
await storeService.search(bookQuery, ["@cardstack/base/"]);
|
|
1269
|
+
assert.strictEqual(fetchCalls, 1, "the second search is served from the first one's cache entry");
|
|
1270
|
+
});
|
|
1271
|
+
(0, import_qunit.test)(`cache bypasses outside a prerender (live SPA path)`, async function(assert) {
|
|
1272
|
+
releaseFetch.fulfill();
|
|
1273
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1274
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1275
|
+
assert.strictEqual(fetchCalls, 2, "two sequential calls each fetch — no cache outside prerender");
|
|
1276
|
+
});
|
|
1277
|
+
(0, import_qunit.test)(`cache bypasses when __boxelJobId is unset (prerender with no job)`, async function(assert) {
|
|
1278
|
+
let g = globalThis;
|
|
1279
|
+
g.__boxelRenderContext = true;
|
|
1280
|
+
g.__boxelConsumingRealm = testRealmURL;
|
|
1281
|
+
releaseFetch.fulfill();
|
|
1282
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1283
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1284
|
+
assert.strictEqual(fetchCalls, 2, "sequential calls re-fetch when no jobId is on the page");
|
|
1285
|
+
});
|
|
1286
|
+
(0, import_qunit.test)(`cache bypasses cross-realm reads even inside a prerender`, async function(assert) {
|
|
1287
|
+
enterPrerender("job-1", testRealmURL);
|
|
1288
|
+
releaseFetch.fulfill();
|
|
1289
|
+
await storeService.search(bookQuery, [testRealmURL, "http://other-realm/data/"]);
|
|
1290
|
+
await storeService.search(bookQuery, [testRealmURL, "http://other-realm/data/"]);
|
|
1291
|
+
assert.strictEqual(fetchCalls, 2, "cross-realm reads bypass the same-realm cache");
|
|
1292
|
+
});
|
|
1293
|
+
(0, import_qunit.test)(`jobId change drops the cache (defensive clear at fetch-entry)`, async function(assert) {
|
|
1294
|
+
enterPrerender("job-1", testRealmURL);
|
|
1295
|
+
releaseFetch.fulfill();
|
|
1296
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1297
|
+
assert.strictEqual(fetchCalls, 1, "populates cache under job-1");
|
|
1298
|
+
globalThis.__boxelJobId = "job-2";
|
|
1299
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1300
|
+
assert.strictEqual(fetchCalls, 2, "cache entry from prior job is not served under new jobId");
|
|
1301
|
+
});
|
|
1302
|
+
(0, import_qunit.test)(`a render-scope change drops the cache while the job stays the same`, async function(assert) {
|
|
1303
|
+
enterPrerender("job-1", testRealmURL);
|
|
1304
|
+
let g = globalThis;
|
|
1305
|
+
g.__boxelRenderScope = `${testRealmURL}@1`;
|
|
1306
|
+
releaseFetch.fulfill();
|
|
1307
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1308
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1309
|
+
assert.strictEqual(fetchCalls, 1, "one scope serves repeats from cache");
|
|
1310
|
+
g.__boxelRenderScope = `${testRealmURL}@1~1`;
|
|
1311
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1312
|
+
assert.strictEqual(fetchCalls, 2, "an answer cached under the previous scope is not served under the new one");
|
|
1313
|
+
});
|
|
1314
|
+
(0, import_qunit.test)(`clearSearchCache drops cached entries so subsequent same-key calls re-fetch`, async function(assert) {
|
|
1315
|
+
enterPrerender("job-1", testRealmURL);
|
|
1316
|
+
releaseFetch.fulfill();
|
|
1317
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1318
|
+
assert.strictEqual(fetchCalls, 1, "first call populates cache");
|
|
1319
|
+
storeService.clearSearchCache();
|
|
1320
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1321
|
+
assert.strictEqual(fetchCalls, 2, "post-clear same-key caller re-fetches");
|
|
1322
|
+
});
|
|
1323
|
+
(0, import_qunit.test)(`cache hit short-circuits before the in-flight Map is consulted`, async function(assert) {
|
|
1324
|
+
enterPrerender("job-1", testRealmURL);
|
|
1325
|
+
releaseFetch.fulfill();
|
|
1326
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1327
|
+
assert.strictEqual(fetchCalls, 1, "first call populates cache");
|
|
1328
|
+
let p1 = storeService.search(bookQuery, [testRealmURL]);
|
|
1329
|
+
let p2 = storeService.search(bookQuery, [testRealmURL]);
|
|
1330
|
+
assert.strictEqual(fetchCalls, 1, "cache short-circuits both callers");
|
|
1331
|
+
await Promise.all([p1, p2]);
|
|
1332
|
+
});
|
|
1333
|
+
(0, import_qunit.test)(`cache survives across renders within the same indexing job`, async function(assert) {
|
|
1334
|
+
enterPrerender("job-1", testRealmURL);
|
|
1335
|
+
releaseFetch.fulfill();
|
|
1336
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1337
|
+
assert.strictEqual(fetchCalls, 1, "first render populates cache");
|
|
1338
|
+
storeService.clearInFlightSearch();
|
|
1339
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1340
|
+
assert.strictEqual(fetchCalls, 1, "second render in the same job reuses the cached doc");
|
|
1341
|
+
});
|
|
1342
|
+
(0, import_qunit.test)(`clearSearchCache during an in-flight fetch suppresses the post-resolve populate`, async function(assert) {
|
|
1343
|
+
enterPrerender("job-1", testRealmURL);
|
|
1344
|
+
let p1 = storeService.search(bookQuery, [testRealmURL]);
|
|
1345
|
+
assert.strictEqual(fetchCalls, 1, "first call entered the fetch");
|
|
1346
|
+
storeService.clearSearchCache();
|
|
1347
|
+
releaseFetch.fulfill();
|
|
1348
|
+
await p1;
|
|
1349
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1350
|
+
assert.strictEqual(fetchCalls, 2, "post-clear repopulate was suppressed; next call re-fetches");
|
|
1351
|
+
});
|
|
1352
|
+
(0, import_qunit.test)(`consumingRealm mismatch on a single-realm search bypasses the cache`, async function(assert) {
|
|
1353
|
+
enterPrerender("job-1", "http://other-realm/data/");
|
|
1354
|
+
releaseFetch.fulfill();
|
|
1355
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1356
|
+
await storeService.search(bookQuery, [testRealmURL]);
|
|
1357
|
+
assert.strictEqual(fetchCalls, 2, "single-realm search against a non-consumingRealm is not cached");
|
|
1358
|
+
});
|
|
1359
|
+
});
|
|
1360
|
+
(0, import_qunit.module)(`non-live SearchResource with seed (prerender query-field path)`, function(innerHooks) {
|
|
1361
|
+
let releaseFetch;
|
|
1362
|
+
let fetchCalls;
|
|
1363
|
+
let restoreFetch;
|
|
1364
|
+
innerHooks.beforeEach(function() {
|
|
1365
|
+
releaseFetch = new Deferred();
|
|
1366
|
+
fetchCalls = 0;
|
|
1367
|
+
let realmServer = getService("realm-server");
|
|
1368
|
+
let original = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
1369
|
+
realmServer.maybeAuthedFetchForRealms = async (url, ...args) => {
|
|
1370
|
+
if (typeof url === "string" && url.includes("_federated-search")) {
|
|
1371
|
+
fetchCalls++;
|
|
1372
|
+
await releaseFetch.promise;
|
|
1373
|
+
}
|
|
1374
|
+
return await original(url, ...args);
|
|
1375
|
+
};
|
|
1376
|
+
restoreFetch = () => {
|
|
1377
|
+
realmServer.maybeAuthedFetchForRealms = original;
|
|
1378
|
+
};
|
|
1379
|
+
});
|
|
1380
|
+
innerHooks.afterEach(function() {
|
|
1381
|
+
try {
|
|
1382
|
+
releaseFetch.fulfill();
|
|
1383
|
+
} catch {}
|
|
1384
|
+
restoreFetch?.();
|
|
1385
|
+
restoreFetch = void 0;
|
|
1386
|
+
globalThis.__boxelRenderContext = void 0;
|
|
1387
|
+
storeService.clearInFlightSearch();
|
|
1388
|
+
});
|
|
1389
|
+
let bookQuery = { filter: {
|
|
1390
|
+
on: {
|
|
1391
|
+
module: testRRI("book"),
|
|
1392
|
+
name: "Book"
|
|
1393
|
+
},
|
|
1394
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
1395
|
+
} };
|
|
1396
|
+
async function buildSeed() {
|
|
1397
|
+
releaseFetch.fulfill();
|
|
1398
|
+
return {
|
|
1399
|
+
cards: await storeService.search(bookQuery, [testRealmURL]),
|
|
1400
|
+
searchURL: buildQuerySearchURL([testRealmURL], bookQuery)
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
(0, import_qunit.test)(`a seed that reports its count unknowable does not have one inferred from its rows`, async function(assert) {
|
|
1404
|
+
let { cards, searchURL } = await buildSeed();
|
|
1405
|
+
fetchCalls = 0;
|
|
1406
|
+
globalThis.__boxelRenderContext = true;
|
|
1407
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1408
|
+
query: bookQuery,
|
|
1409
|
+
realms: [testRealmURL],
|
|
1410
|
+
isLive: false,
|
|
1411
|
+
isAutoSaved: false,
|
|
1412
|
+
storeService,
|
|
1413
|
+
seed: {
|
|
1414
|
+
cards,
|
|
1415
|
+
searchURL,
|
|
1416
|
+
realms: [testRealmURL],
|
|
1417
|
+
totalUnknown: true
|
|
1418
|
+
},
|
|
1419
|
+
owner: this.owner
|
|
1420
|
+
} }));
|
|
1421
|
+
await search.loaded;
|
|
1422
|
+
await settled();
|
|
1423
|
+
assert.strictEqual(search.instances.length, cards.length, "the seeded rows are still held");
|
|
1424
|
+
assert.strictEqual(search.totalMatchCount, void 0, "but no match count is reported");
|
|
1425
|
+
assert.false(search.isPartial, "and no shortfall is claimed against a count nobody reported");
|
|
1426
|
+
});
|
|
1427
|
+
(0, import_qunit.test)(`a seed carrying a count larger than its rows reports the shortfall`, async function(assert) {
|
|
1428
|
+
let { cards, searchURL } = await buildSeed();
|
|
1429
|
+
fetchCalls = 0;
|
|
1430
|
+
globalThis.__boxelRenderContext = true;
|
|
1431
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1432
|
+
query: bookQuery,
|
|
1433
|
+
realms: [testRealmURL],
|
|
1434
|
+
isLive: false,
|
|
1435
|
+
isAutoSaved: false,
|
|
1436
|
+
storeService,
|
|
1437
|
+
seed: {
|
|
1438
|
+
cards,
|
|
1439
|
+
searchURL,
|
|
1440
|
+
realms: [testRealmURL],
|
|
1441
|
+
meta: { page: { total: cards.length + 3 } }
|
|
1442
|
+
},
|
|
1443
|
+
owner: this.owner
|
|
1444
|
+
} }));
|
|
1445
|
+
await search.loaded;
|
|
1446
|
+
await settled();
|
|
1447
|
+
assert.strictEqual(search.totalMatchCount, cards.length + 3, "the seeded match count is reported as given");
|
|
1448
|
+
assert.true(search.isPartial, "and the rows falling short of it is a shortfall");
|
|
1449
|
+
});
|
|
1450
|
+
(0, import_qunit.test)(`seed-only resolve: no fetch fires when isLive=false and a seed is present (prerender path)`, async function(assert) {
|
|
1451
|
+
let { cards, searchURL } = await buildSeed();
|
|
1452
|
+
fetchCalls = 0;
|
|
1453
|
+
globalThis.__boxelRenderContext = true;
|
|
1454
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1455
|
+
query: bookQuery,
|
|
1456
|
+
realms: [testRealmURL],
|
|
1457
|
+
isLive: false,
|
|
1458
|
+
isAutoSaved: false,
|
|
1459
|
+
storeService,
|
|
1460
|
+
seed: {
|
|
1461
|
+
cards,
|
|
1462
|
+
searchURL,
|
|
1463
|
+
realms: [testRealmURL]
|
|
1464
|
+
},
|
|
1465
|
+
owner: this.owner
|
|
1466
|
+
} }));
|
|
1467
|
+
await search.loaded;
|
|
1468
|
+
await settled();
|
|
1469
|
+
assert.strictEqual(fetchCalls, 0, "seed-only resolve: no _federated-search fetch fires");
|
|
1470
|
+
assert.strictEqual(search.instances.length, cards.length, "resource exposes seed cards");
|
|
1471
|
+
assert.deepEqual(search.instances.map((i) => i.id), cards.map((c) => c.id), "seed cards are returned in order");
|
|
1472
|
+
});
|
|
1473
|
+
(0, import_qunit.test)(`a seed carrying no meta infers the total from its rows`, async function(assert) {
|
|
1474
|
+
let { cards, searchURL } = await buildSeed();
|
|
1475
|
+
fetchCalls = 0;
|
|
1476
|
+
globalThis.__boxelRenderContext = true;
|
|
1477
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1478
|
+
query: bookQuery,
|
|
1479
|
+
realms: [testRealmURL],
|
|
1480
|
+
isLive: false,
|
|
1481
|
+
isAutoSaved: false,
|
|
1482
|
+
storeService,
|
|
1483
|
+
seed: {
|
|
1484
|
+
cards,
|
|
1485
|
+
searchURL,
|
|
1486
|
+
realms: [testRealmURL]
|
|
1487
|
+
},
|
|
1488
|
+
owner: this.owner
|
|
1489
|
+
} }));
|
|
1490
|
+
await search.loaded;
|
|
1491
|
+
await settled();
|
|
1492
|
+
assert.strictEqual(search.meta?.page?.total, cards.length, "nothing was withheld, so the rows in hand are the match count");
|
|
1493
|
+
assert.notOk(search.meta?.incomplete, "and the result set is not labelled short");
|
|
1494
|
+
});
|
|
1495
|
+
(0, import_qunit.test)(`a seed labelled incomplete keeps the label, so its count reads as a floor`, async function(assert) {
|
|
1496
|
+
let { cards, searchURL } = await buildSeed();
|
|
1497
|
+
fetchCalls = 0;
|
|
1498
|
+
globalThis.__boxelRenderContext = true;
|
|
1499
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1500
|
+
query: bookQuery,
|
|
1501
|
+
realms: [testRealmURL],
|
|
1502
|
+
isLive: false,
|
|
1503
|
+
isAutoSaved: false,
|
|
1504
|
+
storeService,
|
|
1505
|
+
seed: {
|
|
1506
|
+
cards,
|
|
1507
|
+
searchURL,
|
|
1508
|
+
realms: [testRealmURL],
|
|
1509
|
+
meta: {
|
|
1510
|
+
page: { total: cards.length },
|
|
1511
|
+
incomplete: true
|
|
1512
|
+
},
|
|
1513
|
+
queryErrors: [{
|
|
1514
|
+
realm: "https://example.invalid/offline/",
|
|
1515
|
+
type: "network",
|
|
1516
|
+
message: "realm did not answer"
|
|
1517
|
+
}]
|
|
1518
|
+
},
|
|
1519
|
+
owner: this.owner
|
|
1520
|
+
} }));
|
|
1521
|
+
await search.loaded;
|
|
1522
|
+
await settled();
|
|
1523
|
+
assert.true(search.meta?.incomplete, "the label survives seeding, so a consumer can tell the count is a floor");
|
|
1524
|
+
assert.strictEqual(search.instances.length, cards.length, "the realms that answered still contribute their rows");
|
|
1525
|
+
});
|
|
1526
|
+
(0, import_qunit.test)(`a search that fails as a unit refuses to call its empty result a count`, async function(assert) {
|
|
1527
|
+
releaseFetch.fulfill();
|
|
1528
|
+
let realmServer = getService("realm-server");
|
|
1529
|
+
realmServer.maybeAuthedFetchForRealms = async () => {
|
|
1530
|
+
throw new Error("realm did not answer");
|
|
1531
|
+
};
|
|
1532
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1533
|
+
query: bookQuery,
|
|
1534
|
+
realms: [testRealmURL],
|
|
1535
|
+
isLive: true,
|
|
1536
|
+
isAutoSaved: false,
|
|
1537
|
+
storeService,
|
|
1538
|
+
owner: this.owner
|
|
1539
|
+
} }));
|
|
1540
|
+
await search.loaded;
|
|
1541
|
+
await settled();
|
|
1542
|
+
assert.strictEqual(search.instances.length, 0, "the failed search holds no rows");
|
|
1543
|
+
assert.true(search.meta?.incomplete, "and labels the empty result set, so its zero is not read as a count");
|
|
1544
|
+
});
|
|
1545
|
+
(0, import_qunit.test)(`a live resource seeded with its document's answer subscribes without searching`, async function(assert) {
|
|
1546
|
+
let { cards, searchURL } = await buildSeed();
|
|
1547
|
+
fetchCalls = 0;
|
|
1548
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1549
|
+
query: bookQuery,
|
|
1550
|
+
realms: [testRealmURL],
|
|
1551
|
+
isLive: true,
|
|
1552
|
+
isAutoSaved: false,
|
|
1553
|
+
storeService,
|
|
1554
|
+
seed: {
|
|
1555
|
+
cards,
|
|
1556
|
+
searchURL,
|
|
1557
|
+
realms: [testRealmURL]
|
|
1558
|
+
},
|
|
1559
|
+
owner: this.owner
|
|
1560
|
+
} }));
|
|
1561
|
+
await search.loaded;
|
|
1562
|
+
await settled();
|
|
1563
|
+
assert.strictEqual(search.instances.length, cards.length, "the seed resolves the field to the set the document named");
|
|
1564
|
+
assert.strictEqual(fetchCalls, 0, "and no search is issued to re-derive it");
|
|
1565
|
+
});
|
|
1566
|
+
(0, import_qunit.test)(`non-live with no seed still fetches (other non-live callers are unaffected)`, async function(assert) {
|
|
1567
|
+
releaseFetch.fulfill();
|
|
1568
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1569
|
+
query: bookQuery,
|
|
1570
|
+
realms: [testRealmURL],
|
|
1571
|
+
isLive: false,
|
|
1572
|
+
isAutoSaved: false,
|
|
1573
|
+
storeService,
|
|
1574
|
+
owner: this.owner
|
|
1575
|
+
} }));
|
|
1576
|
+
await search.loaded;
|
|
1577
|
+
assert.ok(fetchCalls >= 1, "non-live + no-seed callers still hit the network");
|
|
1578
|
+
assert.strictEqual(search.instances.length, 2, "returns the books matching the query");
|
|
1579
|
+
});
|
|
1580
|
+
(0, import_qunit.test)(`empty unresolved seed still falls back to a fetch in prerender (cards=[], no searchURL)`, async function(assert) {
|
|
1581
|
+
releaseFetch.fulfill();
|
|
1582
|
+
globalThis.__boxelRenderContext = true;
|
|
1583
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1584
|
+
query: bookQuery,
|
|
1585
|
+
realms: [testRealmURL],
|
|
1586
|
+
isLive: false,
|
|
1587
|
+
isAutoSaved: false,
|
|
1588
|
+
storeService,
|
|
1589
|
+
seed: {
|
|
1590
|
+
cards: [],
|
|
1591
|
+
realms: [testRealmURL]
|
|
1592
|
+
},
|
|
1593
|
+
owner: this.owner
|
|
1594
|
+
} }));
|
|
1595
|
+
await search.loaded;
|
|
1596
|
+
assert.ok(fetchCalls >= 1, "empty unresolved seed in prerender falls back to fetch");
|
|
1597
|
+
assert.strictEqual(search.instances.length, 2, "fallback fetch returns the books matching the query");
|
|
1598
|
+
});
|
|
1599
|
+
});
|
|
1600
|
+
(0, import_qunit.module)(`client-side Store filtering step`, function(innerHooks) {
|
|
1601
|
+
let fetchCalls;
|
|
1602
|
+
let restoreFetch;
|
|
1603
|
+
innerHooks.beforeEach(function() {
|
|
1604
|
+
fetchCalls = 0;
|
|
1605
|
+
let realmServer = getService("realm-server");
|
|
1606
|
+
let original = realmServer.maybeAuthedFetchForRealms.bind(realmServer);
|
|
1607
|
+
realmServer.maybeAuthedFetchForRealms = async (url, ...args) => {
|
|
1608
|
+
if (typeof url === "string" && url.includes("_federated-search")) fetchCalls++;
|
|
1609
|
+
return await original(url, ...args);
|
|
1610
|
+
};
|
|
1611
|
+
restoreFetch = () => {
|
|
1612
|
+
realmServer.maybeAuthedFetchForRealms = original;
|
|
1613
|
+
};
|
|
1614
|
+
});
|
|
1615
|
+
innerHooks.afterEach(function() {
|
|
1616
|
+
restoreFetch?.();
|
|
1617
|
+
restoreFetch = void 0;
|
|
1618
|
+
});
|
|
1619
|
+
const bookRef = {
|
|
1620
|
+
module: testRRI("book"),
|
|
1621
|
+
name: "Book"
|
|
1622
|
+
};
|
|
1623
|
+
let abdelRahmanQuery = { filter: {
|
|
1624
|
+
on: bookRef,
|
|
1625
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
1626
|
+
} };
|
|
1627
|
+
let aguilarQuery = { filter: {
|
|
1628
|
+
on: bookRef,
|
|
1629
|
+
eq: { "author.lastName": "Aguilar" }
|
|
1630
|
+
} };
|
|
1631
|
+
async function addBookCandidate(idPath, firstName, lastName) {
|
|
1632
|
+
return await storeService.addWithoutPersisting({ data: {
|
|
1633
|
+
type: "card",
|
|
1634
|
+
id: `${testRealmURL}${idPath}`,
|
|
1635
|
+
attributes: {
|
|
1636
|
+
author: {
|
|
1637
|
+
firstName,
|
|
1638
|
+
lastName
|
|
1639
|
+
},
|
|
1640
|
+
editions: 0,
|
|
1641
|
+
pubDate: "2024-01-01"
|
|
1642
|
+
},
|
|
1643
|
+
meta: { adoptsFrom: bookRef }
|
|
1644
|
+
} });
|
|
1645
|
+
}
|
|
1646
|
+
(0, import_qunit.test)(`a locally added matching card appears in an eligible live search without a server round-trip`, async function(assert) {
|
|
1647
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1648
|
+
query: abdelRahmanQuery,
|
|
1649
|
+
realms: [testRealmURL],
|
|
1650
|
+
isLive: true,
|
|
1651
|
+
isAutoSaved: false,
|
|
1652
|
+
storeService,
|
|
1653
|
+
owner: this.owner
|
|
1654
|
+
} }));
|
|
1655
|
+
await search.loaded;
|
|
1656
|
+
await settled();
|
|
1657
|
+
assert.strictEqual(search.instances.length, 2, "server returns the two matching books");
|
|
1658
|
+
let fetchesBefore = fetchCalls;
|
|
1659
|
+
await addBookCandidate("books/local-new", "Apple", "Abdel-Rahman");
|
|
1660
|
+
await settled();
|
|
1661
|
+
let ids = search.instances.map((i) => i.id);
|
|
1662
|
+
assert.strictEqual(search.instances.length, 3, "the locally added matching card is merged into the result set");
|
|
1663
|
+
assert.ok(ids.includes(rri(`${testRealmURL}books/local-new`)), "the new card appears in results");
|
|
1664
|
+
assert.strictEqual(fetchCalls, fetchesBefore, "no _federated-search fetch fired for the client-side recompute");
|
|
1665
|
+
});
|
|
1666
|
+
(0, import_qunit.test)(`a surfaced candidate is not duplicated even though it is keyed by both local and remote id`, async function(assert) {
|
|
1667
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1668
|
+
query: abdelRahmanQuery,
|
|
1669
|
+
realms: [testRealmURL],
|
|
1670
|
+
isLive: true,
|
|
1671
|
+
isAutoSaved: false,
|
|
1672
|
+
storeService,
|
|
1673
|
+
owner: this.owner
|
|
1674
|
+
} }));
|
|
1675
|
+
await search.loaded;
|
|
1676
|
+
await settled();
|
|
1677
|
+
let candidate = await addBookCandidate("books/dupe-check", "Apple", "Abdel-Rahman");
|
|
1678
|
+
await settled();
|
|
1679
|
+
let poolOccurrences = storeService.allCardInstances().filter((c) => c === candidate).length;
|
|
1680
|
+
assert.strictEqual(poolOccurrences, 1, "the candidate appears exactly once in allCardInstances despite dual keying");
|
|
1681
|
+
let ids = search.instances.map((i) => i.id);
|
|
1682
|
+
assert.strictEqual(ids.length, new Set(ids).size, "the displayed result set has no duplicate ids");
|
|
1683
|
+
assert.strictEqual(ids.filter((id) => id === rri(`${testRealmURL}books/dupe-check`)).length, 1, "the surfaced candidate is rendered exactly once");
|
|
1684
|
+
assert.strictEqual(search.instances.length, 3, "two server books plus the single surfaced candidate");
|
|
1685
|
+
});
|
|
1686
|
+
(0, import_qunit.test)(`a server-returned card that no longer matches local state is removed`, async function(assert) {
|
|
1687
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1688
|
+
query: abdelRahmanQuery,
|
|
1689
|
+
realms: [testRealmURL],
|
|
1690
|
+
isLive: true,
|
|
1691
|
+
isAutoSaved: false,
|
|
1692
|
+
storeService,
|
|
1693
|
+
owner: this.owner
|
|
1694
|
+
} }));
|
|
1695
|
+
await search.loaded;
|
|
1696
|
+
await settled();
|
|
1697
|
+
assert.strictEqual(search.instances.length, 2);
|
|
1698
|
+
let book1 = storeService.peek(`${testRealmURL}books/1`);
|
|
1699
|
+
book1.author.lastName = "Changed";
|
|
1700
|
+
let ids = search.instances.map((i) => i.id);
|
|
1701
|
+
assert.strictEqual(search.instances.length, 1, "the now-non-matching server card is removed");
|
|
1702
|
+
assert.notOk(ids.includes(rri(`${testRealmURL}books/1`)), "books/1 dropped from results");
|
|
1703
|
+
});
|
|
1704
|
+
(0, import_qunit.test)(`editing a candidate toggles its membership reactively (recompute on Store mutation)`, async function(assert) {
|
|
1705
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1706
|
+
query: abdelRahmanQuery,
|
|
1707
|
+
realms: [testRealmURL],
|
|
1708
|
+
isLive: true,
|
|
1709
|
+
isAutoSaved: false,
|
|
1710
|
+
storeService,
|
|
1711
|
+
owner: this.owner
|
|
1712
|
+
} }));
|
|
1713
|
+
await search.loaded;
|
|
1714
|
+
await settled();
|
|
1715
|
+
assert.strictEqual(search.instances.length, 2);
|
|
1716
|
+
let candidate = await addBookCandidate("books/edit-me", "Switch", "Other");
|
|
1717
|
+
await settled();
|
|
1718
|
+
assert.strictEqual(search.instances.length, 2, "a candidate that does not match is not shown");
|
|
1719
|
+
candidate.author.lastName = "Abdel-Rahman";
|
|
1720
|
+
assert.strictEqual(search.instances.length, 3, "after editing to match, the candidate appears");
|
|
1721
|
+
assert.ok(search.instances.map((i) => i.id).includes(rri(`${testRealmURL}books/edit-me`)));
|
|
1722
|
+
candidate.author.lastName = "Other again";
|
|
1723
|
+
assert.strictEqual(search.instances.length, 2, "after editing away from match, the candidate disappears");
|
|
1724
|
+
});
|
|
1725
|
+
(0, import_qunit.test)(`a merged candidate is reference-retained while displayed and released when it leaves`, async function(assert) {
|
|
1726
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1727
|
+
query: abdelRahmanQuery,
|
|
1728
|
+
realms: [testRealmURL],
|
|
1729
|
+
isLive: true,
|
|
1730
|
+
isAutoSaved: false,
|
|
1731
|
+
storeService,
|
|
1732
|
+
owner: this.owner
|
|
1733
|
+
} }));
|
|
1734
|
+
await search.loaded;
|
|
1735
|
+
await settled();
|
|
1736
|
+
let candidate = await addBookCandidate("books/retained", "Apple", "Abdel-Rahman");
|
|
1737
|
+
let candidateId = `${testRealmURL}books/retained`;
|
|
1738
|
+
await settled();
|
|
1739
|
+
assert.strictEqual(storeService.getReferenceCount(candidateId), 0, "a freshly hydrated candidate carries no reference before it is displayed");
|
|
1740
|
+
assert.ok(search.instances.map((i) => i.id).includes(rri(candidateId)), "the candidate is displayed");
|
|
1741
|
+
await settled();
|
|
1742
|
+
assert.ok(storeService.getReferenceCount(candidateId) > 0, "a Store reference is retained while the candidate is displayed");
|
|
1743
|
+
candidate.author.lastName = "Other";
|
|
1744
|
+
assert.notOk(search.instances.map((i) => i.id).includes(rri(candidateId)), "the candidate leaves the result set");
|
|
1745
|
+
await settled();
|
|
1746
|
+
assert.strictEqual(storeService.getReferenceCount(candidateId), 0, "the reference is released once the candidate is no longer displayed");
|
|
1747
|
+
});
|
|
1748
|
+
(0, import_qunit.test)(`the merged set is ordered per the query sort`, async function(assert) {
|
|
1749
|
+
let sortedQuery = {
|
|
1750
|
+
filter: {
|
|
1751
|
+
on: bookRef,
|
|
1752
|
+
eq: { "author.lastName": "Abdel-Rahman" }
|
|
1753
|
+
},
|
|
1754
|
+
sort: [{
|
|
1755
|
+
by: "author.firstName",
|
|
1756
|
+
on: bookRef,
|
|
1757
|
+
direction: "asc"
|
|
1758
|
+
}]
|
|
1759
|
+
};
|
|
1760
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1761
|
+
query: sortedQuery,
|
|
1762
|
+
realms: [testRealmURL],
|
|
1763
|
+
isLive: true,
|
|
1764
|
+
isAutoSaved: false,
|
|
1765
|
+
storeService,
|
|
1766
|
+
owner: this.owner
|
|
1767
|
+
} }));
|
|
1768
|
+
await search.loaded;
|
|
1769
|
+
await settled();
|
|
1770
|
+
assert.deepEqual(search.instances.map((i) => i.id), [`${testRealmURL}books/1`, `${testRealmURL}books/2`]);
|
|
1771
|
+
await addBookCandidate("books/apple", "Apple", "Abdel-Rahman");
|
|
1772
|
+
await settled();
|
|
1773
|
+
assert.deepEqual(search.instances.map((i) => i.id), [
|
|
1774
|
+
`${testRealmURL}books/apple`,
|
|
1775
|
+
`${testRealmURL}books/1`,
|
|
1776
|
+
`${testRealmURL}books/2`
|
|
1777
|
+
], "the candidate sorts into position by author.firstName");
|
|
1778
|
+
});
|
|
1779
|
+
(0, import_qunit.test)(`one-shot store.search never runs the client step (server-only)`, async function(assert) {
|
|
1780
|
+
await addBookCandidate("books/local-only", "Local", "Abdel-Rahman");
|
|
1781
|
+
let result = await storeService.search(abdelRahmanQuery, [testRealmURL]);
|
|
1782
|
+
assert.notOk(result.map((c) => c.id).includes(`${testRealmURL}books/local-only`), "one-shot store.search ignores the local-only candidate");
|
|
1783
|
+
});
|
|
1784
|
+
(0, import_qunit.test)(`a non-live search is a server-only passthrough`, async function(assert) {
|
|
1785
|
+
await addBookCandidate("books/passthrough", "Zoe", "Abdel-Rahman");
|
|
1786
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1787
|
+
query: abdelRahmanQuery,
|
|
1788
|
+
realms: [testRealmURL],
|
|
1789
|
+
isLive: false,
|
|
1790
|
+
isAutoSaved: false,
|
|
1791
|
+
storeService,
|
|
1792
|
+
owner: this.owner
|
|
1793
|
+
} }));
|
|
1794
|
+
await search.loaded;
|
|
1795
|
+
await settled();
|
|
1796
|
+
assert.strictEqual(search.instances.length, 2, "a non-live search ignores the local candidate");
|
|
1797
|
+
assert.notOk(search.instances.map((i) => i.id).includes(rri(`${testRealmURL}books/passthrough`)));
|
|
1798
|
+
});
|
|
1799
|
+
(0, import_qunit.test)(`an incompletely-loaded (paginated) result set skips the client step`, async function(assert) {
|
|
1800
|
+
let pagedQuery = {
|
|
1801
|
+
filter: { type: bookRef },
|
|
1802
|
+
page: {
|
|
1803
|
+
number: 0,
|
|
1804
|
+
size: 2
|
|
1805
|
+
},
|
|
1806
|
+
sort: [{
|
|
1807
|
+
by: "author.firstName",
|
|
1808
|
+
on: bookRef,
|
|
1809
|
+
direction: "asc"
|
|
1810
|
+
}]
|
|
1811
|
+
};
|
|
1812
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1813
|
+
query: pagedQuery,
|
|
1814
|
+
realms: [testRealmURL],
|
|
1815
|
+
isLive: true,
|
|
1816
|
+
isAutoSaved: false,
|
|
1817
|
+
storeService,
|
|
1818
|
+
owner: this.owner
|
|
1819
|
+
} }));
|
|
1820
|
+
await search.loaded;
|
|
1821
|
+
await settled();
|
|
1822
|
+
assert.strictEqual(search.instances.length, 2, "first page holds 2");
|
|
1823
|
+
assert.strictEqual(search.meta.page?.total, 4, "total is 4 across all pages — the loaded set is incomplete");
|
|
1824
|
+
await addBookCandidate("books/paged-extra", "Aaa", "Zzz");
|
|
1825
|
+
await settled();
|
|
1826
|
+
assert.strictEqual(search.instances.length, 2, "an incomplete result set is not reconciled against the Store");
|
|
1827
|
+
assert.notOk(search.instances.map((i) => i.id).includes(rri(`${testRealmURL}books/paged-extra`)));
|
|
1828
|
+
});
|
|
1829
|
+
(0, import_qunit.test)(`a non-client-evaluable filter (matches) forces server-only`, async function(assert) {
|
|
1830
|
+
let matchesQuery = { filter: { matches: "Abdel-Rahman" } };
|
|
1831
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1832
|
+
query: matchesQuery,
|
|
1833
|
+
realms: [testRealmURL],
|
|
1834
|
+
isLive: true,
|
|
1835
|
+
isAutoSaved: false,
|
|
1836
|
+
storeService,
|
|
1837
|
+
owner: this.owner
|
|
1838
|
+
} }));
|
|
1839
|
+
await search.loaded;
|
|
1840
|
+
await settled();
|
|
1841
|
+
let serverIds = search.instances.map((i) => i.id);
|
|
1842
|
+
await addBookCandidate("books/matches-extra", "Nope", "Abdel-Rahman");
|
|
1843
|
+
await settled();
|
|
1844
|
+
assert.ok(storeService.peek(`${testRealmURL}books/matches-extra`), "the candidate is hydrated in the Store");
|
|
1845
|
+
assert.deepEqual(search.instances.map((i) => i.id), serverIds, "the displayed set stays equal to the server result — no candidate merged");
|
|
1846
|
+
assert.notOk(search.instances.map((i) => i.id).includes(rri(`${testRealmURL}books/matches-extra`)), "the locally added candidate is not pulled into a matches search");
|
|
1847
|
+
});
|
|
1848
|
+
(0, import_qunit.test)(`a candidate evicted from the Store drops out of the displayed set on the next reactive pass`, async function(assert) {
|
|
1849
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1850
|
+
query: abdelRahmanQuery,
|
|
1851
|
+
realms: [testRealmURL],
|
|
1852
|
+
isLive: true,
|
|
1853
|
+
isAutoSaved: false,
|
|
1854
|
+
storeService,
|
|
1855
|
+
owner: this.owner
|
|
1856
|
+
} }));
|
|
1857
|
+
await search.loaded;
|
|
1858
|
+
await settled();
|
|
1859
|
+
await addBookCandidate("books/will-evict", "Plum", "Abdel-Rahman");
|
|
1860
|
+
await settled();
|
|
1861
|
+
let candidateId = `${testRealmURL}books/will-evict`;
|
|
1862
|
+
assert.ok(search.instances.map((i) => i.id).includes(rri(candidateId)), "the candidate is displayed before eviction");
|
|
1863
|
+
let fetchesBefore = fetchCalls;
|
|
1864
|
+
storeService.store.delete(candidateId);
|
|
1865
|
+
await settled();
|
|
1866
|
+
assert.notOk(search.instances.map((i) => i.id).includes(rri(candidateId)), "the candidate drops out after a Store eviction");
|
|
1867
|
+
assert.strictEqual(fetchCalls, fetchesBefore, "no _federated-search fetch fired for the recompute");
|
|
1868
|
+
});
|
|
1869
|
+
(0, import_qunit.test)(`a candidate with an unresolvable predicate (unloaded linksTo) is not added`, async function(assert) {
|
|
1870
|
+
let postRef = {
|
|
1871
|
+
module: testRRI("post"),
|
|
1872
|
+
name: "Post"
|
|
1873
|
+
};
|
|
1874
|
+
let query = { filter: {
|
|
1875
|
+
on: postRef,
|
|
1876
|
+
eq: { "article.cardTitle": "Any Title" }
|
|
1877
|
+
} };
|
|
1878
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1879
|
+
query,
|
|
1880
|
+
realms: [testRealmURL],
|
|
1881
|
+
isLive: true,
|
|
1882
|
+
isAutoSaved: false,
|
|
1883
|
+
storeService,
|
|
1884
|
+
owner: this.owner
|
|
1885
|
+
} }));
|
|
1886
|
+
await search.loaded;
|
|
1887
|
+
await settled();
|
|
1888
|
+
let serverIds = search.instances.map((i) => i.id);
|
|
1889
|
+
await storeService.addWithoutPersisting({ data: {
|
|
1890
|
+
type: "card",
|
|
1891
|
+
id: `${testRealmURL}posts/unresolved`,
|
|
1892
|
+
attributes: { cardTitle: "Lonely Post" },
|
|
1893
|
+
relationships: { article: { links: { self: `${testRealmURL}does/not/exist` } } },
|
|
1894
|
+
meta: { adoptsFrom: postRef }
|
|
1895
|
+
} });
|
|
1896
|
+
await settled();
|
|
1897
|
+
assert.deepEqual(search.instances.map((i) => i.id), serverIds, "an unresolvable candidate does not enter the displayed set");
|
|
1898
|
+
assert.notOk(search.instances.map((i) => i.id).includes(rri(`${testRealmURL}posts/unresolved`)), "the unresolvable candidate is absent");
|
|
1899
|
+
});
|
|
1900
|
+
(0, import_qunit.test)(`a Store candidate outside the query's target realm is not added`, async function(assert) {
|
|
1901
|
+
let otherRealmURL = "https://other-realm.example/";
|
|
1902
|
+
await storeService.addWithoutPersisting({ data: {
|
|
1903
|
+
type: "card",
|
|
1904
|
+
id: `${otherRealmURL}books/foreign`,
|
|
1905
|
+
attributes: {
|
|
1906
|
+
author: {
|
|
1907
|
+
firstName: "Foreign",
|
|
1908
|
+
lastName: "Abdel-Rahman"
|
|
1909
|
+
},
|
|
1910
|
+
editions: 0,
|
|
1911
|
+
pubDate: "2024-01-01"
|
|
1912
|
+
},
|
|
1913
|
+
meta: { adoptsFrom: bookRef }
|
|
1914
|
+
} });
|
|
1915
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1916
|
+
query: abdelRahmanQuery,
|
|
1917
|
+
realms: [testRealmURL],
|
|
1918
|
+
isLive: true,
|
|
1919
|
+
isAutoSaved: false,
|
|
1920
|
+
storeService,
|
|
1921
|
+
owner: this.owner
|
|
1922
|
+
} }));
|
|
1923
|
+
await search.loaded;
|
|
1924
|
+
await settled();
|
|
1925
|
+
let ids = search.instances.map((i) => i.id).map(String);
|
|
1926
|
+
assert.strictEqual(search.instances.length, 2, "only the two in-realm matches are displayed");
|
|
1927
|
+
assert.notOk(ids.some((id) => id.startsWith(otherRealmURL)), "the candidate outside [testRealmURL] is excluded");
|
|
1928
|
+
});
|
|
1929
|
+
(0, import_qunit.test)(`override authority: a server-card removal and a candidate add both reach the displayed set`, async function(assert) {
|
|
1930
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: {
|
|
1931
|
+
query: abdelRahmanQuery,
|
|
1932
|
+
realms: [testRealmURL],
|
|
1933
|
+
isLive: true,
|
|
1934
|
+
isAutoSaved: false,
|
|
1935
|
+
storeService,
|
|
1936
|
+
owner: this.owner
|
|
1937
|
+
} }));
|
|
1938
|
+
await search.loaded;
|
|
1939
|
+
await settled();
|
|
1940
|
+
assert.strictEqual(search.instances.length, 2);
|
|
1941
|
+
let book1 = storeService.peek(`${testRealmURL}books/1`);
|
|
1942
|
+
book1.author.lastName = "Changed";
|
|
1943
|
+
await addBookCandidate("books/local-add", "Local", "Abdel-Rahman");
|
|
1944
|
+
await settled();
|
|
1945
|
+
let ids = search.instances.map((i) => i.id);
|
|
1946
|
+
assert.strictEqual(search.instances.length, 2, "one server card dropped, one local candidate surfaced — same count, different members");
|
|
1947
|
+
assert.notOk(ids.includes(rri(`${testRealmURL}books/1`)), "the now-non-matching server card is gone");
|
|
1948
|
+
assert.ok(ids.includes(rri(`${testRealmURL}books/local-add`)), "the local-only matching candidate is present");
|
|
1949
|
+
});
|
|
1950
|
+
(0, import_qunit.test)("performThrottledSearch caps concurrent card searches at the configured limit", async function(assert) {
|
|
1951
|
+
let inFlight = 0;
|
|
1952
|
+
let maxInFlight = 0;
|
|
1953
|
+
let started = 0;
|
|
1954
|
+
let gates = [];
|
|
1955
|
+
let count = SEARCH_CONCURRENCY_CAP + 2;
|
|
1956
|
+
let makeRun = () => {
|
|
1957
|
+
let gate = new Deferred();
|
|
1958
|
+
gates.push(gate);
|
|
1959
|
+
return async () => {
|
|
1960
|
+
started++;
|
|
1961
|
+
inFlight++;
|
|
1962
|
+
maxInFlight = Math.max(maxInFlight, inFlight);
|
|
1963
|
+
await gate.promise;
|
|
1964
|
+
inFlight--;
|
|
1965
|
+
};
|
|
1966
|
+
};
|
|
1967
|
+
let results = Array.from({ length: count }, () => storeService.performThrottledSearch(makeRun(), "card"));
|
|
1968
|
+
try {
|
|
1969
|
+
await waitUntil(() => started >= SEARCH_CONCURRENCY_CAP);
|
|
1970
|
+
assert.strictEqual(maxInFlight, SEARCH_CONCURRENCY_CAP, "no more than the cap run at once");
|
|
1971
|
+
assert.strictEqual(started, SEARCH_CONCURRENCY_CAP, "excess searches are queued, not started");
|
|
1972
|
+
} finally {
|
|
1973
|
+
for (let gate of gates) {
|
|
1974
|
+
gate.fulfill();
|
|
1975
|
+
await settled();
|
|
1976
|
+
}
|
|
1977
|
+
await Promise.all(results);
|
|
1978
|
+
}
|
|
1979
|
+
assert.strictEqual(maxInFlight, SEARCH_CONCURRENCY_CAP, "the cap held across the whole drain");
|
|
1980
|
+
assert.strictEqual(started, count, "every queued search eventually ran (enqueue, not drop)");
|
|
1981
|
+
});
|
|
1982
|
+
(0, import_qunit.test)("a throttled search waits for a slot before it reaches the network; a host search does not", async function(assert) {
|
|
1983
|
+
let cap = fillTheLane("query-field");
|
|
1984
|
+
await waitUntil(cap.started, { timeout: 5e3 });
|
|
1985
|
+
fetchCalls = 0;
|
|
1986
|
+
let throttledDone = false;
|
|
1987
|
+
let throttled = storeService.search(abdelRahmanQuery, [testRealmURL], { throttled: true }).then(() => {
|
|
1988
|
+
throttledDone = true;
|
|
1989
|
+
});
|
|
1990
|
+
let hostDone = false;
|
|
1991
|
+
let host = storeService.search(abdelRahmanQuery, [testRealmURL]).then(() => {
|
|
1992
|
+
hostDone = true;
|
|
1993
|
+
});
|
|
1994
|
+
try {
|
|
1995
|
+
await waitUntil(() => hostDone, { timeout: 5e3 });
|
|
1996
|
+
assert.strictEqual(fetchCalls, 1, "the host search reached the network while every slot was taken");
|
|
1997
|
+
assert.false(throttledDone, "the throttled search is still queued behind the full cap");
|
|
1998
|
+
} finally {
|
|
1999
|
+
await cap.release();
|
|
2000
|
+
}
|
|
2001
|
+
await throttled;
|
|
2002
|
+
await host;
|
|
2003
|
+
assert.true(throttledDone, "the throttled search ran once a slot freed");
|
|
2004
|
+
assert.strictEqual(fetchCalls, 2, "it reached the network only after it had a slot");
|
|
2005
|
+
});
|
|
2006
|
+
(0, import_qunit.test)("a card search reaches the network while the query-field lane is full", async function(assert) {
|
|
2007
|
+
let cap = fillTheLane("query-field");
|
|
2008
|
+
await waitUntil(cap.started, { timeout: 5e3 });
|
|
2009
|
+
fetchCalls = 0;
|
|
2010
|
+
let queryFieldDone = false;
|
|
2011
|
+
let queryField = storeService.search(abdelRahmanQuery, [testRealmURL], { throttled: true }).then(() => {
|
|
2012
|
+
queryFieldDone = true;
|
|
2013
|
+
});
|
|
2014
|
+
let cardDone = false;
|
|
2015
|
+
let card = storeService.search(abdelRahmanQuery, [testRealmURL], { cardInitiated: true }).then(() => {
|
|
2016
|
+
cardDone = true;
|
|
2017
|
+
});
|
|
2018
|
+
try {
|
|
2019
|
+
await waitUntil(() => cardDone, { timeout: 5e3 });
|
|
2020
|
+
assert.strictEqual(fetchCalls, 1, "the card search reached the network past the queued fan-out");
|
|
2021
|
+
assert.false(queryFieldDone, "the query-field search is still queued behind its own full lane");
|
|
2022
|
+
} finally {
|
|
2023
|
+
await cap.release();
|
|
2024
|
+
}
|
|
2025
|
+
await queryField;
|
|
2026
|
+
await card;
|
|
2027
|
+
assert.strictEqual(fetchCalls, 2, "the query-field search ran once its lane freed");
|
|
2028
|
+
});
|
|
2029
|
+
(0, import_qunit.test)("a query-field search reaches the network while the card lane is full", async function(assert) {
|
|
2030
|
+
let cap = fillTheLane("card");
|
|
2031
|
+
await waitUntil(cap.started, { timeout: 5e3 });
|
|
2032
|
+
fetchCalls = 0;
|
|
2033
|
+
let cardDone = false;
|
|
2034
|
+
let card = storeService.search(abdelRahmanQuery, [testRealmURL], { cardInitiated: true }).then(() => {
|
|
2035
|
+
cardDone = true;
|
|
2036
|
+
});
|
|
2037
|
+
let queryFieldDone = false;
|
|
2038
|
+
let queryField = storeService.search(abdelRahmanQuery, [testRealmURL], { throttled: true }).then(() => {
|
|
2039
|
+
queryFieldDone = true;
|
|
2040
|
+
});
|
|
2041
|
+
try {
|
|
2042
|
+
await waitUntil(() => queryFieldDone, { timeout: 5e3 });
|
|
2043
|
+
assert.strictEqual(fetchCalls, 1, "the query-field search reached the network past the queued card search");
|
|
2044
|
+
assert.false(cardDone, "the card search is still queued behind its own full lane");
|
|
2045
|
+
} finally {
|
|
2046
|
+
await cap.release();
|
|
2047
|
+
}
|
|
2048
|
+
await card;
|
|
2049
|
+
await queryField;
|
|
2050
|
+
assert.strictEqual(fetchCalls, 2, "the card search ran once its lane freed");
|
|
2051
|
+
});
|
|
2052
|
+
(0, import_qunit.test)("a queued search whose consumer has gone away gives back its slot instead of fetching", async function(assert) {
|
|
2053
|
+
let cap = fillTheLane("query-field");
|
|
2054
|
+
await waitUntil(cap.started, { timeout: 5e3 });
|
|
2055
|
+
fetchCalls = 0;
|
|
2056
|
+
let obsolete = false;
|
|
2057
|
+
let queued = storeService.searchWithMeta(abdelRahmanQuery, [testRealmURL], {
|
|
2058
|
+
throttled: true,
|
|
2059
|
+
isObsolete: () => obsolete
|
|
2060
|
+
});
|
|
2061
|
+
obsolete = true;
|
|
2062
|
+
await cap.release();
|
|
2063
|
+
let result = await queued;
|
|
2064
|
+
assert.strictEqual(fetchCalls, 0, "the abandoned search never reached the network");
|
|
2065
|
+
assert.deepEqual(result.instances, [], "it resolves empty for the caller that is no longer listening");
|
|
2066
|
+
assert.strictEqual(result.meta.page?.total, 0, "and reports no count rather than a stale one");
|
|
2067
|
+
});
|
|
2068
|
+
function fillTheLane(lane) {
|
|
2069
|
+
let laneCap = lane === "card" ? SEARCH_CONCURRENCY_CAP : QUERY_FIELD_SEARCH_CONCURRENCY_CAP;
|
|
2070
|
+
let gates = [];
|
|
2071
|
+
let occupied = 0;
|
|
2072
|
+
let occupying = Array.from({ length: laneCap }, () => {
|
|
2073
|
+
let gate = new Deferred();
|
|
2074
|
+
gates.push(gate);
|
|
2075
|
+
return storeService.performThrottledSearch(async () => {
|
|
2076
|
+
occupied++;
|
|
2077
|
+
await gate.promise;
|
|
2078
|
+
}, lane);
|
|
2079
|
+
});
|
|
2080
|
+
return {
|
|
2081
|
+
started: () => occupied >= laneCap,
|
|
2082
|
+
release: async () => {
|
|
2083
|
+
for (let gate of gates) try {
|
|
2084
|
+
gate.fulfill();
|
|
2085
|
+
} catch {}
|
|
2086
|
+
await Promise.all(occupying);
|
|
2087
|
+
}
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
function countThrottledRuns() {
|
|
2091
|
+
let enqueued = 0;
|
|
2092
|
+
let perform = storeService.performThrottledSearch.bind(storeService);
|
|
2093
|
+
storeService.performThrottledSearch = (run, lane) => {
|
|
2094
|
+
enqueued++;
|
|
2095
|
+
return perform(run, lane);
|
|
2096
|
+
};
|
|
2097
|
+
return {
|
|
2098
|
+
enqueued: () => enqueued,
|
|
2099
|
+
restore: () => delete storeService.performThrottledSearch
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
(0, import_qunit.test)("a queued search superseded by a query change never sends the superseded query", async function(assert) {
|
|
2103
|
+
let cap = fillTheLane("query-field");
|
|
2104
|
+
await waitUntil(cap.started, { timeout: 5e3 });
|
|
2105
|
+
let counter = countThrottledRuns();
|
|
2106
|
+
fetchCalls = 0;
|
|
2107
|
+
let args = {
|
|
2108
|
+
query: abdelRahmanQuery,
|
|
2109
|
+
realms: [testRealmURL],
|
|
2110
|
+
isLive: true,
|
|
2111
|
+
isAutoSaved: false,
|
|
2112
|
+
throttled: true,
|
|
2113
|
+
storeService,
|
|
2114
|
+
owner: this.owner
|
|
2115
|
+
};
|
|
2116
|
+
let search = getSearchResourceForTest(loaderService, () => ({ named: args }));
|
|
2117
|
+
try {
|
|
2118
|
+
search.isLoading;
|
|
2119
|
+
await waitUntil(() => counter.enqueued() > 0, { timeout: 5e3 });
|
|
2120
|
+
search.modify([], {
|
|
2121
|
+
...args,
|
|
2122
|
+
query: aguilarQuery
|
|
2123
|
+
});
|
|
2124
|
+
await waitUntil(() => counter.enqueued() > 1, { timeout: 5e3 });
|
|
2125
|
+
await cap.release();
|
|
2126
|
+
await settled();
|
|
2127
|
+
assert.strictEqual(fetchCalls, 1, "only the surviving query reached the network");
|
|
2128
|
+
assert.strictEqual(search.instances.length, 1, "the resource holds the surviving query's one match, not the superseded query's two");
|
|
2129
|
+
} finally {
|
|
2130
|
+
counter.restore();
|
|
2131
|
+
await cap.release();
|
|
2132
|
+
}
|
|
2133
|
+
});
|
|
2134
|
+
(0, import_qunit.test)("a queued search whose resource is destroyed never reaches the network", async function(assert) {
|
|
2135
|
+
let cap = fillTheLane("query-field");
|
|
2136
|
+
await waitUntil(cap.started, { timeout: 5e3 });
|
|
2137
|
+
let counter = countThrottledRuns();
|
|
2138
|
+
fetchCalls = 0;
|
|
2139
|
+
let parent = {};
|
|
2140
|
+
setOwner(parent, this.owner);
|
|
2141
|
+
let search = getSearchResourceForTest(parent, () => ({ named: {
|
|
2142
|
+
query: abdelRahmanQuery,
|
|
2143
|
+
realms: [testRealmURL],
|
|
2144
|
+
isLive: true,
|
|
2145
|
+
isAutoSaved: false,
|
|
2146
|
+
throttled: true,
|
|
2147
|
+
storeService,
|
|
2148
|
+
owner: this.owner
|
|
2149
|
+
} }));
|
|
2150
|
+
try {
|
|
2151
|
+
search.isLoading;
|
|
2152
|
+
await waitUntil(() => counter.enqueued() > 0, { timeout: 5e3 });
|
|
2153
|
+
run(() => destroy(parent));
|
|
2154
|
+
await cap.release();
|
|
2155
|
+
await settled();
|
|
2156
|
+
assert.strictEqual(fetchCalls, 0, "the destroyed resource never sent the search it had queued");
|
|
2157
|
+
} finally {
|
|
2158
|
+
counter.restore();
|
|
2159
|
+
await cap.release();
|
|
2160
|
+
}
|
|
2161
|
+
});
|
|
2162
|
+
(0, import_qunit.test)("a card-initiated search over the realms cap is rejected; the host is not", async function(assert) {
|
|
2163
|
+
let query = { filter: { eq: {} } };
|
|
2164
|
+
let realms = [
|
|
2165
|
+
"http://r1/",
|
|
2166
|
+
"http://r2/",
|
|
2167
|
+
"http://r3/"
|
|
2168
|
+
];
|
|
2169
|
+
await assert.rejects(storeService.search(query, realms, { cardInitiated: true }), (e) => e instanceof SearchBoundError, "a card search over the realms cap throws a SearchBoundError");
|
|
2170
|
+
let hostErr;
|
|
2171
|
+
try {
|
|
2172
|
+
await storeService.search(query, realms);
|
|
2173
|
+
} catch (e) {
|
|
2174
|
+
hostErr = e;
|
|
2175
|
+
}
|
|
2176
|
+
assert.false(hostErr instanceof SearchBoundError, "the host search is not subject to the realms cap");
|
|
2177
|
+
});
|
|
2178
|
+
(0, import_qunit.test)("a card-initiated search over the page cap is rejected", async function(assert) {
|
|
2179
|
+
await assert.rejects(storeService.search({ page: { size: 1e3 } }, ["http://r1/"], { cardInitiated: true }), (e) => e instanceof SearchBoundError, "a card search over the page cap throws a SearchBoundError");
|
|
2180
|
+
});
|
|
2181
|
+
(0, import_qunit.test)("the card-facing store defaults a no-realm search to the current realm", async function(assert) {
|
|
2182
|
+
let results = await storeService.cardFacingStore(() => void 0).search({ filter: { eq: {} } });
|
|
2183
|
+
assert.deepEqual(results, [], "a no-realm search with no current realm is empty");
|
|
2184
|
+
let bound = storeService.cardFacingStore(() => "http://current/");
|
|
2185
|
+
await assert.rejects(bound.search({ filter: { eq: {} } }, [
|
|
2186
|
+
"http://r1/",
|
|
2187
|
+
"http://r2/",
|
|
2188
|
+
"http://r3/"
|
|
2189
|
+
]), (e) => e instanceof SearchBoundError, "the facade enforces the realms cap on an explicit list");
|
|
2190
|
+
});
|
|
2191
|
+
(0, import_qunit.test)("the card-facing store withholds the search methods that skip the caps", async function(assert) {
|
|
2192
|
+
let cardStore = storeService.cardFacingStore(() => "http://current/");
|
|
2193
|
+
for (let name of [
|
|
2194
|
+
"searchWithMeta",
|
|
2195
|
+
"searchEntries",
|
|
2196
|
+
"getWithoutCache"
|
|
2197
|
+
]) {
|
|
2198
|
+
assert.strictEqual(typeof storeService[name], "function", `${name} is a real method on the store service`);
|
|
2199
|
+
assert.strictEqual(cardStore[name], void 0, `${name} is not reachable through the card-facing store`);
|
|
2200
|
+
}
|
|
2201
|
+
for (let name of [
|
|
2202
|
+
"save",
|
|
2203
|
+
"create",
|
|
2204
|
+
"add",
|
|
2205
|
+
"addWithoutPersisting",
|
|
2206
|
+
"addWithoutWaiting",
|
|
2207
|
+
"peek",
|
|
2208
|
+
"peekError",
|
|
2209
|
+
"get",
|
|
2210
|
+
"delete",
|
|
2211
|
+
"patch",
|
|
2212
|
+
"search",
|
|
2213
|
+
"getSaveState"
|
|
2214
|
+
]) assert.strictEqual(typeof cardStore[name], "function", `${name} is reachable through the card-facing store`);
|
|
2215
|
+
});
|
|
2216
|
+
(0, import_qunit.test)("the card-facing store gives no way back to the service and refuses writes", async function(assert) {
|
|
2217
|
+
let cardStore = storeService.cardFacingStore(() => "http://current/");
|
|
2218
|
+
let realGet = storeService.get;
|
|
2219
|
+
let realSearch = storeService.search;
|
|
2220
|
+
assert.strictEqual(cardStore.valueOf(), cardStore, "valueOf answers the facade, not the service");
|
|
2221
|
+
assert.strictEqual(cardStore.valueOf().searchWithMeta, void 0, "so an uncapped sibling stays out of reach through it");
|
|
2222
|
+
assert.strictEqual(String(cardStore), "[object Object]", "the facade still converts to a string");
|
|
2223
|
+
assert.throws(() => {
|
|
2224
|
+
cardStore.get = () => "replaced";
|
|
2225
|
+
}, TypeError, "assigning a method through the facade is refused");
|
|
2226
|
+
assert.throws(() => cardStore.__defineGetter__("search", () => "replaced"), TypeError, "defining a getter through the facade is refused");
|
|
2227
|
+
assert.throws(() => Object.defineProperty(cardStore, "patch", { value: "replaced" }), TypeError, "defining a property on the facade is refused");
|
|
2228
|
+
assert.throws(() => {
|
|
2229
|
+
delete cardStore.search;
|
|
2230
|
+
}, TypeError, "deleting a method through the facade is refused");
|
|
2231
|
+
assert.strictEqual(storeService.get, realGet, "the service's get is untouched");
|
|
2232
|
+
assert.strictEqual(storeService.search, realSearch, "the service's search is untouched");
|
|
2233
|
+
for (let name of [
|
|
2234
|
+
"get",
|
|
2235
|
+
"search",
|
|
2236
|
+
"patch"
|
|
2237
|
+
]) assert.false(Object.prototype.hasOwnProperty.call(storeService, name), `nothing was installed as an own ${name} on the service`);
|
|
2238
|
+
});
|
|
2239
|
+
});
|
|
2240
|
+
});
|
|
2241
|
+
//#endregion
|