diff --git a/flutter/lib/common/formatter/id_formatter.dart b/flutter/lib/common/formatter/id_formatter.dart index c2329d53f..79c4bc6b1 100644 --- a/flutter/lib/common/formatter/id_formatter.dart +++ b/flutter/lib/common/formatter/id_formatter.dart @@ -33,8 +33,13 @@ class IDTextInputFormatter extends TextInputFormatter { } } +// Pasted IDs can carry a trailing newline or tab (e.g. copied from a +// spreadsheet cell) or non-breaking spaces, so strip all whitespace, not only +// plain spaces. +final _whitespace = RegExp(r'\s'); + String formatID(String id) { - String id2 = id.replaceAll(' ', ''); + String id2 = id.replaceAll(_whitespace, ''); String suffix = ''; if (id2.endsWith(r'\r') || id2.endsWith(r'/r')) { suffix = id2.substring(id2.length - 2, id2.length); @@ -56,5 +61,5 @@ String formatID(String id) { } String trimID(String id) { - return id.replaceAll(' ', ''); + return id.replaceAll(_whitespace, ''); } diff --git a/flutter/test/id_formatter_test.dart b/flutter/test/id_formatter_test.dart new file mode 100644 index 000000000..b1a271ec4 --- /dev/null +++ b/flutter/test/id_formatter_test.dart @@ -0,0 +1,44 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_hbb/common/formatter/id_formatter.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('formatID', () { + test('groups typed IDs from the right', () { + expect(formatID('53464938'), '53 464 938'); + expect(formatID('123456789'), '123 456 789'); + expect(formatID('1234'), '1 234'); + }); + + test('ignores line breaks, tabs and non-breaking spaces from a paste', () { + expect(formatID('53464938\r\n'), '53 464 938'); + expect(formatID('53464938\n'), '53 464 938'); + expect(formatID('\t53464938'), '53 464 938'); + expect(formatID('53\u00a0464\u00a0938'), '53 464 938'); + }); + + test('keeps the relay suffix', () { + expect(formatID(r'53464938\r'), r'53 464 938\r'); + }); + + test('leaves non-numeric input alone', () { + expect(formatID('my-host.example.com'), 'my-host.example.com'); + }); + }); + + test('trimID drops all whitespace', () { + expect(trimID('53 464 938\r\n'), '53464938'); + expect(trimID('53\u00a0464\u00a0938'), '53464938'); + }); + + test('pasting an ID with a trailing newline formats it like typing', () { + final formatted = IDTextInputFormatter().formatEditUpdate( + TextEditingValue.empty, + const TextEditingValue( + text: '53464938\r\n', + selection: TextSelection.collapsed(offset: 10), + ), + ); + expect(formatted.text, '53 464 938'); + }); +}