175 lines
5.9 KiB
Dart
175 lines
5.9 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:reelbox/data/api_service.dart';
|
|
import 'package:reelbox/data/home_banners.dart';
|
|
|
|
class BannerApi extends ApiService {
|
|
String? requested;
|
|
dynamic response;
|
|
bool fail = false;
|
|
@override
|
|
Future<dynamic> get(String path, {Map<String, dynamic>? query}) async {
|
|
requested = path;
|
|
if (fail) throw const ApiException('Offline');
|
|
return response;
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
test('real trusted transport preserves configured ads without restoring vendor feeds', () async {
|
|
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
|
|
addTearDown(() => server.close(force: true));
|
|
final paths = <String>[];
|
|
server.listen((request) async {
|
|
paths.add(request.uri.path);
|
|
request.response.headers.contentType = ContentType.json;
|
|
request.response.write(
|
|
jsonEncode({
|
|
'banners': [
|
|
{
|
|
'title_en': 'Fixture sponsor',
|
|
'target_url': 'https://sponsor.example/offer',
|
|
},
|
|
{
|
|
'title_en': 'Melodybox fixture',
|
|
'target_url': 'https://vendor.example/',
|
|
},
|
|
{
|
|
'title_en': 'Blocked link',
|
|
'target_url': 'https://t.me/OtherChannel',
|
|
},
|
|
],
|
|
}),
|
|
);
|
|
await request.response.close();
|
|
});
|
|
final api = ApiService(baseUrl: 'http://127.0.0.1:${server.port}/api/');
|
|
final banners = await HomeBannerService(api).load();
|
|
expect(paths, ['/api/banners/']);
|
|
expect(banners, hasLength(2));
|
|
expect(banners.first, HomeBanner.telegram);
|
|
expect(banners.last.title(false), 'Fixture sponsor');
|
|
expect(banners.last.isAdvertisement, isTrue);
|
|
});
|
|
test(
|
|
'unsafe ads are skipped independently and config work is bounded',
|
|
() async {
|
|
final api = BannerApi();
|
|
final valid = {
|
|
'title_en': 'Fixture sponsor',
|
|
'target_url': 'https://sponsor.example/',
|
|
};
|
|
for (final target in [
|
|
'http://sponsor.example/',
|
|
'javascript:alert(1)',
|
|
'//sponsor.example/',
|
|
'https://user:pass@sponsor.example/',
|
|
'https://sponsor.example:444/',
|
|
'https://sponsor.example/ bad',
|
|
'https://sponsor.example/\\\\evil',
|
|
'https://',
|
|
'https://t.me/OtherChannel',
|
|
'https://sponsor.example/app.apk',
|
|
'https://sponsor.example/%0aevil',
|
|
'https://-bad.example/',
|
|
'https://bad..example/',
|
|
'https://bad.example./',
|
|
'https://sponsor.example/%zz',
|
|
'https://sponsor.example/${'x' * 2048}',
|
|
]) {
|
|
api.response = {
|
|
'banners': [
|
|
{...valid, 'target_url': target},
|
|
valid,
|
|
],
|
|
};
|
|
final banners = await HomeBannerService(api).load();
|
|
expect(banners, hasLength(2), reason: target);
|
|
expect(banners.last.target.toString(), 'https://sponsor.example/');
|
|
}
|
|
for (final invalid in [
|
|
null,
|
|
true,
|
|
4,
|
|
[],
|
|
{},
|
|
{'banners': {}},
|
|
{
|
|
'banners': [null, 7, true, {}],
|
|
},
|
|
]) {
|
|
api.response = invalid;
|
|
expect(await HomeBannerService(api).load(), [HomeBanner.telegram]);
|
|
}
|
|
api.response = {
|
|
'banners': [
|
|
{...valid, 'title_en': 'x' * 81},
|
|
{...valid, 'title_en': 'bad\u202etext'},
|
|
{...valid, 'subtitle_en': 'x' * 181},
|
|
{...valid, 'title_en': 5},
|
|
{...valid, 'image_url': 'http://sponsor.example/image.jpg'},
|
|
valid,
|
|
],
|
|
};
|
|
expect(await HomeBannerService(api).load(), hasLength(2));
|
|
api.response = {'banners': List.filled(1000, valid)};
|
|
expect(await HomeBannerService(api).load(), hasLength(6));
|
|
api.response = {
|
|
'banners': [...List.filled(20, {}), valid],
|
|
};
|
|
expect(await HomeBannerService(api).load(), [HomeBanner.telegram]);
|
|
},
|
|
);
|
|
test(
|
|
'configured bilingual ads append after Telegram with optional image',
|
|
() async {
|
|
final api = BannerApi()
|
|
..response = {
|
|
'banners': [
|
|
{
|
|
'title_en': 'Test sponsor',
|
|
'title_fa': 'حامی آزمایشی',
|
|
'subtitle_en': 'Fixture only',
|
|
'subtitle_fa': 'فقط دادهٔ آزمایشی',
|
|
'target_url': 'https://sponsor.example/offer?ref=reelbox',
|
|
'image_url': 'https://sponsor.example/banner.jpg',
|
|
},
|
|
{
|
|
'title_en': 'Text sponsor',
|
|
'target_url': 'https://sponsor.example/text',
|
|
},
|
|
],
|
|
};
|
|
final banners = await HomeBannerService(api).load();
|
|
expect(banners, hasLength(3));
|
|
expect(banners.first, same(HomeBanner.telegram));
|
|
expect(banners[1].isAdvertisement, isTrue);
|
|
expect(banners[1].title(true), 'حامی آزمایشی');
|
|
expect(banners[1].subtitle(true), 'فقط دادهٔ آزمایشی');
|
|
expect(banners[1].image.toString(), 'https://sponsor.example/banner.jpg');
|
|
expect(banners.last.title(true), 'Text sponsor');
|
|
expect(banners.last.image, isNull);
|
|
},
|
|
);
|
|
test(
|
|
'default Telegram banner survives missing config and API failures',
|
|
() async {
|
|
final api = BannerApi();
|
|
final service = HomeBannerService(api);
|
|
for (final fail in [false, true]) {
|
|
api.fail = fail;
|
|
final banners = await service.load();
|
|
expect(banners, hasLength(1));
|
|
expect(banners.single.target.toString(), 'https://t.me/ReelBoxApp');
|
|
expect(banners.single.title(false), 'ReelBox updates');
|
|
expect(banners.single.subtitle(false), 'Updates and announcements');
|
|
expect(banners.single.title(true), 'تازههای ریلباکس');
|
|
expect(banners.single.isAdvertisement, isFalse);
|
|
}
|
|
expect(api.requested, 'banners/');
|
|
},
|
|
);
|
|
}
|