Skip to content

Commit fbdedfb

Browse files
committed
Move lint endpoint test to its own file
1 parent 84c93a0 commit fbdedfb

4 files changed

Lines changed: 265 additions & 31 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ jobs:
257257
"queue-test.ts",
258258
"realm-endpoints/directory-test.ts",
259259
"realm-endpoints/info-test.ts",
260+
"realm-endpoints/lint-test.ts",
260261
"realm-endpoints/mtimes-test.ts",
261262
"realm-endpoints/permissions-test.ts",
262263
"realm-endpoints/search-test.ts",

packages/realm-server/tests/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import './card-source-endpoints-test';
1414
import './realm-endpoints-test';
1515
import './realm-endpoints/directory-test';
1616
import './realm-endpoints/info-test';
17+
import './realm-endpoints/lint-test';
1718
import './realm-endpoints/mtimes-test';
1819
import './realm-endpoints/permissions-test';
1920
import './realm-endpoints/search-test';

packages/realm-server/tests/realm-endpoints-test.ts

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -567,37 +567,6 @@ module(basename(__filename), function () {
567567
'true',
568568
);
569569
});
570-
571-
module('linting endpoint', function () {
572-
setupPermissionedRealm(hooks, {
573-
john: ['read', 'write'],
574-
});
575-
576-
test('401 with invalid JWT', async function (assert) {
577-
let response = await request
578-
.post('/_lint')
579-
.set('Authorization', `Bearer invalid-token`)
580-
.set('X-HTTP-Method-Override', 'QUERY')
581-
.send(`console.log('hi')`);
582-
583-
assert.strictEqual(response.status, 401, 'HTTP 401 status');
584-
});
585-
586-
test('user can do a lint with fix', async function (assert) {
587-
let response = await request
588-
.post('/_lint')
589-
.set(
590-
'Authorization',
591-
`Bearer ${createJWT(testRealm, 'john', ['read', 'write'])}`,
592-
)
593-
.set('X-HTTP-Method-Override', 'QUERY')
594-
.set('Accept', 'application/json')
595-
.send(`console.log('hi')`);
596-
597-
assert.strictEqual(response.status, 200, 'HTTP 200 status');
598-
assert.strictEqual(response.body, 'xxx');
599-
});
600-
});
601570
});
602571

