mirror of
https://github.com/oliverschwendener/ueli.git
synced 2024-10-04 01:57:45 +03:00
✨ Add option for setting a default target currency (#1210)
* ✨ Add option for setting a default target currency
* Added new test case
* Simplify code
---------
Co-authored-by: Oliver Schwendener <oliver.schwendener@proton.me>
This commit is contained in:
parent
30f4e00cae
commit
5cbca27034
@ -1,4 +1,5 @@
|
||||
import type { AssetPathResolver } from "@Core/AssetPathResolver";
|
||||
import type { SettingsManager } from "@Core/SettingsManager";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { CurrencyConversion } from "./CurrencyConversion";
|
||||
import type { Rates } from "./Rates";
|
||||
@ -9,10 +10,12 @@ describe(CurrencyConversion, () => {
|
||||
expectedResult,
|
||||
userInput,
|
||||
rates,
|
||||
defaultTarget,
|
||||
}: {
|
||||
expectedResult: string;
|
||||
userInput: string;
|
||||
rates: Rates;
|
||||
defaultTarget?: string;
|
||||
}) => {
|
||||
const imageFilePath = "/path/to/image";
|
||||
const getExtensionAssetPathMock = vi.fn().mockReturnValue(imageFilePath);
|
||||
@ -22,12 +25,19 @@ describe(CurrencyConversion, () => {
|
||||
getModuleAssetPath: () => null,
|
||||
};
|
||||
|
||||
const currencyConversion = new CurrencyConversion(null, null, assetPathResolver);
|
||||
const getValueMock = vi.fn().mockReturnValue(defaultTarget);
|
||||
|
||||
const settingsManager = <SettingsManager>{
|
||||
getValue: (k, d, s) => getValueMock(k, d, s),
|
||||
};
|
||||
|
||||
const currencyConversion = new CurrencyConversion(settingsManager, null, assetPathResolver);
|
||||
|
||||
currencyConversion["rates"] = rates;
|
||||
|
||||
const actual = currencyConversion.getInstantSearchResultItems(userInput);
|
||||
|
||||
expect(actual.length).toEqual(1);
|
||||
expect(actual[0].name).toEqual(expectedResult);
|
||||
expect(actual[0].image).toEqual({ url: `file://${imageFilePath}` });
|
||||
expect(getExtensionAssetPathMock).toHaveBeenCalledWith(currencyConversion.id, "currency-conversion.png");
|
||||
@ -38,7 +48,9 @@ describe(CurrencyConversion, () => {
|
||||
|
||||
currencyConversion["rates"] = { chf: { usd: 2 } };
|
||||
|
||||
expect(currencyConversion.getInstantSearchResultItems("1")).toEqual([]);
|
||||
expect(currencyConversion.getInstantSearchResultItems("1 CHF to")).toEqual([]);
|
||||
expect(currencyConversion.getInstantSearchResultItems("1 CHF to USD else")).toEqual([]);
|
||||
});
|
||||
|
||||
it("should return empty array when first part in user input is not numerical", () => {
|
||||
@ -77,8 +89,15 @@ describe(CurrencyConversion, () => {
|
||||
it("should convert currencies based on the rates when user input matches expected pattern", () => {
|
||||
const rates: Rates = { chf: { usd: 2, eur: 0.5 } };
|
||||
|
||||
testSuccessfulConversion({ expectedResult: "2.00 USD", userInput: " 1 CHF to USD ", rates });
|
||||
testSuccessfulConversion({ expectedResult: "2.00 USD", userInput: "1 CHF to USD", rates });
|
||||
testSuccessfulConversion({ expectedResult: "0.50 EUR", userInput: "1 CHF in EUR", rates });
|
||||
});
|
||||
|
||||
it("should convert currencies to default currency when user input matches expected pattern", () => {
|
||||
const rates: Rates = { chf: { usd: 2, eur: 0.5 } };
|
||||
|
||||
testSuccessfulConversion({ expectedResult: "2.00 USD", userInput: "1 CHF", rates, defaultTarget: "usd" });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -26,6 +26,7 @@ export class CurrencyConversion implements Extension {
|
||||
|
||||
private readonly defaultSettings = {
|
||||
currencies: ["usd", "chf", "eur"],
|
||||
defaultTargetCurrency: "eur",
|
||||
};
|
||||
|
||||
private rates: Rates;
|
||||
@ -42,11 +43,14 @@ export class CurrencyConversion implements Extension {
|
||||
const parts = searchTerm.trim().split(" ");
|
||||
|
||||
const validators = [
|
||||
() => parts.length === 4,
|
||||
() => parts.length === 2 || parts.length === 4,
|
||||
() => !isNaN(Number(parts[0])),
|
||||
() => Object.keys(this.rates).includes(parts[1].toLowerCase()),
|
||||
() => ["in", "to"].includes(parts[2].toLowerCase()),
|
||||
() => Object.keys(this.rates[parts[1].toLowerCase()]).includes(parts[3].toLowerCase()),
|
||||
() => parts.length === 2 || (parts.length === 4 && ["in", "to"].includes(parts[2].toLowerCase())),
|
||||
() =>
|
||||
Object.keys(this.rates[parts[1].toLowerCase()]).includes(
|
||||
parts.length === 4 ? parts[3].toLowerCase() : this.getDefaultTargetCurrency(),
|
||||
),
|
||||
];
|
||||
|
||||
for (const validator of validators) {
|
||||
@ -57,7 +61,7 @@ export class CurrencyConversion implements Extension {
|
||||
|
||||
const value = Number(parts[0]);
|
||||
const base = parts[1];
|
||||
const target = parts[3];
|
||||
const target = parts.length === 4 ? parts[3].toLowerCase() : this.getDefaultTargetCurrency();
|
||||
|
||||
const conversionResult = convert({ value, base, target, rates: this.rates });
|
||||
|
||||
@ -78,7 +82,7 @@ export class CurrencyConversion implements Extension {
|
||||
},
|
||||
id: `currency-conversion:instant-result`,
|
||||
image: this.getImage(),
|
||||
name: `${conversionResult.result.toFixed(2)} ${parts[3].toUpperCase()}`,
|
||||
name: `${conversionResult.result.toFixed(2)} ${target.toUpperCase()}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
@ -107,6 +111,7 @@ export class CurrencyConversion implements Extension {
|
||||
"en-US": {
|
||||
extensionName: "Currency Conversion",
|
||||
currencies: "Currencies",
|
||||
defaultTargetCurrency: "Default Target Currency",
|
||||
selectCurrencies: "Select currencies",
|
||||
copyToClipboard: "Copy to clipboard",
|
||||
currencyConversion: "Currency Conversion",
|
||||
@ -114,6 +119,7 @@ export class CurrencyConversion implements Extension {
|
||||
"de-CH": {
|
||||
extensionName: "Währungsumrechnung",
|
||||
currencies: "Währungen",
|
||||
defaultTargetCurrency: "Standard-Zielwährung",
|
||||
selectCurrencies: "Währungen wählen",
|
||||
copyToClipboard: "In Zwischenablage kopieren",
|
||||
currencyConversion: "Währungsumrechnung",
|
||||
@ -122,7 +128,10 @@ export class CurrencyConversion implements Extension {
|
||||
}
|
||||
|
||||
public getSettingKeysTriggeringRescan(): string[] {
|
||||
return [getExtensionSettingKey(this.id, "currencies")];
|
||||
return [
|
||||
getExtensionSettingKey(this.id, "currencies"),
|
||||
getExtensionSettingKey(this.id, "defaultTargetCurrency"),
|
||||
];
|
||||
}
|
||||
|
||||
private async setRates(): Promise<void> {
|
||||
@ -143,4 +152,11 @@ export class CurrencyConversion implements Extension {
|
||||
|
||||
this.rates[currency] = responseJson[currency];
|
||||
}
|
||||
|
||||
private getDefaultTargetCurrency(): string {
|
||||
return this.settingsManager.getValue<string>(
|
||||
getExtensionSettingKey(this.id, "defaultTargetCurrency"),
|
||||
this.getSettingDefaultValue<string>("defaultTargetCurrency"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,11 @@ export const CurrencyConversionSettings = () => {
|
||||
key: "currencies",
|
||||
});
|
||||
|
||||
const { value: defaultTargetCurrency, updateValue: setDefaultTargetCurrency } = useExtensionSetting<string>({
|
||||
extensionId: "CurrencyConversion",
|
||||
key: "defaultTargetCurrency",
|
||||
});
|
||||
|
||||
return (
|
||||
<SettingGroupList>
|
||||
<SettingGroup title={t("extensionName")}>
|
||||
@ -35,6 +40,25 @@ export const CurrencyConversionSettings = () => {
|
||||
</Dropdown>
|
||||
}
|
||||
/>
|
||||
<Setting
|
||||
label={t("defaultTargetCurrency")}
|
||||
control={
|
||||
<Dropdown
|
||||
selectedOptions={[defaultTargetCurrency]}
|
||||
value={defaultTargetCurrency.toUpperCase()}
|
||||
placeholder={t("selectDefaultTargetCurrency")}
|
||||
onOptionSelect={(_, { optionValue }) =>
|
||||
optionValue && setDefaultTargetCurrency(optionValue)
|
||||
}
|
||||
>
|
||||
{currencies.map((currency) => (
|
||||
<Option key={currency} value={currency}>
|
||||
{`${currency.toUpperCase()}`}
|
||||
</Option>
|
||||
))}
|
||||
</Dropdown>
|
||||
}
|
||||
/>
|
||||
</SettingGroup>
|
||||
</SettingGroupList>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user