From f674f3e314b06f416373aa7e5475c3704c0b8f96 Mon Sep 17 00:00:00 2001 From: Erick Zanardo Date: Fri, 23 Jun 2023 14:21:49 -0300 Subject: [PATCH] pr suggestion --- .../analysis_options.yaml | 2 +- examples/basic_authentication/pubspec.yaml | 2 +- .../routes/users/[id].dart | 5 + .../test/lib/user_repository_test.dart | 233 ++++++++++++++++++ .../test/lib/user_repostiroy_test.dart | 226 ----------------- .../test/routes/users/[id]_test.dart | 214 ++++++++++------ 6 files changed, 372 insertions(+), 310 deletions(-) create mode 100644 examples/basic_authentication/test/lib/user_repository_test.dart delete mode 100644 examples/basic_authentication/test/lib/user_repostiroy_test.dart diff --git a/examples/basic_authentication/analysis_options.yaml b/examples/basic_authentication/analysis_options.yaml index c7627ffd8..fee8b582c 100644 --- a/examples/basic_authentication/analysis_options.yaml +++ b/examples/basic_authentication/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:very_good_analysis/analysis_options.4.0.0.yaml +include: package:very_good_analysis/analysis_options.5.0.0.yaml analyzer: exclude: - build/** diff --git a/examples/basic_authentication/pubspec.yaml b/examples/basic_authentication/pubspec.yaml index ae2c3a4e8..21ed8d14f 100644 --- a/examples/basic_authentication/pubspec.yaml +++ b/examples/basic_authentication/pubspec.yaml @@ -16,4 +16,4 @@ dependencies: dev_dependencies: mocktail: ^0.3.0 test: ^1.19.2 - very_good_analysis: ^4.0.0 + very_good_analysis: ^5.0.0 diff --git a/examples/basic_authentication/routes/users/[id].dart b/examples/basic_authentication/routes/users/[id].dart index ae409e269..078955133 100644 --- a/examples/basic_authentication/routes/users/[id].dart +++ b/examples/basic_authentication/routes/users/[id].dart @@ -27,6 +27,11 @@ Future _getUser(RequestContext context, String id) async { } Future _updateUser(RequestContext context, String id) async { + final user = context.read(); + if (user.id != id) { + return Response(statusCode: HttpStatus.forbidden); + } + final body = await context.request.json() as Map; final name = body['name'] as String?; final username = body['username'] as String?; diff --git a/examples/basic_authentication/test/lib/user_repository_test.dart b/examples/basic_authentication/test/lib/user_repository_test.dart new file mode 100644 index 000000000..ab216e666 --- /dev/null +++ b/examples/basic_authentication/test/lib/user_repository_test.dart @@ -0,0 +1,233 @@ +// ignore_for_file: prefer_const_constructors + +import 'package:basic_authentication/user_repository.dart'; +import 'package:test/test.dart'; + +void main() { + const id = 'ae5deb822e0d71992900471a7199d0d95b8e7c9d05c40a8245a281fd2c1d6684'; + const password = + '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8'; + const updatedPassword = + '089542505d659cecbb988bb5ccff5bccf85be2dfa8c221359079aee2531298bb'; + + group('UserRepository', () { + test('can be instantiated', () { + expect(UserRepository(), isNotNull); + }); + + group('userFromCredentials', () { + test('userFromCredentials return null if no user is found', () async { + mockUserData([]); + final repository = UserRepository(); + final user = + await repository.userFromCredentials('testuser', 'password'); + + expect(user, isNull); + }); + + test('userFromCredentials return null if password is incorrect', + () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + final repository = UserRepository(); + final user = await repository.userFromCredentials('testuser', 'wrong'); + + expect(user, isNull); + }); + + test('userFromCredentials return user if password is correct', () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + + final repository = UserRepository(); + final user = + await repository.userFromCredentials('testuser', 'password'); + + expect( + user, + equals( + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ), + ); + }); + }); + + test('createUser adds a new user, returning its id', () async { + mockUserData([]); + final repository = UserRepository(); + final returnedId = await repository.createUser( + name: 'Test User', + username: 'testuser', + password: 'password', + ); + + expect(returnedId, equals(id)); + + expect( + getDb(), + equals([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]), + ); + }); + + test('deleteUser deletes a user', () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + final repository = UserRepository(); + await repository.deleteUser(id); + + expect(getDb(), isEmpty); + }); + + group('updateUser', () { + test('updates the user on the db', () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + final repository = UserRepository(); + await repository.updateUser( + id: id, + name: 'New Name', + username: 'newusername', + password: 'newpassword', + ); + + expect( + getDb(), + equals([ + User( + id: id, + name: 'New Name', + username: 'newusername', + password: updatedPassword, + ), + ]), + ); + }); + + test('can update just the name', () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + final repository = UserRepository(); + await repository.updateUser( + id: id, + name: 'New Name', + username: null, + password: null, + ); + + expect( + getDb(), + equals([ + User( + id: id, + name: 'New Name', + username: 'testuser', + password: password, + ), + ]), + ); + }); + + test('can update just the username', () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + final repository = UserRepository(); + await repository.updateUser( + id: id, + name: null, + username: 'newusername', + password: null, + ); + + expect( + getDb(), + equals([ + User( + id: id, + name: 'Test User', + username: 'newusername', + password: password, + ), + ]), + ); + }); + + test('can update just the password', () async { + mockUserData([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: password, + ), + ]); + final repository = UserRepository(); + await repository.updateUser( + id: id, + name: null, + username: null, + password: 'newpassword', + ); + + expect( + getDb(), + equals([ + User( + id: id, + name: 'Test User', + username: 'testuser', + password: updatedPassword, + ), + ]), + ); + }); + }); + }); +} diff --git a/examples/basic_authentication/test/lib/user_repostiroy_test.dart b/examples/basic_authentication/test/lib/user_repostiroy_test.dart deleted file mode 100644 index c80fd050c..000000000 --- a/examples/basic_authentication/test/lib/user_repostiroy_test.dart +++ /dev/null @@ -1,226 +0,0 @@ -// ignore_for_file: prefer_const_constructors - -import 'package:basic_authentication/user_repository.dart'; -import 'package:test/test.dart'; - -void main() { - const id = 'ae5deb822e0d71992900471a7199d0d95b8e7c9d05c40a8245a281fd2c1d6684'; - const password = - '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8'; - const updatedPassword = - '089542505d659cecbb988bb5ccff5bccf85be2dfa8c221359079aee2531298bb'; - - group('UserRepository', () { - test('can be instantiated', () { - expect(UserRepository(), isNotNull); - }); - - test('userFromCredentials return null if no user is found', () async { - mockUserData([]); - final repository = UserRepository(); - final user = await repository.userFromCredentials('testuser', 'password'); - - expect(user, isNull); - }); - - test('userFromCredentials return null if password is incorrect', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - final repository = UserRepository(); - final user = await repository.userFromCredentials('testuser', 'wrong'); - - expect(user, isNull); - }); - - test('userFromCredentials return user if password is correct', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - - final repository = UserRepository(); - final user = await repository.userFromCredentials('testuser', 'password'); - - expect( - user, - equals( - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ), - ); - }); - - test('createUser adds a new user, returning its id', () async { - mockUserData([]); - final repository = UserRepository(); - final returnedId = await repository.createUser( - name: 'Test User', - username: 'testuser', - password: 'password', - ); - - expect(returnedId, equals(id)); - - expect( - getDb(), - equals([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]), - ); - }); - - test('deleteUser deletes a user', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - final repository = UserRepository(); - await repository.deleteUser(id); - - expect(getDb(), isEmpty); - }); - - test('updateUser updates the user on the db', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - final repository = UserRepository(); - await repository.updateUser( - id: id, - name: 'New Name', - username: 'newusername', - password: 'newpassword', - ); - - expect( - getDb(), - equals([ - User( - id: id, - name: 'New Name', - username: 'newusername', - password: updatedPassword, - ), - ]), - ); - }); - - test('updateUser can update just the name', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - final repository = UserRepository(); - await repository.updateUser( - id: id, - name: 'New Name', - username: null, - password: null, - ); - - expect( - getDb(), - equals([ - User( - id: id, - name: 'New Name', - username: 'testuser', - password: password, - ), - ]), - ); - }); - - test('updateUser can update just the username', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - final repository = UserRepository(); - await repository.updateUser( - id: id, - name: null, - username: 'newusername', - password: null, - ); - - expect( - getDb(), - equals([ - User( - id: id, - name: 'Test User', - username: 'newusername', - password: password, - ), - ]), - ); - }); - - test('updateUser can update just the password', () async { - mockUserData([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: password, - ), - ]); - final repository = UserRepository(); - await repository.updateUser( - id: id, - name: null, - username: null, - password: 'newpassword', - ); - - expect( - getDb(), - equals([ - User( - id: id, - name: 'Test User', - username: 'testuser', - password: updatedPassword, - ), - ]), - ); - }); - }); -} diff --git a/examples/basic_authentication/test/routes/users/[id]_test.dart b/examples/basic_authentication/test/routes/users/[id]_test.dart index 2ffcc05cb..384628eab 100644 --- a/examples/basic_authentication/test/routes/users/[id]_test.dart +++ b/examples/basic_authentication/test/routes/users/[id]_test.dart @@ -66,107 +66,157 @@ void main() { expect(response.statusCode, equals(HttpStatus.forbidden)); }); - test('PATCH updates the user', () async { - final user = User( - id: '1', - name: 'John Doe', - username: 'johndoe', - password: '', - ); - when(() => context.read()).thenReturn(user); - - final userRepository = _MockUserRepository(); - when( - () => userRepository.updateUser( + group('PATCH', () { + test('updates the user', () async { + final user = User( id: '1', - name: 'Jane Doe', - username: 'janedoe', - password: 'password', - ), - ).thenAnswer((_) async {}); - - when(() => context.read()).thenReturn(userRepository); - - when(() => request.method).thenReturn(HttpMethod.patch); - when(() => request.json()).thenAnswer( - (_) async => { - 'name': 'Jane Doe', - 'username': 'janedoe', - 'password': 'password', - }, - ); + name: 'John Doe', + username: 'johndoe', + password: '', + ); + when(() => context.read()).thenReturn(user); + + final userRepository = _MockUserRepository(); + when( + () => userRepository.updateUser( + id: '1', + name: 'Jane Doe', + username: 'janedoe', + password: 'password', + ), + ).thenAnswer((_) async {}); + + when(() => context.read()).thenReturn(userRepository); + + when(() => request.method).thenReturn(HttpMethod.patch); + when(() => request.json()).thenAnswer( + (_) async => { + 'name': 'Jane Doe', + 'username': 'janedoe', + 'password': 'password', + }, + ); - final response = await route.onRequest(context, '1'); + final response = await route.onRequest(context, '1'); - expect(response.statusCode, equals(HttpStatus.noContent)); - verify( - () => userRepository.updateUser( + expect(response.statusCode, equals(HttpStatus.noContent)); + verify( + () => userRepository.updateUser( + id: '1', + name: 'Jane Doe', + username: 'janedoe', + password: 'password', + ), + ).called(1); + }); + + test('returns bad content if there is no information to update', + () async { + final user = User( id: '1', - name: 'Jane Doe', - username: 'janedoe', - password: 'password', - ), - ).called(1); - }); + name: 'John Doe', + username: 'johndoe', + password: '', + ); + when(() => context.read()).thenReturn(user); - test('PATCH returns bad content if there is no information to update', - () async { - final user = User( - id: '1', - name: 'John Doe', - username: 'johndoe', - password: '', - ); - when(() => context.read()).thenReturn(user); + final userRepository = _MockUserRepository(); + when(() => context.read()).thenReturn(userRepository); - final userRepository = _MockUserRepository(); - when(() => context.read()).thenReturn(userRepository); + when(() => request.method).thenReturn(HttpMethod.patch); + when(() => request.json()).thenAnswer( + (_) async => {}, + ); - when(() => request.method).thenReturn(HttpMethod.patch); - when(() => request.json()).thenAnswer( - (_) async => {}, - ); + final response = await route.onRequest(context, '1'); - final response = await route.onRequest(context, '1'); + expect(response.statusCode, equals(HttpStatus.badRequest)); + }); - expect(response.statusCode, equals(HttpStatus.badRequest)); + test( + 'returns forbidden when the logged user is not the requested one', + () async { + final user = User( + id: '1', + name: 'John Doe', + username: 'johndoe', + password: '', + ); + when(() => context.read()).thenReturn(user); + + final userRepository = _MockUserRepository(); + when( + () => userRepository.updateUser( + id: '1', + name: 'Jane Doe', + username: 'janedoe', + password: 'password', + ), + ).thenAnswer((_) async {}); + + when(() => context.read()).thenReturn(userRepository); + + when(() => request.method).thenReturn(HttpMethod.patch); + when(() => request.json()).thenAnswer( + (_) async => { + 'name': 'Jane Doe', + 'username': 'janedoe', + 'password': 'password', + }, + ); + + final response = await route.onRequest(context, '1'); + + expect(response.statusCode, equals(HttpStatus.noContent)); + verify( + () => userRepository.updateUser( + id: '1', + name: 'Jane Doe', + username: 'janedoe', + password: 'password', + ), + ).called(1); + }, + ); }); - test('DELETE deletes the user', () async { - final user = User( - id: '1', - name: 'John Doe', - username: 'johndoe', - password: '', - ); - when(() => context.read()).thenReturn(user); + group('DELETE', () { + test('deletes the user', () async { + final user = User( + id: '1', + name: 'John Doe', + username: 'johndoe', + password: '', + ); + when(() => context.read()).thenReturn(user); - final userRepository = _MockUserRepository(); - when(() => userRepository.deleteUser('1')).thenAnswer((_) async {}); + final userRepository = _MockUserRepository(); + when(() => userRepository.deleteUser('1')).thenAnswer((_) async {}); - when(() => context.read()).thenReturn(userRepository); + when(() => context.read()).thenReturn(userRepository); - when(() => request.method).thenReturn(HttpMethod.delete); + when(() => request.method).thenReturn(HttpMethod.delete); - final response = await route.onRequest(context, '1'); + final response = await route.onRequest(context, '1'); - expect(response.statusCode, equals(HttpStatus.noContent)); - verify(() => userRepository.deleteUser('1')).called(1); - }); + expect(response.statusCode, equals(HttpStatus.noContent)); + verify(() => userRepository.deleteUser('1')).called(1); + }); - test('DELETE returns forbidden when deleting a different user', () async { - final user = User( - id: '1', - name: 'John Doe', - username: 'johndoe', - password: '', - ); - when(() => context.read()).thenReturn(user); - when(() => request.method).thenReturn(HttpMethod.delete); + test('returns forbidden when deleting a different user', () async { + final user = User( + id: '1', + name: 'John Doe', + username: 'johndoe', + password: '', + ); + when(() => context.read()).thenReturn(user); + when(() => request.method).thenReturn(HttpMethod.delete); - final response = await route.onRequest(context, '2'); + final response = await route.onRequest(context, '2'); - expect(response.statusCode, equals(HttpStatus.forbidden)); + expect(response.statusCode, equals(HttpStatus.forbidden)); + }); }); test(