diff --git a/build/pipelines/templates/run-ui-tests.yaml b/build/pipelines/templates/run-ui-tests.yaml index 41d441ad..070293db 100644 --- a/build/pipelines/templates/run-ui-tests.yaml +++ b/build/pipelines/templates/run-ui-tests.yaml @@ -15,10 +15,6 @@ jobs: steps: - checkout: none - - powershell: Set-DisplayResolution -Width 1920 -Height 1080 -Force - displayName: Set resolution to 1920x1080 - continueOnError: true - - task: DownloadBuildArtifacts@0 displayName: Download AppxBundle and CalculatorUITests inputs: @@ -39,8 +35,10 @@ jobs: filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1 arguments: -Force - - powershell: Start-Process -FilePath "C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe" -Verb RunAs - displayName: Start WinAppDriver + - task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0 + displayName: 'WinAppDriver - Start' + inputs: + AgentResolution: 1080p - task: VSTest@2 displayName: Run CalculatorUITests @@ -49,4 +47,9 @@ jobs: vsTestVersion: 16.0 runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.runsettings platform: ${{ parameters.platform }} - configuration: Release \ No newline at end of file + configuration: Release + + - task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0 + displayName: 'WinAppDriver - Stop' + inputs: + OperationType: Stop \ No newline at end of file diff --git a/internal/Calculator.TestPackage/Calculator.TestPackage.csproj b/internal/Calculator.TestPackage/Calculator.TestPackage.csproj index 2a3a29d2..85791283 100644 --- a/internal/Calculator.TestPackage/Calculator.TestPackage.csproj +++ b/internal/Calculator.TestPackage/Calculator.TestPackage.csproj @@ -123,7 +123,7 @@ @(AppxBundleOutput->'%(RootDir)%(Directory)') $(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).Debug.14.00.appx; $(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).14.00.appx; - $(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.0.appx; + $(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.1.appx; $(UniversalTestCustomMacros)AppxPackagePublicKeyFile=@(AppxPackagePublicKeyFile->'%(FullPath)');AppxBundleOutput=@(AppxBundleOutput->'%(FullPath)'); diff --git a/src/CalcViewModel/Common/DateCalculator.cpp b/src/CalcViewModel/Common/DateCalculator.cpp index 9c5d5e0a..8d5bedb5 100644 --- a/src/CalcViewModel/Common/DateCalculator.cpp +++ b/src/CalcViewModel/Common/DateCalculator.cpp @@ -26,22 +26,20 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date { m_calendar->SetDateTime(startDate); + // The Japanese Era system can have multiple year partitions within the same year. + // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. + // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results + // in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date + // math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and + // durations as the Gregorian system and is only different in display value. + if (currentCalendarSystem == CalendarIdentifiers::Japanese) + { + m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); + } + if (duration.year != 0) { - // The Japanese Era system can have multiple year partitions within the same year. - // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. - // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 - // results in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian - // system, do date math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month - // boundaries and durations as the Gregorian system and is only different in display value. - if (currentCalendarSystem == CalendarIdentifiers::Japanese) - { - m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); - } - m_calendar->AddYears(duration.year); - - m_calendar->ChangeCalendarSystem(currentCalendarSystem); } if (duration.month != 0) { @@ -63,6 +61,8 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date return false; } + m_calendar->ChangeCalendarSystem(currentCalendarSystem); + return true; } @@ -78,6 +78,17 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const { m_calendar->SetDateTime(startDate); + // The Japanese Era system can have multiple year partitions within the same year. + // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. + // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results + // in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date + // math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and + // durations as the Gregorian system and is only different in display value. + if (currentCalendarSystem == CalendarIdentifiers::Japanese) + { + m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); + } + if (duration.day != 0) { m_calendar->AddDays(-duration.day); @@ -88,22 +99,8 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const } if (duration.year != 0) { - // The Japanese Era system can have multiple year partitions within the same year. - // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. - // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 - // results in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian - // system, do date math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month - // boundaries and durations as the Gregorian system and is only different in display value. - if (currentCalendarSystem == CalendarIdentifiers::Japanese) - { - m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); - } - m_calendar->AddYears(-duration.year); - - m_calendar->ChangeCalendarSystem(currentCalendarSystem); } - *endDate = m_calendar->GetDateTime(); } catch (Platform::InvalidArgumentException ^ ex) @@ -115,6 +112,8 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const return false; } + m_calendar->ChangeCalendarSystem(currentCalendarSystem); + // Check that the UniversalTime value is not negative return (endDate->UniversalTime >= 0); } @@ -310,24 +309,23 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime { m_calendar->SetDateTime(date); + // The Japanese Era system can have multiple year partitions within the same year. + // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. + // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in + // a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, + // and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and durations as + // the Gregorian system and is only different in display value. + auto currentCalendarSystem = m_calendar->GetCalendarSystem(); + if (currentCalendarSystem == CalendarIdentifiers::Japanese) + { + m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); + } + switch (dateUnit) { case DateUnit::Year: - { - // In the Japanese calendar, transition years have 2 partial years. - // It is not guaranteed that adding 1 year will always add 365 days in the Japanese Calendar. - // To work around this quirk, we will change the calendar system to Gregorian before adding 1 year in the Japanese Calendar case only. - // We will then return the calendar system back to the Japanese Calendar. - auto currentCalendarSystem = m_calendar->GetCalendarSystem(); - if (currentCalendarSystem == CalendarIdentifiers::Japanese) - { - m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); - } - m_calendar->AddYears(difference); - m_calendar->ChangeCalendarSystem(currentCalendarSystem); break; - } case DateUnit::Month: m_calendar->AddMonths(difference); break; @@ -336,5 +334,7 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime break; } + m_calendar->ChangeCalendarSystem(currentCalendarSystem); + return m_calendar->GetDateTime(); } diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj index 9a3bbeb3..208344c8 100644 --- a/src/Calculator/Calculator.vcxproj +++ b/src/Calculator/Calculator.vcxproj @@ -839,7 +839,7 @@ - + @@ -847,6 +847,6 @@ - + \ No newline at end of file diff --git a/src/Calculator/packages.config b/src/Calculator/packages.config index 3716522e..d41e98b7 100644 --- a/src/Calculator/packages.config +++ b/src/Calculator/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp b/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp index 28ff47e5..7603a3dc 100644 --- a/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp +++ b/src/CalculatorUnitTests/DateCalculatorUnitTests.cpp @@ -958,7 +958,7 @@ TEST_METHOD(JaEraTransitionAddition) auto viewModel = make_unique(CalendarIdentifiers::Japanese); auto cal = ref new Calendar(); - // Showa period ended in Jan 1989. + // The Showa period ended in Jan 1989. cal->Year = 1989; cal->Month = 1; cal->Day = 1; @@ -969,14 +969,28 @@ TEST_METHOD(JaEraTransitionAddition) cal->Day = 1; // Expect that adding a year across boundaries adds the equivalent in the Gregorian calendar. - auto expectedResult = cal->GetDateTime(); - DateDifference duration; - duration.year = 1; + auto expectedYearResult = cal->GetDateTime(); + DateDifference yearDuration; + yearDuration.year = 1; - DateTime actualResult; - viewModel->AddDuration(startTime, duration, &actualResult); + DateTime actualYearResult; + viewModel->AddDuration(startTime, yearDuration, &actualYearResult); - VERIFY_ARE_EQUAL(expectedResult.UniversalTime, actualResult.UniversalTime); + VERIFY_ARE_EQUAL(expectedYearResult.UniversalTime, actualYearResult.UniversalTime); + + cal->Year = 1989; + cal->Month = 2; + cal->Day = 1; + + // Expect that adding a month across boundaries adds the equivalent in the Gregorian calendar. + auto expectedMonthResult = cal->GetDateTime(); + DateDifference monthDuration; + monthDuration.month = 1; + + DateTime actualMonthResult; + viewModel->AddDuration(startTime, monthDuration, &actualMonthResult); + + VERIFY_ARE_EQUAL(expectedMonthResult.UniversalTime, actualMonthResult.UniversalTime); } TEST_METHOD(JaEraTransitionSubtraction) @@ -984,25 +998,61 @@ TEST_METHOD(JaEraTransitionSubtraction) auto viewModel = make_unique(CalendarIdentifiers::Japanese); auto cal = ref new Calendar(); - // Showa period ended in Jan 1989. - cal->Year = 1990; + // The Showa period ended in Jan 1989. + cal->Year = 1989; + cal->Month = 2; + cal->Day = 1; + auto startTime = cal->GetDateTime(); + + cal->Year = 1988; + cal->Month = 2; + cal->Day = 1; + + // Expect that adding a year across boundaries adds the equivalent in the Gregorian calendar. + auto expectedYearResult = cal->GetDateTime(); + DateDifference yearDuration; + yearDuration.year = 1; + + DateTime actualYearResult; + viewModel->SubtractDuration(startTime, yearDuration, &actualYearResult); + + VERIFY_ARE_EQUAL(expectedYearResult.UniversalTime, actualYearResult.UniversalTime); + + cal->Year = 1989; + cal->Month = 1; + cal->Day = 1; + + // Expect that adding a month across boundaries adds the equivalent in the Gregorian calendar. + auto expectedMonthResult = cal->GetDateTime(); + DateDifference monthDuration; + monthDuration.month = 1; + + DateTime actualMonthResult; + viewModel->SubtractDuration(startTime, monthDuration, &actualMonthResult); + + VERIFY_ARE_EQUAL(expectedMonthResult.UniversalTime, actualMonthResult.UniversalTime); +} + +TEST_METHOD(JaEraTransitionDifference) +{ + auto viewModel = make_unique(CalendarIdentifiers::Japanese); + auto cal = ref new Calendar(); + + // The Showa period ended in Jan 8, 1989. Pick 2 days across that boundary + cal->Year = 1989; cal->Month = 1; cal->Day = 1; auto startTime = cal->GetDateTime(); cal->Year = 1989; cal->Month = 1; - cal->Day = 1; + cal->Day = 20; + auto endTime = cal->GetDateTime(); - // Expect that adding a year across boundaries adds the equivalent in the Gregorian calendar. - auto expectedResult = cal->GetDateTime(); - DateDifference duration; - duration.year = 1; + DateDifference diff; + viewModel->GetDateDifference(startTime, endTime, DateUnit::Day, &diff); - DateTime actualResult; - viewModel->SubtractDuration(startTime, duration, &actualResult); - - VERIFY_ARE_EQUAL(expectedResult.UniversalTime, actualResult.UniversalTime); + VERIFY_ARE_EQUAL(diff.day, 19); } } ;