104 lines
4.3 KiB
Dart
104 lines
4.3 KiB
Dart
import 'package:fancake/features/auth/social_providers.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart' as fb;
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
/// 인증 오류 문구가 **경로별로** 맞는 사실을 말하는지 고정한다.
|
|
///
|
|
/// `account-exists-with-different-credential` 은 로그인 경로와 계정 연결 경로에서
|
|
/// 서로 다른 사실을 뜻한다(별첨 B v1.4 「복수 소셜 Provider 연결 허용」).
|
|
/// 한 벌로 합쳐 두면 로그인에 실패한 사용자가 자기가 하지도 않은 계정 연결을
|
|
/// 설명받고 무엇을 해야 하는지 알 수 없으므로, 회귀 가드를 둔다.
|
|
void main() {
|
|
group('account-exists-with-different-credential — 경로별 문구', () {
|
|
test('로그인 경로는 「다른 수단으로 로그인한 뒤 연결」을 안내한다', () {
|
|
final message = authMessage(
|
|
_exception('account-exists-with-different-credential',
|
|
email: 'fan@gmail.com'),
|
|
flow: AuthFlow.signIn,
|
|
);
|
|
|
|
// 오류 응답의 이메일 힌트를 그대로 넣어야 어느 계정인지 알 수 있다.
|
|
expect(message, contains('fan@gmail.com'));
|
|
expect(message, contains('처음 가입에 쓰신 수단으로 로그인'));
|
|
expect(message, contains('SNS 연동'));
|
|
// 로그인 경로에서는 「연결된 소셜 계정」이 사실이 아니다.
|
|
expect(message, isNot(contains('이미 연결된 소셜 계정')));
|
|
});
|
|
|
|
test('계정 연결 경로는 「다른 FANUZU 계정에 붙어 있다」로 남는다', () {
|
|
final message = authMessage(
|
|
_exception('account-exists-with-different-credential',
|
|
email: 'fan@gmail.com'),
|
|
flow: AuthFlow.link,
|
|
);
|
|
|
|
expect(message, '다른 FANUZU 계정에 이미 연결된 소셜 계정입니다.');
|
|
});
|
|
|
|
test('두 경로의 문구가 서로 다르다', () {
|
|
final error = _exception('account-exists-with-different-credential',
|
|
email: 'fan@gmail.com');
|
|
|
|
expect(
|
|
authMessage(error, flow: AuthFlow.signIn),
|
|
isNot(authMessage(error, flow: AuthFlow.link)),
|
|
);
|
|
});
|
|
|
|
test('이메일 힌트가 없으면 이메일 없이 같은 안내를 한다', () {
|
|
// Apple 은 최초 인가 때만 이메일을 준다 — 두 번째부터 힌트가 없다.
|
|
final message = authMessage(
|
|
_exception('account-exists-with-different-credential'),
|
|
flow: AuthFlow.signIn,
|
|
);
|
|
|
|
expect(message, startsWith('이 계정은'));
|
|
expect(message, contains('처음 가입에 쓰신 수단으로 로그인'));
|
|
expect(message, isNot(contains('null')));
|
|
});
|
|
|
|
test('에러 카탈로그 ID 는 경로와 무관하게 E-AUTH-08 이다', () {
|
|
// 문구만 갈랐다. 카탈로그를 손대면 Admin·QA 의 코드 대조가 어긋난다.
|
|
expect(
|
|
authCatalogCode(_exception('account-exists-with-different-credential')),
|
|
'E-AUTH-08',
|
|
);
|
|
});
|
|
});
|
|
|
|
group('경로와 무관한 코드는 한 문구를 유지한다', () {
|
|
test('credential-already-in-use 는 양쪽이 같다', () {
|
|
final error = _exception('credential-already-in-use');
|
|
|
|
expect(
|
|
authMessage(error, flow: AuthFlow.signIn),
|
|
'다른 FANUZU 계정에 이미 연결된 소셜 계정입니다.',
|
|
);
|
|
expect(
|
|
authMessage(error, flow: AuthFlow.link),
|
|
authMessage(error, flow: AuthFlow.signIn),
|
|
);
|
|
});
|
|
|
|
test('계정 존재 여부를 갈라 주지 않는다 — 열거 방지', () {
|
|
// 「등록되지 않은 이메일」과 「비밀번호 오류」가 같은 문구로 나가야 한다.
|
|
for (final code in ['user-not-found', 'wrong-password']) {
|
|
expect(
|
|
authMessage(_exception(code), flow: AuthFlow.signIn),
|
|
'이메일 또는 비밀번호를 확인해 주세요.',
|
|
reason: code,
|
|
);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
/// `FirebaseAuthException` 의 생성자가 `@protected` 라 밖에서 직접 부르면
|
|
/// 분석 경고가 난다. 하위 클래스에서 부르는 것은 허용되므로 테스트용으로 뚫는다.
|
|
final class _FakeAuthException extends fb.FirebaseAuthException {
|
|
_FakeAuthException({required super.code, super.email});
|
|
}
|
|
|
|
fb.FirebaseAuthException _exception(String code, {String? email}) =>
|
|
_FakeAuthException(code: code, email: email);
|