blob: ec1ca2275d1a51c710cf04c07e045d81cf2486e6 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// Tests for the MessageFormat class.
///
/// Currently, these tests are the ones directly ported from Closure.
import 'package:intl/message_format.dart';
import 'package:test/test.dart';
void main() {
test('testEmptyPattern', () {
var fmt = MessageFormat('');
expect(fmt.format({}), '');
});
test('testMissingLeftCurlyBrace', () {
expect(() {
var fmt = MessageFormat('\'\'{}}');
fmt.format({});
}, throwsA(predicate((e) {
return e is AssertionError && e.message == 'No matching { for }.';
})));
});
test('testTooManyLeftCurlyBraces', () {
expect(() {
var fmt = MessageFormat('{} {');
fmt.format({});
}, throwsA(predicate((e) {
return e is AssertionError &&
e.message == 'There are mismatched { or } in the pattern.';
})));
});
test('testSimpleReplacement', () {
var fmt = MessageFormat('New York in {SEASON} is nice.');
expect(fmt.format({'SEASON': 'the Summer'}),
'New York in the Summer is nice.');
});
test('testSimpleSelect', () {
var fmt = MessageFormat('{GENDER, select,'
'male {His}'
'female {Her}'
'other {Its}}'
' bicycle is {GENDER, select, male {blue} female {red} other {green}}.');
expect(fmt.format({'GENDER': 'male'}), 'His bicycle is blue.');
expect(fmt.format({'GENDER': 'female'}), 'Her bicycle is red.');
expect(fmt.format({'GENDER': 'other'}), 'Its bicycle is green.');
expect(fmt.format({'GENDER': 'whatever'}), 'Its bicycle is green.');
});
test('testSimplePlural', () {
var fmt = MessageFormat('I see {NUM_PEOPLE, plural, offset:1 '
'=0 {no one at all in {PLACE}.} '
'=1 {{PERSON} in {PLACE}.} '
'one {{PERSON} and one other person in {PLACE}.} '
'other {{PERSON} and # other people in {PLACE}.}}');
expect(fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Belgrade'}),
'I see no one at all in Belgrade.');
expect(fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markus', 'PLACE': 'Berlin'}),
'I see Markus in Berlin.');
expect(fmt.format({'NUM_PEOPLE': 2, 'PERSON': 'Mark', 'PLACE': 'Athens'}),
'I see Mark and one other person in Athens.');
expect(
fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibu', 'PLACE': 'the cubes'}),
'I see Cibu and 99 other people in the cubes.');
});
test('testSimplePluralNoOffset', () {
var fmt = MessageFormat('I see {NUM_PEOPLE, plural, '
'=0 {no one at all} '
'=1 {{PERSON}} '
'one {{PERSON} and one other person} '
'other {{PERSON} and # other people}} in {PLACE}.');
expect(fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Belgrade'}),
'I see no one at all in Belgrade.');
expect(fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markus', 'PLACE': 'Berlin'}),
'I see Markus in Berlin.');
expect(fmt.format({'NUM_PEOPLE': 2, 'PERSON': 'Mark', 'PLACE': 'Athens'}),
'I see Mark and 2 other people in Athens.');
expect(
fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibu', 'PLACE': 'the cubes'}),
'I see Cibu and 100 other people in the cubes.');
});
test('testSelectNestedInPlural', () {
var fmt = MessageFormat('{CIRCLES, plural, '
'one {{GENDER, select, '
' female {{WHO} added you to her circle} '
' other {{WHO} added you to his circle}}} '
'other {{GENDER, select, '
' female {{WHO} added you to her # circles} '
' other {{WHO} added you to his # circles}}}}');
expect(fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 1}),
'Jelena added you to her circle');
expect(fmt.format({'GENDER': 'male', 'WHO': 'Milan', 'CIRCLES': 1234}),
'Milan added you to his 1,234 circles');
});
test('testPluralNestedInSelect', () {
// Added offset just for testing purposes. It doesn't make sense
// to have it otherwise.
var fmt = MessageFormat('{GENDER, select, '
'female {{NUM_GROUPS, plural, '
' one {{WHO} added you to her group} '
' other {{WHO} added you to her # groups}}} '
'other {{NUM_GROUPS, plural, offset:1'
' one {{WHO} added you to his group} '
' other {{WHO} added you to his # groups}}}}');
expect(fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'NUM_GROUPS': 1}),
'Jelena added you to her group');
expect(fmt.format({'GENDER': 'male', 'WHO': 'Milan', 'NUM_GROUPS': 1234}),
'Milan added you to his 1,233 groups');
});
test('testLiteralOpenCurlyBrace', () {
var fmt = MessageFormat(
"Anna's house has '{0} and # in the roof' and {NUM_COWS} cows.");
expect(fmt.format({'NUM_COWS': '5'}),
"Anna's house has {0} and # in the roof and 5 cows.");
});
test('testLiteralClosedCurlyBrace', () {
var fmt = MessageFormat(
'Anna\'s house has \'{\'0\'} and # in the roof\' and {NUM_COWS} cows.');
expect(fmt.format({'NUM_COWS': '5'}),
'Anna\'s house has {0} and # in the roof and 5 cows.');
// Regression for Closure implementation bug: b/34764827
expect(fmt.format({'NUM_COWS': '8'}),
'Anna\'s house has {0} and # in the roof and 8 cows.');
});
test('testLiteralPoundSign', () {
var fmt = MessageFormat(
"Anna's house has '{0}' and '# in the roof' and {NUM_COWS} cows.");
expect(fmt.format({'NUM_COWS': '5'}),
"Anna's house has {0} and # in the roof and 5 cows.");
// Regression for: b/34764827
expect(fmt.format({'NUM_COWS': '10'}),
'Anna\'s house has {0} and # in the roof and 10 cows.');
});
test('testNoLiteralsForSingleQuotes', () {
var fmt = MessageFormat("Anna's house 'has {NUM_COWS} cows'.");
expect(fmt.format({'NUM_COWS': '5'}), "Anna's house 'has 5 cows'.");
});
test('testConsecutiveSingleQuotesAreReplacedWithOneSingleQuote', () {
var fmt = MessageFormat("Anna''s house a'{''''b'");
expect(fmt.format({}), "Anna's house a{''b");
});
test('testConsecutiveSingleQuotesBeforeSpecialCharDontCreateLiteral', () {
var fmt = MessageFormat("a''{NUM_COWS}'b");
expect(fmt.format({'NUM_COWS': '5'}), "a'5'b");
});
test('testSerbianSimpleSelect', () {
var fmt = MessageFormat(
'{GENDER, select, female {Njen} other {Njegov}} bicikl je '
'{GENDER, select, female {crven} other {plav}}.',
locale: 'sr');
expect(fmt.format({'GENDER': 'male'}), 'Njegov bicikl je plav.');
expect(fmt.format({'GENDER': 'female'}), 'Njen bicikl je crven.');
});
test('testSerbianSimplePlural', () {
var fmt = MessageFormat(
'Ja {NUM_PEOPLE, plural, offset:1 '
' =0 {ne vidim nikoga} '
' =1 {vidim {PERSON}} '
' one {vidim {PERSON} i jos # osobu} '
' few {vidim {PERSON} i jos # osobe} '
' many {vidim {PERSON} i jos # osoba} '
' other {vidim {PERSON} i jos # osoba}} '
'u {PLACE}.',
locale: 'sr');
expect(fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Beogradu'}),
'Ja ne vidim nikoga u Beogradu.');
expect(
fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markusa', 'PLACE': 'Berlinu'}),
'Ja vidim Markusa u Berlinu.');
expect(fmt.format({'NUM_PEOPLE': 2, 'PERSON': 'Marka', 'PLACE': 'Atini'}),
'Ja vidim Marka i jos 1 osobu u Atini.');
expect(fmt.format({'NUM_PEOPLE': 4, 'PERSON': 'Petra', 'PLACE': 'muzeju'}),
'Ja vidim Petra i jos 3 osobe u muzeju.');
expect(
fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibua', 'PLACE': 'bazenu'}),
'Ja vidim Cibua i jos 99 osoba u bazenu.');
});
test('testSerbianSimplePluralNoOffset', () {
var fmt = MessageFormat(
'Ja {NUM_PEOPLE, plural, '
' =0 {ne vidim nikoga} '
' =1 {vidim {PERSON}} '
' one {vidim {PERSON} i jos # osobu} '
' few {vidim {PERSON} i jos # osobe} '
' many {vidim {PERSON} i jos # osoba} '
' other {vidim {PERSON} i jos # osoba}} '
'u {PLACE}.',
locale: 'sr');
expect(fmt.format({'NUM_PEOPLE': 0, 'PLACE': 'Beogradu'}),
'Ja ne vidim nikoga u Beogradu.');
expect(
fmt.format({'NUM_PEOPLE': 1, 'PERSON': 'Markusa', 'PLACE': 'Berlinu'}),
'Ja vidim Markusa u Berlinu.');
expect(fmt.format({'NUM_PEOPLE': 21, 'PERSON': 'Marka', 'PLACE': 'Atini'}),
'Ja vidim Marka i jos 21 osobu u Atini.');
expect(fmt.format({'NUM_PEOPLE': 3, 'PERSON': 'Petra', 'PLACE': 'muzeju'}),
'Ja vidim Petra i jos 3 osobe u muzeju.');
expect(
fmt.format({'NUM_PEOPLE': 100, 'PERSON': 'Cibua', 'PLACE': 'bazenu'}),
'Ja vidim Cibua i jos 100 osoba u bazenu.');
});
test('testSerbianSelectNestedInPlural', () {
var fmt = MessageFormat(
'{CIRCLES, plural, '
' one {{GENDER, select, '
' female {{WHO} vas je dodala u njen # kruzok} '
' other {{WHO} vas je dodao u njegov # kruzok}}} '
' few {{GENDER, select, '
' female {{WHO} vas je dodala u njena # kruzoka} '
' other {{WHO} vas je dodao u njegova # kruzoka}}} '
' many {{GENDER, select, '
' female {{WHO} vas je dodala u njenih # kruzoka} '
' other {{WHO} vas je dodao u njegovih # kruzoka}}} '
' other {{GENDER, select, '
' female {{WHO} vas je dodala u njenih # kruzoka} '
' other {{WHO} vas je dodao u njegovih # kruzoka}}}}',
locale: 'hr');
expect(fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 21}),
'Jelena vas je dodala u njen 21 kruzok');
expect(fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 3}),
'Jelena vas je dodala u njena 3 kruzoka');
expect(fmt.format({'GENDER': 'female', 'WHO': 'Jelena', 'CIRCLES': 5}),
'Jelena vas je dodala u njenih 5 kruzoka');
expect(fmt.format({'GENDER': 'male', 'WHO': 'Milan', 'CIRCLES': 1235}),
'Milan vas je dodao u njegovih 1.235 kruzoka');
});
test('testFallbackToOtherOptionInPlurals', () {
// Use Arabic plural rules since they have all six cases.
// Only locale and numbers matter, the actual language of the message
// does not.
var fmt =
MessageFormat('{NUM_MINUTES, plural, other {# minutes}}', locale: 'ar');
// These numbers exercise all cases for the arabic plural rules.
expect(fmt.format({'NUM_MINUTES': 0}), '0 minutes');
expect(fmt.format({'NUM_MINUTES': 1}), '1 minutes');
expect(fmt.format({'NUM_MINUTES': 2}), '2 minutes');
expect(fmt.format({'NUM_MINUTES': 3}), '3 minutes');
expect(fmt.format({'NUM_MINUTES': 11}), '11 minutes');
expect(fmt.format({'NUM_MINUTES': 1.5}), '1.5 minutes');
});
test('testPoundShowsNumberMinusOffsetInAllCases', () {
var fmt = MessageFormat(
'{SOME_NUM, plural, offset:1 =0 {#} =1 {#} =2 {#} one {#} other {#}}');
expect(fmt.format({'SOME_NUM': '0'}), '-1');
expect(fmt.format({'SOME_NUM': '1'}), '0');
expect(fmt.format({'SOME_NUM': '2'}), '1');
expect(fmt.format({'SOME_NUM': '21'}), '20');
});
test('testSpecialCharactersInParamaterDontChangeFormat', () {
var fmt = MessageFormat('{SOME_NUM, plural, other {# {GROUP}}}');
// Test pound sign.
expect(fmt.format({'SOME_NUM': '10', 'GROUP': 'group#1'}), '10 group#1');
// Test other special characters in parameters, like { and }.
expect(fmt.format({'SOME_NUM': '10', 'GROUP': '} {'}), '10 } {');
});
test('testMissingOrInvalidPluralParameter', () {
var fmt = MessageFormat('{SOME_NUM, plural, other {result}}');
// Key name doesn't match A != SOME_NUM.
expect(fmt.format({'A': '10'}), 'Undefined parameter - SOME_NUM');
// Value is not a number.
expect(fmt.format({'SOME_NUM': 'Value'}), 'Invalid parameter - SOME_NUM');
});
test('testMissingSelectParameter', () {
var fmt = MessageFormat('{GENDER, select, other {result}}');
// Key name doesn't match A != GENDER.
expect(fmt.format({'A': 'female'}), 'Undefined parameter - GENDER');
});
test('testMissingSimplePlaceholder', () {
var fmt = MessageFormat('{result}');
// Key name doesn't match A != result.
expect(fmt.format({'A': 'none'}), 'Undefined parameter - result');
});
test('testPlural', () {
var fmt = MessageFormat(
'{SOME_NUM, plural,'
' =0 {none}'
' =1 {exactly one}'
' one {# one}'
' few {# few}'
' many {# many}'
' other {# other}'
'}',
locale: 'ru');
expect(fmt.format({'SOME_NUM': 0}), 'none');
expect(fmt.format({'SOME_NUM': 1}), 'exactly one');
expect(fmt.format({'SOME_NUM': 21}), '21 one');
expect(fmt.format({'SOME_NUM': 23}), '23 few');
expect(fmt.format({'SOME_NUM': 17}), '17 many');
expect(fmt.format({'SOME_NUM': 100}), '100 many');
expect(fmt.format({'SOME_NUM': 1.4}), '1,4 other');
expect(fmt.format({'SOME_NUM': '10.0'}), '10 other');
expect(fmt.format({'SOME_NUM': '100.00'}), '100 other');
});
test('testPluralWithIgnorePound', () {
var fmt = MessageFormat('{SOME_NUM, plural, other {# {GROUP}}}');
// Test pound sign.
expect(fmt.formatIgnoringPound({'SOME_NUM': '10', 'GROUP': 'group#1'}),
'# group#1');
// Test other special characters in parameters, like { and }.
expect(
fmt.formatIgnoringPound({'SOME_NUM': '10', 'GROUP': '} {'}), '# } {');
});
test('testSimplePluralWithIgnorePound', () {
var fmt = MessageFormat('I see {NUM_PEOPLE, plural, offset:1 '
'=0 {no one at all in {PLACE}.} '
'=1 {{PERSON} in {PLACE}.} '
'one {{PERSON} and one other person in {PLACE}.} '
'other {{PERSON} and # other people in {PLACE}.}}');
expect(
fmt.formatIgnoringPound(
{'NUM_PEOPLE': 100, 'PERSON': 'Cibu', 'PLACE': 'the cubes'}),
'I see Cibu and # other people in the cubes.');
});
test('testRomanianOffsetWithNegativeValue', () {
var fmt = MessageFormat(
'{NUM_FLOOR, plural, offset:2 '
'one {One #}'
'few {Few #}'
'other {Other #}}',
locale: 'ro');
// Checking that the decision is done after the offset is substracted
expect(fmt.format({'NUM_FLOOR': -1}), 'Few -3');
expect(fmt.format({'NUM_FLOOR': 1}), 'One -1');
expect(fmt.format({'NUM_FLOOR': -3}), 'Few -5');
expect(fmt.format({'NUM_FLOOR': 3}), 'One 1');
expect(fmt.format({'NUM_FLOOR': -25}), 'Other -27');
expect(fmt.format({'NUM_FLOOR': 25}), 'Other 23');
});
ignoreTest('testSimpleOrdinal', () {
// TOFIX. Ordinal not supported in Dart
var fmt = MessageFormat('{NUM_FLOOR, selectordinal, '
'one {Take the elevator to the #st floor.}'
'two {Take the elevator to the #nd floor.}'
'few {Take the elevator to the #rd floor.}'
'other {Take the elevator to the #th floor.}}');
expect(fmt.format({'NUM_FLOOR': 1}), 'Take the elevator to the 1st floor.');
expect(fmt.format({'NUM_FLOOR': 2}), 'Take the elevator to the 2nd floor.');
expect(fmt.format({'NUM_FLOOR': 3}), 'Take the elevator to the 3rd floor.');
expect(fmt.format({'NUM_FLOOR': 4}), 'Take the elevator to the 4th floor.');
expect(
fmt.format({'NUM_FLOOR': 23}), 'Take the elevator to the 23rd floor.');
// Esoteric example.
expect(fmt.format({'NUM_FLOOR': 0}), 'Take the elevator to the 0th floor.');
});
ignoreTest('testOrdinalWithNegativeValue', () {
// TOFIX. Ordinal not supported in Dart
var fmt = MessageFormat('{NUM_FLOOR, selectordinal, '
'one {Take the elevator to the #st floor.}'
'two {Take the elevator to the #nd floor.}'
'few {Take the elevator to the #rd floor.}'
'other {Take the elevator to the #th floor.}}');
expect(
fmt.format({'NUM_FLOOR': -1}), 'Take the elevator to the -1st floor.');
expect(
fmt.format({'NUM_FLOOR': -2}), 'Take the elevator to the -2nd floor.');
expect(
fmt.format({'NUM_FLOOR': -3}), 'Take the elevator to the -3rd floor.');
expect(
fmt.format({'NUM_FLOOR': -4}), 'Take the elevator to the -4th floor.');
});
ignoreTest('testSimpleOrdinalWithIgnorePound', () {
// TOFIX. Ordinal not supported in Dart
var fmt = MessageFormat('{NUM_FLOOR, selectordinal, '
'one {Take the elevator to the #st floor.}'
'two {Take the elevator to the #nd floor.}'
'few {Take the elevator to the #rd floor.}'
'other {Take the elevator to the #th floor.}}');
expect(fmt.formatIgnoringPound({'NUM_FLOOR': 100}),
'Take the elevator to the #th floor.');
});
ignoreTest('testMissingOrInvalidOrdinalParameter', () {
// TOFIX. Ordinal not supported in Dart
var fmt = MessageFormat('{SOME_NUM, selectordinal, other {result}}');
// Key name doesn't match A != SOME_NUM.
expect(
fmt.format({'A': '10'}), 'Undefined or invalid parameter - SOME_NUM');
// Value is not a number.
expect(fmt.format({'SOME_NUM': 'Value'}),
'Undefined or invalid parameter - SOME_NUM');
});
} // end of main
// Disabling unit tests without having to comment the whole body.
// Similar to @Ignore in JUnit
void ignoreTest(description, body) {
print('\u001b[93mTest ignored: $description\u001b[m');
}