tests: add unit tests and fix bugs
parent
f5d8e07170
commit
c0bd61db05
|
@ -1,7 +1,11 @@
|
|||
import 'package:release_schedule/model/movie.dart';
|
||||
|
||||
abstract class MovieApi {
|
||||
Future<List<MovieData>> getUpcomingMovies(DateTime startDate, [int count]);
|
||||
Future<List<MovieData>> searchForMovies(String searchTerm);
|
||||
Future<void> addMovieDetails(List<MovieData> movies);
|
||||
class MovieApi {
|
||||
Future<List<MovieData>> getUpcomingMovies(DateTime startDate,
|
||||
[int count = 10]) async =>
|
||||
[];
|
||||
|
||||
Future<List<MovieData>> searchForMovies(String searchTerm) async => [];
|
||||
|
||||
Future<void> addMovieDetails(List<MovieData> movies) async {}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ String _durationToRelativeDateString(Duration duration) {
|
|||
return "Yesterday";
|
||||
}
|
||||
if (duration.isNegative) {
|
||||
return "${_durationApproximatedInWords(-duration)} ago";
|
||||
String result = _durationApproximatedInWords(-duration);
|
||||
return "${result[0].toUpperCase()}${result.substring(1)} ago";
|
||||
} else if (duration == Duration.zero) {
|
||||
return "Today";
|
||||
} else {
|
||||
|
|
|
@ -95,12 +95,12 @@ class MovieData extends ChangeNotifier {
|
|||
"releaseDates": releaseDatesByCountry,
|
||||
"genres": genres,
|
||||
"titles": titlesByCountry,
|
||||
"reviews": reviews,
|
||||
"reviews": reviews?.map((review) => review.toJsonEncodable()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
bool same(MovieData other) {
|
||||
return title == other.title && releaseDate == other.releaseDate;
|
||||
return title == other.title && releaseDate.date == other.releaseDate.date;
|
||||
}
|
||||
|
||||
MovieData.fromJsonEncodable(Map json)
|
||||
|
@ -112,13 +112,13 @@ class MovieData extends ChangeNotifier {
|
|||
?.map((genre) => genre as String)
|
||||
.toList(),
|
||||
releaseDates: json["releaseDates"] != null
|
||||
? (json["releaseDates"] as List<List<dynamic>>)
|
||||
? (json["releaseDates"] as List<dynamic>)
|
||||
.map((release) =>
|
||||
DateWithPrecisionAndCountry.fromJsonEncodable(release))
|
||||
.toList()
|
||||
: null,
|
||||
reviews: json["reviews"] != null
|
||||
? (json["reviews"] as List<Map<String, dynamic>>)
|
||||
? (json["reviews"] as List<dynamic>)
|
||||
.map((review) => Review.fromJsonEncodable(review))
|
||||
.toList()
|
||||
: null,
|
||||
|
@ -155,7 +155,9 @@ class DateWithPrecisionAndCountry {
|
|||
@override
|
||||
String toString() {
|
||||
String dateString = switch (precision) {
|
||||
DatePrecision.decade || DatePrecision.year => date.year.toString(),
|
||||
DatePrecision.decade =>
|
||||
"${DateFormat("yyyy").format(date).substring(0, 3)}0s",
|
||||
DatePrecision.year => date.year.toString(),
|
||||
DatePrecision.month => DateFormat("MMMM yyyy").format(date),
|
||||
DatePrecision.day => DateFormat("MMMM d, yyyy").format(date),
|
||||
DatePrecision.hour => DateFormat("MMMM d, yyyy, HH").format(date),
|
||||
|
|
|
@ -21,16 +21,64 @@ void main() {
|
|||
expect(result, 'Yesterday');
|
||||
});
|
||||
|
||||
test('returns "in X days" for future dates', () {
|
||||
test('returns "In 5 days" for a date 5 days in the future', () {
|
||||
final futureDate = DateTime.now().add(const Duration(days: 5));
|
||||
final result = dateRelativeToNow(futureDate);
|
||||
expect(result, 'In 5 days');
|
||||
});
|
||||
|
||||
test('returns "X days ago" for past dates', () {
|
||||
test('returns "5 days ago" for a date 5 days in the past', () {
|
||||
final pastDate = DateTime.now().subtract(const Duration(days: 5));
|
||||
final result = dateRelativeToNow(pastDate);
|
||||
expect(result, '5 days ago');
|
||||
});
|
||||
|
||||
test('returns "a week" for a date 7 days in the future', () {
|
||||
final futureDate = DateTime.now().add(const Duration(days: 7));
|
||||
final result = dateRelativeToNow(futureDate);
|
||||
expect(result, 'In a week');
|
||||
});
|
||||
|
||||
test('returns "a week" for a date 7 days in the past', () {
|
||||
final pastDate = DateTime.now().subtract(const Duration(days: 7));
|
||||
final result = dateRelativeToNow(pastDate);
|
||||
expect(result, 'A week ago');
|
||||
});
|
||||
|
||||
test('returns "a month" for a date 30 days in the future', () {
|
||||
final futureDate = DateTime.now().add(const Duration(days: 30));
|
||||
final result = dateRelativeToNow(futureDate);
|
||||
expect(result, 'In a month');
|
||||
});
|
||||
|
||||
test('returns "a month" for a date 30 days in the past', () {
|
||||
final pastDate = DateTime.now().subtract(const Duration(days: 30));
|
||||
final result = dateRelativeToNow(pastDate);
|
||||
expect(result, 'A month ago');
|
||||
});
|
||||
|
||||
test('returns "a year" for a date 365 days in the future', () {
|
||||
final futureDate = DateTime.now().add(const Duration(days: 365));
|
||||
final result = dateRelativeToNow(futureDate);
|
||||
expect(result, 'In a year');
|
||||
});
|
||||
|
||||
test('returns "a year" for a date 365 days in the past', () {
|
||||
final pastDate = DateTime.now().subtract(const Duration(days: 365));
|
||||
final result = dateRelativeToNow(pastDate);
|
||||
expect(result, 'A year ago');
|
||||
});
|
||||
|
||||
test('returns "a century" for a date 100 years in the future', () {
|
||||
final futureDate = DateTime.now().add(const Duration(days: 365 * 100));
|
||||
final result = dateRelativeToNow(futureDate);
|
||||
expect(result, 'In a century');
|
||||
});
|
||||
|
||||
test('returns "a century" for a date 100 years in the past', () {
|
||||
final pastDate = DateTime.now().subtract(const Duration(days: 365 * 100));
|
||||
final result = dateRelativeToNow(pastDate);
|
||||
expect(result, 'A century ago');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:release_schedule/api/movie_api.dart';
|
||||
import 'package:release_schedule/model/local_movie_storage.dart';
|
||||
import 'package:release_schedule/model/movie.dart';
|
||||
import 'package:release_schedule/model/movie_manager.dart';
|
||||
|
||||
void main() {
|
||||
group('MovieManager', () {
|
||||
late MovieManager movieManager;
|
||||
|
||||
setUp(() {
|
||||
movieManager = MovieManager(
|
||||
MovieApi(),
|
||||
LocalMovieStorage(),
|
||||
);
|
||||
});
|
||||
|
||||
test('addMovies should add movies to the list', () {
|
||||
final movies = [
|
||||
MovieData(
|
||||
'The Matrix',
|
||||
DateWithPrecisionAndCountry(DateTime(1999, 3, 31), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
MovieData(
|
||||
'The Matrix Reloaded',
|
||||
DateWithPrecisionAndCountry(DateTime(2003, 5, 7), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
];
|
||||
|
||||
movieManager.addMovies(movies);
|
||||
|
||||
expect(movieManager.movies, equals(movies));
|
||||
});
|
||||
|
||||
test('addMovies should add new movies', () {
|
||||
final movies = [
|
||||
MovieData(
|
||||
'The Matrix',
|
||||
DateWithPrecisionAndCountry(DateTime(1999, 3, 31), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
MovieData(
|
||||
'The Matrix Reloaded',
|
||||
DateWithPrecisionAndCountry(DateTime(2003, 5, 7), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
];
|
||||
|
||||
movieManager.addMovies(movies);
|
||||
|
||||
final newMovies = [
|
||||
MovieData(
|
||||
'The Matrix Revolutions',
|
||||
DateWithPrecisionAndCountry(DateTime(2003, 11, 5), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
];
|
||||
|
||||
movieManager.addMovies(newMovies);
|
||||
|
||||
expect(movieManager.movies, equals([...movies, ...newMovies]));
|
||||
});
|
||||
|
||||
test("addMovies should sort movies by their release dates", () {
|
||||
final movies = [
|
||||
MovieData(
|
||||
'The Matrix Reloaded',
|
||||
DateWithPrecisionAndCountry(DateTime(2003, 5, 7), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
MovieData(
|
||||
'The Matrix',
|
||||
DateWithPrecisionAndCountry(DateTime(1999, 3, 31), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
];
|
||||
|
||||
movieManager.addMovies(movies);
|
||||
|
||||
expect(movieManager.movies, equals([...movies.reversed]));
|
||||
});
|
||||
|
||||
test(
|
||||
'when a movie is modified and it\'s date is changed the movies should be resorted',
|
||||
() async {
|
||||
final movies = [
|
||||
MovieData(
|
||||
'The Matrix Reloaded',
|
||||
DateWithPrecisionAndCountry(DateTime(1998, 5, 7), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
MovieData(
|
||||
'The Matrix',
|
||||
DateWithPrecisionAndCountry(DateTime(1999, 3, 31), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
];
|
||||
|
||||
movieManager.addMovies(movies);
|
||||
|
||||
final movie = movieManager.movies.first;
|
||||
movie.setDetails(
|
||||
releaseDate: DateWithPrecisionAndCountry(DateTime(2003, 5, 7),
|
||||
DatePrecision.day, 'United States of America'),
|
||||
);
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
expect(movieManager.movies, equals([...movies.reversed]));
|
||||
});
|
||||
|
||||
test('removeMoviesWhere should remove movies from the list', () {
|
||||
final movies = [
|
||||
MovieData(
|
||||
'The Matrix',
|
||||
DateWithPrecisionAndCountry(DateTime(1999, 3, 31), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
MovieData(
|
||||
'The Matrix Reloaded',
|
||||
DateWithPrecisionAndCountry(DateTime(2003, 5, 7), DatePrecision.day,
|
||||
'United States of America'),
|
||||
),
|
||||
];
|
||||
MovieData notRemoved = MovieData(
|
||||
'Harry Potter and the Philosopher\'s Stone',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2001, 11, 4), DatePrecision.day, 'United Kingdom'),
|
||||
);
|
||||
|
||||
movieManager.addMovies([...movies, notRemoved]);
|
||||
|
||||
movieManager.removeMoviesWhere((movie) => movie.title.contains('Matrix'));
|
||||
|
||||
expect(movieManager.movies, equals([notRemoved]));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:release_schedule/model/movie.dart';
|
||||
|
||||
void main() {
|
||||
group('MovieData', () {
|
||||
test('updateWithNew() updates all fields', () {
|
||||
final movie1 = MovieData('Title 1',
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US'));
|
||||
final movie2 = MovieData('Title 2',
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'UK'));
|
||||
movie2.setDetails(releaseDates: [
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US')
|
||||
], genres: [
|
||||
'Action',
|
||||
'Adventure'
|
||||
], titles: [
|
||||
(title: 'Title 2', language: 'en')
|
||||
], reviews: [
|
||||
Review('8.5', 'John Doe', DateTime.now(), 100)
|
||||
]);
|
||||
movie1.updateWithNew(movie2);
|
||||
expect(movie1.title, equals('Title 2'));
|
||||
expect(movie1.releaseDate.country, equals('UK'));
|
||||
expect(movie1.releaseDates!.length, equals(1));
|
||||
expect(movie1.releaseDates![0].country, equals('US'));
|
||||
expect(movie1.genres!.length, equals(2));
|
||||
expect(movie1.genres![0], equals('Action'));
|
||||
expect(movie1.genres![1], equals('Adventure'));
|
||||
expect(movie1.titles!.length, equals(1));
|
||||
expect(movie1.titles![0].title, equals('Title 2'));
|
||||
expect(movie1.titles![0].language, equals('en'));
|
||||
expect(movie1.reviews!.length, equals(1));
|
||||
expect(movie1.reviews![0].score, equals('8.5'));
|
||||
expect(movie1.reviews![0].by, equals('John Doe'));
|
||||
expect(movie1.reviews![0].count, equals(100));
|
||||
});
|
||||
|
||||
test('same() returns true for same title and release date', () {
|
||||
final movie1 = MovieData(
|
||||
'Title 1',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.day, 'US'));
|
||||
final movie2 = MovieData(
|
||||
'Title 1',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.day, 'US'));
|
||||
expect(movie1.same(movie2), isTrue);
|
||||
});
|
||||
|
||||
test('same() returns false for different title', () {
|
||||
final movie1 = MovieData(
|
||||
'Title 1',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.day, 'US'));
|
||||
final movie2 = MovieData(
|
||||
'Title 2',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.day, 'US'));
|
||||
expect(movie1.same(movie2), isFalse);
|
||||
});
|
||||
|
||||
test('same() returns false for different release date', () {
|
||||
final movie1 = MovieData(
|
||||
'Title 1',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.day, 'US'));
|
||||
final movie2 = MovieData(
|
||||
'Title 1',
|
||||
DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 2), DatePrecision.day, 'US'));
|
||||
expect(movie1.same(movie2), isFalse);
|
||||
});
|
||||
test('can be encoded to JSON and back', () {
|
||||
final movie = MovieData('Title 1',
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US'));
|
||||
movie.setDetails(releaseDates: [
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US')
|
||||
], genres: [
|
||||
'Action',
|
||||
'Adventure'
|
||||
], titles: [
|
||||
(title: 'Title 2', language: 'en')
|
||||
], reviews: [
|
||||
Review('8.5', 'John Doe', DateTime.now(), 100)
|
||||
]);
|
||||
final json = movie.toJsonEncodable();
|
||||
final movie2 = MovieData.fromJsonEncodable(json);
|
||||
expect(movie2.title, equals('Title 1'));
|
||||
expect(movie2.releaseDate.country, equals('US'));
|
||||
expect(movie2.releaseDates!.length, equals(1));
|
||||
expect(movie2.releaseDates![0].country, equals('US'));
|
||||
expect(movie2.genres!.length, equals(2));
|
||||
expect(movie2.genres![0], equals('Action'));
|
||||
expect(movie2.genres![1], equals('Adventure'));
|
||||
expect(movie2.titles!.length, equals(1));
|
||||
expect(movie2.titles![0].title, equals('Title 2'));
|
||||
expect(movie2.titles![0].language, equals('en'));
|
||||
expect(movie2.reviews!.length, equals(1));
|
||||
expect(movie2.reviews![0].score, equals('8.5'));
|
||||
expect(movie2.reviews![0].by, equals('John Doe'));
|
||||
expect(movie2.reviews![0].count, equals(100));
|
||||
});
|
||||
|
||||
test('toString()', () {
|
||||
final movie = MovieData('Title 1',
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US'));
|
||||
movie.setDetails(releaseDates: [
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US')
|
||||
], genres: [
|
||||
'Action',
|
||||
'Adventure'
|
||||
], titles: [
|
||||
(title: 'Title 2', language: 'en')
|
||||
], reviews: [
|
||||
Review('8.5', 'John Doe', DateTime.now(), 100)
|
||||
]);
|
||||
expect(movie.toString(),
|
||||
equals('Title 1 (November 16, 2023 (US); Action, Adventure)'));
|
||||
});
|
||||
});
|
||||
|
||||
group('DateWithPrecisionAndCountry', () {
|
||||
test('can be encoded to JSON and back', () {
|
||||
final date =
|
||||
DateWithPrecisionAndCountry(DateTime.now(), DatePrecision.day, 'US');
|
||||
final json = date.toJsonEncodable();
|
||||
final date2 = DateWithPrecisionAndCountry.fromJsonEncodable(json);
|
||||
expect(date2.date, equals(date.date));
|
||||
expect(date2.precision, equals(date.precision));
|
||||
expect(date2.country, equals(date.country));
|
||||
});
|
||||
|
||||
test('toString()', () {
|
||||
final date = DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.day, 'US');
|
||||
expect(date.toString(), equals('January 1, 2023 (US)'));
|
||||
});
|
||||
|
||||
test('toString() with month precision', () {
|
||||
final date = DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.month, 'US');
|
||||
expect(date.toString(), equals('January 2023 (US)'));
|
||||
});
|
||||
|
||||
test('toString() with year precision', () {
|
||||
final date = DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.year, 'US');
|
||||
expect(date.toString(), equals('2023 (US)'));
|
||||
});
|
||||
|
||||
test('toString() with decade precision', () {
|
||||
final date = DateWithPrecisionAndCountry(
|
||||
DateTime(2023, 1, 1), DatePrecision.decade, 'US');
|
||||
expect(date.toString(), equals('2020s (US)'));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:release_schedule/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue