Skip to content

Commit ab81606

Browse files
committed
test(core): cover brand-guards for detached calls
- APIPromise: detached then/catch/finally do not throw private-field TypeError - Pagination: AbstractPage.getNextPage guarded under detachment - Streaming: Stream.tee remains stable under detachment
1 parent acadd48 commit ab81606

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

tests/core/brand-guards.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { APIPromise } from 'openai/core/api-promise';
2+
import { AbstractPage, Page } from 'openai/core/pagination';
3+
import { Stream } from 'openai/core/streaming';
4+
5+
const dummyResponseProps: any = { response: new Response(), options: {} };
6+
const dummyParse = (_client: any, _props: any) => ({ data: null, response: new Response() });
7+
8+
describe('core brand-guard stability', () => {
9+
test('APIPromise.then with mismatched this does not throw private-field TypeError', async () => {
10+
const fake: any = Object.create(APIPromise.prototype);
11+
fake.responsePromise = Promise.resolve(dummyResponseProps);
12+
fake.parseResponse = dummyParse;
13+
14+
const call = () => (APIPromise.prototype.then as any).call(fake, () => {});
15+
expect(call).toThrow(Error);
16+
expect(call).not.toThrow(/private member/i);
17+
});
18+
19+
test('APIPromise.catch with mismatched this does not throw private-field TypeError', async () => {
20+
const fake: any = Object.create(APIPromise.prototype);
21+
fake.responsePromise = Promise.resolve(dummyResponseProps);
22+
fake.parseResponse = dummyParse;
23+
24+
const call = () => (APIPromise.prototype.catch as any).call(fake, () => {});
25+
expect(call).toThrow(Error);
26+
expect(call).not.toThrow(/private member/i);
27+
});
28+
29+
test('APIPromise.finally with mismatched this does not throw private-field TypeError', async () => {
30+
const fake: any = Object.create(APIPromise.prototype);
31+
fake.responsePromise = Promise.resolve(dummyResponseProps);
32+
fake.parseResponse = dummyParse;
33+
34+
const call = () => (APIPromise.prototype.finally as any).call(fake, () => {});
35+
expect(call).toThrow(Error);
36+
expect(call).not.toThrow(/private member/i);
37+
});
38+
39+
test('AbstractPage.getNextPage with mismatched this does not throw private-field TypeError', async () => {
40+
class TestPage<Item> extends Page<Item> {
41+
override nextPageRequestOptions() {
42+
return { path: '/v1/anything', method: 'get' } as any;
43+
}
44+
}
45+
46+
const fake: any = Object.create(TestPage.prototype);
47+
fake.options = { path: '/v1/anything', method: 'get' };
48+
fake.getPaginatedItems = () => [1];
49+
fake.response = new Response();
50+
fake.body = {};
51+
52+
const call = () => (AbstractPage.prototype.getNextPage as any).call(fake);
53+
await expect(call()).rejects.toBeInstanceOf(Error);
54+
await expect(call()).rejects.not.toThrow(/private member/i);
55+
});
56+
57+
test('Stream.tee with mismatched this does not throw private-field TypeError', () => {
58+
const fake: any = Object.create(Stream.prototype);
59+
fake.controller = new AbortController();
60+
fake.iterator = async function* () {};
61+
62+
const call = () => (Stream.prototype.tee as any).call(fake);
63+
expect(call).not.toThrow(/private member/i);
64+
});
65+
});

0 commit comments

Comments
 (0)