diff --git a/packages/host/app/lib/browser-queue.ts b/packages/host/app/lib/browser-queue.ts index 7256de6c74..c1271aa603 100644 --- a/packages/host/app/lib/browser-queue.ts +++ b/packages/host/app/lib/browser-queue.ts @@ -79,7 +79,7 @@ export class BrowserQueue implements QueuePublisher, QueueRunner { private debouncedDrainJobs = debounce(() => { this.drainJobs(); - }, 250); + }, 1); private async drainJobs() { await this.flush(); diff --git a/packages/host/app/lib/sqlite-adapter.ts b/packages/host/app/lib/sqlite-adapter.ts index 54982ac51a..e611786a8f 100644 --- a/packages/host/app/lib/sqlite-adapter.ts +++ b/packages/host/app/lib/sqlite-adapter.ts @@ -18,6 +18,8 @@ export default class SQLiteAdapter implements DBAdapter { private _dbId: string | undefined; private primaryKeys = new Map(); private tables: string[] = []; + private snapshotCounter = 0; + private snapshotInfos = new Map(); #isClosed = false; private started = this.#startClient(); @@ -42,55 +44,7 @@ export default class SQLiteAdapter implements DBAdapter { }); this._sqlite = await waitForPromise(ready.promise, 'sqlite startup'); - let response = await this.sqlite('open', { - // It is possible to write to the local - // filesystem via Origin Private Filesystem, but it requires _very_ - // restrictive response headers that would cause our host app to break - // "Cross-Origin-Embedder-Policy: require-corp" - // "Cross-Origin-Opener-Policy: same-origin" - // https://webkit.org/blog/12257/the-file-system-access-api-with-origin-private-file-system/ - - // Otherwise, local storage and session storage are off limits to the - // worker (they are available in the synchronous interface), so only - // ephemeral memory storage is available - filename: ':memory:', - }); - const { dbId } = response; - this._dbId = dbId; - - if (this.schemaSQL) { - try { - await this.sqlite('exec', { - dbId: this.dbId, - sql: this.schemaSQL, - }); - } catch (e: any) { - console.error( - `Error executing SQL: ${e.result.message}\n${this.schemaSQL}`, - e, - ); - throw e; - } - - this.tables = ( - (await this.internalExecute( - `SELECT name FROM pragma_table_list WHERE schema = 'main' AND name != 'sqlite_schema'`, - )) as { name: string }[] - ).map((r) => r.name); - let pks = (await this.internalExecute( - ` - SELECT m.name AS table_name, - GROUP_CONCAT(p.name, ', ') AS primary_keys - FROM sqlite_master AS m - JOIN pragma_table_info(m.name) AS p ON m.type = 'table' - WHERE p.pk > 0 - GROUP BY m.name; - `, - )) as { table_name: string; primary_keys: string }[]; - for (let { table_name, primary_keys } of pks) { - this.primaryKeys.set(table_name, primary_keys); - } - } + await this.#openDatabase(':memory:', true); } async execute(sql: string, opts?: ExecuteOptions) { @@ -107,6 +61,9 @@ export default class SQLiteAdapter implements DBAdapter { async close() { this.assertNotClosed(); await this.started; + for (let snapshotName of Array.from(this.snapshotInfos.keys())) { + await this.deleteSnapshot(snapshotName); + } await this.sqlite('close', { dbId: this.dbId }); this.#isClosed = true; } @@ -209,6 +166,221 @@ export default class SQLiteAdapter implements DBAdapter { return results; } + async exportSnapshot(snapshotName?: string): Promise { + this.assertNotClosed(); + await this.started; + let alias = snapshotName ?? `snapshot_${++this.snapshotCounter}`; + if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(alias)) { + throw new Error( + `Snapshot name '${alias}' is invalid. Snapshot names must match /^[A-Za-z][A-Za-z0-9_]*$/.`, + ); + } + if (this.snapshotInfos.has(alias)) { + throw new Error(`Snapshot database '${alias}' already exists`); + } + let filename = `file:${alias}?mode=memory&cache=shared`; + let response = await this.sqlite('open', { + filename, + }); + this.snapshotInfos.set(alias, { filename, dbId: response.dbId }); + await this.sqlite('exec', { + dbId: this.dbId, + sql: `ATTACH DATABASE '${filename}' AS ${alias};`, + }); + let schemaEntries = (await this.internalExecute( + `SELECT name, sql + FROM sqlite_schema + WHERE type = 'table' + AND sql IS NOT NULL + AND name NOT LIKE 'sqlite_%' + ORDER BY name;`, + )) as { name: string; sql: string }[]; + for (let entry of schemaEntries) { + let rewritten = this.#rewriteSchemaSql(entry.sql, alias); + await this.sqlite('exec', { dbId: this.dbId, sql: rewritten }); + await this.sqlite('exec', { + dbId: this.dbId, + sql: `DELETE FROM ${alias}.${this.#quoteIdentifier(entry.name)};`, + }); + let columns = await this.getColumnNames(entry.name); + let copySql = this.#buildCopyIntoTableSql({ + destinationSchema: alias, + sourceSchema: 'main', + tableName: entry.name, + columns, + }); + try { + await this.sqlite('exec', { + dbId: this.dbId, + sql: copySql, + }); + } catch (e: any) { + console.error( + `Snapshot export failed while copying table '${entry.name}': ${ + e?.result?.message ?? e?.message ?? e + }\nSQL:\n${copySql}`, + e, + ); + throw e; + } + } + return alias; + } + + hasSnapshot(snapshotName: string): boolean { + return this.snapshotInfos.has(snapshotName); + } + + async deleteSnapshotsByPrefix(snapshotNamePrefix: string): Promise { + this.assertNotClosed(); + await this.started; + let snapshotNames = Array.from(this.snapshotInfos.keys()).filter((name) => + name.startsWith(snapshotNamePrefix), + ); + for (let snapshotName of snapshotNames) { + await this.deleteSnapshot(snapshotName); + } + } + + async deleteSnapshot(snapshotName: string): Promise { + this.assertNotClosed(); + await this.started; + let snapshotInfo = this.snapshotInfos.get(snapshotName); + if (!snapshotInfo) { + return; + } + + let attached = (await this.internalExecute( + 'SELECT name FROM pragma_database_list WHERE name = $1;', + { bind: [snapshotName] }, + )) as { name: string }[]; + + if (attached.length) { + await this.sqlite('exec', { + dbId: this.dbId, + sql: `DETACH DATABASE ${this.#quoteIdentifier(snapshotName)};`, + }); + } + + await this.sqlite('close', { + dbId: snapshotInfo.dbId, + }); + this.snapshotInfos.delete(snapshotName); + } + + async importSnapshot(snapshotName: string) { + this.assertNotClosed(); + await this.started; + let snapshotInfo = this.snapshotInfos.get(snapshotName); + if (!snapshotInfo) { + throw new Error(`Unknown snapshot database '${snapshotName}'`); + } + let attached = (await this.internalExecute( + `SELECT name FROM pragma_database_list WHERE name = '${snapshotName}'`, + )) as { name: string }[]; + if (!attached.length) { + await this.sqlite('exec', { + dbId: this.dbId, + sql: `ATTACH DATABASE '${snapshotInfo.filename}' AS ${snapshotName};`, + }); + } + let tables = (await this.internalExecute( + `SELECT name + FROM ${snapshotName}.sqlite_schema + WHERE type = 'table' + AND name NOT LIKE 'sqlite_%';`, + )) as { name: string }[]; + let tableNames = tables.map((t) => t.name); + let columnsByTable = await this.#getWritableColumnsByTable(tableNames); + let statements: string[] = ['BEGIN IMMEDIATE;']; + for (let tableName of tableNames) { + let columns = columnsByTable.get(tableName); + if (!columns?.length) { + columns = await this.getColumnNames(tableName); + } + statements.push( + `DELETE FROM main.${this.#quoteIdentifier(tableName)};`, + this.#buildCopyIntoTableSql({ + destinationSchema: 'main', + sourceSchema: snapshotName, + tableName, + columns, + }), + ); + } + statements.push('COMMIT;'); + try { + await this.sqlite('exec', { + dbId: this.dbId, + sql: statements.join('\n'), + }); + } catch (e: any) { + // Ensure we don't leave an open transaction after a failed batched import. + try { + await this.sqlite('exec', { dbId: this.dbId, sql: 'ROLLBACK;' }); + } catch (_rollbackError) { + // noop + } + console.error( + `Snapshot import failed while executing batched restore: ${ + e?.result?.message ?? e?.message ?? e + }`, + e, + ); + throw e; + } + } + + async #openDatabase(filename: string, initializeSchema = true) { + // It is possible to write to the local + // filesystem via Origin Private Filesystem, but it requires _very_ + // restrictive response headers that would cause our host app to break + // so we always stick to in-memory files to keep behavior deterministic. + let response = await this.sqlite('open', { + filename, + }); + const { dbId } = response; + this._dbId = dbId; + + if (initializeSchema && this.schemaSQL) { + try { + await this.sqlite('exec', { + dbId: this.dbId, + sql: this.schemaSQL, + }); + } catch (e: any) { + console.error( + `Error executing SQL: ${e.result.message}\n${this.schemaSQL}`, + e, + ); + throw e; + } + } + + await this.#loadSchemaMetadata(); + } + + async #loadSchemaMetadata() { + let tables = (await this.internalExecute( + `SELECT name FROM pragma_table_list WHERE schema = 'main' AND name != 'sqlite_schema'`, + )) as { name: string }[]; + this.tables = tables.map((r) => r.name); + let pks = (await this.internalExecute( + ` + SELECT m.name AS table_name, + GROUP_CONCAT(p.name, ', ') AS primary_keys + FROM sqlite_master AS m + JOIN pragma_table_info(m.name) AS p ON m.type = 'table' + WHERE p.pk > 0 + GROUP BY m.name; + `, + )) as { table_name: string; primary_keys: string }[]; + this.primaryKeys.clear(); + for (let { table_name, primary_keys } of pks) { + this.primaryKeys.set(table_name, primary_keys); + } + } + private adjustSQL(sql: string): string { return sql .replace(/ON CONFLICT ON CONSTRAINT (\w*)\b/, (_, constraint) => { @@ -227,16 +399,12 @@ export default class SQLiteAdapter implements DBAdapter { .replace(/ILIKE/g, 'LIKE') // sqlite LIKE is case insensitive .replace(/jsonb_array_elements_text\(/g, 'json_each(') .replace(/jsonb_tree\(/g, 'json_tree(') - .replace( - /\b([A-Za-z0-9_]+)_array_element\b/g, - (match, _alias, offset, sql) => { - let preceding = sql.slice(0, offset); - if (/as\s+$/i.test(preceding)) { - return match; - } - return `${match}.value`; - }, - ) + .replace(/([^\s]+\s[^\s]+)_array_element/g, (match, group) => { + if (group.startsWith('as ')) { + return match; + } + return `${match}.value`; + }) .replace(/\.text_value/g, '.value') .replace(/\.jsonb_value/g, '.value') .replace(/= 'null'::jsonb/g, 'IS NULL') @@ -252,6 +420,60 @@ export default class SQLiteAdapter implements DBAdapter { ); } } + + #quoteIdentifier(identifier: string) { + return `"${identifier.replace(/"/g, '""')}"`; + } + + #rewriteSchemaSql(sql: string, schema: string) { + return sql.replace( + /^(CREATE\s+(?:TEMP\s+)?TABLE(?:\s+IF\s+NOT\s+EXISTS)?)\s+/i, + (match) => `${match} ${schema}.`, + ); + } + + #buildCopyIntoTableSql({ + destinationSchema, + sourceSchema, + tableName, + columns, + }: { + destinationSchema: string; + sourceSchema: string; + tableName: string; + columns: string[]; + }) { + let quotedColumns = columns.map((c) => this.#quoteIdentifier(c)).join(', '); + return `INSERT INTO ${destinationSchema}.${this.#quoteIdentifier(tableName)} (${quotedColumns}) + SELECT ${quotedColumns} FROM ${sourceSchema}.${this.#quoteIdentifier(tableName)};`; + } + + async #getWritableColumnsByTable(tableNames: string[]) { + if (!tableNames.length) { + return new Map(); + } + let tableNamesSql = tableNames + .map((name) => `'${name.replace(/'/g, "''")}'`) + .join(', '); + let rows = (await this.internalExecute(` + SELECT m.name AS table_name, p.name AS column_name + FROM main.sqlite_schema AS m + JOIN pragma_table_info(m.name) AS p + WHERE m.type = 'table' + AND m.name IN (${tableNamesSql}) + ORDER BY m.name, p.cid; + `)) as { table_name: string; column_name: string }[]; + let map = new Map(); + for (let { table_name, column_name } of rows) { + let columns = map.get(table_name); + if (!columns) { + columns = []; + map.set(table_name, columns); + } + columns.push(column_name); + } + return map; + } } function assertNever(value: never) { diff --git a/packages/host/tests/acceptance/code-patches-test.gts b/packages/host/tests/acceptance/code-patches-test.gts index 738a60f805..7e31a641e4 100644 --- a/packages/host/tests/acceptance/code-patches-test.gts +++ b/packages/host/tests/acceptance/code-patches-test.gts @@ -23,6 +23,7 @@ import { import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, @@ -30,6 +31,7 @@ import { setupAuthEndpoints, setupUserSubscription, getMonacoContent, + withCachedRealmSetup, } from '../helpers'; import { CardsGrid, setupBaseRealm } from '../helpers/base-realm'; @@ -66,6 +68,7 @@ module('Acceptance | Code patches tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -93,60 +96,62 @@ module('Acceptance | Code patches tests', function (hooks) { setupUserSubscription(); setupAuthEndpoints(); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.json': new CardsGrid(), - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - 'hello.txt': 'Hello, world!', - 'hi.txt': 'Hi, world!\nHow are you?', - 'empty-file.gts': '', - 'test-card.gts': testCardContent, - 'Skill/useful-commands.json': { - data: { - type: 'card', - attributes: { - instructions: - 'Here are few commands you might find useful: * switch-submode: use this with "code" to go to code mode and "interact" to go to interact mode. * search-cards-by-type-and-title: search for cards by name or description.', - commands: [ - { - codeRef: { - name: 'SearchCardsByTypeAndTitleCommand', - module: '@cardstack/boxel-host/commands/search-cards', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.json': new CardsGrid(), + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, + 'hello.txt': 'Hello, world!', + 'hi.txt': 'Hi, world!\nHow are you?', + 'empty-file.gts': '', + 'test-card.gts': testCardContent, + 'Skill/useful-commands.json': { + data: { + type: 'card', + attributes: { + instructions: + 'Here are few commands you might find useful: * switch-submode: use this with "code" to go to code mode and "interact" to go to interact mode. * search-cards-by-type-and-title: search for cards by name or description.', + commands: [ + { + codeRef: { + name: 'SearchCardsByTypeAndTitleCommand', + module: '@cardstack/boxel-host/commands/search-cards', + }, + requiresApproval: true, }, - requiresApproval: true, - }, - { - codeRef: { - name: 'default', - module: '@cardstack/boxel-host/commands/switch-submode', + { + codeRef: { + name: 'default', + module: '@cardstack/boxel-host/commands/switch-submode', + }, + requiresApproval: true, }, - requiresApproval: true, - }, - { - codeRef: { - name: 'default', - module: '@cardstack/boxel-host/commands/show-card', + { + codeRef: { + name: 'default', + module: '@cardstack/boxel-host/commands/show-card', + }, + requiresApproval: true, }, - requiresApproval: true, - }, - ], - cardTitle: 'Useful Commands', - cardDescription: null, - cardThumbnailURL: null, - }, - meta: { - adoptsFrom: skillCardRef, + ], + cardTitle: 'Useful Commands', + cardDescription: null, + cardThumbnailURL: null, + }, + meta: { + adoptsFrom: skillCardRef, + }, }, }, }, - }, + }); }); }); diff --git a/packages/host/tests/acceptance/code-submode-test.ts b/packages/host/tests/acceptance/code-submode-test.ts index 2c4cada5cf..f345e0064f 100644 --- a/packages/host/tests/acceptance/code-submode-test.ts +++ b/packages/host/tests/acceptance/code-submode-test.ts @@ -35,6 +35,7 @@ import { import { getMonacoContent, percySnapshot, + setupRealmCacheTeardown, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, setMonacoContent, @@ -44,6 +45,7 @@ import { setupAuthEndpoints, setupUserSubscription, assertMessages, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { @@ -428,6 +430,7 @@ module('Acceptance | code submode tests', function (_hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -460,53 +463,67 @@ module('Acceptance | code submode tests', function (_hooks) { catalogRealmURL = `${realmServerService.url}catalog/`; setActiveRealms([catalogRealmURL, additionalRealmURL, personalRealmURL]); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: personalRealmURL, - permissions: { - '@testuser:localhost': ['read', 'write', 'realm-owner'], - }, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'hello.txt': txtSource, - '.realm.json': { - name: `Test User's Workspace`, - backgroundURL: 'https://i.postimg.cc/NjcjbyD3/4k-origami-flock.jpg', - iconURL: 'https://i.postimg.cc/Rq550Bwv/T.png', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: personalRealmURL, + permissions: { + '@testuser:localhost': ['read', 'write', 'realm-owner'], }, - }, - }); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: additionalRealmURL, - permissions: { - '@testuser:localhost': ['read', 'write', 'realm-owner'], - }, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'hello.txt': txtSource, - '.realm.json': { - name: `Additional Workspace`, - backgroundURL: 'https://i.postimg.cc/4ycXQZ94/4k-powder-puff.jpg', - iconURL: 'https://i.postimg.cc/BZwv0LyC/A.png', + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'hello.txt': txtSource, + '.realm.json': { + name: `Test User's Workspace`, + backgroundURL: + 'https://i.postimg.cc/NjcjbyD3/4k-origami-flock.jpg', + iconURL: 'https://i.postimg.cc/Rq550Bwv/T.png', + }, }, - }, - }); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: catalogRealmURL, - permissions: { - '*': ['read'], - }, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'hello.txt': txtSource, - '.realm.json': { - name: `Catalog Realm`, - backgroundURL: 'https://i.postimg.cc/zXsXLmqb/C.png', - iconURL: 'https://i.postimg.cc/qv4pyPM0/4k-watercolor-splashes.jpg', + }); + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: additionalRealmURL, + permissions: { + '@testuser:localhost': ['read', 'write', 'realm-owner'], }, - }, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'hello.txt': txtSource, + '.realm.json': { + name: `Additional Workspace`, + backgroundURL: 'https://i.postimg.cc/4ycXQZ94/4k-powder-puff.jpg', + iconURL: 'https://i.postimg.cc/BZwv0LyC/A.png', + }, + }, + }); + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: catalogRealmURL, + permissions: { + '*': ['read'], + }, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'hello.txt': txtSource, + '.realm.json': { + name: `Catalog Realm`, + backgroundURL: 'https://i.postimg.cc/zXsXLmqb/C.png', + iconURL: + 'https://i.postimg.cc/qv4pyPM0/4k-watercolor-splashes.jpg', + }, + }, + }); + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + permissions: { + '@testuser:localhost': ['read', 'write', 'realm-owner'], + }, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + }, + }); }); setupAuthEndpoints({ @@ -514,16 +531,6 @@ module('Acceptance | code submode tests', function (_hooks) { [additionalRealmURL]: ['read', 'write', 'realm-owner'], [personalRealmURL]: ['read', 'write', 'realm-owner'], }); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - permissions: { - '@testuser:localhost': ['read', 'write', 'realm-owner'], - }, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - }, - }); }); test('default realm is the personal realm', async function (assert) { @@ -569,6 +576,7 @@ module('Acceptance | code submode tests', function (_hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -589,273 +597,275 @@ module('Acceptance | code submode tests', function (_hooks) { // this seeds the loader used during index which obtains url mappings // from the global loader - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.gts': indexCardSource, - 'pet-person.gts': personCardSource, - 'person.gts': personCardSource, - 'pet.gts': petCardSource, - 'friend.gts': friendCardSource, - 'employee.gts': employeeCardSource, - 'in-this-file.gts': inThisFileSource, - 'postal-code.gts': postalCodeFieldSource, - 'address.gts': addressFieldSource, - 'country.gts': countryCardSource, - 'trips.gts': tripsFieldSource, - 'broken.gts': brokenSource, - 'broken-country.gts': brokenCountryCardSource, - 'broken-adoption-instance.json': brokenAdoptionInstance, - 'not-found-adoption-instance.json': notFoundAdoptionInstance, - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.gts': indexCardSource, + 'pet-person.gts': personCardSource, + 'person.gts': personCardSource, + 'pet.gts': petCardSource, + 'friend.gts': friendCardSource, + 'employee.gts': employeeCardSource, + 'in-this-file.gts': inThisFileSource, + 'postal-code.gts': postalCodeFieldSource, + 'address.gts': addressFieldSource, + 'country.gts': countryCardSource, + 'trips.gts': tripsFieldSource, + 'broken.gts': brokenSource, + 'broken-country.gts': brokenCountryCardSource, + 'broken-adoption-instance.json': brokenAdoptionInstance, + 'not-found-adoption-instance.json': notFoundAdoptionInstance, + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'pet-entry.json': { - data: { - type: 'card', - attributes: { - specType: 'card', - ref: { - module: `./pet`, - name: 'Pet', + 'pet-entry.json': { + data: { + type: 'card', + attributes: { + specType: 'card', + ref: { + module: `./pet`, + name: 'Pet', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'pet-entry-2.json': { - data: { - type: 'card', - attributes: { - specType: 'card', - ref: { - module: `./pet`, - name: 'Pet', + 'pet-entry-2.json': { + data: { + type: 'card', + attributes: { + specType: 'card', + ref: { + module: `./pet`, + name: 'Pet', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'index.json': { - data: { - type: 'card', - attributes: {}, - meta: { - adoptsFrom: { - module: './index', - name: 'Index', + 'index.json': { + data: { + type: 'card', + attributes: {}, + meta: { + adoptsFrom: { + module: './index', + name: 'Index', + }, }, }, }, - }, - 'not-json.json': 'I am not JSON.', - 'Person/fadhlan.json': { - data: { - attributes: { - firstName: 'Fadhlan', - address: [ - { - city: 'Bandung', - country: 'Indonesia', - shippingInfo: { - preferredCarrier: 'DHL', - remarks: `Don't let bob deliver the package--he's always bringing it to the wrong address`, + 'not-json.json': 'I am not JSON.', + 'Person/fadhlan.json': { + data: { + attributes: { + firstName: 'Fadhlan', + address: [ + { + city: 'Bandung', + country: 'Indonesia', + shippingInfo: { + preferredCarrier: 'DHL', + remarks: `Don't let bob deliver the package--he's always bringing it to the wrong address`, + }, + }, + ], + }, + relationships: { + pet: { + links: { + self: `${testRealmURL}Pet/mango`, }, - }, - ], - }, - relationships: { - pet: { - links: { - self: `${testRealmURL}Pet/mango`, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Person', + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Person', + }, }, }, }, - }, - 'Person/1.json': { - data: { - type: 'card', - attributes: { - firstName: 'Hassan', - lastName: 'Abdel-Rahman', - }, - meta: { - adoptsFrom: { - module: '../person', - name: 'Person', + 'Person/1.json': { + data: { + type: 'card', + attributes: { + firstName: 'Hassan', + lastName: 'Abdel-Rahman', + }, + meta: { + adoptsFrom: { + module: '../person', + name: 'Person', + }, }, }, }, - }, - 'Pet/mango.json': { - data: { - attributes: { - name: 'Mango', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/mango.json': { + data: { + attributes: { + name: 'Mango', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'Friend/amy.json': { - data: { - attributes: { - name: 'Amy', - }, - relationships: { - friend: { - links: { - self: `${testRealmURL}Friend/bob`, + 'Friend/amy.json': { + data: { + attributes: { + name: 'Amy', + }, + relationships: { + friend: { + links: { + self: `${testRealmURL}Friend/bob`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}friend`, - name: 'Friend', + meta: { + adoptsFrom: { + module: `${testRealmURL}friend`, + name: 'Friend', + }, }, }, }, - }, - 'Friend/bob.json': { - data: { - attributes: { - name: 'Bob', - }, - relationships: {}, - meta: { - adoptsFrom: { - module: `${testRealmURL}friend`, - name: 'Friend', + 'Friend/bob.json': { + data: { + attributes: { + name: 'Bob', + }, + relationships: {}, + meta: { + adoptsFrom: { + module: `${testRealmURL}friend`, + name: 'Friend', + }, }, }, }, - }, - 'Person/with-friends.json': { - data: { - attributes: { - firstName: 'With', - lastName: 'Friends', - }, - relationships: { - 'friends.0': { - links: { - self: `${testRealmURL}Friend/amy`, - }, + 'Person/with-friends.json': { + data: { + attributes: { + firstName: 'With', + lastName: 'Friends', }, - 'friends.1': { - links: { - self: `${testRealmURL}Friend/bob`, + relationships: { + 'friends.0': { + links: { + self: `${testRealmURL}Friend/amy`, + }, + }, + 'friends.1': { + links: { + self: `${testRealmURL}Friend/bob`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Person', + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Person', + }, }, }, }, - }, - 'Country/united-states.json': { - data: { - type: 'card', - attributes: { - name: 'United States', - cardDescription: null, - cardThumbnailURL: null, - }, - meta: { - adoptsFrom: { - module: '../country', - name: 'Country', + 'Country/united-states.json': { + data: { + type: 'card', + attributes: { + name: 'United States', + cardDescription: null, + cardThumbnailURL: null, + }, + meta: { + adoptsFrom: { + module: '../country', + name: 'Country', + }, }, }, }, - }, - 'BrokenCountry/broken-country.json': { - data: { - type: 'card', - attributes: { - name: 'Broken Country', - }, - meta: { - adoptsFrom: { - module: '../broken-country', - name: 'Country', + 'BrokenCountry/broken-country.json': { + data: { + type: 'card', + attributes: { + name: 'Broken Country', + }, + meta: { + adoptsFrom: { + module: '../broken-country', + name: 'Country', + }, }, }, }, + 'hello.txt': txtSource, + 'z00.json': '{}', + 'z01.json': '{}', + 'z02.json': '{}', + 'z03.json': '{}', + 'z04.json': '{}', + 'z05.json': '{}', + 'z06.json': '{}', + 'z07.json': '{}', + 'z08.json': '{}', + 'z09.json': '{}', + 'z10.json': '{}', + 'z11.json': '{}', + 'z12.json': '{}', + 'z13.json': '{}', + 'z14.json': '{}', + 'z15.json': '{}', + 'z16.json': '{}', + 'z17.json': '{}', + 'z18.json': '{}', + 'z19.json': '{}', + 'zzz/zzz/file.json': '{}', + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, + 'noop.gts': `export function noop() {};\nclass NoopClass {}`, }, - 'hello.txt': txtSource, - 'z00.json': '{}', - 'z01.json': '{}', - 'z02.json': '{}', - 'z03.json': '{}', - 'z04.json': '{}', - 'z05.json': '{}', - 'z06.json': '{}', - 'z07.json': '{}', - 'z08.json': '{}', - 'z09.json': '{}', - 'z10.json': '{}', - 'z11.json': '{}', - 'z12.json': '{}', - 'z13.json': '{}', - 'z14.json': '{}', - 'z15.json': '{}', - 'z16.json': '{}', - 'z17.json': '{}', - 'z18.json': '{}', - 'z19.json': '{}', - 'zzz/zzz/file.json': '{}', - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - 'noop.gts': `export function noop() {};\nclass NoopClass {}`, - }, - })); + }), + )); }); test('defaults to inheritance view and can toggle to file view', async function (assert) { diff --git a/packages/host/tests/acceptance/code-submode/card-playground-test.gts b/packages/host/tests/acceptance/code-submode/card-playground-test.gts index c952f068c2..e7e9a6df32 100644 --- a/packages/host/tests/acceptance/code-submode/card-playground-test.gts +++ b/packages/host/tests/acceptance/code-submode/card-playground-test.gts @@ -26,6 +26,7 @@ import { setupAcceptanceTestRealm, setupAuthEndpoints, setupLocalIndexing, + setupRealmCacheTeardown, setMonacoContent, setupOnSave, setupUserSubscription, @@ -35,6 +36,7 @@ import { withoutLoaderMonitoring, type TestContextWithSave, assertMessages, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { @@ -224,6 +226,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { mockMatrixUtils; setupOnSave(hooks); + setupRealmCacheTeardown(hooks); hooks.beforeEach(async function () { let loader = getService('loader-service').loader; @@ -238,177 +241,179 @@ module('Acceptance | code-submode | card playground', function (_hooks) { setupUserSubscription(); setupAuthEndpoints(); - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.json': new CardsGrid(), - 'author.gts': authorCard, - 'blog-post.gts': blogPostCard, - 'code-ref-driver.gts': codeRefDriverCard, - 'test-spec.gts': testSpecCard, - 'person.gts': personCard, - 'head-preview.gts': headPreviewCard, - 'Author/jane-doe.json': { - data: { - attributes: { - firstName: 'Jane', - lastName: 'Doe', - bio: "Jane Doe is the Senior Managing Editor at Ramped.com, where she leads content strategy, editorial direction, and ensures the highest standards of quality across all publications. With over a decade of experience in digital media and editorial management, Jane has a proven track record of shaping impactful narratives, growing engaged audiences, and collaborating with cross-functional teams to deliver compelling content. When she's not editing, you can find her exploring new books, hiking, or indulging in her love of photography.", - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}author`, - name: 'Author', + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.json': new CardsGrid(), + 'author.gts': authorCard, + 'blog-post.gts': blogPostCard, + 'code-ref-driver.gts': codeRefDriverCard, + 'test-spec.gts': testSpecCard, + 'person.gts': personCard, + 'head-preview.gts': headPreviewCard, + 'Author/jane-doe.json': { + data: { + attributes: { + firstName: 'Jane', + lastName: 'Doe', + bio: "Jane Doe is the Senior Managing Editor at Ramped.com, where she leads content strategy, editorial direction, and ensures the highest standards of quality across all publications. With over a decade of experience in digital media and editorial management, Jane has a proven track record of shaping impactful narratives, growing engaged audiences, and collaborating with cross-functional teams to deliver compelling content. When she's not editing, you can find her exploring new books, hiking, or indulging in her love of photography.", + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}author`, + name: 'Author', + }, }, }, }, - }, - 'HeadPreview/example.json': { - data: { - attributes: { - cardTitle: 'Definition Title', - cardDescription: 'Definition description', - url: 'https://example.com/definition', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}head-preview`, - name: 'HeadPreview', + 'HeadPreview/example.json': { + data: { + attributes: { + cardTitle: 'Definition Title', + cardDescription: 'Definition description', + url: 'https://example.com/definition', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}head-preview`, + name: 'HeadPreview', + }, }, }, }, - }, - 'BlogPost/remote-work.json': { - data: { - attributes: { - title: 'The Ultimate Guide to Remote Work', - cardDescription: - 'In today’s digital age, remote work has transformed from a luxury to a necessity. This comprehensive guide will help you navigate the world of remote work, offering tips, tools, and best practices for success.', - }, - relationships: { - author: { - links: { - self: `${testRealmURL}Author/jane-doe`, + 'BlogPost/remote-work.json': { + data: { + attributes: { + title: 'The Ultimate Guide to Remote Work', + cardDescription: + 'In today’s digital age, remote work has transformed from a luxury to a necessity. This comprehensive guide will help you navigate the world of remote work, offering tips, tools, and best practices for success.', + }, + relationships: { + author: { + links: { + self: `${testRealmURL}Author/jane-doe`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'BlogPost', + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'BlogPost', + }, }, }, }, - }, - 'BlogPost/mad-hatter.json': { - data: { - attributes: { cardTitle: 'Mad As a Hatter' }, - relationships: { - author: { - links: { - self: `${testRealmURL}Author/jane-doe`, + 'BlogPost/mad-hatter.json': { + data: { + attributes: { cardTitle: 'Mad As a Hatter' }, + relationships: { + author: { + links: { + self: `${testRealmURL}Author/jane-doe`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'BlogPost', + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'BlogPost', + }, }, }, }, - }, - 'BlogPost/urban-living.json': { - data: { - attributes: { - cardTitle: - 'The Future of Urban Living: Skyscrapers or Sustainable Communities?', - }, - relationships: { - author: { - links: { - self: `${testRealmURL}Author/jane-doe`, + 'BlogPost/urban-living.json': { + data: { + attributes: { + cardTitle: + 'The Future of Urban Living: Skyscrapers or Sustainable Communities?', + }, + relationships: { + author: { + links: { + self: `${testRealmURL}Author/jane-doe`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'BlogPost', + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'BlogPost', + }, }, }, }, - }, - 'Category/city-design.json': { - data: { - attributes: { cardInfo: { name: 'City Design' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'Category', + 'Category/city-design.json': { + data: { + attributes: { cardInfo: { name: 'City Design' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'Category', + }, }, }, }, - }, - 'Category/future-tech.json': { - data: { - attributes: { cardInfo: { name: 'Future Tech' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'Category', + 'Category/future-tech.json': { + data: { + attributes: { cardInfo: { name: 'Future Tech' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'Category', + }, }, }, }, - }, - 'Category/interior-design.json': { - data: { - attributes: { cardInfo: { name: 'Interior Design' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'Category', + 'Category/interior-design.json': { + data: { + attributes: { cardInfo: { name: 'Interior Design' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'Category', + }, }, }, }, - }, - 'Category/landscaping.json': { - data: { - attributes: { cardInfo: { name: 'Landscaping' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'Category', + 'Category/landscaping.json': { + data: { + attributes: { cardInfo: { name: 'Landscaping' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'Category', + }, }, }, }, - }, - 'Category/home-gym.json': { - data: { - attributes: { cardInfo: { name: 'Home Gym' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'Category', + 'Category/home-gym.json': { + data: { + attributes: { cardInfo: { name: 'Home Gym' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'Category', + }, }, }, }, - }, - 'Person/pet-mango.json': { - data: { - attributes: { cardInfo: { name: 'Mango' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Pet', + 'Person/pet-mango.json': { + data: { + attributes: { cardInfo: { name: 'Mango' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Pet', + }, }, }, }, }, - }, - })); + }), + )); setRecentFiles([ [testRealmURL, 'blog-post.gts'], @@ -1513,6 +1518,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { let { setActiveRealms, setRealmPermissions, createAndJoinRoom } = mockMatrixUtils; + setupRealmCacheTeardown(hooks); hooks.beforeEach(async function () { createAndJoinRoom({ @@ -1527,33 +1533,36 @@ module('Acceptance | code-submode | card playground', function (_hooks) { additionalRealmURL = `${realmServerService.url}testuser/aaa/`; // writeable realm that is lexically before the personal realm setActiveRealms([additionalRealmURL, personalRealmURL]); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: personalRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'author-card.gts': authorCard, - 'StyleReference/local-style.json': localStyleReferenceCard, - '.realm.json': { - name: `Test User's Workspace`, - backgroundURL: 'https://i.postimg.cc/NjcjbyD3/4k-origami-flock.jpg', - iconURL: 'https://i.postimg.cc/Rq550Bwv/T.png', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: personalRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'author-card.gts': authorCard, + 'StyleReference/local-style.json': localStyleReferenceCard, + '.realm.json': { + name: `Test User's Workspace`, + backgroundURL: + 'https://i.postimg.cc/NjcjbyD3/4k-origami-flock.jpg', + iconURL: 'https://i.postimg.cc/Rq550Bwv/T.png', + }, }, - }, - }); - - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: additionalRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'author-card.gts': authorCard, - '.realm.json': { - name: `Additional Workspace`, - backgroundURL: 'https://i.postimg.cc/4ycXQZ94/4k-powder-puff.jpg', - iconURL: 'https://i.postimg.cc/BZwv0LyC/A.png', + }); + + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: additionalRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'author-card.gts': authorCard, + '.realm.json': { + name: `Additional Workspace`, + backgroundURL: 'https://i.postimg.cc/4ycXQZ94/4k-powder-puff.jpg', + iconURL: 'https://i.postimg.cc/BZwv0LyC/A.png', + }, }, - }, + }); }); setRealmPermissions({ @@ -1655,6 +1664,7 @@ module('Acceptance | code-submode | card playground', function (_hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -1734,28 +1744,30 @@ module('Acceptance | code-submode | card playground', function (_hooks) { setRealmPermissions({ [testRealmURL]: ['read', 'write'], }); - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'boom-pet.gts': boomPet, - 'person.gts': personCard, - 'boom-person.gts': boomPerson, - 'syntax-error.gts': syntaxError, - 'Person/delilah.json': { - data: { - attributes: { cardInfo: { name: 'Delilah' } }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Person', + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'boom-pet.gts': boomPet, + 'person.gts': personCard, + 'boom-person.gts': boomPerson, + 'syntax-error.gts': syntaxError, + 'Person/delilah.json': { + data: { + attributes: { cardInfo: { name: 'Delilah' } }, + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Person', + }, }, }, }, }, - }, - })); + }), + )); }); test('it renders a module error', async function (assert) { diff --git a/packages/host/tests/acceptance/code-submode/create-file-test.gts b/packages/host/tests/acceptance/code-submode/create-file-test.gts index 685cc73461..5f9cdebebb 100644 --- a/packages/host/tests/acceptance/code-submode/create-file-test.gts +++ b/packages/host/tests/acceptance/code-submode/create-file-test.gts @@ -4,16 +4,18 @@ import { getService } from '@universal-ember/test-support'; import { module, test } from 'qunit'; import { baseRealm, Deferred } from '@cardstack/runtime-common'; - +import { Loader } from '@cardstack/runtime-common'; import { percySnapshot, setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupOnSave, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, getMonacoContent, visitOperatorMode as _visitOperatorMode, + withCachedRealmSetup, type TestContextWithSave, setupAuthEndpoints, setupUserSubscription, @@ -200,6 +202,7 @@ module('Acceptance | code submode | create-file tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -209,14 +212,16 @@ module('Acceptance | code submode | create-file tests', function (hooks) { let { setRealmPermissions, createAndJoinRoom } = mockMatrixUtils; hooks.beforeEach(async function () { - await setupAcceptanceTestRealm({ - contents: { ...SYSTEM_CARD_FIXTURE_CONTENTS, ...filesB }, - realmURL: testRealmURL2, - mockMatrixUtils, - }); - ({ adapter } = await setupAcceptanceTestRealm({ - contents: { ...SYSTEM_CARD_FIXTURE_CONTENTS, ...files }, - mockMatrixUtils, + ({ adapter } = await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + contents: { ...SYSTEM_CARD_FIXTURE_CONTENTS, ...filesB }, + realmURL: testRealmURL2, + mockMatrixUtils, + }); + return await setupAcceptanceTestRealm({ + contents: { ...SYSTEM_CARD_FIXTURE_CONTENTS, ...files }, + mockMatrixUtils, + }); })); createAndJoinRoom({ diff --git a/packages/host/tests/acceptance/code-submode/editor-test.ts b/packages/host/tests/acceptance/code-submode/editor-test.ts index dec46d6c90..f02bd7ac3a 100644 --- a/packages/host/tests/acceptance/code-submode/editor-test.ts +++ b/packages/host/tests/acceptance/code-submode/editor-test.ts @@ -21,6 +21,7 @@ import { RecentFiles } from '@cardstack/host/utils/local-storage-keys'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, getMonacoContent, setMonacoContent, @@ -30,6 +31,7 @@ import { setupAuthEndpoints, setupUserSubscription, withSlowSave, + withCachedRealmSetup, type TestContextWithSave, } from '../../helpers'; @@ -45,6 +47,7 @@ module('Acceptance | code submode | editor tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', activeRealms: [baseRealm.url, testRealmURL], @@ -69,11 +72,12 @@ module('Acceptance | code submode | editor tests', function (hooks) { JSON.stringify([[testRealmURL, 'Pet/mango.json']]), ); - ({ adapter } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'pet.gts': ` + ({ adapter } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'pet.gts': ` import { contains, field, Component, CardDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; @@ -94,7 +98,7 @@ module('Acceptance | code submode | editor tests', function (hooks) { } } `, - 'shipping-info.gts': ` + 'shipping-info.gts': ` import { contains, field, Component, FieldDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; export class ShippingInfo extends FieldDef { @@ -114,7 +118,7 @@ module('Acceptance | code submode | editor tests', function (hooks) { } } `, - 'address.gts': ` + 'address.gts': ` import { contains, field, Component, FieldDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; import { ShippingInfo } from "./shipping-info"; @@ -150,7 +154,7 @@ module('Acceptance | code submode | editor tests', function (hooks) { }; } `, - 'person.gts': ` + 'person.gts': ` import { contains, linksTo, field, Component, CardDef, linksToMany } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; import { Pet } from "./pet"; @@ -187,120 +191,121 @@ module('Acceptance | code submode | editor tests', function (hooks) { } } `, - 'README.txt': `Hello World`, - 'Pet/mango.json': { - data: { - attributes: { - name: 'Mango', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'README.txt': `Hello World`, + 'Pet/mango.json': { + data: { + attributes: { + name: 'Mango', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'Pet/vangogh.json': { - data: { - attributes: { - name: 'Van Gogh', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/vangogh.json': { + data: { + attributes: { + name: 'Van Gogh', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'Person/fadhlan.json': { - data: { - attributes: { - firstName: 'Fadhlan', - address: { - city: 'Bandung', - country: 'Indonesia', - shippingInfo: { - preferredCarrier: 'DHL', - remarks: `Don't let bob deliver the package--he's always bringing it to the wrong address`, + 'Person/fadhlan.json': { + data: { + attributes: { + firstName: 'Fadhlan', + address: { + city: 'Bandung', + country: 'Indonesia', + shippingInfo: { + preferredCarrier: 'DHL', + remarks: `Don't let bob deliver the package--he's always bringing it to the wrong address`, + }, }, }, - }, - relationships: { - pet: { - links: { - self: `${testRealmURL}Pet/mango`, + relationships: { + pet: { + links: { + self: `${testRealmURL}Pet/mango`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Person', + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Person', + }, }, }, }, - }, - 'index.json': { - data: { - type: 'card', - attributes: {}, - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/cards-grid', - name: 'CardsGrid', + 'index.json': { + data: { + type: 'card', + attributes: {}, + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/cards-grid', + name: 'CardsGrid', + }, }, }, }, - }, - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - 'Person/john-with-bad-pet-link.json': { - data: { - attributes: { - firstName: 'John', - address: { - city: 'Ljubljana', - country: 'Slovenia', + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, + 'Person/john-with-bad-pet-link.json': { + data: { + attributes: { + firstName: 'John', + address: { + city: 'Ljubljana', + country: 'Slovenia', + }, }, - }, - relationships: { - pet: { - links: { - self: `http://badlink.com/nonexisting-pet`, + relationships: { + pet: { + links: { + self: `http://badlink.com/nonexisting-pet`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Person', + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Person', + }, }, }, }, - }, - 'theme-starry-night.json': { - data: { - meta: { - adoptsFrom: { - name: 'Theme', - module: 'https://cardstack.com/base/card-api', + 'theme-starry-night.json': { + data: { + meta: { + adoptsFrom: { + name: 'Theme', + module: 'https://cardstack.com/base/card-api', + }, + }, + attributes: { + cardInfo: { name: 'Theme Starry Night' }, + cssVariables: + ':root {\n --background: #f5f7fa;\n --foreground: #1a2238;\n --card: #e3eaf2;\n --card-foreground: #1a2238;\n --popover: #fffbe6;\n --popover-foreground: #1a2238;\n --primary: #3a5ba0;\n --primary-foreground: #fffbe6;\n --secondary: #f7c873;\n --secondary-foreground: #1a2238;\n --muted: #e5e5df;\n --muted-foreground: #3a5ba0;\n --accent: #6ea3c1;\n --accent-foreground: #fffbe6;\n --destructive: #2d1e2f;\n --destructive-foreground: #fffbe6;\n --border: #b0b8c1;\n --input: #6ea3c1;\n --ring: #f7c873;\n --chart-1: #3a5ba0;\n --chart-2: #f7c873;\n --chart-3: #6ea3c1;\n --chart-4: #b0b8c1;\n --chart-5: #2d1e2f;\n --sidebar: #e3eaf2;\n --sidebar-foreground: #1a2238;\n --sidebar-primary: #3a5ba0;\n --sidebar-primary-foreground: #fffbe6;\n --sidebar-accent: #f7c873;\n --sidebar-accent-foreground: #1a2238;\n --sidebar-border: #b0b8c1;\n --sidebar-ring: #f7c873;\n --font-sans: Libre Baskerville, serif;\n --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n --radius: 0.5rem;\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);\n --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);\n --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n --tracking-normal: 0em;\n --spacing: 0.25rem;\n}\n\n.dark {\n --background: #181a24;\n --foreground: #e6eaf3;\n --card: #23243a;\n --card-foreground: #e6eaf3;\n --popover: #23243a;\n --popover-foreground: #ffe066;\n --primary: #3a5ba0;\n --primary-foreground: #ffe066;\n --secondary: #ffe066;\n --secondary-foreground: #23243a;\n --muted: #23243a;\n --muted-foreground: #7a88a1;\n --accent: #bccdf0;\n --accent-foreground: #181a24;\n --destructive: #a04a6c;\n --destructive-foreground: #ffe066;\n --border: #2d2e3e;\n --input: #3a5ba0;\n --ring: #ffe066;\n --chart-1: #3a5ba0;\n --chart-2: #ffe066;\n --chart-3: #6ea3c1;\n --chart-4: #7a88a1;\n --chart-5: #a04a6c;\n --sidebar: #23243a;\n --sidebar-foreground: #e6eaf3;\n --sidebar-primary: #3a5ba0;\n --sidebar-primary-foreground: #ffe066;\n --sidebar-accent: #ffe066;\n --sidebar-accent-foreground: #23243a;\n --sidebar-border: #2d2e3e;\n --sidebar-ring: #ffe066;\n --font-sans: Libre Baskerville, serif;\n --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n --radius: 0.5rem;\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);\n --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);\n --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n}', }, - }, - attributes: { - cardInfo: { name: 'Theme Starry Night' }, - cssVariables: - ':root {\n --background: #f5f7fa;\n --foreground: #1a2238;\n --card: #e3eaf2;\n --card-foreground: #1a2238;\n --popover: #fffbe6;\n --popover-foreground: #1a2238;\n --primary: #3a5ba0;\n --primary-foreground: #fffbe6;\n --secondary: #f7c873;\n --secondary-foreground: #1a2238;\n --muted: #e5e5df;\n --muted-foreground: #3a5ba0;\n --accent: #6ea3c1;\n --accent-foreground: #fffbe6;\n --destructive: #2d1e2f;\n --destructive-foreground: #fffbe6;\n --border: #b0b8c1;\n --input: #6ea3c1;\n --ring: #f7c873;\n --chart-1: #3a5ba0;\n --chart-2: #f7c873;\n --chart-3: #6ea3c1;\n --chart-4: #b0b8c1;\n --chart-5: #2d1e2f;\n --sidebar: #e3eaf2;\n --sidebar-foreground: #1a2238;\n --sidebar-primary: #3a5ba0;\n --sidebar-primary-foreground: #fffbe6;\n --sidebar-accent: #f7c873;\n --sidebar-accent-foreground: #1a2238;\n --sidebar-border: #b0b8c1;\n --sidebar-ring: #f7c873;\n --font-sans: Libre Baskerville, serif;\n --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n --radius: 0.5rem;\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);\n --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);\n --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n --tracking-normal: 0em;\n --spacing: 0.25rem;\n}\n\n.dark {\n --background: #181a24;\n --foreground: #e6eaf3;\n --card: #23243a;\n --card-foreground: #e6eaf3;\n --popover: #23243a;\n --popover-foreground: #ffe066;\n --primary: #3a5ba0;\n --primary-foreground: #ffe066;\n --secondary: #ffe066;\n --secondary-foreground: #23243a;\n --muted: #23243a;\n --muted-foreground: #7a88a1;\n --accent: #bccdf0;\n --accent-foreground: #181a24;\n --destructive: #a04a6c;\n --destructive-foreground: #ffe066;\n --border: #2d2e3e;\n --input: #3a5ba0;\n --ring: #ffe066;\n --chart-1: #3a5ba0;\n --chart-2: #ffe066;\n --chart-3: #6ea3c1;\n --chart-4: #7a88a1;\n --chart-5: #a04a6c;\n --sidebar: #23243a;\n --sidebar-foreground: #e6eaf3;\n --sidebar-primary: #3a5ba0;\n --sidebar-primary-foreground: #ffe066;\n --sidebar-accent: #ffe066;\n --sidebar-accent-foreground: #23243a;\n --sidebar-border: #2d2e3e;\n --sidebar-ring: #ffe066;\n --font-sans: Libre Baskerville, serif;\n --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;\n --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n --radius: 0.5rem;\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10);\n --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10);\n --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10);\n --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n}', }, }, }, - }, - })); + }), + )); }); test('card instance JSON displayed in monaco editor', async function (assert) { diff --git a/packages/host/tests/acceptance/code-submode/field-playground-test.gts b/packages/host/tests/acceptance/code-submode/field-playground-test.gts index c8aa5273e4..af111a64a9 100644 --- a/packages/host/tests/acceptance/code-submode/field-playground-test.gts +++ b/packages/host/tests/acceptance/code-submode/field-playground-test.gts @@ -9,12 +9,14 @@ import ENV from '@cardstack/host/config/environment'; import { assertMessages, percySnapshot, + setupRealmCacheTeardown, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, setupAuthEndpoints, setupLocalIndexing, setupUserSubscription, testRealmURL, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { @@ -297,6 +299,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { let realm: Realm; setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -314,178 +317,180 @@ module('Acceptance | code-submode | field playground', function (_hooks) { setupUserSubscription(); setupAuthEndpoints(); - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'author.gts': authorCard, - 'blog-post.gts': blogPostCard, - 'pet.gts': petCard, - 'Author/jane-doe.json': { - data: { - attributes: { - firstName: 'Jane', - lastName: 'Doe', - bio: "Jane Doe is the Senior Managing Editor at Ramped.com, where she leads content strategy, editorial direction, and ensures the highest standards of quality across all publications. With over a decade of experience in digital media and editorial management, Jane has a proven track record of shaping impactful narratives, growing engaged audiences, and collaborating with cross-functional teams to deliver compelling content. When she's not editing, you can find her exploring new books, hiking, or indulging in her love of photography.", - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}author`, - name: 'Author', + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'author.gts': authorCard, + 'blog-post.gts': blogPostCard, + 'pet.gts': petCard, + 'Author/jane-doe.json': { + data: { + attributes: { + firstName: 'Jane', + lastName: 'Doe', + bio: "Jane Doe is the Senior Managing Editor at Ramped.com, where she leads content strategy, editorial direction, and ensures the highest standards of quality across all publications. With over a decade of experience in digital media and editorial management, Jane has a proven track record of shaping impactful narratives, growing engaged audiences, and collaborating with cross-functional teams to deliver compelling content. When she's not editing, you can find her exploring new books, hiking, or indulging in her love of photography.", + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}author`, + name: 'Author', + }, }, }, }, - }, - 'BlogPost/remote-work.json': { - data: { - attributes: { - cardTitle: 'The Ultimate Guide to Remote Work', - cardDescription: - 'In today’s digital age, remote work has transformed from a luxury to a necessity. This comprehensive guide will help you navigate the world of remote work, offering tips, tools, and best practices for success.', - }, - relationships: { - author: { - links: { - self: `${testRealmURL}Author/jane-doe`, + 'BlogPost/remote-work.json': { + data: { + attributes: { + cardTitle: 'The Ultimate Guide to Remote Work', + cardDescription: + 'In today’s digital age, remote work has transformed from a luxury to a necessity. This comprehensive guide will help you navigate the world of remote work, offering tips, tools, and best practices for success.', + }, + relationships: { + author: { + links: { + self: `${testRealmURL}Author/jane-doe`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}blog-post`, - name: 'BlogPost', + meta: { + adoptsFrom: { + module: `${testRealmURL}blog-post`, + name: 'BlogPost', + }, }, }, }, - }, - 'Spec/comment-alt.json': clone(commentSpec2), - 'Spec/comment-main.json': clone(commentSpec1), - 'Spec/full-name.json': { - data: { - type: 'card', - attributes: { - ref: { - name: 'FullNameField', - module: '../author', + 'Spec/comment-alt.json': clone(commentSpec2), + 'Spec/comment-main.json': clone(commentSpec1), + 'Spec/full-name.json': { + data: { + type: 'card', + attributes: { + ref: { + name: 'FullNameField', + module: '../author', + }, + specType: 'field', + containedExamples: [], + cardTitle: 'FullNameField spec', }, - specType: 'field', - containedExamples: [], - cardTitle: 'FullNameField spec', - }, - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/spec', - name: 'Spec', + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/spec', + name: 'Spec', + }, }, }, }, - }, - 'Spec/contact-info.json': { - data: { - type: 'card', - attributes: { - ref: { - name: 'ContactInfo', - module: '../blog-post', - }, - specType: 'field', - containedExamples: [ - { email: 'marcelius@email.com' }, - { email: 'lilian@email.com' }, - { email: 'susie@email.com' }, - ], - cardTitle: 'Contact Info', - }, - meta: { - fields: { + 'Spec/contact-info.json': { + data: { + type: 'card', + attributes: { + ref: { + name: 'ContactInfo', + module: '../blog-post', + }, + specType: 'field', containedExamples: [ - { - adoptsFrom: { - module: '../blog-post', - name: 'ContactInfo', + { email: 'marcelius@email.com' }, + { email: 'lilian@email.com' }, + { email: 'susie@email.com' }, + ], + cardTitle: 'Contact Info', + }, + meta: { + fields: { + containedExamples: [ + { + adoptsFrom: { + module: '../blog-post', + name: 'ContactInfo', + }, }, - }, - { - adoptsFrom: { - module: '../blog-post', - name: 'ContactInfo', + { + adoptsFrom: { + module: '../blog-post', + name: 'ContactInfo', + }, }, - }, - { - adoptsFrom: { - module: '../blog-post', - name: 'ContactInfo', + { + adoptsFrom: { + module: '../blog-post', + name: 'ContactInfo', + }, }, - }, - ], - }, - adoptsFrom: { - module: 'https://cardstack.com/base/spec', - name: 'Spec', + ], + }, + adoptsFrom: { + module: 'https://cardstack.com/base/spec', + name: 'Spec', + }, }, }, }, - }, - 'Spec/toy.json': { - data: { - type: 'card', - attributes: { - ref: { - name: 'ToyField', - module: '../pet', - }, - specType: 'field', - containedExamples: [ - { cardTitle: 'Tug rope' }, - { cardTitle: 'Lambchop' }, - ], - cardTitle: 'Toy', - }, - meta: { - fields: { + 'Spec/toy.json': { + data: { + type: 'card', + attributes: { + ref: { + name: 'ToyField', + module: '../pet', + }, + specType: 'field', containedExamples: [ - { - adoptsFrom: { - module: '../pet', - name: 'ToyField', - }, - }, - { - adoptsFrom: { - module: '../pet', - name: 'ToyField', - }, - }, + { cardTitle: 'Tug rope' }, + { cardTitle: 'Lambchop' }, ], + cardTitle: 'Toy', }, - adoptsFrom: { - module: 'https://cardstack.com/base/spec', - name: 'Spec', + meta: { + fields: { + containedExamples: [ + { + adoptsFrom: { + module: '../pet', + name: 'ToyField', + }, + }, + { + adoptsFrom: { + module: '../pet', + name: 'ToyField', + }, + }, + ], + }, + adoptsFrom: { + module: 'https://cardstack.com/base/spec', + name: 'Spec', + }, }, }, }, - }, - 'Pet/mango.json': { - data: { - attributes: { - firstName: 'Mango', - cardTitle: 'Mango', - favoriteToys: [ - { cardTitle: 'Tug rope' }, - { cardTitle: 'Lambchop' }, - ], - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'PetCard', + 'Pet/mango.json': { + data: { + attributes: { + firstName: 'Mango', + cardTitle: 'Mango', + favoriteToys: [ + { cardTitle: 'Tug rope' }, + { cardTitle: 'Lambchop' }, + ], + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'PetCard', + }, }, }, }, }, - }, - })); + }), + )); await realm.delete('Spec/comment-main.json'); await realm.write('Spec/comment-main.json', JSON.stringify(commentSpec1)); setRecentFiles([ @@ -1087,6 +1092,7 @@ module('Acceptance | code-submode | field playground', function (_hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -1101,83 +1107,86 @@ module('Acceptance | code-submode | field playground', function (_hooks) { }); setupUserSubscription(); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: personalRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'author.gts': authorCard, - '.realm.json': { - name: `Test User's Workspace`, - backgroundURL: 'https://i.postimg.cc/NjcjbyD3/4k-origami-flock.jpg', - iconURL: 'https://i.postimg.cc/Rq550Bwv/T.png', + ({ realm } = await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: personalRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'author.gts': authorCard, + '.realm.json': { + name: `Test User's Workspace`, + backgroundURL: + 'https://i.postimg.cc/NjcjbyD3/4k-origami-flock.jpg', + iconURL: 'https://i.postimg.cc/Rq550Bwv/T.png', + }, }, - }, - }); - - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: additionalRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'author.gts': authorCard, - 'pet.gts': petCard, - 'Spec/toy.json': { - data: { - type: 'card', - attributes: { - ref: { - name: 'ToyField', - module: '../pet', + }); + + return setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: additionalRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'author.gts': authorCard, + 'pet.gts': petCard, + 'Spec/toy.json': { + data: { + type: 'card', + attributes: { + ref: { + name: 'ToyField', + module: '../pet', + }, + specType: 'field', + containedExamples: [{ cardTitle: 'Tug rope' }], + cardTitle: 'Toy', }, - specType: 'field', - containedExamples: [{ cardTitle: 'Tug rope' }], - cardTitle: 'Toy', - }, - meta: { - fields: { - containedExamples: [ - { - adoptsFrom: { - module: '../pet', - name: 'ToyField', + meta: { + fields: { + containedExamples: [ + { + adoptsFrom: { + module: '../pet', + name: 'ToyField', + }, }, - }, - ], - }, - adoptsFrom: { - module: 'https://cardstack.com/base/spec', - name: 'Spec', + ], + }, + adoptsFrom: { + module: 'https://cardstack.com/base/spec', + name: 'Spec', + }, }, }, }, - }, - 'Spec/full-name.json': { - data: { - type: 'card', - attributes: { - ref: { - name: 'FullNameField', - module: '../author', + 'Spec/full-name.json': { + data: { + type: 'card', + attributes: { + ref: { + name: 'FullNameField', + module: '../author', + }, + specType: 'field', + containedExamples: [], + cardTitle: 'FullNameField spec', }, - specType: 'field', - containedExamples: [], - cardTitle: 'FullNameField spec', - }, - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/spec', - name: 'Spec', + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/spec', + name: 'Spec', + }, }, }, }, + '.realm.json': { + name: `Additional Workspace`, + backgroundURL: 'https://i.postimg.cc/4ycXQZ94/4k-powder-puff.jpg', + iconURL: 'https://i.postimg.cc/BZwv0LyC/A.png', + }, }, - '.realm.json': { - name: `Additional Workspace`, - backgroundURL: 'https://i.postimg.cc/4ycXQZ94/4k-powder-puff.jpg', - iconURL: 'https://i.postimg.cc/BZwv0LyC/A.png', - }, - }, + }); })); setRealmPermissions({ diff --git a/packages/host/tests/acceptance/code-submode/file-def-navigation-test.gts b/packages/host/tests/acceptance/code-submode/file-def-navigation-test.gts index 1fb90dd1e6..01965b9b28 100644 --- a/packages/host/tests/acceptance/code-submode/file-def-navigation-test.gts +++ b/packages/host/tests/acceptance/code-submode/file-def-navigation-test.gts @@ -10,9 +10,11 @@ import { setupAcceptanceTestRealm, setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, SYSTEM_CARD_FIXTURE_CONTENTS, testRealmURL, visitOperatorMode, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -21,6 +23,7 @@ module('Acceptance | code submode | file def navigation', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -56,40 +59,42 @@ module('Acceptance | code submode | file def navigation', function (hooks) { }; } - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'file-link-card.gts': { FileLinkCard }, - 'FileLinkCard/notes.md': `# Notes + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'file-link-card.gts': { FileLinkCard }, + 'FileLinkCard/notes.md': `# Notes Some markdown content.`, - 'FileLinkCard/with-markdown.json': { - data: { - type: 'card', - attributes: { - title: 'Linked markdown example', - }, - relationships: { - attachment: { - links: { - self: './notes.md', - }, - data: { - type: 'file-meta', - id: './notes.md', + 'FileLinkCard/with-markdown.json': { + data: { + type: 'card', + attributes: { + title: 'Linked markdown example', + }, + relationships: { + attachment: { + links: { + self: './notes.md', + }, + data: { + type: 'file-meta', + id: './notes.md', + }, }, }, - }, - meta: { - adoptsFrom: { - module: '../file-link-card', - name: 'FileLinkCard', + meta: { + adoptsFrom: { + module: '../file-link-card', + name: 'FileLinkCard', + }, }, }, }, }, - }, + }); }); }); diff --git a/packages/host/tests/acceptance/code-submode/file-tree-test.ts b/packages/host/tests/acceptance/code-submode/file-tree-test.ts index 93bf92a7ff..8492f615f8 100644 --- a/packages/host/tests/acceptance/code-submode/file-tree-test.ts +++ b/packages/host/tests/acceptance/code-submode/file-tree-test.ts @@ -21,12 +21,14 @@ import { ScrollPositions } from '@cardstack/host/utils/local-storage-keys'; import { elementIsVisible, setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, visitOperatorMode, setupAuthEndpoints, setupUserSubscription, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -200,6 +202,7 @@ const realmInfo = { module('Acceptance | code submode | file-tree tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -226,68 +229,70 @@ module('Acceptance | code submode | file-tree tests', function (hooks) { // this seeds the loader used during index which obtains url mappings // from the global loader - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.gts': indexCardSource, - 'pet-person.gts': personCardSource, - 'person.gts': personCardSource, - 'friend.gts': friendCardSource, - 'employee.gts': employeeCardSource, - 'in-this-file.gts': inThisFileSource, - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.gts': indexCardSource, + 'pet-person.gts': personCardSource, + 'person.gts': personCardSource, + 'friend.gts': friendCardSource, + 'employee.gts': employeeCardSource, + 'in-this-file.gts': inThisFileSource, + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'index.json': { - data: { - type: 'card', - attributes: {}, - meta: { - adoptsFrom: { - module: './index', - name: 'Index', + 'index.json': { + data: { + type: 'card', + attributes: {}, + meta: { + adoptsFrom: { + module: './index', + name: 'Index', + }, }, }, }, - }, - 'not-json.json': 'I am not JSON.', - 'Person/1.json': { - data: { - type: 'card', - attributes: { - firstName: 'Hassan', - lastName: 'Abdel-Rahman', - }, - meta: { - adoptsFrom: { - module: '../person', - name: 'Person', + 'not-json.json': 'I am not JSON.', + 'Person/1.json': { + data: { + type: 'card', + attributes: { + firstName: 'Hassan', + lastName: 'Abdel-Rahman', + }, + meta: { + adoptsFrom: { + module: '../person', + name: 'Person', + }, }, }, }, + ...stubFiles, + 'zzz/zzz/file.json': '{}', + '.realm.json': realmInfo, }, - ...stubFiles, - 'zzz/zzz/file.json': '{}', - '.realm.json': realmInfo, - }, + }); }); }); diff --git a/packages/host/tests/acceptance/code-submode/head-format-preview-test.ts b/packages/host/tests/acceptance/code-submode/head-format-preview-test.ts index f631b73623..54aa2e29b5 100644 --- a/packages/host/tests/acceptance/code-submode/head-format-preview-test.ts +++ b/packages/host/tests/acceptance/code-submode/head-format-preview-test.ts @@ -10,6 +10,7 @@ import { RecentFiles } from '@cardstack/host/utils/local-storage-keys'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, @@ -17,6 +18,7 @@ import { setupAuthEndpoints, setupUserSubscription, setMonacoContent, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -69,6 +71,7 @@ module('Acceptance | code submode | head format preview', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -92,42 +95,44 @@ module('Acceptance | code submode | head format preview', function (hooks) { JSON.stringify([[testRealmURL, 'HeadPreview/example.json']]), ); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'head-preview.gts': headPreviewCardSource, - 'head-preview-unsafe.gts': headPreviewWithDisallowedTagsSource, - 'HeadPreview/example.json': { - data: { - type: 'card', - attributes: { - title: 'Preview Title', - description: 'Preview description', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}head-preview`, - name: 'HeadPreview', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'head-preview.gts': headPreviewCardSource, + 'head-preview-unsafe.gts': headPreviewWithDisallowedTagsSource, + 'HeadPreview/example.json': { + data: { + type: 'card', + attributes: { + title: 'Preview Title', + description: 'Preview description', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}head-preview`, + name: 'HeadPreview', + }, }, }, }, - }, - 'HeadPreviewUnsafe/example.json': { - data: { - type: 'card', - attributes: { - title: 'Unsafe Card', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}head-preview-unsafe`, - name: 'HeadPreviewUnsafe', + 'HeadPreviewUnsafe/example.json': { + data: { + type: 'card', + attributes: { + title: 'Unsafe Card', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}head-preview-unsafe`, + name: 'HeadPreviewUnsafe', + }, }, }, }, }, - }, + }); }); }); diff --git a/packages/host/tests/acceptance/code-submode/inspector-test.ts b/packages/host/tests/acceptance/code-submode/inspector-test.ts index 3d858daad5..519a982a74 100644 --- a/packages/host/tests/acceptance/code-submode/inspector-test.ts +++ b/packages/host/tests/acceptance/code-submode/inspector-test.ts @@ -35,6 +35,7 @@ import { getMonacoContent, percySnapshot, setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, @@ -44,6 +45,7 @@ import { setupUserSubscription, type TestContextWithSave, setMonacoContent, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -438,6 +440,7 @@ module('Acceptance | code submode | inspector tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -462,136 +465,138 @@ module('Acceptance | code submode | inspector tests', function (hooks) { // this seeds the loader used during index which obtains url mappings // from the global loader - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { ...SYSTEM_CARD_FIXTURE_CONTENTS, ...realmAFiles }, - realmURL: testRealmURL2, - }); - ({ adapter } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.gts': indexCardSource, - 'pet-person.gts': personCardSource, - 'person.gts': personCardSource, - 'pet.gts': petCardSource, - 'friend.gts': friendCardSource, - 'employee.gts': employeeCardSource, - 'in-this-file.gts': inThisFileSource, - 'exports.gts': exportsSource, - 'special-exports.gts': specialExportsSource, - 'imports.gts': importsSource, - 're-export.gts': reExportSource, - 'local-inherit.gts': localInheritSource, - 'file-def.gts': fileDefSource, - 'command-module.gts': commandModuleSource, - 'erroring-module.gts': erroringModuleSource, - 'empty-file.gts': '', - 'sample-styles.css': 'body { color: red; }', - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + ({ adapter } = await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { ...SYSTEM_CARD_FIXTURE_CONTENTS, ...realmAFiles }, + realmURL: testRealmURL2, + }); + return setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.gts': indexCardSource, + 'pet-person.gts': personCardSource, + 'person.gts': personCardSource, + 'pet.gts': petCardSource, + 'friend.gts': friendCardSource, + 'employee.gts': employeeCardSource, + 'in-this-file.gts': inThisFileSource, + 'exports.gts': exportsSource, + 'special-exports.gts': specialExportsSource, + 'imports.gts': importsSource, + 're-export.gts': reExportSource, + 'local-inherit.gts': localInheritSource, + 'file-def.gts': fileDefSource, + 'command-module.gts': commandModuleSource, + 'erroring-module.gts': erroringModuleSource, + 'empty-file.gts': '', + 'sample-styles.css': 'body { color: red; }', + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'index.json': { - data: { - type: 'card', - attributes: {}, - meta: { - adoptsFrom: { - module: './index', - name: 'Index', + 'index.json': { + data: { + type: 'card', + attributes: {}, + meta: { + adoptsFrom: { + module: './index', + name: 'Index', + }, }, }, }, - }, - 'léame.md': 'hola mundo', - 'readme.md': 'hello world', - 'not-json.json': 'I am not JSON.', - 'Person/1.json': { - data: { - type: 'card', - attributes: { - firstName: 'Hassan', - lastName: 'Abdel-Rahman', - }, - meta: { - adoptsFrom: { - module: '../person', - name: 'Person', + 'léame.md': 'hola mundo', + 'readme.md': 'hello world', + 'not-json.json': 'I am not JSON.', + 'Person/1.json': { + data: { + type: 'card', + attributes: { + firstName: 'Hassan', + lastName: 'Abdel-Rahman', + }, + meta: { + adoptsFrom: { + module: '../person', + name: 'Person', + }, }, }, }, - }, - 'Pet/mango.json': { - data: { - attributes: { - name: 'Mango', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/mango.json': { + data: { + attributes: { + name: 'Mango', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'Pet/vangogh.json': { - data: { - attributes: { - name: 'Van Gogh', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/vangogh.json': { + data: { + attributes: { + name: 'Van Gogh', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, + 'z00.json': '{}', + 'z01.json': '{}', + 'z02.json': '{}', + 'z03.json': '{}', + 'z04.json': '{}', + 'z05.json': '{}', + 'z06.json': '{}', + 'z07.json': '{}', + 'z08.json': '{}', + 'z09.json': '{}', + 'z10.json': '{}', + 'z11.json': '{}', + 'z12.json': '{}', + 'z13.json': '{}', + 'z14.json': '{}', + 'z15.json': '{}', + 'z16.json': '{}', + 'z17.json': '{}', + 'z18.json': '{}', + 'z19.json': '{}', + 'zzz/zzz/file.json': '{}', + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, }, - 'z00.json': '{}', - 'z01.json': '{}', - 'z02.json': '{}', - 'z03.json': '{}', - 'z04.json': '{}', - 'z05.json': '{}', - 'z06.json': '{}', - 'z07.json': '{}', - 'z08.json': '{}', - 'z09.json': '{}', - 'z10.json': '{}', - 'z11.json': '{}', - 'z12.json': '{}', - 'z13.json': '{}', - 'z14.json': '{}', - 'z15.json': '{}', - 'z16.json': '{}', - 'z17.json': '{}', - 'z18.json': '{}', - 'z19.json': '{}', - 'zzz/zzz/file.json': '{}', - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - }, + }); })); monacoService = getService('monaco-service'); diff --git a/packages/host/tests/acceptance/code-submode/recent-files-test.ts b/packages/host/tests/acceptance/code-submode/recent-files-test.ts index 4775c7ac3a..d15c7055c8 100644 --- a/packages/host/tests/acceptance/code-submode/recent-files-test.ts +++ b/packages/host/tests/acceptance/code-submode/recent-files-test.ts @@ -20,12 +20,14 @@ import type MonacoService from '@cardstack/host/services/monaco-service'; import { percySnapshot, setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, visitOperatorMode, setupAuthEndpoints, setupUserSubscription, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { @@ -193,6 +195,7 @@ let monacoService: MonacoService; module('Acceptance | code submode | recent files tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -212,93 +215,95 @@ module('Acceptance | code submode | recent files tests', function (hooks) { // this seeds the loader used during index which obtains url mappings // from the global loader - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.gts': indexCardSource, - 'pet-person.gts': personCardSource, - 'person.gts': personCardSource, - 'français.json': '{}', - 'friend.gts': friendCardSource, - 'employee.gts': employeeCardSource, - 'in-this-file.gts': inThisFileSource, - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.gts': indexCardSource, + 'pet-person.gts': personCardSource, + 'person.gts': personCardSource, + 'français.json': '{}', + 'friend.gts': friendCardSource, + 'employee.gts': employeeCardSource, + 'in-this-file.gts': inThisFileSource, + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'index.json': { - data: { - type: 'card', - attributes: {}, - meta: { - adoptsFrom: { - module: './index', - name: 'Index', + 'index.json': { + data: { + type: 'card', + attributes: {}, + meta: { + adoptsFrom: { + module: './index', + name: 'Index', + }, }, }, }, - }, - 'not-json.json': 'I am not JSON.', - 'Person/1.json': { - data: { - type: 'card', - attributes: { - firstName: 'Hassan', - lastName: 'Abdel-Rahman', - }, - meta: { - adoptsFrom: { - module: '../person', - name: 'Person', + 'not-json.json': 'I am not JSON.', + 'Person/1.json': { + data: { + type: 'card', + attributes: { + firstName: 'Hassan', + lastName: 'Abdel-Rahman', + }, + meta: { + adoptsFrom: { + module: '../person', + name: 'Person', + }, }, }, }, + 'z00.json': '{}', + 'z01.json': '{}', + 'z02.json': '{}', + 'z03.json': '{}', + 'z04.json': '{}', + 'z05.json': '{}', + 'z06.json': '{}', + 'z07.json': '{}', + 'z08.json': '{}', + 'z09.json': '{}', + 'z10.json': '{}', + 'z11.json': '{}', + 'z12.json': '{}', + 'z13.json': '{}', + 'z14.json': '{}', + 'z15.json': '{}', + 'z16.json': '{}', + 'z17.json': '{}', + 'z18.json': '{}', + 'z19.json': '{}', + 'zzz/zzz/file.json': '{}', + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, }, - 'z00.json': '{}', - 'z01.json': '{}', - 'z02.json': '{}', - 'z03.json': '{}', - 'z04.json': '{}', - 'z05.json': '{}', - 'z06.json': '{}', - 'z07.json': '{}', - 'z08.json': '{}', - 'z09.json': '{}', - 'z10.json': '{}', - 'z11.json': '{}', - 'z12.json': '{}', - 'z13.json': '{}', - 'z14.json': '{}', - 'z15.json': '{}', - 'z16.json': '{}', - 'z17.json': '{}', - 'z18.json': '{}', - 'z19.json': '{}', - 'zzz/zzz/file.json': '{}', - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - }, + }); }); }); diff --git a/packages/host/tests/acceptance/code-submode/schema-editor-test.ts b/packages/host/tests/acceptance/code-submode/schema-editor-test.ts index bd9a5a6bb1..30d61a7873 100644 --- a/packages/host/tests/acceptance/code-submode/schema-editor-test.ts +++ b/packages/host/tests/acceptance/code-submode/schema-editor-test.ts @@ -16,6 +16,7 @@ import type MonacoService from '@cardstack/host/services/monaco-service'; import { setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, @@ -25,6 +26,7 @@ import { setupAuthEndpoints, setupUserSubscription, type TestContextWithSave, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -248,6 +250,7 @@ module('Acceptance | code submode | schema editor tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -266,94 +269,96 @@ module('Acceptance | code submode | schema editor tests', function (hooks) { // this seeds the loader used during index which obtains url mappings // from the global loader - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.gts': indexCardSource, - 'empty.gts': ' ', - 'pet-person.gts': personCardSource, - 'person.gts': personCardSource, - 'friend.gts': friendCardSource, - 'employee.gts': employeeCardSource, - 'in-this-file.gts': inThisFileSource, - 'ambiguous-display-names.gts': ambiguousDisplayNamesCardSource, - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.gts': indexCardSource, + 'empty.gts': ' ', + 'pet-person.gts': personCardSource, + 'person.gts': personCardSource, + 'friend.gts': friendCardSource, + 'employee.gts': employeeCardSource, + 'in-this-file.gts': inThisFileSource, + 'ambiguous-display-names.gts': ambiguousDisplayNamesCardSource, + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'index.json': { - data: { - type: 'card', - attributes: {}, - meta: { - adoptsFrom: { - module: './index', - name: 'Index', + 'index.json': { + data: { + type: 'card', + attributes: {}, + meta: { + adoptsFrom: { + module: './index', + name: 'Index', + }, }, }, }, - }, - 'not-json.json': 'I am not JSON.', - 'Person/1.json': { - data: { - type: 'card', - attributes: { - firstName: 'Hassan', - lastName: 'Abdel-Rahman', - }, - meta: { - adoptsFrom: { - module: '../person', - name: 'Person', + 'not-json.json': 'I am not JSON.', + 'Person/1.json': { + data: { + type: 'card', + attributes: { + firstName: 'Hassan', + lastName: 'Abdel-Rahman', + }, + meta: { + adoptsFrom: { + module: '../person', + name: 'Person', + }, }, }, }, + 'z00.json': '{}', + 'z01.json': '{}', + 'z02.json': '{}', + 'z03.json': '{}', + 'z04.json': '{}', + 'z05.json': '{}', + 'z06.json': '{}', + 'z07.json': '{}', + 'z08.json': '{}', + 'z09.json': '{}', + 'z10.json': '{}', + 'z11.json': '{}', + 'z12.json': '{}', + 'z13.json': '{}', + 'z14.json': '{}', + 'z15.json': '{}', + 'z16.json': '{}', + 'z17.json': '{}', + 'z18.json': '{}', + 'z19.json': '{}', + 'zzz/zzz/file.json': '{}', + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, }, - 'z00.json': '{}', - 'z01.json': '{}', - 'z02.json': '{}', - 'z03.json': '{}', - 'z04.json': '{}', - 'z05.json': '{}', - 'z06.json': '{}', - 'z07.json': '{}', - 'z08.json': '{}', - 'z09.json': '{}', - 'z10.json': '{}', - 'z11.json': '{}', - 'z12.json': '{}', - 'z13.json': '{}', - 'z14.json': '{}', - 'z15.json': '{}', - 'z16.json': '{}', - 'z17.json': '{}', - 'z18.json': '{}', - 'z19.json': '{}', - 'zzz/zzz/file.json': '{}', - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - }, + }); }); monacoService = getService('monaco-service'); diff --git a/packages/host/tests/acceptance/code-submode/spec-test.gts b/packages/host/tests/acceptance/code-submode/spec-test.gts index fbced6df6c..377517f418 100644 --- a/packages/host/tests/acceptance/code-submode/spec-test.gts +++ b/packages/host/tests/acceptance/code-submode/spec-test.gts @@ -14,6 +14,7 @@ import { baseRealm, Deferred } from '@cardstack/runtime-common'; import { setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, @@ -24,6 +25,7 @@ import { type TestContextWithSave, setupOnSave, setupRealmServerEndpoints, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -280,6 +282,7 @@ module('Acceptance | Spec preview', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -301,393 +304,395 @@ module('Acceptance | Spec preview', function (hooks) { // this seeds the loader used during index which obtains url mappings // from the global loader - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'person.gts': personCardSource, - 'person-1.gts': person1CardSource, - 'pet.gts': petCardSource, - 'employee.gts': employeeCardSource, - 'new-skill.gts': newSkillCardSource, - 'test-spec.gts': specCardSource, - 'quote-field.gts': quoteFieldCardSource, - 'primitive-field.gts': primitiveFieldCardSource, - 'polymorphic-field.gts': polymorphicFieldCardSource, - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec for Person', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'person.gts': personCardSource, + 'person-1.gts': person1CardSource, + 'pet.gts': petCardSource, + 'employee.gts': employeeCardSource, + 'new-skill.gts': newSkillCardSource, + 'test-spec.gts': specCardSource, + 'quote-field.gts': quoteFieldCardSource, + 'primitive-field.gts': primitiveFieldCardSource, + 'polymorphic-field.gts': polymorphicFieldCardSource, + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec for Person', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'quote-field-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'QuoteField', - specType: 'field', - ref: { - module: './quote-field', - name: 'QuoteField', - }, - containedExamples: [ - { - text: 'Words build worlds', + 'quote-field-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'QuoteField', + specType: 'field', + ref: { + module: './quote-field', + name: 'QuoteField', }, - ], - }, - meta: { - fields: { containedExamples: [ { - adoptsFrom: { - module: './quote-field', - name: 'QuoteField', - }, + text: 'Words build worlds', }, ], }, - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + fields: { + containedExamples: [ + { + adoptsFrom: { + module: './quote-field', + name: 'QuoteField', + }, + }, + ], + }, + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'employee-entry.json': { - data: { - type: 'card', - attributes: { - specType: 'card', - ref: { - module: `./employee`, - name: 'default', + 'employee-entry.json': { + data: { + type: 'card', + attributes: { + specType: 'card', + ref: { + module: `./employee`, + name: 'default', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'pet-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Pet', - specType: 'card', - ref: { - module: `./pet`, - name: 'Pet', + 'pet-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Pet', + specType: 'card', + ref: { + module: `./pet`, + name: 'Pet', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'pet-entry-2.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Pet2', - specType: 'card', - ref: { - module: `./pet`, - name: 'Pet', - }, - }, - relationships: { - 'linkedExamples.0': { - links: { - self: `${testRealmURL}Pet/mango`, + 'pet-entry-2.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Pet2', + specType: 'card', + ref: { + module: `./pet`, + name: 'Pet', }, }, - 'linkedExamples.1': { - links: { - self: `${testRealmURL}Pet/pudding`, + relationships: { + 'linkedExamples.0': { + links: { + self: `${testRealmURL}Pet/mango`, + }, + }, + 'linkedExamples.1': { + links: { + self: `${testRealmURL}Pet/pudding`, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'Person/fadhlan.json': { - data: { - attributes: { - firstName: 'Fadhlan', - address: [ - { - city: 'Bandung', - country: 'Indonesia', - shippingInfo: { - preferredCarrier: 'DHL', - remarks: `Don't let bob deliver the package--he's always bringing it to the wrong address`, + 'Person/fadhlan.json': { + data: { + attributes: { + firstName: 'Fadhlan', + address: [ + { + city: 'Bandung', + country: 'Indonesia', + shippingInfo: { + preferredCarrier: 'DHL', + remarks: `Don't let bob deliver the package--he's always bringing it to the wrong address`, + }, + }, + ], + }, + relationships: { + pet: { + links: { + self: `${testRealmURL}Pet/mango`, }, - }, - ], - }, - relationships: { - pet: { - links: { - self: `${testRealmURL}Pet/mango`, }, }, - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}person`, - name: 'Person', + meta: { + adoptsFrom: { + module: `${testRealmURL}person`, + name: 'Person', + }, }, }, }, - }, - 'Person/1.json': { - data: { - type: 'card', - attributes: { - firstName: 'Hassan', - lastName: 'Abdel-Rahman', - }, - meta: { - adoptsFrom: { - module: '../person', - name: 'Person', + 'Person/1.json': { + data: { + type: 'card', + attributes: { + firstName: 'Hassan', + lastName: 'Abdel-Rahman', + }, + meta: { + adoptsFrom: { + module: '../person', + name: 'Person', + }, }, }, }, - }, - 'Pet/mango.json': { - data: { - attributes: { - name: 'Mango', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/mango.json': { + data: { + attributes: { + name: 'Mango', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'Pet/pudding.json': { - data: { - attributes: { - name: 'Pudding', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/pudding.json': { + data: { + attributes: { + name: 'Pudding', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'subTestField.json': { - data: { - type: 'card', - attributes: { - readMe: null, - ref: { - name: 'SubTestField', - module: './polymorphic-field', + 'subTestField.json': { + data: { + type: 'card', + attributes: { + readMe: null, + ref: { + name: 'SubTestField', + module: './polymorphic-field', + }, + specType: 'field', + containedExamples: [], + cardDescription: null, + cardThumbnailURL: null, }, - specType: 'field', - containedExamples: [], - cardDescription: null, - cardThumbnailURL: null, - }, - relationships: { - linkedExamples: { - links: { - self: null, + relationships: { + linkedExamples: { + links: { + self: null, + }, }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'pet-field-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'PetField', - cardDescription: 'Spec', - specType: 'field', - ref: { - module: `./pet`, - name: 'PetField', + 'pet-field-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'PetField', + cardDescription: 'Spec', + specType: 'field', + ref: { + module: `./pet`, + name: 'PetField', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'different-field-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'DifferentField', - cardDescription: 'Spec for DifferentField', - specType: 'field', - ref: { - module: `./person`, - name: 'DifferentField', + 'different-field-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'DifferentField', + cardDescription: 'Spec for DifferentField', + specType: 'field', + ref: { + module: `./person`, + name: 'DifferentField', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'primitve-field-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'PrimitiveField', - cardDescription: 'Spec for PrimitiveField', - specType: 'field', - ref: { - module: `./primitive-field`, - name: 'PrimitiveField', + 'primitve-field-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'PrimitiveField', + cardDescription: 'Spec for PrimitiveField', + specType: 'field', + ref: { + module: `./primitive-field`, + name: 'PrimitiveField', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'subclass-primitive-field-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'SubclassPrimitiveField', - cardDescription: 'Spec for SubclassPrimitiveField', - specType: 'field', - ref: { - module: `./primitive-field`, - name: 'SubclassPrimitiveField', + 'subclass-primitive-field-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'SubclassPrimitiveField', + cardDescription: 'Spec for SubclassPrimitiveField', + specType: 'field', + ref: { + module: `./primitive-field`, + name: 'SubclassPrimitiveField', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, + '.realm.json': { + name: 'Test Workspace B', + backgroundURL: + 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', + iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', + }, }, - '.realm.json': { - name: 'Test Workspace B', - backgroundURL: - 'https://i.postimg.cc/VNvHH93M/pawel-czerwinski-Ly-ZLa-A5jti-Y-unsplash.jpg', - iconURL: 'https://i.postimg.cc/L8yXRvws/icon.png', - }, - }, - }); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealm2URL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'new-skill.gts': newSkillCardSource, - 'person.gts': personCardSource, - 'quote-field.gts': quoteFieldCardSource, - 'person-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'Person', - cardDescription: 'Spec', - specType: 'card', - ref: { - module: `./person`, - name: 'Person', + }); + await setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealm2URL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'new-skill.gts': newSkillCardSource, + 'person.gts': personCardSource, + 'quote-field.gts': quoteFieldCardSource, + 'person-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'Person', + cardDescription: 'Spec', + specType: 'card', + ref: { + module: `./person`, + name: 'Person', + }, }, - }, - meta: { - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, - }, - 'quote-field-entry.json': { - data: { - type: 'card', - attributes: { - cardTitle: 'QuoteField', - specType: 'field', - ref: { - module: './quote-field', - name: 'QuoteField', - }, - containedExamples: [ - { - text: 'Words build worlds', + 'quote-field-entry.json': { + data: { + type: 'card', + attributes: { + cardTitle: 'QuoteField', + specType: 'field', + ref: { + module: './quote-field', + name: 'QuoteField', }, - ], - }, - meta: { - fields: { containedExamples: [ { - adoptsFrom: { - module: './quote-field', - name: 'QuoteField', - }, + text: 'Words build worlds', }, ], }, - adoptsFrom: { - module: `${baseRealm.url}spec`, - name: 'Spec', + meta: { + fields: { + containedExamples: [ + { + adoptsFrom: { + module: './quote-field', + name: 'QuoteField', + }, + }, + ], + }, + adoptsFrom: { + module: `${baseRealm.url}spec`, + name: 'Spec', + }, }, }, }, }, - }, + }); }); setActiveRealms([testRealmURL, testRealm2URL]); setRealmPermissions({ diff --git a/packages/host/tests/acceptance/host-mode-test.gts b/packages/host/tests/acceptance/host-mode-test.gts index 0d852f45eb..e1aac02495 100644 --- a/packages/host/tests/acceptance/host-mode-test.gts +++ b/packages/host/tests/acceptance/host-mode-test.gts @@ -130,7 +130,6 @@ module('Acceptance | host mode tests', function (hooks) { }; } - await setupAcceptanceTestRealm({ realmURL: testHostModeRealmURL, mockMatrixUtils, diff --git a/packages/host/tests/acceptance/image-def/avif-image-def-test.gts b/packages/host/tests/acceptance/image-def/avif-image-def-test.gts index 0857827ea6..39560703b5 100644 --- a/packages/host/tests/acceptance/image-def/avif-image-def-test.gts +++ b/packages/host/tests/acceptance/image-def/avif-image-def-test.gts @@ -18,10 +18,12 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, capturePrerenderResult, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -102,6 +104,7 @@ module('Acceptance | avif image def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupTestRealmServiceWorker(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { @@ -176,15 +179,17 @@ module('Acceptance | avif image def', function (hooks) { hooks.beforeEach(async function () { let renderableAvif = await makeRenderableAvif(2, 3); - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'sample.avif': makeMinimalAvif(2, 3), - 'renderable.avif': renderableAvif, - 'not-an-avif.avif': 'This is plain text, not an AVIF file.', - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'sample.avif': makeMinimalAvif(2, 3), + 'renderable.avif': renderableAvif, + 'not-an-avif.avif': 'This is plain text, not an AVIF file.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/image-def/gif-image-def-test.gts b/packages/host/tests/acceptance/image-def/gif-image-def-test.gts index eb0774cf15..7a686d0845 100644 --- a/packages/host/tests/acceptance/image-def/gif-image-def-test.gts +++ b/packages/host/tests/acceptance/image-def/gif-image-def-test.gts @@ -18,10 +18,12 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, capturePrerenderResult, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -57,6 +59,7 @@ module('Acceptance | gif image def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupTestRealmServiceWorker(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { @@ -131,14 +134,16 @@ module('Acceptance | gif image def', function (hooks) { hooks.beforeEach(async function () { let gifBytes = makeMinimalGif(6, 7); - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'sample.gif': gifBytes, - 'not-a-gif.gif': 'This is plain text, not a GIF file.', - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'sample.gif': gifBytes, + 'not-a-gif.gif': 'This is plain text, not a GIF file.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/image-def/jpg-image-def-test.gts b/packages/host/tests/acceptance/image-def/jpg-image-def-test.gts index 793f3e3a17..31e4154530 100644 --- a/packages/host/tests/acceptance/image-def/jpg-image-def-test.gts +++ b/packages/host/tests/acceptance/image-def/jpg-image-def-test.gts @@ -18,10 +18,12 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, capturePrerenderResult, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -56,6 +58,7 @@ module('Acceptance | jpg image def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupTestRealmServiceWorker(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { @@ -129,14 +132,16 @@ module('Acceptance | jpg image def', function (hooks) { } hooks.beforeEach(async function () { - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'sample.jpg': VALID_JPEG_4x5, - 'not-a-jpg.jpg': 'This is plain text, not a JPEG file.', - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'sample.jpg': VALID_JPEG_4x5, + 'not-a-jpg.jpg': 'This is plain text, not a JPEG file.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/image-def/png-image-def-test.gts b/packages/host/tests/acceptance/image-def/png-image-def-test.gts index fb09dcb67a..f3d1fa3a5b 100644 --- a/packages/host/tests/acceptance/image-def/png-image-def-test.gts +++ b/packages/host/tests/acceptance/image-def/png-image-def-test.gts @@ -18,10 +18,12 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, capturePrerenderResult, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -131,6 +133,7 @@ module('Acceptance | png image def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupTestRealmServiceWorker(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { @@ -205,14 +208,16 @@ module('Acceptance | png image def', function (hooks) { hooks.beforeEach(async function () { let pngBytes = makeMinimalPng(2, 3); - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'sample.png': pngBytes, - 'not-a-png.png': 'This is plain text, not a PNG file.', - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'sample.png': pngBytes, + 'not-a-png.png': 'This is plain text, not a PNG file.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/image-def/svg-image-def-test.gts b/packages/host/tests/acceptance/image-def/svg-image-def-test.gts index e79db4e302..00be842c0f 100644 --- a/packages/host/tests/acceptance/image-def/svg-image-def-test.gts +++ b/packages/host/tests/acceptance/image-def/svg-image-def-test.gts @@ -18,10 +18,12 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, capturePrerenderResult, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -35,6 +37,7 @@ module('Acceptance | svg image def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupTestRealmServiceWorker(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { @@ -108,16 +111,18 @@ module('Acceptance | svg image def', function (hooks) { } hooks.beforeEach(async function () { - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'sample.svg': makeMinimalSvg(120, 80), - 'viewbox-only.svg': - '', - 'not-an-svg.svg': 'This is plain text, not an SVG file.', - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'sample.svg': makeMinimalSvg(120, 80), + 'viewbox-only.svg': + '', + 'not-an-svg.svg': 'This is plain text, not an SVG file.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/image-def/webp-image-def-test.gts b/packages/host/tests/acceptance/image-def/webp-image-def-test.gts index a6f33e81f0..4dde8e5390 100644 --- a/packages/host/tests/acceptance/image-def/webp-image-def-test.gts +++ b/packages/host/tests/acceptance/image-def/webp-image-def-test.gts @@ -18,10 +18,12 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, capturePrerenderResult, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupApplicationTest } from '../../helpers/setup'; @@ -42,6 +44,7 @@ module('Acceptance | webp image def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupTestRealmServiceWorker(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { @@ -115,14 +118,16 @@ module('Acceptance | webp image def', function (hooks) { } hooks.beforeEach(async function () { - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'sample.webp': VALID_WEBP_8x9, - 'not-a-webp.webp': 'This is plain text, not a WebP file.', - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'sample.webp': VALID_WEBP_8x9, + 'not-a-webp.webp': 'This is plain text, not a WebP file.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/interact-submode/create-file-test.gts b/packages/host/tests/acceptance/interact-submode/create-file-test.gts index 4ea4649ddf..ec43ebd9dc 100644 --- a/packages/host/tests/acceptance/interact-submode/create-file-test.gts +++ b/packages/host/tests/acceptance/interact-submode/create-file-test.gts @@ -7,6 +7,7 @@ import { baseRealm, specRef } from '@cardstack/runtime-common'; import { setupLocalIndexing, + setupRealmCacheTeardown, testRealmURL, setupOnSave, setupAcceptanceTestRealm, @@ -15,6 +16,7 @@ import { setupAuthEndpoints, setupUserSubscription, type TestContextWithSave, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { @@ -207,6 +209,7 @@ module('Acceptance | interact submode | create-file tests', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -220,26 +223,28 @@ module('Acceptance | interact submode | create-file tests', function (hooks) { cardsGrid = await loader.import(`${baseRealm.url}cards-grid`); let { CardsGrid } = cardsGrid; - await Promise.all([ - setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.json': new CardsGrid(), - ...testRealmFiles, - }, - }), - setupAcceptanceTestRealm({ - mockMatrixUtils, - realmURL: userRealm, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.json': new CardsGrid(), - ...userRealmFiles, - }, - }), - ]); + await withCachedRealmSetup(async () => { + await Promise.all([ + setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.json': new CardsGrid(), + ...testRealmFiles, + }, + }), + setupAcceptanceTestRealm({ + mockMatrixUtils, + realmURL: userRealm, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.json': new CardsGrid(), + ...userRealmFiles, + }, + }), + ]); + }); createAndJoinRoom({ sender: '@testuser:localhost', diff --git a/packages/host/tests/acceptance/markdown-file-def-test.gts b/packages/host/tests/acceptance/markdown-file-def-test.gts index e451be46da..3a15850f78 100644 --- a/packages/host/tests/acceptance/markdown-file-def-test.gts +++ b/packages/host/tests/acceptance/markdown-file-def-test.gts @@ -18,9 +18,11 @@ import type NetworkService from '@cardstack/host/services/network'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupApplicationTest } from '../helpers/setup'; @@ -29,6 +31,7 @@ module('Acceptance | markdown file def', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -90,18 +93,20 @@ module('Acceptance | markdown file def', function (hooks) { } hooks.beforeEach(async function () { - ({ realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'readme.md': `# Project Overview + ({ realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'readme.md': `# Project Overview This is the first paragraph. Another paragraph follows.`, - 'notes.txt': 'Plain text file contents.', - }, - })); + 'notes.txt': 'Plain text file contents.', + }, + }), + )); }); hooks.afterEach(function () { diff --git a/packages/host/tests/acceptance/prerender-file-extract-test.gts b/packages/host/tests/acceptance/prerender-file-extract-test.gts index e09ebd9669..3862f8374c 100644 --- a/packages/host/tests/acceptance/prerender-file-extract-test.gts +++ b/packages/host/tests/acceptance/prerender-file-extract-test.gts @@ -16,9 +16,11 @@ import type RenderStoreService from '@cardstack/host/services/render-store'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, testRealmURL, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupApplicationTest } from '../helpers/setup'; @@ -27,6 +29,7 @@ module('Acceptance | prerender | file-extract', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -90,11 +93,12 @@ module('Acceptance | prerender | file-extract', function (hooks) { } hooks.beforeEach(async function () { - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'filedef-success.gts': ` + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'filedef-success.gts': ` import { FileDef as BaseFileDef } from "${baseRealm.url}file-api"; export class SuccessDef extends BaseFileDef { @@ -108,7 +112,7 @@ module('Acceptance | prerender | file-extract', function (hooks) { } } `, - 'filedef-mismatch.gts': ` + 'filedef-mismatch.gts': ` import { FileDef as BaseFileDef, FileContentMismatchError, @@ -120,7 +124,7 @@ module('Acceptance | prerender | file-extract', function (hooks) { } } `, - 'filedef-throws.gts': ` + 'filedef-throws.gts': ` import { FileDef as BaseFileDef } from "${baseRealm.url}file-api"; export class ThrowingDef extends BaseFileDef { @@ -129,12 +133,13 @@ module('Acceptance | prerender | file-extract', function (hooks) { } } `, - 'filedef-missing.gts': ` + 'filedef-missing.gts': ` export const NotFileDef = {}; `, - 'sample.txt': 'hello world', - 'mismatch.txt': 'mismatch content', - }, + 'sample.txt': 'hello world', + 'mismatch.txt': 'mismatch content', + }, + }); }); }); diff --git a/packages/host/tests/acceptance/prerender-module-test.gts b/packages/host/tests/acceptance/prerender-module-test.gts index 999b48cd31..47cce456df 100644 --- a/packages/host/tests/acceptance/prerender-module-test.gts +++ b/packages/host/tests/acceptance/prerender-module-test.gts @@ -15,11 +15,13 @@ import type { Realm } from '@cardstack/runtime-common/realm'; import { setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, testRealmURL, captureModuleResult, createPrerenderAuth, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupApplicationTest } from '../helpers/setup'; @@ -30,6 +32,7 @@ module('Acceptance | prerender | module', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -73,16 +76,18 @@ module('Acceptance | prerender | module', function (hooks) { const BROKEN_MODULE = `export const Broken = ;`; hooks.beforeEach(async function () { - ({ adapter, realm } = await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'person.gts': PERSON_MODULE, - 'parent.gts': PARENT_MODULE, - 'child.gts': CHILD_MODULE, - 'broken.gts': BROKEN_MODULE, - }, - })); + ({ adapter, realm } = await withCachedRealmSetup(async () => + setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'person.gts': PERSON_MODULE, + 'parent.gts': PARENT_MODULE, + 'child.gts': CHILD_MODULE, + 'broken.gts': BROKEN_MODULE, + }, + }), + )); }); test('captures module metadata when module loads successfully', async function (assert) { diff --git a/packages/host/tests/acceptance/theme-card-test.gts b/packages/host/tests/acceptance/theme-card-test.gts index da23c21d95..849c10cc67 100644 --- a/packages/host/tests/acceptance/theme-card-test.gts +++ b/packages/host/tests/acceptance/theme-card-test.gts @@ -11,12 +11,14 @@ import { percySnapshot, setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, setupUserSubscription, setupAuthEndpoints, setupAcceptanceTestRealm, SYSTEM_CARD_FIXTURE_CONTENTS, visitOperatorMode, testRealmURL, + withCachedRealmSetup, type TestContextWithSave, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; @@ -150,6 +152,7 @@ module('Acceptance | theme-card-test', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -169,104 +172,106 @@ module('Acceptance | theme-card-test', function (hooks) { setupUserSubscription(); setupAuthEndpoints(); - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - '.realm.json': { - name: 'Theme Playground', - }, - 'starry-night.json': { - data: { - meta: { - adoptsFrom: { - name: 'default', - module: 'https://cardstack.com/base/structured-theme', + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + '.realm.json': { + name: 'Theme Playground', + }, + 'starry-night.json': { + data: { + meta: { + adoptsFrom: { + name: 'default', + module: 'https://cardstack.com/base/structured-theme', + }, }, - }, - type: 'card', - attributes: { - cardInfo: { - name: 'Starry Night', - summmary: 'A celestial theme', - cardThumbnailURL: - 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?q=80&w=400&auto=format&fit=crop', + type: 'card', + attributes: { + cardInfo: { + name: 'Starry Night', + summmary: 'A celestial theme', + cardThumbnailURL: + 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?q=80&w=400&auto=format&fit=crop', + }, + cssImports: [ + 'https://fonts.googleapis.com/css2?family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap', + 'https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;1,400&display=swap', + 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap', + ], + rootVariables: ROOT_CSS_VARS, + darkModeVariables: DARK_MODE_VARS, }, - cssImports: [ - 'https://fonts.googleapis.com/css2?family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap', - 'https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;1,400&display=swap', - 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap', - ], - rootVariables: ROOT_CSS_VARS, - darkModeVariables: DARK_MODE_VARS, }, }, - }, - 'style-ref-starry-night.json': { - data: { - meta: { - adoptsFrom: { - name: 'default', - module: 'https://cardstack.com/base/style-reference', + 'style-ref-starry-night.json': { + data: { + meta: { + adoptsFrom: { + name: 'default', + module: 'https://cardstack.com/base/style-reference', + }, }, - }, - type: 'card', - attributes: { - cardInfo: { - notes: - 'Color palette extracted from the famous painting: deep Prussian blue (#0a0f23), golden yellow (#ffd700), warm amber (#ffb347), and creamy highlights (#f4f1e8). Uses elegant serif fonts to match the artistic, classical nature of the inspiration.', - name: 'Starry Night', - summary: - "A celestial theme inspired by Van Gogh's masterpiece, featuring deep midnight blues swirling with golden yellows and warm amber accents.", - cardThumbnailURL: - 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?q=80&w=400&auto=format&fit=crop', + type: 'card', + attributes: { + cardInfo: { + notes: + 'Color palette extracted from the famous painting: deep Prussian blue (#0a0f23), golden yellow (#ffd700), warm amber (#ffb347), and creamy highlights (#f4f1e8). Uses elegant serif fonts to match the artistic, classical nature of the inspiration.', + name: 'Starry Night', + summary: + "A celestial theme inspired by Van Gogh's masterpiece, featuring deep midnight blues swirling with golden yellows and warm amber accents.", + cardThumbnailURL: + 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?q=80&w=400&auto=format&fit=crop', + }, + styleName: 'Starry Night', + visualDNA: + "A celestial theme inspired by Van Gogh's masterpiece, featuring deep midnight blues swirling with golden yellows and warm amber accents. The palette captures the cosmic energy of a starlit night with flowing, organic movements and luminous highlights that dance across dark surfaces.", + cssImports: [ + 'https://fonts.googleapis.com/css2?family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap', + 'https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;1,400&display=swap', + 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap', + ], + inspirations: [ + 'Van Gogh', + 'Post-Impressionism', + 'Cosmic swirls', + 'Night sky', + 'Cypress trees', + 'Village lights', + 'Impasto technique', + 'Dynamic brushstrokes', + ], + rootVariables: ROOT_CSS_VARS, + wallpaperImages: [ + 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?q=80&w=1200&auto=format&fit=crop', + 'https://images.unsplash.com/photo-1447433589675-4aaa569f3e05?q=80&w=1200&auto=format&fit=crop', + 'https://images.unsplash.com/photo-1419242902214-272b3f66ee7a?q=80&w=1200&auto=format&fit=crop', + ], + darkModeVariables: DARK_MODE_VARS, }, - styleName: 'Starry Night', - visualDNA: - "A celestial theme inspired by Van Gogh's masterpiece, featuring deep midnight blues swirling with golden yellows and warm amber accents. The palette captures the cosmic energy of a starlit night with flowing, organic movements and luminous highlights that dance across dark surfaces.", - cssImports: [ - 'https://fonts.googleapis.com/css2?family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&display=swap', - 'https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;1,400&display=swap', - 'https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,300;0,400;0,500;0,600;1,400&display=swap', - ], - inspirations: [ - 'Van Gogh', - 'Post-Impressionism', - 'Cosmic swirls', - 'Night sky', - 'Cypress trees', - 'Village lights', - 'Impasto technique', - 'Dynamic brushstrokes', - ], - rootVariables: ROOT_CSS_VARS, - wallpaperImages: [ - 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?q=80&w=1200&auto=format&fit=crop', - 'https://images.unsplash.com/photo-1447433589675-4aaa569f3e05?q=80&w=1200&auto=format&fit=crop', - 'https://images.unsplash.com/photo-1419242902214-272b3f66ee7a?q=80&w=1200&auto=format&fit=crop', - ], - darkModeVariables: DARK_MODE_VARS, }, }, - }, - 'soft-pop.json': { - data: { - meta: { - adoptsFrom: { - name: 'default', - module: 'https://cardstack.com/base/structured-theme', + 'soft-pop.json': { + data: { + meta: { + adoptsFrom: { + name: 'default', + module: 'https://cardstack.com/base/structured-theme', + }, }, - }, - type: 'card', - attributes: { - cardInfo: { - name: 'Soft Pop', - summary: 'A theme with soft color pops', + type: 'card', + attributes: { + cardInfo: { + name: 'Soft Pop', + summary: 'A theme with soft color pops', + }, }, }, }, }, - }, + }); }); }); diff --git a/packages/host/tests/acceptance/workspace-delete-multiple-test.gts b/packages/host/tests/acceptance/workspace-delete-multiple-test.gts index 00d3d53944..52c990849c 100644 --- a/packages/host/tests/acceptance/workspace-delete-multiple-test.gts +++ b/packages/host/tests/acceptance/workspace-delete-multiple-test.gts @@ -8,11 +8,13 @@ import { baseRealm } from '@cardstack/runtime-common'; import { setupLocalIndexing, setupAcceptanceTestRealm, + setupRealmCacheTeardown, testRealmURL, setupAuthEndpoints, setupUserSubscription, SYSTEM_CARD_FIXTURE_CONTENTS, visitOperatorMode, + withCachedRealmSetup, } from '../helpers'; import { setupBaseRealm, CardsGrid } from '../helpers/base-realm'; import { setupMockMatrix } from '../helpers/mock-matrix'; @@ -21,6 +23,7 @@ import { setupApplicationTest } from '../helpers/setup'; module('Acceptance | workspace-delete-multiple', function (hooks) { setupApplicationTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks, { loggedInAs: '@testuser:localhost', @@ -68,30 +71,32 @@ module('Acceptance | workspace-delete-multiple', function (hooks) { }; } - await setupAcceptanceTestRealm({ - mockMatrixUtils, - contents: { - ...SYSTEM_CARD_FIXTURE_CONTENTS, - 'index.json': new CardsGrid(), - 'pet.gts': { Pet }, - 'Pet/1.json': new Pet({ - name: 'Fluffy', - species: 'Cat', - }), - 'Pet/2.json': new Pet({ - name: 'Buddy', - species: 'Dog', - }), - 'Pet/3.json': new Pet({ - name: 'Charlie', - species: 'Bird', - }), - '.realm.json': { - name: 'Test Realm', - backgroundURL: null, - iconURL: null, + await withCachedRealmSetup(async () => { + await setupAcceptanceTestRealm({ + mockMatrixUtils, + contents: { + ...SYSTEM_CARD_FIXTURE_CONTENTS, + 'index.json': new CardsGrid(), + 'pet.gts': { Pet }, + 'Pet/1.json': new Pet({ + name: 'Fluffy', + species: 'Cat', + }), + 'Pet/2.json': new Pet({ + name: 'Buddy', + species: 'Dog', + }), + 'Pet/3.json': new Pet({ + name: 'Charlie', + species: 'Bird', + }), + '.realm.json': { + name: 'Test Realm', + backgroundURL: null, + iconURL: null, + }, }, - }, + }); }); }); diff --git a/packages/host/tests/helpers/index.gts b/packages/host/tests/helpers/index.gts index a8a5526829..e6b177682a 100644 --- a/packages/host/tests/helpers/index.gts +++ b/packages/host/tests/helpers/index.gts @@ -12,6 +12,7 @@ import { tracked } from '@glimmer/tracking'; import { getService } from '@universal-ember/test-support'; +import QUnit from 'qunit'; import { validate as uuidValidate } from 'uuid'; import { @@ -24,6 +25,7 @@ import { Loader, MatrixClient, Realm, + simpleHash, testHostModeRealmURL, testRealmInfo, testRealmURL, @@ -99,6 +101,9 @@ export { const { sqlSchema } = ENV; type CardAPI = typeof import('https://cardstack.com/base/card-api'); +type ModuleHooks = { + after: (callback: () => void | Promise) => void; +}; const baseTestMatrix = { url: new URL(`http://localhost:8008`), @@ -158,6 +163,111 @@ export async function getDbAdapter() { return dbAdapter; } +const realmCacheTeardownRegistrations = new WeakMap>(); + +export function setupRealmCacheTeardown( + hooks: ModuleHooks, + moduleCacheKey?: string, +): void { + let resolvedModuleCacheKey = moduleCacheKey ?? getCurrentModuleCacheKey(); + let snapshotPrefix = snapshotPrefixForModule(resolvedModuleCacheKey); + let registrations = realmCacheTeardownRegistrations.get(hooks); + if (!registrations) { + registrations = new Set(); + realmCacheTeardownRegistrations.set(hooks, registrations); + } + if (registrations.has(snapshotPrefix)) { + return; + } + registrations.add(snapshotPrefix); + hooks.after(async () => { + let dbAdapter = await getDbAdapter(); + await dbAdapter.deleteSnapshotsByPrefix(snapshotPrefix); + }); +} + +export async function withCachedRealmSetup( + setupOrAdditionalKey: (() => Promise) | string, + maybeSetup?: () => Promise, +): Promise { + let moduleCacheKey = getCurrentModuleCacheKey(); + let additionalKey: string | undefined; + let setup: () => Promise; + + if (typeof setupOrAdditionalKey === 'function') { + setup = setupOrAdditionalKey; + } else { + if (!maybeSetup) { + throw new Error( + 'withCachedRealmSetup(additionalKey, setup) requires a setup callback', + ); + } + additionalKey = setupOrAdditionalKey; + setup = maybeSetup; + } + + let snapshotName = snapshotNameForCacheKey(moduleCacheKey, additionalKey); + let dbAdapter = await getDbAdapter(); + if (dbAdapter.hasSnapshot(snapshotName)) { + await dbAdapter.importSnapshot(snapshotName); + return setup(); + } + let result = await setup(); + await dbAdapter.exportSnapshot(snapshotName); + return result; +} + +function getCurrentModuleCacheKey(): string { + let config = QUnit.config as QUnit['config'] & { + currentModule?: { name?: string }; + }; + let moduleName = + QUnit.config.current?.module?.name ?? config.currentModule?.name; + if (moduleName?.trim()) { + return moduleName; + } + throw new Error( + 'withCachedRealmSetup() was called without an explicit cacheKey, but no active QUnit module name was available', + ); +} + +function snapshotNameForCacheKey( + moduleCacheKey: string, + additionalKey?: string, +): string { + let trimmedModuleCacheKey = moduleCacheKey.trim(); + if (!trimmedModuleCacheKey) { + throw new Error('snapshotNameForCacheKey() requires a non-empty cache key'); + } + + let trimmedAdditionalKey = additionalKey?.trim(); + let effectiveCacheKey = trimmedAdditionalKey + ? `${trimmedModuleCacheKey}::${trimmedAdditionalKey}` + : trimmedModuleCacheKey; + + let slug = (trimmedAdditionalKey ?? trimmedModuleCacheKey) + .toLowerCase() + .replace(/[^a-z0-9]+/g, '_') + .replace(/^_+|_+$/g, '') + .slice(0, 40); + + if (!slug) { + slug = 'module'; + } + + return `${snapshotPrefixForModule(trimmedModuleCacheKey)}${simpleHash( + effectiveCacheKey, + )}_${slug}`; +} + +function snapshotPrefixForModule(moduleCacheKey: string): string { + let trimmedModuleCacheKey = moduleCacheKey.trim(); + if (!trimmedModuleCacheKey) { + throw new Error('snapshotPrefixForModule() requires a non-empty cache key'); + } + return `snapshot_${simpleHash(trimmedModuleCacheKey)}_`; +} + export async function withSlowSave( delayMs: number, cb: () => Promise, @@ -672,6 +782,7 @@ export async function setupIntegrationTestRealm({ permissions, mockMatrixUtils, startMatrix = true, + fileSizeLimitBytes, }: { contents: RealmContents; realmURL?: string; @@ -690,6 +801,7 @@ export async function setupIntegrationTestRealm({ permissions: permissions as RealmPermissions, mockMatrixUtils, startMatrix, + fileSizeLimitBytes, }); getTestRealmRegistry().set(result.realm.url, { realm: result.realm, @@ -714,6 +826,7 @@ export const createPrerenderAuth = ( // Host tests prerender via the in-app card-prerender component, so we don't need real JWT auth. return JSON.stringify({}); }; + async function setupTestRealm({ contents, realmURL, @@ -778,7 +891,6 @@ async function setupTestRealm({ 'definition-lookup:main', ) as DefinitionLookup; } - await insertPermissions(dbAdapter, new URL(realmURL), permissions); let worker = new Worker({ indexWriter: new IndexWriter(dbAdapter), diff --git a/packages/host/tests/integration/commands/add-field-to-card-definition-command-test.gts b/packages/host/tests/integration/commands/add-field-to-card-definition-command-test.gts index 775bffae75..ace6aa4f0e 100644 --- a/packages/host/tests/integration/commands/add-field-to-card-definition-command-test.gts +++ b/packages/host/tests/integration/commands/add-field-to-card-definition-command-test.gts @@ -13,6 +13,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -37,11 +39,14 @@ module( getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': ` import { contains, field, Component, CardDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; export class Person extends CardDef { @@ -49,9 +54,10 @@ module( @field firstName = contains(StringField); } `, - }, - realmURL: 'http://test-realm/test/', - }); + }, + realmURL: 'http://test-realm/test/', + }), + ); }); test('adds a field to a card definition', async function (assert) { diff --git a/packages/host/tests/integration/commands/apply-markdown-edit-test.gts b/packages/host/tests/integration/commands/apply-markdown-edit-test.gts index 6a4d7e6580..b0ccf864cc 100644 --- a/packages/host/tests/integration/commands/apply-markdown-edit-test.gts +++ b/packages/host/tests/integration/commands/apply-markdown-edit-test.gts @@ -19,6 +19,8 @@ import { testRealmURL, testRealmInfo, setupRealmServerEndpoints, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -102,14 +104,17 @@ module('Integration | commands | apply-markdown-edit', function (hooks) { }, ]); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { forwardRequests = []; parsedRequestBodies = []; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'article.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'article.gts': ` import { CardDef, field, contains } from "https://cardstack.com/base/card-api"; import MarkdownField from "https://cardstack.com/base/markdown"; @@ -119,47 +124,48 @@ module('Integration | commands | apply-markdown-edit', function (hooks) { @field body = contains(MarkdownField); } `, - 'Article/ambiguous.json': { - data: { - type: 'card', - attributes: { - body: 'Repeat me.\n\nRepeat me.\n\nKeep me.', - }, - meta: { - adoptsFrom: { - module: '../article', - name: 'Article', + 'Article/ambiguous.json': { + data: { + type: 'card', + attributes: { + body: 'Repeat me.\n\nRepeat me.\n\nKeep me.', + }, + meta: { + adoptsFrom: { + module: '../article', + name: 'Article', + }, }, }, }, - }, - 'Article/1.json': { - data: { - type: 'card', - attributes: { body: post1 }, - meta: { - adoptsFrom: { - module: '../article', - name: 'Article', + 'Article/1.json': { + data: { + type: 'card', + attributes: { body: post1 }, + meta: { + adoptsFrom: { + module: '../article', + name: 'Article', + }, }, }, }, - }, - 'Article/2.json': { - data: { - type: 'card', - attributes: { intro: post2 }, - meta: { - adoptsFrom: { - module: '../article', - name: 'Article', + 'Article/2.json': { + data: { + type: 'card', + attributes: { intro: post2 }, + meta: { + adoptsFrom: { + module: '../article', + name: 'Article', + }, }, }, }, + '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-m.png" }`, }, - '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-m.png" }`, - }, - }); + }), + ); command = new ApplyMarkdownEditCommand( getService('command-service').commandContext, diff --git a/packages/host/tests/integration/commands/bot-registration-test.gts b/packages/host/tests/integration/commands/bot-registration-test.gts index 65046baf0d..c5cf358a9e 100644 --- a/packages/host/tests/integration/commands/bot-registration-test.gts +++ b/packages/host/tests/integration/commands/bot-registration-test.gts @@ -14,6 +14,8 @@ import { setupRealmServerEndpoints, testRealmInfo, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -109,15 +111,19 @@ module('Integration | commands | bot-registration', function (hooks) { }, ]); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { getOwner(this)!.register('service:realm', StubRealmService); botRegistrations = []; // we are setting this up to get the matrixClient started - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: {}, + }), + ); }); test('register-bot returns botRegistrationId', async function (assert) { diff --git a/packages/host/tests/integration/commands/check-correctness-test.gts b/packages/host/tests/integration/commands/check-correctness-test.gts index 9935bbb26a..587142f3c2 100644 --- a/packages/host/tests/integration/commands/check-correctness-test.gts +++ b/packages/host/tests/integration/commands/check-correctness-test.gts @@ -19,6 +19,8 @@ import { testRealmURL, setupIntegrationTestRealm, setupLocalIndexing, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -34,11 +36,14 @@ module('Integration | commands | check-correctness', function (hooks) { activeRealms: [testRealmURL], }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'pet.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'pet.gts': ` import { contains, field, CardDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; import BooleanField from "https://cardstack.com/base/boolean"; @@ -56,23 +61,24 @@ module('Integration | commands | check-correctness', function (hooks) { }); } `, - 'Pet/billy.json': { - data: { - type: 'card', - attributes: { - name: 'Billy', - hasError: false, - }, - meta: { - adoptsFrom: { - module: '../pet', - name: 'Pet', + 'Pet/billy.json': { + data: { + type: 'card', + attributes: { + name: 'Billy', + hasError: false, + }, + meta: { + adoptsFrom: { + module: '../pet', + name: 'Pet', + }, }, }, }, }, - }, - }); + }), + ); let realmService = getService('realm'); let messageService = getService('message-service'); messageService.register(); diff --git a/packages/host/tests/integration/commands/copy-and-edit-test.gts b/packages/host/tests/integration/commands/copy-and-edit-test.gts index dee6d2442b..7ebf25b634 100644 --- a/packages/host/tests/integration/commands/copy-and-edit-test.gts +++ b/packages/host/tests/integration/commands/copy-and-edit-test.gts @@ -14,6 +14,8 @@ import { setupIntegrationTestRealm, setupLocalIndexing, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -29,12 +31,15 @@ module('Integration | commands | copy-and-edit', function (hooks) { activeRealms: [testRealmURL, otherRealmURL], }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - 'content-card.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + 'content-card.gts': ` import { CardDef, contains, field, linksTo, linksToMany } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; @@ -49,45 +54,45 @@ module('Integration | commands | copy-and-edit', function (hooks) { @field children = linksToMany(() => Child); } `, - 'Child/og.json': { - data: { - type: 'card', - attributes: { - name: 'Original', - }, - meta: { - adoptsFrom: { - module: '../content-card', - name: 'Child', + 'Child/og.json': { + data: { + type: 'card', + attributes: { + name: 'Original', + }, + meta: { + adoptsFrom: { + module: '../content-card', + name: 'Child', + }, }, }, }, - }, - 'Parent/root.json': { - data: { - type: 'card', - relationships: { - child: { - data: { - type: 'card', - id: '../Child/og', + 'Parent/root.json': { + data: { + type: 'card', + relationships: { + child: { + data: { + type: 'card', + id: '../Child/og', + }, }, - }, - 'children.0': { - links: { - self: '../Child/og', + 'children.0': { + links: { + self: '../Child/og', + }, }, }, - }, - meta: { - adoptsFrom: { - module: '../content-card', - name: 'Parent', + meta: { + adoptsFrom: { + module: '../content-card', + name: 'Parent', + }, }, }, }, - }, - 'simple-card.gts': ` + 'simple-card.gts': ` import { CardDef, field, contains } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; @@ -100,49 +105,51 @@ module('Integration | commands | copy-and-edit', function (hooks) { static displayName = 'SimpleCard'; } `, - 'Theme/og.json': { - data: { - type: 'card', - attributes: { - name: 'Original Theme', - }, - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/theme', - name: 'default', + 'Theme/og.json': { + data: { + type: 'card', + attributes: { + name: 'Original Theme', + }, + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/theme', + name: 'default', + }, }, }, }, - }, - 'simple-card-instance.json': { - data: { - type: 'card', - attributes: {}, - relationships: { - // Establish nested relationship via dotted path - 'cardInfo.theme': { - data: { - type: 'card', - id: './Theme/og', + 'simple-card-instance.json': { + data: { + type: 'card', + attributes: {}, + relationships: { + // Establish nested relationship via dotted path + 'cardInfo.theme': { + data: { + type: 'card', + id: './Theme/og', + }, }, }, - }, - meta: { - adoptsFrom: { - module: './simple-card', - name: 'SimpleCard', + meta: { + adoptsFrom: { + module: './simple-card', + name: 'SimpleCard', + }, }, }, }, }, - }, - }); + }), + ); - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: otherRealmURL, - contents: { - 'content-card.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: otherRealmURL, + contents: { + 'content-card.gts': ` import { CardDef, contains, field } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; @@ -151,22 +158,23 @@ module('Integration | commands | copy-and-edit', function (hooks) { @field name = contains(StringField); } `, - 'Child/remote.json': { - data: { - type: 'card', - attributes: { - name: 'RemoteChild', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}content-card`, - name: 'Child', + 'Child/remote.json': { + data: { + type: 'card', + attributes: { + name: 'RemoteChild', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}content-card`, + name: 'Child', + }, }, }, }, }, - }, - }); + }), + ); let realmService = getService('realm'); await realmService.login(testRealmURL); diff --git a/packages/host/tests/integration/commands/copy-card-test.gts b/packages/host/tests/integration/commands/copy-card-test.gts index e534ac2bab..8e289096cc 100644 --- a/packages/host/tests/integration/commands/copy-card-test.gts +++ b/packages/host/tests/integration/commands/copy-card-test.gts @@ -13,6 +13,8 @@ import { setupIntegrationTestRealm, setupLocalIndexing, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -28,12 +30,15 @@ module('Integration | commands | copy-card', function (hooks) { activeRealms: [testRealmURL, testRealm2URL], }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - 'pet.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + 'pet.gts': ` import { contains, field, CardDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; export class Pet extends CardDef { @@ -41,54 +46,57 @@ module('Integration | commands | copy-card', function (hooks) { @field firstName = contains(StringField); } `, - 'Pet/mango.json': { - data: { - type: 'card', - attributes: { - firstName: 'Mango', - }, - meta: { - adoptsFrom: { - module: '../pet', - name: 'Pet', + 'Pet/mango.json': { + data: { + type: 'card', + attributes: { + firstName: 'Mango', + }, + meta: { + adoptsFrom: { + module: '../pet', + name: 'Pet', + }, }, }, }, }, - }, - }); + }), + ); - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealm2URL, - contents: { - 'index.json': { - data: { - type: 'card', - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/cards-grid', - name: 'CardsGrid', + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealm2URL, + contents: { + 'index.json': { + data: { + type: 'card', + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/cards-grid', + name: 'CardsGrid', + }, }, }, }, - }, - 'Pet/fluffy.json': { - data: { - type: 'card', - attributes: { - firstName: 'Fluffy', - }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/fluffy.json': { + data: { + type: 'card', + attributes: { + firstName: 'Fluffy', + }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, }, - }, - }); + }), + ); // Ensure realms are logged in with write permissions let realmService = getService('realm'); diff --git a/packages/host/tests/integration/commands/copy-source-test.gts b/packages/host/tests/integration/commands/copy-source-test.gts index 0ab7f698bb..0f7606214d 100644 --- a/packages/host/tests/integration/commands/copy-source-test.gts +++ b/packages/host/tests/integration/commands/copy-source-test.gts @@ -14,6 +14,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -40,12 +42,15 @@ module('Integration | commands | copy-source', function (hooks) { fetch = getService('network').fetch; }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - 'person.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + 'person.gts': ` import { contains, field, Component, CardDef } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; export class Person extends CardDef { @@ -53,8 +58,9 @@ module('Integration | commands | copy-source', function (hooks) { @field firstName = contains(StringField); } `, - }, - }); + }, + }), + ); }); test('able to copy source or file', async function (assert) { diff --git a/packages/host/tests/integration/commands/create-spec-test.gts b/packages/host/tests/integration/commands/create-spec-test.gts index e6dc6f5f92..c1afd09760 100644 --- a/packages/host/tests/integration/commands/create-spec-test.gts +++ b/packages/host/tests/integration/commands/create-spec-test.gts @@ -15,6 +15,8 @@ import { setupLocalIndexing, setupAuthEndpoints, setupRealmServerEndpoints, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -73,47 +75,51 @@ module('Integration | Command | create-specs', function (hooks) { async () => await loader.import(`${baseRealm.url}card-api`), ); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { setupAuthEndpoints(); - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - 'test-card.gts': `import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + 'test-card.gts': `import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; export class TestCard extends CardDef { static displayName = 'Test Card'; @field name = contains(StringField); }`, - 'test-field.gts': `import { FieldDef } from 'https://cardstack.com/base/card-api'; + 'test-field.gts': `import { FieldDef } from 'https://cardstack.com/base/card-api'; export class TestField extends FieldDef { static displayName = 'Test Field'; }`, - 'app-card.gts': `import { CardDef } from 'https://cardstack.com/base/card-api'; + 'app-card.gts': `import { CardDef } from 'https://cardstack.com/base/card-api'; export class AppCard extends CardDef { static displayName = 'App Card'; }`, - 'test-component.gts': `import Component from '@glimmer/component'; + 'test-component.gts': `import Component from '@glimmer/component'; export default class TestComponent extends Component { static displayName = 'Test Component'; }`, - 'test-command.gts': `import { Command } from '@cardstack/runtime-common'; + 'test-command.gts': `import { Command } from '@cardstack/runtime-common'; export default class TestCommand extends Command { static displayName = 'Test Command'; }`, - 'test-spec.gts': `import { Spec } from 'https://cardstack.com/base/spec'; + 'test-spec.gts': `import { Spec } from 'https://cardstack.com/base/spec'; export class TestSpec extends Spec { static displayName = 'Test Spec'; }`, - '.realm.json': `{ "name": "${realmName}" }`, - }, - }); + '.realm.json': `{ "name": "${realmName}" }`, + }, + }), + ); }); test('creates spec with correct type for card definition', async function (assert) { diff --git a/packages/host/tests/integration/commands/generate-example-cards-one-shot-test.gts b/packages/host/tests/integration/commands/generate-example-cards-one-shot-test.gts index 04bd131289..30ff98e9d6 100644 --- a/packages/host/tests/integration/commands/generate-example-cards-one-shot-test.gts +++ b/packages/host/tests/integration/commands/generate-example-cards-one-shot-test.gts @@ -8,6 +8,8 @@ import { setupLocalIndexing, setupRealmServerEndpoints, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -68,11 +70,14 @@ module( typeof GenerateExampleCardsOneShotCommand >; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'test-card.gts': `import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'test-card.gts': `import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; export class TestCard extends CardDef { @@ -80,8 +85,9 @@ export class TestCard extends CardDef { @field cardTitle = contains(StringField); @field cardDescription = contains(StringField); }`, - }, - }); + }, + }), + ); const commandService = getService('command-service'); generateExampleCommand = new GenerateExampleCardsOneShotCommand( diff --git a/packages/host/tests/integration/commands/invite-user-to-room-test.gts b/packages/host/tests/integration/commands/invite-user-to-room-test.gts index e19698764f..ecd5e16ee7 100644 --- a/packages/host/tests/integration/commands/invite-user-to-room-test.gts +++ b/packages/host/tests/integration/commands/invite-user-to-room-test.gts @@ -14,6 +14,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -43,11 +45,15 @@ module('Integration | commands | invite-user-to-room', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('invites a user to a room', async function (assert) { diff --git a/packages/host/tests/integration/commands/open-workspace-test.gts b/packages/host/tests/integration/commands/open-workspace-test.gts index c02bb153b6..39fe4feb3b 100644 --- a/packages/host/tests/integration/commands/open-workspace-test.gts +++ b/packages/host/tests/integration/commands/open-workspace-test.gts @@ -7,6 +7,8 @@ import { setupIntegrationTestRealm, setupLocalIndexing, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -23,11 +25,15 @@ module('Integration | commands | open-workspace', function (hooks) { autostart: true, }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('opens specified workspace in interact submode', async function (assert) { diff --git a/packages/host/tests/integration/commands/patch-code-test.gts b/packages/host/tests/integration/commands/patch-code-test.gts index 8fe165f169..4377c2268c 100644 --- a/packages/host/tests/integration/commands/patch-code-test.gts +++ b/packages/host/tests/integration/commands/patch-code-test.gts @@ -20,6 +20,8 @@ import { testRealmURL, setupIntegrationTestRealm, setupLocalIndexing, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -38,11 +40,14 @@ module('Integration | commands | patch-code', function (hooks) { const jsonFileUrl = `${testRealmURL}${jsonFileName}`; let adapter: any; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - let realmSetup = await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - [testFileName]: `import { + let realmSetup = await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + [testFileName]: `import { contains, field, CardDef, @@ -56,13 +61,14 @@ export class Task extends CardDef { @field cardDescription = contains(StringField); @field priority = contains(NumberField); }`, - [jsonFileName]: `{ + [jsonFileName]: `{ "title": "Old title", "count": 1 } `, - }, - }); + }, + }), + ); adapter = realmSetup.adapter; adapter.lintStub = async ( request: Request, diff --git a/packages/host/tests/integration/commands/patch-instance-test.gts b/packages/host/tests/integration/commands/patch-instance-test.gts index f52b0e48ce..02a7c8ff38 100644 --- a/packages/host/tests/integration/commands/patch-instance-test.gts +++ b/packages/host/tests/integration/commands/patch-instance-test.gts @@ -20,6 +20,8 @@ import { setupOnSave, withSlowSave, type TestContextWithSave, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { CardDef, @@ -46,6 +48,8 @@ module('Integration | commands | patch-instance', function (hooks) { let PersonDef: typeof CardDefType; let indexQuery: RealmIndexQueryEngine; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { commandService = getService('command-service'); class Person extends CardDef { @@ -56,16 +60,18 @@ module('Integration | commands | patch-instance', function (hooks) { } PersonDef = Person; - let { realm } = await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': { Person }, - 'Person/hassan.json': new Person({ name: 'Hassan' }), - 'Person/jade.json': new Person({ name: 'Jade' }), - 'Person/queenzy.json': new Person({ name: 'Queenzy' }), - 'Person/germaine.json': new Person({ name: 'Germaine' }), - }, - }); + let { realm } = await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': { Person }, + 'Person/hassan.json': new Person({ name: 'Hassan' }), + 'Person/jade.json': new Person({ name: 'Jade' }), + 'Person/queenzy.json': new Person({ name: 'Queenzy' }), + 'Person/germaine.json': new Person({ name: 'Germaine' }), + }, + }), + ); indexQuery = realm.realmIndexQueryEngine; }); diff --git a/packages/host/tests/integration/commands/preview-format-test.gts b/packages/host/tests/integration/commands/preview-format-test.gts index 07738fa438..599024919e 100644 --- a/packages/host/tests/integration/commands/preview-format-test.gts +++ b/packages/host/tests/integration/commands/preview-format-test.gts @@ -19,6 +19,8 @@ import { setupOnSave, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -59,11 +61,14 @@ module('Integration | Command | preview-format', function (hooks) { let command: PreviewFormatCommand; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'rental-item.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'rental-item.gts': ` import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; import NumberField from 'https://cardstack.com/base/number'; @@ -80,25 +85,26 @@ module('Integration | Command | preview-format', function (hooks) { }); } `, - 'RentalItem/example.json': { - data: { - type: 'card', - attributes: { - name: 'Bike Rental', - cardDescription: 'Mountain bike for rent', - price: 25, - }, - meta: { - adoptsFrom: { - module: `../rental-item`, - name: 'RentalItem', + 'RentalItem/example.json': { + data: { + type: 'card', + attributes: { + name: 'Bike Rental', + cardDescription: 'Mountain bike for rent', + price: 25, + }, + meta: { + adoptsFrom: { + module: `../rental-item`, + name: 'RentalItem', + }, }, }, }, + '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-s.png" }`, }, - '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-s.png" }`, - }, - }); + }), + ); command = new PreviewFormatCommand( getService('command-service').commandContext, diff --git a/packages/host/tests/integration/commands/read-card-for-ai-assistant-test.gts b/packages/host/tests/integration/commands/read-card-for-ai-assistant-test.gts index e577e9383b..eeba687e1f 100644 --- a/packages/host/tests/integration/commands/read-card-for-ai-assistant-test.gts +++ b/packages/host/tests/integration/commands/read-card-for-ai-assistant-test.gts @@ -15,6 +15,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -42,11 +44,14 @@ module('Integration | commands | read-card-for-ai-assistant', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': ` import { contains, field, CardDef, Component } from "https://cardstack.com/base/card-api"; import StringField from "https://cardstack.com/base/string"; import NumberField from "https://cardstack.com/base/number"; @@ -84,21 +89,22 @@ module('Integration | commands | read-card-for-ai-assistant', function (hooks) { } } `, - 'mango.json': { - data: { - attributes: { - firstName: 'Mango', - }, - meta: { - adoptsFrom: { - module: './person', - name: 'Person', + 'mango.json': { + data: { + attributes: { + firstName: 'Mango', + }, + meta: { + adoptsFrom: { + module: './person', + name: 'Person', + }, }, }, }, }, - }, - }); + }), + ); }); test('read card', async function (assert) { diff --git a/packages/host/tests/integration/commands/read-file-for-ai-assistant-test.gts b/packages/host/tests/integration/commands/read-file-for-ai-assistant-test.gts index e906be3453..5654c9a6fa 100644 --- a/packages/host/tests/integration/commands/read-file-for-ai-assistant-test.gts +++ b/packages/host/tests/integration/commands/read-file-for-ai-assistant-test.gts @@ -13,6 +13,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -40,13 +42,17 @@ module('Integration | commands | read-file-for-ai-assistant', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'files/test.txt': 'This is a test file for AI assistant.', - }, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'files/test.txt': 'This is a test file for AI assistant.', + }, + }), + ); }); test('read file', async function (assert) { diff --git a/packages/host/tests/integration/commands/read-source-test.gts b/packages/host/tests/integration/commands/read-source-test.gts index bd1296c0cb..6e5a998ff4 100644 --- a/packages/host/tests/integration/commands/read-source-test.gts +++ b/packages/host/tests/integration/commands/read-source-test.gts @@ -13,6 +13,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -37,13 +39,17 @@ module('Integration | commands | read-source', function (hooks) { }); let readSourceCommand: ReadSourceCommand; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'component.gts': `import Component from '@glimmer/component';\n\nexport default class TestComponent extends Component {}`, - }, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'component.gts': `import Component from '@glimmer/component';\n\nexport default class TestComponent extends Component {}`, + }, + }), + ); let commandService = getService('command-service'); readSourceCommand = new ReadSourceCommand(commandService.commandContext); }); diff --git a/packages/host/tests/integration/commands/read-text-file-test.gts b/packages/host/tests/integration/commands/read-text-file-test.gts index ebf555a553..56c7cbf6da 100644 --- a/packages/host/tests/integration/commands/read-text-file-test.gts +++ b/packages/host/tests/integration/commands/read-text-file-test.gts @@ -13,6 +13,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -37,17 +39,21 @@ module('Integration | commands | read-text-file', function (hooks) { }); let readTextFileCommand: ReadTextFileCommand; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'test.txt': 'Hello World!', - 'subdir/nested.txt': 'I am nested.', - 'empty.txt': '', - 'data.json': JSON.stringify({ message: 'test data' }), - 'component.gts': `import Component from '@glimmer/component';\nexport default class TestComponent extends Component {}`, - }, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'test.txt': 'Hello World!', + 'subdir/nested.txt': 'I am nested.', + 'empty.txt': '', + 'data.json': JSON.stringify({ message: 'test data' }), + 'component.gts': `import Component from '@glimmer/component';\nexport default class TestComponent extends Component {}`, + }, + }), + ); let commandService = getService('command-service'); readTextFileCommand = new ReadTextFileCommand( commandService.commandContext, diff --git a/packages/host/tests/integration/commands/search-command-test.gts b/packages/host/tests/integration/commands/search-command-test.gts index 67eccb1418..94b609c954 100644 --- a/packages/host/tests/integration/commands/search-command-test.gts +++ b/packages/host/tests/integration/commands/search-command-test.gts @@ -15,6 +15,8 @@ import { setupIntegrationTestRealm, setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -31,6 +33,7 @@ module('Integration | commands | search', function (hooks) { setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupCardLogs( hooks, async () => await loader.import(`${baseRealm.url}card-api`), @@ -63,17 +66,19 @@ module('Integration | commands | search', function (hooks) { }, }); } - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'author.gts': { Author }, - 'Author/r2.json': new Author({ firstName: 'R2-D2' }), - 'Author/mark.json': new Author({ - firstName: 'Mark', - lastName: 'Jackson', - }), - '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-o.png" }`, - }, + await withCachedRealmSetup(async () => { + await setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'author.gts': { Author }, + 'Author/r2.json': new Author({ firstName: 'R2-D2' }), + 'Author/mark.json': new Author({ + firstName: 'Mark', + lastName: 'Jackson', + }), + '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-o.png" }`, + }, + }); }); }); diff --git a/packages/host/tests/integration/commands/search-google-images-test.gts b/packages/host/tests/integration/commands/search-google-images-test.gts index 9a6f14fd48..59ebbfafda 100644 --- a/packages/host/tests/integration/commands/search-google-images-test.gts +++ b/packages/host/tests/integration/commands/search-google-images-test.gts @@ -8,6 +8,8 @@ import { setupLocalIndexing, testRealmURL, setupRealmServerEndpoints, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -137,11 +139,15 @@ module('Integration | commands | search-google-images', function (hooks) { }, ]); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('successfully searches Google Images and returns results', async function (assert) { diff --git a/packages/host/tests/integration/commands/send-ai-assistant-message-test.gts b/packages/host/tests/integration/commands/send-ai-assistant-message-test.gts index c3725aaca9..28149f9ed0 100644 --- a/packages/host/tests/integration/commands/send-ai-assistant-message-test.gts +++ b/packages/host/tests/integration/commands/send-ai-assistant-message-test.gts @@ -15,6 +15,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -44,11 +46,15 @@ module('Integration | commands | send-ai-assistant-message', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('send an ai assistant message', async function (assert) { diff --git a/packages/host/tests/integration/commands/send-bot-trigger-event-test.gts b/packages/host/tests/integration/commands/send-bot-trigger-event-test.gts index b2279aecdb..c1a8d782cd 100644 --- a/packages/host/tests/integration/commands/send-bot-trigger-event-test.gts +++ b/packages/host/tests/integration/commands/send-bot-trigger-event-test.gts @@ -15,6 +15,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -43,11 +45,15 @@ module('Integration | commands | send-bot-trigger-event', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('sends a bot trigger event', async function (assert) { diff --git a/packages/host/tests/integration/commands/send-request-via-proxy-test.gts b/packages/host/tests/integration/commands/send-request-via-proxy-test.gts index d805a98913..1412dadd7f 100644 --- a/packages/host/tests/integration/commands/send-request-via-proxy-test.gts +++ b/packages/host/tests/integration/commands/send-request-via-proxy-test.gts @@ -13,6 +13,8 @@ import { testRealmURL, testRealmInfo, setupRealmServerEndpoints, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -160,11 +162,15 @@ module('Integration | commands | send-request-via-proxy', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); // Helper function to create mock send request via proxy input diff --git a/packages/host/tests/integration/commands/set-user-system-card-test.gts b/packages/host/tests/integration/commands/set-user-system-card-test.gts index 850deb942f..931f2bffc9 100644 --- a/packages/host/tests/integration/commands/set-user-system-card-test.gts +++ b/packages/host/tests/integration/commands/set-user-system-card-test.gts @@ -12,6 +12,8 @@ import { setupLocalIndexing, testRealmInfo, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -39,11 +41,15 @@ module('Integration | commands | set-user-system-card', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('sets the system card account data', async function (assert) { diff --git a/packages/host/tests/integration/commands/show-card-test.gts b/packages/host/tests/integration/commands/show-card-test.gts index 9433f592d4..97a9505a19 100644 --- a/packages/host/tests/integration/commands/show-card-test.gts +++ b/packages/host/tests/integration/commands/show-card-test.gts @@ -28,6 +28,8 @@ import { setupOnSave, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -144,11 +146,14 @@ module('Integration | Command | show-card', function (hooks) { let mockOperatorModeStateService: MockOperatorModeStateService; let mockPlaygroundPanelService: MockPlaygroundPanelService; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': ` import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; @@ -163,7 +168,7 @@ module('Integration | Command | show-card', function (hooks) { }); } `, - 'pet.gts': ` + 'pet.gts': ` import { CardDef, field, contains } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; @@ -178,54 +183,55 @@ module('Integration | Command | show-card', function (hooks) { }); } `, - 'Person/alice.json': { - data: { - type: 'card', - attributes: { - firstName: 'Alice', - lastName: 'Johnson', - }, - meta: { - adoptsFrom: { - module: `../person`, - name: 'Person', + 'Person/alice.json': { + data: { + type: 'card', + attributes: { + firstName: 'Alice', + lastName: 'Johnson', + }, + meta: { + adoptsFrom: { + module: `../person`, + name: 'Person', + }, }, }, }, - }, - 'Person/bob.json': { - data: { - type: 'card', - attributes: { - firstName: 'Bob', - lastName: 'Smith', - }, - meta: { - adoptsFrom: { - module: `../person`, - name: 'Person', + 'Person/bob.json': { + data: { + type: 'card', + attributes: { + firstName: 'Bob', + lastName: 'Smith', + }, + meta: { + adoptsFrom: { + module: `../person`, + name: 'Person', + }, }, }, }, - }, - 'Pet/fluffy.json': { - data: { - type: 'card', - attributes: { - name: 'Fluffy', - species: 'Cat', - }, - meta: { - adoptsFrom: { - module: `../pet`, - name: 'Pet', + 'Pet/fluffy.json': { + data: { + type: 'card', + attributes: { + name: 'Fluffy', + species: 'Cat', + }, + meta: { + adoptsFrom: { + module: `../pet`, + name: 'Pet', + }, }, }, }, + '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-s.png" }`, }, - '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-s.png" }`, - }, - }); + }), + ); mockOperatorModeStateService = new MockOperatorModeStateService(); mockPlaygroundPanelService = new MockPlaygroundPanelService(); diff --git a/packages/host/tests/integration/commands/summarize-session-test.gts b/packages/host/tests/integration/commands/summarize-session-test.gts index b4214d31e0..36984e098d 100644 --- a/packages/host/tests/integration/commands/summarize-session-test.gts +++ b/packages/host/tests/integration/commands/summarize-session-test.gts @@ -13,6 +13,8 @@ import { testRealmURL, testRealmInfo, setupRealmServerEndpoints, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -122,11 +124,15 @@ module('Integration | commands | summarize-session', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); // Helper function to create mock summarize session input diff --git a/packages/host/tests/integration/commands/switch-submode-test.gts b/packages/host/tests/integration/commands/switch-submode-test.gts index 5a0290a950..368ebd189c 100644 --- a/packages/host/tests/integration/commands/switch-submode-test.gts +++ b/packages/host/tests/integration/commands/switch-submode-test.gts @@ -17,6 +17,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { CardDef, setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -49,11 +51,15 @@ module('Integration | commands | switch-submode', function (hooks) { store = getService('store'); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('switch to code submode by local id of a saved instance', async function (assert) { diff --git a/packages/host/tests/integration/commands/update-room-skills-test.gts b/packages/host/tests/integration/commands/update-room-skills-test.gts index 82b216b515..402969e576 100644 --- a/packages/host/tests/integration/commands/update-room-skills-test.gts +++ b/packages/host/tests/integration/commands/update-room-skills-test.gts @@ -26,6 +26,8 @@ import { setupOnSave, testRealmInfo, testRealmURL, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm, CommandField, Skill } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -123,12 +125,15 @@ module('Integration | Command | update-room-skills', function (hooks) { let matrixRoomId: string; module('run', function (hooks) { + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - realmURL: testRealmURL, - contents: { - 'test-command.gts': `import { Command } from '@cardstack/runtime-common'; + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + realmURL: testRealmURL, + contents: { + 'test-command.gts': `import { Command } from '@cardstack/runtime-common'; export class DoThing extends Command { static displayName = 'Test Command'; @@ -136,40 +141,41 @@ export class DoThing extends Command { return undefined; } }`, - 'skill-with-commands.json': new Skill({ - cardTitle: 'Skill with invalid command', - cardDescription: 'test', - instructions: 'test', - commands: [ - new CommandField({ - codeRef: { module: '', name: '' }, - requiresApproval: false, - }), - new CommandField({ - codeRef: { - module: `${testRealmURL}test-command.gts`, - name: 'DoThing', - }, - requiresApproval: false, - }), - ], - }), - 'Skill/boxel-environment.json': new Skill({ - title: 'Boxel Environment', - description: 'Test environment skill', - instructions: 'Test skill card for environment commands', - commands: [ - new CommandField({ - codeRef: { - module: `${testRealmURL}test-command.gts`, - name: 'DoThing', - }, - requiresApproval: false, - }), - ], - }), - }, - }); + 'skill-with-commands.json': new Skill({ + cardTitle: 'Skill with invalid command', + cardDescription: 'test', + instructions: 'test', + commands: [ + new CommandField({ + codeRef: { module: '', name: '' }, + requiresApproval: false, + }), + new CommandField({ + codeRef: { + module: `${testRealmURL}test-command.gts`, + name: 'DoThing', + }, + requiresApproval: false, + }), + ], + }), + 'Skill/boxel-environment.json': new Skill({ + title: 'Boxel Environment', + description: 'Test environment skill', + instructions: 'Test skill card for environment commands', + commands: [ + new CommandField({ + codeRef: { + module: `${testRealmURL}test-command.gts`, + name: 'DoThing', + }, + requiresApproval: false, + }), + ], + }), + }, + }), + ); let matrixService = getService('matrix-service') as any; await matrixService.ready; matrixRoomId = mockMatrixUtils.createAndJoinRoom({ diff --git a/packages/host/tests/integration/commands/use-ai-assistant-test.gts b/packages/host/tests/integration/commands/use-ai-assistant-test.gts index 1a63e26cb3..185279e8e5 100644 --- a/packages/host/tests/integration/commands/use-ai-assistant-test.gts +++ b/packages/host/tests/integration/commands/use-ai-assistant-test.gts @@ -26,6 +26,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -59,72 +61,76 @@ module('Integration | commands | ai-assistant', function (hooks) { getOwner(this)!.register('service:realm', StubRealmService); }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'empty1.json': { - data: { - attributes: { - cardTitle: 'Empty Card 1', - cardDescription: 'This is an empty card.', - }, - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/card-api', - name: 'CardDef', + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'empty1.json': { + data: { + attributes: { + cardTitle: 'Empty Card 1', + cardDescription: 'This is an empty card.', + }, + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/card-api', + name: 'CardDef', + }, }, }, }, - }, - 'empty2.json': { - data: { - attributes: { - cardTitle: 'Empty Card 2', - cardDescription: 'This is an empty card.', - }, - meta: { - adoptsFrom: { - module: 'https://cardstack.com/base/card-api', - name: 'CardDef', + 'empty2.json': { + data: { + attributes: { + cardTitle: 'Empty Card 2', + cardDescription: 'This is an empty card.', + }, + meta: { + adoptsFrom: { + module: 'https://cardstack.com/base/card-api', + name: 'CardDef', + }, }, }, }, - }, - 'file1.gts': 'This is file 1 content', - 'file2.gts': 'This is file 2 content', - 'skill1.json': { - data: { - type: 'card', - attributes: { - instructions: 'Here is the one thing you need to know.', - commands: [], - cardTitle: 'Skill1', - cardDescription: null, - cardThumbnailURL: null, - }, - meta: { - adoptsFrom: skillCardRef, + 'file1.gts': 'This is file 1 content', + 'file2.gts': 'This is file 2 content', + 'skill1.json': { + data: { + type: 'card', + attributes: { + instructions: 'Here is the one thing you need to know.', + commands: [], + cardTitle: 'Skill1', + cardDescription: null, + cardThumbnailURL: null, + }, + meta: { + adoptsFrom: skillCardRef, + }, }, }, - }, - 'skill2.json': { - data: { - type: 'card', - attributes: { - instructions: 'Here is the two thing you need to know.', - commands: [], - cardTitle: 'Skill2', - cardDescription: null, - cardThumbnailURL: null, - }, - meta: { - adoptsFrom: skillCardRef, + 'skill2.json': { + data: { + type: 'card', + attributes: { + instructions: 'Here is the two thing you need to know.', + commands: [], + cardTitle: 'Skill2', + cardDescription: null, + cardThumbnailURL: null, + }, + meta: { + adoptsFrom: skillCardRef, + }, }, }, }, - }, - }); + }), + ); commandService = getService('command-service'); }); diff --git a/packages/host/tests/integration/commands/write-text-file-test.gts b/packages/host/tests/integration/commands/write-text-file-test.gts index e8188ff194..399c4d2b2e 100644 --- a/packages/host/tests/integration/commands/write-text-file-test.gts +++ b/packages/host/tests/integration/commands/write-text-file-test.gts @@ -14,6 +14,8 @@ import { setupLocalIndexing, testRealmURL, testRealmInfo, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -48,11 +50,15 @@ module('Integration | commands | write-text-file', function (hooks) { fetch = getService('network').fetch; }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('writes a text file', async function (assert) { diff --git a/packages/host/tests/integration/components/ai-assistant-panel/debug-message-test.gts b/packages/host/tests/integration/components/ai-assistant-panel/debug-message-test.gts index fe75c02836..67a8c3891a 100644 --- a/packages/host/tests/integration/components/ai-assistant-panel/debug-message-test.gts +++ b/packages/host/tests/integration/components/ai-assistant-panel/debug-message-test.gts @@ -30,6 +30,8 @@ import { setupLocalIndexing, setupOnSave, setupOperatorModeStateCleanup, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../../helpers'; import { setupBaseRealm } from '../../../helpers/base-realm'; import { setupMockMatrix } from '../../../helpers/mock-matrix'; @@ -68,17 +70,21 @@ module('Integration | ai-assistant-panel | debug-message', function (hooks) { let { simulateRemoteMessage } = mockMatrixUtils; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { operatorModeStateService = this.owner.lookup( 'service:operator-mode-state-service', ) as OperatorModeStateService; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - '.realm.json': `{ "name": "${realmName}" }`, - }, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + '.realm.json': `{ "name": "${realmName}" }`, + }, + }), + ); }); function setCardInOperatorModeState( diff --git a/packages/host/tests/integration/components/ai-assistant-panel/reasoning-test.gts b/packages/host/tests/integration/components/ai-assistant-panel/reasoning-test.gts index 7197c6a660..cd7aa8b330 100644 --- a/packages/host/tests/integration/components/ai-assistant-panel/reasoning-test.gts +++ b/packages/host/tests/integration/components/ai-assistant-panel/reasoning-test.gts @@ -22,6 +22,8 @@ import { setupLocalIndexing, setupOnSave, setupOperatorModeStateCleanup, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../../helpers'; import { CardDef, @@ -50,6 +52,7 @@ module('Integration | ai-assistant-panel | reasoning', function (hooks) { setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupCardLogs( hooks, async () => await loader.import(`${baseRealm.url}card-api`), @@ -99,15 +102,17 @@ module('Integration | ai-assistant-panel | reasoning', function (hooks) { }; } - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': { Person }, - 'Person/fadhlan.json': new Person({ - firstName: 'Fadhlan', - }), - '.realm.json': `{ "name": "${realmName}" }`, - }, + await withCachedRealmSetup(async () => { + await setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': { Person }, + 'Person/fadhlan.json': new Person({ + firstName: 'Fadhlan', + }), + '.realm.json': `{ "name": "${realmName}" }`, + }, + }); }); }); diff --git a/packages/host/tests/integration/components/ai-assistant-panel/scrolling-test.gts b/packages/host/tests/integration/components/ai-assistant-panel/scrolling-test.gts index dcc6a7801d..35956070e3 100644 --- a/packages/host/tests/integration/components/ai-assistant-panel/scrolling-test.gts +++ b/packages/host/tests/integration/components/ai-assistant-panel/scrolling-test.gts @@ -23,6 +23,8 @@ import { setupLocalIndexing, setupOnSave, setupOperatorModeStateCleanup, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../../helpers'; import { CardDef, @@ -51,6 +53,7 @@ module('Integration | ai-assistant-panel | scrolling', function (hooks) { setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupCardLogs( hooks, async () => await loader.import(`${baseRealm.url}card-api`), @@ -101,15 +104,17 @@ module('Integration | ai-assistant-panel | scrolling', function (hooks) { }; } - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': { Person }, - 'Person/fadhlan.json': new Person({ - firstName: 'Fadhlan', - }), - '.realm.json': `{ "name": "${realmName}" }`, - }, + await withCachedRealmSetup(async () => { + await setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': { Person }, + 'Person/fadhlan.json': new Person({ + firstName: 'Fadhlan', + }), + '.realm.json': `{ "name": "${realmName}" }`, + }, + }); }); }); diff --git a/packages/host/tests/integration/components/ai-assistant-panel/sending-test.gts b/packages/host/tests/integration/components/ai-assistant-panel/sending-test.gts index 5393b468af..0ffe08f25a 100644 --- a/packages/host/tests/integration/components/ai-assistant-panel/sending-test.gts +++ b/packages/host/tests/integration/components/ai-assistant-panel/sending-test.gts @@ -30,6 +30,8 @@ import { setupLocalIndexing, setupOnSave, setupOperatorModeStateCleanup, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../../helpers'; import { CardDef, @@ -58,6 +60,7 @@ module('Integration | ai-assistant-panel | sending', function (hooks) { setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupCardLogs( hooks, async () => await loader.import(`${baseRealm.url}card-api`), @@ -105,15 +108,17 @@ module('Integration | ai-assistant-panel | sending', function (hooks) { }; } - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': { Person }, - 'Person/fadhlan.json': new Person({ - firstName: 'Fadhlan', - }), - '.realm.json': `{ "name": "${realmName}" }`, - }, + await withCachedRealmSetup(async () => { + await setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': { Person }, + 'Person/fadhlan.json': new Person({ + firstName: 'Fadhlan', + }), + '.realm.json': `{ "name": "${realmName}" }`, + }, + }); }); }); diff --git a/packages/host/tests/integration/components/ask-ai-test.gts b/packages/host/tests/integration/components/ask-ai-test.gts index c65f3dc04c..182e2e07ef 100644 --- a/packages/host/tests/integration/components/ask-ai-test.gts +++ b/packages/host/tests/integration/components/ask-ai-test.gts @@ -20,6 +20,8 @@ import { setupOnSave, assertMessages, setupOperatorModeStateCleanup, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupBaseRealm } from '../../helpers/base-realm'; import { setupMockMatrix } from '../../helpers/mock-matrix'; @@ -41,6 +43,7 @@ module('Integration | ask-ai', function (hooks) { setupLocalIndexing(hooks); setupOnSave(hooks); + setupRealmCacheTeardown(hooks); setupCardLogs( hooks, async () => await loader.import(`${baseRealm.url}card-api`), @@ -68,34 +71,36 @@ module('Integration | ask-ai', function (hooks) { }; }`; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'pet.gts': petCard, - 'Pet/marco.json': { - data: { - attributes: { cardTitle: 'Marco' }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + await withCachedRealmSetup(async () => { + await setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'pet.gts': petCard, + 'Pet/marco.json': { + data: { + attributes: { cardTitle: 'Marco' }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, - }, - 'Pet/mango.json': { - data: { - attributes: { cardTitle: 'Mango' }, - meta: { - adoptsFrom: { - module: `${testRealmURL}pet`, - name: 'Pet', + 'Pet/mango.json': { + data: { + attributes: { cardTitle: 'Mango' }, + meta: { + adoptsFrom: { + module: `${testRealmURL}pet`, + name: 'Pet', + }, }, }, }, + '.realm.json': `{ "name": "Operator Mode Workspace" }`, }, - '.realm.json': `{ "name": "Operator Mode Workspace" }`, - }, + }); }); }); diff --git a/packages/host/tests/integration/components/loading-test.gts b/packages/host/tests/integration/components/loading-test.gts index a73c903fd4..36eef567af 100644 --- a/packages/host/tests/integration/components/loading-test.gts +++ b/packages/host/tests/integration/components/loading-test.gts @@ -12,6 +12,8 @@ import { setupIntegrationTestRealm, setupLocalIndexing, setupOnSave, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { renderCard } from '../../helpers/render-component'; @@ -41,6 +43,8 @@ module('Integration | loading', function (hooks) { autostart: true, }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { let cardWithBrokenIconDefSource = ` import NonExistentIcon from '@cardstack/boxel-icons/non-existent'; @@ -52,13 +56,15 @@ module('Integration | loading', function (hooks) { } `; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'card-with-broken-icon.gts': cardWithBrokenIconDefSource, - '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-o.png" }`, - }, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'card-with-broken-icon.gts': cardWithBrokenIconDefSource, + '.realm.json': `{ "name": "${realmName}", "iconURL": "https://boxel-images.boxel.ai/icons/Letter-o.png" }`, + }, + }), + ); }); test('Cards attempting to import boxel icon that does not exist renders a 404 icon instead', async function (assert) { diff --git a/packages/host/tests/integration/components/text-input-validator-test.gts b/packages/host/tests/integration/components/text-input-validator-test.gts index 7f226e294b..b951bac7ad 100644 --- a/packages/host/tests/integration/components/text-input-validator-test.gts +++ b/packages/host/tests/integration/components/text-input-validator-test.gts @@ -17,6 +17,8 @@ import { setupOnSave, type TestContextWithSave, setupOperatorModeStateCleanup, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { BigIntegerField, @@ -44,6 +46,8 @@ module('Integration | text-input-validator', function (hooks) { autostart: true, }); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { let operatorModeStateService = getService('operator-mode-state-service'); @@ -54,17 +58,19 @@ module('Integration | text-input-validator', function (hooks) { @field someNumber = contains(NumberField); } - ({ realm } = await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'sample.gts': { Sample }, - 'Sample/1.json': new Sample({ - someBigInt: null, - anotherBigInt: '123', - someNumber: 0, - }), - }, - })); + ({ realm } = await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'sample.gts': { Sample }, + 'Sample/1.json': new Sample({ + someBigInt: null, + anotherBigInt: '123', + someNumber: 0, + }), + }, + }), + )); operatorModeStateService.restore({ stacks: [[{ id: `${testRealmURL}Sample/1`, format: 'edit' }]], diff --git a/packages/host/tests/integration/components/text-suggestion-test.gts b/packages/host/tests/integration/components/text-suggestion-test.gts index 26e8531388..5c51b0bd4e 100644 --- a/packages/host/tests/integration/components/text-suggestion-test.gts +++ b/packages/host/tests/integration/components/text-suggestion-test.gts @@ -15,6 +15,8 @@ import { testRealmURL, setupIntegrationTestRealm, setupLocalIndexing, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../../helpers'; import { setupMockMatrix } from '../../helpers/mock-matrix'; import { setupRenderingTest } from '../../helpers/setup'; @@ -26,6 +28,7 @@ let loader: Loader; module('Integration | text-suggestion | card-chooser-title', function (hooks) { setupRenderingTest(hooks); setupLocalIndexing(hooks); + setupRealmCacheTeardown(hooks); let mockMatrixUtils = setupMockMatrix(hooks); @@ -66,15 +69,17 @@ module('Integration | text-suggestion | card-chooser-title', function (hooks) { @field booker = contains(StringField); } - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'article.gts': { Article }, - 'blog-post.gts': { BlogPost }, - 'book.gts': { Book }, - 'booking.gts': { Booking }, - 'post.gts': { Post }, - }, + await withCachedRealmSetup(async () => { + await setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'article.gts': { Article }, + 'blog-post.gts': { BlogPost }, + 'book.gts': { Book }, + 'booking.gts': { Booking }, + 'post.gts': { Post }, + }, + }); }); }); diff --git a/packages/host/tests/integration/message-service-subscription-test.gts b/packages/host/tests/integration/message-service-subscription-test.gts index c5879533ff..d193461071 100644 --- a/packages/host/tests/integration/message-service-subscription-test.gts +++ b/packages/host/tests/integration/message-service-subscription-test.gts @@ -25,6 +25,8 @@ import { setupCardLogs, setupLocalIndexing, setupIntegrationTestRealm, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupRenderingTest } from '../helpers/setup'; @@ -57,11 +59,15 @@ module('Integration | message service subscription', function (hooks) { async () => await loader.import(`${baseRealm.url}card-api`), ); + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: {}, - }); + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: {}, + }), + ); }); test('realm event subscriptions are released when the subscriber is destroyed', async function (assert) { diff --git a/packages/host/tests/integration/realm-querying-test.gts b/packages/host/tests/integration/realm-querying-test.gts index 110b98fdb0..152664e2cc 100644 --- a/packages/host/tests/integration/realm-querying-test.gts +++ b/packages/host/tests/integration/realm-querying-test.gts @@ -16,6 +16,8 @@ import { type CardDocFiles, setupIntegrationTestRealm, testModuleRealm, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupRenderingTest } from '../helpers/setup'; @@ -574,29 +576,33 @@ module(`Integration | realm querying`, function (hooks) { let queryEngine: RealmIndexQueryEngine; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function () { - let { realm } = await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - ...sampleCards, - 'files/sample.txt': 'Hello world', - 'files/sample.md': 'Hello markdown', - 'file-query-card-instance.json': { - data: { - type: 'card', - attributes: { - nameFilter: '', - }, - meta: { - adoptsFrom: { - module: `${testModuleRealm}file-query-card`, - name: 'FileQueryCard', + let { realm } = await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + ...sampleCards, + 'files/sample.txt': 'Hello world', + 'files/sample.md': 'Hello markdown', + 'file-query-card-instance.json': { + data: { + type: 'card', + attributes: { + nameFilter: '', + }, + meta: { + adoptsFrom: { + module: `${testModuleRealm}file-query-card`, + name: 'FileQueryCard', + }, }, }, }, }, - }, - }); + }), + ); queryEngine = realm.realmIndexQueryEngine; }); diff --git a/packages/host/tests/test-helper.js b/packages/host/tests/test-helper.js index 92a8df666a..b2cc907f39 100644 --- a/packages/host/tests/test-helper.js +++ b/packages/host/tests/test-helper.js @@ -16,4 +16,12 @@ setApplication(Application.create(config.APP)); setup(QUnit.assert); setupOperatorModeParametersMatchAssertion(QUnit.assert); +const urlParams = new URLSearchParams(window.location.search); +const isParallelExamRun = + urlParams.has('browser') || urlParams.has('partition'); + +if (isParallelExamRun) { + QUnit.config.failOnZeroTests = false; +} + start(); diff --git a/packages/host/tests/unit/code-ref-test.ts b/packages/host/tests/unit/code-ref-test.ts index b3db9cd9f8..315fa36b14 100644 --- a/packages/host/tests/unit/code-ref-test.ts +++ b/packages/host/tests/unit/code-ref-test.ts @@ -19,6 +19,8 @@ import { setupCardLogs, setupLocalIndexing, setupIntegrationTestRealm, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupRenderingTest } from '../helpers/setup'; @@ -30,13 +32,16 @@ module('code-ref', function (hooks) { let loader: Loader; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { loader = getService('loader-service').loader; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'person.gts': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'person.gts': ` import { contains, field, CardDef } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; export class Person extends CardDef { @@ -44,7 +49,7 @@ module('code-ref', function (hooks) { @field firstName = contains(StringField); } `, - 'code-ref-test.ts': ` + 'code-ref-test.ts': ` import { contains, field, Component, CardDef } from 'https://cardstack.com/base/card-api'; import CodeRefField from 'https://cardstack.com/base/code-ref'; @@ -57,8 +62,9 @@ module('code-ref', function (hooks) { }; } `, - }, - }); + }, + }), + ); }); setupCardLogs( diff --git a/packages/host/tests/unit/loader-parallel-prefetch-test.ts b/packages/host/tests/unit/loader-parallel-prefetch-test.ts index 46eb43dcf1..2770542f8e 100644 --- a/packages/host/tests/unit/loader-parallel-prefetch-test.ts +++ b/packages/host/tests/unit/loader-parallel-prefetch-test.ts @@ -12,6 +12,8 @@ import { setupCardLogs, setupLocalIndexing, setupIntegrationTestRealm, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupRenderingTest } from '../helpers/setup'; @@ -37,69 +39,73 @@ module('Unit | loader prefetch', function (hooks) { let loader: Loader; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { loader = getService('loader-service').loader; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - // Base prefetch fixtures - 'prefetch/main.js': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + // Base prefetch fixtures + 'prefetch/main.js': ` import { slowValue } from './slow-dep'; export function mainValue() { return slowValue; } `, - 'prefetch/slow-dep.js': ` + 'prefetch/slow-dep.js': ` export const slowValue = 'slow'; `, - // Broken dependency fixtures - 'prefetch/broken-main.js': ` + // Broken dependency fixtures + 'prefetch/broken-main.js': ` import './broken-dep'; export function usesBroken() { return true; } `, - 'prefetch/broken-dep.js': ` + 'prefetch/broken-dep.js': ` export const shouldNotLoad = true; `, - // Shared dep fixtures - 'prefetch/shared-parent.js': ` + // Shared dep fixtures + 'prefetch/shared-parent.js': ` import { shared } from './shared-dep'; export function parent() { return shared; } `, - 'prefetch/shared-dep.js': ` + 'prefetch/shared-dep.js': ` export const shared = 'shared'; `, - // Two-parents race fixtures - 'prefetch/parent-a.js': ` + // Two-parents race fixtures + 'prefetch/parent-a.js': ` import { shared } from './shared-dep'; export const a = shared; `, - 'prefetch/parent-b.js': ` + 'prefetch/parent-b.js': ` import { shared } from './shared-dep'; export const b = shared; `, - // Transitive prefetch fixtures - 'prefetch/deep-main.js': ` + // Transitive prefetch fixtures + 'prefetch/deep-main.js': ` import './mid'; export const ok = true; `, - 'prefetch/mid.js': ` + 'prefetch/mid.js': ` import { leaf } from './leaf'; export const mid = leaf; `, - 'prefetch/leaf.js': ` + 'prefetch/leaf.js': ` export const leaf = 'leaf'; `, - // Shim fixture (no file for './shimmed' on purpose; it's shimmed) - 'prefetch/uses-shim.js': ` + // Shim fixture (no file for './shimmed' on purpose; it's shimmed) + 'prefetch/uses-shim.js': ` import { x } from './shimmed'; export const y = x; `, - }, - }); + }, + }), + ); }); setupCardLogs( diff --git a/packages/host/tests/unit/loader-test.ts b/packages/host/tests/unit/loader-test.ts index 1cff8441df..47e0b4447d 100644 --- a/packages/host/tests/unit/loader-test.ts +++ b/packages/host/tests/unit/loader-test.ts @@ -11,6 +11,8 @@ import { setupCardLogs, setupLocalIndexing, setupIntegrationTestRealm, + setupRealmCacheTeardown, + withCachedRealmSetup, } from '../helpers'; import { setupMockMatrix } from '../helpers/mock-matrix'; import { setupRenderingTest } from '../helpers/setup'; @@ -22,58 +24,61 @@ module('Unit | loader', function (hooks) { let loader: Loader; + setupRealmCacheTeardown(hooks); + hooks.beforeEach(async function (this: RenderingTestContext) { loader = getService('loader-service').loader; - await setupIntegrationTestRealm({ - mockMatrixUtils, - contents: { - 'a.js': ` + await withCachedRealmSetup(async () => + setupIntegrationTestRealm({ + mockMatrixUtils, + contents: { + 'a.js': ` import { b } from './b'; export function a() { return 'a' + b(); } `, - 'b.js': ` + 'b.js': ` import { c } from './c'; export function b() { return 'b' + c(); } `, - 'c.js': ` + 'c.js': ` export function c() { return 'c'; } `, - 'd.js': ` + 'd.js': ` import { a } from './a'; import { e } from './e'; export function d() { return a() + e(); } `, - 'e.js': ` + 'e.js': ` throw new Error('intentional error thrown'); `, - 'f.js': ` + 'f.js': ` import { b } from './b'; import { g } from './g'; export function f() { return b() + g(); } `, - 'g.js': ` + 'g.js': ` export function g() { return 'g'; } `, - 'cycle-one.js': ` + 'cycle-one.js': ` import { two } from './cycle-two'; export function one() { return two() - 1; } `, - 'cycle-two.js': ` + 'cycle-two.js': ` import { one } from './cycle-one'; export function two() { return 2; @@ -82,7 +87,7 @@ module('Unit | loader', function (hooks) { return one() * 3; } `, - 'deadlock/a.js': ` + 'deadlock/a.js': ` import { b } from './b'; export function d() { return 'd'; @@ -91,19 +96,19 @@ module('Unit | loader', function (hooks) { return 'a' + b(); } `, - 'deadlock/b.js': ` + 'deadlock/b.js': ` import { c } from './c'; export function b() { return 'b' + c(); } `, - 'deadlock/c.js': ` + 'deadlock/c.js': ` import { d } from './a'; export function c() { return 'c' + d(); } `, - 'person.gts': ` + 'person.gts': ` import { contains, field, CardDef } from 'https://cardstack.com/base/card-api'; import StringField from 'https://cardstack.com/base/string'; export class Person extends CardDef { @@ -115,12 +120,13 @@ module('Unit | loader', function (hooks) { counter++; } `, - 'foo.js': ` + 'foo.js': ` export function checkImportMeta() { return import.meta.url; } export function myLoader() { return import.meta.loader; } `, - }, - }); + }, + }), + ); }); setupCardLogs(