Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const _skipOnWeb = kIsWeb;
/// Supabase stack, one sign in method per test:
///
/// * email & password (sign up, sign out, sign in)
/// * a full password reset (the recovery code is read back from the mail server)
/// * a full password reset (the recovery code is read back from the mail
/// server)
/// * passwordless email OTP (the code is read back from the local mail server)
/// * phone SMS OTP (using the configured test OTP)
/// * anonymous sign in and upgrading it to a permanent account
Expand Down Expand Up @@ -389,7 +390,8 @@ List<int> _base32Decode(String input) {
return output;
}

/// Pumps frames until [finder] matches at least one widget or [timeout] elapses.
/// Pumps frames until [finder] matches at least one widget or [timeout]
/// elapses.
///
/// Auth calls go over the network, so the UI can't be settled with
/// `pumpAndSettle`; this polls the widget tree instead.
Expand Down
7 changes: 4 additions & 3 deletions examples/authentication/lib/auth_repository.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'package:supabase_flutter/supabase_flutter.dart';

/// Every `supabase.auth.*` call for the example lives here, so the UI stays thin
/// and each authentication flow is easy to read and to drive from an integration
/// test. The methods are grouped by the sign in method they belong to.
/// Every `supabase.auth.*` call for the example lives here, so the UI stays
/// thin and each authentication flow is easy to read and to drive from an
/// integration test. The methods are grouped by the sign in method they belong
/// to.
class AuthRepository {
AuthRepository(this._client);

Expand Down
12 changes: 6 additions & 6 deletions examples/authentication/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ class _PasswordFormState extends State<_PasswordForm> {
),
);

/// Sends the reset email, then reveals the fields to finish the reset with the
/// code from that email.
/// Sends the reset email, then reveals the fields to finish the reset with
/// the code from that email.
Future<void> _startReset() => _run(() async {
await _auth.sendPasswordReset(
_email.text.trim(),
Expand Down Expand Up @@ -250,8 +250,8 @@ class _PasswordFormState extends State<_PasswordForm> {
}
}

/// Passwordless sign in with `signInWithOtp` (email) then `verifyOTP`. The email
/// carries both a magic link and the code entered here.
/// Passwordless sign in with `signInWithOtp` (email) then `verifyOTP`. The
/// email carries both a magic link and the code entered here.
class _EmailOtpForm extends StatefulWidget {
const _EmailOtpForm();

Expand Down Expand Up @@ -518,8 +518,8 @@ class _AnonymousFormState extends State<_AnonymousForm> {
}
}

/// The account screen: shows who is signed in, lets an anonymous user upgrade to
/// a permanent account, manages MFA factors and signs out.
/// The account screen: shows who is signed in, lets an anonymous user upgrade
/// to a permanent account, manages MFA factors and signs out.
class _SignedInView extends StatelessWidget {
const _SignedInView({required this.user});

Expand Down
4 changes: 2 additions & 2 deletions examples/authentication/lib/models.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// The sign in methods the example offers on its signed-out screen. Each maps to
/// one or two calls on [AuthRepository]; the label is what the method picker
/// The sign in methods the example offers on its signed-out screen. Each maps
/// to one or two calls on [AuthRepository]; the label is what the method picker
/// shows.
enum AuthMethod {
password('Email & password'),
Expand Down
18 changes: 9 additions & 9 deletions examples/database_crud/integration_test/tasks_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ void main() {
createdTitle,
);
await tester.tap(find.widgetWithText(FilledButton, 'Create'));
// Searches for the new task rather than looking for it in the full list: the
// dialog leaves the keyboard up, and on a phone that leaves room for only a
// couple of tiles, so it would otherwise end up below the fold. Waits for the
// tile rather than the title text, which also matches the text field of the
// dialog that is still animating away.
// Searches for the new task rather than looking for it in the full list:
// the dialog leaves the keyboard up, and on a phone that leaves room for
// only a couple of tiles, so it would otherwise end up below the fold.
// Waits for the tile rather than the title text, which also matches the
// text field of the dialog that is still animating away.
await _searchFor(tester, createdTitle);
await _pumpUntil(tester, _tile(createdTitle));

Expand Down Expand Up @@ -122,7 +122,8 @@ Finder _inTile(String title, Finder target) =>
Future<void> _searchFor(WidgetTester tester, String query) =>
tester.enterText(find.widgetWithText(TextField, 'Search title'), query);

/// Pumps frames until [finder] matches at least one widget or [timeout] elapses.
/// Pumps frames until [finder] matches at least one widget or [timeout]
/// elapses.
///
/// Reads and writes go over the network, so the UI can't be settled with
/// `pumpAndSettle`; this polls the widget tree instead.
Expand Down Expand Up @@ -157,9 +158,8 @@ String _screen() {
.byType(Checkbox)
.evaluate()
.map((element) => '${(element.widget as Checkbox).value}');
return 'Labels: ${labels.join(' | ')}\n'
'Text fields: ${fields.join(' | ')}\n'
'Checkboxes: ${boxes.join(' | ')}';
return 'Labels: ${labels.join(' | ')}\nText fields: '
'${fields.join(' | ')}\nCheckboxes: ${boxes.join(' | ')}';
}

/// The inverse of [_pumpUntil]: pumps until [finder] matches nothing.
Expand Down
8 changes: 4 additions & 4 deletions examples/database_crud/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class _TasksPageState extends State<TasksPage> {
bool _mutating = false;
Timer? _debounce;

/// Bumped on every task reload so a slower earlier request can't overwrite the
/// results of a later one.
/// Bumped on every task reload so a slower earlier request can't overwrite
/// the results of a later one.
int _requestId = 0;

@override
Expand Down Expand Up @@ -87,8 +87,8 @@ class _TasksPageState extends State<TasksPage> {
}

/// Reloads the task list for the current filters. Leaves the previous list on
/// screen while it runs, so changing a filter or toggling a task doesn't flash
/// a spinner over the whole list.
/// screen while it runs, so changing a filter or toggling a task doesn't
/// flash a spinner over the whole list.
Future<void> _loadTasks() async {
final requestId = ++_requestId;
// Ignore a response if a newer reload started or the widget went away while
Expand Down
4 changes: 2 additions & 2 deletions examples/database_crud/lib/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Task {
final Priority priority;
final DateTime createdAt;

/// Name of the task's project, populated from the embedded `projects` row when
/// the task is fetched with a join.
/// Name of the task's project, populated from the embedded `projects` row
/// when the task is fetched with a join.
final String? projectName;
}
4 changes: 2 additions & 2 deletions examples/database_crud/lib/tasks_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import 'package:supabase_flutter/supabase_flutter.dart';

import 'models.dart';

/// All database access for the CRUD example lives here, so the UI stays thin and
/// every `supabase.from(...)` call is easy to read and to exercise from an
/// All database access for the CRUD example lives here, so the UI stays thin
/// and every `supabase.from(...)` call is easy to read and to exercise from an
/// integration test.
class TasksRepository {
TasksRepository(this._client);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const supabasePublishableKey = String.fromEnvironment(
///
/// The first test exercises the core flow through the repository (a JSON
/// greeting over POST and GET, a plain-text transform, and a validation error),
/// asserting on what each function returns. The second drives the app widgets to
/// confirm the greeting card is wired to the function. Edge Functions are
/// asserting on what each function returns. The second drives the app widgets
/// to confirm the greeting card is wired to the function. Edge Functions are
/// stateless, so there is nothing to clean up between runs.
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
Expand Down Expand Up @@ -85,7 +85,8 @@ void main() {
});
}

/// Pumps frames until [finder] matches at least one widget or [timeout] elapses.
/// Pumps frames until [finder] matches at least one widget or [timeout]
/// elapses.
///
/// Invoking a function goes over the network, so the UI can't be settled with
/// `pumpAndSettle`; this polls the widget tree instead.
Expand Down
3 changes: 2 additions & 1 deletion examples/edge_functions/integration_test/invoke_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ void main() {
_,
) async {
// A client pointed at a closed port can never connect, so the request
// fails before any response, surfacing as a fetch exception with status 0.
// fails before any response, surfacing as a fetch exception with status
// 0.
final unreachable = FunctionsClient(
'http://127.0.0.1:1/functions/v1',
const {'apikey': supabasePublishableKey},
Expand Down
18 changes: 10 additions & 8 deletions examples/edge_functions/lib/functions_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import 'package:supabase_flutter/supabase_flutter.dart';

import 'models.dart';

/// All Edge Function access for the example lives here, so the UI stays thin and
/// every `supabase.functions.invoke(...)` call is easy to read and to exercise
/// from an integration test.
/// All Edge Function access for the example lives here, so the UI stays thin
/// and every `supabase.functions.invoke(...)` call is easy to read and to
/// exercise from an integration test.
class FunctionsRepository {
FunctionsRepository(this._client);

Expand All @@ -17,7 +17,8 @@ class FunctionsRepository {
///
/// The custom `x-greeting-source` header is echoed back in the response, so
/// the example can show that headers set here reach the function. A JSON body
/// comes back decoded as a `Map`, which [Greeting.fromJson] turns into a model.
/// comes back decoded as a `Map`, which [Greeting.fromJson] turns into a
/// model.
Future<Greeting> greet({required String name, bool excited = false}) async {
final response = await _functions.invoke(
'greet',
Expand All @@ -42,17 +43,18 @@ class FunctionsRepository {
/// responds with.
///
/// A `String` body is sent as `text/plain`, and the function replies with
/// `text/plain` too, so `response.data` is a `String` rather than decoded JSON.
/// `text/plain` too, so `response.data` is a `String` rather than decoded
/// JSON.
Future<String> shout(String text) async {
final response = await _functions.invoke('shout', body: text);
return response.data as String;
}

/// Invokes the `word-count` function, which validates its input.
///
/// When [text] is empty the function replies with a 400 and a JSON error body,
/// which surfaces here as a [FunctionException] whose `details` hold that body.
/// The caller is expected to handle that exception.
/// When [text] is empty the function replies with a 400 and a JSON error
/// body, which surfaces here as a [FunctionException] whose `details` hold
/// that body. The caller is expected to handle that exception.
Future<WordCount> countWords(String text) async {
final response = await _functions.invoke(
'word-count',
Expand Down
4 changes: 2 additions & 2 deletions examples/edge_functions/lib/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class Greeting {

factory Greeting.fromJson(Map<String, dynamic> json) => Greeting(
message: json['message'] as String,
// How the function was invoked (`GET` or `POST`), echoed back so the app can
// show that the same function was reached two different ways.
// How the function was invoked (`GET` or `POST`), echoed back so the app
// can show that the same function was reached two different ways.
method: json['method'] as String,
// The `x-greeting-source` header the app sent, echoed back to show that
// custom headers reach the function.
Expand Down
11 changes: 6 additions & 5 deletions examples/launcher/lib/launcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ const _ok = 0;
const _failure = 1;

const _noTerminalMessage =
'The launcher needs an interactive terminal to pick an example. '
'Run it directly in your terminal.';
'The launcher needs an interactive terminal to pick an example. Run it '
'directly in your terminal.';

final _logger = Logger();

Expand Down Expand Up @@ -90,8 +90,8 @@ Future<int> run(List<String> args) async {
_logger
..info('')
..info(
'${styleBold.wrap('Running')} ${cyan.wrap(selected.name)} '
'against ${cyan.wrap(url)}',
'${styleBold.wrap('Running')} ${cyan.wrap(selected.name)} against '
'${cyan.wrap(url)}',
);

// Serve on a fixed origin so it matches the WebAuthn rp_origins configured
Expand Down Expand Up @@ -119,7 +119,8 @@ Future<int> run(List<String> args) async {
);

// Forward Ctrl-C to flutter so it shuts down and control returns here,
// letting the cleanup below stop Supabase, rather than killing the launcher.
// letting the cleanup below stop Supabase, rather than killing the
// launcher.
final sigint = ProcessSignal.sigint.watch().listen(
(_) => process.kill(ProcessSignal.sigint),
);
Expand Down
12 changes: 7 additions & 5 deletions examples/passkeys/integration_test/passkeys_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ const supabasePublishableKey = String.fromEnvironment(
/// Supabase stack.
///
/// It covers everything around the WebAuthn ceremony: creating an account,
/// landing on the passkey management screen, signing out, a failed sign in and a
/// successful password sign in. The ceremony itself (`registerPasskey` /
/// `signInWithPasskey`) drives a platform authenticator prompt (Face ID, Windows
/// Hello, a security key, ...) that can't be automated headlessly, so it is
/// landing on the passkey management screen, signing out, a failed sign in and
/// a successful password sign in. The ceremony itself (`registerPasskey` /
/// `signInWithPasskey`) drives an authenticator prompt, whether from a platform
/// authenticator such as Face ID or Windows Hello or from a roaming one such as
/// a security key. That prompt can't be automated headlessly, so it is
/// exercised manually per the README rather than here.
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
Expand Down Expand Up @@ -93,7 +94,8 @@ void main() {
});
}

/// Pumps frames until [finder] matches at least one widget or [timeout] elapses.
/// Pumps frames until [finder] matches at least one widget or [timeout]
/// elapses.
///
/// Auth calls go over the network, so the UI can't be settled with
/// `pumpAndSettle`; this polls the widget tree instead.
Expand Down
13 changes: 7 additions & 6 deletions examples/realtime_room/integration_test/room_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const supabasePublishableKey = String.fromEnvironment(

/// End-to-end test that drives the real app widgets against the local Supabase
/// stack, exercising all three realtime features through the UI: Postgres
/// Changes (a message round-tripping through the database), Presence (the online
/// roster) and Broadcast (the typing indicator).
/// Changes (a message round-tripping through the database), Presence (the
/// online roster) and Broadcast (the typing indicator).
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

Expand Down Expand Up @@ -47,9 +47,9 @@ void main() {
await tester.tap(find.text('Join room'));
await tester.pumpAndSettle();

// Wait for the loading spinner to clear. The room only finishes loading once
// Postgres Changes replication is live, so a message sent after this is
// guaranteed to stream back rather than being missed during setup.
// Wait for the loading spinner to clear. The room only finishes loading
// once Postgres Changes replication is live, so a message sent after this
// is guaranteed to stream back rather than being missed during setup.
await _pumpUntilGone(tester, find.byType(CircularProgressIndicator));

// Presence: once subscribed, our own name appears in the roster.
Expand Down Expand Up @@ -100,7 +100,8 @@ void main() {
});
}

/// Pumps frames until [finder] matches at least one widget or [timeout] elapses.
/// Pumps frames until [finder] matches at least one widget or [timeout]
/// elapses.
///
/// Realtime updates arrive asynchronously over the network, so the UI can't be
/// settled with `pumpAndSettle`; this polls the widget tree instead.
Expand Down
16 changes: 8 additions & 8 deletions examples/realtime_room/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class RealtimeRoomApp extends StatelessWidget {
}
}

/// Asks for a display name before joining the room. Open the example in a second
/// window with a different name to see the realtime features in action.
/// Asks for a display name before joining the room. Open the example in a
/// second window with a different name to see the realtime features in action.
class JoinPage extends StatefulWidget {
const JoinPage({super.key});

Expand Down Expand Up @@ -193,8 +193,8 @@ class _RoomPageState extends State<RoomPage> {
setState(() => _messages.removeWhere((message) => message.id == id));
}

/// Shows `<name> is typing` for a short while, resetting the timer each time a
/// fresh ping arrives from that user.
/// Shows `<name> is typing` for a short while, resetting the timer each time
/// a fresh ping arrives from that user.
void _showTyping(String name) {
_typingTimers[name]?.cancel();
setState(() => _typingUsers.add(name));
Expand All @@ -203,8 +203,8 @@ class _RoomPageState extends State<RoomPage> {
});
}

/// Throttles typing pings so a burst of keystrokes sends at most one broadcast
/// per second.
/// Throttles typing pings so a burst of keystrokes sends at most one
/// broadcast per second.
void _onInputChanged(String _) {
if (_typingThrottle?.isActive ?? false) return;
_typingThrottle = Timer(const Duration(seconds: 1), () {});
Expand All @@ -230,8 +230,8 @@ class _RoomPageState extends State<RoomPage> {
}
}

/// Deletes a message and reports any failure, like [_send]. The row leaves the
/// list through the Postgres Changes delete stream, so there's nothing to
/// Deletes a message and reports any failure, like [_send]. The row leaves
/// the list through the Postgres Changes delete stream, so there's nothing to
/// remove here on success.
Future<void> _delete(String id) async {
try {
Expand Down
4 changes: 2 additions & 2 deletions examples/realtime_room/lib/models.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// A chat message stored in the `messages` table. New rows are streamed to every
/// client in the room through realtime Postgres Changes.
/// A chat message stored in the `messages` table. New rows are streamed to
/// every client in the room through realtime Postgres Changes.
class Message {
const Message({
required this.id,
Expand Down
Loading
Loading