diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..40cab31 --- /dev/null +++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "monthly"
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml new file mode 100644 index 0000000..9bf6845 --- /dev/null +++ b/.github/workflows/test-package.yml
@@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v3 + - uses: dart-lang/setup-dart@v1 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [2.12.0, dev] + steps: + - uses: actions/checkout@v3 + - uses: dart-lang/setup-dart@v1 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success'
diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e6a4be6..0000000 --- a/.travis.yml +++ /dev/null
@@ -1,20 +0,0 @@ -language: dart - -dart: - - dev - -jobs: - include: - - script: pub run --enable-experiment=non-nullable test - - script: pub run --enable-experiment=non-nullable test -p chrome - - dart_task: dartfmt - - dart_task: - dartanalyzer: --enable-experiment=non-nullable --fatal-infos --fatal-warnings . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache
diff --git a/CHANGELOG.md b/CHANGELOG.md index fb80a73..3f2542a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md
@@ -1,5 +1,8 @@ -## 0.17.0-nullsafety +## 0.17.1-dev +* Add optional parameter to `NumberFormat.compact()` to provide custom pattern. + +## 0.17.0 * Migrate to null safety. * Add `@pragma('vm:prefer-inline')` to `Intl` methods that already have `@pragma('dart2js:tryInline')`, for the same reason: to help omit message
diff --git a/LICENSE b/LICENSE index ee99930..7efe25f 100644 --- a/LICENSE +++ b/LICENSE
@@ -1,4 +1,5 @@ -Copyright 2013, the Dart project authors. All rights reserved. +Copyright 2013, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
diff --git a/analysis_options.yaml b/analysis_options.yaml index 4cce960..d18178b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml
@@ -1,7 +1,4 @@ analyzer: - enable-experiment: - - non-nullable - language: strict-raw-types: true
diff --git a/lib/date_time_patterns.dart b/lib/date_time_patterns.dart index 162dc20..af734be 100644 --- a/lib/date_time_patterns.dart +++ b/lib/date_time_patterns.dart
@@ -16,7 +16,7 @@ /// Returns a Map from locale names to another Map that goes from skeletons /// to the locale-specific formatting patterns. /// Internal use only. Call initializeDateFormatting instead. -Map<String, Map<String, String>> dateTimePatternMap() => const { +Map<String, Map<String, String>> dateTimePatternMap() => { /// Extended set of localized date/time patterns for locale af. 'af': const { 'd': 'd', // DAY
diff --git a/lib/message_format.dart b/lib/message_format.dart index 45b47ef..7b31ac9 100644 --- a/lib/message_format.dart +++ b/lib/message_format.dart
@@ -76,7 +76,7 @@ /// produce `"I see Mark and one other person in Athens."` as output. /// /// Calling `format({'NUM_PEOPLE': 5, 'WHO': 'Mark', 'PLACE': 'Athens'})` would -/// produce `"I see Mark and one 4 other people in Athens."` as output. +/// produce `"I see Mark and 4 other people in Athens."` as output. /// Notice how the "#" is the value of `NUM_PEOPLE` - 1 (the offset). /// /// Another important thing to notice is the existence of both `"=1"` and
diff --git a/lib/src/intl/number_format.dart b/lib/src/intl/number_format.dart index 9a3a8f2..85c1b05 100644 --- a/lib/src/intl/number_format.dart +++ b/lib/src/intl/number_format.dart
@@ -364,18 +364,24 @@ /// A number format for compact representations, e.g. "1.2M" instead /// of "1,200,000". - factory NumberFormat.compact({String? locale}) { + factory NumberFormat.compact({String? locale, String? pattern}) { return _CompactNumberFormat( locale: locale, - formatType: _CompactFormatType.COMPACT_DECIMAL_SHORT_PATTERN); + formatType: _CompactFormatType.COMPACT_DECIMAL_SHORT_PATTERN, + getPattern: pattern != null + ? (x) => pattern + : _CompactNumberFormat._forDecimal); } /// A number format for "long" compact representations, e.g. "1.2 million" - /// instead of of "1,200,000". - factory NumberFormat.compactLong({String? locale}) { + /// instead of "1,200,000". + factory NumberFormat.compactLong({String? locale, String? pattern}) { return _CompactNumberFormat( locale: locale, - formatType: _CompactFormatType.COMPACT_DECIMAL_LONG_PATTERN); + formatType: _CompactFormatType.COMPACT_DECIMAL_LONG_PATTERN, + getPattern: pattern != null + ? (x) => pattern + : _CompactNumberFormat._forDecimal); } /// A number format for compact currency representations, e.g. "$1.2M" instead
diff --git a/pubspec.yaml b/pubspec.yaml index 98c064f..870f832 100644 --- a/pubspec.yaml +++ b/pubspec.yaml
@@ -1,5 +1,5 @@ name: intl -version: 0.17.0-nullsafety +version: 0.17.1-dev homepage: https://github.com/dart-lang/intl description: >- Contains code to deal with internationalized/localized messages, date and @@ -7,23 +7,14 @@ internationalization issues. environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.11.0-180.0.dev <2.11.0' + sdk: '>=2.12.0-0 <3.0.0' dependencies: - clock: ^1.1.0-nullsafety.1 - path: ^1.8.0-nullsafety.1 + clock: ^1.1.0 + path: ^1.8.0 dev_dependencies: - ffi: any - fixnum: '>=0.9.0 <0.11.0' - js: ^0.6.3-nullsafety - test: ^1.16.0-nullsafety.4 - -dependency_overrides: - ffi: - git: - url: https://github.com/dart-lang/ffi - ref: null_safety - fixnum: - git: https://github.com/dart-lang/fixnum + ffi: ^1.0.0 + fixnum: ^1.0.0 + js: ^0.6.3 + test: ^1.16.0
diff --git a/test/date_time_format_custom_test.dart b/test/date_time_format_custom_test.dart index 4dc42e2..f29f368 100644 --- a/test/date_time_format_custom_test.dart +++ b/test/date_time_format_custom_test.dart
@@ -4,10 +4,9 @@ /// Test date formatting and parsing using custom locale data, which we get /// from the local copy. - +import 'package:intl/date_symbol_data_custom.dart'; import 'package:intl/date_symbol_data_local.dart' as local_symbols; import 'package:intl/date_time_patterns.dart' as local_patterns; -import 'package:intl/date_symbol_data_custom.dart'; import 'date_time_format_test_stub.dart';
diff --git a/test/date_time_format_test_stub.dart b/test/date_time_format_test_stub.dart index a1d5b63..ea4d967 100644 --- a/test/date_time_format_test_stub.dart +++ b/test/date_time_format_test_stub.dart
@@ -7,8 +7,9 @@ library date_time_format_test; -import 'package:test/test.dart'; import 'package:intl/intl.dart'; +import 'package:test/test.dart'; + import 'date_time_format_test_core.dart'; typedef TestListFunc = List<String> Function();
diff --git a/test/fixnum_test.dart b/test/fixnum_test.dart index 8f9f874..a5c1a84 100644 --- a/test/fixnum_test.dart +++ b/test/fixnum_test.dart
@@ -4,9 +4,9 @@ library fixnum_test; +import 'package:fixnum/fixnum.dart'; import 'package:intl/intl.dart'; import 'package:test/test.dart'; -import 'package:fixnum/fixnum.dart'; var int64Values = { Int64(12345): ['USD12,345.00', '1,234,500%'],
diff --git a/test/intl_test.dart b/test/intl_test.dart index 77f10c5..a780abe 100644 --- a/test/intl_test.dart +++ b/test/intl_test.dart
@@ -4,9 +4,9 @@ library intl_test; +import 'package:intl/date_symbol_data_local.dart'; import 'package:intl/intl.dart'; import 'package:test/test.dart'; -import 'package:intl/date_symbol_data_local.dart'; void main() { test("Locale setting doesn't verify the core locale", () {
diff --git a/test/locale_test.dart b/test/locale_test.dart index 59d75af..58c4e1b 100644 --- a/test/locale_test.dart +++ b/test/locale_test.dart
@@ -9,9 +9,8 @@ /// /// For production code, use of ICU would influence what needs and doesn't need /// to be tested. - -import 'package:test/test.dart'; import 'package:intl/locale.dart'; +import 'package:test/test.dart'; import 'locale_test_data.dart';
diff --git a/test/number_format_compact_icu_test.dart b/test/number_format_compact_icu_test.dart index 250b580..5cb1255 100644 --- a/test/number_format_compact_icu_test.dart +++ b/test/number_format_compact_icu_test.dart
@@ -16,58 +16,62 @@ import 'more_compact_number_test_data.dart' as more_testdata; main() { - var problemLocales = [ + var problemLocales = { // ICU produces numerals in Arabic script, package:intl uses Latin script. 'ar', // package:intl includes some tweaks to compact numbers for Bengali. 'bn', - ]; - + }; runICUTests(systemIcuVersion: 63, skipLocales: problemLocales); } void runICUTests( - {int? systemIcuVersion, String? specialIcuLib, List<String>? skipLocales}) { - if (!setupICU( + {int? systemIcuVersion, + String? specialIcuLib, + Set<String> skipLocales = const {}}) { + if (!_setupICU( systemIcuVersion: systemIcuVersion, specialIcuLibPath: specialIcuLib)) { return; } - print("Skipping problem locales $skipLocales."); - testdata35.compactNumberTestData - .removeWhere((k, v) => skipLocales!.contains(k)); + void validate(String locale, List<List<String>> expected) { + _validateShort(locale, expected, skipLocales); + _validateLong(locale, expected, skipLocales); + } + testdata35.compactNumberTestData.forEach(validate); - more_testdata.cldr35CompactNumTests.forEach(validateFancy); + more_testdata.cldr35CompactNumTests.forEach(_validateFancy); test('UNumberFormatter simple integer formatting', () { - expect(FormatWithUnumf('en', 'precision-integer', 5142.3), '5,142'); + expect(_formatWithUnumf('en', 'precision-integer', 5142.3), '5,142'); }); } -void validate(String locale, List<List<String>> expected) { - validateShort(locale, expected); - validateLong(locale, expected); -} - -void validateShort(String locale, List<List<String>> expected) { +void _validateShort( + String locale, List<List<String>> expected, Set<String> skipLocales) { + var skip = + skipLocales.contains(locale) ? 'Skipping problem locale $locale' : false; test('Validate $locale SHORT', () { for (var data in expected) { var number = num.parse(data.first); - expect(FormatWithUnumf(locale, 'compact-short', number), data[1]); + expect(_formatWithUnumf(locale, 'compact-short', number), data[1]); } - }); + }, skip: skip); } -void validateLong(String locale, List<List<String>> expected) { +void _validateLong( + String locale, List<List<String>> expected, Set<String> skipLocales) { + var skip = + skipLocales.contains(locale) ? 'Skipping problem locale $locale' : false; test('Validate $locale LONG', () { for (var data in expected) { var number = num.parse(data.first); - expect(FormatWithUnumf(locale, 'compact-long', number), data[2]); + expect(_formatWithUnumf(locale, 'compact-long', number), data[2]); } - }); + }, skip: skip); } -void validateFancy(more_testdata.CompactRoundingTestCase t) { +void _validateFancy(more_testdata.CompactRoundingTestCase t) { var locale = 'en'; var skel = 'compact-short'; if (t.minimumIntegerDigits != null) { @@ -84,7 +88,7 @@ skel += ' .' + '#' * t.maximumFractionDigits!; } test(t.toString(), () { - expect(FormatWithUnumf(locale, skel, t.number), t.expected, + expect(_formatWithUnumf(locale, skel, t.number), t.expected, reason: 'Skeleton: $skel'); }); } @@ -106,7 +110,7 @@ /// /// If [systemIcuVersion] is unspecified, we expect to find all functions in a /// library with filename [specialIcuLibPath]. -bool setupICU({int? systemIcuVersion, String? specialIcuLibPath}) { +bool _setupICU({int? systemIcuVersion, String? specialIcuLibPath}) { DynamicLibrary libicui18n; String icuVersionSuffix; if (systemIcuVersion != null) { @@ -152,21 +156,21 @@ return true; } -String FormatWithUnumf(String locale, String skeleton, num number) { +String _formatWithUnumf(String locale, String skeleton, num number) { // // Setup: // UErrorCode ec = U_ZERO_ERROR; // UNumberFormatter* uformatter = // unumf_openForSkeletonAndLocale(u"precision-integer", -1, "en", &ec); // UFormattedNumber* uresult = unumf_openResult(&ec); // if (U_FAILURE(ec)) { return; } - final cLocale = Utf8.toUtf8(locale); - final cSkeleton = Utf16.toUtf16(skeleton); - final cErrorCode = allocate<Int32>(count: 1); + final cLocale = locale.toNativeUtf8(); + final cSkeleton = skeleton.toNativeUtf16(); + final cErrorCode = calloc<Int32>(); cErrorCode.value = 0; final uformatter = unumf_openForSkeletonAndLocale!(cSkeleton, -1, cLocale, cErrorCode); - free(cSkeleton); - free(cLocale); + calloc.free(cSkeleton); + calloc.free(cLocale); var errorCode = cErrorCode.value; expect(errorCode, lessThanOrEqualTo(0), reason: u_errorName!(errorCode).toString()); @@ -201,7 +205,7 @@ expect(errorCode, equals(15), // U_BUFFER_OVERFLOW_ERROR reason: u_errorName!(errorCode).toString()); cErrorCode.value = 0; - final buffer = allocate<Utf16>(count: reqLen + 1); + final buffer = calloc<Uint16>(reqLen + 1).cast<Utf16>(); unumf_resultToString!(uresult, buffer, reqLen + 1, cErrorCode); errorCode = cErrorCode.value; expect(errorCode, lessThanOrEqualTo(0), @@ -211,11 +215,11 @@ // // Cleanup: // unumf_close(uformatter); // unumf_closeResult(uresult); - // free(buffer); + // calloc.free(buffer); unumf_close!(uformatter); unumf_closeResult!(uresult); - free(buffer); - free(cErrorCode); + calloc.free(buffer); + calloc.free(cErrorCode); return result; } @@ -229,10 +233,10 @@ typedef UErrorNameOp = Pointer<Utf8> Function(int code); /// [UNumberFormatter](http://icu-project.org/apiref/icu4c/unumberformatter_8h.html#a7c1238b2dd08f32f1ea245ece41e71bd) -class UNumberFormatter extends Struct {} +class UNumberFormatter extends Opaque {} /// [UFormattedNumber](http://icu-project.org/apiref/icu4c/unumberformatter_8h.html#a9d4030bdc4dd1ec4de828bf1bcf4b1b6) -class UFormattedNumber extends Struct {} +class UFormattedNumber extends Opaque {} /// C signature for /// [unumf_openForSkeletonAndLocale()](http://icu-project.org/apiref/icu4c/unumberformatter_8h.html#a29339e144833880bda36fb7c17032698)
diff --git a/test/number_format_compact_test.dart b/test/number_format_compact_test.dart index 0103c97..1545815 100644 --- a/test/number_format_compact_test.dart +++ b/test/number_format_compact_test.dart
@@ -4,10 +4,13 @@ /// Tests for compact format numbers, e.g. 1.2M rather than 1,200,000 import 'dart:math'; -import 'package:test/test.dart'; -import 'package:intl/intl.dart'; + import 'package:fixnum/fixnum.dart'; +import 'package:intl/intl.dart'; +import 'package:intl/number_symbols_data.dart'; import 'package:intl/number_symbols_data.dart' as patterns; +import 'package:test/test.dart'; + import 'compact_number_test_data_33.dart' as testdata33; // End-goal: to stop testing against testdata33 and use testdata35 instead: // import 'compact_number_test_data.dart' as testdata35; @@ -19,13 +22,43 @@ // 'mn' : [['4321', '4.32M', 'whatever']] }; +var compactWithPatternCases = <List<String>>[ + ['0.012', '+0.01', '+0.01'], + ['0.123', '+0.12', '+0.12'], + ['1.234', '+1.23', '+1.23'], + ['12.34', '+12.3', '+12.3'], + ['123.4', '+123', '+123'], + ['123.41', '+123', '+123'], + ['1234.1', '+1.23K', '+1.23 thousand'], + ['12341', '+12.3K', '+12.3 thousand'], + ['123412', '+123K', '+123 thousand'], + ['1234123', '+1.23M', '+1.23 million'], + ['12341234', '+12.3M', '+12.3 million'], + ['123412341', '+123M', '+123 million'], + ['1234123412', '+1.23B', '+1.23 billion'], + ['-0.012', '-0.01', '-0.01'], + ['-0.123', '-0.12', '-0.12'], + ['-1.234', '-1.23', '-1.23'], + ['-12.34', '-12.3', '-12.3'], + ['-123.4', '-123', '-123'], + ['-123.41', '-123', '-123'], + ['-1234.1', '-1.23K', '-1.23 thousand'], + ['-12341', '-12.3K', '-12.3 thousand'], + ['-123412', '-123K', '-123 thousand'], + ['-1234123', '-1.23M', '-1.23 million'], + ['-12341234', '-12.3M', '-12.3 million'], + ['-123412341', '-123M', '-123 million'], + ['-1234123412', '-1.23B', '-1.23 billion'], +]; + void main() { - interestingCases.forEach(validate); - testdata33.compactNumberTestData.forEach(validate); - more_testdata.oldIntlCompactNumTests.forEach(validateFancy); + interestingCases.forEach(_validate); + testdata33.compactNumberTestData.forEach(_validate); + more_testdata.oldIntlCompactNumTests.forEach(_validateFancy); // Once code and data is updated to CLDR35: // testdata35.compactNumberTestData.forEach(validate); // more_testdata.cldr35CompactNumTests.forEach(validateFancy); + compactWithPatternCases.forEach(_validateWithPattern); test("Patterns are consistent across locales", () { patterns.compactNumberSymbols.forEach((locale, patterns) { @@ -139,7 +172,7 @@ // case. // TODO(alanknight): Fix the problems, or at least figure out precisely where // the differences are. -var problemLocalesShort = [ +var _skipLocalsShort = { 'am', // AM Suffixes differ, not sure why. 'ca', // For CA, CLDR rules are different. Jumps from 0000 to 00 prefix, so // 11 digits prints as 11900. @@ -167,7 +200,7 @@ 'tr', // TR Doesn't have a 0B format, goes directly to 00B, as a result 54321 // just prints as 54321 'ur', // UR Fails one with Expected: '15 ٹریلین' Actual: '150 کھرب' -]; +}; /// Locales that have problems in the long format. /// @@ -178,7 +211,7 @@ /// //TODO(alanknight): Narrow these down to particular numbers. Often it's just // 999999. -var problemLocalesLong = [ +var _skipLocalesLong = { 'ar', 'ar_DZ', 'ar_EG', 'be', 'bg', 'bs', 'ca', 'cs', 'da', 'de', 'de_AT', 'de_CH', 'el', 'es', 'es_419', 'es_ES', @@ -200,55 +233,53 @@ 'sk', 'sl', 'sr', 'sr_Latn', 'sv', 'te', 'tl', 'ur', 'uk', -]; +}; -void validate(String locale, List<List<String>> expected) { - validateShort(locale, expected); - validateLong(locale, expected); +void _validate(String locale, List<List<String>> expected) { + _validateShort(locale, expected); + _validateLong(locale, expected); } /// Check each bit of test data against the short compact format, both /// formatting and parsing. -void validateShort(String locale, List<List<String>> expected) { - if (problemLocalesShort.contains(locale)) { - print("Skipping problem locale '$locale' for SHORT compact number tests"); - return; - } +void _validateShort(String locale, List<List<String>> expected) { + var skip = _skipLocalsShort.contains(locale) + ? "Skipping problem locale '$locale' for SHORT compact number tests" + : false; var shortFormat = NumberFormat.compact(locale: locale); test('Validate $locale SHORT', () { for (var data in expected) { var number = num.parse(data.first); - validateNumber(number, shortFormat, data[1]); + _validateNumber(number, shortFormat, data[1]); var int64Number = Int64(number as int); - validateNumber(int64Number, shortFormat, data[1]); + _validateNumber(int64Number, shortFormat, data[1]); // TODO(alanknight): Make this work for MicroMoney } - }); + }, skip: skip); } -void validateLong(String locale, List<List<String>> expected) { - if (problemLocalesLong.contains(locale)) { - print("Skipping problem locale '$locale' for LONG compact number tests"); - return; - } +void _validateLong(String locale, List<List<String>> expected) { + var skip = _skipLocalesLong.contains(locale) + ? "Skipping problem locale '$locale' for LONG compact number tests" + : false; var longFormat = NumberFormat.compactLong(locale: locale); test('Validate $locale LONG', () { for (var data in expected) { var number = num.parse(data.first); - validateNumber(number, longFormat, data[2]); + _validateNumber(number, longFormat, data[2]); } - }); + }, skip: skip); } -void validateNumber(number, NumberFormat format, String expected) { +void _validateNumber(number, NumberFormat format, String expected) { var formatted = format.format(number); - var ok = closeEnough(formatted, expected); + var ok = _closeEnough(formatted, expected); if (!ok) { expect( '$formatted ${formatted.codeUnits}', '$expected ${expected.codeUnits}'); } var parsed = format.parse(formatted); - var rounded = roundForPrinting(number, format); + var rounded = _roundForPrinting(number, format); expect((parsed - rounded) / rounded < 0.001, isTrue); } @@ -256,7 +287,7 @@ /// number that will round to print differently depending on the number /// of significant digits, we need to check that as well, e.g. /// 999999 may print as 1M. -num roundForPrinting(number, NumberFormat format) { +num _roundForPrinting(number, NumberFormat format) { var originalLength = NumberFormat.numberOfIntegerDigits(number); var additionalDigits = originalLength - format.significantDigits!; if (additionalDigits > 0) { @@ -278,7 +309,7 @@ /// currently producing and the CLDR data. So if the strings differ only in the /// presence or absence of a period at the end or of a space between the number /// and the suffix, consider it close enough and return true. -bool closeEnough(String result, String reference) { +bool _closeEnough(String result, String reference) { var expected = reference.replaceAll(' ', _nbspString); if (result == expected) { return true; @@ -313,7 +344,7 @@ expectedDifference <= 1; } -void validateFancy(more_testdata.CompactRoundingTestCase t) { +void _validateFancy(more_testdata.CompactRoundingTestCase t) { var shortFormat = NumberFormat.compact(locale: 'en'); if (t.maximumIntegerDigits != null) { shortFormat.maximumIntegerDigits = t.maximumIntegerDigits!; @@ -343,3 +374,21 @@ expect(shortFormat.format(t.number), t.expected); }); } + +void _validateWithPattern(List<String> testData) { + final locale = 'en_US'; + final currentLocale = Intl.verifiedLocale(locale, NumberFormat.localeExists); + final symbols = numberFormatSymbols[currentLocale]; + final pattern = '${symbols.PLUS_SIGN}${symbols.DECIMAL_PATTERN};' + '${symbols.MINUS_SIGN}${symbols.DECIMAL_PATTERN}'; + final input = num.parse(testData[0]); + test('Validate compact with $locale and $pattern', () { + final numberFormat = NumberFormat.compact(locale: locale, pattern: pattern); + expect(testData[1], numberFormat.format(input)); + }); + test('Validate compactLong with $locale and $pattern', () { + final numberFormat = + NumberFormat.compactLong(locale: locale, pattern: pattern); + expect(testData[2], numberFormat.format(input)); + }); +}
diff --git a/test/number_format_compact_web_test.dart b/test/number_format_compact_web_test.dart index 8738a14..b211f56 100644 --- a/test/number_format_compact_web_test.dart +++ b/test/number_format_compact_web_test.dart
@@ -13,15 +13,15 @@ import 'more_compact_number_test_data.dart' as more_testdata; void main() { - testdata35.compactNumberTestData.forEach(validate); - more_testdata.cldr35CompactNumTests.forEach(validateMore); + testdata35.compactNumberTestData.forEach(_validate); + more_testdata.cldr35CompactNumTests.forEach(_validateMore); test('RTL currency formatting', () { var basic = intl.NumberFormat.currency(locale: 'he'); expect(basic.format(1234), '\u200F1,234.00 ILS'); basic = intl.NumberFormat.currency(locale: 'he', symbol: '₪'); expect(basic.format(1234), '\u200F1,234.00 ₪'); - expect(ecmaFormatNumber('he', 1234, style: 'currency', currency: 'ILS'), + expect(_ecmaFormatNumber('he', 1234, style: 'currency', currency: 'ILS'), '\u200F1,234.00 ₪'); var compact = intl.NumberFormat.compactCurrency(locale: 'he'); @@ -32,19 +32,19 @@ expect(compact.format(1234), '₪ \u200F1.23K'); // ECMAScript skips the RTL character for notation:'compact': expect( - ecmaFormatNumber('he', 1234, + _ecmaFormatNumber('he', 1234, style: 'currency', currency: 'ILS', notation: 'compact'), '₪ 1.2K'); // short/long compactDisplay doesn't change anything here: expect( - ecmaFormatNumber('he', 1234, + _ecmaFormatNumber('he', 1234, style: 'currency', currency: 'ILS', notation: 'compact', compactDisplay: 'short'), '₪ 1.2K'); expect( - ecmaFormatNumber('he', 1234, + _ecmaFormatNumber('he', 1234, style: 'currency', currency: 'ILS', notation: 'compact', @@ -56,7 +56,7 @@ }); } -String ecmaFormatNumber(String locale, num number, +String _ecmaFormatNumber(String locale, num number, {String? style, String? currency, String? notation, @@ -71,60 +71,59 @@ return js.callMethod(number, 'toLocaleString', [locale, options]); } -var ecmaProblemLocalesShort = [ +var _unsupportedChromeLocales = { // Not supported in Chrome: 'af', 'az', 'be', 'br', 'bs', 'eu', 'ga', 'gl', 'gsw', 'haw', 'hy', 'is', 'ka', 'kk', 'km', 'ky', 'ln', 'lo', 'mk', 'mn', 'mt', 'my', 'ne', 'no', - 'no-NO', 'or', 'pa', 'si', 'sq', 'ur', 'uz', 'ps', + 'no-NO', 'or', 'pa', 'si', 'sq', 'ur', 'uz', 'ps', 'chr', 'cy', 'tl', 'zu' +}; + +var _skipLocalesShort = [ + 'am', 'bn', 'fa', // Some results change in chrome 88 + ..._unsupportedChromeLocales ]; -var ecmaProblemLocalesLong = ecmaProblemLocalesShort + - [ - // Short happens to match 'en', but actually not in Chrome: - 'chr', 'cy', 'tl', 'zu' - ]; +var _skipLocalesLong = _unsupportedChromeLocales; -String fixLocale(String locale) { +String _fixLocale(String locale) { return locale.replaceAll('_', '-'); } -void validate(String locale, List<List<String>> expected) { - validateShort(fixLocale(locale), expected); - validateLong(fixLocale(locale), expected); +void _validate(String locale, List<List<String>> expected) { + _validateShort(_fixLocale(locale), expected); + _validateLong(_fixLocale(locale), expected); } -void validateShort(String locale, List<List<String>> expected) { - if (ecmaProblemLocalesShort.contains(locale)) { - print("Skipping problem locale '$locale' for SHORT compact number tests"); - return; - } +void _validateShort(String locale, List<List<String>> expected) { + var skip = _skipLocalesShort.contains(locale) + ? "Skipping problem locale '$locale' for SHORT compact number tests" + : false; test('Validate $locale SHORT', () { for (var data in expected) { var number = num.parse(data.first); - expect(ecmaFormatNumber(locale, number, notation: 'compact'), data[1]); + expect(_ecmaFormatNumber(locale, number, notation: 'compact'), data[1]); } - }); + }, skip: skip); } -void validateLong(String locale, List<List<String>> expected) { - if (ecmaProblemLocalesLong.contains(locale)) { - print("Skipping problem locale '$locale' for LONG compact number tests"); - return; - } +void _validateLong(String locale, List<List<String>> expected) { + var skip = _skipLocalesLong.contains(locale) + ? "Skipping problem locale '$locale' for LONG compact number tests" + : false; test('Validate $locale LONG', () { for (var data in expected) { var number = num.parse(data.first); expect( - ecmaFormatNumber(locale, number, + _ecmaFormatNumber(locale, number, notation: 'compact', compactDisplay: 'long'), data[2]); } - }); + }, skip: skip); } -void validateMore(more_testdata.CompactRoundingTestCase t) { +void _validateMore(more_testdata.CompactRoundingTestCase t) { var options = js.newObject(); js.setProperty(options, 'notation', 'compact'); if (t.maximumIntegerDigits != null) {
diff --git a/test/number_format_test_core.dart b/test/number_format_test_core.dart index 2c74137..ea79d03 100644 --- a/test/number_format_test_core.dart +++ b/test/number_format_test_core.dart
@@ -4,9 +4,10 @@ library number_format_test; -import 'package:test/test.dart'; -import 'package:intl/number_symbols_data.dart'; import 'package:intl/intl.dart'; +import 'package:intl/number_symbols_data.dart'; +import 'package:test/test.dart'; + import 'number_test_data.dart'; /// Tests the Numeric formatting library in dart.