603572
module('Realm server with realm mounted at the origin', function (hooks) {
Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
import { module, test } from 'qunit';
2+
import supertest, { Test, SuperTest } from 'supertest';
3+
import { join, resolve, basename } from 'path';
4+
import { Server } from 'http';
5+
import { dirSync, setGracefulCleanup, type DirResult } from 'tmp';
6+
import { copySync, ensureDirSync } from 'fs-extra';
7+
import {
8+
baseRealm,
9+
Realm,
10+
RealmPermissions,
11+
type LooseSingleCardDocument,
12+
type QueuePublisher,
13+
type QueueRunner,
14+
} from '@cardstack/runtime-common';
15+
import {
16+
setupCardLogs,
17+
setupBaseRealmServer,
18+
runTestRealmServer,
19+
setupDB,
20+
realmServerTestMatrix,
21+
realmSecretSeed,
22+
createVirtualNetwork,
23+
createVirtualNetworkAndLoader,
24+
matrixURL,
25+
closeServer,
26+
} from '../helpers';
27+
import '@cardstack/runtime-common/helpers/code-equality-assertion';
28+
import { MatrixClient } from '@cardstack/runtime-common/matrix-client';
29+
import { type PgAdapter } from '@cardstack/postgres';
30+
import { resetCatalogRealms } from '../../handlers/handle-fetch-catalog-realms';
31+
32+
setGracefulCleanup();
33+
const testRealmURL = new URL('http://127.0.0.1:4444/');
34+
const testRealm2URL = new URL('http://127.0.0.1:4445/test/');
35+
const distDir = resolve(join(__dirname, '..', '..', '..', 'host', 'dist'));
36+
console.log(`using host dist dir: ${distDir}`);
37+
38+
let createJWT = (
39+
realm: Realm,
40+
user: string,
41+
permissions: RealmPermissions['user'] = [],
42+
) => {
43+
return realm.createJWT(
44+
{
45+
user,
46+
realm: realm.url,
47+
permissions,
48+
sessionRoom: `test-session-room-for-${user}`,
49+
},
50+
'7d',
51+
);
52+
};
53+
54+
module(`realm-endpoints/${basename(__filename)}`, function () {
55+
module('Realm-specific Endpoints | POST _lint', function (hooks) {
56+
let testRealm: Realm;
57+
let testRealmHttpServer: Server;
58+
let request: SuperTest<Test>;
59+
let dir: DirResult;
60+
let testRealmHttpServer2: Server;
61+
let testRealm2: Realm;
62+
let dbAdapter2: PgAdapter;
63+
let publisher: QueuePublisher;
64+
let runner: QueueRunner;
65+
let testRealmDir: string;
66+
let seedRealm: Realm | undefined;
67+
68+
function setupPermissionedRealm(
69+
hooks: NestedHooks,
70+
permissions: RealmPermissions,
71+
fileSystem?: Record<string, string | LooseSingleCardDocument>,
72+
) {
73+
setupDB(hooks, {
74+
beforeEach: async (_dbAdapter, publisher, runner) => {
75+
dir = dirSync();
76+
let testRealmDir = join(dir.name, '..', 'realm_server_1', 'test');
77+
ensureDirSync(testRealmDir);
78+
// If a fileSystem is provided, use it to populate the test realm, otherwise copy the default cards
79+
if (!fileSystem) {
80+
copySync(join(__dirname, '..', 'cards'), testRealmDir);
81+
}
82+
83+
let virtualNetwork = createVirtualNetwork();
84+
85+
({ testRealm, testRealmHttpServer } = await runTestRealmServer({
86+
virtualNetwork,
87+
testRealmDir,
88+
realmsRootPath: join(dir.name, '..', 'realm_server_1'),
89+
realmURL: testRealmURL,
90+
permissions,
91+
dbAdapter: _dbAdapter,
92+
runner,
93+
publisher,
94+
matrixURL,
95+
fileSystem,
96+
}));
97+
98+
request = supertest(testRealmHttpServer);
99+
},
100+
});
101+
}
102+
103+
function setupMatrixRoom(hooks: NestedHooks) {
104+
let matrixClient = new MatrixClient({
105+
matrixURL: realmServerTestMatrix.url,
106+
// it's a little awkward that we are hijacking a realm user to pretend to
107+
// act like a normal user, but that's what's happening here
108+
username: 'node-test_realm',
109+
seed: realmSecretSeed,
110+
});
111+
112+
let testAuthRoomId: string | undefined;
113+
114+
hooks.beforeEach(async function () {
115+
await matrixClient.login();
116+
let userId = matrixClient.getUserId()!;
117+
118+
let response = await request
119+
.post('/_server-session')
120+
.send(JSON.stringify({ user: userId }))
121+
.set('Accept', 'application/json')
122+
.set('Content-Type', 'application/json');
123+
124+
let json = response.body;
125+
126+
let { joined_rooms: rooms } = await matrixClient.getJoinedRooms();
127+
128+
if (!rooms.includes(json.room)) {
129+
await matrixClient.joinRoom(json.room);
130+
}
131+
132+
await matrixClient.sendEvent(json.room, 'm.room.message', {
133+
body: `auth-response: ${json.challenge}`,
134+
msgtype: 'm.text',
135+
});
136+
137+
response = await request
138+
.post('/_server-session')
139+
.send(JSON.stringify({ user: userId, challenge: json.challenge }))
140+
.set('Accept', 'application/json')
141+
.set('Content-Type', 'application/json');
142+
143+
testAuthRoomId = json.room;
144+
145+
await matrixClient.setAccountData('boxel.session-rooms', {
146+
[userId]: json.room,
147+
});
148+
});
149+
150+
return {
151+
matrixClient,
152+
getMessagesSince: async function (since: number) {
153+
let allMessages = await matrixClient.roomMessages(testAuthRoomId!);
154+
let messagesAfterSentinel = allMessages.filter(
155+
(m) => m.origin_server_ts > since,
156+
);
157+
158+
return messagesAfterSentinel;
159+
},
160+
};
161+
}
162+
163+
let { virtualNetwork, loader } = createVirtualNetworkAndLoader();
164+
165+
setupCardLogs(
166+
hooks,
167+
async () => await loader.import(`${baseRealm.url}card-api`),
168+
);
169+
170+
setupBaseRealmServer(hooks, virtualNetwork, matrixURL);
171+
172+
hooks.beforeEach(async function () {
173+
dir = dirSync();
174+
copySync(join(__dirname, '..', 'cards'), dir.name);
175+
});
176+
177+
hooks.afterEach(async function () {
178+
await closeServer(testRealmHttpServer);
179+
resetCatalogRealms();
180+
});
181+
182+
setupPermissionedRealm(hooks, {
183+
'*': ['read', 'write'],
184+
});
185+
186+
setupMatrixRoom(hooks);
187+
188+
async function startRealmServer(
189+
dbAdapter: PgAdapter,
190+
publisher: QueuePublisher,
191+
runner: QueueRunner,
192+
) {
193+
if (testRealm2) {
194+
virtualNetwork.unmount(testRealm2.handle);
195+
}
196+
({
197+
seedRealm,
198+
testRealm: testRealm2,
199+
testRealmHttpServer: testRealmHttpServer2,
200+
} = await runTestRealmServer({
201+
virtualNetwork,
202+
testRealmDir,
203+
realmsRootPath: join(dir.name, '..', 'realm_server_2'),
204+
realmURL: testRealm2URL,
205+
dbAdapter,
206+
publisher,
207+
runner,
208+
matrixURL,
209+
}));
210+
211+
await testRealm.logInToMatrix();
212+
}
213+
214+
setupDB(hooks, {
215+
beforeEach: async (_dbAdapter, _publisher, _runner) => {
216+
dbAdapter2 = _dbAdapter;
217+
publisher = _publisher;
218+
runner = _runner;
219+
testRealmDir = join(dir.name, '..', 'realm_server_2', 'test');
220+
ensureDirSync(testRealmDir);
221+
copySync(join(__dirname, '..', 'cards'), testRealmDir);
222+
await startRealmServer(dbAdapter2, publisher, runner);
223+
},
224+
afterEach: async () => {
225+
if (seedRealm) {
226+
virtualNetwork.unmount(seedRealm.handle);
227+
}
228+
await closeServer(testRealmHttpServer2);
229+
},
230+
});
231+
232+
module('linting endpoint', function () {
233+
setupPermissionedRealm(hooks, {
234+
john: ['read', 'write'],
235+
});
236+
237+
test('401 with invalid JWT', async function (assert) {
238+
let response = await request
239+
.post('/_lint')
240+
.set('Authorization', `Bearer invalid-token`)
241+
.set('X-HTTP-Method-Override', 'QUERY')
242+
.send(`console.log('hi')`);
243+
244+
assert.strictEqual(response.status, 401, 'HTTP 401 status');
245+
});
246+
247+
test('user can do a lint with fix', async function (assert) {
248+
let response = await request
249+
.post('/_lint')
250+
.set(
251+
'Authorization',
252+
`Bearer ${createJWT(testRealm, 'john', ['read', 'write'])}`,
253+
)
254+
.set('X-HTTP-Method-Override', 'QUERY')
255+
.set('Accept', 'application/json')
256+
.send(`console.log('hi')`);
257+
258+
assert.strictEqual(response.status, 200, 'HTTP 200 status');
259+
assert.strictEqual(response.body, 'xxx');
260+
});
261+
});
262+
});
263+
});

0 commit comments

Comments
 (0)