/* * Copyright (c) 2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ecmascript/intl/locale_helper.h" #include "ecmascript/js_number_format.h" #include "ecmascript/napi/jsnapi_helper.h" #include "ecmascript/tests/test_helper.h" using namespace panda::ecmascript; namespace panda::test { class JSNumberFormatTest : public BaseTestWithScope { }; /** * @tc.name: GetIcuCallTarget * @tc.desc: Call "NewJSIntlIcuData" function Set IcuCallTarget,check whether the IcuCallTarget through * "GetIcuCallTarget" function is within expectations then call "formatInt" function format * Int type data and check the returned value is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(JSNumberFormatTest, GetIcuCallTarget) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle ctor = env->GetNumberFormatFunction(); JSHandle numberFormat = JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(ctor), ctor)); icu::Locale icuLocale("en", "US"); icu::number::LocalizedNumberFormatter icuNumberFormatter = icu::number::NumberFormatter::withLocale(icuLocale).roundingMode(UNUM_ROUND_HALFUP); // Set IcuCallTarget factory->NewJSIntlIcuData(numberFormat, icuNumberFormatter, JSNumberFormat::FreeIcuNumberformat); icu::number::LocalizedNumberFormatter *resultIcuNumberFormatter = numberFormat->GetIcuCallTarget(thread); EXPECT_TRUE(resultIcuNumberFormatter != nullptr); // Use IcuCallTarget format Int int64_t value = -123456; UErrorCode status = U_ZERO_ERROR; icu::number::FormattedNumber formattedNumber = resultIcuNumberFormatter->formatInt(value, status); icu::UnicodeString result = formattedNumber.toString(status); JSHandle stringValue = intl::LocaleHelper::UStringToString(thread, result); EXPECT_STREQ("-123,456", EcmaStringAccessor(stringValue).ToCString(thread).c_str()); } /** * @tc.name: InitializeNumberFormat * @tc.desc: Call "InitializeNumberFormat" function Initialize NumberFormat,and check whether the properties of * the object is within expectations. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(JSNumberFormatTest, InitializeNumberFormat) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); JSHandle ctor = env->GetNumberFormatFunction(); JSHandle numberFormat = JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(ctor), ctor)); EXPECT_TRUE(*numberFormat != nullptr); JSHandle locales(factory->NewFromASCII("zh-Hans-CN")); JSHandle undefinedOptions(thread, JSTaggedValue::Undefined()); JSNumberFormat::InitializeNumberFormat(thread, numberFormat, locales, undefinedOptions); // Initialize attribute comparison EXPECT_TRUE(numberFormat->GetNumberingSystem(thread).IsUndefined()); JSHandle localeStr(thread, numberFormat->GetLocale(thread).GetTaggedObject()); EXPECT_STREQ("zh-Hans-CN", EcmaStringAccessor(localeStr).ToCString(thread).c_str()); EXPECT_EQ(NotationOption::STANDARD, numberFormat->GetNotation()); EXPECT_EQ(CompactDisplayOption::SHORT, numberFormat->GetCompactDisplay()); EXPECT_EQ(SignDisplayOption::AUTO, numberFormat->GetSignDisplay()); EXPECT_EQ(CurrencyDisplayOption::SYMBOL, numberFormat->GetCurrencyDisplay()); EXPECT_EQ(CurrencySignOption::STANDARD, numberFormat->GetCurrencySign()); EXPECT_EQ(UnitDisplayOption::SHORT, numberFormat->GetUnitDisplay()); EXPECT_EQ(numberFormat->GetMinimumIntegerDigits(thread).GetInt(), 1); // 1 : 1 default minimum integer EXPECT_EQ(numberFormat->GetMinimumFractionDigits(thread).GetInt(), 0); // 0 : 0 default minimum fraction EXPECT_EQ(numberFormat->GetMaximumFractionDigits(thread).GetInt(), 3); // 1 : 1 default maximum fraction EXPECT_EQ(numberFormat->GetMinimumSignificantDigits(thread).GetInt(), 0); // 0 : 0 default minimum sigfraction EXPECT_EQ(numberFormat->GetMaximumSignificantDigits(thread).GetInt(), 0); // 0 : 0 default maximum sigfraction EXPECT_TRUE(numberFormat->GetUseGrouping(thread).IsTrue()); EXPECT_TRUE(numberFormat->GetBoundFormat(thread).IsUndefined()); EXPECT_TRUE(numberFormat->GetUnit(thread).IsUndefined()); EXPECT_TRUE(numberFormat->GetCurrency(thread).IsUndefined()); } /** * @tc.name: CurrencyDigits * @tc.desc: If the ISO 4217 currency contains currency as an alphabetic code, return the minor unit value * corresponding to the currency from the list * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(JSNumberFormatTest, CurrencyDigits) { // Alphabetic code:USD icu::UnicodeString usdCurrency("USD"); // 2 : 2 fraction digits EXPECT_EQ(JSNumberFormat::CurrencyDigits(usdCurrency), 2); // Alphabetic code:EUR icu::UnicodeString eurCurrency("EUR"); // 2 : 2 fraction digits EXPECT_EQ(JSNumberFormat::CurrencyDigits(eurCurrency), 2); // Alphabetic code:CHF icu::UnicodeString numberCurrency("CHF"); // 2 : 2 fraction digits EXPECT_EQ(JSNumberFormat::CurrencyDigits(numberCurrency), 2); } /** * @tc.name: FormatNumeric * @tc.desc: Call "InitializeNumberFormat" function Initialize NumberFormat,Set the sytle attribute of the object to * decimal,construct a bigint type data,and the object calls the FormatNumeric method to interpret the bigint * type data into the corresponding decimal, and check whether the decimal meets the expectation. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(JSNumberFormatTest, FormatNumeric) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); auto globalConst = thread->GlobalConstants(); JSHandle objFun = env->GetObjectFunction(); JSHandle ctor = env->GetNumberFormatFunction(); JSHandle numberFormat = JSHandle::Cast(factory->NewJSObjectByConstructor(JSHandle(ctor), ctor)); JSHandle styleKey = globalConst->GetHandledStyleString(); JSHandle styleValue(factory->NewFromASCII("decimal")); JSHandle localeString(factory->NewFromASCII("en-US")); JSHandle optionsObj = factory->NewJSObjectByConstructor(JSHandle(objFun), objFun); JSObject::SetProperty(thread, optionsObj, styleKey, styleValue); JSNumberFormat::InitializeNumberFormat(thread, numberFormat, localeString, JSHandle(optionsObj)); // format BigInt JSHandle number(thread, JSTaggedValue(123456789)); JSHandle jsBigInt(thread, BigInt::NumberToBigInt(thread, number)); JSHandle formatResult = JSNumberFormat::FormatNumeric(thread, numberFormat, jsBigInt.GetTaggedValue()); JSHandle resultEcmaStr(thread, formatResult.GetTaggedValue()); EXPECT_STREQ("123,456,789", EcmaStringAccessor(resultEcmaStr).ToCString(thread).c_str()); } /** * @tc.name: UnwrapNumberFormat * @tc.desc: Construct an object,If it is a numberformat object,it will be returned.If it is an object of other types * and inherits the numberformat object, it will get value from the fallbacksymbol key and return. * @tc.type: FUNC * @tc.require: */ HWTEST_F_L0(JSNumberFormatTest, UnwrapNumberFormat) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); EcmaVM *vm = thread->GetEcmaVM(); JSHandle numberFormatFunc = env->GetNumberFormatFunction(); JSHandle numberFormat( factory->NewJSObjectByConstructor(JSHandle(numberFormatFunc), numberFormatFunc)); Local numberFormatLocal = JSNApiHelper::ToLocal(numberFormatFunc); JSHandle disPlayNamesFunc = env->GetDisplayNamesFunction(); Local disPlayNamesLocal = JSNApiHelper::ToLocal(disPlayNamesFunc); // displaynames Inherit numberformat disPlayNamesLocal->Inherit(vm, numberFormatLocal); JSHandle disPlayNamesHandle = JSNApiHelper::ToJSHandle(disPlayNamesLocal); JSHandle disPlayNamesObj( factory->NewJSObjectByConstructor(JSHandle::Cast(disPlayNamesHandle), disPlayNamesHandle)); // object has no Instance JSHandle unwrapNumberFormat1 = JSNumberFormat::UnwrapNumberFormat(thread, numberFormat); EXPECT_TRUE(JSTaggedValue::SameValue(thread, numberFormat, unwrapNumberFormat1)); // object has Instance JSHandle unwrapNumberFormat2 = JSNumberFormat::UnwrapNumberFormat(thread, disPlayNamesObj); EXPECT_TRUE(unwrapNumberFormat2->IsUndefined()); } } // namespace panda::test