Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Tests] Added some tests for the banner history logic
- Loading branch information
Showing
4 changed files
with
462 additions
and
1 deletion.
There are no files selected for viewing
238 changes: 238 additions & 0 deletions
238
test/application/banner_history/banner_history_bloc_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
}, | ||
); | ||
} |
71 changes: 71 additions & 0 deletions
71
test/application/banner_history_item/banner_history_item_bloc_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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>()], | ||
); | ||
}); | ||
} |
65 changes: 65 additions & 0 deletions
65
test/application/item_release_history/item_release_history_bloc_test.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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>()], | ||
); | ||
}); | ||
} |
Oops, something went wrong.