Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/realm-server/tests/fixtures/blank/.realm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions packages/realm-server/tests/fixtures/simple/.realm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
14 changes: 14 additions & 0 deletions packages/realm-server/tests/fixtures/simple/person-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"data": {
"type": "card",
"attributes": {
"firstName": "Mango"
},
"meta": {
"adoptsFrom": {
"module": "./person.gts",
"name": "Person"
}
}
}
}
22 changes: 22 additions & 0 deletions packages/realm-server/tests/fixtures/simple/person.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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 {
static displayName = 'Person';
@field firstName = contains(StringField);
@field cardTitle = contains(StringField, {
computeVia: function (this: Person) {
return this.firstName;
},
});
static isolated = class Isolated extends Component<typeof this> {
<template>
<h1 data-test-card><@fields.firstName /></h1>
</template>
};
}
5 changes: 5 additions & 0 deletions packages/realm-server/tests/fixtures/simple/sample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Sample

Plain markdown content used as the "one file" component of the simple
fixture — exercises non-card file handling without dragging in any of
the realistic fixture's card-content baggage.
94 changes: 89 additions & 5 deletions packages/realm-server/tests/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,7 @@ type InternalPermissionedRealmsSetupOptions = {
realmURL: string;
permissions: RealmPermissions;
fileSystem?: Record<string, string | LooseSingleCardDocument>;
fixture?: RealmFixtureName;
}[];
prerenderer?: Prerenderer;
};
Expand All @@ -1392,14 +1393,26 @@ async function startPermissionedRealmsFixture(
let realms: PermissionedRealmsFixtureRealm[] = [];

for (let realmArg of realmConfigs.values()) {
if (realmArg.fileSystem && realmArg.fixture) {
throw new Error(
'setupPermissionedRealms: pass either `fileSystem` or `fixture` per realm, not both',
);
}
let testRealmDir = dirSync().name;
if (!realmArg.fileSystem) {
// The plural helper has historically left the disk empty by default;
// preserve that — only copy a fixture onto disk when one is named.
if (realmArg.fixture) {
copySync(fixtureDir(realmArg.fixture), testRealmDir);
}
}
let {
testRealmDir: realmPath,
testRealm: realm,
testRealmHttpServer: realmHttpServer,
testRealmAdapter: realmAdapter,
} = await runTestRealmServer({
virtualNetwork: await createVirtualNetwork(),
testRealmDir: dirSync().name,
testRealmDir,
realmsRootPath: dirSync().name,
realmURL: new URL(realmArg.realmURL),
fileSystem: realmArg.fileSystem,
Expand All @@ -1412,7 +1425,7 @@ async function startPermissionedRealmsFixture(
});
realms.push({
realm,
realmPath,
realmPath: testRealmDir,
realmHttpServer,
realmAdapter,
});
Expand Down Expand Up @@ -1444,6 +1457,7 @@ export function setupPermissionedRealms(
realmURL: string;
permissions: RealmPermissions;
fileSystem?: Record<string, string | LooseSingleCardDocument>;
fixture?: RealmFixtureName;
}[];
prerenderer?: Prerenderer;
// Internal hook used by cached setup wrappers
Expand Down Expand Up @@ -1777,10 +1791,34 @@ function realmEventIsIndex(
return event.eventName === 'index';
}

// The three realm fixtures available under tests/fixtures/. See CS-10009.
// blank — `.realm.json: {}` only; for tests that need a working realm
// with no card content.
// simple — one card def (Person), one instance, one non-card file; for
// tests that need *some* indexed content but nothing exotic.
// realistic — the historical tests/cards/ kitchen sink; for tests that
// lean on specific instances, cyclic imports, error cases,
// Unicode filenames, etc. To be renamed to fixtures/realistic
// in a follow-up; until then `fixtureDir('realistic')` points
// at the old path.
export type RealmFixtureName = 'blank' | 'simple' | 'realistic';

export function fixtureDir(name: RealmFixtureName): string {
switch (name) {
case 'blank':
return join(__dirname, '..', 'fixtures', 'blank');
case 'simple':
return join(__dirname, '..', 'fixtures', 'simple');
case 'realistic':
return join(__dirname, '..', 'cards');
}
}

type InternalPermissionedRealmSetupOptions = {
permissions: RealmPermissions;
realmURL?: URL;
fileSystem?: Record<string, string | LooseSingleCardDocument>;
fixture?: RealmFixtureName;
subscribeToRealmEvents?: boolean;
prerenderer?: Prerenderer;
published?: boolean;
Expand All @@ -1796,6 +1834,7 @@ async function startPermissionedRealmFixture(
permissions,
realmURL,
fileSystem,
fixture,
subscribeToRealmEvents = false,
prerenderer,
published = false,
Expand All @@ -1807,6 +1846,11 @@ async function startPermissionedRealmFixture(
request: SuperTest<Test>;
dir: DirResult;
}> {
if (fileSystem && fixture) {
throw new Error(
'setupPermissionedRealm: pass either `fileSystem` or `fixture`, not both',
);
}
let resolvedRealmURL = realmURL ?? testRealmURL;
let dir = dirSync();

Expand Down Expand Up @@ -1838,9 +1882,12 @@ async function startPermissionedRealmFixture(

ensureDirSync(testRealmDir);

// If a fileSystem is provided, use it to populate the test realm, otherwise copy the default cards
// If a fileSystem is provided, the realm is populated through createRealm
// from that object. Otherwise copy a fixture folder onto disk. Default to
// `realistic` to preserve existing behavior until the final PR of CS-10009
// flips it to `blank`.
if (!fileSystem) {
copySync(join(__dirname, '..', 'cards'), testRealmDir);
copySync(fixtureDir(fixture ?? 'realistic'), testRealmDir);
}

let virtualNetwork = createVirtualNetwork();
Expand Down Expand Up @@ -1917,6 +1964,7 @@ export function setupPermissionedRealm(
permissions,
realmURL,
fileSystem,
fixture,
onRealmSetup,
subscribeToRealmEvents = false,
mode = 'beforeEach',
Expand All @@ -1929,6 +1977,7 @@ export function setupPermissionedRealm(
permissions: RealmPermissions;
realmURL?: URL;
fileSystem?: Record<string, string | LooseSingleCardDocument>;
fixture?: RealmFixtureName;
onRealmSetup?: (args: {
dbAdapter: PgAdapter;
publisher: QueuePublisher;
Expand Down Expand Up @@ -1970,6 +2019,7 @@ export function setupPermissionedRealm(
} = await startPermissionedRealmFixture(dbAdapter, publisher, runner, {
realmURL,
fileSystem,
fixture,
permissions,
subscribeToRealmEvents,
prerenderer,
Expand Down Expand Up @@ -2009,12 +2059,21 @@ function permissionedRealmTemplateCacheKey(
options: SetupPermissionedRealmCachedOptions,
): string {
let resolvedRealmURL = options.realmURL ?? testRealmURL;
// Canonicalize the fixture choice so callers that omit `fixture` (and
// implicitly get 'realistic') share a cache with callers that pass
// `fixture: 'realistic'` explicitly. When `fileSystem` is provided, the
// fixture choice is irrelevant — fileSystem's own hash carries the
// content.
let resolvedFixture = options.fileSystem
? null
: (options.fixture ?? 'realistic');
Comment on lines +2062 to +2069
return hashCacheKeyPayload({
version: 1,
type: 'permissioned-realm',
realmURL: resolvedRealmURL.href,
permissions: options.permissions,
fileSystem: options.fileSystem ?? null,
fixture: resolvedFixture,
subscribeToRealmEvents: Boolean(options.subscribeToRealmEvents),
published: Boolean(options.published),
cardSizeLimitBytes: options.cardSizeLimitBytes ?? null,
Expand Down Expand Up @@ -2058,6 +2117,7 @@ async function buildPermissionedRealmTemplate(
{
realmURL: options.realmURL,
fileSystem: options.fileSystem,
fixture: options.fixture,
permissions: options.permissions,
subscribeToRealmEvents: options.subscribeToRealmEvents,
prerenderer: options.prerenderer,
Expand Down Expand Up @@ -2150,6 +2210,20 @@ export function setupPermissionedRealmCached(
hooks: NestedHooks,
options: SetupPermissionedRealmCachedOptions,
) {
// Validate before the cache lookup. The cache key canonicalizes
// `fixture` to `null` when `fileSystem` is present (see
// permissionedRealmTemplateCacheKey), so an invalid call passing
// both would hash the same as a valid `fileSystem`-only call and
// silently reuse that template — the throw in
// startPermissionedRealmFixture only fires later at beforeEach,
// after the misleading reuse. Mirror the same check up front so
// an invalid combo errors at test-module load time, before any
// cache work runs.
if (options.fileSystem && options.fixture) {
throw new Error(
'setupPermissionedRealmCached: pass either `fileSystem` or `fixture`, not both',
);
}
let acquiredTemplateDatabase: string | undefined;

hooks.before(async function () {
Expand Down Expand Up @@ -2301,6 +2375,16 @@ export function setupPermissionedRealmsCached(
hooks: NestedHooks,
options: SetupPermissionedRealmsCachedOptions,
) {
// Same up-front validation as setupPermissionedRealmCached so the
// per-realm fileSystem/fixture conflict errors at test-module load
// time rather than at beforeEach inside startPermissionedRealmsFixture.
for (let realm of options.realms) {
if (realm.fileSystem && realm.fixture) {
throw new Error(
`setupPermissionedRealmsCached: realm "${realm.realmURL}" passed both \`fileSystem\` and \`fixture\` — pass one or the other, not both`,
);
}
}
let acquiredTemplateDatabase: string | undefined;

hooks.before(async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module(`realm-endpoints/${basename(__filename)}`, function () {
}

setupPermissionedRealmCached(hooks, {
fixture: 'simple',
permissions: {
writer: ['read', 'write'],
reader: ['read'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module(`server-endpoints/${basename(__filename)}`, function () {
}

setupPermissionedRealmCached(hooks, {
fileSystem: {},
fixture: 'blank',
permissions: {
'*': ['read', 'write'],
},
Expand Down
Loading