import 'package:flutter_test/flutter_test.dart'; import 'package:halkyon_oidc_flutter/halkyon_oidc_flutter.dart'; void main() { const state = 'app-scheme.q3J0aGVyZQ'; OidcCallback parse(String query, {String base = 'my.app://oidc-callback'}) => OidcCallback.parse('$base?$query', state: state); test('reads the code that came back for the sign-in', () { expect(parse('code=abc&state=$state'), const OidcCode('abc')); }); test('reads it from the loopback and from an https address alike', () { for (final base in [ 'http://127.0.0.1:43823/oidc-callback', 'https://example.org/oidc-callback', ]) { expect( parse('state=$state&code=abc', base: base), const OidcCode('abc'), reason: base, ); } }); test("reads the provider's refusal", () { expect( parse('error=access_denied&state=$state'), const OidcDenied('access_denied'), ); // SimpleLogin's own. expect(parse('error=deny&state=$state'), const OidcDenied('deny')); }); test('refuses what came back for another sign-in, or for none', () { for (final query in [ 'code=abc&state=app-scheme.other', 'code=abc&state=', 'code=abc', 'error=deny&state=app-scheme.other', 'error=deny', ]) { expect( () => parse(query), throwsA(_problem(OidcCallbackProblem.wrongState)), reason: query, ); } }); test('refuses what is neither a code nor a refusal', () { for (final query in [ 'state=$state', 'code=&state=$state', 'error=&state=$state', 'code=abc&error=deny&state=$state', 'code=a&code=b&state=$state', 'error=deny&error=deny&state=$state', 'code=abc&state=$state&state=$state', ]) { expect( () => parse(query), throwsA(_problem(OidcCallbackProblem.malformed)), reason: query, ); } }); test("refuses an address that can't be read", () { // A UTF-8 sequence cut short. expect( () => parse('code=%E0%A4&state=$state'), throwsA(_problem(OidcCallbackProblem.malformed)), ); }); } Matcher _problem(OidcCallbackProblem problem) => isA() .having((error) => error.problem, 'problem', problem);