Skip to content

Commit

Permalink
[Tests] Added some tests for the banner history logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Apr 20, 2022
1 parent 20bf94b commit 525db1d
Show file tree
Hide file tree
Showing 4 changed files with 462 additions and 1 deletion.
238 changes: 238 additions & 0 deletions test/application/banner_history/banner_history_bloc_test.dart
@@ -0,0 +1,238 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:shiori/application/bloc.dart';
import 'package:shiori/domain/enums/enums.dart';
import 'package:shiori/domain/models/models.dart';
import 'package:shiori/domain/services/genshin_service.dart';
import 'package:shiori/domain/services/telemetry_service.dart';
import 'package:shiori/infrastructure/infrastructure.dart';

import '../../common.dart';
import '../../mocks.mocks.dart';

void main() {
late GenshinService _genshinService;
late TelemetryService _telemetryService;

setUpAll(() {
TestWidgetsFlutterBinding.ensureInitialized();
return Future(() async {
_telemetryService = MockTelemetryService();
final settingsService = MockSettingsService();
when(settingsService.language).thenReturn(AppLanguageType.english);

final localeService = LocaleServiceImpl(settingsService);
_genshinService = GenshinServiceImpl(localeService);

await _genshinService.init(settingsService.language);
});
});

void checkBannerItem(BannerHistoryItemModel banner, BannerHistoryItemType expectedType) {
checkItemKeyAndImage(banner.key, banner.image);
checkTranslation(banner.name, canBeNull: false);
expect(banner.rarity >= 4, isTrue);
expect(banner.type, expectedType);
expect(banner.versions, isNotEmpty);
for (final version in banner.versions) {
if (version.released) {
expect(version.number, isNull);
expect(version.version >= 1, isTrue);
} else if (version.number == 0) {
expect(version.released, isFalse);
} else {
expect(version.released, isFalse);
expect(version.number! >= 1, isTrue);
}
}
}

void checkCommonState(
BannerHistoryState state, {
BannerHistoryItemType type = BannerHistoryItemType.character,
BannerHistorySortType sortType = BannerHistorySortType.versionAsc,
List<String> selectedItemKeys = const [],
List<double> selectedVersions = const [],
}) {
state.map(
initial: (state) {
expect(state.type, type);
expect(state.versions, isNotEmpty);
expect(state.versions.length, state.versions.toSet().length);
expect(state.banners.isNotEmpty, isTrue);
for (final banner in state.banners) {
checkBannerItem(banner, type);
}
expect(state.sortType, sortType);
expect(state.selectedItemKeys, selectedItemKeys);
expect(state.selectedVersions, selectedVersions);

if (selectedItemKeys.isNotEmpty) {
expect(state.banners.length, state.selectedItemKeys.length);
}

if (selectedVersions.isNotEmpty) {
final versions = state.banners
.expand((el) => el.versions)
.where((e) => e.released && selectedVersions.contains(e.version))
.map((e) => e.version)
.toSet()
.toList();
expect(versions.length, selectedVersions.length);
}
},
);
}

test(
'Initial state',
() => expect(
BannerHistoryBloc(_genshinService, _telemetryService).state,
const BannerHistoryState.initial(
type: BannerHistoryItemType.character,
sortType: BannerHistorySortType.versionAsc,
banners: [],
versions: [],
selectedItemKeys: [],
selectedVersions: [],
),
),
);

blocTest<BannerHistoryBloc, BannerHistoryState>(
'Init',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc.add(const BannerHistoryEvent.init()),
verify: (bloc) => checkCommonState(bloc.state),
);

group('Type changed', () {
blocTest<BannerHistoryBloc, BannerHistoryState>(
'weapon selected',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.typeChanged(type: BannerHistoryItemType.weapon)),
verify: (bloc) => checkCommonState(bloc.state, type: BannerHistoryItemType.weapon),
);

blocTest<BannerHistoryBloc, BannerHistoryState>(
'no state change',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.typeChanged(type: BannerHistoryItemType.character)),
skip: 1,
expect: () => [],
);
});

