mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
a707348b9b
* feat: add cloud webdriver artifacts * fix: clean up local session after provider release failure * fix: tag cloud webdriver provider requests * feat: connect hosted webdriver providers * docs: document hosted provider credentials * refactor: tighten cloud webdriver provider internals * refactor: consolidate cloud webdriver provider definitions * refactor: collapse hosted webdriver runtime wrapper * refactor: reduce cloud webdriver smell surface * docs: clarify hosted provider interfaces * fix: avoid regex slash trimming in webdriver urls * docs: rename hosted providers to device clouds * fix: align provider profile imports with remote modules * fix: skip local android recovery for provider devices * test: classify cloud provider integration flags * fix: close active cloud connection session * test: cover provider disconnect cli flow * fix: make cloud webdriver sessions launchable * fix: align cloud webdriver input gestures * fix: avoid keyboard input during cloud scroll * fix: constrain cloud webdriver scroll gestures * refactor: isolate cloud webdriver scroll frame * refactor: deduplicate cloud webdriver helpers * refactor: tighten cloud webdriver action types * fix: harden cloud webdriver release * fix: polish provider disconnect diagnostics * refactor: group connection profile helpers * fix: repair rebased internal paths * fix: satisfy cloud webdriver CI guards
96 lines
3.0 KiB
TypeScript
96 lines
3.0 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import http, {
|
|
type IncomingHttpHeaders,
|
|
type IncomingMessage,
|
|
type ServerResponse,
|
|
} from 'node:http';
|
|
|
|
export type CloudWebDriverHttpCall = {
|
|
method: string;
|
|
path: string;
|
|
headers: IncomingHttpHeaders;
|
|
body?: unknown;
|
|
};
|
|
|
|
export abstract class CloudWebDriverTestServer {
|
|
readonly calls: CloudWebDriverHttpCall[] = [];
|
|
url = '';
|
|
|
|
constructor() {
|
|
const server = http.createServer();
|
|
server.on('request', async (req, res) => await this.handle(req, res));
|
|
cloudWebDriverHttpServers.set(this, server);
|
|
}
|
|
|
|
protected abstract respond(call: CloudWebDriverHttpCall, res: ServerResponse): void;
|
|
|
|
private async handle(req: IncomingMessage, res: ServerResponse): Promise<void> {
|
|
const body = await readRequestBody(req);
|
|
const call: CloudWebDriverHttpCall = {
|
|
method: req.method ?? 'GET',
|
|
path: req.url ?? '/',
|
|
headers: req.headers,
|
|
...(body === undefined ? {} : { body }),
|
|
};
|
|
this.calls.push(call);
|
|
this.respond(call, res);
|
|
}
|
|
}
|
|
|
|
const cloudWebDriverHttpServers = new WeakMap<CloudWebDriverTestServer, http.Server>();
|
|
|
|
export type StartedCloudWebDriverTestServer<T extends CloudWebDriverTestServer> = T & {
|
|
close(): Promise<void>;
|
|
};
|
|
|
|
export async function startCloudWebDriverTestServer<T extends CloudWebDriverTestServer>(
|
|
testServer: T,
|
|
): Promise<StartedCloudWebDriverTestServer<T>> {
|
|
const server = getCloudWebDriverHttpServer(testServer);
|
|
await new Promise<void>((resolve, reject) => {
|
|
server.once('error', reject);
|
|
server.listen(0, '127.0.0.1', resolve);
|
|
});
|
|
const address = server.address();
|
|
assert.ok(address && typeof address === 'object');
|
|
testServer.url = `http://127.0.0.1:${address.port}`;
|
|
return Object.assign(testServer, {
|
|
close: async () => await closeCloudWebDriverTestServer(testServer),
|
|
});
|
|
}
|
|
|
|
export function writeCloudWebDriverTestJson(
|
|
res: ServerResponse,
|
|
body: unknown,
|
|
status = 200,
|
|
): void {
|
|
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify(body));
|
|
}
|
|
|
|
async function readRequestBody(req: IncomingMessage): Promise<unknown> {
|
|
const chunks: Buffer[] = [];
|
|
for await (const chunk of req) {
|
|
chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);
|
|
}
|
|
const buffer = Buffer.concat(chunks);
|
|
if (req.headers['content-type']?.startsWith('multipart/form-data') === true) {
|
|
return { multipartBytes: buffer.length };
|
|
}
|
|
const text = buffer.toString('utf8');
|
|
return text ? (JSON.parse(text) as unknown) : undefined;
|
|
}
|
|
|
|
function getCloudWebDriverHttpServer(testServer: CloudWebDriverTestServer): http.Server {
|
|
const server = cloudWebDriverHttpServers.get(testServer);
|
|
assert.ok(server);
|
|
return server;
|
|
}
|
|
|
|
async function closeCloudWebDriverTestServer(testServer: CloudWebDriverTestServer): Promise<void> {
|
|
const server = getCloudWebDriverHttpServer(testServer);
|
|
await new Promise<void>((resolve, reject) => {
|
|
server.close((error) => (error ? reject(error) : resolve()));
|
|
});
|
|
}
|