The CI Flutter SDK predates v3.41 and only exposes ReorderableListView's onReorder; the newer onReorderItem broke the build with three analyzer errors. onReorder exists in both SDKs, so use it and compensate for its pre-removal newIndex internally. Fixing the call site surfaced a real ordering bug: _onReorder located the target neighbour in the untrimmed global list, while ServicioFavoritos .reordenar inserts into the list after the station is removed. Dragging a station downwards past its neighbours therefore landed it one slot too far. Adds a mid-list downward-drag test, the only case that separates the two coordinate spaces.
97 lines
3.1 KiB
Dart
97 lines
3.1 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'arb_test_helpers.dart';
|
|
import 'identical_value_allowlist.dart';
|
|
|
|
/// WU18 task 18.1b -- the anti-copy guard.
|
|
///
|
|
/// A key-parity test alone is NOT sufficient: it passes just as happily if
|
|
/// all 11 non-`es` locales simply copy the Spanish template value verbatim
|
|
/// for every key -- which would certify the exact bug it exists to catch
|
|
/// (see `reference/l10n-spanish-template-fallback`). This test collects
|
|
/// every value in a non-`es` locale that is byte-identical to the Spanish
|
|
/// template's value for the same key and fails unless that (locale, key)
|
|
/// pair is explicitly, individually allowlisted in
|
|
/// `identical_value_allowlist.dart`.
|
|
///
|
|
/// Scope note: `en` is deliberately excluded from this guard. Unlike the
|
|
/// other 11 locales -- which this change batch-translates for the first
|
|
/// time -- `en` and `es` have been hand-maintained together by every work
|
|
/// unit throughout this whole redesign (`en`/`es`-only new keys, never
|
|
/// left lagging), so `en` never carries the "silently fell back to the
|
|
/// template" risk this guard exists to catch.
|
|
const _auditedLocales = [
|
|
'ar',
|
|
'bn',
|
|
'de',
|
|
'fr',
|
|
'hi',
|
|
'id',
|
|
'it',
|
|
'ja',
|
|
'pt',
|
|
'ru',
|
|
'zh',
|
|
];
|
|
|
|
void main() {
|
|
test('every non-es value identical to the Spanish template is a '
|
|
'deliberately allowlisted exception, not an accidental untranslated '
|
|
'copy', () {
|
|
final es = readArb('es');
|
|
final unlisted = <String>[];
|
|
|
|
for (final locale in _auditedLocales) {
|
|
final arb = readArb(locale);
|
|
for (final key in realKeys(arb)) {
|
|
// Missing keys are arb_parity_test's job, not this one's.
|
|
if (!es.containsKey(key)) continue;
|
|
if (arb[key] == es[key] &&
|
|
!identicalValueAllowlist.contains((locale, key))) {
|
|
unlisted.add('$locale/$key = "${arb[key]}"');
|
|
}
|
|
}
|
|
}
|
|
|
|
expect(
|
|
unlisted,
|
|
isEmpty,
|
|
reason:
|
|
'Found value(s) identical to the Spanish template that are NOT '
|
|
'in identical_value_allowlist.dart -- this is very likely an '
|
|
'untranslated copy-paste, not a deliberate cognate/brand-name/'
|
|
'symbol exception. Translate it, or add a reviewed, individual '
|
|
'allowlist entry with a justification comment if it truly is '
|
|
'untranslatable:\n${unlisted.join('\n')}',
|
|
);
|
|
});
|
|
|
|
test(
|
|
'every allowlisted pair is a real, current collision (no stale entries)',
|
|
() {
|
|
final es = readArb('es');
|
|
final stale = <String>[];
|
|
|
|
for (final entry in identicalValueAllowlist) {
|
|
final (locale, key) = entry;
|
|
final arb = readArb(locale);
|
|
final stillCollides =
|
|
arb.containsKey(key) && es.containsKey(key) && arb[key] == es[key];
|
|
if (!stillCollides) {
|
|
stale.add('$locale/$key');
|
|
}
|
|
}
|
|
|
|
expect(
|
|
stale,
|
|
isEmpty,
|
|
reason:
|
|
'identical_value_allowlist.dart has entries that no longer '
|
|
'correspond to a real identical value -- remove them, the '
|
|
'allowlist must only contain genuine, current exceptions:\n'
|
|
'${stale.join('\n')}',
|
|
);
|
|
},
|
|
);
|
|
}
|