group('Sort changed', () {
blocTest<BannerHistoryBloc, BannerHistoryState>(
'sorted by name desc.',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.sortTypeChanged(type: BannerHistorySortType.nameDesc)),
verify: (bloc) => bloc.state.map(
initial: (state) {
checkCommonState(bloc.state, sortType: BannerHistorySortType.nameDesc);
final names = state.banners.map((e) => e.name).toList();
final sorted = [...names]..sort((x, y) => y.compareTo(x));
expect(names, sorted);
},
),
);

blocTest<BannerHistoryBloc, BannerHistoryState>(
'sorted by version desc.',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.sortTypeChanged(type: BannerHistorySortType.versionDesc)),
verify: (bloc) => bloc.state.map(
initial: (state) {
checkCommonState(bloc.state, sortType: BannerHistorySortType.versionDesc);
final versions = state.versions.map((e) => e).toList();
final sorted = [...versions]..sort((x, y) => y.compareTo(x));
expect(versions, sorted);
},
),
);

blocTest<BannerHistoryBloc, BannerHistoryState>(
'no state change',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.sortTypeChanged(type: BannerHistorySortType.versionAsc)),
skip: 1,
expect: () => [],
);
});

group('Version selected', () {
blocTest<BannerHistoryBloc, BannerHistoryState>(
'to 2.5 and 2.4',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.versionSelected(version: 2.5))
..add(const BannerHistoryEvent.versionSelected(version: 2.4)),
verify: (bloc) => checkCommonState(bloc.state, selectedVersions: [2.5, 2.4]),
);

blocTest<BannerHistoryBloc, BannerHistoryState>(
'to 2.5 but it gets deselected',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.versionSelected(version: 2.5))
..add(const BannerHistoryEvent.versionSelected(version: 2.5)),
verify: (bloc) => checkCommonState(bloc.state),
);
});

group('Item selected', () {
blocTest<BannerHistoryBloc, BannerHistoryState>(
'to 2.5 but it gets deselected',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.itemsSelected(keys: ['keqing', 'xiangling'])),
verify: (bloc) => checkCommonState(bloc.state, selectedItemKeys: ['keqing', 'xiangling']),
);

blocTest<BannerHistoryBloc, BannerHistoryState>(
'empty array',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.itemsSelected(keys: [])),
verify: (bloc) => checkCommonState(bloc.state, selectedItemKeys: []),
);
});

blocTest<BannerHistoryBloc, BannerHistoryState>(
'Items for search',
build: () => BannerHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc
..add(const BannerHistoryEvent.init())
..add(const BannerHistoryEvent.sortTypeChanged(type: BannerHistorySortType.nameDesc))
..add(const BannerHistoryEvent.typeChanged(type: BannerHistoryItemType.weapon))
..add(const BannerHistoryEvent.versionSelected(version: 1.1)),
verify: (bloc) {
checkCommonState(bloc.state, type: BannerHistoryItemType.weapon, sortType: BannerHistorySortType.nameDesc, selectedVersions: [1.1]);
final itemsForSearch = bloc.getItemsForSearch();
final banners = _genshinService.getBanners(bloc.state.selectedVersions.first);
final expectedCount = banners.where((el) => el.type == BannerHistoryItemType.weapon).expand((el) => el.items).map((e) => e.key).toSet().length;
final expectedItems = bloc.state.banners.map((e) => e.key).toSet().toList();
expect(expectedCount, 14);
expect(expectedItems.length, expectedCount);
for (final key in expectedItems) {
expect(itemsForSearch.any((el) => el.key == key), isTrue);
}
},
);
}
@@ -0,0 +1,71 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:shiori/application/bloc.dart';
import 'package:shiori/domain/enums/enums.dart';
import 'package:shiori/domain/services/genshin_service.dart';
import 'package:shiori/domain/services/telemetry_service.dart';
import 'package:shiori/infrastructure/infrastructure.dart';

import '../../common.dart';
import '../../mocks.mocks.dart';

