initial commit (migrated)

This commit is contained in:
fiatcode 2025-10-20 16:43:59 +07:00
commit b594facb51
143 changed files with 11057 additions and 0 deletions

View file

@ -0,0 +1,91 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:kuwot/core/env.dart';
import 'package:kuwot/core/network/network.dart';
import 'package:kuwot/features/quote/data/data_sources/remote/kuwot_api_remote_data_source.dart';
import 'package:kuwot/features/quote/data/models/image_model.dart';
import 'package:kuwot/features/quote/data/models/quote_model.dart';
import 'package:kuwot/features/quote/data/models/translation_model.dart';
import 'package:mocktail/mocktail.dart';
import '../../../../../_responses/_response.dart';
class MockEnv extends Mock implements Env {}
class MockNetwork extends Mock implements Network {}
class FakeUri extends Fake implements Uri {}
void main() {
late MockEnv mockEnv;
late MockNetwork mockNetwork;
late KuwotApiRemoteDataSource dataSource;
setUpAll(() {
registerFallbackValue(FakeUri());
});
setUp(() {
mockEnv = MockEnv();
mockNetwork = MockNetwork();
dataSource = KuwotApiRemoteApiImpl(env: mockEnv, network: mockNetwork);
// global stubs
when(() => mockEnv.authPublicKey).thenReturn('test');
when(() => mockEnv.quoteApiScheme).thenReturn('http');
when(() => mockEnv.quoteApiHost).thenReturn('10.0.2.2');
when(() => mockEnv.quoteApiPort).thenReturn(8080);
});
group('getDailyQuote', () {
test('should return random quote when response is successful', () async {
// arrange
final tResponse = readResponse('quote');
when(
() => mockNetwork.get(any(), headers: any(named: 'headers')),
).thenAnswer((_) async => tResponse);
// act
final result = await dataSource.getQuote();
// assert
expect(result, isA<QuoteModel>());
});
test(
'should return translated quote when response is successful',
() async {
// arrange
final tResponse = readResponse('quote');
when(
() => mockNetwork.get(any(), headers: any(named: 'headers')),
).thenAnswer((_) async => tResponse);
// act
final result = await dataSource.getTranslatedQuote(1);
// assert
expect(result, isA<QuoteModel>());
},
);
test('should return random images when response is successful', () async {
// arrange
final tResponse = readResponse('random_images');
when(
() => mockNetwork.get(any(), headers: any(named: 'headers')),
).thenAnswer((_) async => tResponse);
// act
final result = await dataSource.getRandomImages();
// assert
expect(result, isA<List<ImageModel>>());
});
test('should return translations when response is successful', () async {
// arrange
final tResponse = readResponse('translations');
when(
() => mockNetwork.get(any(), headers: any(named: 'headers')),
).thenAnswer((_) async => tResponse);
// act
final result = await dataSource.getTranslations();
// assert
expect(result, isA<List<TranslationModel>>());
});
});
}

View file

