diff --git a/packages/host/app/components/operator-mode/preview-panel/index.gts b/packages/host/app/components/operator-mode/preview-panel/index.gts index 5ad553f2113..c9b280b8222 100644 --- a/packages/host/app/components/operator-mode/preview-panel/index.gts +++ b/packages/host/app/components/operator-mode/preview-panel/index.gts @@ -26,6 +26,7 @@ import { isCardInstance, isFileDefInstance, isResolvedCodeRef, + rri, cardDefFormats, fileDefFormats, fieldDefFormats, @@ -133,10 +134,13 @@ export default class PreviewPanel extends Component { private editTemplate = () => { const type = identifyCard(this.args.card.constructor as any); if (type && isResolvedCodeRef(type)) { - const gtsFileUrl = type.module.endsWith('.gts') + // `identifyCard` reports a module in canonical form, which for a + // mapped realm is a prefix identifier rather than a URL — parsing it + // here would throw. `updateCodePath` resolves an identifier itself. + const gtsFile = type.module.endsWith('.gts') ? type.module : `${type.module}.gts`; - this.operatorModeStateService.updateCodePath(new URL(gtsFileUrl)); + this.operatorModeStateService.updateCodePath(rri(gtsFile)); } }; diff --git a/packages/host/tests/acceptance/code-submode-test.ts b/packages/host/tests/acceptance/code-submode-test.ts index 809e5266aa7..a9096d1d224 100644 --- a/packages/host/tests/acceptance/code-submode-test.ts +++ b/packages/host/tests/acceptance/code-submode-test.ts @@ -1,5 +1,6 @@ import { click, + find, waitFor, fillIn, triggerEvent, @@ -2911,5 +2912,40 @@ module('Acceptance | code submode tests', function (_hooks) { .dom('[data-test-card-url-bar-input]') .hasValue(`${testRealmURL}person.gts`); }); + + test('Edit Template opens the source of a card whose type lives in a mapped realm', async function (assert) { + // `person-entry` is a Spec, so its type resolves to the base realm — a + // prefix identifier rather than a URL. The button used to parse that + // module as a URL, which throws for any mapped realm, so the source + // never opened. + await visitOperatorMode({ + stacks: [ + [ + { + id: `${testRealmURL}person-entry`, + format: 'isolated', + }, + ], + ], + submode: 'code', + codePath: `${testRealmURL}person-entry.json`, + }); + + await waitFor('[data-test-card-resource-loaded]'); + await click('[data-test-edit-template-button]'); + + await waitFor('[data-test-card-url-bar-input]'); + let codePath = ( + find('[data-test-card-url-bar-input]') as HTMLInputElement + ).value; + assert.true( + codePath.endsWith('spec.gts'), + `the base realm's spec source opened (got ${codePath})`, + ); + assert.false( + codePath.startsWith('@'), + 'the identifier was resolved to a URL rather than passed through raw', + ); + }); }); });