feat: embed a Flutter G4F client with Cronet, cookie jar, and origin WebView
Port the Oracle off the Python g4f container onto on-device providers: Chromium HTTP via Cronet, a shared cookie session, IterList retry, hosted OpenAI-compat aggregators, and same-origin WebView fallbacks instead of CORS fetch.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
import 'package:words999/g4f/cookie_jar.dart';
|
||||
import 'package:words999/g4f/http_client.dart';
|
||||
import 'package:words999/g4f/http_util.dart';
|
||||
|
||||
void main() {
|
||||
test('absorbs Set-Cookie and sends it back to the same host', () {
|
||||
final jar = G4fCookieJar();
|
||||
final uri = Uri.parse('https://phindai.org/');
|
||||
jar.absorb(uri, {
|
||||
'set-cookie': 'sid=abc; Path=/; Domain=.phindai.org, nonce=fff; Path=/',
|
||||
});
|
||||
final header = jar.headerFor(Uri.parse('https://phindai.org/wp-admin/admin-ajax.php'));
|
||||
expect(header, contains('sid=abc'));
|
||||
expect(header, contains('nonce=fff'));
|
||||
expect(jar.headerFor(Uri.parse('https://evil.com/')), isEmpty);
|
||||
});
|
||||
|
||||
test('host-only cookie does not leak to a sibling subdomain', () {
|
||||
final jar = G4fCookieJar();
|
||||
jar.absorb(Uri.parse('https://chat.example.com/'), {
|
||||
'set-cookie': 'id=1; Path=/',
|
||||
});
|
||||
expect(jar.headerFor(Uri.parse('https://chat.example.com/api')), contains('id=1'));
|
||||
expect(jar.headerFor(Uri.parse('https://other.example.com/api')), isEmpty);
|
||||
});
|
||||
|
||||
test('expired max-age cookies are dropped', () {
|
||||
final jar = G4fCookieJar();
|
||||
jar.absorb(Uri.parse('https://example.com/'), {
|
||||
'set-cookie': 'gone=1; Max-Age=0; Path=/',
|
||||
});
|
||||
expect(jar.headerFor(Uri.parse('https://example.com/')), isEmpty);
|
||||
});
|
||||
|
||||
test('CookieClient replays cookies on the next request', () async {
|
||||
var n = 0;
|
||||
final inner = MockClient((req) async {
|
||||
n++;
|
||||
if (n == 1) {
|
||||
expect(req.headers['cookie'], isNull);
|
||||
return http.Response(
|
||||
'ok',
|
||||
200,
|
||||
headers: {'set-cookie': 'sid=abc; Path=/; Domain=example.com'},
|
||||
);
|
||||
}
|
||||
expect(req.headers['cookie'], contains('sid=abc'));
|
||||
return http.Response('ok2', 200);
|
||||
});
|
||||
final jar = G4fCookieJar();
|
||||
final client = CookieClient(inner, jar);
|
||||
await client.get(Uri.parse('https://example.com/'));
|
||||
await client.get(Uri.parse('https://example.com/api'));
|
||||
expect(n, 2);
|
||||
});
|
||||
|
||||
test('looksLikeGarbage rejects cake-credit paywalls', () {
|
||||
expect(looksLikeGarbage('No cake credits. Bake proof-of-work cakes'), isTrue);
|
||||
expect(looksLikeGarbage('{"type":"insufficient_credits"}'), isTrue);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user