Allow Richese reveal during selected responses
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
a1b2aacbac
commit
82d857b667
9 files changed
+518
-4
No files matched your search
@@ -1,6 +1,8 @@
|
||||
// @dune-suite integration
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { Agent as HttpAgent, request as httpRequest } from 'node:http';
|
||||
import { Agent as HttpsAgent, request as httpsRequest } from 'node:https';
|
||||
import type { GameView } from '../game/engine';
|
||||
import type { TalkPage } from '../lib/table-talk';
|
||||
const base = process.env.DUNE_TEST_URL ?? 'http://localhost:3000';
|
||||
@@ -230,3 +232,59 @@ void test('discussion HTTP retries save once and seat recovery inherits conversa
|
||||
{ messages: [], before: null, muted: false },
|
||||
);
|
||||
});
|
||||
|
||||
/** Reuse one connection when the server permits it; a server that explicitly
|
||||
* closes a connection may instead provide a fresh one. Never retry a POST. */
|
||||
void test('rejected discussion posts leave the next recovered-seat request usable', async () => {
|
||||
const f = await fixture();
|
||||
const endpoint = f.path + '/messages';
|
||||
const message = { id: crypto.randomUUID(), recipientId: f.b.data.me, text: 'Keep-alive recovery witness.' };
|
||||
assert.equal((await request(endpoint, message, f.a.cookie)).status, 200);
|
||||
const recoverySecret = 'b8'.repeat(32);
|
||||
assert.equal((await request(f.path + '/control', {
|
||||
type: 'setRecoveryKey', version: f.version, recoverySecret,
|
||||
}, f.a.cookie)).status, 200);
|
||||
const recovered = await request(f.path + '/control', {
|
||||
type: 'recoverSeat', playerId: f.a.data.me, recoverySecret,
|
||||
operationId: crypto.randomUUID(),
|
||||
newSessionToken: crypto.randomUUID().replaceAll('-', '') + crypto.randomUUID().replaceAll('-', ''),
|
||||
});
|
||||
assert.equal(recovered.status, 200);
|
||||
assert.ok(recovered.cookie);
|
||||
|
||||
const address = new URL(base);
|
||||
const agent = address.protocol === 'https:'
|
||||
? new HttpsAgent({ keepAlive: true, maxSockets: 1 })
|
||||
: new HttpAgent({ keepAlive: true, maxSockets: 1 });
|
||||
async function onConnection(path: string, cookie: string, body?: unknown, origin?: string) {
|
||||
const url = new URL(path, base);
|
||||
const payload = body === undefined ? undefined : JSON.stringify(body);
|
||||
const send = url.protocol === 'https:' ? httpsRequest : httpRequest;
|
||||
return await new Promise<{status: number; body: string}>((resolve, reject) => {
|
||||
const req = send(url, {
|
||||
agent, method: payload === undefined ? 'GET' : 'POST', signal: AbortSignal.timeout(15_000),
|
||||
headers: { cookie, ...(origin ? { origin } : {}),
|
||||
...(payload === undefined ? {} : { 'content-type': 'application/json', 'content-length': Buffer.byteLength(payload) }) },
|
||||
}, response => {
|
||||
const chunks: Buffer[] = [];
|
||||
response.on('data', chunk => chunks.push(Buffer.from(chunk)));
|
||||
response.on('error', reject);
|
||||
response.on('end', () => resolve({status: response.statusCode ?? 0, body: Buffer.concat(chunks).toString('utf8')}));
|
||||
});
|
||||
req.on('error', reject);
|
||||
req.end(payload);
|
||||
});
|
||||
}
|
||||
try {
|
||||
const restoredPath = endpoint + `?recipient=${f.b.data.me}`;
|
||||
assert.equal((await onConnection(endpoint, f.a.cookie!, message)).status, 409);
|
||||
const restored = await onConnection(restoredPath, recovered.cookie);
|
||||
assert.equal(restored.status, 200);
|
||||
assert.deepEqual((JSON.parse(restored.body) as TalkPage).messages.map(row => row.id), [message.id]);
|
||||
assert.equal((await onConnection(endpoint, recovered.cookie, message, 'https://foreign.invalid')).status, 403);
|
||||
assert.equal((await onConnection(restoredPath, recovered.cookie)).status, 200);
|
||||
assert.equal((await onConnection(restoredPath, f.a.cookie!)).status, 409);
|
||||
} finally {
|
||||
agent.destroy();
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user