2022-06-02 11:44:12 +02:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
2023-03-15 08:36:07 +01:00
using System.Globalization ;
2022-06-02 11:44:12 +02:00
using System.Linq ;
2024-09-16 16:09:43 -04:00
2024-02-20 13:08:54 +01:00
using Microsoft.PowerToys.Settings.UI.Library ;
2022-06-02 11:44:12 +02:00
using Microsoft.VisualStudio.TestTools.UnitTesting ;
using Moq ;
using Wox.Plugin ;
namespace Microsoft.PowerToys.Run.Plugin.Calculator.UnitTests
{
[TestClass]
public class QueryTests
{
2024-02-20 13:08:54 +01:00
private static Mock < Main > _main ;
private static Mock < IPublicAPI > _api ;
[TestInitialize]
public void Initialize ( )
{
_api = new Mock < IPublicAPI > ( ) ;
_api . Setup ( api = > api . ChangeQuery ( It . IsAny < string > ( ) , It . IsAny < bool > ( ) ) ) . Verifiable ( ) ;
_main = new Mock < Main > ( ) ;
_main . Object . Init ( new PluginInitContext ( ) { API = _api . Object } ) ;
}
2022-06-02 11:44:12 +02:00
[DataTestMethod]
[DataRow("=pi(9+)", "Expression wrong or incomplete (Did you forget some parentheses?)")]
[DataRow("=pi,", "Expression wrong or incomplete (Did you forget some parentheses?)")]
[DataRow("=log()", "Expression wrong or incomplete (Did you forget some parentheses?)")]
[DataRow("=0xf0x6", "Expression wrong or incomplete (Did you forget some parentheses?)")]
[DataRow("=0xf,0x6", "Expression wrong or incomplete (Did you forget some parentheses?)")]
[DataRow("=2^96", "Result value was either too large or too small for a decimal number")]
[DataRow("=+()", "Calculation result is not a valid number (NaN)")]
[DataRow("=[10,10] ", " Unsupported use of square brackets ")]
2022-08-26 17:40:15 +02:00
[DataRow("=5/0", "Expression contains division by zero")]
[DataRow("=5 / 0", "Expression contains division by zero")]
[DataRow("10+(8*9)/0+7", "Expression contains division by zero")]
[DataRow("10+(8*9)/0*7", "Expression contains division by zero")]
2025-01-08 11:49:26 +01:00
[DataRow("10+(8*9)/0x00", "Expression contains division by zero")]
[DataRow("10+(8*9)/0b0", "Expression contains division by zero")]
2022-06-02 11:44:12 +02:00
public void ErrorResultOnInvalidKeywordQuery ( string typedString , string expectedResult )
{
2022-12-18 14:27:14 +01:00
Query expectedQuery = new ( typedString , "=" ) ;
2022-06-02 11:44:12 +02:00
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . FirstOrDefault ( ) . SubTitle ;
2022-06-02 11:44:12 +02:00
// Assert
Assert . AreEqual ( expectedResult , result ) ;
}
[DataTestMethod]
[DataRow("pi(9+)")]
[DataRow("pi,")]
[DataRow("log()")]
[DataRow("0xf0x6")]
[DataRow("0xf,0x6")]
[DataRow("2^96")]
[DataRow("+()")]
[DataRow("[10,10] ")]
2022-08-26 17:40:15 +02:00
[DataRow("5/0")]
[DataRow("5 / 0")]
[DataRow("10+(8*9)/0+7")]
[DataRow("10+(8*9)/0*7")]
2022-06-02 11:44:12 +02:00
public void NoResultOnInvalidGlobalQuery ( string typedString )
{
// Setup
2022-12-18 14:27:14 +01:00
Query expectedQuery = new ( typedString ) ;
2022-06-02 11:44:12 +02:00
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . Count ;
2022-06-02 11:44:12 +02:00
// Assert
2026-04-01 13:15:14 -07:00
Assert . AreEqual ( 0 , result ) ;
2022-06-02 11:44:12 +02:00
}
2022-08-26 17:40:15 +02:00
[DataTestMethod]
[DataRow("9+")]
[DataRow("9-")]
[DataRow("9*")]
[DataRow("9|")]
[DataRow("9\\")]
[DataRow("9^")]
[DataRow("9=")]
[DataRow("9&")]
[DataRow("9/")]
[DataRow("9%")]
public void NoResultIfQueryEndsWithBinaryOperator ( string typedString )
{
// Setup
2022-12-18 14:27:14 +01:00
Query expectedQuery = new ( typedString ) ;
Query expectedQueryWithKeyword = new ( "=" + typedString , "=" ) ;
2022-08-26 17:40:15 +02:00
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . Count ;
var resultWithKeyword = _main . Object . Query ( expectedQueryWithKeyword ) . Count ;
2022-08-26 17:40:15 +02:00
// Assert
2026-04-01 13:15:14 -07:00
Assert . AreEqual ( 0 , result ) ;
Assert . AreEqual ( 0 , resultWithKeyword ) ;
2022-08-26 17:40:15 +02:00
}
[DataTestMethod]
2026-04-01 13:15:14 -07:00
[DataRow("10+(8*9)/0,5")] // German decimal digit separator
2022-08-26 17:40:15 +02:00
[DataRow("10+(8*9)/0.5")]
[DataRow("10+(8*9)/1,5")] // German decimal digit separator
[DataRow("10+(8*9)/1.5")]
public void NoErrorForDivisionByNumberWithDecimalDigits ( string typedString )
{
// Setup
2022-12-18 14:27:14 +01:00
Query expectedQuery = new ( typedString ) ;
Query expectedQueryWithKeyword = new ( "=" + typedString , "=" ) ;
2022-08-26 17:40:15 +02:00
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . FirstOrDefault ( ) . SubTitle ;
var resultWithKeyword = _main . Object . Query ( expectedQueryWithKeyword ) . FirstOrDefault ( ) . SubTitle ;
2022-08-26 17:40:15 +02:00
// Assert
2026-04-01 13:15:14 -07:00
Assert . AreEqual ( "Copy this number to the clipboard" , result ) ;
Assert . AreEqual ( "Copy this number to the clipboard" , resultWithKeyword ) ;
2022-08-26 17:40:15 +02:00
}
2023-03-10 21:48:04 +01:00
[DataTestMethod]
[DataRow("pie", "pi * e")]
[DataRow("eln(100)", "e * ln(100)")]
[DataRow("pi(1+1)", "pi * (1+1)")]
[DataRow("2pi", "2 * pi")]
[DataRow("2log10(100)", "2 * log10(100)")]
[DataRow("2(3+4)", "2 * (3+4)")]
[DataRow("sin(pi)cos(pi)", "sin(pi) * cos(pi)")]
[DataRow("log10(100)(2+3)", "log10(100) * (2+3)")]
[DataRow("(1+1)cos(pi)", "(1+1) * cos(pi)")]
[DataRow("(1+1)(2+2)", "(1+1) * (2+2)")]
[DataRow("2(1+1)", "2 * (1+1)")]
[DataRow("pi(1+1)", "pi * (1+1)")]
[DataRow("pilog(100)", "pi * log(100)")]
[DataRow("3log(100)", "3 * log(100)")]
[DataRow("2e", "2 * e")]
[DataRow("(1+1)(3+2)", "(1+1) * (3+2)")]
[DataRow("(1+1)cos(pi)", "(1+1) * cos(pi)")]
[DataRow("sin(pi)cos(pi)", "sin(pi) * cos(pi)")]
[DataRow("2 (1+1)", "2 * (1+1)")]
[DataRow("pi (1+1)", "pi * (1+1)")]
[DataRow("pi log(100)", "pi * log(100)")]
[DataRow("3 log(100)", "3 * log(100)")]
[DataRow("2 e", "2 * e")]
[DataRow("(1+1) (3+2)", "(1+1) * (3+2)")]
[DataRow("(1+1) cos(pi)", "(1+1) * cos(pi)")]
[DataRow("sin (pi) cos(pi)", "sin (pi) * cos(pi)")]
[DataRow("2picos(pi)(1+1)", "2 * pi * cos(pi) * (1+1)")]
[DataRow("pilog(100)log(1000)", "pi * log(100) * log(1000)")]
[DataRow("pipipie", "pi * pi * pi * e")]
[DataRow("(1+1)(3+2)(1+1)(1+1)", "(1+1) * (3+2) * (1+1) * (1+1)")]
[DataRow("(1+1) (3+2) (1+1)(1+1)", "(1+1) * (3+2) * (1+1) * (1+1)")]
2024-01-03 06:22:09 -05:00
[DataRow("1.0E2", "(1.0 * 10^(2))")]
[DataRow("-1.0E-2", "(-1.0 * 10^(-2))")]
[DataRow("1.2E2", "(1.2 * 10^(2))")]
[DataRow("5/1.0E2", "5/(1.0 * 10^(2))")]
[DataRow("0.1E2", "(0.1 * 10^(2))")]
[DataRow(".1E2", "(.1 * 10^(2))")]
[DataRow(".1E2", "(.1 * 10^(2))")]
[DataRow("5/5E3", "5/(5 * 10^(3))")]
[DataRow("1.E2", "(1. * 10^(2))")]
2023-03-10 21:48:04 +01:00
public void RightHumanMultiplicationExpressionTransformation ( string typedString , string expectedQuery )
{
// Setup
// Act
var result = CalculateHelper . FixHumanMultiplicationExpressions ( typedString ) ;
// Assert
Assert . AreEqual ( expectedQuery , result ) ;
}
[DataTestMethod]
[DataRow("2(1+1)")]
[DataRow("pi(1+1)")]
[DataRow("pilog(100)")]
[DataRow("3log(100)")]
[DataRow("2e")]
[DataRow("(1+1)(3+2)")]
[DataRow("(1+1)cos(pi)")]
[DataRow("sin(pi)cos(pi)")]
[DataRow("2 (1+1)")]
[DataRow("pi (1+1)")]
[DataRow("pi log(100)")]
[DataRow("3 log(100)")]
[DataRow("2 e")]
[DataRow("(1+1) (3+2)")]
[DataRow("(1+1) cos(pi)")]
[DataRow("sin (pi) cos(pi)")]
[DataRow("2picos(pi)(1+1)")]
[DataRow("pilog(100)log(1000)")]
[DataRow("pipipie")]
[DataRow("(1+1)(3+2)(1+1)(1+1)")]
[DataRow("(1+1) (3+2) (1+1)(1+1)")]
public void NoErrorForHumanMultiplicationExpressions ( string typedString )
{
// Setup
Query expectedQuery = new ( typedString ) ;
Query expectedQueryWithKeyword = new ( "=" + typedString , "=" ) ;
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . FirstOrDefault ( ) ? . SubTitle ;
var resultWithKeyword = _main . Object . Query ( expectedQueryWithKeyword ) . FirstOrDefault ( ) ? . SubTitle ;
2023-03-10 21:48:04 +01:00
// Assert
Assert . AreEqual ( "Copy this number to the clipboard" , result ) ;
Assert . AreEqual ( "Copy this number to the clipboard" , resultWithKeyword ) ;
}
[DataTestMethod]
2023-03-15 08:36:07 +01:00
[DataRow("2(1+1)", 4)]
[DataRow("pi(1+1)", 6.2831853072)]
[DataRow("pilog(100)", 6.2831853072)]
[DataRow("3log(100)", 6)]
[DataRow("2e", 5.4365636569)]
2024-01-03 06:22:09 -05:00
[DataRow("2E2", 200)]
[DataRow("2E-2", 0.02)]
[DataRow("1.2E2", 120)]
[DataRow("1.2E-1", 0.12)]
[DataRow("5/5E3", 0.001)]
[DataRow("-5/5E3", -0.001)]
2023-03-15 08:36:07 +01:00
[DataRow("(1+1)(3+2)", 10)]
[DataRow("(1+1)cos(pi)", -2)]
[DataRow("log(100)cos(pi)", -2)]
public void RightAnswerForHumanMultiplicationExpressions ( string typedString , double answer )
2023-03-10 21:48:04 +01:00
{
// Setup
2025-01-08 11:34:13 +01:00
typedString = typedString . Replace ( "." , CultureInfo . CurrentCulture . NumberFormat . CurrencyDecimalSeparator ) ; // Workaround to get correct results when the tests are running on a non-english systems.
2023-03-10 21:48:04 +01:00
Query expectedQuery = new ( typedString ) ;
Query expectedQueryWithKeyword = new ( "=" + typedString , "=" ) ;
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . FirstOrDefault ( ) ? . Title ;
var resultWithKeyword = _main . Object . Query ( expectedQueryWithKeyword ) . FirstOrDefault ( ) ? . Title ;
2023-03-10 21:48:04 +01:00
// Assert
2023-03-15 08:36:07 +01:00
Assert . AreEqual ( answer . ToString ( CultureInfo . CurrentCulture ) , result ) ;
Assert . AreEqual ( answer . ToString ( CultureInfo . CurrentCulture ) , resultWithKeyword ) ;
2023-03-10 21:48:04 +01:00
}
2024-01-26 15:09:38 +01:00
[DataTestMethod]
[DataRow("0x1234+0x1234", 9320)]
[DataRow("0x1234-0x1234", 0)]
[DataRow("0x12345678+0x12345678", 610839792)]
[DataRow("0xf4572220-0xf4572410", -496)]
public void RightAnswerForLargeHexadecimalNumbers ( string typedString , double answer )
{
// Setup
Query expectedQuery = new ( typedString ) ;
Query expectedQueryWithKeyword = new ( "=" + typedString , "=" ) ;
// Act
2024-02-20 13:08:54 +01:00
var result = _main . Object . Query ( expectedQuery ) . FirstOrDefault ( ) ? . Title ;
var resultWithKeyword = _main . Object . Query ( expectedQueryWithKeyword ) . FirstOrDefault ( ) ? . Title ;
2024-01-26 15:09:38 +01:00
// Assert
Assert . AreEqual ( answer . ToString ( CultureInfo . CurrentCulture ) , result ) ;
Assert . AreEqual ( answer . ToString ( CultureInfo . CurrentCulture ) , resultWithKeyword ) ;
}
2024-02-20 13:08:54 +01:00
[DataTestMethod]
[DataRow("#", "#1+1=", true)]
[DataRow("#", "#1+1", false)]
[DataRow("#", "#1/0=", false)]
[DataRow("", "1+1=", false)]
public void HandleInputReplace ( string actionKeyword , string query , bool shouldChangeQuery )
{
// Setup
Query expectedQuery = new ( query , actionKeyword ) ;
_main . Object . UpdateSettings ( new PowerLauncherPluginSettings ( ) ) ; // Default settings
// Act
_main . Object . Query ( expectedQuery ) ;
// Assert
_api . Verify ( api = > api . ChangeQuery ( It . IsAny < string > ( ) , It . IsAny < bool > ( ) ) , shouldChangeQuery ? Times . Once : Times . Never ) ;
}
2022-06-02 11:44:12 +02:00
}
}