void main() {
late GenshinService _genshinService;
late TelemetryService _telemetryService;

setUpAll(() {
TestWidgetsFlutterBinding.ensureInitialized();
return Future(() async {
_telemetryService = MockTelemetryService();
final settingsService = MockSettingsService();
when(settingsService.language).thenReturn(AppLanguageType.english);

final localeService = LocaleServiceImpl(settingsService);
_genshinService = GenshinServiceImpl(localeService);

await _genshinService.init(settingsService.language);
});
});

test(
'Initial state',
() => expect(
BannerHistoryItemBloc(_genshinService, _telemetryService).state,
const BannerHistoryItemState.loading(),
),
);

group('Init', () {
blocTest<BannerHistoryItemBloc, BannerHistoryItemState>(
'valid version',
build: () => BannerHistoryItemBloc(_genshinService, _telemetryService),
act: (bloc) => bloc.add(const BannerHistoryItemEvent.init(version: 1.1)),
verify: (bloc) => bloc.state.map(
loading: (_) => throw Exception('Invalid state'),
loadedState: (state) {
final validItemTypes = [ItemType.character, ItemType.weapon];
expect(state.version, 1.1);
expect(state.items.isNotEmpty, isTrue);
for (final item in state.items) {
expect(item.until.isAfter(item.from), isTrue);
expect(item.version >= 1, isTrue);
expect(BannerHistoryItemType.values.contains(item.type), isTrue);
for (final el in item.items) {
checkItemKeyAndImage(el.key, el.image);
expect(el.rarity >= 4, isTrue);
expect(validItemTypes.contains(el.type), isTrue);
}
}
},
),
);

blocTest<BannerHistoryItemBloc, BannerHistoryItemState>(
'invalid version',
build: () => BannerHistoryItemBloc(_genshinService, _telemetryService),
act: (bloc) => bloc.add(const BannerHistoryItemEvent.init(version: 0.5)),
errors: () => [isA<Exception>()],
);
});
}
@@ -0,0 +1,65 @@
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:shiori/application/bloc.dart';
import 'package:shiori/domain/enums/enums.dart';
import 'package:shiori/domain/services/genshin_service.dart';
import 'package:shiori/domain/services/telemetry_service.dart';
import 'package:shiori/infrastructure/infrastructure.dart';

import '../../mocks.mocks.dart';

void main() {
late GenshinService _genshinService;
late TelemetryService _telemetryService;

setUpAll(() {
TestWidgetsFlutterBinding.ensureInitialized();
return Future(() async {
_telemetryService = MockTelemetryService();
final settingsService = MockSettingsService();
when(settingsService.language).thenReturn(AppLanguageType.english);

final localeService = LocaleServiceImpl(settingsService);
_genshinService = GenshinServiceImpl(localeService);

await _genshinService.init(settingsService.language);
});
});

test(
'Initial state',
() => expect(
ItemReleaseHistoryBloc(_genshinService, _telemetryService).state,
const ItemReleaseHistoryState.loading(),
),
);

group('Init', () {
blocTest<ItemReleaseHistoryBloc, ItemReleaseHistoryState>(
'valid item key',
build: () => ItemReleaseHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc.add(const ItemReleaseHistoryEvent.init(itemKey: 'keqing')),
verify: (bloc) => bloc.state.map(
loading: (_) => throw Exception('Invalid state'),
initial: (state) {
expect(state.itemKey, 'keqing');
expect(state.history.isNotEmpty, isTrue);
for (final history in state.history) {
expect(history.version >= 1, isTrue);
for (final dates in history.dates) {
expect(dates.until.isAfter(dates.from), isTrue);
}
}
},
),
);

blocTest<ItemReleaseHistoryBloc, ItemReleaseHistoryState>(
'invalid item key',
build: () => ItemReleaseHistoryBloc(_genshinService, _telemetryService),
act: (bloc) => bloc.add(const ItemReleaseHistoryEvent.init(itemKey: 'no-existent-item')),
errors: () => [isA<Exception>()],
);
});
}

0 comments on commit 525db1d

Please sign in to comment.