@cardstack/boxel-cli 0.13.0-unstable.4 → 0.13.0-unstable.5
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/bundled-realms/pretui/components/doc-report.gts +2 -2
- package/bundled-realms/pretui/components/doc-report.usage.gts +3 -3
- package/bundled-realms/pretui/components/form-field.md +1 -1
- package/bundled-realms/pretui/components/icon-button.md +1 -1
- package/bundled-realms/pretui/components/popup.md +1 -1
- package/bundled-realms/pretui/components/switch.gts +13 -0
- package/bundled-realms/pretui/components/switch.md +5 -3
- package/bundled-realms/pretui/components/theme-frame.gts +49 -22
- package/bundled-realms/pretui/components/tooltip.gts +141 -42
- package/bundled-realms/pretui/components/tooltip.md +10 -12
- package/bundled-realms/pretui/components/tooltip.usage.gts +3 -5
- package/bundled-realms/pretui/docs/structure.md +1 -1
- package/bundled-realms/pretui/internal/overlay.gts +4 -2
- package/bundled-realms/pretui/pretui-css.gts +6 -2
- package/bundled-realms/pretui/theme-scoped-css.gts +262 -0
- package/bundled-test-harness/assets/account-switch-failed-test-DwAZq6Sc.js +45 -0
- package/bundled-test-harness/assets/adapter-C_6pnsx1.js +2 -0
- package/bundled-test-harness/assets/add-field-to-card-definition-tool-test-zMYtJWBv.js +112 -0
- package/bundled-test-harness/assets/ai-assistant-create-workspace-test-CwhAV-Ow.js +130 -0
- package/bundled-test-harness/assets/ai-assistant-panel-relogin-test-DNgclkGJ.js +46 -0
- package/bundled-test-harness/assets/ai-assistant-test-DGYFiRTb.js +2223 -0
- package/bundled-test-harness/assets/ai-function-generation-test-Dj6WzKkh.js +1176 -0
- package/bundled-test-harness/assets/ai-module-creation-test-EsOoJpQ1.js +151 -0
- package/bundled-test-harness/assets/aibot-message-uGaCPn5o.js +1312 -0
- package/bundled-test-harness/assets/app-pIzBYfiZ.js +14146 -0
- package/bundled-test-harness/assets/apply-markdown-edit-test-CPhfeg1i.js +230 -0
- package/bundled-test-harness/assets/ask-user-picker-NVRkhKwt.js +370 -0
- package/bundled-test-harness/assets/ask-user-picker-test-SsZqFm9W.js +39 -0
- package/bundled-test-harness/assets/assistant-transcript-test-DesuBCIB.js +57 -0
- package/bundled-test-harness/assets/audio-metadata-extractor-test-8JM6oZXG.js +1176 -0
- package/bundled-test-harness/assets/authed-fetch-test-yPTMe-9V.js +73 -0
- package/bundled-test-harness/assets/avif-image-def-test-Kyknj908.js +187 -0
- package/bundled-test-harness/assets/basic-test-D9OrrMaq.js +139 -0
- package/bundled-test-harness/assets/binary-upload-dedupe-test-Dnxlbbu6.js +308 -0
- package/bundled-test-harness/assets/bot-registration-test-Bk2lTaCW.js +97 -0
- package/bundled-test-harness/assets/box-test-BbV9sMyU.js +50 -0
- package/bundled-test-harness/assets/brand-guide-attachments-test-z4wTsKbI.js +84 -0
- package/bundled-test-harness/assets/brand-guide-custom-css-test-BlSJE8xo.js +196 -0
- package/bundled-test-harness/assets/brand-guide-edit-test-DJ1OQ6IB.js +140 -0
- package/bundled-test-harness/assets/brand-logo-mark-field-test-ux7eetkO.js +86 -0
- package/bundled-test-harness/assets/broken-link-template-test-CqB3MWyw.js +192 -0
- package/bundled-test-harness/assets/bundled-base-modules-test-B2oNLZSJ.js +54 -0
- package/bundled-test-harness/assets/bundled-base-oracle-test-DelPfFjn.js +37 -0
- package/bundled-test-harness/assets/buried-stack-item-scroll-test-Ixsl1tS0.js +236 -0
- package/bundled-test-harness/assets/button-BvYQm_A1.js +141 -0
- package/bundled-test-harness/assets/bxl-cyclic-graph-test-p23WCLRW.js +47 -0
- package/bundled-test-harness/assets/bxl-expression-test-CVTQYT_C.js +250 -0
- package/bundled-test-harness/assets/bxl-indexing-test-D_A7X2sr.js +212 -0
- package/bundled-test-harness/assets/bxl-platform-module-test-Cltfyybp.js +71 -0
- package/bundled-test-harness/assets/can-invoke-test-DJi7jMaU.js +455 -0
- package/bundled-test-harness/assets/can-read-realm-test-CIz6WX_K.js +56 -0
- package/bundled-test-harness/assets/cancel-indexing-job-test-0LlrOgYK.js +69 -0
- package/bundled-test-harness/assets/capture-test-diHIWmh0.js +360 -0
- package/bundled-test-harness/assets/card-api-test-Ci9b0ghP.js +198 -0
- package/bundled-test-harness/assets/card-basics-test-RKQoQWZD.js +5364 -0
- package/bundled-test-harness/assets/card-chooser-paging-test-BoUyFMEw.js +235 -0
- package/bundled-test-harness/assets/card-chooser-test-7ZwhxxkH.js +393 -0
- package/bundled-test-harness/assets/card-context-search-results-KmkXJbmC.js +30 -0
- package/bundled-test-harness/assets/card-context-search-results-test-CpMr8OlX.js +184 -0
- package/bundled-test-harness/assets/card-def-field-def-relationships-test-ByPl5n55.js +562 -0
- package/bundled-test-harness/assets/card-def-menu-items-test-ohuHc0b4.js +228 -0
- package/bundled-test-harness/assets/card-delete-test-Be971b-V.js +466 -0
- package/bundled-test-harness/assets/card-error-3q1o3i0e.js +72 -0
- package/bundled-test-harness/assets/card-error-awaiting-index-test-DPgYKfbF.js +53 -0
- package/bundled-test-harness/assets/card-info-thumbnail-picker-test-CVfeJyjt.js +219 -0
- package/bundled-test-harness/assets/card-playground-test-D-7bi4PQ.js +1491 -0
- package/bundled-test-harness/assets/card-prerender-DemTfK_a.js +12939 -0
- package/bundled-test-harness/assets/card-thunk-error-test-DCBh1vRT.js +48 -0
- package/bundled-test-harness/assets/card-type-service-test-DXPrfVYk.js +161 -0
- package/bundled-test-harness/assets/check-correctness-test-DjE7r1X2.js +1093 -0
- package/bundled-test-harness/assets/check-domain-availability-test-U10xSKbY.js +98 -0
- package/bundled-test-harness/assets/chip-0r_r9SC8.js +44 -0
- package/bundled-test-harness/assets/choreo-Ci5dG5fv.js +2 -0
- package/bundled-test-harness/assets/choreo-D1K9RyjM.js +1031 -0
- package/bundled-test-harness/assets/choreo-feature-reel-test-vzmW-SFd.js +155 -0
- package/bundled-test-harness/assets/choreo-gallery-build-order-test-J6n0_PKm.js +436 -0
- package/bundled-test-harness/assets/choreo-gallery-compositor-test-DSi1N9bi.js +399 -0
- package/bundled-test-harness/assets/choreo-gallery-cover-test-BT05gNKC.js +214 -0
- package/bundled-test-harness/assets/choreo-gallery-crossing-stage-test-BIuLOZH6.js +133 -0
- package/bundled-test-harness/assets/choreo-gallery-demos-alive-test-ClGjpnj6.js +42 -0
- package/bundled-test-harness/assets/choreo-gallery-drift-test-OjxMXV0Y.js +620 -0
- package/bundled-test-harness/assets/choreo-gallery-escort-test-D6VL4FfT.js +187 -0
- package/bundled-test-harness/assets/choreo-gallery-films-test-DBcDHGx8.js +140 -0
- package/bundled-test-harness/assets/choreo-gallery-filter-test-BUghtJZe.js +46 -0
- package/bundled-test-harness/assets/choreo-gallery-fold-test-0D9-_h_I.js +180 -0
- package/bundled-test-harness/assets/choreo-gallery-guide-pages-test-DS41eNNV.js +114 -0
- package/bundled-test-harness/assets/choreo-gallery-guides-test-CZnaxUNJ.js +321 -0
- package/bundled-test-harness/assets/choreo-gallery-hang-test-WFvsJ-MJ.js +426 -0
- package/bundled-test-harness/assets/choreo-gallery-highlight-test-Dn0hYPLC.js +60 -0
- package/bundled-test-harness/assets/choreo-gallery-inline-edit-test-C5WvS67s.js +370 -0
- package/bundled-test-harness/assets/choreo-gallery-interruption-test-CgT9RKTe.js +176 -0
- package/bundled-test-harness/assets/choreo-gallery-lone-stack-test-BZgqbTJd.js +104 -0
- package/bundled-test-harness/assets/choreo-gallery-navigation-test-CWzXkvbW.js +193 -0
- package/bundled-test-harness/assets/choreo-gallery-playhead-transport-test-Dt71t4CU.js +111 -0
- package/bundled-test-harness/assets/choreo-gallery-poplayout-subtree-test-B_rDq4em.js +127 -0
- package/bundled-test-harness/assets/choreo-gallery-presence-modes-test-j_cZ9cAM.js +100 -0
- package/bundled-test-harness/assets/choreo-gallery-presentation-test-CIFKR65J.js +157 -0
- package/bundled-test-harness/assets/choreo-gallery-reduced-motion-test-BvRCiCvB.js +145 -0
- package/bundled-test-harness/assets/choreo-gallery-sheet-standalone-test-DgO2MBzU.js +89 -0
- package/bundled-test-harness/assets/choreo-gallery-sheet-test-BntUKT_P.js +48 -0
- package/bundled-test-harness/assets/choreo-gallery-site-test-CvSE6Jyq.js +237 -0
- package/bundled-test-harness/assets/choreo-gallery-stage-Dj6tFzon.js +256 -0
- package/bundled-test-harness/assets/choreo-gallery-stage-keyboard-test-CkDrAPA8.js +102 -0
- package/bundled-test-harness/assets/choreo-gallery-stages-test-DHUmzoRW.js +35 -0
- package/bundled-test-harness/assets/choreo-gallery-subdivision-test-BZ9-cDFh.js +138 -0
- package/bundled-test-harness/assets/choreo-gallery-table-plan-test-7uP6mZpo.js +144 -0
- package/bundled-test-harness/assets/choreo-gallery-theater-test-DgEue9FD.js +252 -0
- package/bundled-test-harness/assets/choreo-gallery-tuning-test-CfPx5iCp.js +95 -0
- package/bundled-test-harness/assets/choreo-gallery-widget-room-test-o9T2EFKq.js +88 -0
- package/bundled-test-harness/assets/choreo-gallery-wires-test-73JLkxn6.js +148 -0
- package/bundled-test-harness/assets/client-telemetry-test-DFM4mML2.js +340 -0
- package/bundled-test-harness/assets/clip-CsRtHZiN.js +92 -0
- package/bundled-test-harness/assets/clip-CycGr0Lf.js +2 -0
- package/bundled-test-harness/assets/code-block-DRE8KQZQ.js +502 -0
- package/bundled-test-harness/assets/code-ref-test-CDcqE8_C.js +163 -0
- package/bundled-test-harness/assets/code-submode-availability-test-DPTqZYYm.js +198 -0
- package/bundled-test-harness/assets/code-submode-test-AHV4mzJ4.js +1839 -0
- package/bundled-test-harness/assets/codeblocks-test-D9pbJMK8.js +418 -0
- package/bundled-test-harness/assets/codemirror-editor-test-BeAMVivu.js +1512 -0
- package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Bnb7_KUT.js +366 -0
- package/bundled-test-harness/assets/color-field-test-CR6gGEqE.js +212 -0
- package/bundled-test-harness/assets/compaction-test-BSqAGv4g.js +150 -0
- package/bundled-test-harness/assets/computed-test-DtyZGgdc.js +1320 -0
- package/bundled-test-harness/assets/container-CEslVSTe.js +10884 -0
- package/bundled-test-harness/assets/content-preview-components-test-BztI4fz-.js +462 -0
- package/bundled-test-harness/assets/copy-and-edit-test-Cqw7kcur.js +292 -0
- package/bundled-test-harness/assets/copy-card-test-D5m3eVEH.js +218 -0
- package/bundled-test-harness/assets/copy-file-to-realm-test-FPY-6Ddm.js +148 -0
- package/bundled-test-harness/assets/copy-source-test-9pJD-qey.js +56 -0
- package/bundled-test-harness/assets/create-file-test-DjMf88u_.js +1086 -0
- package/bundled-test-harness/assets/create-file-test-XbgOqg38.js +464 -0
- package/bundled-test-harness/assets/create-listing-modal-test-DyGlGMWu.js +273 -0
- package/bundled-test-harness/assets/create-listing-pr-request-test-CBtIV0Z8.js +117 -0
- package/bundled-test-harness/assets/create-spec-test-4xR0gM7E.js +256 -0
- package/bundled-test-harness/assets/create-submission-workflow-test-DQpWrpGT.js +132 -0
- package/bundled-test-harness/assets/create-workspace-test-BQAudgpS.js +104 -0
- package/bundled-test-harness/assets/credential-fields-test-DXKBdbZD.js +200 -0
- package/bundled-test-harness/assets/csv-file-def-test-Cnp4y834.js +102 -0
- package/bundled-test-harness/assets/dashboard-CmuOhIYC.js +3628 -0
- package/bundled-test-harness/assets/dashboard-CzN49x74.css +2400 -0
- package/bundled-test-harness/assets/dashboard-add-workspace-test-T32hWB-g.js +50 -0
- package/bundled-test-harness/assets/dashboard-agents-test-BN5maCgQ.js +334 -0
- package/bundled-test-harness/assets/dashboard-archive-test-BzwUte_Z.js +128 -0
- package/bundled-test-harness/assets/dashboard-delete-test-D2Gcp81V.js +163 -0
- package/bundled-test-harness/assets/dashboard-duplicate-offer-test-BgKNIr35.js +71 -0
- package/bundled-test-harness/assets/dashboard-duplicate-test-D7JEWylc.js +222 -0
- package/bundled-test-harness/assets/dashboard-get-started-test-DOGPzGoA.js +374 -0
- package/bundled-test-harness/assets/dashboard-ir2bakJS.js +142 -0
- package/bundled-test-harness/assets/dashboard-pinned-cards-test-Bn_P9xJU.js +220 -0
- package/bundled-test-harness/assets/dashboard-publish-test-64sGQ0nG.js +70 -0
- package/bundled-test-harness/assets/dashboard-reindex-test-DJjYq1ct.js +115 -0
- package/bundled-test-harness/assets/dashboard-section-rail-test-ZkAhWu5V.js +169 -0
- package/bundled-test-harness/assets/dashboard-state-test-BbkpPB5L.js +162 -0
- package/bundled-test-harness/assets/dashboard-test-CBLdPrSt.js +545 -0
- package/bundled-test-harness/assets/dashboard-unreachable-notice-test-DFT3R1Zx.js +62 -0
- package/bundled-test-harness/assets/dashboard-workspace-test-DqBdCFo2.js +537 -0
- package/bundled-test-harness/assets/dashboard-workspaces-section-test-CH1HDfxR.js +410 -0
- package/bundled-test-harness/assets/data-file-def-preview-test-CNsZwQEJ.js +155 -0
- package/bundled-test-harness/assets/date-time-fields-test-CEFaZTnF.js +359 -0
- package/bundled-test-harness/assets/debug-message-test-0hv0RwE_.js +117 -0
- package/bundled-test-harness/assets/declared-captures-test-C-0yPRU7.js +879 -0
- package/bundled-test-harness/assets/delete-workspace-test-CZOwGy78.js +102 -0
- package/bundled-test-harness/assets/diffing-test-BEKI905O.js +210 -0
- package/bundled-test-harness/assets/download-file-to-realm-test-C1kAGDll.js +119 -0
- package/bundled-test-harness/assets/editor-test-C9x5ZY6g.js +688 -0
- package/bundled-test-harness/assets/edits-D76-aanh.js +651 -0
- package/bundled-test-harness/assets/email-field-test-LGkrB_2B.js +75 -0
- package/bundled-test-harness/assets/enum-field-test-CPyV1J-m.js +935 -0
- package/bundled-test-harness/assets/error-display-test-bWuUtfIG.js +343 -0
- package/bundled-test-harness/assets/evaluate-module-test-CbS5h8t3.js +91 -0
- package/bundled-test-harness/assets/execute-atomic-operations-test-B4Kfco0k.js +113 -0
- package/bundled-test-harness/assets/externals-CDQm-Lm7.js +4393 -0
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-DQSiTzvj.js +207 -0
- package/bundled-test-harness/assets/fallback-banner-test-CJFKLpOy.js +225 -0
- package/bundled-test-harness/assets/fallback-banner-test-DQkrFE4-.js +53 -0
- package/bundled-test-harness/assets/fallback-models-test-CiWfmxaB.js +161 -0
- package/bundled-test-harness/assets/fetch-card-json-test-DULUqUEu.js +61 -0
- package/bundled-test-harness/assets/field-configuration-test-BXZq28xa.js +551 -0
- package/bundled-test-harness/assets/field-markdown-domain-test-DdXCifs6.js +616 -0
- package/bundled-test-harness/assets/field-markdown-oversize-test-DouPPTHX.js +88 -0
- package/bundled-test-harness/assets/field-markdown-primitives-test-DSRGJeyl.js +365 -0
- package/bundled-test-harness/assets/field-markdown-specialized-test-DlTYLl_s.js +534 -0
- package/bundled-test-harness/assets/field-playground-test-NhS4VvoN.js +894 -0
- package/bundled-test-harness/assets/field-support-predicates-test-DWpyT1Qf.js +167 -0
- package/bundled-test-harness/assets/file-attachment-test-m72-VerW.js +796 -0
- package/bundled-test-harness/assets/file-chooser-panel-test-DuAqD9bn.js +153 -0
- package/bundled-test-harness/assets/file-chooser-test-CjaXXwpT.js +504 -0
- package/bundled-test-harness/assets/file-def-format-templates-test-BDs4OmHq.js +380 -0
- package/bundled-test-harness/assets/file-def-live-reload-test-BqTdnq-W.js +124 -0
- package/bundled-test-harness/assets/file-def-menu-items-test-DqdINXsD.js +138 -0
- package/bundled-test-harness/assets/file-def-navigation-test-BPGr0SQy.js +109 -0
- package/bundled-test-harness/assets/file-def-serialization-test-CvjW-FlC.js +89 -0
- package/bundled-test-harness/assets/file-def-test-C-Yv_NjS.js +216 -0
- package/bundled-test-harness/assets/file-preview-live-reload-test-MzwGwasU.js +310 -0
- package/bundled-test-harness/assets/file-resource-primitives-test-D3GmfqNs.js +255 -0
- package/bundled-test-harness/assets/file-tree-from-index-test-CfldnUgm.js +96 -0
- package/bundled-test-harness/assets/file-tree-test--0ZCPRe9.js +851 -0
- package/bundled-test-harness/assets/file-view-model-test-BDIAeBV8.js +346 -0
- package/bundled-test-harness/assets/filedef-export-shape-test-B2tgU404.js +61 -0
- package/bundled-test-harness/assets/film-D1E-odYG.js +13 -0
- package/bundled-test-harness/assets/film-D25Y0ED6.js +2 -0
- package/bundled-test-harness/assets/film-D97U-ydx.js +4074 -0
- package/bundled-test-harness/assets/flac-audio-def-test-ByoXMoQ1.js +143 -0
- package/bundled-test-harness/assets/font-metadata-extractor-test-hawLTDTG.js +415 -0
- package/bundled-test-harness/assets/formatted-aibot-message-test-Bdx_-Ktn.js +109 -0
- package/bundled-test-harness/assets/formatted-user-message-test-CodbrU3t.js +43 -0
- package/bundled-test-harness/assets/freestyle-test-faQhSciz.js +17 -0
- package/bundled-test-harness/assets/full-reindex-realm-test-CE5RJTIC.js +101 -0
- package/bundled-test-harness/assets/garbage-collection-test-v-3sev77.js +403 -0
- package/bundled-test-harness/assets/general-test-DQuxDvXK.js +923 -0
- package/bundled-test-harness/assets/generate-example-cards-one-shot-test-CucWyrkH.js +65 -0
- package/bundled-test-harness/assets/generic-file-def-preview-test-_EDRsebi.js +71 -0
- package/bundled-test-harness/assets/get-available-realm-identifiers-test-CV023yek.js +47 -0
- package/bundled-test-harness/assets/get-catalog-realm-identifiers-test--DOu3DyV.js +47 -0
- package/bundled-test-harness/assets/get-default-writable-realm-test-Bic8jl6R.js +54 -0
- package/bundled-test-harness/assets/get-published-realms-test-DrA5YcFN.js +71 -0
- package/bundled-test-harness/assets/get-realm-of-resource-identifier-test-jfU6SIWn.js +54 -0
- package/bundled-test-harness/assets/get-relationship-membership-state-test-Ccy2Z7MN.js +1308 -0
- package/bundled-test-harness/assets/get-user-system-card-test-Bmq2lmWv.js +67 -0
- package/bundled-test-harness/assets/gif-image-def-test-N1mMQC-X.js +188 -0
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-DzPKH76g.js +160 -0
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-D9mlcQuN.js +74 -0
- package/bundled-test-harness/assets/gts-file-def-test-BL1jpQ9J.js +100 -0
- package/bundled-test-harness/assets/head-format-preview-test-BVCaPQqc.js +158 -0
- package/bundled-test-harness/assets/helpers-Ds68JxHe.js +5 -0
- package/bundled-test-harness/assets/host-mode-service-B4bisRdR.js +262 -0
- package/bundled-test-harness/assets/host-mode-test-BmkN2PCJ.js +831 -0
- package/bundled-test-harness/assets/host-submode-test-C6SxQ796.js +1392 -0
- package/bundled-test-harness/assets/html-component-test-CNQ9wF0Q.js +65 -0
- package/bundled-test-harness/assets/html-def-test-BcaCVVQq.js +160 -0
- package/bundled-test-harness/assets/html-meta-extractor-test-BU1hjkTp.js +60 -0
- package/bundled-test-harness/assets/hydratable-card-test-CX6MWiti.js +426 -0
- package/bundled-test-harness/assets/icon-button-C1zH38Nc.js +67 -0
- package/bundled-test-harness/assets/image-metadata-extractor-test-CakSBPZ_.js +1109 -0
- package/bundled-test-harness/assets/index-changes-test-D8RtgfyG.js +367 -0
- package/bundled-test-harness/assets/index-query-engine-test-BOvxkx07.js +2593 -0
- package/bundled-test-harness/assets/index-writer-test-B_bR2fjw.js +3040 -0
- package/bundled-test-harness/assets/inspector-test-BwPXJj1S.js +2058 -0
- package/bundled-test-harness/assets/instance-filter-matcher-test-COAlkUed.js +788 -0
- package/bundled-test-harness/assets/instantiate-card-test-BVQhZjpq.js +164 -0
- package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DzQLG41H.js +475 -0
- package/bundled-test-harness/assets/interact-submode-setup-C5bKXq73.js +566 -0
- package/bundled-test-harness/assets/invalidate-realm-identifiers-test-Cd3dpjhB.js +99 -0
- package/bundled-test-harness/assets/invite-user-to-room-test-Brabz1tt.js +142 -0
- package/bundled-test-harness/assets/invoke-card-operation-test-C1Q1FUf4.js +333 -0
- package/bundled-test-harness/assets/isolated-render-test-BLJfS7BU.js +51 -0
- package/bundled-test-harness/assets/job-scoped-doc-cache-test-Bgv5woaB.js +181 -0
- package/bundled-test-harness/assets/job-scoped-instance-residency-test-C_bB6KpR.js +103 -0
- package/bundled-test-harness/assets/jpg-image-def-test-gdLIKocD.js +697 -0
- package/bundled-test-harness/assets/json-file-def-test-CPYMRBY-.js +95 -0
- package/bundled-test-harness/assets/key-notices-badge-test-DemslfLw.js +155 -0
- package/bundled-test-harness/assets/key-readiness-test-5tq5JycL.js +190 -0
- package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-BbhDZ2PH.js +398 -0
- package/bundled-test-harness/assets/linksto-error-sentinel-test-C2t7fFPi.js +238 -0
- package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test--U_UvUty.js +354 -0
- package/bundled-test-harness/assets/linksto-many-per-slot-access-test-Dj3Xy0ZF.js +303 -0
- package/bundled-test-harness/assets/linksto-sentinel-reload-test-D0dK4Jjs.js +197 -0
- package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test---IYiXok.js +260 -0
- package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-CT04MhES.js +196 -0
- package/bundled-test-harness/assets/lint-and-fix-test-aadgx7rX.js +51 -0
- package/bundled-test-harness/assets/live-test-BGij_vuc.js +100 -0
- package/bundled-test-harness/assets/live-test-CppvValf.js +2 -0
- package/bundled-test-harness/assets/load-default-skills-test-Cp2m_ebp.js +74 -0
- package/bundled-test-harness/assets/loader-parallel-prefetch-test-vU_26Jqu.js +257 -0
- package/bundled-test-harness/assets/loader-test-CTaw8K_B.js +482 -0
- package/bundled-test-harness/assets/loading-test-DGGt4qZZ.js +63 -0
- package/bundled-test-harness/assets/m4a-audio-def-test-DAiReOXH.js +190 -0
- package/bundled-test-harness/assets/main-DUKPWRts.js +5 -0
- package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-CIXq9FqR.js +470 -0
- package/bundled-test-harness/assets/markdown-embed-chooser-test-zFGh9WfP.js +334 -0
- package/bundled-test-harness/assets/markdown-embed-preview-pane-test-Byn_WFwY.js +447 -0
- package/bundled-test-harness/assets/markdown-embed-preview-test-Y3iFMttg.js +368 -0
- package/bundled-test-harness/assets/markdown-fallback-test-Br1TPkLZ.js +316 -0
- package/bundled-test-harness/assets/markdown-file-def-test-Crm2MAnq.js +380 -0
- package/bundled-test-harness/assets/markdown-helpers-test-CZ9Vvywc.js +188 -0
- package/bundled-test-harness/assets/markdown-highlighting-test-CFMkoVDl.js +244 -0
- package/bundled-test-harness/assets/markdown-preview-Df5fp1SY.js +72 -0
- package/bundled-test-harness/assets/markdown-preview-test-DDaPzsVs.js +238 -0
- package/bundled-test-harness/assets/markdown-skill-frontmatter-test-aH6HQly1.js +146 -0
- package/bundled-test-harness/assets/markdown-skill-search-test-CiNLQs-5.js +80 -0
- package/bundled-test-harness/assets/matrix-service-account-switch-sessions-test-DaA8w1Jj.js +63 -0
- package/bundled-test-harness/assets/matrix-service-boot-assembly-test-21GIlf55.js +300 -0
- package/bundled-test-harness/assets/matrix-service-personal-realm-test-jn9DUENm.js +125 -0
- package/bundled-test-harness/assets/matrix-service-realm-servers-test-eNZVJakl.js +55 -0
- package/bundled-test-harness/assets/matrix-service-realms-list-updated-test-Cabm8_dY.js +132 -0
- package/bundled-test-harness/assets/matrix-service-relogin-test-C77EFgjc.js +59 -0
- package/bundled-test-harness/assets/matrix-service-sliding-sync-test-BgM0fPiO.js +35 -0
- package/bundled-test-harness/assets/menu-Cl50TSFe.js +3561 -0
- package/bundled-test-harness/assets/message-service-subscription-test-CfEqH2jP.js +110 -0
- package/bundled-test-harness/assets/message-service-test-DsTzH1In.js +144 -0
- package/bundled-test-harness/assets/message-tool-test-C5xVfTtj.js +33 -0
- package/bundled-test-harness/assets/midi-audio-def-test-goLRCNCZ.js +182 -0
- package/bundled-test-harness/assets/migrate-skill-test-yPCbVfxG.js +161 -0
- package/bundled-test-harness/assets/mini-YXjrY_tH.js +1404 -0
- package/bundled-test-harness/assets/mini-card-chooser-test-DrllikHB.js +272 -0
- package/bundled-test-harness/assets/mini-file-chooser-test-BfqayhmI.js +201 -0
- package/bundled-test-harness/assets/mock-matrix-C7BrPS6S.js +2 -0
- package/bundled-test-harness/assets/mock-matrix-FjsXmU7-.js +15107 -0
- package/bundled-test-harness/assets/modal-BgaZavcs.js +322 -0
- package/bundled-test-harness/assets/model-cost-tier-test-CZlu1zww.js +174 -0
- package/bundled-test-harness/assets/model-file-extract-test-CjEBupY5.js +206 -0
- package/bundled-test-harness/assets/module-transpile-cache-test-XW6DDsmz.js +67 -0
- package/bundled-test-harness/assets/monaco-test-DkoRuFiQ.js +100 -0
- package/bundled-test-harness/assets/mp3-audio-def-test-v369NNsQ.js +133 -0
- package/bundled-test-harness/assets/multiple-stacks-test-CJpYPWdM.js +208 -0
- package/bundled-test-harness/assets/nested-query-field-render-test-CfDrBcUN.js +249 -0
- package/bundled-test-harness/assets/no-stacks-test-MmsJeLpz.js +48 -0
- package/bundled-test-harness/assets/number-field-test-A7B2r0M5.js +184 -0
- package/bundled-test-harness/assets/office-file-def-test-BNRvFmCB.js +263 -0
- package/bundled-test-harness/assets/office-metadata-extractor-test-zlDoEIEp.js +218 -0
- package/bundled-test-harness/assets/office-poster-capture-test-DdFEaOxR.js +203 -0
- package/bundled-test-harness/assets/ogg-audio-def-test-kk91BzQY.js +196 -0
- package/bundled-test-harness/assets/open-create-listing-modal-test-D1Dl1pov.js +131 -0
- package/bundled-test-harness/assets/open-image-in-new-tab-test-DyCmdMyO.js +52 -0
- package/bundled-test-harness/assets/open-secure-window-test-dz1vPudF.js +253 -0
- package/bundled-test-harness/assets/open-workspace-test-BvTcskzP.js +46 -0
- package/bundled-test-harness/assets/operation-lowering-test-CKkamOQt.js +2957 -0
- package/bundled-test-harness/assets/operations-invocation-test-BMj42rQe.js +523 -0
- package/bundled-test-harness/assets/operations-optimistic-test-KJLyzT8v.js +203 -0
- package/bundled-test-harness/assets/operations-query-test-J3HcnaoK.js +459 -0
- package/bundled-test-harness/assets/operations-store-reconciliation-test-CkbGBMBQ.js +406 -0
- package/bundled-test-harness/assets/operations-test-C7zXXpRW.js +2518 -0
- package/bundled-test-harness/assets/operator-mode-acceptance-test-BPolI_RD.js +1195 -0
- package/bundled-test-harness/assets/operator-mode-card-chooser-test-CQ1v8med.js +1036 -0
- package/bundled-test-harness/assets/operator-mode-links-test-BMHEauS3.js +797 -0
- package/bundled-test-harness/assets/operator-mode-test-blL_JVF8.js +696 -0
- package/bundled-test-harness/assets/operator-mode-ui-test-BG6I7-Hc.js +1045 -0
- package/bundled-test-harness/assets/overlay-D2rQi8lJ.js +427 -0
- package/bundled-test-harness/assets/overlay-menu-items-test-D-zmRQQ0.js +331 -0
- package/bundled-test-harness/assets/overlays-COinwHCP.js +2 -0
- package/bundled-test-harness/assets/overlays-detached-element-test-C73nMXes.js +56 -0
- package/bundled-test-harness/assets/overlays-nTqcu69K.js +75 -0
- package/bundled-test-harness/assets/panel-D9SEMehG.js +15124 -0
- package/bundled-test-harness/assets/past-sessions-test-De9N4wVX.js +321 -0
- package/bundled-test-harness/assets/patch-fields-test-Bp2IE0Jw.js +1014 -0
- package/bundled-test-harness/assets/patch-instance-test-DssuRGKP.js +348 -0
- package/bundled-test-harness/assets/pdf-file-def-test-Barj9ffD.js +111 -0
- package/bundled-test-harness/assets/pdf-metadata-extractor-test-B7KnXcIm.js +130 -0
- package/bundled-test-harness/assets/permission-checking-realm-test-OBzvhDB_.js +306 -0
- package/bundled-test-harness/assets/persist-module-inspector-view-test-BIdbkdPr.js +60 -0
- package/bundled-test-harness/assets/persist-scroll-position-test-Bhb7wJiy.js +254 -0
- package/bundled-test-harness/assets/phone-number-field-test-C2yuCrXY.js +73 -0
- package/bundled-test-harness/assets/pill-menu-test-BIp91YXi.js +60 -0
- package/bundled-test-harness/assets/plate-DAr_pvwC.js +41 -0
- package/bundled-test-harness/assets/plate-DeoQd99m.js +2 -0
- package/bundled-test-harness/assets/player-BvXGBItd.js +2 -0
- package/bundled-test-harness/assets/player-CAVQUyKk.js +82 -0
- package/bundled-test-harness/assets/playground-B02e8uqB.js +58 -0
- package/bundled-test-harness/assets/plural-field-components-test-C1acuN-A.js +198 -0
- package/bundled-test-harness/assets/png-image-def-test-B9QeVo1f.js +266 -0
- package/bundled-test-harness/assets/policy-audit-confirmation-test-CeVquvc_.js +155 -0
- package/bundled-test-harness/assets/policy-scoped-search-test-SFPiIqR3.js +339 -0
- package/bundled-test-harness/assets/prerender-file-extract-test-HSJKAHyO.js +346 -0
- package/bundled-test-harness/assets/prerender-html-test-BTAcFCme.js +670 -0
- package/bundled-test-harness/assets/prerender-meta-test-Csyz2b21.js +614 -0
- package/bundled-test-harness/assets/prerender-module-test-DpTYAbmI.js +409 -0
- package/bundled-test-harness/assets/prerender-persistence-block-test-BhIt-7kK.js +124 -0
- package/bundled-test-harness/assets/prerender-pre-model-error-test-DxKPQKqx.js +61 -0
- package/bundled-test-harness/assets/prerender-serialize-cycle-test-C8V5YWQO.js +134 -0
- package/bundled-test-harness/assets/prerendered-html-read-test-Cq7JVGwg.js +191 -0
- package/bundled-test-harness/assets/pretui-components-test-Ducr9fLT.css +743 -0
- package/bundled-test-harness/assets/pretui-components-test-Hs0uyIUQ.js +992 -0
- package/bundled-test-harness/assets/pretui-primitives-CRs8NRm0.js +69 -0
- package/bundled-test-harness/assets/preview-format-test-cCqLrfdY.js +103 -0
- package/bundled-test-harness/assets/preview-test-BMqJSoR1.js +474 -0
- package/bundled-test-harness/assets/process-card-test-578tfDvr.js +94 -0
- package/bundled-test-harness/assets/profile-settings-modal-CVnNl7Yu.js +990 -0
- package/bundled-test-harness/assets/publish-realm-COoeWexp.js +82 -0
- package/bundled-test-harness/assets/publish-realm-test-a5nkx0Ov.js +210 -0
- package/bundled-test-harness/assets/query-field-barrier-test-qX3xVPfk.js +113 -0
- package/bundled-test-harness/assets/query-field-error-sentinel-test-V6JDPFLX.js +201 -0
- package/bundled-test-harness/assets/query-field-membership-status-test-CK7eDf-K.js +323 -0
- package/bundled-test-harness/assets/query-field-page-optin-test-B5YBHUvU.js +126 -0
- package/bundled-test-harness/assets/query-field-schema-test-D4SjOGlK.js +231 -0
- package/bundled-test-harness/assets/query-field-search-throttle-test-BVkm1-D8.js +154 -0
- package/bundled-test-harness/assets/query-field-stale-prerender-test-9g7hcD91.js +152 -0
- package/bundled-test-harness/assets/query-fields-test-CQYqhzpN.js +535 -0
- package/bundled-test-harness/assets/quick-look-test-icQwb1NJ.js +139 -0
- package/bundled-test-harness/assets/read-card-for-ai-assistant-test-D0mJorwH.js +91 -0
- package/bundled-test-harness/assets/read-file-for-ai-assistant-test-B_F_2GEB.js +45 -0
- package/bundled-test-harness/assets/read-source-test-BgJV4B4F.js +67 -0
- package/bundled-test-harness/assets/read-text-file-test-DaeLzg4u.js +124 -0
- package/bundled-test-harness/assets/realm-C_a9su1j.js +2858 -0
- package/bundled-test-harness/assets/realm-api-keys-D5USFOoS.js +2 -0
- package/bundled-test-harness/assets/realm-api-keys-m_VOcixC.js +578 -0
- package/bundled-test-harness/assets/realm-api-keys-test-C_uZnTmq.js +588 -0
- package/bundled-test-harness/assets/realm-api-keys-test-gtJ8XZCE.js +109 -0
- package/bundled-test-harness/assets/realm-config-m5eccPW8.js +833 -0
- package/bundled-test-harness/assets/realm-config-policy-standing-test-CXJ4ZMde.js +290 -0
- package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-DoEunShH.js +274 -0
- package/bundled-test-harness/assets/realm-config-settings-test-BYi9i4O6.js +187 -0
- package/bundled-test-harness/assets/realm-field-test-B_PUoqnk.js +100 -0
- package/bundled-test-harness/assets/realm-indexing-test-8iLjeV_e.js +4380 -0
- package/bundled-test-harness/assets/realm-policy-fitted-test-Bptvra0U.js +206 -0
- package/bundled-test-harness/assets/realm-policy-test-DwG0qqXE.js +1141 -0
- package/bundled-test-harness/assets/realm-querying-test-Dvw26A6Q.js +1067 -0
- package/bundled-test-harness/assets/realm-server-form-agnostic-test-DrXQH0UP.js +96 -0
- package/bundled-test-harness/assets/realm-server-subscriber-test-Dkj23vQK.js +46 -0
- package/bundled-test-harness/assets/realm-service-info-test-CdRlDhj-.js +67 -0
- package/bundled-test-harness/assets/realm-test-DGYN48Qx.js +2364 -0
- package/bundled-test-harness/assets/realm-token-refresh-test-CEWATL9h.js +153 -0
- package/bundled-test-harness/assets/realm-url-tooltip-test-8ZjTNPuy.js +78 -0
- package/bundled-test-harness/assets/reasoning-test-WUx-4agu.js +221 -0
- package/bundled-test-harness/assets/recent-files-test-Dc6L6Dm4.js +450 -0
- package/bundled-test-harness/assets/reindex-realm-test-CFRSt39u.js +117 -0
- package/bundled-test-harness/assets/relationship-loading-state-test-FKbtOFUr.js +290 -0
- package/bundled-test-harness/assets/remix-card-test-CKGC_Sgq.js +58 -0
- package/bundled-test-harness/assets/rendered-markdown-B_jWmDrK.js +292 -0
- package/bundled-test-harness/assets/rendered-markdown-test-sdWhU0NA.js +587 -0
- package/bundled-test-harness/assets/resident-instance-reuse-test-BjdhE6CM.js +82 -0
- package/bundled-test-harness/assets/result-tile-o6dtjgX4.js +144 -0
- package/bundled-test-harness/assets/rich-markdown-field-test-VXr6l20h.js +1647 -0
- package/bundled-test-harness/assets/room-message-test-BYNhZ39n.js +484 -0
- package/bundled-test-harness/assets/run-FzaqmBEl.js +3959 -0
- package/bundled-test-harness/assets/run-realm-code-DsBUf1si.js +2964 -0
- package/bundled-test-harness/assets/run-realm-code-test-cS0DzaKo.js +3844 -0
- package/bundled-test-harness/assets/sanitize-module-list-test-CvuOOiUY.js +85 -0
- package/bundled-test-harness/assets/save-card-skip-index-wait-test-fpJ1eq32.js +89 -0
- package/bundled-test-harness/assets/schema-editor-test-NkKjCgyf.js +785 -0
- package/bundled-test-harness/assets/schema-generation-test-Dmg3lWl7.js +28 -0
- package/bundled-test-harness/assets/scrolling-test-Dd4gv_fj.js +412 -0
- package/bundled-test-harness/assets/search-adorn-test-CZebk7_y.js +136 -0
- package/bundled-test-harness/assets/search-and-choose-test-Bd4NZUup.js +154 -0
- package/bundled-test-harness/assets/search-correlation-id-test-DXKlEO55.js +139 -0
- package/bundled-test-harness/assets/search-entries-result-test-QQawA8Fm.js +234 -0
- package/bundled-test-harness/assets/search-entries-test-3DlqGPQq.js +1486 -0
- package/bundled-test-harness/assets/search-entries-tool-test-D1TvDE9D.js +504 -0
- package/bundled-test-harness/assets/search-google-images-test-DqsoQGr1.js +166 -0
- package/bundled-test-harness/assets/search-results-DGrNaPxh.js +266 -0
- package/bundled-test-harness/assets/search-results-test-CqVHYNRt.js +578 -0
- package/bundled-test-harness/assets/search-selection-menu-test-D6bIjKiH.js +108 -0
- package/bundled-test-harness/assets/search-sheet-files-test-Bf37TQXo.js +126 -0
- package/bundled-test-harness/assets/search-sheet-persistence-test-CV4_XdxR.js +131 -0
- package/bundled-test-harness/assets/search-test-Dlb-wg3a.js +2249 -0
- package/bundled-test-harness/assets/search-tool-test-BJLgVMoL.js +156 -0
- package/bundled-test-harness/assets/searchable-option-test-eJaIPH_L.js +322 -0
- package/bundled-test-harness/assets/searchable-search-doc-test-yH9fLGNS.js +1271 -0
- package/bundled-test-harness/assets/section-rail-CNFCebtT.js +113 -0
- package/bundled-test-harness/assets/section-rail-test-KNJAWWl6.js +256 -0
- package/bundled-test-harness/assets/secure-sign-in-Dyljp0Th.js +174 -0
- package/bundled-test-harness/assets/secure-sign-in-test-QnqNuTP3.js +373 -0
- package/bundled-test-harness/assets/segmented-control-DxJdoJ4Z.js +173 -0
- package/bundled-test-harness/assets/select-BiQTg2ts.js +175 -0
- package/bundled-test-harness/assets/send-ai-assistant-message-test-CAn7M2dZ.js +52 -0
- package/bundled-test-harness/assets/send-bot-trigger-event-test-qBu5E_jy.js +56 -0
- package/bundled-test-harness/assets/send-request-via-proxy-test-CLuwLBq_.js +380 -0
- package/bundled-test-harness/assets/sending-test-Dt9Dh2wW.js +659 -0
- package/bundled-test-harness/assets/serialization-rri-form-audit-test-hMJukiKt.js +136 -0
- package/bundled-test-harness/assets/serialization-test-W5e3wKbz.js +8758 -0
- package/bundled-test-harness/assets/set-user-system-card-test-CjgWLkNV.js +59 -0
- package/bundled-test-harness/assets/setup-CssMNvui.js +772 -0
- package/bundled-test-harness/assets/setup-D8YXvK-p.js +2 -0
- package/bundled-test-harness/assets/shared-link-target-reuse-test-D42UO8DC.js +207 -0
- package/bundled-test-harness/assets/show-card-test-CHEaS514.js +365 -0
- package/bundled-test-harness/assets/signed-capture-link-test-BgEu0F-S.js +132 -0
- package/bundled-test-harness/assets/single-stack-test-DYcu_v7Z.js +652 -0
- package/bundled-test-harness/assets/skills-test-BP8QNesE.js +648 -0
- package/bundled-test-harness/assets/skip-boot-index-guard-test-BzRIncDN.js +46 -0
- package/bundled-test-harness/assets/spec-test-BYvFR6Xb.js +1077 -0
- package/bundled-test-harness/assets/spinner-Bx9x55NA.js +49 -0
- package/bundled-test-harness/assets/src-LqENIikj.js +5 -0
- package/bundled-test-harness/assets/src-a4d10Hra.js +216 -0
- package/bundled-test-harness/assets/stick-to-bottom-resize-test-BBLiCR3X.js +56 -0
- package/bundled-test-harness/assets/store-add-test-D_9IHQjZ.js +50 -0
- package/bundled-test-harness/assets/store-module-rebuild-test-BRGZoLRV.js +454 -0
- package/bundled-test-harness/assets/store-search-test-3G8JHuj2.js +175 -0
- package/bundled-test-harness/assets/store-test-Dd4WQp7L.js +3672 -0
- package/bundled-test-harness/assets/structured-theme-test-11TNsgUW.js +377 -0
- package/bundled-test-harness/assets/summarize-session-test-CwzD_ZbD.js +172 -0
- package/bundled-test-harness/assets/svg-image-def-test-zV6aMK9q.js +167 -0
- package/bundled-test-harness/assets/switch-submode-test-DQU2cP5_.js +168 -0
- package/bundled-test-harness/assets/sync-openrouter-models-test-xrXVaC2H.js +97 -0
- package/bundled-test-harness/assets/test-support-QTh6wGxu.js +3 -0
- package/bundled-test-harness/assets/test-support-Tr-PYFgc.js +99 -0
- package/bundled-test-harness/assets/tests-zLlwPutr.js +3598 -0
- package/bundled-test-harness/assets/text-file-def-test-Cyq78UFY.js +94 -0
- package/bundled-test-harness/assets/text-input-validator-test-C1uDVZU7.js +156 -0
- package/bundled-test-harness/assets/text-suggestion-test-C4XAqWqY.js +340 -0
- package/bundled-test-harness/assets/theme-card-test-dVNz4tgU.js +621 -0
- package/bundled-test-harness/assets/theme-dashboard-nav-test-DYSn5pqo.js +196 -0
- package/bundled-test-harness/assets/theme-scheme-island-test-C1WpkfEP.js +264 -0
- package/bundled-test-harness/assets/theme-scoped-css-parity-test-BVluppsE.js +176 -0
- package/bundled-test-harness/assets/titles-0a1luoTq.js +52 -0
- package/bundled-test-harness/assets/titles-DKHNLVwC.js +2 -0
- package/bundled-test-harness/assets/to-device-streaming-test-3A6jI0_r.js +163 -0
- package/bundled-test-harness/assets/token-usage-test-33ovcqPk.js +160 -0
- package/bundled-test-harness/assets/tools-J_Knr_W6.js +774 -0
- package/bundled-test-harness/assets/tools-calling-test-CfqZX0Ed.js +200 -0
- package/bundled-test-harness/assets/tools-test-B4x58ZmI.js +1624 -0
- package/bundled-test-harness/assets/tools-test-DtUQp5ez.js +3204 -0
- package/bundled-test-harness/assets/tooltip-B0rEgyMW.css +66 -0
- package/bundled-test-harness/assets/tooltip-DvUMUgVX.js +195 -0
- package/bundled-test-harness/assets/transform-cards-test-CYQbZeD9.js +341 -0
- package/bundled-test-harness/assets/ts-file-def-preview-test-m39f8Zio.js +95 -0
- package/bundled-test-harness/assets/ts-file-def-test-xIcL5xWe.js +92 -0
- package/bundled-test-harness/assets/ttf-font-def-test-ClQ2SzFF.js +206 -0
- package/bundled-test-harness/assets/turn-settling-test-DqYk312r.js +160 -0
- package/bundled-test-harness/assets/turn-summary-Bmt7ZxTS.js +1039 -0
- package/bundled-test-harness/assets/unpublish-realm-test-0ToTJczx.js +102 -0
- package/bundled-test-harness/assets/update-room-skills-test-o_j8NOUV.js +240 -0
- package/bundled-test-harness/assets/use-ai-assistant-test-D7HFpxKJ.js +384 -0
- package/bundled-test-harness/assets/user-message-BAOt1hS3.js +262 -0
- package/bundled-test-harness/assets/validate-realm-test-e3xIbNLB.js +67 -0
- package/bundled-test-harness/assets/video-metadata-extractor-test-D8naLSlg.js +520 -0
- package/bundled-test-harness/assets/view-visually-test-BuhGau5E.js +335 -0
- package/bundled-test-harness/assets/virtual-network-reset-test-CgaFNGPi.js +96 -0
- package/bundled-test-harness/assets/wav-audio-def-test-CWG_UdCh.js +160 -0
- package/bundled-test-harness/assets/webp-image-def-test-sN4yw8Zu.js +226 -0
- package/bundled-test-harness/assets/workspace-0LfPqbYB.js +445 -0
- package/bundled-test-harness/assets/workspace-a11y-test-DQxYDRAP.js +197 -0
- package/bundled-test-harness/assets/workspace-actions-jGJSfl8M.js +588 -0
- package/bundled-test-harness/assets/workspace-behavior-test-BnF-bmBN.js +338 -0
- package/bundled-test-harness/assets/workspace-delete-multiple-test-D-rxPDuT.js +212 -0
- package/bundled-test-harness/assets/workspace-delete-summary-test-C2-Mve5R.js +63 -0
- package/bundled-test-harness/assets/workspace-hosting-test-BvDKdlOb.js +138 -0
- package/bundled-test-harness/assets/workspace-indexing-test-B34T3kqD.js +71 -0
- package/bundled-test-harness/assets/workspace-test-CJivgv-m.js +51 -0
- package/bundled-test-harness/assets/workspace-test-CuSRpPnQ.js +385 -0
- package/bundled-test-harness/assets/workspace-timestamp-labels-test-aWgjdbCp.js +68 -0
- package/bundled-test-harness/assets/workspace-unit-test-DHMUf2KT.js +122 -0
- package/bundled-test-harness/assets/write-binary-file-test-P-hVQuin.js +124 -0
- package/bundled-test-harness/assets/write-text-file-test-fXvJueDd.js +191 -0
- package/bundled-test-harness/assets/zip-archive-test-C2P5CUSR.js +285 -0
- package/bundled-test-harness/assets/zip-file-def-test-BfJZAmGt.js +164 -0
- package/bundled-test-harness/boxel-ui-checksum.txt +1 -1
- package/bundled-test-harness/index.html +47 -47
- package/bundled-test-harness/tests/index.html +49 -49
- package/bundled-types/boxel-ui/helpers/theme-scoped-css.ts +4 -0
- package/bundled-types/choreo/choreo.gts +13 -1
- package/bundled-types/choreo/run.ts +19 -0
- package/bundled-types/host-app/components/operator-mode/dashboard/get-started.gts +152 -7
- package/bundled-types/host-app/components/operator-mode/dashboard/index.gts +2 -0
- package/bundled-types/host-app/components/operator-mode/dashboard/workspace.gts +5 -3
- package/bundled-types/host-app/components/operator-mode/dashboard-modals/workspace-modals.gts +5 -22
- package/bundled-types/host-app/components/operator-mode/host-submode/publishing-realm-popover.gts +1 -1
- package/bundled-types/host-app/components/operator-mode/host-submode.gts +111 -37
- package/bundled-types/host-app/components/operator-mode/publish-realm-modal.gts +1 -0
- package/bundled-types/host-app/lib/modal-focus-trap.ts +33 -0
- package/bundled-types/host-app/lib/workspace-actions.ts +21 -0
- package/bundled-types/host-app/services/host-mode-service.ts +39 -0
- package/bundled-types/host-app/services/realm.ts +14 -0
- package/bundled-types/host-tests/helpers/dashboard.ts +67 -0
- package/package.json +1 -1
- package/bundled-test-harness/assets/account-switch-failed-test-FytUFiPO.js +0 -45
- package/bundled-test-harness/assets/adapter-DvmPwSZv.js +0 -2
- package/bundled-test-harness/assets/add-field-to-card-definition-tool-test-DN525jiY.js +0 -112
- package/bundled-test-harness/assets/ai-assistant-create-workspace-test-q3tKqVJQ.js +0 -130
- package/bundled-test-harness/assets/ai-assistant-panel-relogin-test-DgeXcCyi.js +0 -46
- package/bundled-test-harness/assets/ai-assistant-test-lDIGPKFP.js +0 -2223
- package/bundled-test-harness/assets/ai-function-generation-test-D5GbLyvL.js +0 -1176
- package/bundled-test-harness/assets/ai-module-creation-test-I3-j2beD.js +0 -151
- package/bundled-test-harness/assets/aibot-message-Dmsjifs6.js +0 -1312
- package/bundled-test-harness/assets/app-BS9_-DhN.js +0 -14146
- package/bundled-test-harness/assets/apply-markdown-edit-test-4zlwt0Db.js +0 -230
- package/bundled-test-harness/assets/ask-user-picker-Dr-0qpNr.js +0 -370
- package/bundled-test-harness/assets/ask-user-picker-test-633AFdmS.js +0 -39
- package/bundled-test-harness/assets/assistant-transcript-test-BgRnLvMg.js +0 -57
- package/bundled-test-harness/assets/audio-metadata-extractor-test-4xsQqL-0.js +0 -1176
- package/bundled-test-harness/assets/authed-fetch-test-663mT5_N.js +0 -73
- package/bundled-test-harness/assets/avif-image-def-test-h01BPIJy.js +0 -187
- package/bundled-test-harness/assets/basic-test-DiD6T-8Q.js +0 -139
- package/bundled-test-harness/assets/binary-upload-dedupe-test-CkjMPO_e.js +0 -308
- package/bundled-test-harness/assets/bot-registration-test-CFZHpwdj.js +0 -97
- package/bundled-test-harness/assets/box-test-C3pSy5ED.js +0 -50
- package/bundled-test-harness/assets/brand-guide-attachments-test-EoC_u7Vc.js +0 -84
- package/bundled-test-harness/assets/brand-guide-custom-css-test-Dn3fvblr.js +0 -196
- package/bundled-test-harness/assets/brand-guide-edit-test-NeiT3MyK.js +0 -140
- package/bundled-test-harness/assets/brand-logo-mark-field-test-C2A1EnBB.js +0 -86
- package/bundled-test-harness/assets/broken-link-template-test-CWn6V5zZ.js +0 -192
- package/bundled-test-harness/assets/bundled-base-modules-test-D7mLzpsw.js +0 -54
- package/bundled-test-harness/assets/bundled-base-oracle-test-I7xCId_k.js +0 -37
- package/bundled-test-harness/assets/buried-stack-item-scroll-test-DFBev0h-.js +0 -236
- package/bundled-test-harness/assets/button-BeSuhveJ.js +0 -207
- package/bundled-test-harness/assets/bxl-cyclic-graph-test-DPykwvvx.js +0 -47
- package/bundled-test-harness/assets/bxl-expression-test-LBWJiFb9.js +0 -250
- package/bundled-test-harness/assets/bxl-indexing-test-BuZmLk7y.js +0 -212
- package/bundled-test-harness/assets/bxl-platform-module-test-BNIvlkCM.js +0 -71
- package/bundled-test-harness/assets/can-invoke-test-t-bFIIeX.js +0 -455
- package/bundled-test-harness/assets/can-read-realm-test-2Q_MzRT9.js +0 -56
- package/bundled-test-harness/assets/cancel-indexing-job-test-QeYxEukn.js +0 -69
- package/bundled-test-harness/assets/capture-test-CJmJG8YR.js +0 -360
- package/bundled-test-harness/assets/card-api-test-B43I510H.js +0 -198
- package/bundled-test-harness/assets/card-basics-test-CBClzP2y.js +0 -5364
- package/bundled-test-harness/assets/card-chooser-paging-test-HEVzf6pR.js +0 -235
- package/bundled-test-harness/assets/card-chooser-test-GfjBRPFI.js +0 -393
- package/bundled-test-harness/assets/card-context-search-results-CoSr4EdS.js +0 -30
- package/bundled-test-harness/assets/card-context-search-results-test-BLMlZu9t.js +0 -184
- package/bundled-test-harness/assets/card-def-field-def-relationships-test-DEBOzKan.js +0 -562
- package/bundled-test-harness/assets/card-def-menu-items-test-88_h8o0D.js +0 -228
- package/bundled-test-harness/assets/card-delete-test-DKom1phy.js +0 -466
- package/bundled-test-harness/assets/card-error-awaiting-index-test-DEwgFZMP.js +0 -53
- package/bundled-test-harness/assets/card-error-r6_cXst9.js +0 -72
- package/bundled-test-harness/assets/card-info-thumbnail-picker-test-B7LiY15e.js +0 -219
- package/bundled-test-harness/assets/card-playground-test-CgyIJHui.js +0 -1491
- package/bundled-test-harness/assets/card-prerender-rPfzpIOU.js +0 -12939
- package/bundled-test-harness/assets/card-thunk-error-test-L0pvg4Ce.js +0 -48
- package/bundled-test-harness/assets/card-type-service-test-B2dhqxSD.js +0 -161
- package/bundled-test-harness/assets/check-correctness-test-DgqaLlCW.js +0 -1093
- package/bundled-test-harness/assets/check-domain-availability-test-B0hJHY5l.js +0 -98
- package/bundled-test-harness/assets/chip-D01NW3WH.js +0 -44
- package/bundled-test-harness/assets/choreo-D2Jl79RU.js +0 -1019
- package/bundled-test-harness/assets/choreo-_E8SOEe-.js +0 -2
- package/bundled-test-harness/assets/choreo-feature-reel-test-WLjsZDmS.js +0 -155
- package/bundled-test-harness/assets/choreo-gallery-build-order-test-6jnS8PsS.js +0 -436
- package/bundled-test-harness/assets/choreo-gallery-compositor-test-CbUZsVB6.js +0 -399
- package/bundled-test-harness/assets/choreo-gallery-cover-test-CbvAStgk.js +0 -214
- package/bundled-test-harness/assets/choreo-gallery-crossing-stage-test-tdjvUSa6.js +0 -133
- package/bundled-test-harness/assets/choreo-gallery-demos-alive-test-CsnM3hQK.js +0 -42
- package/bundled-test-harness/assets/choreo-gallery-drift-test-DG2LQTa7.js +0 -620
- package/bundled-test-harness/assets/choreo-gallery-escort-test-mn3-qXP1.js +0 -187
- package/bundled-test-harness/assets/choreo-gallery-films-test-BuktaC0D.js +0 -140
- package/bundled-test-harness/assets/choreo-gallery-filter-test-Dd-zpps0.js +0 -46
- package/bundled-test-harness/assets/choreo-gallery-fold-test-CWc1ijGc.js +0 -180
- package/bundled-test-harness/assets/choreo-gallery-guide-pages-test-tk2QmYPU.js +0 -114
- package/bundled-test-harness/assets/choreo-gallery-guides-test-DVbf1zM4.js +0 -321
- package/bundled-test-harness/assets/choreo-gallery-hang-test-B7EFp2dx.js +0 -426
- package/bundled-test-harness/assets/choreo-gallery-highlight-test-BFgbdesP.js +0 -60
- package/bundled-test-harness/assets/choreo-gallery-inline-edit-test-DJb8FC5R.js +0 -370
- package/bundled-test-harness/assets/choreo-gallery-interruption-test-DWyMXo5D.js +0 -176
- package/bundled-test-harness/assets/choreo-gallery-lone-stack-test-D3b8LsJ6.js +0 -104
- package/bundled-test-harness/assets/choreo-gallery-navigation-test-CjjU6Rvn.js +0 -193
- package/bundled-test-harness/assets/choreo-gallery-playhead-transport-test-Le_h3QWU.js +0 -111
- package/bundled-test-harness/assets/choreo-gallery-poplayout-subtree-test-Cp-DlWj4.js +0 -127
- package/bundled-test-harness/assets/choreo-gallery-presence-modes-test-DayS4GCJ.js +0 -100
- package/bundled-test-harness/assets/choreo-gallery-presentation-test-DeAfuFS7.js +0 -157
- package/bundled-test-harness/assets/choreo-gallery-reduced-motion-test-BgPWpggq.js +0 -145
- package/bundled-test-harness/assets/choreo-gallery-sheet-standalone-test-PzyoMNYv.js +0 -89
- package/bundled-test-harness/assets/choreo-gallery-sheet-test-CxaiNBkL.js +0 -48
- package/bundled-test-harness/assets/choreo-gallery-site-test-6xtSntS5.js +0 -237
- package/bundled-test-harness/assets/choreo-gallery-stage-E6Q5r-zU.js +0 -256
- package/bundled-test-harness/assets/choreo-gallery-stage-keyboard-test-C7aWMr9a.js +0 -102
- package/bundled-test-harness/assets/choreo-gallery-stages-test-CDWWgC61.js +0 -35
- package/bundled-test-harness/assets/choreo-gallery-subdivision-test-Bkp15XJv.js +0 -138
- package/bundled-test-harness/assets/choreo-gallery-table-plan-test-CcGRi_3O.js +0 -144
- package/bundled-test-harness/assets/choreo-gallery-theater-test-Qph5pLT_.js +0 -252
- package/bundled-test-harness/assets/choreo-gallery-tuning-test-C4DhFLVA.js +0 -95
- package/bundled-test-harness/assets/choreo-gallery-widget-room-test-LK493r1M.js +0 -88
- package/bundled-test-harness/assets/choreo-gallery-wires-test-B7SeUCc8.js +0 -148
- package/bundled-test-harness/assets/client-telemetry-test-DGmHzAFx.js +0 -340
- package/bundled-test-harness/assets/clip-BpYQPVz_.js +0 -2
- package/bundled-test-harness/assets/clip-CNaYbIwL.js +0 -92
- package/bundled-test-harness/assets/code-block-Cp2CJo5-.js +0 -502
- package/bundled-test-harness/assets/code-ref-test-C8JBHDb-.js +0 -163
- package/bundled-test-harness/assets/code-submode-availability-test-CzG1Tv6L.js +0 -198
- package/bundled-test-harness/assets/code-submode-test-BclVWjm5.js +0 -1839
- package/bundled-test-harness/assets/codeblocks-test-CmQlyxN7.js +0 -418
- package/bundled-test-harness/assets/codemirror-editor-test-B74H_yn8.js +0 -1512
- package/bundled-test-harness/assets/codemirror-embed-toolbar-test-Bz6VEysU.js +0 -366
- package/bundled-test-harness/assets/color-field-test-DMCPQKIP.js +0 -212
- package/bundled-test-harness/assets/compaction-test-saQCLBrQ.js +0 -150
- package/bundled-test-harness/assets/computed-test-C05HliJC.js +0 -1320
- package/bundled-test-harness/assets/container-Cqcwrd-m.js +0 -10857
- package/bundled-test-harness/assets/content-preview-components-test-DZPj4_CU.js +0 -462
- package/bundled-test-harness/assets/copy-and-edit-test-DiXTQNTF.js +0 -292
- package/bundled-test-harness/assets/copy-card-test-ys7GquUY.js +0 -218
- package/bundled-test-harness/assets/copy-file-to-realm-test-Gn0Wn4vT.js +0 -148
- package/bundled-test-harness/assets/copy-source-test-BTLrOmPm.js +0 -56
- package/bundled-test-harness/assets/create-file-test-BCeIW-Rt.js +0 -464
- package/bundled-test-harness/assets/create-file-test-DbHQ5JsS.js +0 -1086
- package/bundled-test-harness/assets/create-listing-modal-test-CeHc4ter.js +0 -273
- package/bundled-test-harness/assets/create-listing-pr-request-test-DXbJNfMh.js +0 -117
- package/bundled-test-harness/assets/create-spec-test-BDIZoyHT.js +0 -256
- package/bundled-test-harness/assets/create-submission-workflow-test-Bix5J-3A.js +0 -132
- package/bundled-test-harness/assets/create-workspace-test-BmNnLHwC.js +0 -104
- package/bundled-test-harness/assets/credential-fields-test-NK1F4QWn.js +0 -200
- package/bundled-test-harness/assets/csv-file-def-test-BSfs4TTP.js +0 -102
- package/bundled-test-harness/assets/dashboard-C4T7ffKY.js +0 -3576
- package/bundled-test-harness/assets/dashboard-CFeHuP5-.js +0 -81
- package/bundled-test-harness/assets/dashboard-DQlpW-ux.css +0 -2392
- package/bundled-test-harness/assets/dashboard-add-workspace-test--rr6objf.js +0 -50
- package/bundled-test-harness/assets/dashboard-agents-test-D1y8H4xH.js +0 -334
- package/bundled-test-harness/assets/dashboard-archive-test-bN4EQaXv.js +0 -128
- package/bundled-test-harness/assets/dashboard-delete-test-BvsASb8B.js +0 -163
- package/bundled-test-harness/assets/dashboard-duplicate-offer-test-DEsd5ZzZ.js +0 -71
- package/bundled-test-harness/assets/dashboard-duplicate-test-BnR0sTgB.js +0 -222
- package/bundled-test-harness/assets/dashboard-get-started-test-DG4uUXLv.js +0 -246
- package/bundled-test-harness/assets/dashboard-pinned-cards-test-AoGGVRAS.js +0 -220
- package/bundled-test-harness/assets/dashboard-reindex-test-BN9a96Xp.js +0 -115
- package/bundled-test-harness/assets/dashboard-section-rail-test-B3OT9V2T.js +0 -169
- package/bundled-test-harness/assets/dashboard-state-test-BY0Zqrmj.js +0 -162
- package/bundled-test-harness/assets/dashboard-test-C13oNpWt.js +0 -545
- package/bundled-test-harness/assets/dashboard-unreachable-notice-test-DZIV4x5j.js +0 -62
- package/bundled-test-harness/assets/dashboard-workspace-test-CBnOQViI.js +0 -537
- package/bundled-test-harness/assets/dashboard-workspaces-section-test-KU8ZVOYp.js +0 -396
- package/bundled-test-harness/assets/data-file-def-preview-test-CI5gcdtK.js +0 -155
- package/bundled-test-harness/assets/date-time-fields-test-D2CpR_Pb.js +0 -359
- package/bundled-test-harness/assets/debug-message-test-Df1kHesw.js +0 -117
- package/bundled-test-harness/assets/declared-captures-test-hQ43zuox.js +0 -879
- package/bundled-test-harness/assets/delete-workspace-test-BhfMKsix.js +0 -102
- package/bundled-test-harness/assets/diffing-test-CHRh55mC.js +0 -210
- package/bundled-test-harness/assets/download-file-to-realm-test-CC1HURCi.js +0 -119
- package/bundled-test-harness/assets/editor-test-DkeCv28f.js +0 -688
- package/bundled-test-harness/assets/edits-BSJqtUXM.js +0 -651
- package/bundled-test-harness/assets/email-field-test-DihK0suO.js +0 -75
- package/bundled-test-harness/assets/enum-field-test-Gja3bzt5.js +0 -935
- package/bundled-test-harness/assets/error-display-test-GhYZu7cp.js +0 -343
- package/bundled-test-harness/assets/evaluate-module-test-D_t4CiUq.js +0 -91
- package/bundled-test-harness/assets/execute-atomic-operations-test-xtou8Zeg.js +0 -113
- package/bundled-test-harness/assets/externals-B02-sD_L.js +0 -4393
- package/bundled-test-harness/assets/fallback-banner-live-delete-test-DtxzNXdE.js +0 -207
- package/bundled-test-harness/assets/fallback-banner-test-BfmiQ_68.js +0 -53
- package/bundled-test-harness/assets/fallback-banner-test-DLtTdmvn.js +0 -225
- package/bundled-test-harness/assets/fallback-models-test-BxNJxhfd.js +0 -161
- package/bundled-test-harness/assets/fetch-card-json-test-DofKbzvC.js +0 -61
- package/bundled-test-harness/assets/field-configuration-test-SUoPaXWy.js +0 -551
- package/bundled-test-harness/assets/field-markdown-domain-test-BwtR0dPP.js +0 -616
- package/bundled-test-harness/assets/field-markdown-oversize-test-D8UJcBc3.js +0 -88
- package/bundled-test-harness/assets/field-markdown-primitives-test-D5_ZdoDO.js +0 -365
- package/bundled-test-harness/assets/field-markdown-specialized-test-Dpd5hs04.js +0 -534
- package/bundled-test-harness/assets/field-playground-test-CzhYzKGv.js +0 -894
- package/bundled-test-harness/assets/field-support-predicates-test-BSvVOFth.js +0 -167
- package/bundled-test-harness/assets/file-attachment-test-fM-yFedm.js +0 -796
- package/bundled-test-harness/assets/file-chooser-panel-test-CKj8YTdY.js +0 -153
- package/bundled-test-harness/assets/file-chooser-test-Bs8jFXqa.js +0 -504
- package/bundled-test-harness/assets/file-def-format-templates-test-CxrRoWoD.js +0 -380
- package/bundled-test-harness/assets/file-def-live-reload-test-X_8YEkve.js +0 -124
- package/bundled-test-harness/assets/file-def-menu-items-test-Dx879o_o.js +0 -138
- package/bundled-test-harness/assets/file-def-navigation-test-MMI_EEO1.js +0 -109
- package/bundled-test-harness/assets/file-def-serialization-test-B5lguBQD.js +0 -89
- package/bundled-test-harness/assets/file-def-test-Di9QWcrj.js +0 -216
- package/bundled-test-harness/assets/file-preview-live-reload-test-aqx93A7c.js +0 -310
- package/bundled-test-harness/assets/file-resource-primitives-test-a5abpcSB.js +0 -255
- package/bundled-test-harness/assets/file-tree-from-index-test-CnruGxJ8.js +0 -96
- package/bundled-test-harness/assets/file-tree-test-BCyWDdSE.js +0 -851
- package/bundled-test-harness/assets/file-view-model-test-BfpLa01Y.js +0 -346
- package/bundled-test-harness/assets/filedef-export-shape-test-CQ9XbrzS.js +0 -61
- package/bundled-test-harness/assets/film-CL1zj_bJ.js +0 -2
- package/bundled-test-harness/assets/film-Dq_quZ31.js +0 -13
- package/bundled-test-harness/assets/film-xbkQa060.js +0 -4074
- package/bundled-test-harness/assets/flac-audio-def-test-BmVp9dMx.js +0 -143
- package/bundled-test-harness/assets/focus-Dm4wkM72.js +0 -306
- package/bundled-test-harness/assets/font-metadata-extractor-test-OWEh9_MS.js +0 -415
- package/bundled-test-harness/assets/formatted-aibot-message-test-BpHsWpuV.js +0 -109
- package/bundled-test-harness/assets/formatted-user-message-test-DZW5TAr0.js +0 -43
- package/bundled-test-harness/assets/freestyle-test-D_uaPU_3.js +0 -17
- package/bundled-test-harness/assets/full-reindex-realm-test-C6vHL5kC.js +0 -101
- package/bundled-test-harness/assets/garbage-collection-test-D-Ao4t2n.js +0 -403
- package/bundled-test-harness/assets/general-test-PSGI8W0z.js +0 -923
- package/bundled-test-harness/assets/generate-example-cards-one-shot-test-J-m-0E6W.js +0 -65
- package/bundled-test-harness/assets/generic-file-def-preview-test-BAsOhTYU.js +0 -71
- package/bundled-test-harness/assets/get-available-realm-identifiers-test-D5PBOr97.js +0 -47
- package/bundled-test-harness/assets/get-catalog-realm-identifiers-test-NM9UURHE.js +0 -47
- package/bundled-test-harness/assets/get-default-writable-realm-test-BxXc9a3J.js +0 -54
- package/bundled-test-harness/assets/get-published-realms-test-C8TJEc4-.js +0 -71
- package/bundled-test-harness/assets/get-realm-of-resource-identifier-test-Dt8CB6lS.js +0 -54
- package/bundled-test-harness/assets/get-relationship-membership-state-test-9_8x3myJ.js +0 -1308
- package/bundled-test-harness/assets/get-user-system-card-test-k0UO-uba.js +0 -67
- package/bundled-test-harness/assets/gif-image-def-test-BWrqPGDX.js +0 -188
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-in-cards-test-BgG8QI9E.js +0 -160
- package/bundled-test-harness/assets/glimmer-motion-and-choreo-test-BKOvNyCN.js +0 -74
- package/bundled-test-harness/assets/gts-file-def-test-BCRHwDeZ.js +0 -100
- package/bundled-test-harness/assets/head-format-preview-test-DnfUhniI.js +0 -158
- package/bundled-test-harness/assets/helpers-DklkegO_.js +0 -5
- package/bundled-test-harness/assets/host-mode-service-vOfN0smp.js +0 -232
- package/bundled-test-harness/assets/host-mode-test-CCCJFz6_.js +0 -831
- package/bundled-test-harness/assets/host-submode-test-CtCfbuPA.js +0 -1342
- package/bundled-test-harness/assets/html-component-test-CWyhb5ZX.js +0 -65
- package/bundled-test-harness/assets/html-def-test-Cb8C2lUx.js +0 -160
- package/bundled-test-harness/assets/html-meta-extractor-test-BHT9Rtir.js +0 -60
- package/bundled-test-harness/assets/hydratable-card-test-DpgpdesD.js +0 -426
- package/bundled-test-harness/assets/icon-button-ABCGVF3C.js +0 -67
- package/bundled-test-harness/assets/image-metadata-extractor-test-ClhPTouq.js +0 -1109
- package/bundled-test-harness/assets/index-changes-test-CgnVr3LH.js +0 -367
- package/bundled-test-harness/assets/index-query-engine-test-CQTwju5_.js +0 -2593
- package/bundled-test-harness/assets/index-writer-test-IoVOoZT2.js +0 -3040
- package/bundled-test-harness/assets/inspector-test-BN2Ieb77.js +0 -2058
- package/bundled-test-harness/assets/instance-filter-matcher-test-Bq-_Sy89.js +0 -788
- package/bundled-test-harness/assets/instantiate-card-test-DEeDTzFV.js +0 -164
- package/bundled-test-harness/assets/interact-submode-creation-and-permissions-test-DP6kOyJS.js +0 -475
- package/bundled-test-harness/assets/interact-submode-setup-B0_cHqH-.js +0 -566
- package/bundled-test-harness/assets/invalidate-realm-identifiers-test-9uUD91Pw.js +0 -99
- package/bundled-test-harness/assets/invite-user-to-room-test-CcDA45Ac.js +0 -142
- package/bundled-test-harness/assets/invoke-card-operation-test-DmUtgueM.js +0 -333
- package/bundled-test-harness/assets/isolated-render-test-B2eXNHu6.js +0 -51
- package/bundled-test-harness/assets/job-scoped-doc-cache-test-DF9D7cOc.js +0 -181
- package/bundled-test-harness/assets/job-scoped-instance-residency-test-CSS8xUU5.js +0 -103
- package/bundled-test-harness/assets/jpg-image-def-test-voECMTht.js +0 -697
- package/bundled-test-harness/assets/json-file-def-test-8Y4KLjUC.js +0 -95
- package/bundled-test-harness/assets/key-notices-badge-test-d1mYqx0e.js +0 -155
- package/bundled-test-harness/assets/key-readiness-test-BtCg7PCk.js +0 -190
- package/bundled-test-harness/assets/linksto-broken-link-placeholder-test-CyCMbJnN.js +0 -398
- package/bundled-test-harness/assets/linksto-error-sentinel-test-BDW572-v.js +0 -238
- package/bundled-test-harness/assets/linksto-many-broken-link-placeholder-test-B4wM97hD.js +0 -354
- package/bundled-test-harness/assets/linksto-many-per-slot-access-test-BhJmtJ0_.js +0 -303
- package/bundled-test-harness/assets/linksto-sentinel-reload-test-BpBQ5V_i.js +0 -197
- package/bundled-test-harness/assets/linksto-sentinel-roundtrip-test-pkBBl4e9.js +0 -260
- package/bundled-test-harness/assets/linksto-singular-js-access-contract-test-Bb6wjUdD.js +0 -196
- package/bundled-test-harness/assets/lint-and-fix-test-CcMLn-co.js +0 -51
- package/bundled-test-harness/assets/live-test-AyBnq7BX.js +0 -2
- package/bundled-test-harness/assets/live-test-CgnAcIDw.js +0 -100
- package/bundled-test-harness/assets/load-default-skills-test-BIOwtx0Y.js +0 -74
- package/bundled-test-harness/assets/loader-parallel-prefetch-test-D5_oRSER.js +0 -257
- package/bundled-test-harness/assets/loader-test-DSc_jR1c.js +0 -482
- package/bundled-test-harness/assets/loading-test-8pldx7S-.js +0 -63
- package/bundled-test-harness/assets/m4a-audio-def-test-BDI5apzM.js +0 -190
- package/bundled-test-harness/assets/main-5kHyCkdm.js +0 -5
- package/bundled-test-harness/assets/markdown-embed-chooser-modal-test-Wud0s7WZ.js +0 -470
- package/bundled-test-harness/assets/markdown-embed-chooser-test-DVzzS-0C.js +0 -334
- package/bundled-test-harness/assets/markdown-embed-preview-pane-test-B5W_iqsi.js +0 -447
- package/bundled-test-harness/assets/markdown-embed-preview-test-CZF_s0fB.js +0 -368
- package/bundled-test-harness/assets/markdown-fallback-test-fT6BS4W7.js +0 -316
- package/bundled-test-harness/assets/markdown-file-def-test-B1aTzazR.js +0 -380
- package/bundled-test-harness/assets/markdown-helpers-test-gNKZf7Mw.js +0 -188
- package/bundled-test-harness/assets/markdown-highlighting-test-Du5_CQmD.js +0 -244
- package/bundled-test-harness/assets/markdown-preview-h-_aJhRc.js +0 -72
- package/bundled-test-harness/assets/markdown-preview-test-DJvoVsXw.js +0 -238
- package/bundled-test-harness/assets/markdown-skill-frontmatter-test-VwJi3Paj.js +0 -146
- package/bundled-test-harness/assets/markdown-skill-search-test-ysCdf0xM.js +0 -80
- package/bundled-test-harness/assets/matrix-service-account-switch-sessions-test-K2JuMy36.js +0 -63
- package/bundled-test-harness/assets/matrix-service-boot-assembly-test-CkdL_-os.js +0 -300
- package/bundled-test-harness/assets/matrix-service-personal-realm-test-Dy1DultK.js +0 -125
- package/bundled-test-harness/assets/matrix-service-realm-servers-test-DHDDKuEg.js +0 -55
- package/bundled-test-harness/assets/matrix-service-realms-list-updated-test-DcTbZpMl.js +0 -132
- package/bundled-test-harness/assets/matrix-service-relogin-test-D3NQktoa.js +0 -59
- package/bundled-test-harness/assets/matrix-service-sliding-sync-test-6CAflWOA.js +0 -35
- package/bundled-test-harness/assets/menu-kUSaJIPq.js +0 -3562
- package/bundled-test-harness/assets/message-service-subscription-test-DaQdgDWi.js +0 -110
- package/bundled-test-harness/assets/message-service-test-BsGEgM_m.js +0 -144
- package/bundled-test-harness/assets/message-tool-test-BB_4kw1V.js +0 -33
- package/bundled-test-harness/assets/midi-audio-def-test-BbbkFjqf.js +0 -182
- package/bundled-test-harness/assets/migrate-skill-test-X9xImDuq.js +0 -161
- package/bundled-test-harness/assets/mini-AwF31elJ.js +0 -1404
- package/bundled-test-harness/assets/mini-card-chooser-test-BZtrEiWu.js +0 -272
- package/bundled-test-harness/assets/mini-file-chooser-test-MIHW3kCI.js +0 -201
- package/bundled-test-harness/assets/mock-matrix-Dd8k0DNa.js +0 -15107
- package/bundled-test-harness/assets/mock-matrix-DhPN_34j.js +0 -2
- package/bundled-test-harness/assets/modal-LTh3_oHK.js +0 -322
- package/bundled-test-harness/assets/model-cost-tier-test-h1IkU9mp.js +0 -174
- package/bundled-test-harness/assets/model-file-extract-test-ntSo0wZF.js +0 -206
- package/bundled-test-harness/assets/module-transpile-cache-test-CDeRaaeP.js +0 -67
- package/bundled-test-harness/assets/monaco-test-C0Fa744D.js +0 -100
- package/bundled-test-harness/assets/mp3-audio-def-test-B4j4qR9H.js +0 -133
- package/bundled-test-harness/assets/multiple-stacks-test-BhA25ywL.js +0 -208
- package/bundled-test-harness/assets/nested-query-field-render-test-S9Y8YNKB.js +0 -249
- package/bundled-test-harness/assets/no-stacks-test-B7VciWyg.js +0 -48
- package/bundled-test-harness/assets/number-field-test-CS74lDPN.js +0 -184
- package/bundled-test-harness/assets/office-file-def-test-2cKc1pmd.js +0 -263
- package/bundled-test-harness/assets/office-metadata-extractor-test-DC8Fo-OW.js +0 -218
- package/bundled-test-harness/assets/office-poster-capture-test-Ba0_5UrT.js +0 -203
- package/bundled-test-harness/assets/ogg-audio-def-test-CIPQ1d4w.js +0 -196
- package/bundled-test-harness/assets/open-create-listing-modal-test-bmQkY5Zl.js +0 -131
- package/bundled-test-harness/assets/open-image-in-new-tab-test-DBD7_vMH.js +0 -52
- package/bundled-test-harness/assets/open-secure-window-test-BgeuYAqz.js +0 -253
- package/bundled-test-harness/assets/open-workspace-test-DRHGljV0.js +0 -46
- package/bundled-test-harness/assets/operation-lowering-test-CH1c0pSH.js +0 -2957
- package/bundled-test-harness/assets/operations-invocation-test-B1YkCLrv.js +0 -523
- package/bundled-test-harness/assets/operations-optimistic-test-DAbtOwsC.js +0 -203
- package/bundled-test-harness/assets/operations-query-test-9p1ZIDe-.js +0 -459
- package/bundled-test-harness/assets/operations-store-reconciliation-test-D0EQh3w2.js +0 -406
- package/bundled-test-harness/assets/operations-test-BQhlrfe3.js +0 -2518
- package/bundled-test-harness/assets/operator-mode-acceptance-test-DtHnonEb.js +0 -1195
- package/bundled-test-harness/assets/operator-mode-card-chooser-test-DQUxZxaq.js +0 -1036
- package/bundled-test-harness/assets/operator-mode-links-test-BJ26HllS.js +0 -797
- package/bundled-test-harness/assets/operator-mode-test-DIPDI0qt.js +0 -696
- package/bundled-test-harness/assets/operator-mode-ui-test-CfA-fAh4.js +0 -1045
- package/bundled-test-harness/assets/overlay-DecPh3nt.js +0 -123
- package/bundled-test-harness/assets/overlay-menu-items-test-C6XqjLtu.js +0 -331
- package/bundled-test-harness/assets/overlays-Ctp8ePzZ.js +0 -75
- package/bundled-test-harness/assets/overlays-CzWpSg5T.js +0 -2
- package/bundled-test-harness/assets/overlays-detached-element-test-DvL_8Bb5.js +0 -56
- package/bundled-test-harness/assets/panel-CImumikB.js +0 -15124
- package/bundled-test-harness/assets/past-sessions-test-N6riGN_I.js +0 -321
- package/bundled-test-harness/assets/patch-fields-test-D30_-KwQ.js +0 -1014
- package/bundled-test-harness/assets/patch-instance-test-C5rGscZq.js +0 -348
- package/bundled-test-harness/assets/pdf-file-def-test-DtiqGRvZ.js +0 -111
- package/bundled-test-harness/assets/pdf-metadata-extractor-test-FU02KmdV.js +0 -130
- package/bundled-test-harness/assets/permission-checking-realm-test-DqdNJDwU.js +0 -306
- package/bundled-test-harness/assets/persist-module-inspector-view-test-BHOAgPVy.js +0 -60
- package/bundled-test-harness/assets/persist-scroll-position-test-qtmS518r.js +0 -254
- package/bundled-test-harness/assets/phone-number-field-test-DhdaM7uL.js +0 -73
- package/bundled-test-harness/assets/pill-menu-test-C9Mrrepl.js +0 -60
- package/bundled-test-harness/assets/plate-9n-sXyCw.js +0 -41
- package/bundled-test-harness/assets/plate-BnZcAk-_.js +0 -2
- package/bundled-test-harness/assets/player-Cu5b4LEJ.js +0 -82
- package/bundled-test-harness/assets/player-unk2mkxV.js +0 -2
- package/bundled-test-harness/assets/playground-BwA8wFGK.js +0 -58
- package/bundled-test-harness/assets/plural-field-components-test-CFNQKETg.js +0 -198
- package/bundled-test-harness/assets/png-image-def-test-DG5Vhlqb.js +0 -266
- package/bundled-test-harness/assets/policy-audit-confirmation-test-yfKU47LR.js +0 -155
- package/bundled-test-harness/assets/policy-scoped-search-test-BjQRDYqR.js +0 -339
- package/bundled-test-harness/assets/prerender-file-extract-test-CEU4SaAZ.js +0 -346
- package/bundled-test-harness/assets/prerender-html-test-CGB3ClCS.js +0 -670
- package/bundled-test-harness/assets/prerender-meta-test-xqc4fW_0.js +0 -614
- package/bundled-test-harness/assets/prerender-module-test-CI1TmZw-.js +0 -409
- package/bundled-test-harness/assets/prerender-persistence-block-test-Da0dJO_N.js +0 -124
- package/bundled-test-harness/assets/prerender-pre-model-error-test-BVLyhk8R.js +0 -61
- package/bundled-test-harness/assets/prerender-serialize-cycle-test-glJFfxHU.js +0 -134
- package/bundled-test-harness/assets/prerendered-html-read-test-Mp4L0VHQ.js +0 -191
- package/bundled-test-harness/assets/pretui-components-test-BBpA9UnA.js +0 -991
- package/bundled-test-harness/assets/pretui-components-test-BqFq7rw_.css +0 -730
- package/bundled-test-harness/assets/preview-format-test-C55Bwcur.js +0 -103
- package/bundled-test-harness/assets/preview-test-CTAhRGU8.js +0 -474
- package/bundled-test-harness/assets/process-card-test-UjqpuxB7.js +0 -94
- package/bundled-test-harness/assets/profile-settings-modal-C8bCgTMK.js +0 -989
- package/bundled-test-harness/assets/publish-realm-ixUB4FPK.js +0 -82
- package/bundled-test-harness/assets/publish-realm-test-CrrsdL4W.js +0 -210
- package/bundled-test-harness/assets/query-field-barrier-test-DjivFE93.js +0 -113
- package/bundled-test-harness/assets/query-field-error-sentinel-test-0HwnV4Mw.js +0 -201
- package/bundled-test-harness/assets/query-field-membership-status-test-C8yTTBkc.js +0 -323
- package/bundled-test-harness/assets/query-field-page-optin-test-D4l_GcII.js +0 -126
- package/bundled-test-harness/assets/query-field-schema-test-DDbcNNm5.js +0 -231
- package/bundled-test-harness/assets/query-field-search-throttle-test-CXp50Ax0.js +0 -154
- package/bundled-test-harness/assets/query-field-stale-prerender-test-DErzt-Cv.js +0 -152
- package/bundled-test-harness/assets/query-fields-test-Dz67fdSl.js +0 -535
- package/bundled-test-harness/assets/quick-look-test-B1ijDsh_.js +0 -139
- package/bundled-test-harness/assets/read-card-for-ai-assistant-test-DJxZ16H_.js +0 -91
- package/bundled-test-harness/assets/read-file-for-ai-assistant-test-BoRQkZ8c.js +0 -45
- package/bundled-test-harness/assets/read-source-test-Bl-NjchO.js +0 -67
- package/bundled-test-harness/assets/read-text-file-test-CP37CZoo.js +0 -124
- package/bundled-test-harness/assets/realm-CaK5mkT-.js +0 -2852
- package/bundled-test-harness/assets/realm-api-keys-BNUFWbGR.js +0 -579
- package/bundled-test-harness/assets/realm-api-keys-CkshxhXC.js +0 -2
- package/bundled-test-harness/assets/realm-api-keys-test-BP8xifjn.js +0 -109
- package/bundled-test-harness/assets/realm-api-keys-test-CwdK9YXp.js +0 -588
- package/bundled-test-harness/assets/realm-config-iKwE3Htp.js +0 -833
- package/bundled-test-harness/assets/realm-config-policy-standing-test-BgVEIDnB.js +0 -290
- package/bundled-test-harness/assets/realm-config-routing-rule-edit-test-BoJoKzmX.js +0 -274
- package/bundled-test-harness/assets/realm-config-settings-test-Kxw-GHye.js +0 -187
- package/bundled-test-harness/assets/realm-field-test-CdGOxrFb.js +0 -100
- package/bundled-test-harness/assets/realm-indexing-test-CHtsBV2b.js +0 -4380
- package/bundled-test-harness/assets/realm-policy-fitted-test--DhNZSdC.js +0 -206
- package/bundled-test-harness/assets/realm-policy-test-D7714iVa.js +0 -1141
- package/bundled-test-harness/assets/realm-querying-test-Cj1ekZ0H.js +0 -1067
- package/bundled-test-harness/assets/realm-server-form-agnostic-test-CZFPNJfD.js +0 -96
- package/bundled-test-harness/assets/realm-server-subscriber-test-C86WmBp0.js +0 -46
- package/bundled-test-harness/assets/realm-service-info-test-CdgcwKDR.js +0 -67
- package/bundled-test-harness/assets/realm-test-DPoLsvKz.js +0 -2364
- package/bundled-test-harness/assets/realm-token-refresh-test-Ch35Siwi.js +0 -153
- package/bundled-test-harness/assets/realm-url-tooltip-test-x8xWOENK.js +0 -78
- package/bundled-test-harness/assets/reasoning-test-BxpE8Jvf.js +0 -221
- package/bundled-test-harness/assets/recent-files-test-DTmEzPLq.js +0 -450
- package/bundled-test-harness/assets/reindex-realm-test-BQ8KULn4.js +0 -117
- package/bundled-test-harness/assets/relationship-loading-state-test-BJoArPWf.js +0 -290
- package/bundled-test-harness/assets/remix-card-test-DsTA1KoG.js +0 -58
- package/bundled-test-harness/assets/rendered-markdown-DvukulDO.js +0 -292
- package/bundled-test-harness/assets/rendered-markdown-test-DxGptXSV.js +0 -587
- package/bundled-test-harness/assets/resident-instance-reuse-test-ZWnVu8uj.js +0 -82
- package/bundled-test-harness/assets/result-tile-CPyI6Vmv.js +0 -144
- package/bundled-test-harness/assets/rich-markdown-field-test-CdygoXIO.js +0 -1647
- package/bundled-test-harness/assets/room-message-test-D3NfMqH0.js +0 -484
- package/bundled-test-harness/assets/run-D_Px28eF.js +0 -3956
- package/bundled-test-harness/assets/run-realm-code-qWCZxmJ7.js +0 -2964
- package/bundled-test-harness/assets/run-realm-code-test-UzyeEJq6.js +0 -3844
- package/bundled-test-harness/assets/sanitize-module-list-test-Babq44bP.js +0 -85
- package/bundled-test-harness/assets/save-card-skip-index-wait-test-BcELXlQ_.js +0 -89
- package/bundled-test-harness/assets/schema-editor-test-CEvruZbt.js +0 -785
- package/bundled-test-harness/assets/schema-generation-test-hYAMdCrn.js +0 -28
- package/bundled-test-harness/assets/scrolling-test-DVIsh-_1.js +0 -412
- package/bundled-test-harness/assets/search-adorn-test-CkVhqFd0.js +0 -136
- package/bundled-test-harness/assets/search-and-choose-test-DUhOB3FV.js +0 -154
- package/bundled-test-harness/assets/search-correlation-id-test-Drn4r26N.js +0 -139
- package/bundled-test-harness/assets/search-entries-result-test-DTCRJ_wc.js +0 -234
- package/bundled-test-harness/assets/search-entries-test-CE0B47pw.js +0 -1486
- package/bundled-test-harness/assets/search-entries-tool-test-C4aG0ckM.js +0 -504
- package/bundled-test-harness/assets/search-google-images-test-LyhcB2f3.js +0 -166
- package/bundled-test-harness/assets/search-results-D4pSne0x.js +0 -266
- package/bundled-test-harness/assets/search-results-test-CRZHhqhn.js +0 -578
- package/bundled-test-harness/assets/search-selection-menu-test-B7Y3E_nj.js +0 -108
- package/bundled-test-harness/assets/search-sheet-files-test-C2y534g8.js +0 -126
- package/bundled-test-harness/assets/search-sheet-persistence-test-DePC59Bk.js +0 -131
- package/bundled-test-harness/assets/search-test-Dy8NxFkU.js +0 -2249
- package/bundled-test-harness/assets/search-tool-test-lctDaMH3.js +0 -156
- package/bundled-test-harness/assets/searchable-option-test-CE64M8oM.js +0 -322
- package/bundled-test-harness/assets/searchable-search-doc-test-C6u3mVvT.js +0 -1271
- package/bundled-test-harness/assets/section-rail-B_UQX00B.js +0 -113
- package/bundled-test-harness/assets/section-rail-test-DIda7MIw.js +0 -256
- package/bundled-test-harness/assets/secure-sign-in-CqqqfQG8.js +0 -174
- package/bundled-test-harness/assets/secure-sign-in-test-DimbVr_W.js +0 -373
- package/bundled-test-harness/assets/segmented-control-iePxSdTS.js +0 -173
- package/bundled-test-harness/assets/select-tNs6_xwW.js +0 -175
- package/bundled-test-harness/assets/send-ai-assistant-message-test-2GVrMF9Z.js +0 -52
- package/bundled-test-harness/assets/send-bot-trigger-event-test-B_3dKfGN.js +0 -56
- package/bundled-test-harness/assets/send-request-via-proxy-test-_clNWyYc.js +0 -380
- package/bundled-test-harness/assets/sending-test-DCPFXUVg.js +0 -659
- package/bundled-test-harness/assets/serialization-rri-form-audit-test-BI0zCs8Y.js +0 -136
- package/bundled-test-harness/assets/serialization-test-bjdtVlZL.js +0 -8758
- package/bundled-test-harness/assets/set-user-system-card-test-BUv1vL08.js +0 -59
- package/bundled-test-harness/assets/setup-BW1mmC7C.js +0 -772
- package/bundled-test-harness/assets/setup-DsIcFT-T.js +0 -2
- package/bundled-test-harness/assets/shared-link-target-reuse-test-9NeJEjkb.js +0 -207
- package/bundled-test-harness/assets/show-card-test-mfyLwusD.js +0 -365
- package/bundled-test-harness/assets/signed-capture-link-test-BOtKNCAM.js +0 -132
- package/bundled-test-harness/assets/single-stack-test-B4MGjaLk.js +0 -652
- package/bundled-test-harness/assets/skills-test-BuP-Yzk1.js +0 -648
- package/bundled-test-harness/assets/skip-boot-index-guard-test-Cmrx2-K7.js +0 -46
- package/bundled-test-harness/assets/spec-test-BhZDdhVQ.js +0 -1077
- package/bundled-test-harness/assets/spinner-CpIBUG9m.js +0 -49
- package/bundled-test-harness/assets/src-DGHttmW-.js +0 -216
- package/bundled-test-harness/assets/src-DaNDSbp7.js +0 -5
- package/bundled-test-harness/assets/stick-to-bottom-resize-test-Dpy3OVum.js +0 -56
- package/bundled-test-harness/assets/store-add-test-_IYS8o74.js +0 -50
- package/bundled-test-harness/assets/store-module-rebuild-test-B5VMaICy.js +0 -454
- package/bundled-test-harness/assets/store-search-test-C2VZabrH.js +0 -175
- package/bundled-test-harness/assets/store-test-D6PObxoD.js +0 -3672
- package/bundled-test-harness/assets/structured-theme-test-BHjVeMf-.js +0 -377
- package/bundled-test-harness/assets/summarize-session-test-BFtTuhe0.js +0 -172
- package/bundled-test-harness/assets/svg-image-def-test-BL6lkWUX.js +0 -167
- package/bundled-test-harness/assets/switch-submode-test-6Uv3bZMl.js +0 -168
- package/bundled-test-harness/assets/sync-openrouter-models-test-Dp9E05tL.js +0 -97
- package/bundled-test-harness/assets/test-support-DYm8XZ0E.js +0 -3
- package/bundled-test-harness/assets/test-support-DfnhiIMV.js +0 -99
- package/bundled-test-harness/assets/tests-CZk0Iag2.js +0 -3596
- package/bundled-test-harness/assets/text-file-def-test-CHdC0yIU.js +0 -94
- package/bundled-test-harness/assets/text-input-validator-test-B9ZR8XPU.js +0 -156
- package/bundled-test-harness/assets/text-suggestion-test-CGLspKFQ.js +0 -340
- package/bundled-test-harness/assets/theme-card-test-CXZvSEvG.js +0 -621
- package/bundled-test-harness/assets/theme-dashboard-nav-test-CkEE0ILk.js +0 -196
- package/bundled-test-harness/assets/theme-scheme-island-test-URXTjipF.js +0 -264
- package/bundled-test-harness/assets/titles-C6enAdIv.js +0 -2
- package/bundled-test-harness/assets/titles-Dft1HoUT.js +0 -52
- package/bundled-test-harness/assets/to-device-streaming-test-D33ZOc9o.js +0 -163
- package/bundled-test-harness/assets/token-usage-test-BHQlU4J4.js +0 -160
- package/bundled-test-harness/assets/tools-CrudqfS3.js +0 -774
- package/bundled-test-harness/assets/tools-calling-test-jo7IREau.js +0 -200
- package/bundled-test-harness/assets/tools-test-D1wMfUa0.js +0 -1624
- package/bundled-test-harness/assets/tools-test-Dn1LYsXp.js +0 -3204
- package/bundled-test-harness/assets/tooltip-8Wyz4IIn.css +0 -68
- package/bundled-test-harness/assets/tooltip-CqwLzRz5.js +0 -134
- package/bundled-test-harness/assets/transform-cards-test-BPhwPFtp.js +0 -341
- package/bundled-test-harness/assets/ts-file-def-preview-test-Bq3zTgw8.js +0 -95
- package/bundled-test-harness/assets/ts-file-def-test-GLswMl7O.js +0 -92
- package/bundled-test-harness/assets/ttf-font-def-test-DQulvUWs.js +0 -206
- package/bundled-test-harness/assets/turn-settling-test-BspmOUQP.js +0 -160
- package/bundled-test-harness/assets/turn-summary-9A8nvC0-.js +0 -1039
- package/bundled-test-harness/assets/unpublish-realm-test-SkYPEhDz.js +0 -102
- package/bundled-test-harness/assets/update-room-skills-test-cTxb-WU6.js +0 -240
- package/bundled-test-harness/assets/use-ai-assistant-test-uaqW1T_A.js +0 -384
- package/bundled-test-harness/assets/user-message-BudkIP-3.js +0 -262
- package/bundled-test-harness/assets/validate-realm-test-DxrGgH9n.js +0 -67
- package/bundled-test-harness/assets/video-metadata-extractor-test-B2pe-Iqa.js +0 -520
- package/bundled-test-harness/assets/view-visually-test-PNon6fUo.js +0 -335
- package/bundled-test-harness/assets/virtual-network-reset-test-uYJLaQHf.js +0 -96
- package/bundled-test-harness/assets/wav-audio-def-test-F4OrFFR4.js +0 -160
- package/bundled-test-harness/assets/webp-image-def-test-B0a_-Vya.js +0 -226
- package/bundled-test-harness/assets/workspace-Cyftysy9.js +0 -440
- package/bundled-test-harness/assets/workspace-a11y-test-sKiPDcbl.js +0 -197
- package/bundled-test-harness/assets/workspace-actions-BuawjFmZ.js +0 -561
- package/bundled-test-harness/assets/workspace-behavior-test-CKa-pb3T.js +0 -338
- package/bundled-test-harness/assets/workspace-delete-multiple-test-Dt2weG5R.js +0 -212
- package/bundled-test-harness/assets/workspace-delete-summary-test-CkqgFqZ8.js +0 -63
- package/bundled-test-harness/assets/workspace-hosting-test-Ci7EEtHP.js +0 -138
- package/bundled-test-harness/assets/workspace-indexing-test-BPVxxY6W.js +0 -71
- package/bundled-test-harness/assets/workspace-test-CWr7vFbg.js +0 -385
- package/bundled-test-harness/assets/workspace-test-INNpQovc.js +0 -51
- package/bundled-test-harness/assets/workspace-timestamp-labels-test-CigQb5wr.js +0 -68
- package/bundled-test-harness/assets/workspace-unit-test-BwVKpuXT.js +0 -122
- package/bundled-test-harness/assets/write-binary-file-test-BKP3gv1k.js +0 -124
- package/bundled-test-harness/assets/write-text-file-test-B6ijTKTa.js +0 -191
- package/bundled-test-harness/assets/zip-archive-test-C-PBzkTn.js +0 -285
- package/bundled-test-harness/assets/zip-file-def-test-FyCzJT-9.js +0 -164
|
@@ -1,3672 +0,0 @@
|
|
|
1
|
-
import { s as __toESM } from "./chunk-Rp0pCe6z.js";
|
|
2
|
-
import { n as decorateMethodV2, r as initializeDeferredDecorator, t as decorateFieldV2 } from "./runtime--fcdnjmJ-BoCBNIsz.js";
|
|
3
|
-
import { Br as testRealmURL, Co as SupportedMimeType, Ec as CardError, Jo as isCardInstance, Lr as testRRI, Qo as isFileDefInstance, Rc as Deferred, Xn as APP_BOXEL_REALM_EVENT_TYPE } from "./runtime-common-BTaLJEw-.js";
|
|
4
|
-
import { B as localId, G as realmURL, w as baseCardRef } from "./constants-Icc0nFW-.js";
|
|
5
|
-
import { wt as setComponentTemplate } from "./cache-DtDz7X5V-Wn8jRDfL.js";
|
|
6
|
-
import { r as service } from "./service-LFpJ8EEP.js";
|
|
7
|
-
import { H as templateFactory } from "./index-DaCZcoCY-CgzbilMy.js";
|
|
8
|
-
import "./component-BJO47HTh.js";
|
|
9
|
-
import { t as Component } from "./dist-CkA1rgqO.js";
|
|
10
|
-
import { n as tracked, t as cached } from "./tracking-800VJb8b.js";
|
|
11
|
-
import "./template-factory-ds9s0u8l.js";
|
|
12
|
-
import { n as getCardCollection } from "./card-collection-BQMglA2Y.js";
|
|
13
|
-
import { n as getCard } from "./card-resource-9nZR8YyO.js";
|
|
14
|
-
import { t as OperatorModeContainer } from "./container-Cqcwrd-m.js";
|
|
15
|
-
import { M as waitUntil, T as settled, a as find, d as click, o as waitFor, r as typeIn } from "./dist-BOAdzfkP.js";
|
|
16
|
-
import { t as require_qunit } from "./qunit-C-Foo4Nd.js";
|
|
17
|
-
import { $ as withSavesHeldOpen, F as setupLocalIndexing, I as setupOnSave, L as setupRealmCacheTeardown, M as setupCardLogs, P as setupIntegrationTestRealm, Z as withCachedRealmSetup, et as withSlowSave, lt as setupRenderingTest, ot as setupOperatorModeStateCleanup, t as setupMockMatrix, vt as registerDefaultRoutes, yt as registerRealmServerRoute } from "./mock-matrix-Dd8k0DNa.js";
|
|
18
|
-
import { r as getService } from "./dist-CPfIHBla.js";
|
|
19
|
-
import { A as field, H as linksTo, U as linksToMany, a as CardDef, d as FileDef, s as Component$1, w as contains } from "./card-api-Cc8uZunB.js";
|
|
20
|
-
import "./file-api-BsT3Q6C9.js";
|
|
21
|
-
import { t as BooleanField } from "./boolean-Dk3JuO7r.js";
|
|
22
|
-
import { t as string_default } from "./string-5IAMEUit.js";
|
|
23
|
-
import { n as renderComponent } from "./render-component-B15Z0e2v.js";
|
|
24
|
-
//#region tests/integration/store-test.gts
|
|
25
|
-
var import_qunit = /* @__PURE__ */ __toESM(require_qunit());
|
|
26
|
-
(0, import_qunit.module)("Integration | Store", function(hooks) {
|
|
27
|
-
setupRenderingTest(hooks);
|
|
28
|
-
setupOperatorModeStateCleanup(hooks);
|
|
29
|
-
let api;
|
|
30
|
-
let loader;
|
|
31
|
-
let loaderService;
|
|
32
|
-
let testRealm;
|
|
33
|
-
let testRealmAdapter;
|
|
34
|
-
let storeService;
|
|
35
|
-
let operatorModeStateService;
|
|
36
|
-
let cardStore;
|
|
37
|
-
let PersonDef;
|
|
38
|
-
let BoomPersonDef;
|
|
39
|
-
let EmployeeDef;
|
|
40
|
-
let ManagerDef;
|
|
41
|
-
let realmService;
|
|
42
|
-
setupLocalIndexing(hooks);
|
|
43
|
-
setupRealmCacheTeardown(hooks);
|
|
44
|
-
setupOnSave(hooks);
|
|
45
|
-
setupCardLogs(hooks, async () => await loader.import("@cardstack/base/card-api"));
|
|
46
|
-
let mockMatrixUtils = setupMockMatrix(hooks, {
|
|
47
|
-
loggedInAs: "@testuser:localhost",
|
|
48
|
-
activeRealms: [testRealmURL],
|
|
49
|
-
autostart: true
|
|
50
|
-
});
|
|
51
|
-
function forceGC() {
|
|
52
|
-
cardStore.sweep(api);
|
|
53
|
-
cardStore.sweep(api);
|
|
54
|
-
}
|
|
55
|
-
function setCardInOperatorModeState(cardURL, format = "isolated") {
|
|
56
|
-
operatorModeStateService.restore({ stacks: cardURL ? [[{
|
|
57
|
-
id: cardURL,
|
|
58
|
-
format
|
|
59
|
-
}]] : [[]] });
|
|
60
|
-
}
|
|
61
|
-
const noop = () => {};
|
|
62
|
-
async function writePerson(path, name) {
|
|
63
|
-
await testRealm.write(path, JSON.stringify({ data: {
|
|
64
|
-
attributes: { name },
|
|
65
|
-
meta: { adoptsFrom: {
|
|
66
|
-
module: testRRI("person"),
|
|
67
|
-
name: "Person"
|
|
68
|
-
} }
|
|
69
|
-
} }));
|
|
70
|
-
}
|
|
71
|
-
function interceptRealmEvents() {
|
|
72
|
-
let messageService = getService("message-service");
|
|
73
|
-
let deliver = messageService.relayRealmEvent.bind(messageService);
|
|
74
|
-
let captured = [];
|
|
75
|
-
messageService.relayRealmEvent = (event) => {
|
|
76
|
-
captured.push(event);
|
|
77
|
-
};
|
|
78
|
-
function find(url) {
|
|
79
|
-
return captured.find((event) => event.eventName === "index" && event.indexType === "incremental" && event.invalidations.includes(url));
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
deliver,
|
|
83
|
-
async nextEventFor(url) {
|
|
84
|
-
await waitUntil(() => find(url) !== void 0, {
|
|
85
|
-
timeout: 1e4,
|
|
86
|
-
timeoutMessage: `the realm broadcast no incremental index event naming ${url}; observed events: ${JSON.stringify(captured)}`
|
|
87
|
-
});
|
|
88
|
-
let event = find(url);
|
|
89
|
-
captured.length = 0;
|
|
90
|
-
return event;
|
|
91
|
-
},
|
|
92
|
-
restore() {
|
|
93
|
-
messageService.relayRealmEvent = deliver;
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
function countCardReads(pathFragment) {
|
|
98
|
-
let cardService = getService("card-service");
|
|
99
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
100
|
-
let count = 0;
|
|
101
|
-
cardService.fetchJSON = async (fetchUrl, args) => {
|
|
102
|
-
if (String(fetchUrl).includes(pathFragment) && (args?.method ?? "GET") === "GET") count++;
|
|
103
|
-
return originalFetchJSON(fetchUrl, args);
|
|
104
|
-
};
|
|
105
|
-
return {
|
|
106
|
-
get count() {
|
|
107
|
-
return count;
|
|
108
|
-
},
|
|
109
|
-
stop() {
|
|
110
|
-
delete cardService.fetchJSON;
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
function withholdSource(pathFragment) {
|
|
115
|
-
let loadCardDocument = cardStore.loadCardDocument.bind(cardStore);
|
|
116
|
-
cardStore.loadCardDocument = async (url, opts) => {
|
|
117
|
-
if (url.includes(pathFragment)) return new CardError(`${url} is withheld by this test`, { status: 404 });
|
|
118
|
-
return loadCardDocument(url, opts);
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
hooks.afterEach(function() {
|
|
122
|
-
if (cardStore) delete cardStore.loadCardDocument;
|
|
123
|
-
});
|
|
124
|
-
async function settleCardRender(assert, id, selector, opts) {
|
|
125
|
-
let start = performance.now();
|
|
126
|
-
await settled();
|
|
127
|
-
let elapsedMs = Math.round(performance.now() - start);
|
|
128
|
-
if (!find(selector)) {
|
|
129
|
-
let held = storeService.peek(id, { type: opts?.type });
|
|
130
|
-
let error = storeService.peekError(id, { type: opts?.type });
|
|
131
|
-
console.error([
|
|
132
|
-
`[card-render-diag] ${selector} is not rendered after settled() (${elapsedMs}ms)`,
|
|
133
|
-
`reference count: ${storeService.getReferenceCount(id)}`,
|
|
134
|
-
`peek: ${held === void 0 ? "<nothing>" : isCardInstance(held) || isFileDefInstance(held) ? `instance ${held.id}` : `error ${JSON.stringify(held)}`}`,
|
|
135
|
-
`peekError: ${error ? JSON.stringify(error) : "<none>"}`
|
|
136
|
-
].join("\n"));
|
|
137
|
-
} else if (elapsedMs > 1e3) console.warn(`[card-render-diag] ${selector} took ${elapsedMs}ms to load and render`);
|
|
138
|
-
assert.dom(selector).exists(`${id} is rendered`);
|
|
139
|
-
}
|
|
140
|
-
hooks.beforeEach(async function() {
|
|
141
|
-
class Person extends CardDef {
|
|
142
|
-
static {
|
|
143
|
-
decorateFieldV2(this.prototype, "name", [field], function() {
|
|
144
|
-
return contains(string_default);
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
#name = (initializeDeferredDecorator(this, "name"), void 0);
|
|
148
|
-
static {
|
|
149
|
-
decorateFieldV2(this.prototype, "hasError", [field], function() {
|
|
150
|
-
return contains(BooleanField);
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
#hasError = (initializeDeferredDecorator(this, "hasError"), void 0);
|
|
154
|
-
static {
|
|
155
|
-
decorateFieldV2(this.prototype, "bestFriend", [field], function() {
|
|
156
|
-
return linksTo(() => Person);
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
#bestFriend = (initializeDeferredDecorator(this, "bestFriend"), void 0);
|
|
160
|
-
static {
|
|
161
|
-
decorateFieldV2(this.prototype, "friends", [field], function() {
|
|
162
|
-
return linksToMany(() => Person);
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
#friends = (initializeDeferredDecorator(this, "friends"), void 0);
|
|
166
|
-
static {
|
|
167
|
-
decorateFieldV2(this.prototype, "boom", [field], function() {
|
|
168
|
-
return contains(string_default, { computeVia: function() {
|
|
169
|
-
if (this.hasError) throw new Error("intentional error thrown");
|
|
170
|
-
return "boom";
|
|
171
|
-
} });
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
#boom = (initializeDeferredDecorator(this, "boom"), void 0);
|
|
175
|
-
}
|
|
176
|
-
PersonDef = Person;
|
|
177
|
-
class BoomPerson extends CardDef {
|
|
178
|
-
static displayName = "Boom Person";
|
|
179
|
-
static {
|
|
180
|
-
decorateFieldV2(this.prototype, "name", [field], function() {
|
|
181
|
-
return contains(string_default);
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
#name = (initializeDeferredDecorator(this, "name"), void 0);
|
|
185
|
-
static isolated = class Isolated extends Component$1 {
|
|
186
|
-
static {
|
|
187
|
-
setComponentTemplate(templateFactory({
|
|
188
|
-
"id": "I6b4/CsV",
|
|
189
|
-
"block": "[[[1,\"Hello\\n\"],[8,[30,1,[\"name\"]],null,null,null],[1,\"!\\n\"],[1,[30,0,[\"boom\"]]]],[\"@fields\"],[]]",
|
|
190
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
191
|
-
"isStrictMode": true
|
|
192
|
-
}), this);
|
|
193
|
-
}
|
|
194
|
-
boom = () => intentionallyNotDefined();
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
BoomPersonDef = BoomPerson;
|
|
198
|
-
class Employee extends CardDef {
|
|
199
|
-
static displayName = "Employee";
|
|
200
|
-
static {
|
|
201
|
-
decorateFieldV2(this.prototype, "name", [field], function() {
|
|
202
|
-
return contains(string_default);
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
#name = (initializeDeferredDecorator(this, "name"), void 0);
|
|
206
|
-
static isolated = class Isolated extends Component$1 {
|
|
207
|
-
static {
|
|
208
|
-
setComponentTemplate(templateFactory({
|
|
209
|
-
"id": "TyvrA1L5",
|
|
210
|
-
"block": "[[[10,0],[14,\"data-test-employee-badge\",\"\"],[12],[1,\"Employee: \"],[8,[30,1,[\"name\"]],null,null,null],[13]],[\"@fields\"],[]]",
|
|
211
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
212
|
-
"isStrictMode": true
|
|
213
|
-
}), this);
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
EmployeeDef = Employee;
|
|
218
|
-
class Manager extends Employee {
|
|
219
|
-
static displayName = "Manager";
|
|
220
|
-
static isolated = class Isolated extends Component$1 {
|
|
221
|
-
static {
|
|
222
|
-
setComponentTemplate(templateFactory({
|
|
223
|
-
"id": "3Gw4m0Y6",
|
|
224
|
-
"block": "[[[10,0],[14,\"data-test-manager-badge\",\"\"],[12],[1,\"Manager: \"],[8,[30,1,[\"name\"]],null,null,null],[13]],[\"@fields\"],[]]",
|
|
225
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
226
|
-
"isStrictMode": true
|
|
227
|
-
}), this);
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
ManagerDef = Manager;
|
|
232
|
-
loaderService = getService("loader-service");
|
|
233
|
-
loader = loaderService.loader;
|
|
234
|
-
api = await loader.import("@cardstack/base/card-api");
|
|
235
|
-
storeService = getService("store");
|
|
236
|
-
operatorModeStateService = getService("operator-mode-state-service");
|
|
237
|
-
cardStore = storeService.store;
|
|
238
|
-
realmService = getService("realm");
|
|
239
|
-
await withCachedRealmSetup(async () => {
|
|
240
|
-
({adapter: testRealmAdapter, realm: testRealm} = await setupIntegrationTestRealm({
|
|
241
|
-
mockMatrixUtils,
|
|
242
|
-
contents: {
|
|
243
|
-
"person.gts": { Person },
|
|
244
|
-
"boom-person.gts": { BoomPerson },
|
|
245
|
-
"employee.gts": { Employee },
|
|
246
|
-
"manager.gts": { Manager },
|
|
247
|
-
"Person/hassan.json": new Person({ name: "Hassan" }),
|
|
248
|
-
"Person/jade.json": new Person({ name: "Jade" }),
|
|
249
|
-
"Person/queenzy.json": new Person({ name: "Queenzy" }),
|
|
250
|
-
"Person/germaine.json": new Person({ name: "Germaine" }),
|
|
251
|
-
"Person/boris.json": new Person({ name: "Boris" })
|
|
252
|
-
}
|
|
253
|
-
}));
|
|
254
|
-
});
|
|
255
|
-
await realmService.login(testRealmURL);
|
|
256
|
-
});
|
|
257
|
-
hooks.afterEach(function() {
|
|
258
|
-
getService("network").virtualNetwork.removeRealmMapping("@test-prefix/");
|
|
259
|
-
});
|
|
260
|
-
(0, import_qunit.test)("can peek a card instance", async function(assert) {
|
|
261
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
262
|
-
await storeService.flush();
|
|
263
|
-
let instance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
264
|
-
assert.true(isCardInstance(instance), "peeked item is a card instance");
|
|
265
|
-
});
|
|
266
|
-
(0, import_qunit.test)("can peek a card by local id", async function(assert) {
|
|
267
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
268
|
-
await storeService.flush();
|
|
269
|
-
let instanceA = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
270
|
-
let instanceB = storeService.peek(instanceA[localId]);
|
|
271
|
-
assert.true(isCardInstance(instanceB), "peeked item is a card instance");
|
|
272
|
-
assert.strictEqual(instanceA, instanceB, "the same instance is returned by both remote ID and local ID");
|
|
273
|
-
});
|
|
274
|
-
(0, import_qunit.test)("can peek a card error when no stale instance exists", async function(assert) {
|
|
275
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
276
|
-
attributes: {
|
|
277
|
-
name: "Hassan",
|
|
278
|
-
hasError: true
|
|
279
|
-
},
|
|
280
|
-
meta: { adoptsFrom: {
|
|
281
|
-
module: testRRI("person"),
|
|
282
|
-
name: "Person"
|
|
283
|
-
} }
|
|
284
|
-
} }));
|
|
285
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
286
|
-
await storeService.flush();
|
|
287
|
-
let error = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
288
|
-
assert.false(isCardInstance(error), "error is not a card instance");
|
|
289
|
-
assert.ok(error.message.includes("intentional error thrown"), "error message is correct");
|
|
290
|
-
});
|
|
291
|
-
(0, import_qunit.test)("peek returns a stale instance when the server state reflects an error", async function(assert) {
|
|
292
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
293
|
-
await storeService.flush();
|
|
294
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
295
|
-
attributes: {
|
|
296
|
-
name: "Hassan",
|
|
297
|
-
hasError: true
|
|
298
|
-
},
|
|
299
|
-
meta: { adoptsFrom: {
|
|
300
|
-
module: testRRI("person"),
|
|
301
|
-
name: "Person"
|
|
302
|
-
} }
|
|
303
|
-
} }));
|
|
304
|
-
await waitUntil(() => storeService.peekError(`${testRealmURL}Person/hassan`));
|
|
305
|
-
let staleInstance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
306
|
-
assert.true(isCardInstance(staleInstance), "the peek-ed instance is not an error");
|
|
307
|
-
});
|
|
308
|
-
(0, import_qunit.test)("peek for an uncached returns undefined", async function(assert) {
|
|
309
|
-
let instance = storeService.peek(`${testRealmURL}Person/does-not-exist`);
|
|
310
|
-
assert.strictEqual(instance, void 0, "instance is undefined");
|
|
311
|
-
});
|
|
312
|
-
(0, import_qunit.test)("can use registered prefix ids across store APIs", async function(assert) {
|
|
313
|
-
getService("network").virtualNetwork.addRealmMapping("@test-prefix/", testRealmURL);
|
|
314
|
-
storeService.addReference("@test-prefix/Person/hassan");
|
|
315
|
-
await storeService.flush();
|
|
316
|
-
let byPrefix = storeService.peek("@test-prefix/Person/hassan");
|
|
317
|
-
let byUrl = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
318
|
-
assert.true(isCardInstance(byPrefix), "prefix id resolves to a card");
|
|
319
|
-
assert.strictEqual(byPrefix, byUrl, "prefix id and resolved URL return the same instance");
|
|
320
|
-
assert.strictEqual(storeService.getReferenceCount("@test-prefix/Person/hassan"), 1, "prefix id and resolved URL share a single reference count");
|
|
321
|
-
assert.strictEqual(storeService.getReferenceCount(`${testRealmURL}Person/hassan`), 1, "resolved URL sees the same reference count");
|
|
322
|
-
storeService.dropReference("@test-prefix/Person/hassan");
|
|
323
|
-
assert.strictEqual(storeService.getReferenceCount(`${testRealmURL}Person/hassan`), 0, "dropping a prefix reference clears the resolved URL reference count");
|
|
324
|
-
let countsDuringSave;
|
|
325
|
-
this.onSave((url) => {
|
|
326
|
-
if (url.href === `${testRealmURL}Person/hassan`) countsDuringSave = {
|
|
327
|
-
url: storeService.getReferenceCount(`${testRealmURL}Person/hassan`),
|
|
328
|
-
prefix: storeService.getReferenceCount("@test-prefix/Person/hassan")
|
|
329
|
-
};
|
|
330
|
-
});
|
|
331
|
-
storeService.save("@test-prefix/Person/hassan");
|
|
332
|
-
await settled();
|
|
333
|
-
let saveError = storeService.getSaveState(byPrefix[localId])?.lastSaveError;
|
|
334
|
-
assert.strictEqual(saveError, void 0, `save() persists the card${saveError ? `: ${saveError instanceof Error ? saveError.message : JSON.stringify(saveError)}` : ""}`);
|
|
335
|
-
assert.deepEqual(countsDuringSave, {
|
|
336
|
-
url: 1,
|
|
337
|
-
prefix: 1
|
|
338
|
-
}, "save() holds exactly one reference while it runs, read the same through the prefix id and the resolved URL");
|
|
339
|
-
assert.strictEqual(storeService.getReferenceCount("@test-prefix/Person/hassan"), 0, "save() releases its hold once it lands");
|
|
340
|
-
storeService.addReference("@test-prefix/Person/boris");
|
|
341
|
-
await storeService.flush();
|
|
342
|
-
await storeService.delete("@test-prefix/Person/boris");
|
|
343
|
-
assert.strictEqual(storeService.peek("@test-prefix/Person/boris"), void 0, "delete() clears the prefix-form card identity from the store");
|
|
344
|
-
assert.strictEqual(storeService.peek(`${testRealmURL}Person/boris`), void 0, "delete() clears the resolved card identity from the store");
|
|
345
|
-
let file = await testRealmAdapter.openFile(`Person/boris.json`);
|
|
346
|
-
assert.strictEqual(file, void 0, "delete() removes the remote card");
|
|
347
|
-
});
|
|
348
|
-
(0, import_qunit.test)("deleting a linked target rewrites a loaded consumer linksTo slot to a broken-link sentinel", async function(assert) {
|
|
349
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
350
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
351
|
-
await storeService.flush();
|
|
352
|
-
let hassan = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
353
|
-
hassan.bestFriend = storeService.peek(`${testRealmURL}Person/boris`);
|
|
354
|
-
await settled();
|
|
355
|
-
assert.strictEqual(api.getRelationshipMembershipState(hassan, "bestFriend").membership[0].kind, "present", "the consumer link resolves to the target before the delete");
|
|
356
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
357
|
-
let after = api.getRelationshipMembershipState(hassan, "bestFriend").membership[0];
|
|
358
|
-
assert.strictEqual(after.kind, "not-found", "deleting the target rewrites the consumer slot to a broken-link sentinel without a reload");
|
|
359
|
-
assert.strictEqual(after.reference, `${testRealmURL}Person/boris`, "the sentinel preserves the deleted target reference for the placeholder");
|
|
360
|
-
});
|
|
361
|
-
(0, import_qunit.test)("deleting a linked target rewrites only the matching element of a loaded consumer linksToMany slot", async function(assert) {
|
|
362
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
363
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
364
|
-
storeService.addReference(`${testRealmURL}Person/jade`);
|
|
365
|
-
await storeService.flush();
|
|
366
|
-
let hassan = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
367
|
-
let boris = storeService.peek(`${testRealmURL}Person/boris`);
|
|
368
|
-
hassan.friends = [storeService.peek(`${testRealmURL}Person/jade`), boris];
|
|
369
|
-
await settled();
|
|
370
|
-
let before = api.getRelationshipMembershipState(hassan, "friends").membership;
|
|
371
|
-
assert.deepEqual(before.map((s) => s.kind), ["present", "present"], "both linksToMany elements resolve before the delete");
|
|
372
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
373
|
-
let after = api.getRelationshipMembershipState(hassan, "friends").membership;
|
|
374
|
-
let borisEntry = after.find((s) => s.reference === `${testRealmURL}Person/boris`);
|
|
375
|
-
let jadeEntry = after.find((s) => s.reference === `${testRealmURL}Person/jade`);
|
|
376
|
-
assert.strictEqual(borisEntry?.kind, "not-found", "the deleted element becomes a broken-link sentinel");
|
|
377
|
-
assert.strictEqual(jadeEntry?.kind, "present", "the surviving element is left untouched");
|
|
378
|
-
});
|
|
379
|
-
(0, import_qunit.test)("peekError returns the server state error when a stale instance exists", async function(assert) {
|
|
380
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
381
|
-
await storeService.flush();
|
|
382
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
383
|
-
attributes: {
|
|
384
|
-
name: "Hassan",
|
|
385
|
-
hasError: true
|
|
386
|
-
},
|
|
387
|
-
meta: { adoptsFrom: {
|
|
388
|
-
module: testRRI("person"),
|
|
389
|
-
name: "Person"
|
|
390
|
-
} }
|
|
391
|
-
} }));
|
|
392
|
-
await waitUntil(() => storeService.peekError(`${testRealmURL}Person/hassan`));
|
|
393
|
-
let error = storeService.peekError(`${testRealmURL}Person/hassan`);
|
|
394
|
-
assert.false(isCardInstance(error), "error is not a card instance");
|
|
395
|
-
assert.ok(error.message.includes("intentional error thrown"), "error message is correct");
|
|
396
|
-
});
|
|
397
|
-
(0, import_qunit.test)("can add reference to a card url", async function(assert) {
|
|
398
|
-
let instance = storeService.peek(`${testRealmURL}hassan`);
|
|
399
|
-
assert.strictEqual(instance, void 0, "instance is not in store yet");
|
|
400
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
401
|
-
await storeService.flush();
|
|
402
|
-
instance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
403
|
-
if (isCardInstance(instance)) assert.strictEqual(instance.name, "Hassan", "instance is cached in store");
|
|
404
|
-
else assert.ok(false, `expected instance to be a card:${JSON.stringify(instance, null, 2)}`);
|
|
405
|
-
forceGC();
|
|
406
|
-
instance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
407
|
-
if (isCardInstance(instance)) assert.strictEqual(instance.name, "Hassan", "instance is cached in store after GC");
|
|
408
|
-
else assert.ok(false, `expected instance to be a card:${JSON.stringify(instance, null, 2)} after GC`);
|
|
409
|
-
});
|
|
410
|
-
(0, import_qunit.test)("can add reference to a local id", async function(assert) {
|
|
411
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
412
|
-
await storeService.addWithoutPersisting(instance);
|
|
413
|
-
storeService.addReference(instance[localId]);
|
|
414
|
-
forceGC();
|
|
415
|
-
let peekedInstance = storeService.peek(instance[localId]);
|
|
416
|
-
assert.strictEqual(peekedInstance, instance, "instance is not garbage collected");
|
|
417
|
-
});
|
|
418
|
-
(0, import_qunit.test)("a render-context load does not set up the autosave change subscription", async function(assert) {
|
|
419
|
-
let cardService = getService("card-service");
|
|
420
|
-
let originalGetAPI = cardService.getAPI.bind(cardService);
|
|
421
|
-
let realApi = await originalGetAPI();
|
|
422
|
-
let trueSubscribe = realApi.subscribeToChanges;
|
|
423
|
-
let subscribeCount = 0;
|
|
424
|
-
cardService.getAPI = async () => new Proxy(realApi, { get(target, prop, receiver) {
|
|
425
|
-
if (prop === "subscribeToChanges") return (...args) => {
|
|
426
|
-
subscribeCount++;
|
|
427
|
-
return trueSubscribe(...args);
|
|
428
|
-
};
|
|
429
|
-
return Reflect.get(target, prop, receiver);
|
|
430
|
-
} });
|
|
431
|
-
try {
|
|
432
|
-
await storeService.addWithoutPersisting(new PersonDef({ name: "Mango" }));
|
|
433
|
-
assert.true(subscribeCount > 0, "the live store subscribes a loaded instance for autosave");
|
|
434
|
-
subscribeCount = 0;
|
|
435
|
-
globalThis.__boxelRenderContext = true;
|
|
436
|
-
await getService("render-store").addWithoutPersisting(new PersonDef({ name: "Van Gogh" }));
|
|
437
|
-
assert.strictEqual(subscribeCount, 0, "the render store does not subscribe a loaded instance for autosave");
|
|
438
|
-
} finally {
|
|
439
|
-
cardService.getAPI = originalGetAPI;
|
|
440
|
-
delete globalThis.__boxelRenderContext;
|
|
441
|
-
}
|
|
442
|
-
});
|
|
443
|
-
(0, import_qunit.test)("a card render absorbs a blocked write, a headless command reports it", async function(assert) {
|
|
444
|
-
globalThis.__boxelPrerenderApp = true;
|
|
445
|
-
try {
|
|
446
|
-
let rendered = new PersonDef({ name: "Andrea" });
|
|
447
|
-
assert.strictEqual(await storeService.add(rendered), rendered, "a render keeps the instance rather than failing");
|
|
448
|
-
globalThis.__boxelHeadlessCommand = true;
|
|
449
|
-
await assert.rejects(storeService.add(new PersonDef({ name: "Van Gogh" })), /persistence block still raised/, "a command reports the blocked write");
|
|
450
|
-
let ephemeral = new PersonDef({ name: "Mango" });
|
|
451
|
-
assert.strictEqual(await storeService.addWithoutPersisting(ephemeral), ephemeral, "a memory-only add is served as asked");
|
|
452
|
-
} finally {
|
|
453
|
-
delete globalThis.__boxelHeadlessCommand;
|
|
454
|
-
delete globalThis.__boxelPrerenderApp;
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
(0, import_qunit.test)("restoring sessions from storage skips the re-walk when the session blob is unchanged", function(assert) {
|
|
458
|
-
let walks = 0;
|
|
459
|
-
let originalGetOrCreate = realmService.getOrCreateRealmResource.bind(realmService);
|
|
460
|
-
realmService.getOrCreateRealmResource = (...args) => {
|
|
461
|
-
walks++;
|
|
462
|
-
return originalGetOrCreate(...args);
|
|
463
|
-
};
|
|
464
|
-
try {
|
|
465
|
-
realmService.lastRestoredSessionsString = void 0;
|
|
466
|
-
let before = walks;
|
|
467
|
-
realmService.restoreSessionsFromStorage();
|
|
468
|
-
assert.true(walks - before > 0, "the first restore walks the stored sessions");
|
|
469
|
-
before = walks;
|
|
470
|
-
realmService.restoreSessionsFromStorage();
|
|
471
|
-
assert.strictEqual(walks - before, 0, "a restore with an unchanged blob does not re-walk");
|
|
472
|
-
realmService.lastRestoredSessionsString = "stale-sentinel";
|
|
473
|
-
before = walks;
|
|
474
|
-
realmService.restoreSessionsFromStorage();
|
|
475
|
-
assert.true(walks - before > 0, "a restore re-walks once the stored blob no longer matches the memo");
|
|
476
|
-
} finally {
|
|
477
|
-
realmService.getOrCreateRealmResource = originalGetOrCreate;
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
(0, import_qunit.test)("getFields is memoized per instance in the render context and invalidates as the instance grows", function(assert) {
|
|
481
|
-
let person = new PersonDef({ name: "Mango" });
|
|
482
|
-
try {
|
|
483
|
-
globalThis.__boxelRenderContext = true;
|
|
484
|
-
let first = api.getFields(person, { usedLinksToFieldsOnly: true });
|
|
485
|
-
let second = api.getFields(person, { usedLinksToFieldsOnly: true });
|
|
486
|
-
assert.strictEqual(first, second, "a repeat call in the render context returns the memoized field map");
|
|
487
|
-
assert.notOk("bestFriend" in first, "an unused linksTo field is absent before it is populated");
|
|
488
|
-
person.bestFriend = new PersonDef({ name: "Van Gogh" });
|
|
489
|
-
let third = api.getFields(person, { usedLinksToFieldsOnly: true });
|
|
490
|
-
assert.notStrictEqual(third, first, "growing the instance invalidates the memo");
|
|
491
|
-
assert.ok("bestFriend" in third, "the now-used linksTo field appears after the bucket grows");
|
|
492
|
-
delete globalThis.__boxelRenderContext;
|
|
493
|
-
let live1 = api.getFields(person, { usedLinksToFieldsOnly: true });
|
|
494
|
-
let live2 = api.getFields(person, { usedLinksToFieldsOnly: true });
|
|
495
|
-
assert.notStrictEqual(live1, live2, "the live app always gets a fresh field map");
|
|
496
|
-
} finally {
|
|
497
|
-
delete globalThis.__boxelRenderContext;
|
|
498
|
-
}
|
|
499
|
-
});
|
|
500
|
-
(0, import_qunit.test)("can drop reference to a card url", async function(assert) {
|
|
501
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
502
|
-
await storeService.flush();
|
|
503
|
-
let instance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
504
|
-
assert.ok(instance, "instance is in store");
|
|
505
|
-
storeService.dropReference(`${testRealmURL}Person/hassan`);
|
|
506
|
-
forceGC();
|
|
507
|
-
assert.strictEqual(storeService.peek(`${testRealmURL}Person/hassan`), void 0, "instance has been garbage collected from the store");
|
|
508
|
-
});
|
|
509
|
-
(0, import_qunit.test)("can drop reference to a local id", async function(assert) {
|
|
510
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
511
|
-
await storeService.addWithoutPersisting(instance);
|
|
512
|
-
storeService.addReference(instance[localId]);
|
|
513
|
-
storeService.dropReference(instance[localId]);
|
|
514
|
-
forceGC();
|
|
515
|
-
let peekedInstance = storeService.peek(instance[localId]);
|
|
516
|
-
assert.strictEqual(peekedInstance, void 0, "instance is garbage collected");
|
|
517
|
-
});
|
|
518
|
-
(0, import_qunit.test)("file-meta instance is retained when referenced", async function(assert) {
|
|
519
|
-
await testRealm.write("hero.png", "mock hero image");
|
|
520
|
-
let fileUrl = `${testRealmURL}hero.png`;
|
|
521
|
-
let fileInstance = await storeService.get(fileUrl, { type: "file-meta" });
|
|
522
|
-
assert.ok(fileInstance, "file meta instance is loaded");
|
|
523
|
-
assert.ok(fileInstance.constructor?.isFileDef, "file meta instance is a FileDef");
|
|
524
|
-
storeService.addReference(fileUrl);
|
|
525
|
-
forceGC();
|
|
526
|
-
let peekedInstance = cardStore.getFileMeta(fileUrl);
|
|
527
|
-
assert.strictEqual(peekedInstance, fileInstance, "file meta instance is retained after GC with reference");
|
|
528
|
-
});
|
|
529
|
-
(0, import_qunit.test)("file-meta instance is garbage collected when references drop", async function(assert) {
|
|
530
|
-
await testRealm.write("hero.png", "mock hero image");
|
|
531
|
-
let fileUrl = `${testRealmURL}hero.png`;
|
|
532
|
-
await storeService.get(fileUrl, { type: "file-meta" });
|
|
533
|
-
storeService.addReference(fileUrl);
|
|
534
|
-
storeService.dropReference(fileUrl);
|
|
535
|
-
forceGC();
|
|
536
|
-
assert.strictEqual(cardStore.getFileMeta(fileUrl), void 0, "file meta instance is garbage collected after reference drop");
|
|
537
|
-
});
|
|
538
|
-
(0, import_qunit.test)("realm subscription is removed when file-meta reference count drops to zero", async function(assert) {
|
|
539
|
-
await testRealm.write("hero.png", "mock hero image");
|
|
540
|
-
let fileUrl = `${testRealmURL}hero.png`;
|
|
541
|
-
let subscriptions = storeService.subscriptions;
|
|
542
|
-
assert.false(subscriptions.has(testRealmURL), "realm is not subscribed before adding file-meta reference");
|
|
543
|
-
storeService.addReference(fileUrl, { type: "file-meta" });
|
|
544
|
-
assert.true(subscriptions.has(testRealmURL), "realm subscription is created for file-meta reference");
|
|
545
|
-
storeService.dropReference(fileUrl);
|
|
546
|
-
assert.false(subscriptions.has(testRealmURL), "realm subscription is removed when file-meta reference reaches zero");
|
|
547
|
-
});
|
|
548
|
-
(0, import_qunit.test)("add stores FileDef dependencies", async function(assert) {
|
|
549
|
-
class FileCard extends CardDef {
|
|
550
|
-
static {
|
|
551
|
-
decorateFieldV2(this.prototype, "attachment", [field], function() {
|
|
552
|
-
return linksTo(FileDef);
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
#attachment = (initializeDeferredDecorator(this, "attachment"), void 0);
|
|
556
|
-
}
|
|
557
|
-
let fileUrl = `${testRealmURL}hero.png`;
|
|
558
|
-
let fileDef = new FileDef({
|
|
559
|
-
id: fileUrl,
|
|
560
|
-
sourceUrl: fileUrl,
|
|
561
|
-
url: fileUrl,
|
|
562
|
-
name: "hero.png",
|
|
563
|
-
contentType: "image/png"
|
|
564
|
-
});
|
|
565
|
-
let card = new FileCard({ attachment: fileDef });
|
|
566
|
-
await storeService.addWithoutPersisting(card);
|
|
567
|
-
assert.strictEqual(storeService.peek(fileUrl, { type: "file-meta" }), fileDef, "file meta dependency is cached in file-meta store");
|
|
568
|
-
});
|
|
569
|
-
(0, import_qunit.test)("card read of a binary file URL is rerouted to file-meta", async function(assert) {
|
|
570
|
-
await testRealm.write("hero.png", "mock hero image");
|
|
571
|
-
let fileUrl = `${testRealmURL}hero.png`;
|
|
572
|
-
let result = await storeService.get(fileUrl);
|
|
573
|
-
assert.ok(result.constructor?.isFileDef, "card read returns a FileDef via the safety-net reroute");
|
|
574
|
-
let fileInstance = await storeService.get(fileUrl, { type: "file-meta" });
|
|
575
|
-
assert.ok(fileInstance.constructor?.isFileDef, "file-meta read returns a FileDef");
|
|
576
|
-
assert.strictEqual(storeService.peekError(fileUrl), void 0, "no error cached on the card bucket");
|
|
577
|
-
assert.strictEqual(storeService.peekError(fileUrl, { type: "file-meta" }), void 0, "no error cached on the file-meta bucket");
|
|
578
|
-
});
|
|
579
|
-
(0, import_qunit.test)("a file the realm does not hold is reported as a missing file", async function(assert) {
|
|
580
|
-
let missingFileUrl = `${testRealmURL}missing.png`;
|
|
581
|
-
let error = await storeService.get(missingFileUrl, { type: "file-meta" });
|
|
582
|
-
assert.strictEqual(error.status, 404, "the error carries the HTTP status");
|
|
583
|
-
assert.strictEqual(error.title, "File Not Found", "a missing file is titled as a missing file, not a missing card");
|
|
584
|
-
assert.strictEqual(error.message, `The file ${missingFileUrl} does not exist`, "the message names a file, not a card");
|
|
585
|
-
});
|
|
586
|
-
(0, import_qunit.test)("garbage collects cards that only consume each other", async function(assert) {
|
|
587
|
-
let alpha = new PersonDef({ name: "Alpha" });
|
|
588
|
-
let beta = new PersonDef({ name: "Beta" });
|
|
589
|
-
alpha.bestFriend = beta;
|
|
590
|
-
beta.bestFriend = alpha;
|
|
591
|
-
await storeService.addWithoutPersisting(alpha);
|
|
592
|
-
await storeService.addWithoutPersisting(beta);
|
|
593
|
-
assert.strictEqual(storeService.peek(alpha[localId]), alpha, "alpha is present before GC");
|
|
594
|
-
assert.strictEqual(storeService.peek(beta[localId]), beta, "beta is present before GC");
|
|
595
|
-
forceGC();
|
|
596
|
-
assert.strictEqual(storeService.peek(alpha[localId]), void 0, "alpha is garbage collected");
|
|
597
|
-
assert.strictEqual(storeService.peek(beta[localId]), void 0, "beta is garbage collected");
|
|
598
|
-
});
|
|
599
|
-
(0, import_qunit.test)("can manually save an instance", async function(assert) {
|
|
600
|
-
assert.expect(2);
|
|
601
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
602
|
-
await storeService.flush();
|
|
603
|
-
this.onSave((url, doc) => {
|
|
604
|
-
assert.strictEqual(url.href, `${testRealmURL}Person/hassan`, "the saved card id is correct");
|
|
605
|
-
assert.strictEqual(doc.data.attributes?.name, "Hassan", "save data is correct");
|
|
606
|
-
});
|
|
607
|
-
storeService.save(`${testRealmURL}Person/hassan`);
|
|
608
|
-
});
|
|
609
|
-
(0, import_qunit.test)("can create an instance", async function(assert) {
|
|
610
|
-
let url = await storeService.create({ data: {
|
|
611
|
-
attributes: { name: "Andrea" },
|
|
612
|
-
meta: { adoptsFrom: {
|
|
613
|
-
module: testRRI("person"),
|
|
614
|
-
name: "Person"
|
|
615
|
-
} }
|
|
616
|
-
} });
|
|
617
|
-
assert.strictEqual(typeof url, "string", "received a url for new instance");
|
|
618
|
-
let instance = storeService.peek(url);
|
|
619
|
-
assert.strictEqual(instance.id, url);
|
|
620
|
-
assert.strictEqual(instance.name, "Andrea");
|
|
621
|
-
let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
|
|
622
|
-
assert.ok(file, "file exists");
|
|
623
|
-
let fileJSON = JSON.parse(file.content);
|
|
624
|
-
assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
|
|
625
|
-
});
|
|
626
|
-
(0, import_qunit.test)("can handle card error when creating an instance", async function(assert) {
|
|
627
|
-
let error = await storeService.create({ data: {
|
|
628
|
-
attributes: {
|
|
629
|
-
name: "Andrea",
|
|
630
|
-
hasError: true
|
|
631
|
-
},
|
|
632
|
-
meta: { adoptsFrom: {
|
|
633
|
-
module: testRRI("person"),
|
|
634
|
-
name: "Person"
|
|
635
|
-
} }
|
|
636
|
-
} });
|
|
637
|
-
assert.strictEqual(typeof error, "object", "received a error for new instance");
|
|
638
|
-
assert.ok(error.message.includes("intentional error thrown", "the error message is correct"));
|
|
639
|
-
});
|
|
640
|
-
(0, import_qunit.test)("can handle a rendering card error when creating an instance", async function(assert) {
|
|
641
|
-
let instance = new BoomPersonDef({ name: "Andrea" });
|
|
642
|
-
let error = await storeService.add(instance, { realm: testRealmURL });
|
|
643
|
-
storeService.addReference(instance[localId]);
|
|
644
|
-
await storeService.flush();
|
|
645
|
-
let stale = storeService.peek(instance[localId]);
|
|
646
|
-
if (isCardInstance(stale)) assert.strictEqual(stale.name, "Andrea", "the stale card state is correct");
|
|
647
|
-
else assert.ok(false, `expected an instance but got a card error: "${stale.message}"`);
|
|
648
|
-
let peekedError = storeService.peekError(instance[localId]);
|
|
649
|
-
assert.strictEqual(peekedError, error, "the output of store.add is the peek-ed error");
|
|
650
|
-
if (!isCardInstance(error)) {
|
|
651
|
-
assert.strictEqual(error.id, instance[localId], "the error doc id is the local id of the instance");
|
|
652
|
-
assert.ok(error.message.includes("intentionallyNotDefined is not defined"));
|
|
653
|
-
loaderService.resetLoader();
|
|
654
|
-
await testRealm.write(`boom-person.gts`, `
|
|
655
|
-
import { contains, field, CardDef, Component, StringField } from '@cardstack/base/card-api';
|
|
656
|
-
|
|
657
|
-
export class BoomPerson extends CardDef {
|
|
658
|
-
static displayName = 'Boom Person';
|
|
659
|
-
@field name = contains(StringField);
|
|
660
|
-
static isolated = class Isolated extends Component<typeof this> {
|
|
661
|
-
<template>
|
|
662
|
-
Hello
|
|
663
|
-
<@fields.firstName />!
|
|
664
|
-
</template>
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
`.trim());
|
|
668
|
-
await waitUntil(() => !storeService.peekError(instance[localId]), { timeout: 5e3 });
|
|
669
|
-
await waitUntil(() => {
|
|
670
|
-
let card = storeService.peek(instance[localId]);
|
|
671
|
-
return Boolean(card && isCardInstance(card));
|
|
672
|
-
}, { timeout: 5e3 });
|
|
673
|
-
let peek = storeService.peek(instance[localId]);
|
|
674
|
-
assert.strictEqual(peek.name, "Andrea", "peek-ed value has been updated to be the fixed card instance");
|
|
675
|
-
} else assert.ok(false, "expected a card error but got a running instance");
|
|
676
|
-
});
|
|
677
|
-
(0, import_qunit.test)("can add a running instance to the store", async function(assert) {
|
|
678
|
-
assert.expect(5);
|
|
679
|
-
this.onSave((_, doc) => {
|
|
680
|
-
assert.strictEqual(doc.data.attributes?.name, "Andrea", "card data is correct");
|
|
681
|
-
});
|
|
682
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
683
|
-
await storeService.add(instance);
|
|
684
|
-
assert.ok(instance.id, "instance has been assigned remote id");
|
|
685
|
-
let peekedInstance = storeService.peek(instance.id);
|
|
686
|
-
assert.strictEqual(instance, peekedInstance, "instance is the same");
|
|
687
|
-
let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
|
|
688
|
-
assert.ok(file, "file exists");
|
|
689
|
-
let fileJSON = JSON.parse(file.content);
|
|
690
|
-
assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
|
|
691
|
-
});
|
|
692
|
-
(0, import_qunit.test)("add() does not persist an existing card when the realm is read-only", async function(assert) {
|
|
693
|
-
storeService.realm.permissions = () => ({
|
|
694
|
-
get canRead() {
|
|
695
|
-
return true;
|
|
696
|
-
},
|
|
697
|
-
get canWrite() {
|
|
698
|
-
return false;
|
|
699
|
-
}
|
|
700
|
-
});
|
|
701
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
702
|
-
let writes = [];
|
|
703
|
-
this.onSave((url) => writes.push(url.href));
|
|
704
|
-
instance.name = "Hassan Updated";
|
|
705
|
-
let result = await storeService.add(instance);
|
|
706
|
-
await settled();
|
|
707
|
-
assert.deepEqual(writes, [], "no write is attempted without permission");
|
|
708
|
-
assert.true(isCardInstance(result), "add() still resolves with the instance rather than a permission error");
|
|
709
|
-
let file = await testRealmAdapter.openFile("Person/hassan.json");
|
|
710
|
-
assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Hassan", "the durable document is untouched");
|
|
711
|
-
});
|
|
712
|
-
(0, import_qunit.test)("add() reports its save in the card save state", async function(assert) {
|
|
713
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
714
|
-
instance.name = "Hassan Updated";
|
|
715
|
-
await storeService.add(instance);
|
|
716
|
-
let saveState = storeService.getSaveState(instance.id);
|
|
717
|
-
assert.false(saveState.hasUnsavedChanges, "the card no longer reports unsaved changes");
|
|
718
|
-
assert.ok(saveState.lastSaved, "lastSaved reflects the add()-driven save");
|
|
719
|
-
assert.strictEqual(saveState.lastSaveError, void 0, "no save error is reported");
|
|
720
|
-
assert.false(saveState.isSaving, "the save is no longer in flight");
|
|
721
|
-
});
|
|
722
|
-
(0, import_qunit.test)("add() records a persistence failure in the card save state", async function(assert) {
|
|
723
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
724
|
-
instance.name = "Hassan Updated";
|
|
725
|
-
let store = storeService;
|
|
726
|
-
store.saveCardDocument = async () => {
|
|
727
|
-
throw new Error("intentional persistence failure");
|
|
728
|
-
};
|
|
729
|
-
try {
|
|
730
|
-
await storeService.add(instance);
|
|
731
|
-
} finally {
|
|
732
|
-
delete store.saveCardDocument;
|
|
733
|
-
}
|
|
734
|
-
let saveState = storeService.getSaveState(instance.id);
|
|
735
|
-
assert.ok(saveState.lastSaveError, "the failure is visible to the save indicator, not only to the caller");
|
|
736
|
-
assert.false(saveState.isSaving, "the save is no longer in flight");
|
|
737
|
-
});
|
|
738
|
-
(0, import_qunit.test)("add() awaits durable persistence for an existing card", async function(assert) {
|
|
739
|
-
let queenzy = await storeService.get(`${testRealmURL}Person/queenzy`);
|
|
740
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
741
|
-
instance.name = "Hassan Updated";
|
|
742
|
-
instance.bestFriend = queenzy;
|
|
743
|
-
let result = await storeService.add(instance);
|
|
744
|
-
assert.true(isCardInstance(result), "add() resolves with the card instance");
|
|
745
|
-
let file = await testRealmAdapter.openFile("Person/hassan.json");
|
|
746
|
-
let fileJSON = JSON.parse(file.content);
|
|
747
|
-
assert.strictEqual(fileJSON.data.attributes.name, "Hassan Updated", "the scalar mutation is durable as soon as add() resolves");
|
|
748
|
-
assert.ok(fileJSON.data.relationships.bestFriend.links.self.endsWith("queenzy"), "the link mutation is durable as soon as add() resolves");
|
|
749
|
-
});
|
|
750
|
-
(0, import_qunit.test)("add() stays pending until an existing card is durably persisted", async function(assert) {
|
|
751
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
752
|
-
instance.name = "Hassan Updated";
|
|
753
|
-
let store = storeService;
|
|
754
|
-
let gate = new Deferred();
|
|
755
|
-
let originalPersist = store.persistAndUpdate;
|
|
756
|
-
store.persistAndUpdate = async (...args) => {
|
|
757
|
-
await gate.promise;
|
|
758
|
-
return await originalPersist.call(store, ...args);
|
|
759
|
-
};
|
|
760
|
-
try {
|
|
761
|
-
let resolved = false;
|
|
762
|
-
let addPromise = storeService.add(instance).then((r) => {
|
|
763
|
-
resolved = true;
|
|
764
|
-
return r;
|
|
765
|
-
});
|
|
766
|
-
for (let i = 0; i < 10; i++) await Promise.resolve();
|
|
767
|
-
assert.false(resolved, "add() has not resolved while persistence is gated");
|
|
768
|
-
gate.fulfill();
|
|
769
|
-
await addPromise;
|
|
770
|
-
assert.true(resolved, "add() resolves once persistence completes");
|
|
771
|
-
} finally {
|
|
772
|
-
delete store.persistAndUpdate;
|
|
773
|
-
}
|
|
774
|
-
let file = await testRealmAdapter.openFile("Person/hassan.json");
|
|
775
|
-
assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Hassan Updated", "the mutation is durably persisted");
|
|
776
|
-
});
|
|
777
|
-
(0, import_qunit.test)("add() surfaces persistence failures for an existing card", async function(assert) {
|
|
778
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
779
|
-
instance.name = "Hassan Updated";
|
|
780
|
-
let store = storeService;
|
|
781
|
-
store.saveCardDocument = async () => {
|
|
782
|
-
throw new Error("intentional persistence failure");
|
|
783
|
-
};
|
|
784
|
-
let result;
|
|
785
|
-
try {
|
|
786
|
-
result = await storeService.add(instance);
|
|
787
|
-
} finally {
|
|
788
|
-
delete store.saveCardDocument;
|
|
789
|
-
}
|
|
790
|
-
assert.false(isCardInstance(result), "add() resolves with a card error rather than the instance when persistence fails");
|
|
791
|
-
assert.ok(result.message.includes("intentional persistence failure"), "the persistence error propagates to the caller instead of being swallowed");
|
|
792
|
-
});
|
|
793
|
-
(0, import_qunit.test)("can add a serialized instance to the store", async function(assert) {
|
|
794
|
-
assert.expect(6);
|
|
795
|
-
this.onSave((_, doc) => {
|
|
796
|
-
assert.strictEqual(doc.data.attributes?.name, "Andrea", "card data is correct");
|
|
797
|
-
});
|
|
798
|
-
let instance = await storeService.add({ data: {
|
|
799
|
-
attributes: { name: "Andrea" },
|
|
800
|
-
meta: { adoptsFrom: {
|
|
801
|
-
module: testRRI("person"),
|
|
802
|
-
name: "Person"
|
|
803
|
-
} }
|
|
804
|
-
} });
|
|
805
|
-
assert.ok(instance.id, "instance has been assigned remote id");
|
|
806
|
-
let peekedInstance = storeService.peek(instance.id);
|
|
807
|
-
assert.strictEqual(instance, peekedInstance, "instance is the same");
|
|
808
|
-
assert.strictEqual(instance.name, "Andrea", "instance data is correct");
|
|
809
|
-
let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
|
|
810
|
-
assert.ok(file, "file exists");
|
|
811
|
-
let fileJSON = JSON.parse(file.content);
|
|
812
|
-
assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
|
|
813
|
-
});
|
|
814
|
-
(0, import_qunit.test)("can skip saving when adding to the store", async function(assert) {
|
|
815
|
-
assert.expect(3);
|
|
816
|
-
this.onSave(() => {
|
|
817
|
-
assert.ok(false, "save should not happen");
|
|
818
|
-
});
|
|
819
|
-
let instance = await storeService.addWithoutPersisting({ data: {
|
|
820
|
-
attributes: { name: "Andrea" },
|
|
821
|
-
meta: { adoptsFrom: {
|
|
822
|
-
module: testRRI("person"),
|
|
823
|
-
name: "Person"
|
|
824
|
-
} }
|
|
825
|
-
} }, {});
|
|
826
|
-
assert.strictEqual(instance.id, void 0, "instance has NOT been assigned remote id");
|
|
827
|
-
let peekedInstance = storeService.peek(instance[localId]);
|
|
828
|
-
assert.strictEqual(instance, peekedInstance, "instance is the same");
|
|
829
|
-
assert.strictEqual(instance.name, "Andrea", "instance data is correct");
|
|
830
|
-
});
|
|
831
|
-
(0, import_qunit.test)("can skip waiting for the save when adding to the store", async function(assert) {
|
|
832
|
-
assert.expect(6);
|
|
833
|
-
let didSave = false;
|
|
834
|
-
this.onSave((_, doc) => {
|
|
835
|
-
didSave = true;
|
|
836
|
-
assert.strictEqual(doc.data.attributes?.name, "Andrea", "card data is correct");
|
|
837
|
-
});
|
|
838
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
839
|
-
await storeService.addWithoutWaiting(instance);
|
|
840
|
-
assert.false(didSave, "the instance has not saved yet");
|
|
841
|
-
await waitUntil(() => didSave, { timeout: 1e4 });
|
|
842
|
-
assert.ok(instance.id, "instance has been assigned remote id");
|
|
843
|
-
let peekedInstance = storeService.peek(instance.id);
|
|
844
|
-
assert.strictEqual(instance, peekedInstance, "instance is the same");
|
|
845
|
-
let file = await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`);
|
|
846
|
-
assert.ok(file, "file exists");
|
|
847
|
-
let fileJSON = JSON.parse(file.content);
|
|
848
|
-
assert.strictEqual(fileJSON.data.attributes.name, "Andrea", "file exists");
|
|
849
|
-
});
|
|
850
|
-
(0, import_qunit.test)("can set realmURL when adding to the store", async function(assert) {
|
|
851
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
852
|
-
assert.strictEqual(instance[realmURL]?.href, void 0, "realmURL meta is not set on the instance");
|
|
853
|
-
await storeService.addWithoutPersisting(instance, { realm: testRealmURL });
|
|
854
|
-
assert.strictEqual(instance[realmURL]?.href, testRealmURL, "realmURL meta was set on the instance");
|
|
855
|
-
});
|
|
856
|
-
(0, import_qunit.test)("can add linked cards to the store when adding a card", async function(assert) {
|
|
857
|
-
let wu = new PersonDef({ name: "Wu" });
|
|
858
|
-
let michael = new PersonDef({ name: "Michael" });
|
|
859
|
-
let lin = new PersonDef({
|
|
860
|
-
name: "Lin",
|
|
861
|
-
bestFriend: wu,
|
|
862
|
-
friends: [michael]
|
|
863
|
-
});
|
|
864
|
-
await storeService.addWithoutPersisting(lin);
|
|
865
|
-
let peekedMichael = storeService.peek(michael[localId]);
|
|
866
|
-
assert.strictEqual(peekedMichael, michael, "michael instance added to store");
|
|
867
|
-
let peekedWu = storeService.peek(wu[localId]);
|
|
868
|
-
assert.strictEqual(peekedWu, wu, "wu instance added to store");
|
|
869
|
-
});
|
|
870
|
-
(0, import_qunit.test)("can reject a card added to the store that has a conflicting local ID for a given URL", async function(assert) {
|
|
871
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
872
|
-
await storeService.flush();
|
|
873
|
-
let doc = { data: {
|
|
874
|
-
type: "card",
|
|
875
|
-
id: testRRI("Person/hassan"),
|
|
876
|
-
attributes: { name: "Hassan" },
|
|
877
|
-
meta: { adoptsFrom: {
|
|
878
|
-
module: testRRI("person"),
|
|
879
|
-
name: "Person"
|
|
880
|
-
} }
|
|
881
|
-
} };
|
|
882
|
-
let conflictingInstance = await api.createFromSerialized(doc.data, doc, void 0);
|
|
883
|
-
try {
|
|
884
|
-
await storeService.addWithoutPersisting(conflictingInstance);
|
|
885
|
-
throw new Error("expected exception to be thrown");
|
|
886
|
-
} catch (err) {
|
|
887
|
-
assert.ok(err.message.includes("has conflicting instance id in store"), "the expected error was thrown");
|
|
888
|
-
}
|
|
889
|
-
});
|
|
890
|
-
(0, import_qunit.test)("added instance that was previously not saved will begin to auto save after being added", async function(assert) {
|
|
891
|
-
assert.expect(2);
|
|
892
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
893
|
-
await storeService.add(instance);
|
|
894
|
-
this.onSave((url, doc) => {
|
|
895
|
-
assert.strictEqual(url.href, instance.id, "the instance URL is correct");
|
|
896
|
-
assert.strictEqual(doc.data.attributes?.name, "Air", "card data is correct");
|
|
897
|
-
});
|
|
898
|
-
instance.name = "Air";
|
|
899
|
-
});
|
|
900
|
-
(0, import_qunit.test)("an instance will auto save when its data changes", async function(assert) {
|
|
901
|
-
assert.expect(2);
|
|
902
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
903
|
-
this.onSave((url, doc) => {
|
|
904
|
-
assert.strictEqual(url.href, instance.id, "the instance URL is correct");
|
|
905
|
-
assert.strictEqual(doc.data.attributes?.name, "Paper", "card data is correct");
|
|
906
|
-
});
|
|
907
|
-
instance.name = "Paper";
|
|
908
|
-
});
|
|
909
|
-
(0, import_qunit.test)("an unsaved instance will auto save when its data changes", async function(assert) {
|
|
910
|
-
assert.expect(2);
|
|
911
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
912
|
-
await storeService.addWithoutPersisting(instance);
|
|
913
|
-
this.onSave((url, doc) => {
|
|
914
|
-
assert.strictEqual(url.href.split("/").pop(), instance[localId], "the new card url ends with the local id");
|
|
915
|
-
assert.strictEqual(doc.data.attributes?.name, "Air", "card data is correct");
|
|
916
|
-
});
|
|
917
|
-
instance.name = "Air";
|
|
918
|
-
});
|
|
919
|
-
(0, import_qunit.test)("an instance will NOT auto save when its data changes, if the user does not have write permissions", async function(assert) {
|
|
920
|
-
storeService.realm.permissions = () => ({
|
|
921
|
-
get canRead() {
|
|
922
|
-
return true;
|
|
923
|
-
},
|
|
924
|
-
get canWrite() {
|
|
925
|
-
return false;
|
|
926
|
-
}
|
|
927
|
-
});
|
|
928
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
929
|
-
this.onSave(() => {
|
|
930
|
-
assert.ok(false, "should not save");
|
|
931
|
-
});
|
|
932
|
-
instance.name = "Paper";
|
|
933
|
-
assert.strictEqual(instance.name, "Paper");
|
|
934
|
-
let id = instance.id;
|
|
935
|
-
assert.deepEqual(storeService.getSaveState(id), {
|
|
936
|
-
hasUnsavedChanges: true,
|
|
937
|
-
isSaving: false,
|
|
938
|
-
lastSaveError: void 0,
|
|
939
|
-
lastSaved: void 0,
|
|
940
|
-
lastSavedErrorMsg: void 0
|
|
941
|
-
});
|
|
942
|
-
});
|
|
943
|
-
(0, import_qunit.test)("an instance can debounce auto saves", async function(assert) {
|
|
944
|
-
assert.expect(5);
|
|
945
|
-
setCardInOperatorModeState(`${testRealmURL}Person/hassan`, "edit");
|
|
946
|
-
await renderComponent(class TestDriver extends Component {
|
|
947
|
-
static {
|
|
948
|
-
setComponentTemplate(templateFactory({
|
|
949
|
-
"id": "ZD1xwmB+",
|
|
950
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
951
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
952
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
953
|
-
"isStrictMode": true
|
|
954
|
-
}), this);
|
|
955
|
-
}
|
|
956
|
-
});
|
|
957
|
-
let nameInput = `[data-test-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"] input`;
|
|
958
|
-
let typedSoFar = () => find(nameInput)?.value;
|
|
959
|
-
let typedWhenIssued = [];
|
|
960
|
-
let saveLog = [];
|
|
961
|
-
let saveTrace = () => `saves so far: ${saveLog.join(" | ")}`;
|
|
962
|
-
let saveCount = 0;
|
|
963
|
-
this.onSave((url, doc) => {
|
|
964
|
-
saveCount++;
|
|
965
|
-
let savedName = doc.data?.attributes?.name;
|
|
966
|
-
saveLog.push(`#${saveCount} issuedAfter=${JSON.stringify(typedWhenIssued[saveCount - 1])} saved=${JSON.stringify(savedName)}`);
|
|
967
|
-
assert.strictEqual(url.href, `${testRealmURL}Person/hassan`, "correct document is saved");
|
|
968
|
-
switch (saveCount) {
|
|
969
|
-
case 1:
|
|
970
|
-
assert.strictEqual(savedName, "Hassan ", `the initial instance mutation event is saved (${saveTrace()})`);
|
|
971
|
-
break;
|
|
972
|
-
case 2:
|
|
973
|
-
assert.strictEqual(savedName, "Hassan Paper", `the final instance mutation event is saved (${saveTrace()})`);
|
|
974
|
-
break;
|
|
975
|
-
default: assert.ok(false, `unexpected number of saves: ${saveCount} (${saveTrace()})`);
|
|
976
|
-
}
|
|
977
|
-
});
|
|
978
|
-
await withSavesHeldOpen(async (release) => {
|
|
979
|
-
let keystrokes = typeIn(nameInput, " Paper");
|
|
980
|
-
keystrokes.catch(() => {});
|
|
981
|
-
try {
|
|
982
|
-
await Promise.race([keystrokes, waitUntil(() => typedSoFar() === "Hassan Paper", { timeout: 3e3 })]);
|
|
983
|
-
} catch (err) {
|
|
984
|
-
throw new Error(`the keystrokes did not land, input holds ${JSON.stringify(typedSoFar())} (${saveTrace()})`, { cause: err });
|
|
985
|
-
}
|
|
986
|
-
release();
|
|
987
|
-
await keystrokes;
|
|
988
|
-
}, { onSaveIssued: () => typedWhenIssued.push(typedSoFar()) });
|
|
989
|
-
assert.strictEqual(saveCount, 2, `the number of auto-saves is correct (${saveTrace()})`);
|
|
990
|
-
});
|
|
991
|
-
(0, import_qunit.test)("a non-immediate auto save stays in flight for the save-indicator floor", async function(assert) {
|
|
992
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
993
|
-
let id = instance.id;
|
|
994
|
-
let store = storeService;
|
|
995
|
-
let originalPersist = store.persistAndUpdate;
|
|
996
|
-
store.persistAndUpdate = async () => instance;
|
|
997
|
-
try {
|
|
998
|
-
let startedAt = Date.now();
|
|
999
|
-
instance.name = "Paper";
|
|
1000
|
-
await waitUntil(() => storeService.getSaveState(id)?.lastSaved, { timeout: 5e3 });
|
|
1001
|
-
let heldMs = Date.now() - startedAt;
|
|
1002
|
-
assert.ok(heldMs >= 500, `the save is held in flight for the floor (held ${heldMs}ms)`);
|
|
1003
|
-
} finally {
|
|
1004
|
-
store.persistAndUpdate = originalPersist;
|
|
1005
|
-
}
|
|
1006
|
-
});
|
|
1007
|
-
(0, import_qunit.test)("getSaveState works for initially unsaved instance", async function(assert) {
|
|
1008
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
1009
|
-
await storeService.addWithoutPersisting(instance);
|
|
1010
|
-
assert.strictEqual(storeService.getSaveState(instance[localId]), void 0, "save state is undefined");
|
|
1011
|
-
instance.name = "Air";
|
|
1012
|
-
assert.true(storeService.getSaveState(instance[localId])?.hasUnsavedChanges, "hasUnsavedChanges state is correct");
|
|
1013
|
-
await waitUntil(() => storeService.getSaveState(instance[localId])?.isSaving, { timeout: 1e4 });
|
|
1014
|
-
await waitUntil(() => storeService.getSaveState(instance[localId])?.lastSaved, { timeout: 1e4 });
|
|
1015
|
-
assert.false(storeService.getSaveState(instance[localId])?.isSaving, "isSaving state is correct");
|
|
1016
|
-
assert.false(storeService.getSaveState(instance.id)?.isSaving, "isSaving state is correct (by remote id)");
|
|
1017
|
-
assert.ok(storeService.getSaveState(instance.id)?.lastSaved, "lastSaved state is correct (by remote id)");
|
|
1018
|
-
});
|
|
1019
|
-
(0, import_qunit.test)("can capture error when auto saving", async function(assert) {
|
|
1020
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
1021
|
-
try {
|
|
1022
|
-
globalThis.__emulateServerPatchFailure = true;
|
|
1023
|
-
instance.hasError = true;
|
|
1024
|
-
await waitUntil(() => storeService.getSaveState(`${testRealmURL}Person/hassan`)?.lastSaveError, { timeout: 1e4 });
|
|
1025
|
-
let saveState = storeService.getSaveState(`${testRealmURL}Person/hassan`);
|
|
1026
|
-
assert.ok(saveState.lastSavedErrorMsg?.includes("intentional error thrown"), "error message is correct");
|
|
1027
|
-
} finally {
|
|
1028
|
-
delete globalThis.__emulateServerPatchFailure;
|
|
1029
|
-
}
|
|
1030
|
-
});
|
|
1031
|
-
(0, import_qunit.module)("auto save waits for edits to pause", function(hooks) {
|
|
1032
|
-
let saves;
|
|
1033
|
-
let originalQuietPeriodMs;
|
|
1034
|
-
let originalMaxWaitMs;
|
|
1035
|
-
function recordSave(url, doc) {
|
|
1036
|
-
saves.push({
|
|
1037
|
-
url: url.href,
|
|
1038
|
-
name: doc.data?.attributes?.name
|
|
1039
|
-
});
|
|
1040
|
-
}
|
|
1041
|
-
hooks.beforeEach(function() {
|
|
1042
|
-
saves = [];
|
|
1043
|
-
this.onSave(recordSave);
|
|
1044
|
-
let environment = getService("environment-service");
|
|
1045
|
-
originalQuietPeriodMs = environment.autoSaveQuietPeriodMs;
|
|
1046
|
-
originalMaxWaitMs = environment.autoSaveMaxWaitMs;
|
|
1047
|
-
setAutoSaveTiming(NEVER, NEVER);
|
|
1048
|
-
});
|
|
1049
|
-
hooks.afterEach(function() {
|
|
1050
|
-
let environment = getService("environment-service");
|
|
1051
|
-
environment.autoSaveQuietPeriodMs = originalQuietPeriodMs;
|
|
1052
|
-
environment.autoSaveMaxWaitMs = originalMaxWaitMs;
|
|
1053
|
-
});
|
|
1054
|
-
function setAutoSaveTiming(quietPeriodMs, maxWaitMs) {
|
|
1055
|
-
let environment = getService("environment-service");
|
|
1056
|
-
environment.autoSaveQuietPeriodMs = quietPeriodMs;
|
|
1057
|
-
environment.autoSaveMaxWaitMs = maxWaitMs;
|
|
1058
|
-
}
|
|
1059
|
-
const NEVER = 10 * 6e4;
|
|
1060
|
-
function pause(ms) {
|
|
1061
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1062
|
-
}
|
|
1063
|
-
async function waitForSaves(count, message) {
|
|
1064
|
-
try {
|
|
1065
|
-
await waitUntil(() => saves.length >= count, { timeout: 5e3 });
|
|
1066
|
-
} catch (err) {
|
|
1067
|
-
throw new Error(`${message}: expected ${count} save(s), saw ${JSON.stringify(saves)}`, { cause: err });
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
function recordWrites(onWrite) {
|
|
1071
|
-
let virtualNetwork = getService("network").virtualNetwork;
|
|
1072
|
-
let originalFetch = virtualNetwork.fetch;
|
|
1073
|
-
let writes = [];
|
|
1074
|
-
virtualNetwork.fetch = async (input, init) => {
|
|
1075
|
-
let request = input instanceof Request ? input : void 0;
|
|
1076
|
-
let method = init?.method ?? request?.method ?? "GET";
|
|
1077
|
-
if (method === "PATCH" || method === "POST") {
|
|
1078
|
-
let url = request?.url ?? String(input);
|
|
1079
|
-
writes.push({
|
|
1080
|
-
url,
|
|
1081
|
-
keepalive: init?.keepalive ?? request?.keepalive ?? false
|
|
1082
|
-
});
|
|
1083
|
-
onWrite?.(url);
|
|
1084
|
-
}
|
|
1085
|
-
return await originalFetch.call(virtualNetwork, input, init);
|
|
1086
|
-
};
|
|
1087
|
-
return {
|
|
1088
|
-
writes,
|
|
1089
|
-
restore: () => virtualNetwork.fetch = originalFetch
|
|
1090
|
-
};
|
|
1091
|
-
}
|
|
1092
|
-
function hidePage() {
|
|
1093
|
-
Object.defineProperty(document, "visibilityState", {
|
|
1094
|
-
configurable: true,
|
|
1095
|
-
get: () => "hidden"
|
|
1096
|
-
});
|
|
1097
|
-
try {
|
|
1098
|
-
document.dispatchEvent(new Event("visibilitychange"));
|
|
1099
|
-
} finally {
|
|
1100
|
-
delete document.visibilityState;
|
|
1101
|
-
}
|
|
1102
|
-
}
|
|
1103
|
-
(0, import_qunit.test)("edits are saved once, after they pause", async function(assert) {
|
|
1104
|
-
setAutoSaveTiming(300, NEVER);
|
|
1105
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1106
|
-
let instance = await storeService.get(id);
|
|
1107
|
-
for (let name of [
|
|
1108
|
-
"H",
|
|
1109
|
-
"Ha",
|
|
1110
|
-
"Has",
|
|
1111
|
-
"Hass",
|
|
1112
|
-
"Hassa"
|
|
1113
|
-
]) {
|
|
1114
|
-
instance.name = name;
|
|
1115
|
-
await pause(50);
|
|
1116
|
-
}
|
|
1117
|
-
assert.strictEqual(saves.length, 0, "nothing is saved while editing");
|
|
1118
|
-
let saveState = storeService.getSaveState(id);
|
|
1119
|
-
assert.true(saveState.hasUnsavedChanges, "the card has unsaved changes");
|
|
1120
|
-
assert.false(saveState.isSaving, "the card is not saving yet");
|
|
1121
|
-
assert.strictEqual(saveState.lastSavedErrorMsg, "Unsaved changes", "the indicator reports unsaved changes");
|
|
1122
|
-
await waitForSaves(1, "the edits are saved once they pause");
|
|
1123
|
-
await storeService.flushSaves();
|
|
1124
|
-
assert.deepEqual(saves, [{
|
|
1125
|
-
url: id,
|
|
1126
|
-
name: "Hassa"
|
|
1127
|
-
}], "one save carries the last edit");
|
|
1128
|
-
assert.false(storeService.getSaveState(id).hasUnsavedChanges, "nothing is left unsaved");
|
|
1129
|
-
assert.ok(storeService.getSaveState(id).lastSavedErrorMsg?.startsWith("Saved"), "the indicator reports the save");
|
|
1130
|
-
});
|
|
1131
|
-
(0, import_qunit.test)("editing without a pause is saved at the maximum wait", async function(assert) {
|
|
1132
|
-
setAutoSaveTiming(300, 600);
|
|
1133
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1134
|
-
let instance = await storeService.get(id);
|
|
1135
|
-
let maxWaitMs = 600;
|
|
1136
|
-
let edits = 30;
|
|
1137
|
-
let startedAt = Date.now();
|
|
1138
|
-
let timeline = [];
|
|
1139
|
-
this.onSave((url, doc) => {
|
|
1140
|
-
recordSave(url, doc);
|
|
1141
|
-
timeline.push(`saved@${Date.now() - startedAt}`);
|
|
1142
|
-
});
|
|
1143
|
-
let { writes, restore } = recordWrites((url) => timeline.push(`${url === id ? "sent" : `sent ${url}`}@${Date.now() - startedAt}`));
|
|
1144
|
-
let editingMs;
|
|
1145
|
-
let sentWhileEditing;
|
|
1146
|
-
try {
|
|
1147
|
-
for (let i = 1; i <= edits; i++) {
|
|
1148
|
-
instance.name = `Hassan ${i}`;
|
|
1149
|
-
await pause(100);
|
|
1150
|
-
}
|
|
1151
|
-
editingMs = Date.now() - startedAt;
|
|
1152
|
-
sentWhileEditing = writes.filter((w) => w.url === id).length;
|
|
1153
|
-
timeline.push(`editing-ended@${editingMs}`);
|
|
1154
|
-
await storeService.flushSaves();
|
|
1155
|
-
} finally {
|
|
1156
|
-
restore();
|
|
1157
|
-
}
|
|
1158
|
-
assert.ok(sentWhileEditing >= 1, `edits are saved while editing goes on (${sentWhileEditing} sent; ${timeline.join(", ")})`);
|
|
1159
|
-
let bound = Math.ceil(editingMs / maxWaitMs) + 1;
|
|
1160
|
-
assert.ok(saves.length <= bound, `${edits} edits over ${editingMs}ms take at most ${bound} saves (${saves.length} saved; ${timeline.join(", ")})`);
|
|
1161
|
-
assert.ok(saves.length < edits / 3, `${edits} edits take far fewer saves than edits (${saves.length} saved; ${timeline.join(", ")})`);
|
|
1162
|
-
assert.strictEqual(saves[saves.length - 1]?.name, `Hassan ${edits}`, "the last save carries the last edit");
|
|
1163
|
-
});
|
|
1164
|
-
(0, import_qunit.test)("an edit made while its save runs stays unsaved until the next save", async function(assert) {
|
|
1165
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1166
|
-
let instance = await storeService.get(id);
|
|
1167
|
-
await withSavesHeldOpen(async (release) => {
|
|
1168
|
-
instance.name = "Paper";
|
|
1169
|
-
document.body.dispatchEvent(new FocusEvent("focusout", { bubbles: true }));
|
|
1170
|
-
await waitUntil(() => storeService.getSaveState(id)?.isSaving);
|
|
1171
|
-
instance.name = "Paper Hassan";
|
|
1172
|
-
release();
|
|
1173
|
-
await waitUntil(() => !storeService.getSaveState(id)?.isSaving);
|
|
1174
|
-
let saveState = storeService.getSaveState(id);
|
|
1175
|
-
assert.true(saveState.hasUnsavedChanges, "the edit made during the save is still unsaved");
|
|
1176
|
-
assert.strictEqual(saveState.lastSavedErrorMsg, "Unsaved changes", "the indicator does not report the edit as saved");
|
|
1177
|
-
});
|
|
1178
|
-
await storeService.flushSaves();
|
|
1179
|
-
assert.deepEqual(saves.map((s) => s.name), ["Paper", "Paper Hassan"], "both edits are saved, in order");
|
|
1180
|
-
assert.false(storeService.getSaveState(id).hasUnsavedChanges);
|
|
1181
|
-
});
|
|
1182
|
-
(0, import_qunit.test)("a pending save is sent when the last reference to its card is dropped", async function(assert) {
|
|
1183
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1184
|
-
storeService.addReference(id);
|
|
1185
|
-
await storeService.flush();
|
|
1186
|
-
let instance = storeService.peek(id);
|
|
1187
|
-
instance.name = "Paper";
|
|
1188
|
-
storeService.dropReference(id);
|
|
1189
|
-
await waitForSaves(1, "dropping the last reference sends the save");
|
|
1190
|
-
assert.deepEqual(saves, [{
|
|
1191
|
-
url: id,
|
|
1192
|
-
name: "Paper"
|
|
1193
|
-
}]);
|
|
1194
|
-
await storeService.flushSaves();
|
|
1195
|
-
assert.strictEqual(storeService.getReferenceCount(id), 0, "the save's hold on the card is released once it lands");
|
|
1196
|
-
});
|
|
1197
|
-
(0, import_qunit.test)("a pending save is not sent early while something still shows its card", async function(assert) {
|
|
1198
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1199
|
-
storeService.addReference(id);
|
|
1200
|
-
storeService.addReference(id);
|
|
1201
|
-
await storeService.flush();
|
|
1202
|
-
let instance = storeService.peek(id);
|
|
1203
|
-
instance.name = "Paper";
|
|
1204
|
-
storeService.dropReference(id);
|
|
1205
|
-
await pause(1e3);
|
|
1206
|
-
assert.strictEqual(saves.length, 0, "the save keeps waiting");
|
|
1207
|
-
storeService.dropReference(id);
|
|
1208
|
-
await waitForSaves(1, "dropping the last reference sends the save");
|
|
1209
|
-
assert.deepEqual(saves, [{
|
|
1210
|
-
url: id,
|
|
1211
|
-
name: "Paper"
|
|
1212
|
-
}]);
|
|
1213
|
-
});
|
|
1214
|
-
(0, import_qunit.test)("garbage collection keeps a card whose save is pending", async function(assert) {
|
|
1215
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1216
|
-
let controlId = `${testRealmURL}Person/jade`;
|
|
1217
|
-
let instance = await storeService.get(id);
|
|
1218
|
-
let control = await storeService.get(controlId);
|
|
1219
|
-
assert.strictEqual(storeService.getReferenceCount(id), 0);
|
|
1220
|
-
assert.strictEqual(storeService.getReferenceCount(controlId), 0);
|
|
1221
|
-
instance.name = "Paper";
|
|
1222
|
-
forceGC();
|
|
1223
|
-
assert.strictEqual(storeService.peek(controlId), void 0, "an unreferenced card without a pending save is collected");
|
|
1224
|
-
assert.notStrictEqual(control, void 0);
|
|
1225
|
-
assert.strictEqual(storeService.peek(id), instance, "the card with a pending save is kept");
|
|
1226
|
-
await storeService.flushSaves();
|
|
1227
|
-
assert.deepEqual(saves, [{
|
|
1228
|
-
url: id,
|
|
1229
|
-
name: "Paper"
|
|
1230
|
-
}]);
|
|
1231
|
-
});
|
|
1232
|
-
(0, import_qunit.test)("flushSaves sends pending saves and waits for them", async function(assert) {
|
|
1233
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1234
|
-
let instance = await storeService.get(id);
|
|
1235
|
-
instance.name = "Paper";
|
|
1236
|
-
await storeService.flushSaves();
|
|
1237
|
-
assert.deepEqual(saves, [{
|
|
1238
|
-
url: id,
|
|
1239
|
-
name: "Paper"
|
|
1240
|
-
}]);
|
|
1241
|
-
assert.false(storeService.hasUnsavedEdits);
|
|
1242
|
-
});
|
|
1243
|
-
(0, import_qunit.test)("ending the session drops saves still waiting for typing to pause", async function(assert) {
|
|
1244
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1245
|
-
let instance = await storeService.get(id);
|
|
1246
|
-
instance.name = "Paper";
|
|
1247
|
-
storeService.resetState();
|
|
1248
|
-
storeService._onSave(recordSave);
|
|
1249
|
-
await pause(1e3);
|
|
1250
|
-
assert.deepEqual(saves, [], "nothing is written after the session ends");
|
|
1251
|
-
assert.false(storeService.hasUnsavedEdits, "nothing is left pending");
|
|
1252
|
-
});
|
|
1253
|
-
(0, import_qunit.test)("a save queued behind a running one does not write once the session ends", async function(assert) {
|
|
1254
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1255
|
-
let instance = await storeService.get(id);
|
|
1256
|
-
await withSavesHeldOpen(async (release) => {
|
|
1257
|
-
instance.name = "Paper";
|
|
1258
|
-
storeService.flushSaves();
|
|
1259
|
-
await waitUntil(() => storeService.getSaveState(id)?.isSaving);
|
|
1260
|
-
instance.name = "Paper Hassan";
|
|
1261
|
-
storeService.flushSaves();
|
|
1262
|
-
storeService.resetState();
|
|
1263
|
-
storeService._onSave(recordSave);
|
|
1264
|
-
release();
|
|
1265
|
-
await waitUntil(() => !storeService.hasUnsavedEdits, { timeout: 5e3 });
|
|
1266
|
-
});
|
|
1267
|
-
assert.deepEqual(saves.map((s) => s.name), ["Paper"], "only the save that started before the session ended is written");
|
|
1268
|
-
});
|
|
1269
|
-
(0, import_qunit.test)("logout saves pending edits before the session ends", async function(assert) {
|
|
1270
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1271
|
-
let instance = await storeService.get(id);
|
|
1272
|
-
instance.name = "Paper";
|
|
1273
|
-
let matrixService = getService("matrix-service");
|
|
1274
|
-
let originalClearAuth = matrixService.clearAuth;
|
|
1275
|
-
let originalResetState = matrixService.resetState;
|
|
1276
|
-
let savedWhenAuthCleared;
|
|
1277
|
-
matrixService.clearAuth = () => {
|
|
1278
|
-
savedWhenAuthCleared = [...saves];
|
|
1279
|
-
throw new Error("stop logout here");
|
|
1280
|
-
};
|
|
1281
|
-
matrixService.resetState = () => {};
|
|
1282
|
-
try {
|
|
1283
|
-
await matrixService.logout({ skipIndexTransition: true });
|
|
1284
|
-
} finally {
|
|
1285
|
-
matrixService.clearAuth = originalClearAuth;
|
|
1286
|
-
matrixService.resetState = originalResetState;
|
|
1287
|
-
}
|
|
1288
|
-
assert.deepEqual(savedWhenAuthCleared, [{
|
|
1289
|
-
url: id,
|
|
1290
|
-
name: "Paper"
|
|
1291
|
-
}], "the edit is saved before auth is cleared");
|
|
1292
|
-
});
|
|
1293
|
-
(0, import_qunit.test)("resetting the store cache sends pending saves", async function(assert) {
|
|
1294
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1295
|
-
let instance = await storeService.get(id);
|
|
1296
|
-
instance.name = "Paper";
|
|
1297
|
-
storeService.resetCache();
|
|
1298
|
-
await waitForSaves(1, "the reset sends the save");
|
|
1299
|
-
assert.deepEqual(saves, [{
|
|
1300
|
-
url: id,
|
|
1301
|
-
name: "Paper"
|
|
1302
|
-
}]);
|
|
1303
|
-
await storeService.flushSaves();
|
|
1304
|
-
});
|
|
1305
|
-
(0, import_qunit.test)("hiding the page sends pending saves as requests that outlive the page", async function(assert) {
|
|
1306
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1307
|
-
let instance = await storeService.get(id);
|
|
1308
|
-
instance.name = "Paper";
|
|
1309
|
-
let { writes, restore } = recordWrites();
|
|
1310
|
-
try {
|
|
1311
|
-
hidePage();
|
|
1312
|
-
await waitForSaves(1, "hiding the page sends the save");
|
|
1313
|
-
} finally {
|
|
1314
|
-
restore();
|
|
1315
|
-
}
|
|
1316
|
-
assert.deepEqual(saves, [{
|
|
1317
|
-
url: id,
|
|
1318
|
-
name: "Paper"
|
|
1319
|
-
}]);
|
|
1320
|
-
assert.deepEqual(writes, [{
|
|
1321
|
-
url: id,
|
|
1322
|
-
keepalive: true
|
|
1323
|
-
}]);
|
|
1324
|
-
});
|
|
1325
|
-
(0, import_qunit.test)("pagehide sends pending saves as requests that outlive the page", async function(assert) {
|
|
1326
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1327
|
-
let instance = await storeService.get(id);
|
|
1328
|
-
instance.name = "Paper";
|
|
1329
|
-
let { writes, restore } = recordWrites();
|
|
1330
|
-
try {
|
|
1331
|
-
window.dispatchEvent(new PageTransitionEvent("pagehide"));
|
|
1332
|
-
await waitForSaves(1, "pagehide sends the save");
|
|
1333
|
-
await storeService.flushSaves();
|
|
1334
|
-
} finally {
|
|
1335
|
-
restore();
|
|
1336
|
-
}
|
|
1337
|
-
assert.deepEqual(saves, [{
|
|
1338
|
-
url: id,
|
|
1339
|
-
name: "Paper"
|
|
1340
|
-
}]);
|
|
1341
|
-
assert.deepEqual(writes, [{
|
|
1342
|
-
url: id,
|
|
1343
|
-
keepalive: true
|
|
1344
|
-
}]);
|
|
1345
|
-
});
|
|
1346
|
-
(0, import_qunit.test)("saves past the keepalive budget are still sent, without keepalive", async function(assert) {
|
|
1347
|
-
let ids = [`${testRealmURL}Person/hassan`, `${testRealmURL}Person/jade`];
|
|
1348
|
-
let longName = "x".repeat(4e4);
|
|
1349
|
-
for (let id of ids) {
|
|
1350
|
-
let instance = await storeService.get(id);
|
|
1351
|
-
instance.name = longName;
|
|
1352
|
-
}
|
|
1353
|
-
let { writes, restore } = recordWrites();
|
|
1354
|
-
try {
|
|
1355
|
-
window.dispatchEvent(new PageTransitionEvent("pagehide"));
|
|
1356
|
-
await waitForSaves(2, "pagehide sends both saves");
|
|
1357
|
-
await storeService.flushSaves();
|
|
1358
|
-
} finally {
|
|
1359
|
-
restore();
|
|
1360
|
-
}
|
|
1361
|
-
assert.deepEqual(saves.map((s) => s.url).sort(), [...ids].sort(), "both cards are saved");
|
|
1362
|
-
assert.deepEqual(writes.map((w) => w.keepalive).sort(), [false, true], "one save fits the budget and the other is sent as an ordinary request");
|
|
1363
|
-
});
|
|
1364
|
-
(0, import_qunit.test)("an edit after a flush gives up still waits for typing to pause", async function(assert) {
|
|
1365
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1366
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
1367
|
-
let instance = await storeService.get(id);
|
|
1368
|
-
let other = await storeService.get(jade);
|
|
1369
|
-
await withSavesHeldOpen(async (release) => {
|
|
1370
|
-
instance.name = "Paper";
|
|
1371
|
-
await storeService.flushSaves({ timeoutMs: 100 });
|
|
1372
|
-
assert.true(storeService.hasUnsavedEdits, "the held save is running");
|
|
1373
|
-
other.name = "Jade Paper";
|
|
1374
|
-
release();
|
|
1375
|
-
await waitUntil(() => saves.length === 1, { timeout: 5e3 });
|
|
1376
|
-
await pause(500);
|
|
1377
|
-
});
|
|
1378
|
-
assert.deepEqual(saves.map((s) => s.name), ["Paper"], "the later edit is not sent when the flush's save lands");
|
|
1379
|
-
await storeService.flushSaves();
|
|
1380
|
-
assert.deepEqual(saves.map((s) => s.name), ["Paper", "Jade Paper"]);
|
|
1381
|
-
});
|
|
1382
|
-
(0, import_qunit.test)("focus leaving a field sends pending saves", async function(assert) {
|
|
1383
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1384
|
-
let instance = await storeService.get(id);
|
|
1385
|
-
instance.name = "Paper";
|
|
1386
|
-
document.body.dispatchEvent(new FocusEvent("focusout", { bubbles: true }));
|
|
1387
|
-
await waitForSaves(1, "focus leaving sends the save");
|
|
1388
|
-
assert.deepEqual(saves, [{
|
|
1389
|
-
url: id,
|
|
1390
|
-
name: "Paper"
|
|
1391
|
-
}]);
|
|
1392
|
-
});
|
|
1393
|
-
(0, import_qunit.test)("closing a card in the stack sends the save its edit is waiting on", async function(assert) {
|
|
1394
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
1395
|
-
setCardInOperatorModeState(id, "edit");
|
|
1396
|
-
await renderComponent(class TestDriver extends Component {
|
|
1397
|
-
static {
|
|
1398
|
-
setComponentTemplate(templateFactory({
|
|
1399
|
-
"id": "ZD1xwmB+",
|
|
1400
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
1401
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
1402
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
1403
|
-
"isStrictMode": true
|
|
1404
|
-
}), this);
|
|
1405
|
-
}
|
|
1406
|
-
});
|
|
1407
|
-
let input = find(`[data-test-stack-card="${id}"] [data-test-field="name"] input`);
|
|
1408
|
-
input.value = "Hassan Paper";
|
|
1409
|
-
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1410
|
-
assert.strictEqual(saves.length, 0, "the edit waits to be saved");
|
|
1411
|
-
let closed = click(`[data-test-stack-card="${id}"] [data-test-close-button]`);
|
|
1412
|
-
await waitForSaves(1, "closing the card sends the save");
|
|
1413
|
-
await closed;
|
|
1414
|
-
assert.deepEqual(saves, [{
|
|
1415
|
-
url: id,
|
|
1416
|
-
name: "Hassan Paper"
|
|
1417
|
-
}]);
|
|
1418
|
-
});
|
|
1419
|
-
});
|
|
1420
|
-
(0, import_qunit.test)("can delete card from the store", async function(assert) {
|
|
1421
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
1422
|
-
await storeService.flush();
|
|
1423
|
-
let instance = storeService.peek(`${testRealmURL}Person/boris`);
|
|
1424
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
1425
|
-
assert.strictEqual(storeService.peek(instance.id), void 0, "the instance is no longer in the store");
|
|
1426
|
-
assert.strictEqual(storeService.peek(instance[localId]), void 0, "the instance is no longer in the store (via local id)");
|
|
1427
|
-
let file = await testRealmAdapter.openFile(`Person/boris.json`);
|
|
1428
|
-
assert.strictEqual(file, void 0, "file no longer exists");
|
|
1429
|
-
});
|
|
1430
|
-
(0, import_qunit.test)("subscribeToCardInvalidation fires the callback when the card is deleted", async function(assert) {
|
|
1431
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
1432
|
-
await storeService.flush();
|
|
1433
|
-
let fired = 0;
|
|
1434
|
-
let unsubscribe = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
|
|
1435
|
-
fired += 1;
|
|
1436
|
-
});
|
|
1437
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
1438
|
-
assert.strictEqual(fired, 1, "the invalidation subscriber fires exactly once on delete");
|
|
1439
|
-
unsubscribe();
|
|
1440
|
-
});
|
|
1441
|
-
(0, import_qunit.test)("subscribeToCardInvalidation unsubscribe stops firing the callback", async function(assert) {
|
|
1442
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
1443
|
-
await storeService.flush();
|
|
1444
|
-
let fired = 0;
|
|
1445
|
-
storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
|
|
1446
|
-
fired += 1;
|
|
1447
|
-
})();
|
|
1448
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
1449
|
-
assert.strictEqual(fired, 0, "no callbacks fire after unsubscribe");
|
|
1450
|
-
});
|
|
1451
|
-
(0, import_qunit.test)("a synchronously throwing invalidation subscriber does not break siblings", async function(assert) {
|
|
1452
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
1453
|
-
await storeService.flush();
|
|
1454
|
-
let originalError = console.error;
|
|
1455
|
-
let captured = [];
|
|
1456
|
-
console.error = (...args) => {
|
|
1457
|
-
if (typeof args[0] === "string" && args[0].includes("card invalidation subscriber")) captured.push(args);
|
|
1458
|
-
else originalError(...args);
|
|
1459
|
-
};
|
|
1460
|
-
let secondFired = 0;
|
|
1461
|
-
let unsubscribeA = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
|
|
1462
|
-
throw new Error("intentional sync throw from invalidation subscriber");
|
|
1463
|
-
});
|
|
1464
|
-
let unsubscribeB = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
|
|
1465
|
-
secondFired += 1;
|
|
1466
|
-
});
|
|
1467
|
-
try {
|
|
1468
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
1469
|
-
assert.strictEqual(secondFired, 1, "the second subscriber still runs after the first one throws");
|
|
1470
|
-
assert.strictEqual(captured.length, 1, "the synchronous throw is reported via console.error exactly once");
|
|
1471
|
-
} finally {
|
|
1472
|
-
unsubscribeA();
|
|
1473
|
-
unsubscribeB();
|
|
1474
|
-
console.error = originalError;
|
|
1475
|
-
}
|
|
1476
|
-
});
|
|
1477
|
-
(0, import_qunit.test)("an async-rejecting invalidation subscriber does not break siblings and does not surface as an unhandled rejection", async function(assert) {
|
|
1478
|
-
storeService.addReference(`${testRealmURL}Person/boris`);
|
|
1479
|
-
await storeService.flush();
|
|
1480
|
-
let originalError = console.error;
|
|
1481
|
-
let captured = [];
|
|
1482
|
-
console.error = (...args) => {
|
|
1483
|
-
if (typeof args[0] === "string" && args[0].includes("card invalidation subscriber")) captured.push(args);
|
|
1484
|
-
else originalError(...args);
|
|
1485
|
-
};
|
|
1486
|
-
let secondFired = 0;
|
|
1487
|
-
let unsubscribeA = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, async () => {
|
|
1488
|
-
await Promise.resolve();
|
|
1489
|
-
throw new Error("intentional async rejection from invalidation subscriber");
|
|
1490
|
-
});
|
|
1491
|
-
let unsubscribeB = storeService.subscribeToCardInvalidation(`${testRealmURL}Person/boris`, () => {
|
|
1492
|
-
secondFired += 1;
|
|
1493
|
-
});
|
|
1494
|
-
try {
|
|
1495
|
-
await storeService.delete(`${testRealmURL}Person/boris`);
|
|
1496
|
-
await settled();
|
|
1497
|
-
assert.strictEqual(secondFired, 1, "the second subscriber still runs alongside the async-rejecting one");
|
|
1498
|
-
assert.strictEqual(captured.length, 1, "the async rejection is reported via console.error exactly once");
|
|
1499
|
-
} finally {
|
|
1500
|
-
unsubscribeA();
|
|
1501
|
-
unsubscribeB();
|
|
1502
|
-
console.error = originalError;
|
|
1503
|
-
}
|
|
1504
|
-
});
|
|
1505
|
-
(0, import_qunit.test)("can patch an instance", async function(assert) {
|
|
1506
|
-
let instance = await storeService.patch(`${testRealmURL}Person/hassan`, {
|
|
1507
|
-
attributes: { name: "Hassan Updated" },
|
|
1508
|
-
relationships: {
|
|
1509
|
-
bestFriend: { links: { self: `${testRealmURL}Person/jade` } },
|
|
1510
|
-
"friends.0": { links: { self: `${testRealmURL}Person/germaine` } }
|
|
1511
|
-
}
|
|
1512
|
-
});
|
|
1513
|
-
let peekedInstance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
1514
|
-
let jade = storeService.peek(`${testRealmURL}Person/jade`);
|
|
1515
|
-
let germaine = storeService.peek(`${testRealmURL}Person/germaine`);
|
|
1516
|
-
assert.strictEqual(peekedInstance, instance, "the patched instance is in the store");
|
|
1517
|
-
assert.ok(isCardInstance(jade), "jade is in the store");
|
|
1518
|
-
assert.ok(isCardInstance(germaine), "germaine is in the store");
|
|
1519
|
-
assert.strictEqual(instance.name, "Hassan Updated", "the contains field was patched");
|
|
1520
|
-
assert.strictEqual(instance.bestFriend, jade, "the linksTo field was patched");
|
|
1521
|
-
assert.deepEqual(instance.friends, [germaine], "the linksToMany field was patched");
|
|
1522
|
-
});
|
|
1523
|
-
(0, import_qunit.test)("a patch that gives a primitive field an object replaces its value", async function(assert) {
|
|
1524
|
-
await testRealm.write("Settings/one.json", JSON.stringify({ data: {
|
|
1525
|
-
type: "card",
|
|
1526
|
-
attributes: {
|
|
1527
|
-
cardInfo: {
|
|
1528
|
-
name: "Settings",
|
|
1529
|
-
summary: "Kept"
|
|
1530
|
-
},
|
|
1531
|
-
config: {
|
|
1532
|
-
approver: "@mae:localhost",
|
|
1533
|
-
retired: true
|
|
1534
|
-
}
|
|
1535
|
-
},
|
|
1536
|
-
meta: { adoptsFrom: {
|
|
1537
|
-
module: "@cardstack/base/realm-config",
|
|
1538
|
-
name: "RealmConfig"
|
|
1539
|
-
} }
|
|
1540
|
-
} }));
|
|
1541
|
-
let id = `${testRealmURL}Settings/one`;
|
|
1542
|
-
let instance = await storeService.patch(id, { attributes: {
|
|
1543
|
-
cardInfo: { name: "Renamed" },
|
|
1544
|
-
config: { approvers: "@mae:localhost" }
|
|
1545
|
-
} });
|
|
1546
|
-
assert.deepEqual(instance.config, { approvers: "@mae:localhost" }, "the instance holds the map the patch sent");
|
|
1547
|
-
let file = await testRealmAdapter.openFile("Settings/one.json");
|
|
1548
|
-
let { attributes } = JSON.parse(file.content).data;
|
|
1549
|
-
assert.deepEqual(attributes.config, { approvers: "@mae:localhost" }, "and so does the saved file, without the renamed or dropped keys");
|
|
1550
|
-
assert.strictEqual(attributes.cardInfo.summary, "Kept", "the compound field keeps the nested value the patch leaves out");
|
|
1551
|
-
});
|
|
1552
|
-
(0, import_qunit.test)("resolving a linksTo lazily issues no save", async function(assert) {
|
|
1553
|
-
let hassanId = `${testRealmURL}Person/hassan`;
|
|
1554
|
-
await testRealm.write("Person/ghost-friend.json", JSON.stringify({ data: {
|
|
1555
|
-
attributes: { name: "Ghost" },
|
|
1556
|
-
meta: { adoptsFrom: {
|
|
1557
|
-
module: testRRI("person"),
|
|
1558
|
-
name: "Person"
|
|
1559
|
-
} }
|
|
1560
|
-
} }));
|
|
1561
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
1562
|
-
attributes: { name: "Hassan" },
|
|
1563
|
-
relationships: { bestFriend: { links: { self: `${testRealmURL}Person/ghost-friend` } } },
|
|
1564
|
-
meta: { adoptsFrom: {
|
|
1565
|
-
module: testRRI("person"),
|
|
1566
|
-
name: "Person"
|
|
1567
|
-
} }
|
|
1568
|
-
} }));
|
|
1569
|
-
let cardService = getService("card-service");
|
|
1570
|
-
let fetchJSON = cardService.fetchJSON.bind(cardService);
|
|
1571
|
-
let intercepted = 0;
|
|
1572
|
-
cardService.fetchJSON = async (url, args) => {
|
|
1573
|
-
let doc = await fetchJSON(url, args);
|
|
1574
|
-
if (String(url).replace(/\.json$/, "") === hassanId) {
|
|
1575
|
-
intercepted++;
|
|
1576
|
-
delete doc?.included;
|
|
1577
|
-
}
|
|
1578
|
-
return doc;
|
|
1579
|
-
};
|
|
1580
|
-
let saved = [];
|
|
1581
|
-
this.onSave((url) => {
|
|
1582
|
-
saved.push(url.href);
|
|
1583
|
-
});
|
|
1584
|
-
try {
|
|
1585
|
-
let instance = await storeService.get(hassanId);
|
|
1586
|
-
assert.ok(intercepted > 0, "the card fetch was intercepted");
|
|
1587
|
-
assert.strictEqual(instance.bestFriend, void 0, "the link is not loaded yet, so reading it takes the lazy path");
|
|
1588
|
-
await storeService.flush();
|
|
1589
|
-
await settled();
|
|
1590
|
-
assert.strictEqual(instance.bestFriend?.name, "Ghost", "the lazy load resolved the target and assigned it to the field");
|
|
1591
|
-
assert.deepEqual(saved, [], "no save was issued while loading");
|
|
1592
|
-
} finally {
|
|
1593
|
-
cardService.fetchJSON = fetchJSON;
|
|
1594
|
-
}
|
|
1595
|
-
});
|
|
1596
|
-
(0, import_qunit.test)("resolving a linksToMany lazily issues no save", async function(assert) {
|
|
1597
|
-
let hassanId = `${testRealmURL}Person/hassan`;
|
|
1598
|
-
await testRealm.write("Person/ghost-friend.json", JSON.stringify({ data: {
|
|
1599
|
-
attributes: { name: "Ghost" },
|
|
1600
|
-
meta: { adoptsFrom: {
|
|
1601
|
-
module: testRRI("person"),
|
|
1602
|
-
name: "Person"
|
|
1603
|
-
} }
|
|
1604
|
-
} }));
|
|
1605
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
1606
|
-
attributes: { name: "Hassan" },
|
|
1607
|
-
relationships: { "friends.0": { links: { self: `${testRealmURL}Person/ghost-friend` } } },
|
|
1608
|
-
meta: { adoptsFrom: {
|
|
1609
|
-
module: testRRI("person"),
|
|
1610
|
-
name: "Person"
|
|
1611
|
-
} }
|
|
1612
|
-
} }));
|
|
1613
|
-
let cardService = getService("card-service");
|
|
1614
|
-
let fetchJSON = cardService.fetchJSON.bind(cardService);
|
|
1615
|
-
let intercepted = 0;
|
|
1616
|
-
cardService.fetchJSON = async (url, args) => {
|
|
1617
|
-
let doc = await fetchJSON(url, args);
|
|
1618
|
-
if (String(url).replace(/\.json$/, "") === hassanId) {
|
|
1619
|
-
intercepted++;
|
|
1620
|
-
delete doc?.included;
|
|
1621
|
-
}
|
|
1622
|
-
return doc;
|
|
1623
|
-
};
|
|
1624
|
-
let saved = [];
|
|
1625
|
-
this.onSave((url) => {
|
|
1626
|
-
saved.push(url.href);
|
|
1627
|
-
});
|
|
1628
|
-
try {
|
|
1629
|
-
let instance = await storeService.get(hassanId);
|
|
1630
|
-
assert.ok(intercepted > 0, "the card fetch was intercepted");
|
|
1631
|
-
assert.deepEqual(instance.friends.map((f) => f?.name), [void 0], "the element is not loaded yet, so reading it takes the lazy path");
|
|
1632
|
-
await storeService.flush();
|
|
1633
|
-
await settled();
|
|
1634
|
-
assert.deepEqual(instance.friends.map((f) => f?.name), ["Ghost"], "the lazy load resolved the target into its slot");
|
|
1635
|
-
assert.deepEqual(saved, [], "no save was issued while loading");
|
|
1636
|
-
} finally {
|
|
1637
|
-
cardService.fetchJSON = fetchJSON;
|
|
1638
|
-
}
|
|
1639
|
-
});
|
|
1640
|
-
(0, import_qunit.test)("a concurrent field write during store.patch is not clobbered by the patch’s stale snapshot", async function(assert) {
|
|
1641
|
-
let targetId = `${testRealmURL}Person/hassan`;
|
|
1642
|
-
let instance = await storeService.get(targetId);
|
|
1643
|
-
let gate = new Deferred();
|
|
1644
|
-
let enteredGate = new Deferred();
|
|
1645
|
-
let originalLoadPatchedInstances = storeService.loadPatchedInstances;
|
|
1646
|
-
storeService.loadPatchedInstances = async function(...args) {
|
|
1647
|
-
let result = await originalLoadPatchedInstances.apply(this, args);
|
|
1648
|
-
enteredGate.fulfill();
|
|
1649
|
-
await gate.promise;
|
|
1650
|
-
return result;
|
|
1651
|
-
};
|
|
1652
|
-
try {
|
|
1653
|
-
let patchPromise = storeService.patch(targetId, { relationships: { bestFriend: { links: { self: `${testRealmURL}Person/jade` } } } });
|
|
1654
|
-
await enteredGate.promise;
|
|
1655
|
-
instance.name = "Race Winner";
|
|
1656
|
-
gate.fulfill();
|
|
1657
|
-
await patchPromise;
|
|
1658
|
-
} finally {
|
|
1659
|
-
storeService.loadPatchedInstances = originalLoadPatchedInstances;
|
|
1660
|
-
}
|
|
1661
|
-
assert.strictEqual(instance.name, "Race Winner", "the concurrent field write is not clobbered by the patch's stale snapshot");
|
|
1662
|
-
assert.strictEqual(instance.bestFriend?.id, `${testRealmURL}Person/jade`, "the patch itself was still applied");
|
|
1663
|
-
});
|
|
1664
|
-
(0, import_qunit.test)("a create gives the instance a remote identity the rest of the store can use", async function(assert) {
|
|
1665
|
-
let instance = new PersonDef({ name: "Sequence" });
|
|
1666
|
-
let instanceLocalId = instance[localId];
|
|
1667
|
-
let subscriptions = storeService.subscriptions;
|
|
1668
|
-
assert.false(subscriptions.has(testRealmURL), "the realm is not subscribed before the create");
|
|
1669
|
-
let result = await storeService.persistAndUpdate(instance);
|
|
1670
|
-
assert.true(isCardInstance(result), "the create resolved to the instance");
|
|
1671
|
-
assert.ok(instance.id?.startsWith(testRealmURL), "the instance took a remote id in the realm");
|
|
1672
|
-
assert.strictEqual(storeService.peek(instanceLocalId), instance, "the local id still resolves to this instance");
|
|
1673
|
-
assert.strictEqual(storeService.peek(instance.id), instance, "the remote id resolves to the same instance");
|
|
1674
|
-
assert.true(subscriptions.has(testRealmURL), "the store is listening for the realm's index events");
|
|
1675
|
-
let cardPath = `${instance.id.substring(testRealmURL.length)}.json`;
|
|
1676
|
-
assert.ok(await testRealmAdapter.openFile(cardPath), "the realm holds the created card");
|
|
1677
|
-
instance.name = "Sequence Edited";
|
|
1678
|
-
await waitUntil(() => storeService.getSaveState(instanceLocalId)?.lastSaved, { timeout: 1e4 });
|
|
1679
|
-
await settled();
|
|
1680
|
-
let file = await testRealmAdapter.openFile(cardPath);
|
|
1681
|
-
assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Sequence Edited", "an edit after the create autosaves to the realm");
|
|
1682
|
-
});
|
|
1683
|
-
(0, import_qunit.test)("a small new card saves even when its resident linked graph would overflow the size limit if inlined", async function(assert) {
|
|
1684
|
-
let environmentService = getService("environment-service");
|
|
1685
|
-
let originalMaxSize = environmentService.cardSizeLimitBytes;
|
|
1686
|
-
try {
|
|
1687
|
-
let bigFriend = new PersonDef({ name: "x".repeat(6e3) });
|
|
1688
|
-
let savedFriend = await storeService.persistAndUpdate(bigFriend);
|
|
1689
|
-
assert.true(isCardInstance(savedFriend), "the large linked card saved");
|
|
1690
|
-
environmentService.cardSizeLimitBytes = 2500;
|
|
1691
|
-
let instance = new PersonDef({ name: "Small" });
|
|
1692
|
-
instance.bestFriend = bigFriend;
|
|
1693
|
-
let result = await storeService.persistAndUpdate(instance);
|
|
1694
|
-
assert.true(isCardInstance(result), "a new card whose own document is under the limit saves regardless of how large a graph it links to — the check measures what the realm stores, not the tab's loaded `included`");
|
|
1695
|
-
let cardPath = `${instance.id.substring(testRealmURL.length)}.json`;
|
|
1696
|
-
assert.ok(await testRealmAdapter.openFile(cardPath), "the realm holds the created card");
|
|
1697
|
-
} finally {
|
|
1698
|
-
environmentService.cardSizeLimitBytes = originalMaxSize;
|
|
1699
|
-
}
|
|
1700
|
-
});
|
|
1701
|
-
(0, import_qunit.test)("includedScope controls which link targets the serializer builds", async function(assert) {
|
|
1702
|
-
let cardService = getService("card-service");
|
|
1703
|
-
let api = await cardService.getAPI();
|
|
1704
|
-
let saved = new PersonDef({ name: "Saved" });
|
|
1705
|
-
await storeService.persistAndUpdate(saved);
|
|
1706
|
-
let unsaved = new PersonDef({ name: "Unsaved" });
|
|
1707
|
-
let instance = new PersonDef({ name: "Consumer" });
|
|
1708
|
-
instance.bestFriend = saved;
|
|
1709
|
-
instance.friends = [unsaved];
|
|
1710
|
-
let all = api.serializeCard(instance, {
|
|
1711
|
-
useAbsoluteURL: true,
|
|
1712
|
-
includedScope: "all"
|
|
1713
|
-
});
|
|
1714
|
-
assert.ok((all.included ?? []).find((r) => r.id === saved.id), "'all' serializes saved targets into included");
|
|
1715
|
-
assert.ok((all.included ?? []).find((r) => r.lid === unsaved[localId]), "'all' serializes local targets into included");
|
|
1716
|
-
let local = api.serializeCard(instance, {
|
|
1717
|
-
useAbsoluteURL: true,
|
|
1718
|
-
includedScope: "local"
|
|
1719
|
-
});
|
|
1720
|
-
assert.notOk((local.included ?? []).find((r) => r.id === saved.id), "'local' does not serialize saved targets");
|
|
1721
|
-
assert.ok((local.included ?? []).find((r) => r.lid === unsaved[localId]), "'local' serializes local targets — the write's co-creation manifest");
|
|
1722
|
-
let none = api.serializeCard(instance, {
|
|
1723
|
-
useAbsoluteURL: true,
|
|
1724
|
-
includedScope: "none"
|
|
1725
|
-
});
|
|
1726
|
-
assert.strictEqual(none.included, void 0, "'none' builds no included at all");
|
|
1727
|
-
assert.deepEqual(local.data, all.data, "'local' leaves the primary resource identical to 'all'");
|
|
1728
|
-
assert.deepEqual(none.data, all.data, "'none' leaves the primary resource identical to 'all'");
|
|
1729
|
-
let viaCardService = await cardService.serializeCard(instance, {
|
|
1730
|
-
useAbsoluteURL: true,
|
|
1731
|
-
withLocalResourcesIncluded: true
|
|
1732
|
-
});
|
|
1733
|
-
assert.deepEqual(viaCardService, local, "withLocalResourcesIncluded serializes at the 'local' scope");
|
|
1734
|
-
});
|
|
1735
|
-
(0, import_qunit.test)("an oversized unsaved link created alongside a card still fails the size check", async function(assert) {
|
|
1736
|
-
let environmentService = getService("environment-service");
|
|
1737
|
-
let originalMaxSize = environmentService.cardSizeLimitBytes;
|
|
1738
|
-
try {
|
|
1739
|
-
environmentService.cardSizeLimitBytes = 2500;
|
|
1740
|
-
let bigUnsaved = new PersonDef({ name: "x".repeat(6e3) });
|
|
1741
|
-
let instance = new PersonDef({ name: "Small" });
|
|
1742
|
-
instance.bestFriend = bigUnsaved;
|
|
1743
|
-
let result = await storeService.persistAndUpdate(instance);
|
|
1744
|
-
assert.false(isCardInstance(result), "the save is refused: the unsaved link is co-created as its own file and is over the ceiling");
|
|
1745
|
-
assert.ok(String(result?.message).includes("exceeds maximum allowed size"), `the error names the size limit (got: ${result?.message})`);
|
|
1746
|
-
} finally {
|
|
1747
|
-
environmentService.cardSizeLimitBytes = originalMaxSize;
|
|
1748
|
-
}
|
|
1749
|
-
});
|
|
1750
|
-
(0, import_qunit.test)("a save overlapping a create PATCHes instead of issuing a second POST", async function(assert) {
|
|
1751
|
-
let instance = new PersonDef({ name: "Overlap" });
|
|
1752
|
-
await storeService.addWithoutPersisting(instance);
|
|
1753
|
-
let cardService = getService("card-service");
|
|
1754
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
1755
|
-
let methods = [];
|
|
1756
|
-
let reachedPost = new Deferred();
|
|
1757
|
-
let releasePost = new Deferred();
|
|
1758
|
-
cardService.fetchJSON = async (url, args) => {
|
|
1759
|
-
if (args?.method !== "POST" && args?.method !== "PATCH") return originalFetchJSON(url, args);
|
|
1760
|
-
methods.push(args.method);
|
|
1761
|
-
if (args.method === "POST") {
|
|
1762
|
-
reachedPost.fulfill();
|
|
1763
|
-
await releasePost.promise;
|
|
1764
|
-
}
|
|
1765
|
-
return originalFetchJSON(url, args);
|
|
1766
|
-
};
|
|
1767
|
-
try {
|
|
1768
|
-
let creating = storeService.persistAndUpdate(instance);
|
|
1769
|
-
let reachedPostFirst = await Promise.race([reachedPost.promise.then(() => true), creating.then(() => false)]);
|
|
1770
|
-
assert.true(reachedPostFirst, `the create reached its POST (resolved early as: ${JSON.stringify(await Promise.race([creating, Promise.resolve("still in flight")]))})`);
|
|
1771
|
-
let overlapping = storeService.persistAndUpdate(instance);
|
|
1772
|
-
releasePost.fulfill();
|
|
1773
|
-
await Promise.all([creating, overlapping]);
|
|
1774
|
-
} finally {
|
|
1775
|
-
releasePost.fulfill();
|
|
1776
|
-
delete cardService.fetchJSON;
|
|
1777
|
-
}
|
|
1778
|
-
await settled();
|
|
1779
|
-
assert.deepEqual(methods, ["POST", "PATCH"], "the overlapping save waited for the remote id and updated the created card");
|
|
1780
|
-
assert.ok(await testRealmAdapter.openFile(`${instance.id.substring(testRealmURL.length)}.json`), "the realm holds the created card");
|
|
1781
|
-
});
|
|
1782
|
-
function holdCreateResponse(held, opts) {
|
|
1783
|
-
let cardService = getService("card-service");
|
|
1784
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
1785
|
-
let writes = [];
|
|
1786
|
-
let stored = new Deferred();
|
|
1787
|
-
let release = new Deferred();
|
|
1788
|
-
cardService.fetchJSON = async (url, args) => {
|
|
1789
|
-
if (args?.method !== "POST" && args?.method !== "PATCH") return originalFetchJSON(url, args);
|
|
1790
|
-
let body = JSON.parse(args.body);
|
|
1791
|
-
writes.push({
|
|
1792
|
-
method: args.method,
|
|
1793
|
-
body
|
|
1794
|
-
});
|
|
1795
|
-
if (args.method !== "POST" || body.data.lid !== held[localId]) return originalFetchJSON(url, args);
|
|
1796
|
-
let response = await originalFetchJSON(url, args);
|
|
1797
|
-
stored.fulfill();
|
|
1798
|
-
await release.promise;
|
|
1799
|
-
if (opts?.fail) throw new Error("the create response never arrived");
|
|
1800
|
-
return response;
|
|
1801
|
-
};
|
|
1802
|
-
return {
|
|
1803
|
-
writes,
|
|
1804
|
-
stored: stored.promise,
|
|
1805
|
-
release: () => release.fulfill(),
|
|
1806
|
-
restore() {
|
|
1807
|
-
release.fulfill();
|
|
1808
|
-
delete cardService.fetchJSON;
|
|
1809
|
-
}
|
|
1810
|
-
};
|
|
1811
|
-
}
|
|
1812
|
-
function includedLids(body) {
|
|
1813
|
-
return (body.included ?? []).flatMap((resource) => "lid" in resource && resource.lid ? [resource.lid] : []);
|
|
1814
|
-
}
|
|
1815
|
-
(0, import_qunit.test)("a save does not send a linked card whose create is still in flight as a card to create", async function(assert) {
|
|
1816
|
-
let friend = new PersonDef({ name: "Friend" });
|
|
1817
|
-
await storeService.addWithoutPersisting(friend);
|
|
1818
|
-
let person = new PersonDef({ name: "Person" });
|
|
1819
|
-
person.bestFriend = friend;
|
|
1820
|
-
await storeService.addWithoutPersisting(person);
|
|
1821
|
-
let hold = holdCreateResponse(friend);
|
|
1822
|
-
let personResult;
|
|
1823
|
-
try {
|
|
1824
|
-
let creatingFriend = storeService.persistAndUpdate(friend);
|
|
1825
|
-
await hold.stored;
|
|
1826
|
-
let savingPerson = storeService.persistAndUpdate(person);
|
|
1827
|
-
let personSettledWhileFriendHeld = await Promise.race([savingPerson.then(() => true), new Promise((r) => setTimeout(() => r(false), 500))]);
|
|
1828
|
-
assert.false(personSettledWhileFriendHeld, "the save waits while the linked card's create is unanswered");
|
|
1829
|
-
assert.deepEqual(hold.writes.map((w) => w.method), ["POST"], "nothing but the linked card's own create went out while it was unanswered");
|
|
1830
|
-
hold.release();
|
|
1831
|
-
[, personResult] = await Promise.all([creatingFriend, savingPerson]);
|
|
1832
|
-
} finally {
|
|
1833
|
-
hold.restore();
|
|
1834
|
-
}
|
|
1835
|
-
await settled();
|
|
1836
|
-
assert.true(isCardInstance(personResult), `the save succeeded (resolved as: ${JSON.stringify(personResult)})`);
|
|
1837
|
-
let personWrite = hold.writes.find((w) => w.body.data.lid === person[localId]);
|
|
1838
|
-
assert.ok(personWrite, "the card linking to it was saved");
|
|
1839
|
-
assert.deepEqual(includedLids(personWrite.body), [], "the save carried no card to create");
|
|
1840
|
-
assert.strictEqual(personWrite.body.data.relationships?.bestFriend?.links?.self, friend.id, "the save linked to the id the realm assigned the linked card");
|
|
1841
|
-
let file = await testRealmAdapter.openFile(`${person.id.substring(testRealmURL.length)}.json`);
|
|
1842
|
-
assert.ok(file, "the realm holds the saved card");
|
|
1843
|
-
});
|
|
1844
|
-
(0, import_qunit.test)("a save started in the same turn as a linked card's create does not send that card again", async function(assert) {
|
|
1845
|
-
let friend = new PersonDef({ name: "Friend" });
|
|
1846
|
-
await storeService.addWithoutPersisting(friend);
|
|
1847
|
-
let person = new PersonDef({ name: "Person" });
|
|
1848
|
-
person.bestFriend = friend;
|
|
1849
|
-
await storeService.addWithoutPersisting(person);
|
|
1850
|
-
let hold = holdCreateResponse(friend);
|
|
1851
|
-
let results;
|
|
1852
|
-
try {
|
|
1853
|
-
let creatingFriend = storeService.persistAndUpdate(friend);
|
|
1854
|
-
let savingPerson = storeService.persistAndUpdate(person);
|
|
1855
|
-
await hold.stored;
|
|
1856
|
-
hold.release();
|
|
1857
|
-
results = await Promise.all([creatingFriend, savingPerson]);
|
|
1858
|
-
} finally {
|
|
1859
|
-
hold.restore();
|
|
1860
|
-
}
|
|
1861
|
-
await settled();
|
|
1862
|
-
assert.true(results.every((r) => isCardInstance(r)), `both saves succeeded (resolved as: ${JSON.stringify(results)})`);
|
|
1863
|
-
assert.deepEqual(hold.writes.map((w) => includedLids(w.body)), [[], []], "neither request carried a card to create besides its own");
|
|
1864
|
-
});
|
|
1865
|
-
(0, import_qunit.test)("a save still creates a linked card that was never saved alongside it", async function(assert) {
|
|
1866
|
-
let friend = new PersonDef({ name: "Friend" });
|
|
1867
|
-
let person = new PersonDef({ name: "Person" });
|
|
1868
|
-
person.bestFriend = friend;
|
|
1869
|
-
await storeService.addWithoutPersisting(person);
|
|
1870
|
-
let hold = holdCreateResponse(friend);
|
|
1871
|
-
let personResult;
|
|
1872
|
-
try {
|
|
1873
|
-
personResult = await storeService.persistAndUpdate(person);
|
|
1874
|
-
} finally {
|
|
1875
|
-
hold.restore();
|
|
1876
|
-
}
|
|
1877
|
-
await settled();
|
|
1878
|
-
assert.true(isCardInstance(personResult), `the save succeeded (resolved as: ${JSON.stringify(personResult)})`);
|
|
1879
|
-
assert.deepEqual(hold.writes.map((w) => includedLids(w.body)), [[friend[localId]]], "one request carried the unsaved linked card as a card to create");
|
|
1880
|
-
let personFile = await testRealmAdapter.openFile(`${person.id.substring(testRealmURL.length)}.json`);
|
|
1881
|
-
let friendPath = JSON.parse(personFile.content).data.relationships.bestFriend.links.self;
|
|
1882
|
-
assert.ok(await testRealmAdapter.openFile(`${new URL(friendPath, person.id).href.substring(testRealmURL.length)}.json`), "the realm holds the linked card, created with the save");
|
|
1883
|
-
});
|
|
1884
|
-
(0, import_qunit.test)("a save waiting on a linked card whose create fails does not hang", async function(assert) {
|
|
1885
|
-
let friend = new PersonDef({ name: "Friend" });
|
|
1886
|
-
await storeService.addWithoutPersisting(friend);
|
|
1887
|
-
let person = new PersonDef({ name: "Person" });
|
|
1888
|
-
person.bestFriend = friend;
|
|
1889
|
-
await storeService.addWithoutPersisting(person);
|
|
1890
|
-
let hold = holdCreateResponse(friend, { fail: true });
|
|
1891
|
-
let friendResult;
|
|
1892
|
-
let personResult;
|
|
1893
|
-
try {
|
|
1894
|
-
let creatingFriend = storeService.persistAndUpdate(friend);
|
|
1895
|
-
await hold.stored;
|
|
1896
|
-
let savingPerson = storeService.persistAndUpdate(person);
|
|
1897
|
-
let personSettledWhileFriendHeld = await Promise.race([savingPerson.then(() => true), new Promise((r) => setTimeout(() => r(false), 500))]);
|
|
1898
|
-
assert.false(personSettledWhileFriendHeld, "the save waits while the linked card's create is unanswered");
|
|
1899
|
-
assert.deepEqual(hold.writes.map((w) => w.method), ["POST"], "nothing but the linked card's own create went out while it was unanswered");
|
|
1900
|
-
hold.release();
|
|
1901
|
-
[friendResult, personResult] = await Promise.all([creatingFriend, savingPerson]);
|
|
1902
|
-
} finally {
|
|
1903
|
-
hold.restore();
|
|
1904
|
-
}
|
|
1905
|
-
await settled();
|
|
1906
|
-
assert.false(isCardInstance(friendResult), "the linked card's create reported its failure");
|
|
1907
|
-
assert.true(isCardInstance(personResult), `the save answered, linked to the already-stored card (resolved as: ${JSON.stringify(personResult)})`);
|
|
1908
|
-
assert.deepEqual(includedLids(hold.writes.find((w) => w.body.data.lid === person[localId]).body), [friend[localId]], "with no create left on the wire, the save sent the linked card as a card to create");
|
|
1909
|
-
});
|
|
1910
|
-
(0, import_qunit.test)("loads FileDef links from included resources", async function(assert) {
|
|
1911
|
-
await testRealm.writeMany(new Map([
|
|
1912
|
-
["gallery.gts", `
|
|
1913
|
-
import { CardDef, field, linksTo, linksToMany } from "@cardstack/base/card-api";
|
|
1914
|
-
import { FileDef } from "@cardstack/base/file-api";
|
|
1915
|
-
|
|
1916
|
-
export class Gallery extends CardDef {
|
|
1917
|
-
@field hero = linksTo(FileDef);
|
|
1918
|
-
@field attachments = linksToMany(FileDef);
|
|
1919
|
-
}
|
|
1920
|
-
`],
|
|
1921
|
-
["Gallery/hero.json", JSON.stringify({
|
|
1922
|
-
data: {
|
|
1923
|
-
attributes: { cardInfo: {} },
|
|
1924
|
-
relationships: {
|
|
1925
|
-
hero: {
|
|
1926
|
-
links: { self: `${testRealmURL}hero.png` },
|
|
1927
|
-
data: {
|
|
1928
|
-
type: "file-meta",
|
|
1929
|
-
id: `${testRealmURL}hero.png`
|
|
1930
|
-
}
|
|
1931
|
-
},
|
|
1932
|
-
"attachments.0": {
|
|
1933
|
-
links: { self: `${testRealmURL}first.png` },
|
|
1934
|
-
data: {
|
|
1935
|
-
type: "file-meta",
|
|
1936
|
-
id: `${testRealmURL}first.png`
|
|
1937
|
-
}
|
|
1938
|
-
},
|
|
1939
|
-
"attachments.1": {
|
|
1940
|
-
links: { self: `${testRealmURL}second.png` },
|
|
1941
|
-
data: {
|
|
1942
|
-
type: "file-meta",
|
|
1943
|
-
id: `${testRealmURL}second.png`
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
},
|
|
1947
|
-
meta: { adoptsFrom: {
|
|
1948
|
-
module: testRRI("gallery"),
|
|
1949
|
-
name: "Gallery"
|
|
1950
|
-
} }
|
|
1951
|
-
},
|
|
1952
|
-
included: [
|
|
1953
|
-
{
|
|
1954
|
-
type: "file-meta",
|
|
1955
|
-
id: `${testRealmURL}hero.png`,
|
|
1956
|
-
attributes: {
|
|
1957
|
-
name: "hero.png",
|
|
1958
|
-
url: `${testRealmURL}hero.png`,
|
|
1959
|
-
sourceUrl: `${testRealmURL}hero.png`,
|
|
1960
|
-
contentType: "image/png"
|
|
1961
|
-
},
|
|
1962
|
-
meta: { adoptsFrom: {
|
|
1963
|
-
module: "@cardstack/base/card-api",
|
|
1964
|
-
name: "FileDef"
|
|
1965
|
-
} }
|
|
1966
|
-
},
|
|
1967
|
-
{
|
|
1968
|
-
type: "file-meta",
|
|
1969
|
-
id: `${testRealmURL}first.png`,
|
|
1970
|
-
attributes: {
|
|
1971
|
-
name: "first.png",
|
|
1972
|
-
url: `${testRealmURL}first.png`,
|
|
1973
|
-
sourceUrl: `${testRealmURL}first.png`,
|
|
1974
|
-
contentType: "image/png"
|
|
1975
|
-
},
|
|
1976
|
-
meta: { adoptsFrom: {
|
|
1977
|
-
module: "@cardstack/base/card-api",
|
|
1978
|
-
name: "FileDef"
|
|
1979
|
-
} }
|
|
1980
|
-
},
|
|
1981
|
-
{
|
|
1982
|
-
type: "file-meta",
|
|
1983
|
-
id: `${testRealmURL}second.png`,
|
|
1984
|
-
attributes: {
|
|
1985
|
-
name: "second.png",
|
|
1986
|
-
url: `${testRealmURL}second.png`,
|
|
1987
|
-
sourceUrl: `${testRealmURL}second.png`,
|
|
1988
|
-
contentType: "image/png"
|
|
1989
|
-
},
|
|
1990
|
-
meta: { adoptsFrom: {
|
|
1991
|
-
module: "@cardstack/base/card-api",
|
|
1992
|
-
name: "FileDef"
|
|
1993
|
-
} }
|
|
1994
|
-
}
|
|
1995
|
-
]
|
|
1996
|
-
})],
|
|
1997
|
-
["hero.png", "mock hero image"],
|
|
1998
|
-
["first.png", "mock first image"],
|
|
1999
|
-
["second.png", "mock second image"]
|
|
2000
|
-
]));
|
|
2001
|
-
let gallery = await storeService.get(`${testRealmURL}Gallery/hero`);
|
|
2002
|
-
assert.ok(gallery.hero, "hero is loaded from included resources");
|
|
2003
|
-
assert.strictEqual(gallery.hero?.id, `${testRealmURL}hero.png`, "hero FileDef has id set from file meta");
|
|
2004
|
-
assert.strictEqual(gallery.hero?.name, "hero.png", "hero FileDef uses file meta name");
|
|
2005
|
-
assert.strictEqual(gallery.hero?.url, `${testRealmURL}hero.png`, "hero FileDef uses file meta url");
|
|
2006
|
-
let attachments = gallery.attachments ?? [];
|
|
2007
|
-
assert.strictEqual(attachments.length, 2, "attachments are loaded from included resources");
|
|
2008
|
-
assert.strictEqual(attachments[0]?.id, `${testRealmURL}first.png`, "first attachment has id set from file meta");
|
|
2009
|
-
assert.strictEqual(attachments[0]?.name, "first.png", "first attachment uses file meta name");
|
|
2010
|
-
assert.strictEqual(attachments[1]?.id, `${testRealmURL}second.png`, "second attachment has id set from file meta");
|
|
2011
|
-
assert.strictEqual(attachments[1]?.name, "second.png", "second attachment uses file meta name");
|
|
2012
|
-
});
|
|
2013
|
-
(0, import_qunit.test)("uses cached FileDef for links.self when field expects FileDef", async function(assert) {
|
|
2014
|
-
await testRealm.writeMany(new Map([
|
|
2015
|
-
["gallery.gts", `
|
|
2016
|
-
import { CardDef, field, linksTo } from "@cardstack/base/card-api";
|
|
2017
|
-
import { FileDef } from "@cardstack/base/file-api";
|
|
2018
|
-
|
|
2019
|
-
export class Gallery extends CardDef {
|
|
2020
|
-
@field hero = linksTo(FileDef);
|
|
2021
|
-
}
|
|
2022
|
-
`],
|
|
2023
|
-
["Gallery/cached.json", JSON.stringify({ data: {
|
|
2024
|
-
attributes: { cardInfo: {} },
|
|
2025
|
-
relationships: { hero: {
|
|
2026
|
-
links: { self: `${testRealmURL}hero.png` },
|
|
2027
|
-
data: {
|
|
2028
|
-
type: "file-meta",
|
|
2029
|
-
id: `${testRealmURL}hero.png`
|
|
2030
|
-
}
|
|
2031
|
-
} },
|
|
2032
|
-
meta: { adoptsFrom: {
|
|
2033
|
-
module: testRRI("gallery"),
|
|
2034
|
-
name: "Gallery"
|
|
2035
|
-
} }
|
|
2036
|
-
} })],
|
|
2037
|
-
["hero.png", "mock hero image"]
|
|
2038
|
-
]));
|
|
2039
|
-
let cachedFile = await storeService.get(`${testRealmURL}hero.png`, { type: "file-meta" });
|
|
2040
|
-
let gallery = await storeService.get(`${testRealmURL}Gallery/cached`);
|
|
2041
|
-
assert.strictEqual(gallery.hero, cachedFile, "links.self resolves to cached FileDef for FileDef fields");
|
|
2042
|
-
});
|
|
2043
|
-
(0, import_qunit.test)("can skip waiting for the save when patching an instance", async function(assert) {
|
|
2044
|
-
assert.expect(4);
|
|
2045
|
-
let targetId = `${testRealmURL}Person/hassan`;
|
|
2046
|
-
let instance = await storeService.get(targetId);
|
|
2047
|
-
let didSave = false;
|
|
2048
|
-
this.onSave((url, doc) => {
|
|
2049
|
-
if (url.href === targetId) {
|
|
2050
|
-
didSave = true;
|
|
2051
|
-
assert.strictEqual(doc.data.attributes?.name, "Hassan Updated", "patched data is persisted");
|
|
2052
|
-
}
|
|
2053
|
-
});
|
|
2054
|
-
await storeService.patch(targetId, { attributes: { name: "Hassan Updated" } }, { doNotWaitForPersist: true });
|
|
2055
|
-
assert.strictEqual(instance.name, "Hassan Updated", "local instance updated immediately");
|
|
2056
|
-
assert.false(didSave, "instance has not been persisted yet");
|
|
2057
|
-
await waitUntil(() => didSave, { timeout: 1e4 });
|
|
2058
|
-
let file = await testRealmAdapter.openFile("Person/hassan.json");
|
|
2059
|
-
assert.strictEqual(JSON.parse(file.content).data.attributes.name, "Hassan Updated", "remote document reflects patch after persistence completes");
|
|
2060
|
-
});
|
|
2061
|
-
(0, import_qunit.test)("can patch an unsaved instance", async function(assert) {
|
|
2062
|
-
let instance = new PersonDef({ name: "Andrea" });
|
|
2063
|
-
await storeService.addWithoutPersisting(instance, { realm: testRealmURL });
|
|
2064
|
-
await storeService.patch(instance[localId], {
|
|
2065
|
-
attributes: { name: "Andrea Updated" },
|
|
2066
|
-
relationships: {
|
|
2067
|
-
bestFriend: { links: { self: `${testRealmURL}Person/queenzy` } },
|
|
2068
|
-
"friends.0": { links: { self: `${testRealmURL}Person/germaine` } }
|
|
2069
|
-
}
|
|
2070
|
-
});
|
|
2071
|
-
let peekedInstance = storeService.peek(instance[localId]);
|
|
2072
|
-
let queenzy = storeService.peek(`${testRealmURL}Person/queenzy`);
|
|
2073
|
-
let germaine = storeService.peek(`${testRealmURL}Person/germaine`);
|
|
2074
|
-
assert.strictEqual(peekedInstance, instance, "the patched instance is in the store");
|
|
2075
|
-
assert.ok(isCardInstance(queenzy), "queenzy is in the store");
|
|
2076
|
-
assert.ok(isCardInstance(germaine), "germaine is in the store");
|
|
2077
|
-
assert.strictEqual(instance[realmURL]?.href, testRealmURL, "the realm config on the instance is preserved");
|
|
2078
|
-
assert.strictEqual(instance.name, "Andrea Updated", "the contains field was patched");
|
|
2079
|
-
assert.strictEqual(instance.bestFriend, queenzy, "the linksTo field was patched");
|
|
2080
|
-
assert.deepEqual(instance.friends, [germaine], "the linksToMany field was patched");
|
|
2081
|
-
await waitUntil(() => instance.id, { timeoutMessage: "waiting for instance to get assigned an id" });
|
|
2082
|
-
assert.ok(instance.id, "instance was assigned a remote id");
|
|
2083
|
-
});
|
|
2084
|
-
(0, import_qunit.test)("can skip save when patching an instance", async function(assert) {
|
|
2085
|
-
this.onSave(() => {
|
|
2086
|
-
assert.ok(false, "should not save");
|
|
2087
|
-
});
|
|
2088
|
-
let instance = await storeService.patch(`${testRealmURL}Person/hassan`, {
|
|
2089
|
-
attributes: { name: "Hassan Updated" },
|
|
2090
|
-
relationships: {
|
|
2091
|
-
bestFriend: { links: { self: `${testRealmURL}Person/jade` } },
|
|
2092
|
-
"friends.0": { links: { self: `${testRealmURL}Person/germaine` } }
|
|
2093
|
-
}
|
|
2094
|
-
}, { doNotPersist: true });
|
|
2095
|
-
let peekedInstance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
2096
|
-
let jade = storeService.peek(`${testRealmURL}Person/jade`);
|
|
2097
|
-
let germaine = storeService.peek(`${testRealmURL}Person/germaine`);
|
|
2098
|
-
assert.strictEqual(peekedInstance, instance, "the patched instance is in the store");
|
|
2099
|
-
assert.ok(isCardInstance(jade), "jade is in the store");
|
|
2100
|
-
assert.ok(isCardInstance(germaine), "germaine is in the store");
|
|
2101
|
-
assert.strictEqual(instance.name, "Hassan Updated", "the contains field was patched");
|
|
2102
|
-
assert.strictEqual(instance.bestFriend, jade, "the linksTo field was patched");
|
|
2103
|
-
assert.deepEqual(instance.friends, [germaine], "the linksToMany field was patched");
|
|
2104
|
-
});
|
|
2105
|
-
(0, import_qunit.test)("can search", async function(assert) {
|
|
2106
|
-
let results = await storeService.search({ filter: {
|
|
2107
|
-
on: {
|
|
2108
|
-
module: testRRI("person"),
|
|
2109
|
-
name: "Person"
|
|
2110
|
-
},
|
|
2111
|
-
eq: { name: "Hassan" }
|
|
2112
|
-
} }, [testRealmURL]);
|
|
2113
|
-
assert.strictEqual(results.length, 1, "the correct number of results are returned");
|
|
2114
|
-
assert.strictEqual(results[0].id, `${testRealmURL}Person/hassan`, "the result is correct");
|
|
2115
|
-
});
|
|
2116
|
-
function overrideSearchWith(doc) {
|
|
2117
|
-
registerRealmServerRoute({
|
|
2118
|
-
path: "/_federated-search",
|
|
2119
|
-
handler: async () => new Response(JSON.stringify(doc), {
|
|
2120
|
-
status: 200,
|
|
2121
|
-
headers: { "content-type": SupportedMimeType.CardJson }
|
|
2122
|
-
})
|
|
2123
|
-
});
|
|
2124
|
-
}
|
|
2125
|
-
function htmlOnlyEntryDoc(id, opts) {
|
|
2126
|
-
let htmlId = opts?.isFileMeta ? `${id}#fitted` : `${id}#fitted#${testRealmURL}person/Person`;
|
|
2127
|
-
return {
|
|
2128
|
-
data: [{
|
|
2129
|
-
type: "entry",
|
|
2130
|
-
id,
|
|
2131
|
-
relationships: { html: { data: [{
|
|
2132
|
-
type: "html",
|
|
2133
|
-
id: htmlId
|
|
2134
|
-
}] } }
|
|
2135
|
-
}],
|
|
2136
|
-
included: [{
|
|
2137
|
-
type: "html",
|
|
2138
|
-
id: htmlId,
|
|
2139
|
-
attributes: {
|
|
2140
|
-
html: "<div>prerendered</div>",
|
|
2141
|
-
cardType: "Person",
|
|
2142
|
-
format: "fitted"
|
|
2143
|
-
},
|
|
2144
|
-
relationships: { styles: { data: [] } }
|
|
2145
|
-
}],
|
|
2146
|
-
meta: { page: { total: 1 } }
|
|
2147
|
-
};
|
|
2148
|
-
}
|
|
2149
|
-
let personQuery = { filter: {
|
|
2150
|
-
on: {
|
|
2151
|
-
module: testRRI("person"),
|
|
2152
|
-
name: "Person"
|
|
2153
|
-
},
|
|
2154
|
-
eq: { name: "Hassan" }
|
|
2155
|
-
} };
|
|
2156
|
-
(0, import_qunit.test)("a search result with no item serialization is not deposited into the Store", async function(assert) {
|
|
2157
|
-
let id = `${testRealmURL}Person/html-only`;
|
|
2158
|
-
overrideSearchWith(htmlOnlyEntryDoc(id));
|
|
2159
|
-
try {
|
|
2160
|
-
let results = await storeService.search(personQuery, [testRealmURL]);
|
|
2161
|
-
assert.strictEqual(results.length, 0, "the html-only entry is not returned as a hydrated instance");
|
|
2162
|
-
assert.notOk(isCardInstance(storeService.peek(id)), "the html-only entry is not deposited in the Store");
|
|
2163
|
-
} finally {
|
|
2164
|
-
registerDefaultRoutes();
|
|
2165
|
-
}
|
|
2166
|
-
});
|
|
2167
|
-
(0, import_qunit.test)("a search result with no item serialization leaves a resident full instance untouched", async function(assert) {
|
|
2168
|
-
let id = `${testRealmURL}Person/hassan`;
|
|
2169
|
-
storeService.addReference(id);
|
|
2170
|
-
await storeService.flush();
|
|
2171
|
-
let before = storeService.peek(id);
|
|
2172
|
-
assert.true(isCardInstance(before), "the full instance is resident before the search");
|
|
2173
|
-
overrideSearchWith(htmlOnlyEntryDoc(id));
|
|
2174
|
-
try {
|
|
2175
|
-
let results = await storeService.search(personQuery, [testRealmURL]);
|
|
2176
|
-
assert.strictEqual(results.length, 0, "an entry with no serialization contributes no instance");
|
|
2177
|
-
let after = storeService.peek(id);
|
|
2178
|
-
assert.strictEqual(after, before, "the html-only entry left the resident full instance untouched");
|
|
2179
|
-
assert.true(isCardInstance(after), "still a full card instance");
|
|
2180
|
-
} finally {
|
|
2181
|
-
registerDefaultRoutes();
|
|
2182
|
-
}
|
|
2183
|
-
});
|
|
2184
|
-
(0, import_qunit.test)("a file-meta search result with no item serialization leaves a resident FileDef untouched", async function(assert) {
|
|
2185
|
-
await testRealm.write("hero.png", "mock hero image");
|
|
2186
|
-
let fileUrl = `${testRealmURL}hero.png`;
|
|
2187
|
-
let before = await storeService.get(fileUrl, { type: "file-meta" });
|
|
2188
|
-
storeService.addReference(fileUrl, { type: "file-meta" });
|
|
2189
|
-
assert.true(before?.constructor?.isFileDef, "the live FileDef is resident before the search");
|
|
2190
|
-
overrideSearchWith(htmlOnlyEntryDoc(fileUrl, { isFileMeta: true }));
|
|
2191
|
-
try {
|
|
2192
|
-
let results = await storeService.search(personQuery, [testRealmURL]);
|
|
2193
|
-
assert.strictEqual(results.length, 0, "an entry with no serialization contributes no instance");
|
|
2194
|
-
assert.true(storeService.peek(fileUrl, { type: "file-meta" })?.constructor?.isFileDef, "the resident live FileDef is untouched");
|
|
2195
|
-
assert.ok(Object.is(storeService.peek(fileUrl, { type: "file-meta" }), before), "still the same resident FileDef");
|
|
2196
|
-
} finally {
|
|
2197
|
-
storeService.dropReference(fileUrl);
|
|
2198
|
-
registerDefaultRoutes();
|
|
2199
|
-
}
|
|
2200
|
-
});
|
|
2201
|
-
(0, import_qunit.test)("an instance live updates from indexing events for an instance update", async function(assert) {
|
|
2202
|
-
assert.expect(2);
|
|
2203
|
-
let url = `${testRealmURL}Person/hassan`;
|
|
2204
|
-
let didSave = false;
|
|
2205
|
-
this.onSave(() => {
|
|
2206
|
-
didSave = true;
|
|
2207
|
-
});
|
|
2208
|
-
setCardInOperatorModeState(url);
|
|
2209
|
-
await renderComponent(class TestDriver extends Component {
|
|
2210
|
-
static {
|
|
2211
|
-
setComponentTemplate(templateFactory({
|
|
2212
|
-
"id": "ZD1xwmB+",
|
|
2213
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2214
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2215
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2216
|
-
"isStrictMode": true
|
|
2217
|
-
}), this);
|
|
2218
|
-
}
|
|
2219
|
-
});
|
|
2220
|
-
let events = interceptRealmEvents();
|
|
2221
|
-
try {
|
|
2222
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
2223
|
-
attributes: { name: "Hassan updated" },
|
|
2224
|
-
meta: { adoptsFrom: {
|
|
2225
|
-
module: testRRI("person"),
|
|
2226
|
-
name: "Person"
|
|
2227
|
-
} }
|
|
2228
|
-
} }));
|
|
2229
|
-
let event = await events.nextEventFor(url);
|
|
2230
|
-
events.deliver(event);
|
|
2231
|
-
await settled();
|
|
2232
|
-
} finally {
|
|
2233
|
-
events.restore();
|
|
2234
|
-
}
|
|
2235
|
-
await storeService.flushSaves();
|
|
2236
|
-
assert.dom("[data-test-stack-card] [data-test-field=\"name\"]").containsText("Hassan updated", "card live updated");
|
|
2237
|
-
assert.false(didSave, "indexing updates do not auto save instances");
|
|
2238
|
-
});
|
|
2239
|
-
(0, import_qunit.test)("an instance live updates from indexing events for a code update", async function(assert) {
|
|
2240
|
-
setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
|
|
2241
|
-
await renderComponent(class TestDriver extends Component {
|
|
2242
|
-
static {
|
|
2243
|
-
setComponentTemplate(templateFactory({
|
|
2244
|
-
"id": "ZD1xwmB+",
|
|
2245
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2246
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2247
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2248
|
-
"isStrictMode": true
|
|
2249
|
-
}), this);
|
|
2250
|
-
}
|
|
2251
|
-
});
|
|
2252
|
-
let instance = await storeService.get(`${testRealmURL}Person/hassan`);
|
|
2253
|
-
await testRealm.write(`person.gts`, `
|
|
2254
|
-
import { contains, field, Component, CardDef, } from '@cardstack/base/card-api';
|
|
2255
|
-
import StringField from '@cardstack/base/string';
|
|
2256
|
-
|
|
2257
|
-
export class Person extends CardDef {
|
|
2258
|
-
@field name = contains(StringField);
|
|
2259
|
-
static isolated = class Isolated extends Component<typeof this> {
|
|
2260
|
-
<template>
|
|
2261
|
-
<div test-update>Hello</div>
|
|
2262
|
-
<@fields.firstName />
|
|
2263
|
-
</template>
|
|
2264
|
-
};
|
|
2265
|
-
}`.trim());
|
|
2266
|
-
await waitFor("[test-update]", { timeout: 5e3 });
|
|
2267
|
-
assert.dom("[test-update]").containsText("Hello", "the instance rendered with the new code");
|
|
2268
|
-
let newInstance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
2269
|
-
assert.notStrictEqual(instance[localId], newInstance[localId], "the updated instance is a different object than the original instance");
|
|
2270
|
-
});
|
|
2271
|
-
(0, import_qunit.test)("an instance live updates to a new type when its adoptsFrom changes", async function(assert) {
|
|
2272
|
-
setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
|
|
2273
|
-
await renderComponent(class TestDriver extends Component {
|
|
2274
|
-
static {
|
|
2275
|
-
setComponentTemplate(templateFactory({
|
|
2276
|
-
"id": "ZD1xwmB+",
|
|
2277
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2278
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2279
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2280
|
-
"isStrictMode": true
|
|
2281
|
-
}), this);
|
|
2282
|
-
}
|
|
2283
|
-
});
|
|
2284
|
-
let original = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
2285
|
-
assert.true(original instanceof PersonDef, "the card starts out as a Person");
|
|
2286
|
-
assert.dom("[data-test-employee-badge]").doesNotExist();
|
|
2287
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
2288
|
-
attributes: { name: "Hassan" },
|
|
2289
|
-
meta: { adoptsFrom: {
|
|
2290
|
-
module: testRRI("employee"),
|
|
2291
|
-
name: "Employee"
|
|
2292
|
-
} }
|
|
2293
|
-
} }));
|
|
2294
|
-
await waitUntil(() => storeService.peek(`${testRealmURL}Person/hassan`) instanceof EmployeeDef, { timeout: 5e3 });
|
|
2295
|
-
let reloaded = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
2296
|
-
assert.true(reloaded instanceof EmployeeDef, "the store now holds an Employee instance for the same id");
|
|
2297
|
-
await waitFor("[data-test-employee-badge]", { timeout: 5e3 });
|
|
2298
|
-
assert.dom("[data-test-employee-badge]").containsText("Employee: Hassan", "the card re-rendered using the new type");
|
|
2299
|
-
});
|
|
2300
|
-
(0, import_qunit.test)("an instance rebuilds when its adoptsFrom changes to an ancestor type", async function(assert) {
|
|
2301
|
-
await testRealm.write("Manager/m1.json", JSON.stringify({ data: {
|
|
2302
|
-
attributes: { name: "Hassan" },
|
|
2303
|
-
meta: { adoptsFrom: {
|
|
2304
|
-
module: testRRI("manager"),
|
|
2305
|
-
name: "Manager"
|
|
2306
|
-
} }
|
|
2307
|
-
} }));
|
|
2308
|
-
setCardInOperatorModeState(`${testRealmURL}Manager/m1`);
|
|
2309
|
-
await renderComponent(class TestDriver extends Component {
|
|
2310
|
-
static {
|
|
2311
|
-
setComponentTemplate(templateFactory({
|
|
2312
|
-
"id": "ZD1xwmB+",
|
|
2313
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2314
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2315
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2316
|
-
"isStrictMode": true
|
|
2317
|
-
}), this);
|
|
2318
|
-
}
|
|
2319
|
-
});
|
|
2320
|
-
await waitFor("[data-test-manager-badge]");
|
|
2321
|
-
let original = storeService.peek(`${testRealmURL}Manager/m1`);
|
|
2322
|
-
assert.true(original instanceof ManagerDef, "the card starts as a Manager");
|
|
2323
|
-
await testRealm.write("Manager/m1.json", JSON.stringify({ data: {
|
|
2324
|
-
attributes: { name: "Hassan" },
|
|
2325
|
-
meta: { adoptsFrom: {
|
|
2326
|
-
module: testRRI("employee"),
|
|
2327
|
-
name: "Employee"
|
|
2328
|
-
} }
|
|
2329
|
-
} }));
|
|
2330
|
-
await waitUntil(() => {
|
|
2331
|
-
let c = storeService.peek(`${testRealmURL}Manager/m1`);
|
|
2332
|
-
return c instanceof EmployeeDef && !(c instanceof ManagerDef);
|
|
2333
|
-
}, { timeout: 5e3 });
|
|
2334
|
-
await waitFor("[data-test-employee-badge]", { timeout: 5e3 });
|
|
2335
|
-
assert.dom("[data-test-employee-badge]").containsText("Employee: Hassan", "rebuilt as the ancestor type");
|
|
2336
|
-
assert.dom("[data-test-manager-badge]").doesNotExist("no longer rendered as the Manager subclass");
|
|
2337
|
-
});
|
|
2338
|
-
(0, import_qunit.test)("an instance can live update thru an error state", async function(assert) {
|
|
2339
|
-
setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
|
|
2340
|
-
await renderComponent(class TestDriver extends Component {
|
|
2341
|
-
static {
|
|
2342
|
-
setComponentTemplate(templateFactory({
|
|
2343
|
-
"id": "ZD1xwmB+",
|
|
2344
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2345
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2346
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2347
|
-
"isStrictMode": true
|
|
2348
|
-
}), this);
|
|
2349
|
-
}
|
|
2350
|
-
});
|
|
2351
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
2352
|
-
attributes: {
|
|
2353
|
-
name: "Hassan",
|
|
2354
|
-
hasError: true
|
|
2355
|
-
},
|
|
2356
|
-
meta: { adoptsFrom: {
|
|
2357
|
-
module: testRRI("person"),
|
|
2358
|
-
name: "Person"
|
|
2359
|
-
} }
|
|
2360
|
-
} }));
|
|
2361
|
-
await settled();
|
|
2362
|
-
assert.dom("[data-test-card-error]").exists("the card error is shown");
|
|
2363
|
-
assert.dom("[data-test-error-message]").containsText("intentional error thrown");
|
|
2364
|
-
await click("[data-test-toggle-details]");
|
|
2365
|
-
assert.dom("[data-test-error-details]").includesText("Stack trace: Error: Encountered error rendering HTML");
|
|
2366
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
2367
|
-
attributes: {
|
|
2368
|
-
name: "Hassan",
|
|
2369
|
-
hasError: false
|
|
2370
|
-
},
|
|
2371
|
-
meta: { adoptsFrom: {
|
|
2372
|
-
module: testRRI("person"),
|
|
2373
|
-
name: "Person"
|
|
2374
|
-
} }
|
|
2375
|
-
} }));
|
|
2376
|
-
await settled();
|
|
2377
|
-
assert.dom("[data-test-card-error]").doesNotExist("the error is dismissed");
|
|
2378
|
-
assert.dom("[data-test-stack-card] [data-test-field=\"name\"]").containsText("Hassan", "card is still rendered");
|
|
2379
|
-
});
|
|
2380
|
-
(0, import_qunit.test)("a card the realm has not indexed renders from its source, with its computed fields, and takes the indexed state once indexing lands", async function(assert) {
|
|
2381
|
-
let url = `${testRealmURL}Person/unindexed`;
|
|
2382
|
-
await testRealmAdapter.write("Person/unindexed.json", JSON.stringify({ data: {
|
|
2383
|
-
attributes: { name: "Unindexed" },
|
|
2384
|
-
meta: { adoptsFrom: {
|
|
2385
|
-
module: testRRI("person"),
|
|
2386
|
-
name: "Person"
|
|
2387
|
-
} }
|
|
2388
|
-
} }));
|
|
2389
|
-
setCardInOperatorModeState(url);
|
|
2390
|
-
await renderComponent(class TestDriver extends Component {
|
|
2391
|
-
static {
|
|
2392
|
-
setComponentTemplate(templateFactory({
|
|
2393
|
-
"id": "ZD1xwmB+",
|
|
2394
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2395
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2396
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2397
|
-
"isStrictMode": true
|
|
2398
|
-
}), this);
|
|
2399
|
-
}
|
|
2400
|
-
});
|
|
2401
|
-
await settleCardRender(assert, url, `[data-stack-card="${url}"] [data-test-field="name"]`);
|
|
2402
|
-
assert.dom("[data-test-card-awaiting-index]").doesNotExist("no placeholder stands in for a card whose source is there");
|
|
2403
|
-
assert.dom(`[data-stack-card="${url}"] [data-test-field="name"]`).containsText("Unindexed", "the card renders from its source");
|
|
2404
|
-
let instance = storeService.peek(url);
|
|
2405
|
-
assert.true(isCardInstance(instance), "the store holds a running card");
|
|
2406
|
-
assert.strictEqual(instance.boom, "boom", "its computed field evaluates in the tab");
|
|
2407
|
-
await writePerson("Person/unindexed.json", "Indexed Person");
|
|
2408
|
-
await settled();
|
|
2409
|
-
assert.dom(`[data-stack-card="${url}"] [data-test-field="name"]`).containsText("Indexed Person", "the index event brings the indexed state");
|
|
2410
|
-
assert.strictEqual(storeService.peek(url), instance, "into the same instance, so nothing the user holds is swapped out");
|
|
2411
|
-
});
|
|
2412
|
-
(0, import_qunit.test)("a full reindex re-reads a card built from its source in place", async function(assert) {
|
|
2413
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
2414
|
-
await storeService.flush();
|
|
2415
|
-
let url = `${testRealmURL}Person/from-source`;
|
|
2416
|
-
await testRealmAdapter.write("Person/from-source.json", JSON.stringify({ data: {
|
|
2417
|
-
attributes: { name: "From Source" },
|
|
2418
|
-
meta: { adoptsFrom: {
|
|
2419
|
-
module: testRRI("person"),
|
|
2420
|
-
name: "Person"
|
|
2421
|
-
} }
|
|
2422
|
-
} }));
|
|
2423
|
-
let instance = await storeService.get(url);
|
|
2424
|
-
assert.true(isCardInstance(instance), "the read returns a running card rather than a placeholder");
|
|
2425
|
-
assert.strictEqual(storeService.peekError(url), void 0, "and records no error for it");
|
|
2426
|
-
let events = interceptRealmEvents();
|
|
2427
|
-
try {
|
|
2428
|
-
await writePerson("Person/from-source.json", "From Source Indexed");
|
|
2429
|
-
events.deliver({
|
|
2430
|
-
eventName: "index",
|
|
2431
|
-
indexType: "full",
|
|
2432
|
-
realmURL: testRealmURL
|
|
2433
|
-
});
|
|
2434
|
-
await settled();
|
|
2435
|
-
} finally {
|
|
2436
|
-
events.restore();
|
|
2437
|
-
}
|
|
2438
|
-
assert.strictEqual(storeService.peek(url), instance, "the same instance is still the one the store hands out");
|
|
2439
|
-
assert.strictEqual(instance.name, "From Source Indexed", "and it now holds the indexed state");
|
|
2440
|
-
});
|
|
2441
|
-
(0, import_qunit.test)("a read that reports the index state answers awaiting-index without changing what other reads of the card get", async function(assert) {
|
|
2442
|
-
async function writeUnindexed(path, name) {
|
|
2443
|
-
await testRealmAdapter.write(path, JSON.stringify({ data: {
|
|
2444
|
-
attributes: { name },
|
|
2445
|
-
meta: { adoptsFrom: {
|
|
2446
|
-
module: testRRI("person"),
|
|
2447
|
-
name: "Person"
|
|
2448
|
-
} }
|
|
2449
|
-
} }));
|
|
2450
|
-
}
|
|
2451
|
-
let readFirst = `${testRealmURL}Person/report-first`;
|
|
2452
|
-
await writeUnindexed("Person/report-first.json", "Report First");
|
|
2453
|
-
let reported = await storeService.getWithoutCache(readFirst);
|
|
2454
|
-
assert.true(reported.awaitingIndex, "the index-state read reports the card as awaiting index");
|
|
2455
|
-
assert.strictEqual(storeService.peekError(readFirst), void 0, "and records nothing in the store");
|
|
2456
|
-
assert.true(isCardInstance(await storeService.get(readFirst)), "so opening the card afterwards still builds it from its source");
|
|
2457
|
-
let openedFirst = `${testRealmURL}Person/opened-first`;
|
|
2458
|
-
await writeUnindexed("Person/opened-first.json", "Opened First");
|
|
2459
|
-
let opened = await storeService.get(openedFirst);
|
|
2460
|
-
assert.true(isCardInstance(opened), "the opened card is running");
|
|
2461
|
-
reported = await storeService.getWithoutCache(openedFirst);
|
|
2462
|
-
assert.true(reported.awaitingIndex, "the index-state read is not handed the card built from source");
|
|
2463
|
-
assert.strictEqual(storeService.peek(openedFirst), opened, "and the running card stays in place");
|
|
2464
|
-
let concurrent = `${testRealmURL}Person/concurrent`;
|
|
2465
|
-
await writeUnindexed("Person/concurrent.json", "Concurrent");
|
|
2466
|
-
let [got, reportedConcurrently] = await Promise.all([storeService.get(concurrent), storeService.getWithoutCache(concurrent)]);
|
|
2467
|
-
assert.true(isCardInstance(got), "the plain read gets the card");
|
|
2468
|
-
assert.true(reportedConcurrently.awaitingIndex, "the index-state read gets the awaiting-index answer");
|
|
2469
|
-
});
|
|
2470
|
-
(0, import_qunit.test)("a read that reports the index state is not handed a card still being built from its source", async function(assert) {
|
|
2471
|
-
let url = `${testRealmURL}Person/half-built`;
|
|
2472
|
-
await testRealmAdapter.write("Person/half-built.json", JSON.stringify({ data: {
|
|
2473
|
-
attributes: { name: "Half Built" },
|
|
2474
|
-
meta: { adoptsFrom: {
|
|
2475
|
-
module: testRRI("person"),
|
|
2476
|
-
name: "Person"
|
|
2477
|
-
} }
|
|
2478
|
-
} }));
|
|
2479
|
-
let reachedBuilt = new Deferred();
|
|
2480
|
-
let releaseBuilt = new Deferred();
|
|
2481
|
-
let service = storeService;
|
|
2482
|
-
let createFromSerialized = service.createFromSerialized.bind(service);
|
|
2483
|
-
service.createFromSerialized = async (resource, ...rest) => {
|
|
2484
|
-
let instance = await createFromSerialized(resource, ...rest);
|
|
2485
|
-
if (String(resource?.id ?? "").includes("Person/half-built")) {
|
|
2486
|
-
reachedBuilt.fulfill();
|
|
2487
|
-
await releaseBuilt.promise;
|
|
2488
|
-
}
|
|
2489
|
-
return instance;
|
|
2490
|
-
};
|
|
2491
|
-
let reported;
|
|
2492
|
-
let opening;
|
|
2493
|
-
try {
|
|
2494
|
-
opening = storeService.get(url);
|
|
2495
|
-
await reachedBuilt.promise;
|
|
2496
|
-
assert.true(isCardInstance(storeService.peek(url)), "the card being built is already in the identity map");
|
|
2497
|
-
reported = await storeService.getWithoutCache(url);
|
|
2498
|
-
} finally {
|
|
2499
|
-
releaseBuilt.fulfill();
|
|
2500
|
-
delete service.createFromSerialized;
|
|
2501
|
-
}
|
|
2502
|
-
assert.true(reported?.awaitingIndex, "the index-state read gets the awaiting-index answer, not the card being built");
|
|
2503
|
-
assert.true(isCardInstance(await opening), "and the read that was building the card still gets it");
|
|
2504
|
-
});
|
|
2505
|
-
(0, import_qunit.test)("an index event that lands while a card is being built from its source re-reads it once it is built", async function(assert) {
|
|
2506
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
2507
|
-
await storeService.flush();
|
|
2508
|
-
let url = `${testRealmURL}Person/source-racing`;
|
|
2509
|
-
await testRealmAdapter.write("Person/source-racing.json", JSON.stringify({ data: {
|
|
2510
|
-
attributes: { name: "Source Racing" },
|
|
2511
|
-
meta: { adoptsFrom: {
|
|
2512
|
-
module: testRRI("person"),
|
|
2513
|
-
name: "Person"
|
|
2514
|
-
} }
|
|
2515
|
-
} }));
|
|
2516
|
-
let reachedSource = new Deferred();
|
|
2517
|
-
let releaseSource = new Deferred();
|
|
2518
|
-
let loadCardDocument = cardStore.loadCardDocument.bind(cardStore);
|
|
2519
|
-
cardStore.loadCardDocument = async (sourceURL, opts) => {
|
|
2520
|
-
let doc = await loadCardDocument(sourceURL, opts);
|
|
2521
|
-
if (sourceURL.includes("Person/source-racing")) {
|
|
2522
|
-
reachedSource.fulfill();
|
|
2523
|
-
await releaseSource.promise;
|
|
2524
|
-
}
|
|
2525
|
-
return doc;
|
|
2526
|
-
};
|
|
2527
|
-
let events = interceptRealmEvents();
|
|
2528
|
-
try {
|
|
2529
|
-
let reading = storeService.get(url);
|
|
2530
|
-
await reachedSource.promise;
|
|
2531
|
-
await writePerson("Person/source-racing.json", "Source Racing Person");
|
|
2532
|
-
events.deliver({
|
|
2533
|
-
eventName: "index",
|
|
2534
|
-
indexType: "incremental",
|
|
2535
|
-
invalidations: [url],
|
|
2536
|
-
realmURL: testRealmURL
|
|
2537
|
-
});
|
|
2538
|
-
releaseSource.fulfill();
|
|
2539
|
-
await reading;
|
|
2540
|
-
await settled();
|
|
2541
|
-
} finally {
|
|
2542
|
-
releaseSource.fulfill();
|
|
2543
|
-
delete cardStore.loadCardDocument;
|
|
2544
|
-
events.restore();
|
|
2545
|
-
}
|
|
2546
|
-
assert.strictEqual(storeService.peek(url)?.name, "Source Racing Person", "the store re-reads the card rather than keeping the source it read before the write");
|
|
2547
|
-
});
|
|
2548
|
-
(0, import_qunit.test)("a card the realm has not indexed and whose source cannot be read shows as being prepared, then renders once indexing lands", async function(assert) {
|
|
2549
|
-
withholdSource("Person/pending");
|
|
2550
|
-
await testRealmAdapter.write("Person/pending.json", JSON.stringify({ data: {
|
|
2551
|
-
attributes: { name: "Pending" },
|
|
2552
|
-
meta: { adoptsFrom: {
|
|
2553
|
-
module: testRRI("person"),
|
|
2554
|
-
name: "Person"
|
|
2555
|
-
} }
|
|
2556
|
-
} }));
|
|
2557
|
-
setCardInOperatorModeState(`${testRealmURL}Person/pending`);
|
|
2558
|
-
await renderComponent(class TestDriver extends Component {
|
|
2559
|
-
static {
|
|
2560
|
-
setComponentTemplate(templateFactory({
|
|
2561
|
-
"id": "ZD1xwmB+",
|
|
2562
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
2563
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
2564
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
2565
|
-
"isStrictMode": true
|
|
2566
|
-
}), this);
|
|
2567
|
-
}
|
|
2568
|
-
});
|
|
2569
|
-
await waitFor("[data-test-card-awaiting-index]");
|
|
2570
|
-
assert.dom("[data-test-card-awaiting-index]").containsText("Preparing this card", "the card reads as on its way rather than missing");
|
|
2571
|
-
assert.dom("[data-test-card-error]").doesNotExist("no card error is reported");
|
|
2572
|
-
await testRealm.write("Person/pending.json", JSON.stringify({ data: {
|
|
2573
|
-
attributes: { name: "Pending Person" },
|
|
2574
|
-
meta: { adoptsFrom: {
|
|
2575
|
-
module: testRRI("person"),
|
|
2576
|
-
name: "Person"
|
|
2577
|
-
} }
|
|
2578
|
-
} }));
|
|
2579
|
-
await settled();
|
|
2580
|
-
let id = `${testRealmURL}Person/pending`;
|
|
2581
|
-
if (document.querySelector("[data-test-card-awaiting-index]")) {
|
|
2582
|
-
let realmEvents = mockMatrixUtils.getRoomIds().flatMap((roomId) => mockMatrixUtils.getRoomEvents(roomId)).filter((event) => event.type === APP_BOXEL_REALM_EVENT_TYPE).sort((a, b) => a.origin_server_ts - b.origin_server_ts).slice(-5).map((event) => event.content);
|
|
2583
|
-
console.warn(`[awaiting-index-placeholder flake-probe] placeholder still shown after settled(). store error=${JSON.stringify(storeService.peekError(id) ?? null)}; store holds instance=${isCardInstance(storeService.peek(id))}; last realm events in mock homeserver=${JSON.stringify(realmEvents)}.`);
|
|
2584
|
-
}
|
|
2585
|
-
assert.dom("[data-test-card-awaiting-index]").doesNotExist("the placeholder is gone once the card is indexed");
|
|
2586
|
-
assert.dom(`[data-stack-card="${testRealmURL}Person/pending"] [data-test-field="name"]`).containsText("Pending Person", "the real card takes over once it is indexed");
|
|
2587
|
-
});
|
|
2588
|
-
(0, import_qunit.test)("an index event that lands while the first read is in flight still resolves the placeholder", async function(assert) {
|
|
2589
|
-
withholdSource("Person/racing");
|
|
2590
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
2591
|
-
await storeService.flush();
|
|
2592
|
-
await testRealmAdapter.write("Person/racing.json", JSON.stringify({ data: {
|
|
2593
|
-
attributes: { name: "Racing" },
|
|
2594
|
-
meta: { adoptsFrom: {
|
|
2595
|
-
module: testRRI("person"),
|
|
2596
|
-
name: "Person"
|
|
2597
|
-
} }
|
|
2598
|
-
} }));
|
|
2599
|
-
let cardService = getService("card-service");
|
|
2600
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
2601
|
-
let reached404 = new Deferred();
|
|
2602
|
-
let release404 = new Deferred();
|
|
2603
|
-
cardService.fetchJSON = async (url, args) => {
|
|
2604
|
-
if (!String(url).includes("Person/racing")) return originalFetchJSON(url, args);
|
|
2605
|
-
try {
|
|
2606
|
-
return await originalFetchJSON(url, args);
|
|
2607
|
-
} catch (err) {
|
|
2608
|
-
reached404.fulfill();
|
|
2609
|
-
await release404.promise;
|
|
2610
|
-
throw err;
|
|
2611
|
-
}
|
|
2612
|
-
};
|
|
2613
|
-
let messageService = getService("message-service");
|
|
2614
|
-
let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
|
|
2615
|
-
messageService.relayRealmEvent = () => {};
|
|
2616
|
-
try {
|
|
2617
|
-
let reading = storeService.get(`${testRealmURL}Person/racing`);
|
|
2618
|
-
await reached404.promise;
|
|
2619
|
-
await testRealm.write("Person/racing.json", JSON.stringify({ data: {
|
|
2620
|
-
attributes: { name: "Racing Person" },
|
|
2621
|
-
meta: { adoptsFrom: {
|
|
2622
|
-
module: testRRI("person"),
|
|
2623
|
-
name: "Person"
|
|
2624
|
-
} }
|
|
2625
|
-
} }));
|
|
2626
|
-
deliverRealmEvents({
|
|
2627
|
-
eventName: "index",
|
|
2628
|
-
indexType: "incremental",
|
|
2629
|
-
invalidations: [`${testRealmURL}Person/racing`],
|
|
2630
|
-
realmURL: testRealmURL
|
|
2631
|
-
});
|
|
2632
|
-
release404.fulfill();
|
|
2633
|
-
await reading;
|
|
2634
|
-
await settled();
|
|
2635
|
-
} finally {
|
|
2636
|
-
release404.fulfill();
|
|
2637
|
-
delete cardService.fetchJSON;
|
|
2638
|
-
messageService.relayRealmEvent = deliverRealmEvents;
|
|
2639
|
-
}
|
|
2640
|
-
let instance = storeService.peek(`${testRealmURL}Person/racing`);
|
|
2641
|
-
assert.true(isCardInstance(instance), "the store holds the card rather than the stale placeholder");
|
|
2642
|
-
assert.strictEqual(instance.name, "Racing Person", "and it is the indexed state");
|
|
2643
|
-
});
|
|
2644
|
-
(0, import_qunit.test)("a full reindex resolves a placeholder even though it names no cards", async function(assert) {
|
|
2645
|
-
withholdSource("Person/swept");
|
|
2646
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
2647
|
-
await storeService.flush();
|
|
2648
|
-
await testRealmAdapter.write("Person/swept.json", JSON.stringify({ data: {
|
|
2649
|
-
attributes: { name: "Swept" },
|
|
2650
|
-
meta: { adoptsFrom: {
|
|
2651
|
-
module: testRRI("person"),
|
|
2652
|
-
name: "Person"
|
|
2653
|
-
} }
|
|
2654
|
-
} }));
|
|
2655
|
-
let placeholder = await storeService.get(`${testRealmURL}Person/swept`);
|
|
2656
|
-
assert.true(placeholder.awaitingIndex, "the read leaves an awaiting-index placeholder");
|
|
2657
|
-
let messageService = getService("message-service");
|
|
2658
|
-
let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
|
|
2659
|
-
messageService.relayRealmEvent = () => {};
|
|
2660
|
-
try {
|
|
2661
|
-
await testRealm.write("Person/swept.json", JSON.stringify({ data: {
|
|
2662
|
-
attributes: { name: "Swept Person" },
|
|
2663
|
-
meta: { adoptsFrom: {
|
|
2664
|
-
module: testRRI("person"),
|
|
2665
|
-
name: "Person"
|
|
2666
|
-
} }
|
|
2667
|
-
} }));
|
|
2668
|
-
deliverRealmEvents({
|
|
2669
|
-
eventName: "index",
|
|
2670
|
-
indexType: "full",
|
|
2671
|
-
realmURL: testRealmURL
|
|
2672
|
-
});
|
|
2673
|
-
await settled();
|
|
2674
|
-
} finally {
|
|
2675
|
-
messageService.relayRealmEvent = deliverRealmEvents;
|
|
2676
|
-
}
|
|
2677
|
-
let instance = storeService.peek(`${testRealmURL}Person/swept`);
|
|
2678
|
-
assert.true(isCardInstance(instance), "the sweep replaced the placeholder with the card");
|
|
2679
|
-
assert.strictEqual(instance.name, "Swept Person", "and it is the indexed state");
|
|
2680
|
-
});
|
|
2681
|
-
(0, import_qunit.test)("a reload that 404s while the row is being rebuilt keeps the card instead of deleting it", async function(assert) {
|
|
2682
|
-
let url = `${testRealmURL}Person/rebuilt`;
|
|
2683
|
-
await testRealm.write("Person/rebuilt.json", JSON.stringify({ data: {
|
|
2684
|
-
attributes: { name: "Rebuilt" },
|
|
2685
|
-
meta: { adoptsFrom: {
|
|
2686
|
-
module: testRRI("person"),
|
|
2687
|
-
name: "Person"
|
|
2688
|
-
} }
|
|
2689
|
-
} }));
|
|
2690
|
-
storeService.addReference(url);
|
|
2691
|
-
await storeService.flush();
|
|
2692
|
-
assert.true(isCardInstance(storeService.peek(url)), "the card starts out loaded");
|
|
2693
|
-
let messageService = getService("message-service");
|
|
2694
|
-
let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
|
|
2695
|
-
messageService.relayRealmEvent = () => {};
|
|
2696
|
-
try {
|
|
2697
|
-
await testRealm.delete("Person/rebuilt.json");
|
|
2698
|
-
await testRealmAdapter.write("Person/rebuilt.json", JSON.stringify({ data: {
|
|
2699
|
-
attributes: { name: "Rebuilt" },
|
|
2700
|
-
meta: { adoptsFrom: {
|
|
2701
|
-
module: testRRI("person"),
|
|
2702
|
-
name: "Person"
|
|
2703
|
-
} }
|
|
2704
|
-
} }));
|
|
2705
|
-
deliverRealmEvents({
|
|
2706
|
-
eventName: "index",
|
|
2707
|
-
indexType: "incremental",
|
|
2708
|
-
invalidations: [url],
|
|
2709
|
-
realmURL: testRealmURL
|
|
2710
|
-
});
|
|
2711
|
-
await settled();
|
|
2712
|
-
} finally {
|
|
2713
|
-
messageService.relayRealmEvent = deliverRealmEvents;
|
|
2714
|
-
}
|
|
2715
|
-
assert.true(isCardInstance(storeService.peek(url)), "the card is still in the store — nothing was deleted");
|
|
2716
|
-
assert.strictEqual(storeService.peekError(url), void 0, "and it is left alone rather than covered by a placeholder");
|
|
2717
|
-
});
|
|
2718
|
-
(0, import_qunit.test)("a card already running in the store is never displaced by the awaiting-index placeholder", async function(assert) {
|
|
2719
|
-
let instance = await storeService.add(new PersonDef({ name: "Brand New" }));
|
|
2720
|
-
let url = instance.id;
|
|
2721
|
-
assert.ok(url, "the new card was assigned a remote id");
|
|
2722
|
-
let messageService = getService("message-service");
|
|
2723
|
-
let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
|
|
2724
|
-
messageService.relayRealmEvent = () => {};
|
|
2725
|
-
let cardService = getService("card-service");
|
|
2726
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
2727
|
-
cardService.fetchJSON = async (fetchUrl, args) => {
|
|
2728
|
-
if (String(fetchUrl).includes(url)) {
|
|
2729
|
-
let err = /* @__PURE__ */ new Error("awaiting index");
|
|
2730
|
-
err.status = 404;
|
|
2731
|
-
err.responseText = JSON.stringify({ errors: [{
|
|
2732
|
-
id: url,
|
|
2733
|
-
status: 404,
|
|
2734
|
-
title: "Not Found",
|
|
2735
|
-
message: `${url} has not finished indexing`,
|
|
2736
|
-
isCardError: true,
|
|
2737
|
-
awaitingIndex: true,
|
|
2738
|
-
additionalErrors: null
|
|
2739
|
-
}] });
|
|
2740
|
-
throw err;
|
|
2741
|
-
}
|
|
2742
|
-
return originalFetchJSON(fetchUrl, args);
|
|
2743
|
-
};
|
|
2744
|
-
try {
|
|
2745
|
-
deliverRealmEvents({
|
|
2746
|
-
eventName: "index",
|
|
2747
|
-
indexType: "incremental",
|
|
2748
|
-
invalidations: [url],
|
|
2749
|
-
realmURL: testRealmURL
|
|
2750
|
-
});
|
|
2751
|
-
await settled();
|
|
2752
|
-
} finally {
|
|
2753
|
-
delete cardService.fetchJSON;
|
|
2754
|
-
messageService.relayRealmEvent = deliverRealmEvents;
|
|
2755
|
-
}
|
|
2756
|
-
assert.strictEqual(storeService.peek(url), instance, "the running instance is still the one the store hands out");
|
|
2757
|
-
assert.strictEqual(storeService.peekError(url), void 0, "no placeholder stands in front of it");
|
|
2758
|
-
assert.ok(storeService.getSaveState(url), "and it is still autosaving, so the user can keep editing");
|
|
2759
|
-
});
|
|
2760
|
-
(0, import_qunit.test)("a full reindex resolves a placeholder whose read was still in flight when it landed", async function(assert) {
|
|
2761
|
-
withholdSource("Person/swept-inflight");
|
|
2762
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
2763
|
-
await storeService.flush();
|
|
2764
|
-
await testRealmAdapter.write("Person/swept-inflight.json", JSON.stringify({ data: {
|
|
2765
|
-
attributes: { name: "Swept In Flight" },
|
|
2766
|
-
meta: { adoptsFrom: {
|
|
2767
|
-
module: testRRI("person"),
|
|
2768
|
-
name: "Person"
|
|
2769
|
-
} }
|
|
2770
|
-
} }));
|
|
2771
|
-
let url = `${testRealmURL}Person/swept-inflight`;
|
|
2772
|
-
let cardService = getService("card-service");
|
|
2773
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
2774
|
-
let reached404 = new Deferred();
|
|
2775
|
-
let release404 = new Deferred();
|
|
2776
|
-
cardService.fetchJSON = async (fetchUrl, args) => {
|
|
2777
|
-
if (!String(fetchUrl).includes("Person/swept-inflight")) return originalFetchJSON(fetchUrl, args);
|
|
2778
|
-
try {
|
|
2779
|
-
return await originalFetchJSON(fetchUrl, args);
|
|
2780
|
-
} catch (err) {
|
|
2781
|
-
reached404.fulfill();
|
|
2782
|
-
await release404.promise;
|
|
2783
|
-
throw err;
|
|
2784
|
-
}
|
|
2785
|
-
};
|
|
2786
|
-
let messageService = getService("message-service");
|
|
2787
|
-
let deliverRealmEvents = messageService.relayRealmEvent.bind(messageService);
|
|
2788
|
-
messageService.relayRealmEvent = () => {};
|
|
2789
|
-
try {
|
|
2790
|
-
let reading = storeService.get(url);
|
|
2791
|
-
await reached404.promise;
|
|
2792
|
-
await testRealm.write("Person/swept-inflight.json", JSON.stringify({ data: {
|
|
2793
|
-
attributes: { name: "Swept In Flight Person" },
|
|
2794
|
-
meta: { adoptsFrom: {
|
|
2795
|
-
module: testRRI("person"),
|
|
2796
|
-
name: "Person"
|
|
2797
|
-
} }
|
|
2798
|
-
} }));
|
|
2799
|
-
deliverRealmEvents({
|
|
2800
|
-
eventName: "index",
|
|
2801
|
-
indexType: "full",
|
|
2802
|
-
realmURL: testRealmURL
|
|
2803
|
-
});
|
|
2804
|
-
release404.fulfill();
|
|
2805
|
-
await reading;
|
|
2806
|
-
await settled();
|
|
2807
|
-
} finally {
|
|
2808
|
-
release404.fulfill();
|
|
2809
|
-
delete cardService.fetchJSON;
|
|
2810
|
-
messageService.relayRealmEvent = deliverRealmEvents;
|
|
2811
|
-
}
|
|
2812
|
-
let instance = storeService.peek(url);
|
|
2813
|
-
assert.true(isCardInstance(instance), "the card takes over rather than the placeholder being stranded");
|
|
2814
|
-
assert.strictEqual(instance.name, "Swept In Flight Person", "and it is the indexed state");
|
|
2815
|
-
});
|
|
2816
|
-
(0, import_qunit.test)("a duplicate incremental event does not reload a card the store already holds at that generation", async function(assert) {
|
|
2817
|
-
let url = `${testRealmURL}Person/echoed`;
|
|
2818
|
-
let events = interceptRealmEvents();
|
|
2819
|
-
let reads;
|
|
2820
|
-
try {
|
|
2821
|
-
await writePerson("Person/echoed.json", "Echoed");
|
|
2822
|
-
await events.nextEventFor(url);
|
|
2823
|
-
storeService.addReference(url);
|
|
2824
|
-
await storeService.flush();
|
|
2825
|
-
await writePerson("Person/echoed.json", "Echoed Again");
|
|
2826
|
-
let event = await events.nextEventFor(url);
|
|
2827
|
-
assert.strictEqual(typeof event.generation, "number", "the realm reported the generation its pass committed");
|
|
2828
|
-
let { versions: _versions, ...onGeneration } = event;
|
|
2829
|
-
reads = countCardReads("Person/echoed");
|
|
2830
|
-
events.deliver(onGeneration);
|
|
2831
|
-
await settled();
|
|
2832
|
-
assert.strictEqual(reads.count, 1, "the event is acted on once");
|
|
2833
|
-
assert.strictEqual(storeService.peek(url).name, "Echoed Again", "and the store holds what the pass wrote");
|
|
2834
|
-
events.deliver(onGeneration);
|
|
2835
|
-
await settled();
|
|
2836
|
-
assert.strictEqual(reads.count, 1, "the same event delivered a second time is a no-op");
|
|
2837
|
-
let { generation: _generation, ...withoutGeneration } = onGeneration;
|
|
2838
|
-
events.deliver(withoutGeneration);
|
|
2839
|
-
await settled();
|
|
2840
|
-
assert.strictEqual(reads.count, 2, "while an otherwise identical event carrying no generation does reload");
|
|
2841
|
-
} finally {
|
|
2842
|
-
reads?.stop();
|
|
2843
|
-
events.restore();
|
|
2844
|
-
}
|
|
2845
|
-
});
|
|
2846
|
-
(0, import_qunit.test)("a duplicate arriving while the first reload is still in flight is coalesced into it", async function(assert) {
|
|
2847
|
-
let url = `${testRealmURL}Person/coalesced`;
|
|
2848
|
-
let events = interceptRealmEvents();
|
|
2849
|
-
let reads;
|
|
2850
|
-
try {
|
|
2851
|
-
await writePerson("Person/coalesced.json", "Coalesced");
|
|
2852
|
-
await events.nextEventFor(url);
|
|
2853
|
-
storeService.addReference(url);
|
|
2854
|
-
await storeService.flush();
|
|
2855
|
-
await writePerson("Person/coalesced.json", "Coalesced Again");
|
|
2856
|
-
let event = await events.nextEventFor(url);
|
|
2857
|
-
reads = countCardReads("Person/coalesced");
|
|
2858
|
-
events.deliver(event);
|
|
2859
|
-
events.deliver(event);
|
|
2860
|
-
await settled();
|
|
2861
|
-
assert.strictEqual(reads.count, 1, "the duplicate is answered by the reload already in flight");
|
|
2862
|
-
assert.strictEqual(storeService.peek(url).name, "Coalesced Again", "and that reload still brought the state the pass wrote");
|
|
2863
|
-
let { generation: _generation, versions: _versions, ...bare } = event;
|
|
2864
|
-
events.deliver(bare);
|
|
2865
|
-
events.deliver(bare);
|
|
2866
|
-
await settled();
|
|
2867
|
-
assert.strictEqual(reads.count, 3, "while a pair carrying neither member reloads twice");
|
|
2868
|
-
} finally {
|
|
2869
|
-
reads?.stop();
|
|
2870
|
-
events.restore();
|
|
2871
|
-
}
|
|
2872
|
-
});
|
|
2873
|
-
(0, import_qunit.test)("an incremental event overtaken by a newer one does not reload", async function(assert) {
|
|
2874
|
-
let url = `${testRealmURL}Person/overtaken`;
|
|
2875
|
-
let events = interceptRealmEvents();
|
|
2876
|
-
let reads;
|
|
2877
|
-
try {
|
|
2878
|
-
await writePerson("Person/overtaken.json", "Overtaken");
|
|
2879
|
-
await events.nextEventFor(url);
|
|
2880
|
-
storeService.addReference(url);
|
|
2881
|
-
await storeService.flush();
|
|
2882
|
-
await writePerson("Person/overtaken.json", "Second");
|
|
2883
|
-
let earlier = await events.nextEventFor(url);
|
|
2884
|
-
await writePerson("Person/overtaken.json", "Third");
|
|
2885
|
-
let later = await events.nextEventFor(url);
|
|
2886
|
-
assert.true(later.generation > earlier.generation, "the two passes are ordered by generation");
|
|
2887
|
-
reads = countCardReads("Person/overtaken");
|
|
2888
|
-
events.deliver(later);
|
|
2889
|
-
await settled();
|
|
2890
|
-
assert.strictEqual(reads.count, 1, "the newer event is acted on");
|
|
2891
|
-
assert.strictEqual(storeService.peek(url).name, "Third", "and the store holds the state that pass wrote");
|
|
2892
|
-
events.deliver(earlier);
|
|
2893
|
-
await settled();
|
|
2894
|
-
assert.strictEqual(reads.count, 1, "the older event arriving after it is ignored");
|
|
2895
|
-
} finally {
|
|
2896
|
-
reads?.stop();
|
|
2897
|
-
events.restore();
|
|
2898
|
-
}
|
|
2899
|
-
});
|
|
2900
|
-
(0, import_qunit.test)("a write's echo is recognized by its version once the request id has aged out of this client's memory", async function(assert) {
|
|
2901
|
-
let url = `${testRealmURL}Person/aged-out`;
|
|
2902
|
-
let events = interceptRealmEvents();
|
|
2903
|
-
let reads;
|
|
2904
|
-
try {
|
|
2905
|
-
await writePerson("Person/aged-out.json", "Aged Out");
|
|
2906
|
-
await events.nextEventFor(url);
|
|
2907
|
-
storeService.addReference(url);
|
|
2908
|
-
await storeService.flush();
|
|
2909
|
-
let instance = storeService.peek(url);
|
|
2910
|
-
instance.name = "Aged Out Edit";
|
|
2911
|
-
storeService.save(url);
|
|
2912
|
-
await settled();
|
|
2913
|
-
let event = await events.nextEventFor(url);
|
|
2914
|
-
assert.true(event.generation > api.getCardMeta(instance, "generation"), "the event names a generation past the one the store holds");
|
|
2915
|
-
assert.strictEqual(api.getCardMeta(instance, "version"), event.versions?.[url], "and the store recorded the version its own write returned");
|
|
2916
|
-
let agedOut = {
|
|
2917
|
-
...event,
|
|
2918
|
-
clientRequestId: "instance:aged-out-of-this-clients-memory"
|
|
2919
|
-
};
|
|
2920
|
-
reads = countCardReads("Person/aged-out");
|
|
2921
|
-
events.deliver(agedOut);
|
|
2922
|
-
await settled();
|
|
2923
|
-
assert.strictEqual(reads.count, 0, "the echo of our own write is not read back");
|
|
2924
|
-
assert.strictEqual(storeService.peek(url).name, "Aged Out Edit", "and the edit stands");
|
|
2925
|
-
let { versions: _versions, ...withoutVersions } = agedOut;
|
|
2926
|
-
events.deliver(withoutVersions);
|
|
2927
|
-
await settled();
|
|
2928
|
-
assert.strictEqual(reads.count, 1, "while the same event without the map does reload");
|
|
2929
|
-
} finally {
|
|
2930
|
-
reads?.stop();
|
|
2931
|
-
events.restore();
|
|
2932
|
-
}
|
|
2933
|
-
});
|
|
2934
|
-
(0, import_qunit.test)("a reload still in flight when the store is reset leaves the replacement identity map alone", async function(assert) {
|
|
2935
|
-
let url = `${testRealmURL}Person/reset-mid-reload`;
|
|
2936
|
-
let events = interceptRealmEvents();
|
|
2937
|
-
let cardService = getService("card-service");
|
|
2938
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
2939
|
-
let readHeld = new Deferred();
|
|
2940
|
-
let releaseRead = new Deferred();
|
|
2941
|
-
let holding = false;
|
|
2942
|
-
try {
|
|
2943
|
-
await writePerson("Person/reset-mid-reload.json", "Before Reset");
|
|
2944
|
-
await events.nextEventFor(url);
|
|
2945
|
-
storeService.addReference(url);
|
|
2946
|
-
await storeService.flush();
|
|
2947
|
-
let preReset = storeService.peek(url);
|
|
2948
|
-
await writePerson("Person/reset-mid-reload.json", "After Reset");
|
|
2949
|
-
let event = await events.nextEventFor(url);
|
|
2950
|
-
holding = true;
|
|
2951
|
-
cardService.fetchJSON = async (fetchUrl, args) => {
|
|
2952
|
-
if (holding && String(fetchUrl).includes("Person/reset-mid-reload") && (args?.method ?? "GET") === "GET") {
|
|
2953
|
-
holding = false;
|
|
2954
|
-
readHeld.fulfill();
|
|
2955
|
-
await releaseRead.promise;
|
|
2956
|
-
}
|
|
2957
|
-
return originalFetchJSON(fetchUrl, args);
|
|
2958
|
-
};
|
|
2959
|
-
events.deliver(event);
|
|
2960
|
-
await readHeld.promise;
|
|
2961
|
-
storeService.resetCache();
|
|
2962
|
-
let replacement = await storeService.get(url);
|
|
2963
|
-
assert.notStrictEqual(replacement[localId], preReset[localId], "the replacement identity map loads its own instance of the card");
|
|
2964
|
-
releaseRead.fulfill();
|
|
2965
|
-
await settled();
|
|
2966
|
-
assert.strictEqual(storeService.peek(url), replacement, "the resumed reload leaves the replacement instance in place");
|
|
2967
|
-
assert.strictEqual(storeService.peekError(url)?.message, void 0, "and records no error for the card");
|
|
2968
|
-
assert.strictEqual(replacement.name, "After Reset", "the replacement holds the state the realm wrote");
|
|
2969
|
-
} finally {
|
|
2970
|
-
releaseRead.fulfill();
|
|
2971
|
-
delete cardService.fetchJSON;
|
|
2972
|
-
events.restore();
|
|
2973
|
-
}
|
|
2974
|
-
});
|
|
2975
|
-
(0, import_qunit.test)("a reload still in flight when a code change resets identity in place leaves the re-established instance alone", async function(assert) {
|
|
2976
|
-
let url = `${testRealmURL}Person/code-change-mid-reload`;
|
|
2977
|
-
let events = interceptRealmEvents();
|
|
2978
|
-
let cardService = getService("card-service");
|
|
2979
|
-
let originalFetchJSON = cardService.fetchJSON.bind(cardService);
|
|
2980
|
-
let readHeld = new Deferred();
|
|
2981
|
-
let releaseRead = new Deferred();
|
|
2982
|
-
let holding = false;
|
|
2983
|
-
try {
|
|
2984
|
-
await writePerson("Person/code-change-mid-reload.json", "Before Reset");
|
|
2985
|
-
await events.nextEventFor(url);
|
|
2986
|
-
storeService.addReference(url);
|
|
2987
|
-
await storeService.flush();
|
|
2988
|
-
let preReset = storeService.peek(url);
|
|
2989
|
-
await writePerson("Person/code-change-mid-reload.json", "After Reset");
|
|
2990
|
-
let event = await events.nextEventFor(url);
|
|
2991
|
-
holding = true;
|
|
2992
|
-
cardService.fetchJSON = async (fetchUrl, args) => {
|
|
2993
|
-
if (holding && String(fetchUrl).includes("Person/code-change-mid-reload") && (args?.method ?? "GET") === "GET") {
|
|
2994
|
-
holding = false;
|
|
2995
|
-
readHeld.fulfill();
|
|
2996
|
-
await releaseRead.promise;
|
|
2997
|
-
}
|
|
2998
|
-
return originalFetchJSON(fetchUrl, args);
|
|
2999
|
-
};
|
|
3000
|
-
events.deliver(event);
|
|
3001
|
-
await readHeld.promise;
|
|
3002
|
-
storeService.refreshReferencesForCodeChange("test code change");
|
|
3003
|
-
let reestablished = await storeService.get(url);
|
|
3004
|
-
assert.strictEqual(storeService.peek(url), reestablished, "the store holds the instance the code change re-established");
|
|
3005
|
-
assert.notStrictEqual(reestablished[localId], preReset[localId], "the code change re-establishes the card as a fresh instance");
|
|
3006
|
-
releaseRead.fulfill();
|
|
3007
|
-
await settled();
|
|
3008
|
-
assert.strictEqual(storeService.peek(url), reestablished, "the resumed reload leaves the re-established instance in place");
|
|
3009
|
-
assert.strictEqual(storeService.peekError(url)?.message, void 0, "and records no error for the card");
|
|
3010
|
-
assert.strictEqual(reestablished.name, "After Reset", "the re-established instance holds the state the realm wrote");
|
|
3011
|
-
} finally {
|
|
3012
|
-
releaseRead.fulfill();
|
|
3013
|
-
delete cardService.fetchJSON;
|
|
3014
|
-
events.restore();
|
|
3015
|
-
}
|
|
3016
|
-
});
|
|
3017
|
-
async function holdIndexQueue() {
|
|
3018
|
-
let { queue } = getService("queue");
|
|
3019
|
-
let started = new Deferred();
|
|
3020
|
-
let release = new Deferred();
|
|
3021
|
-
queue.register("hold-index-queue", async () => {
|
|
3022
|
-
started.fulfill();
|
|
3023
|
-
await release.promise;
|
|
3024
|
-
return null;
|
|
3025
|
-
});
|
|
3026
|
-
let holder = await queue.publish({
|
|
3027
|
-
jobType: "hold-index-queue",
|
|
3028
|
-
concurrencyGroup: null,
|
|
3029
|
-
timeout: 30,
|
|
3030
|
-
args: null
|
|
3031
|
-
});
|
|
3032
|
-
await started.promise;
|
|
3033
|
-
let pendingCallers = () => queue.jobs.filter((job) => job.jobType === "incremental-index").flatMap((job) => (job.args?.coalescedCallers ?? []).map((caller) => caller.clientRequestId));
|
|
3034
|
-
let published = [];
|
|
3035
|
-
let arrivals = [];
|
|
3036
|
-
let heldAt = performance.now();
|
|
3037
|
-
let publish = queue.publish.bind(queue);
|
|
3038
|
-
queue.publish = async (args) => {
|
|
3039
|
-
let job = await publish(args);
|
|
3040
|
-
published.push({
|
|
3041
|
-
jobType: args.jobType,
|
|
3042
|
-
at: Math.round(performance.now() - heldAt)
|
|
3043
|
-
});
|
|
3044
|
-
for (let arrival of [...arrivals]) if (arrival.ready()) {
|
|
3045
|
-
arrivals.splice(arrivals.indexOf(arrival), 1);
|
|
3046
|
-
arrival.deferred.fulfill();
|
|
3047
|
-
}
|
|
3048
|
-
return job;
|
|
3049
|
-
};
|
|
3050
|
-
let callersArrive = async (description, ready) => {
|
|
3051
|
-
if (ready(pendingCallers())) return;
|
|
3052
|
-
let deferred = new Deferred();
|
|
3053
|
-
let arrival = {
|
|
3054
|
-
ready: () => ready(pendingCallers()),
|
|
3055
|
-
deferred
|
|
3056
|
-
};
|
|
3057
|
-
arrivals.push(arrival);
|
|
3058
|
-
let guard = setTimeout(() => {
|
|
3059
|
-
arrivals.splice(arrivals.indexOf(arrival), 1);
|
|
3060
|
-
deferred.reject(/* @__PURE__ */ new Error(`the held index pass never had ${description}: callers=${JSON.stringify(pendingCallers())} publishes=${JSON.stringify(published)}`));
|
|
3061
|
-
}, 2e4);
|
|
3062
|
-
try {
|
|
3063
|
-
await deferred.promise;
|
|
3064
|
-
} finally {
|
|
3065
|
-
clearTimeout(guard);
|
|
3066
|
-
}
|
|
3067
|
-
};
|
|
3068
|
-
return {
|
|
3069
|
-
holder,
|
|
3070
|
-
release,
|
|
3071
|
-
pendingCallers,
|
|
3072
|
-
callersArrive
|
|
3073
|
-
};
|
|
3074
|
-
}
|
|
3075
|
-
(0, import_qunit.test)("this client's own write, announced under another writer's id in a pass they shared, is not read back", async function(assert) {
|
|
3076
|
-
let mine = `${testRealmURL}Person/shared-mine`;
|
|
3077
|
-
let theirs = `${testRealmURL}Person/shared-theirs`;
|
|
3078
|
-
let events = interceptRealmEvents();
|
|
3079
|
-
let reads;
|
|
3080
|
-
let theirReads;
|
|
3081
|
-
let hold;
|
|
3082
|
-
try {
|
|
3083
|
-
await writePerson("Person/shared-mine.json", "Mine");
|
|
3084
|
-
await events.nextEventFor(mine);
|
|
3085
|
-
await writePerson("Person/shared-theirs.json", "Theirs");
|
|
3086
|
-
await events.nextEventFor(theirs);
|
|
3087
|
-
storeService.addReference(mine);
|
|
3088
|
-
storeService.addReference(theirs);
|
|
3089
|
-
await storeService.flush();
|
|
3090
|
-
hold = await holdIndexQueue();
|
|
3091
|
-
let theirWrite = testRealm.write("Person/shared-theirs.json", JSON.stringify({ data: {
|
|
3092
|
-
attributes: { name: "Theirs Edited" },
|
|
3093
|
-
meta: { adoptsFrom: {
|
|
3094
|
-
module: testRRI("person"),
|
|
3095
|
-
name: "Person"
|
|
3096
|
-
} }
|
|
3097
|
-
} }), { clientRequestId: "instance:another-tab" });
|
|
3098
|
-
await hold.callersArrive("the other writer's write", (callers) => callers.includes("instance:another-tab"));
|
|
3099
|
-
let instance = storeService.peek(mine);
|
|
3100
|
-
instance.name = "Mine Edited";
|
|
3101
|
-
let ownSave = storeService.save(mine);
|
|
3102
|
-
await hold.callersArrive("this client's save", (callers) => callers.length === 2);
|
|
3103
|
-
hold.release.fulfill();
|
|
3104
|
-
await Promise.all([
|
|
3105
|
-
theirWrite,
|
|
3106
|
-
ownSave,
|
|
3107
|
-
hold.holder.done
|
|
3108
|
-
]);
|
|
3109
|
-
await settled();
|
|
3110
|
-
let event = await events.nextEventFor(mine);
|
|
3111
|
-
assert.strictEqual(event.clientRequestId, "instance:another-tab", "the pass is announced under the other writer's id");
|
|
3112
|
-
assert.deepEqual([...event.invalidations].sort(), [mine, theirs].sort(), "and it carries both writes");
|
|
3113
|
-
assert.strictEqual(event.coalescedWrites?.length, 2, "with both writers among its coalesced writes");
|
|
3114
|
-
reads = countCardReads("Person/shared-mine");
|
|
3115
|
-
theirReads = countCardReads("Person/shared-theirs");
|
|
3116
|
-
events.deliver(event);
|
|
3117
|
-
await settled();
|
|
3118
|
-
assert.strictEqual(reads.count, 0, "the card this client wrote is not read back");
|
|
3119
|
-
assert.strictEqual(storeService.peek(mine).name, "Mine Edited", "and its edit stands");
|
|
3120
|
-
assert.strictEqual(theirReads.count, 1, "while the card the other writer changed is");
|
|
3121
|
-
assert.strictEqual(storeService.peek(theirs).name, "Theirs Edited", "and the store holds what that writer wrote");
|
|
3122
|
-
let { coalescedWrites: _coalescedWrites, ...announcedAlone } = event;
|
|
3123
|
-
events.deliver(announcedAlone);
|
|
3124
|
-
await settled();
|
|
3125
|
-
assert.strictEqual(reads.count, 1, "while the same event without its coalesced writes reads it back");
|
|
3126
|
-
} finally {
|
|
3127
|
-
hold?.release.fulfill();
|
|
3128
|
-
reads?.stop();
|
|
3129
|
-
theirReads?.stop();
|
|
3130
|
-
events.restore();
|
|
3131
|
-
}
|
|
3132
|
-
});
|
|
3133
|
-
(0, import_qunit.test)("an instance can be restored after a loader reset", async function(assert) {
|
|
3134
|
-
setCardInOperatorModeState(`${testRealmURL}Person/hassan`);
|
|
3135
|
-
await renderComponent(class TestDriver extends Component {
|
|
3136
|
-
static {
|
|
3137
|
-
setComponentTemplate(templateFactory({
|
|
3138
|
-
"id": "ZD1xwmB+",
|
|
3139
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
3140
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3141
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
3142
|
-
"isStrictMode": true
|
|
3143
|
-
}), this);
|
|
3144
|
-
}
|
|
3145
|
-
});
|
|
3146
|
-
assert.dom(`[data-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"]`).containsText("Hassan", "the card data is correct");
|
|
3147
|
-
await testRealm.write(`foo.gts`, `
|
|
3148
|
-
import { contains, CardDef } from '@cardstack/base/card-api';
|
|
3149
|
-
export class Foo extends CardDef {}
|
|
3150
|
-
`.trim());
|
|
3151
|
-
await waitFor("[data-test-stack-item-loading-card]", {
|
|
3152
|
-
count: 0,
|
|
3153
|
-
timeout: 5e3
|
|
3154
|
-
});
|
|
3155
|
-
assert.dom("[data-test-stack-item-loading-card]").doesNotExist("loading state is not displayed");
|
|
3156
|
-
assert.dom(`[data-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"]`).containsText("Hassan", "the card data is correct");
|
|
3157
|
-
});
|
|
3158
|
-
(0, import_qunit.test)("an instance that started out with a local ID can be restored after a loader reset", async function(assert) {
|
|
3159
|
-
let newInstance = new PersonDef({ name: "Andrea" });
|
|
3160
|
-
await storeService.add(newInstance, { realm: testRealmURL });
|
|
3161
|
-
setCardInOperatorModeState(newInstance[localId]);
|
|
3162
|
-
await renderComponent(class TestDriver extends Component {
|
|
3163
|
-
static {
|
|
3164
|
-
setComponentTemplate(templateFactory({
|
|
3165
|
-
"id": "ZD1xwmB+",
|
|
3166
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
3167
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3168
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
3169
|
-
"isStrictMode": true
|
|
3170
|
-
}), this);
|
|
3171
|
-
}
|
|
3172
|
-
});
|
|
3173
|
-
assert.dom(`[data-stack-card="${newInstance.id}"] [data-test-field="name"]`).containsText("Andrea", "the card data is correct");
|
|
3174
|
-
await testRealm.write(`foo.gts`, `
|
|
3175
|
-
import { contains, CardDef } from '@cardstack/base/card-api';
|
|
3176
|
-
export class Foo extends CardDef {}
|
|
3177
|
-
`.trim());
|
|
3178
|
-
await waitFor("[data-test-stack-item-loading-card]", {
|
|
3179
|
-
count: 0,
|
|
3180
|
-
timeout: 5e3
|
|
3181
|
-
});
|
|
3182
|
-
assert.dom("[data-test-stack-item-loading-card]").doesNotExist("loading state is not displayed");
|
|
3183
|
-
assert.dom(`[data-stack-card="${newInstance.id}"] [data-test-field="name"]`).containsText("Andrea", "the card data is correct");
|
|
3184
|
-
});
|
|
3185
|
-
(0, import_qunit.test)("an unsaved instance live updates when realm event matching local ID is received", async function(assert) {
|
|
3186
|
-
let newInstance = new PersonDef({ name: "Andrea" });
|
|
3187
|
-
await storeService.addWithoutPersisting(newInstance);
|
|
3188
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
3189
|
-
await storeService.flush();
|
|
3190
|
-
let instance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
3191
|
-
instance.friends = [newInstance];
|
|
3192
|
-
await waitUntil(() => newInstance.id, { timeout: 5e3 });
|
|
3193
|
-
assert.strictEqual(newInstance.id.split("/").pop(), newInstance[localId], "the new instance was live updated with a remote id");
|
|
3194
|
-
});
|
|
3195
|
-
(0, import_qunit.test)("an unsaved instance will auto save after it has been assigned a remote ID", async function(assert) {
|
|
3196
|
-
assert.expect(2);
|
|
3197
|
-
let newInstance = new PersonDef({ name: "Andrea" });
|
|
3198
|
-
await storeService.addWithoutPersisting(newInstance);
|
|
3199
|
-
storeService.addReference(`${testRealmURL}Person/hassan`);
|
|
3200
|
-
await storeService.flush();
|
|
3201
|
-
let instance = storeService.peek(`${testRealmURL}Person/hassan`);
|
|
3202
|
-
instance.friends = [newInstance];
|
|
3203
|
-
await waitUntil(() => newInstance.id, { timeout: 5e3 });
|
|
3204
|
-
this.onSave((url, doc) => {
|
|
3205
|
-
if (url.href === newInstance.id) {
|
|
3206
|
-
assert.strictEqual(url.href, newInstance.id, "the save url is correct");
|
|
3207
|
-
assert.strictEqual(doc.data.attributes?.name, "Air", "card data is correct");
|
|
3208
|
-
}
|
|
3209
|
-
});
|
|
3210
|
-
newInstance.name = "Air";
|
|
3211
|
-
});
|
|
3212
|
-
(0, import_qunit.test)("reference count is balanced when used with CardResource that is destroyed", async function(assert) {
|
|
3213
|
-
class Driver {
|
|
3214
|
-
static {
|
|
3215
|
-
decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
|
|
3216
|
-
return false;
|
|
3217
|
-
});
|
|
3218
|
-
}
|
|
3219
|
-
#showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
|
|
3220
|
-
static {
|
|
3221
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3222
|
-
}
|
|
3223
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3224
|
-
}
|
|
3225
|
-
let driver = new Driver();
|
|
3226
|
-
class ResourceConsumer extends Component {
|
|
3227
|
-
resource = getCard(this, () => driver.id);
|
|
3228
|
-
get renderedCard() {
|
|
3229
|
-
return this.resource.card?.constructor.getComponent(this.resource.card);
|
|
3230
|
-
}
|
|
3231
|
-
static {
|
|
3232
|
-
setComponentTemplate(templateFactory({
|
|
3233
|
-
"id": "XWrL4bCI",
|
|
3234
|
-
"block": "[[[41,[30,0,[\"resource\",\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"resource\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3235
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3236
|
-
"isStrictMode": true
|
|
3237
|
-
}), this);
|
|
3238
|
-
}
|
|
3239
|
-
}
|
|
3240
|
-
await renderComponent(class TestDriver extends Component {
|
|
3241
|
-
static {
|
|
3242
|
-
setComponentTemplate(templateFactory({
|
|
3243
|
-
"id": "hNRtWalG",
|
|
3244
|
-
"block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3245
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3246
|
-
"scope": () => [driver, ResourceConsumer],
|
|
3247
|
-
"isStrictMode": true
|
|
3248
|
-
}), this);
|
|
3249
|
-
}
|
|
3250
|
-
});
|
|
3251
|
-
driver.showComponent = true;
|
|
3252
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
3253
|
-
let hassan = `${testRealmURL}Person/hassan`;
|
|
3254
|
-
driver.id = hassan;
|
|
3255
|
-
await settleCardRender(assert, hassan, `[data-test-rendered-card="${hassan}"]`);
|
|
3256
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
|
|
3257
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
|
|
3258
|
-
driver.id = jade;
|
|
3259
|
-
await settleCardRender(assert, jade, `[data-test-rendered-card="${jade}"]`);
|
|
3260
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3261
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
|
|
3262
|
-
driver.showComponent = false;
|
|
3263
|
-
await waitFor(`[data-test-rendered-card]`, { count: 0 });
|
|
3264
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
|
|
3265
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
|
|
3266
|
-
});
|
|
3267
|
-
(0, import_qunit.test)("reference count is balanced when used with CardResource for file-meta that is destroyed", async function(assert) {
|
|
3268
|
-
class Driver {
|
|
3269
|
-
static {
|
|
3270
|
-
decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
|
|
3271
|
-
return false;
|
|
3272
|
-
});
|
|
3273
|
-
}
|
|
3274
|
-
#showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
|
|
3275
|
-
static {
|
|
3276
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3277
|
-
}
|
|
3278
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3279
|
-
}
|
|
3280
|
-
let driver = new Driver();
|
|
3281
|
-
let firstFile = `${testRealmURL}notes.txt`;
|
|
3282
|
-
let secondFile = `${testRealmURL}README.txt`;
|
|
3283
|
-
await testRealm.write("notes.txt", "notes");
|
|
3284
|
-
await testRealm.write("README.txt", "readme");
|
|
3285
|
-
class ResourceConsumer extends Component {
|
|
3286
|
-
resource = getCard(this, () => driver.id, { type: "file-meta" });
|
|
3287
|
-
static {
|
|
3288
|
-
setComponentTemplate(templateFactory({
|
|
3289
|
-
"id": "5jWS7tbo",
|
|
3290
|
-
"block": "[[[41,[30,0,[\"resource\",\"card\"]],[[[1,\" \"],[10,0],[15,\"data-test-rendered-file\",[30,0,[\"resource\",\"id\"]]],[12],[13],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3291
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3292
|
-
"isStrictMode": true
|
|
3293
|
-
}), this);
|
|
3294
|
-
}
|
|
3295
|
-
}
|
|
3296
|
-
await renderComponent(class TestDriver extends Component {
|
|
3297
|
-
static {
|
|
3298
|
-
setComponentTemplate(templateFactory({
|
|
3299
|
-
"id": "hNRtWalG",
|
|
3300
|
-
"block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3301
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3302
|
-
"scope": () => [driver, ResourceConsumer],
|
|
3303
|
-
"isStrictMode": true
|
|
3304
|
-
}), this);
|
|
3305
|
-
}
|
|
3306
|
-
});
|
|
3307
|
-
driver.showComponent = true;
|
|
3308
|
-
driver.id = firstFile;
|
|
3309
|
-
await settleCardRender(assert, firstFile, `[data-test-rendered-file="${firstFile}"]`, { type: "file-meta" });
|
|
3310
|
-
assert.strictEqual(storeService.getReferenceCount(firstFile), 1, `reference count for ${firstFile} is 1`);
|
|
3311
|
-
assert.strictEqual(storeService.getReferenceCount(secondFile), 0, `reference count for ${secondFile} is 0`);
|
|
3312
|
-
driver.id = secondFile;
|
|
3313
|
-
await settleCardRender(assert, secondFile, `[data-test-rendered-file="${secondFile}"]`, { type: "file-meta" });
|
|
3314
|
-
assert.strictEqual(storeService.getReferenceCount(firstFile), 0, `reference count for ${firstFile} is 0`);
|
|
3315
|
-
assert.strictEqual(storeService.getReferenceCount(secondFile), 1, `reference count for ${secondFile} is 1`);
|
|
3316
|
-
driver.showComponent = false;
|
|
3317
|
-
await waitFor(`[data-test-rendered-file]`, { count: 0 });
|
|
3318
|
-
assert.strictEqual(storeService.getReferenceCount(firstFile), 0, `reference count for ${firstFile} is 0`);
|
|
3319
|
-
assert.strictEqual(storeService.getReferenceCount(secondFile), 0, `reference count for ${secondFile} is 0`);
|
|
3320
|
-
});
|
|
3321
|
-
(0, import_qunit.test)("reference count is balanced during auto saving", async function(assert) {
|
|
3322
|
-
let hassan = `${testRealmURL}Person/hassan`;
|
|
3323
|
-
setCardInOperatorModeState(hassan, "edit");
|
|
3324
|
-
await renderComponent(class TestDriver extends Component {
|
|
3325
|
-
static {
|
|
3326
|
-
setComponentTemplate(templateFactory({
|
|
3327
|
-
"id": "ZD1xwmB+",
|
|
3328
|
-
"block": "[[[8,[32,0],null,[[\"@onClose\"],[[32,1]]],null]],[],[]]",
|
|
3329
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3330
|
-
"scope": () => [OperatorModeContainer, noop],
|
|
3331
|
-
"isStrictMode": true
|
|
3332
|
-
}), this);
|
|
3333
|
-
}
|
|
3334
|
-
});
|
|
3335
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
|
|
3336
|
-
await withSlowSave(1e3, async () => {
|
|
3337
|
-
await typeIn(`[data-test-stack-card="${testRealmURL}Person/hassan"] [data-test-field="name"] input`, " Paper");
|
|
3338
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
|
|
3339
|
-
});
|
|
3340
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
|
|
3341
|
-
});
|
|
3342
|
-
(0, import_qunit.test)("reference count is balanced when used with CardCollectionResource that is destroyed", async function(assert) {
|
|
3343
|
-
class Driver {
|
|
3344
|
-
static {
|
|
3345
|
-
decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
|
|
3346
|
-
return false;
|
|
3347
|
-
});
|
|
3348
|
-
}
|
|
3349
|
-
#showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
|
|
3350
|
-
static {
|
|
3351
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3352
|
-
}
|
|
3353
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3354
|
-
}
|
|
3355
|
-
let driver = new Driver();
|
|
3356
|
-
class ResourceConsumer extends Component {
|
|
3357
|
-
resource = getCardCollection(this, () => driver.id ? [driver.id] : []);
|
|
3358
|
-
get card() {
|
|
3359
|
-
return this.resource.cards[0];
|
|
3360
|
-
}
|
|
3361
|
-
get renderedCard() {
|
|
3362
|
-
return this.card?.constructor.getComponent(this.card);
|
|
3363
|
-
}
|
|
3364
|
-
static {
|
|
3365
|
-
setComponentTemplate(templateFactory({
|
|
3366
|
-
"id": "99aOV2w7",
|
|
3367
|
-
"block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3368
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3369
|
-
"isStrictMode": true
|
|
3370
|
-
}), this);
|
|
3371
|
-
}
|
|
3372
|
-
}
|
|
3373
|
-
await renderComponent(class TestDriver extends Component {
|
|
3374
|
-
static {
|
|
3375
|
-
setComponentTemplate(templateFactory({
|
|
3376
|
-
"id": "hNRtWalG",
|
|
3377
|
-
"block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3378
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3379
|
-
"scope": () => [driver, ResourceConsumer],
|
|
3380
|
-
"isStrictMode": true
|
|
3381
|
-
}), this);
|
|
3382
|
-
}
|
|
3383
|
-
});
|
|
3384
|
-
driver.showComponent = true;
|
|
3385
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
3386
|
-
let hassan = `${testRealmURL}Person/hassan`;
|
|
3387
|
-
driver.id = hassan;
|
|
3388
|
-
await settleCardRender(assert, hassan, `[data-test-rendered-card="${hassan}"]`);
|
|
3389
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
|
|
3390
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
|
|
3391
|
-
driver.id = jade;
|
|
3392
|
-
await settleCardRender(assert, jade, `[data-test-rendered-card="${jade}"]`);
|
|
3393
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3394
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
|
|
3395
|
-
driver.showComponent = false;
|
|
3396
|
-
await waitFor(`[data-test-rendered-card]`, { count: 0 });
|
|
3397
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
|
|
3398
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
|
|
3399
|
-
});
|
|
3400
|
-
(0, import_qunit.test)("reference count is balanced when used with SearchResource that is destroyed", async function(assert) {
|
|
3401
|
-
class Driver {
|
|
3402
|
-
static {
|
|
3403
|
-
decorateFieldV2(this.prototype, "showComponent", [tracked], function() {
|
|
3404
|
-
return false;
|
|
3405
|
-
});
|
|
3406
|
-
}
|
|
3407
|
-
#showComponent = (initializeDeferredDecorator(this, "showComponent"), void 0);
|
|
3408
|
-
static {
|
|
3409
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3410
|
-
}
|
|
3411
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3412
|
-
}
|
|
3413
|
-
let driver = new Driver();
|
|
3414
|
-
class ResourceConsumer extends Component {
|
|
3415
|
-
static {
|
|
3416
|
-
decorateFieldV2(this.prototype, "store", [service]);
|
|
3417
|
-
}
|
|
3418
|
-
#store = (initializeDeferredDecorator(this, "store"), void 0);
|
|
3419
|
-
get resource() {
|
|
3420
|
-
return this.store.getSearchResource(this, () => driver.id ? { filter: {
|
|
3421
|
-
on: baseCardRef,
|
|
3422
|
-
eq: { id: driver.id }
|
|
3423
|
-
} } : void 0);
|
|
3424
|
-
}
|
|
3425
|
-
static {
|
|
3426
|
-
decorateMethodV2(this.prototype, "resource", [cached]);
|
|
3427
|
-
}
|
|
3428
|
-
get card() {
|
|
3429
|
-
return this.resource.instances[0];
|
|
3430
|
-
}
|
|
3431
|
-
static {
|
|
3432
|
-
setComponentTemplate(templateFactory({
|
|
3433
|
-
"id": "F3i58yQO",
|
|
3434
|
-
"block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[10,0],[15,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]],[12],[1,\"\\n \"],[1,[30,0,[\"card\",\"id\"]]],[1,\"\\n \"],[13],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3435
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3436
|
-
"isStrictMode": true
|
|
3437
|
-
}), this);
|
|
3438
|
-
}
|
|
3439
|
-
}
|
|
3440
|
-
await renderComponent(class TestDriver extends Component {
|
|
3441
|
-
static {
|
|
3442
|
-
setComponentTemplate(templateFactory({
|
|
3443
|
-
"id": "hNRtWalG",
|
|
3444
|
-
"block": "[[[41,[32,0,[\"showComponent\"]],[[[1,\" \"],[8,[32,1],null,null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3445
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3446
|
-
"scope": () => [driver, ResourceConsumer],
|
|
3447
|
-
"isStrictMode": true
|
|
3448
|
-
}), this);
|
|
3449
|
-
}
|
|
3450
|
-
});
|
|
3451
|
-
driver.showComponent = true;
|
|
3452
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
3453
|
-
let hassan = `${testRealmURL}Person/hassan`;
|
|
3454
|
-
driver.id = hassan;
|
|
3455
|
-
await waitUntil(() => storeService.getReferenceCount(hassan) === 1 && storeService.getReferenceCount(jade) === 0, { timeout: 1e4 });
|
|
3456
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
|
|
3457
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 1, `reference count for ${hassan} is 1`);
|
|
3458
|
-
driver.id = jade;
|
|
3459
|
-
await waitUntil(() => storeService.getReferenceCount(jade) === 1 && storeService.getReferenceCount(hassan) === 0, { timeout: 1e4 });
|
|
3460
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3461
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
|
|
3462
|
-
driver.showComponent = false;
|
|
3463
|
-
await waitUntil(() => storeService.getReferenceCount(jade) === 0 && storeService.getReferenceCount(hassan) === 0, { timeout: 1e4 });
|
|
3464
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 0, `reference count for ${jade} is 0`);
|
|
3465
|
-
assert.strictEqual(storeService.getReferenceCount(hassan), 0, `reference count for ${hassan} is 0`);
|
|
3466
|
-
});
|
|
3467
|
-
(0, import_qunit.test)("reference count is balanced when used with SearchResource that live updates when there is a index event", async function(assert) {
|
|
3468
|
-
class Driver {
|
|
3469
|
-
static {
|
|
3470
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3471
|
-
}
|
|
3472
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3473
|
-
}
|
|
3474
|
-
let driver = new Driver();
|
|
3475
|
-
class ResourceConsumer extends Component {
|
|
3476
|
-
static {
|
|
3477
|
-
decorateFieldV2(this.prototype, "store", [service]);
|
|
3478
|
-
}
|
|
3479
|
-
#store = (initializeDeferredDecorator(this, "store"), void 0);
|
|
3480
|
-
get resource() {
|
|
3481
|
-
return this.store.getSearchResource(this, () => driver.id ? { filter: {
|
|
3482
|
-
on: baseCardRef,
|
|
3483
|
-
eq: { id: driver.id }
|
|
3484
|
-
} } : void 0, void 0, { isLive: true });
|
|
3485
|
-
}
|
|
3486
|
-
static {
|
|
3487
|
-
decorateMethodV2(this.prototype, "resource", [cached]);
|
|
3488
|
-
}
|
|
3489
|
-
get card() {
|
|
3490
|
-
return this.resource.instances[0];
|
|
3491
|
-
}
|
|
3492
|
-
get renderedCard() {
|
|
3493
|
-
return this.card?.constructor.getComponent(this.card);
|
|
3494
|
-
}
|
|
3495
|
-
static {
|
|
3496
|
-
setComponentTemplate(templateFactory({
|
|
3497
|
-
"id": "99aOV2w7",
|
|
3498
|
-
"block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3499
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3500
|
-
"isStrictMode": true
|
|
3501
|
-
}), this);
|
|
3502
|
-
}
|
|
3503
|
-
}
|
|
3504
|
-
await renderComponent(class TestDriver extends Component {
|
|
3505
|
-
static {
|
|
3506
|
-
setComponentTemplate(templateFactory({
|
|
3507
|
-
"id": "HtmuKyv7",
|
|
3508
|
-
"block": "[[[8,[32,0],null,null,null]],[],[]]",
|
|
3509
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3510
|
-
"scope": () => [ResourceConsumer],
|
|
3511
|
-
"isStrictMode": true
|
|
3512
|
-
}), this);
|
|
3513
|
-
}
|
|
3514
|
-
});
|
|
3515
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
3516
|
-
driver.id = jade;
|
|
3517
|
-
await waitFor(`[data-test-rendered-card="${jade}"]`, { timeout: 5e3 });
|
|
3518
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3519
|
-
let deferred = new Deferred();
|
|
3520
|
-
let unsubscribe = getService("message-service").subscribe(testRealmURL, (ev) => {
|
|
3521
|
-
if (ev.eventName === "index" && ev.indexType === "incremental") {
|
|
3522
|
-
unsubscribe();
|
|
3523
|
-
deferred.fulfill();
|
|
3524
|
-
}
|
|
3525
|
-
});
|
|
3526
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
3527
|
-
attributes: { name: "Paper" },
|
|
3528
|
-
meta: { adoptsFrom: {
|
|
3529
|
-
module: testRRI("person"),
|
|
3530
|
-
name: "Person"
|
|
3531
|
-
} }
|
|
3532
|
-
} }));
|
|
3533
|
-
await deferred.promise;
|
|
3534
|
-
deferred = new Deferred();
|
|
3535
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
3536
|
-
attributes: { name: "Paper" },
|
|
3537
|
-
meta: { adoptsFrom: {
|
|
3538
|
-
module: testRRI("person"),
|
|
3539
|
-
name: "Person"
|
|
3540
|
-
} }
|
|
3541
|
-
} }));
|
|
3542
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3543
|
-
});
|
|
3544
|
-
(0, import_qunit.test)("reference count is balanced when used with CardCollectionResource when there is a index event", async function(assert) {
|
|
3545
|
-
class Driver {
|
|
3546
|
-
static {
|
|
3547
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3548
|
-
}
|
|
3549
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3550
|
-
}
|
|
3551
|
-
let driver = new Driver();
|
|
3552
|
-
class ResourceConsumer extends Component {
|
|
3553
|
-
resource = getCardCollection(this, () => driver.id ? [driver.id] : []);
|
|
3554
|
-
get card() {
|
|
3555
|
-
return this.resource.cards[0];
|
|
3556
|
-
}
|
|
3557
|
-
get renderedCard() {
|
|
3558
|
-
return this.card?.constructor.getComponent(this.card);
|
|
3559
|
-
}
|
|
3560
|
-
static {
|
|
3561
|
-
setComponentTemplate(templateFactory({
|
|
3562
|
-
"id": "99aOV2w7",
|
|
3563
|
-
"block": "[[[41,[30,0,[\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"card\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3564
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3565
|
-
"isStrictMode": true
|
|
3566
|
-
}), this);
|
|
3567
|
-
}
|
|
3568
|
-
}
|
|
3569
|
-
await renderComponent(class TestDriver extends Component {
|
|
3570
|
-
static {
|
|
3571
|
-
setComponentTemplate(templateFactory({
|
|
3572
|
-
"id": "HtmuKyv7",
|
|
3573
|
-
"block": "[[[8,[32,0],null,null,null]],[],[]]",
|
|
3574
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3575
|
-
"scope": () => [ResourceConsumer],
|
|
3576
|
-
"isStrictMode": true
|
|
3577
|
-
}), this);
|
|
3578
|
-
}
|
|
3579
|
-
});
|
|
3580
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
3581
|
-
driver.id = jade;
|
|
3582
|
-
await waitFor(`[data-test-rendered-card="${jade}"]`, { timeout: 5e3 });
|
|
3583
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3584
|
-
let deferred = new Deferred();
|
|
3585
|
-
let unsubscribe = getService("message-service").subscribe(testRealmURL, (ev) => {
|
|
3586
|
-
if (ev.eventName === "index" && ev.indexType === "incremental") {
|
|
3587
|
-
unsubscribe();
|
|
3588
|
-
deferred.fulfill();
|
|
3589
|
-
}
|
|
3590
|
-
});
|
|
3591
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
3592
|
-
attributes: { name: "Paper" },
|
|
3593
|
-
meta: { adoptsFrom: {
|
|
3594
|
-
module: testRRI("person"),
|
|
3595
|
-
name: "Person"
|
|
3596
|
-
} }
|
|
3597
|
-
} }));
|
|
3598
|
-
await deferred.promise;
|
|
3599
|
-
deferred = new Deferred();
|
|
3600
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
3601
|
-
attributes: { name: "Paper" },
|
|
3602
|
-
meta: { adoptsFrom: {
|
|
3603
|
-
module: testRRI("person"),
|
|
3604
|
-
name: "Person"
|
|
3605
|
-
} }
|
|
3606
|
-
} }));
|
|
3607
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3608
|
-
});
|
|
3609
|
-
(0, import_qunit.test)("reference count is balanced when used with CardResource when there is a index event", async function(assert) {
|
|
3610
|
-
class Driver {
|
|
3611
|
-
static {
|
|
3612
|
-
decorateFieldV2(this.prototype, "id", [tracked]);
|
|
3613
|
-
}
|
|
3614
|
-
#id = (initializeDeferredDecorator(this, "id"), void 0);
|
|
3615
|
-
}
|
|
3616
|
-
let driver = new Driver();
|
|
3617
|
-
class ResourceConsumer extends Component {
|
|
3618
|
-
resource = getCard(this, () => driver.id);
|
|
3619
|
-
get renderedCard() {
|
|
3620
|
-
return this.resource.card?.constructor.getComponent(this.resource.card);
|
|
3621
|
-
}
|
|
3622
|
-
static {
|
|
3623
|
-
setComponentTemplate(templateFactory({
|
|
3624
|
-
"id": "XWrL4bCI",
|
|
3625
|
-
"block": "[[[41,[30,0,[\"resource\",\"card\"]],[[[1,\" \"],[8,[30,0,[\"renderedCard\"]],[[16,\"data-test-rendered-card\",[30,0,[\"resource\",\"id\"]]]],null,null],[1,\"\\n\"]],[]],null]],[],[\"if\"]]",
|
|
3626
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3627
|
-
"isStrictMode": true
|
|
3628
|
-
}), this);
|
|
3629
|
-
}
|
|
3630
|
-
}
|
|
3631
|
-
await renderComponent(class TestDriver extends Component {
|
|
3632
|
-
static {
|
|
3633
|
-
setComponentTemplate(templateFactory({
|
|
3634
|
-
"id": "HtmuKyv7",
|
|
3635
|
-
"block": "[[[8,[32,0],null,null,null]],[],[]]",
|
|
3636
|
-
"moduleName": "/home/runner/work/boxel/boxel/packages/host/tests/integration/store-test.gts",
|
|
3637
|
-
"scope": () => [ResourceConsumer],
|
|
3638
|
-
"isStrictMode": true
|
|
3639
|
-
}), this);
|
|
3640
|
-
}
|
|
3641
|
-
});
|
|
3642
|
-
let jade = `${testRealmURL}Person/jade`;
|
|
3643
|
-
driver.id = jade;
|
|
3644
|
-
await waitFor(`[data-test-rendered-card="${jade}"]`, { timeout: 5e3 });
|
|
3645
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3646
|
-
let deferred = new Deferred();
|
|
3647
|
-
let unsubscribe = getService("message-service").subscribe(testRealmURL, (ev) => {
|
|
3648
|
-
if (ev.eventName === "index" && ev.indexType === "incremental") {
|
|
3649
|
-
unsubscribe();
|
|
3650
|
-
deferred.fulfill();
|
|
3651
|
-
}
|
|
3652
|
-
});
|
|
3653
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
3654
|
-
attributes: { name: "Paper" },
|
|
3655
|
-
meta: { adoptsFrom: {
|
|
3656
|
-
module: testRRI("person"),
|
|
3657
|
-
name: "Person"
|
|
3658
|
-
} }
|
|
3659
|
-
} }));
|
|
3660
|
-
await deferred.promise;
|
|
3661
|
-
deferred = new Deferred();
|
|
3662
|
-
await testRealm.write("Person/hassan.json", JSON.stringify({ data: {
|
|
3663
|
-
attributes: { name: "Paper" },
|
|
3664
|
-
meta: { adoptsFrom: {
|
|
3665
|
-
module: testRRI("person"),
|
|
3666
|
-
name: "Person"
|
|
3667
|
-
} }
|
|
3668
|
-
} }));
|
|
3669
|
-
assert.strictEqual(storeService.getReferenceCount(jade), 1, `reference count for ${jade} is 1`);
|
|
3670
|
-
});
|
|
3671
|
-
});
|
|
3672
|
-
//#endregion
|