@ -0,0 +1,347 @@
import 'dart:convert';
import 'package:flutter_test/flutter_test.dart';
import 'package:http/http.dart';
import 'package:kuwot/core/data/local/translation_target_config.dart';
import 'package:kuwot/core/error/failure.dart';
import 'package:kuwot/features/quote/data/data_sources/remote/kuwot_api_remote_data_source.dart';
import 'package:kuwot/features/quote/data/models/image_model.dart';
import 'package:kuwot/features/quote/data/models/quote_model.dart';
import 'package:kuwot/features/quote/data/models/translation_model.dart';
import 'package:kuwot/features/quote/data/repositories/quote_repository_impl.dart';
import 'package:kuwot/features/quote/domain/entities/background_image.dart';
import 'package:kuwot/features/quote/domain/entities/quote.dart';
import 'package:kuwot/features/quote/domain/entities/translation.dart';
import 'package:mocktail/mocktail.dart';
import '../../../../_responses/_response.dart';
class MockKuwotApiRemoteDataSource extends Mock
implements KuwotApiRemoteDataSource {}
void main() {
late QuoteRepositoryImpl quoteRepository;
late MockKuwotApiRemoteDataSource mockKuwotApiRemoteDataSource;
setUp(() {
mockKuwotApiRemoteDataSource = MockKuwotApiRemoteDataSource();
quoteRepository = QuoteRepositoryImpl(
quoteDataSource: mockKuwotApiRemoteDataSource,
);
});
const tQuoteModel = QuoteModel(id: 1, author: 'author', text: 'text');
const tExpectedQuote = Quote(id: 1, author: 'author', body: 'text');
const tTranslationTarget = TranslationTarget(id: 'en', name: 'English');
group('getQuote', () {
test('should return a Quote entity', () async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getQuote(query: any(named: 'query')),
).thenAnswer((_) async => tQuoteModel);
// act
final result = await quoteRepository.getQuote(tTranslationTarget);
// assert
verify(
() => mockKuwotApiRemoteDataSource.getQuote(query: any(named: 'query')),
);
result.fold(
(failure) => fail('Expected Quote, but got $failure'),
(quote) => expect(quote, tExpectedQuote),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
test(
'should return ClientFailure when a client exception is thrown',
() async {
// arrange
when(
() =>
mockKuwotApiRemoteDataSource.getQuote(query: any(named: 'query')),
).thenThrow(ClientException('test'));
// act
final result = await quoteRepository.getQuote(null);
// assert
verify(
() =>
mockKuwotApiRemoteDataSource.getQuote(query: any(named: 'query')),
);
result.fold(
(failure) => expect(failure, isA<ClientFailure>()),
(quote) => fail('Expected ClientFailure, but got $quote'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
},
);
test('should return UnknownFailure when an exception is thrown', () async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getQuote(query: any(named: 'query')),
).thenThrow(Exception('test'));
// act
final result = await quoteRepository.getQuote(null);
// assert
verify(
() => mockKuwotApiRemoteDataSource.getQuote(query: any(named: 'query')),
);
result.fold(
(failure) => expect(failure, isA<UnknownFailure>()),
(quote) => fail('Expected UnknownFailure, but got $quote'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
});
group('getTranslatedQuote', () {
const tQuoteId = 1;
test('should return a Quote entity', () async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getTranslatedQuote(
any(),
query: any(named: 'query'),
),
).thenAnswer((_) async => tQuoteModel);
// act
final result = await quoteRepository.getTranslatedQuote(
tQuoteId,
tTranslationTarget,
);
// assert
verify(
() => mockKuwotApiRemoteDataSource.getTranslatedQuote(
any(),
query: any(named: 'query'),
),
);
result.fold(
(failure) => fail('Expected Quote, but got $failure'),
(quote) => expect(quote, tExpectedQuote),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
test(
'should return ClientFailure when a client exception is thrown',
() async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getTranslatedQuote(
any(),
query: any(named: 'query'),
),
).thenThrow(ClientException('test'));
// act
final result = await quoteRepository.getTranslatedQuote(
tQuoteId,
tTranslationTarget,
);
// assert
verify(
() => mockKuwotApiRemoteDataSource.getTranslatedQuote(
any(),
query: any(named: 'query'),
),
);
result.fold(
(failure) => expect(failure, isA<ClientFailure>()),
(quote) => fail('Expected ClientFailure, but got $quote'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
},
);
test('should return UnknownFailure when an exception is thrown', () async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getTranslatedQuote(
any(),
query: any(named: 'query'),
),
).thenThrow(Exception('test'));
// act
final result = await quoteRepository.getTranslatedQuote(
tQuoteId,
tTranslationTarget,
);
// assert
verify(
() => mockKuwotApiRemoteDataSource.getTranslatedQuote(
any(),
query: any(named: 'query'),
),
);
result.fold(
(failure) => expect(failure, isA<UnknownFailure>()),
(quote) => fail('Expected UnknownFailure, but got $quote'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
});
group('getTranslations', () {
test('should return a List of Translation entity', () async {
// arrange
final tTranslationListModel =
(jsonDecode(readResponse('translations')) as List)
.map((e) => TranslationModel.fromJson(e as Map<String, dynamic>))
.toList();
final tExpectedTranslations = tTranslationListModel
.map((e) => Translation(id: e.id, language: e.lang))
.toList();
when(
() => mockKuwotApiRemoteDataSource.getTranslations(),
).thenAnswer((_) async => tTranslationListModel);
// act
final result = await quoteRepository.getTranslations();
// assert
verify(() => mockKuwotApiRemoteDataSource.getTranslations());
result.fold(
(failure) => fail('Expected Translations, but got $failure'),
(translations) => expect(translations, tExpectedTranslations),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
test(
'should return ClientFailure when a client exception is thrown',
() async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getTranslations(),
).thenThrow(ClientException('test'));
// act
final result = await quoteRepository.getTranslations();
// assert
verify(() => mockKuwotApiRemoteDataSource.getTranslations());
result.fold(
(failure) => expect(failure, isA<ClientFailure>()),
(translations) =>
fail('Expected ClientFailure, but got $translations'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
},
);
test('should return UnknownFailure when an exception is thrown', () async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getTranslations(),
).thenThrow(Exception('test'));
// act
final result = await quoteRepository.getTranslations();
// assert
verify(() => mockKuwotApiRemoteDataSource.getTranslations());
result.fold(
(failure) => expect(failure, isA<UnknownFailure>()),
(translations) =>
fail('Expected UnknownFailure, but got $translations'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
});
group('getBackgroundImages', () {
test('should return a List of BackgroundImage entity', () async {
// arrange
final tImageListModel =
(jsonDecode(readResponse('random_images')) as List)
.map((e) => ImageModel.fromJson(e as Map<String, dynamic>))
.toList();
final tExpectedImages = tImageListModel.map(
(e) => BackgroundImage(
id: e.id,
description: e.description,
color: e.color,
blurHash: e.blurHash,
url: e.url,
originUrl: e.originUrl,
authorName: e.authorName,
authorProfileImageUrl: e.authorProfileImageUrl,
authorUrl: e.authorUrl,
authorBio: e.authorBio,
authorLocation: e.authorLocation,
authorTotalLikes: e.authorTotalLikes,
authorTotalPhotos: e.authorTotalPhotos,
authorIsForHire: e.authorIsForHire,
),
);
when(
() => mockKuwotApiRemoteDataSource.getRandomImages(),
).thenAnswer((_) async => tImageListModel);
// act
final result = await quoteRepository.getBackgroundImages();
// assert
verify(() => mockKuwotApiRemoteDataSource.getRandomImages());
result.fold(
(failure) => fail('Expected BackgroundImages, but got $failure'),
(photos) => expect(photos, tExpectedImages),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
test(
'should return ClientFailure when a client exception is thrown',
() async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getRandomImages(),
).thenThrow(ClientException('test'));
// act
final result = await quoteRepository.getBackgroundImages();
// assert
verify(() => mockKuwotApiRemoteDataSource.getRandomImages());
result.fold(
(failure) => expect(failure, isA<ClientFailure>()),
(images) => fail('Expected ClientFailure, but got $images'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
},
);
test('should return UnknownFailure when an exception is thrown', () async {
// arrange
when(
() => mockKuwotApiRemoteDataSource.getRandomImages(),
).thenThrow(Exception('test'));
// act
final result = await quoteRepository.getBackgroundImages();
// assert
verify(() => mockKuwotApiRemoteDataSource.getRandomImages());
result.fold(
(failure) => expect(failure, isA<UnknownFailure>()),
(images) => fail('Expected UnknownFailure, but got $images'),
);
verifyNoMoreInteractions(mockKuwotApiRemoteDataSource);
});
});
}

View file

@ -0,0 +1,35 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/core/domain/no_params.dart';
import 'package:kuwot/features/quote/domain/entities/background_image.dart';
import 'package:kuwot/features/quote/domain/repositories/quote_repository.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_background_images.dart';
import 'package:mocktail/mocktail.dart';
class MockQuoteRepository extends Mock implements QuoteRepository {}
void main() {
late MockQuoteRepository mockQuoteRepository;
late GetBackgroundImages useCase;
setUp(() {
mockQuoteRepository = MockQuoteRepository();
useCase = GetBackgroundImages(mockQuoteRepository);
});
test('should get background photos', () async {
// arrange
const tImages = <BackgroundImage>[];
when(
() => mockQuoteRepository.getBackgroundImages(),
).thenAnswer((_) async => right(tImages));
// act
final result = await useCase(const NoParams());
// assert
expect(result, right(tImages));
verify(() => mockQuoteRepository.getBackgroundImages());
verifyNoMoreInteractions(mockQuoteRepository);
});
}

View file

@ -0,0 +1,34 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/features/quote/domain/entities/quote.dart';
import 'package:kuwot/features/quote/domain/repositories/quote_repository.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_quote.dart';
import 'package:mocktail/mocktail.dart';
class MockQuoteRepository extends Mock implements QuoteRepository {}
void main() {
late MockQuoteRepository mockQuoteRepository;
late GetQuote useCase;
setUp(() {
mockQuoteRepository = MockQuoteRepository();
useCase = GetQuote(mockQuoteRepository);
});
test('should get quote', () async {
// arrange
const tQuote = Quote(id: 1, author: 'author', body: 'text');
when(
() => mockQuoteRepository.getQuote(any()),
).thenAnswer((_) async => right(tQuote));
// act
final result = await useCase(const GetQuoteParams(null));
// assert
expect(result, right(tQuote));
verify(() => mockQuoteRepository.getQuote(any()));
verifyNoMoreInteractions(mockQuoteRepository);
});
}

View file

@ -0,0 +1,44 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/core/data/local/translation_target_config.dart';
import 'package:kuwot/features/quote/domain/entities/quote.dart';
import 'package:kuwot/features/quote/domain/repositories/quote_repository.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_translated_quote.dart';
import 'package:mocktail/mocktail.dart';
class MockQuoteRepository extends Mock implements QuoteRepository {}
class FakeTranslationTarget extends Fake implements TranslationTarget {}
void main() {
late MockQuoteRepository mockQuoteRepository;
late GetTranslatedQuote useCase;
setUpAll(() {
registerFallbackValue(FakeTranslationTarget());
});
setUp(() {
mockQuoteRepository = MockQuoteRepository();
useCase = GetTranslatedQuote(mockQuoteRepository);
});
test('should get translated quote', () async {
// arrange
const tQuote = Quote(id: 1, author: 'author', body: 'text');
const tTarget = TranslationTarget(id: 'en', name: 'English');
when(
() => mockQuoteRepository.getTranslatedQuote(any(), any()),
).thenAnswer((_) async => right(tQuote));
// act
final result = await useCase(
const GetTranslatedQuoteParams(id: 1, translationTarget: tTarget),
);
// assert
expect(result, right(tQuote));
verify(() => mockQuoteRepository.getTranslatedQuote(tQuote.id, tTarget));
verifyNoMoreInteractions(mockQuoteRepository);
});
}

View file

@ -0,0 +1,35 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/core/domain/no_params.dart';
import 'package:kuwot/features/quote/domain/entities/translation.dart';
import 'package:kuwot/features/quote/domain/repositories/quote_repository.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_translations.dart';
import 'package:mocktail/mocktail.dart';
class MockQuoteRepository extends Mock implements QuoteRepository {}
void main() {
late MockQuoteRepository mockQuoteRepository;
late GetTranslations useCase;
setUp(() {
mockQuoteRepository = MockQuoteRepository();
useCase = GetTranslations(mockQuoteRepository);
});
test('should get translations', () async {
// arrange
final tExpected = <Translation>[];
when(
() => mockQuoteRepository.getTranslations(),
).thenAnswer((_) async => right(tExpected));
// act
final result = await useCase(const NoParams());
// assert
expect(result, right(tExpected));
verify(() => mockQuoteRepository.getTranslations());
verifyNoMoreInteractions(mockQuoteRepository);
});
}

View file

@ -0,0 +1,95 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/core/domain/no_params.dart';
import 'package:kuwot/core/error/failure.dart';
import 'package:kuwot/features/quote/domain/entities/background_image.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_background_images.dart';
import 'package:kuwot/features/quote/presentation/bloc/background_images_bloc.dart';
import 'package:mocktail/mocktail.dart';
class MockGetBackgroundImages extends Mock implements GetBackgroundImages {}
class FakeNoParams extends Fake implements NoParams {}
void main() {
late MockGetBackgroundImages mockGetBackgroundImages;
late BackgroundImagesBloc backgroundImagesBloc;
setUpAll(() {
registerFallbackValue(FakeNoParams());
});
setUp(() {
mockGetBackgroundImages = MockGetBackgroundImages();
backgroundImagesBloc = BackgroundImagesBloc(
getBackgroundImages: mockGetBackgroundImages,
);
});
test('initial state is BackgroundImagesInitial', () {
// assert
expect(backgroundImagesBloc.state, const BackgroundImagesInitialState());
});
group('GetBackgroundImages', () {
test(
'should get background photos from GetBackgroundImages use case',
() async {
// arrange
when(
() => mockGetBackgroundImages(any()),
).thenAnswer((_) async => right(const <BackgroundImage>[]));
// act
backgroundImagesBloc.add(const GetBackgroundImagesEvent());
await untilCalled(() => mockGetBackgroundImages(any()));
// assert
verify(() => mockGetBackgroundImages(any())).called(1);
verifyNoMoreInteractions(mockGetBackgroundImages);
},
);
test(
'should emit [BackgroundImagesLoading, BackgroundImagesLoaded] when data is gotten successfully',
() async {
// arrange
const tBackgroundImages = <BackgroundImage>[];
when(
() => mockGetBackgroundImages(any()),
).thenAnswer((_) async => right(tBackgroundImages));
// assert later
final expected = [
const BackgroundImagesLoadingState(),
const BackgroundImagesLoadedState(tBackgroundImages),
];
expectLater(backgroundImagesBloc.stream, emitsInOrder(expected));
// act
backgroundImagesBloc.add(const GetBackgroundImagesEvent());
},
);
test(
'should emit [BackgroundImagesLoading, BackgroundImagesError] when getting data fails',
() async {
// arrange
const tFailure = UnknownFailure(message: 'Unknown Failure');
when(
() => mockGetBackgroundImages(any()),
).thenAnswer((_) async => left(tFailure));
// assert later
final expected = [
const BackgroundImagesLoadingState(),
BackgroundImagesErrorState(message: tFailure.message),
];
expectLater(backgroundImagesBloc.stream, emitsInOrder(expected));
// act
backgroundImagesBloc.add(const GetBackgroundImagesEvent());
},
);
});
}

View file

@ -0,0 +1,180 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/core/data/local/config.dart';
import 'package:kuwot/core/data/local/translation_target_config.dart';
import 'package:kuwot/core/error/failure.dart';
import 'package:kuwot/features/quote/domain/entities/quote.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_quote.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_translated_quote.dart';
import 'package:kuwot/features/quote/presentation/bloc/quote_bloc.dart';
import 'package:mocktail/mocktail.dart';
class MockGetQuote extends Mock implements GetQuote {}
class MockGetTranslatedQuote extends Mock implements GetTranslatedQuote {}
class MockTranslationTargetConfig extends Mock
implements Config<TranslationTarget> {}
class FakeQuoteParams extends Fake implements GetQuoteParams {}
class FakeTranslatedQuoteParams extends Fake
implements GetTranslatedQuoteParams {}
void main() {
late MockGetQuote mockGetQuote;
late MockGetTranslatedQuote mockGetTranslatedQuote;
late MockTranslationTargetConfig mockTranslationTargetConfig;
late QuoteBloc quoteBloc;
setUpAll(() {
registerFallbackValue(FakeQuoteParams());
registerFallbackValue(FakeTranslatedQuoteParams());
});
setUp(() {
mockGetQuote = MockGetQuote();
mockGetTranslatedQuote = MockGetTranslatedQuote();
mockTranslationTargetConfig = MockTranslationTargetConfig();
quoteBloc = QuoteBloc(
getQuote: mockGetQuote,
getTranslatedQuote: mockGetTranslatedQuote,
translationTargetConfig: mockTranslationTargetConfig,
);
});
const tTranslationTarget = TranslationTarget(id: 'en', name: 'English');
const tQuote = Quote(id: 1, author: 'author', body: 'text');
const tFailure = UnknownFailure(message: 'Unknown Failure');
test('initial state is QuoteInitial', () {
// assert
expect(quoteBloc.state, const QuoteInitialState());
});
group('GetQuote', () {
test('should get quote from GetQuote use case', () async {
// arrange
when(() => mockGetQuote(any())).thenAnswer((_) async => right(tQuote));
when(
() => mockTranslationTargetConfig.get(),
).thenAnswer((_) async => tTranslationTarget);
// act
quoteBloc.add(const GetQuoteEvent());
await untilCalled(() => mockTranslationTargetConfig.get());
await untilCalled(() => mockGetQuote(any()));
// assert
verify(() => mockGetQuote(any()));
verifyNoMoreInteractions(mockGetQuote);
});
test(
'should emit [QuoteLoading, QuoteLoaded] when data is gotten successfully',
() async {
// arrange
when(() => mockGetQuote(any())).thenAnswer((_) async => right(tQuote));
when(
() => mockTranslationTargetConfig.get(),
).thenAnswer((_) async => tTranslationTarget);
// assert later
const expected = [QuoteLoadingState(), QuoteLoadedState(quote: tQuote)];
expectLater(quoteBloc.stream, emitsInOrder(expected));
// act
quoteBloc.add(const GetQuoteEvent());
},
);
test(
'should emit [QuoteLoading, QuoteError] when getting data fails',
() async {
// arrange
when(() => mockGetQuote(any())).thenAnswer((_) async => left(tFailure));
when(
() => mockTranslationTargetConfig.get(),
).thenAnswer((_) async => tTranslationTarget);
// assert later
final expected = [
const QuoteLoadingState(),
QuoteErrorState(message: tFailure.message),
];
expectLater(quoteBloc.stream, emitsInOrder(expected));
// act
quoteBloc.add(const GetQuoteEvent());
},
);
});
group('GetTranslatedQuote', () {
test(
'should get translated quote from GetTranslatedQuote use case',
() async {
// arrange
when(
() => mockGetTranslatedQuote(any()),
).thenAnswer((_) async => right(tQuote));
when(
() => mockTranslationTargetConfig.get(),
).thenAnswer((_) async => tTranslationTarget);
// act
quoteBloc.add(const GetTranslatedQuoteEvent(tTranslationTarget));
await untilCalled(() => mockTranslationTargetConfig.get());
await untilCalled(() => mockGetTranslatedQuote(any()));
// assert
verify(() => mockGetTranslatedQuote(any()));
verifyNoMoreInteractions(mockGetTranslatedQuote);
},
);
test(
'should emit [QuoteLoading, QuoteLoaded] when data is gotten successfully',
() async {
// arrange
when(
() => mockGetTranslatedQuote(any()),
).thenAnswer((_) async => right(tQuote));
when(
() => mockTranslationTargetConfig.get(),
).thenAnswer((_) async => tTranslationTarget);
// assert later
const expected = [QuoteLoadingState(), QuoteLoadedState(quote: tQuote)];
expectLater(quoteBloc.stream, emitsInOrder(expected));
// act
quoteBloc.add(const GetTranslatedQuoteEvent(tTranslationTarget));
},
);
test(
'should emit [QuoteLoading, QuoteError] when getting data fails',
() async {
// arrange
when(
() => mockGetTranslatedQuote(any()),
).thenAnswer((_) async => left(tFailure));
when(
() => mockTranslationTargetConfig.get(),
).thenAnswer((_) async => tTranslationTarget);
// assert later
final expected = [
const QuoteLoadingState(),
QuoteErrorState(message: tFailure.message),
];
expectLater(quoteBloc.stream, emitsInOrder(expected));
// act
quoteBloc.add(const GetTranslatedQuoteEvent(tTranslationTarget));
},
);
});
}

View file

@ -0,0 +1,72 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:fpdart/fpdart.dart';
import 'package:kuwot/core/domain/no_params.dart';
import 'package:kuwot/core/error/failure.dart';
import 'package:kuwot/features/quote/domain/use_cases/get_translations.dart';
import 'package:kuwot/features/quote/presentation/bloc/translations_bloc.dart';
import 'package:mocktail/mocktail.dart';
class MockGetTranslations extends Mock implements GetTranslations {}
class FakeNoParams extends Fake implements NoParams {}
void main() {
late MockGetTranslations mockGetTranslations;
late TranslationsBloc translationsBloc;
setUpAll(() {
registerFallbackValue(FakeNoParams());
});
setUp(() {
mockGetTranslations = MockGetTranslations();
translationsBloc = TranslationsBloc(getTranslations: mockGetTranslations);
});
group('GetTranslations', () {
test('should get translations from GetTranslations use case', () async {
// arrange
when(() => mockGetTranslations(any())).thenAnswer((_) async => right([]));
// act
translationsBloc.add(const GetTranslationsEvent());
await untilCalled(() => mockGetTranslations(any()));
// assert
verify(() => mockGetTranslations(any()));
verifyNoMoreInteractions(mockGetTranslations);
});
test('should emit [Loading, Loaded] when successful', () async {
// arrange
when(() => mockGetTranslations(any())).thenAnswer((_) async => right([]));
// assert later
final expected = [
const TranslationsLoadingState(),
const TranslationsLoadedState(translations: []),
];
expectLater(translationsBloc.stream, emitsInOrder(expected));
// act
translationsBloc.add(const GetTranslationsEvent());
});
test('should emit [Loading, Error] when unsuccessful', () async {
// arrange
when(() => mockGetTranslations(any())).thenAnswer(
(_) async => left(const UnknownFailure(message: 'Unknown Failure')),
);
// assert later
final expected = [
const TranslationsLoadingState(),
const TranslationsErrorState(message: 'Unknown Failure'),
];
expectLater(translationsBloc.stream, emitsInOrder(expected));
// act
translationsBloc.add(const GetTranslationsEvent());
});
});
}