migrate to preact
This commit is contained in:
parent
b414de8533
commit
30f86f8748
@ -6,15 +6,8 @@ module.exports = {
|
|||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:react/recommended",
|
"preact",
|
||||||
"plugin:react-hooks/recommended",
|
|
||||||
],
|
],
|
||||||
settings: {
|
|
||||||
"react": {
|
|
||||||
"version": "16.9.6",
|
|
||||||
},
|
|
||||||
|
|
||||||
},
|
|
||||||
rules: {
|
rules: {
|
||||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||||
"prefer-const": ["warn", { destructuring: "all" }],
|
"prefer-const": ["warn", { destructuring: "all" }],
|
||||||
|
@ -9,34 +9,53 @@
|
|||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
||||||
|
"test": "jest ./tests",
|
||||||
"compile": "tsc && rollup -c"
|
"compile": "tsc && rollup -c"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"moment": "^2.29.1",
|
|
||||||
"@gnu-taler/taler-wallet-core": "workspace:*",
|
|
||||||
"@gnu-taler/taler-util": "workspace:*",
|
"@gnu-taler/taler-util": "workspace:*",
|
||||||
|
"@gnu-taler/taler-wallet-core": "workspace:*",
|
||||||
|
"preact": "^10.5.13",
|
||||||
|
"preact-router": "^3.2.1",
|
||||||
"tslib": "^2.1.0"
|
"tslib": "^2.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.14.0",
|
||||||
|
"@babel/plugin-transform-react-jsx-source": "^7.12.13",
|
||||||
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
"@rollup/plugin-commonjs": "^17.0.0",
|
"@rollup/plugin-commonjs": "^17.0.0",
|
||||||
"@rollup/plugin-json": "^4.1.0",
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||||
"@rollup/plugin-replace": "^2.3.4",
|
"@rollup/plugin-replace": "^2.3.4",
|
||||||
|
"@testing-library/preact": "^2.0.1",
|
||||||
"@types/chrome": "^0.0.128",
|
"@types/chrome": "^0.0.128",
|
||||||
"@types/enzyme": "^3.10.8",
|
"@types/jest": "^26.0.23",
|
||||||
"@types/enzyme-adapter-react-16": "^1.0.6",
|
|
||||||
"@types/node": "^14.14.22",
|
"@types/node": "^14.14.22",
|
||||||
"@types/react": "^17.0.0",
|
|
||||||
"@types/react-dom": "^17.0.0",
|
|
||||||
"ava": "3.15.0",
|
"ava": "3.15.0",
|
||||||
|
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"react": "^17.0.1",
|
"enzyme-adapter-preact-pure": "^3.1.0",
|
||||||
"react-dom": "^17.0.1",
|
"jest": "^26.6.3",
|
||||||
|
"jest-preset-preact": "^4.0.3",
|
||||||
|
"preact-cli": "^3.0.5",
|
||||||
|
"preact-render-to-string": "^5.1.19",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rollup": "^2.37.1",
|
"rollup": "^2.37.1",
|
||||||
"rollup-plugin-ignore": "^1.0.9",
|
"rollup-plugin-ignore": "^1.0.9",
|
||||||
"rollup-plugin-sourcemaps": "^0.6.3",
|
"rollup-plugin-sourcemaps": "^0.6.3",
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.3"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "jest-preset-preact",
|
||||||
|
"setupFiles": [
|
||||||
|
"<rootDir>/tests/__mocks__/setupTests.ts"
|
||||||
|
],
|
||||||
|
"moduleNameMapper": {
|
||||||
|
"\\.(css|less)$": "identity-obj-proxy"
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|po)$": "<rootDir>/tests/__mocks__/fileTransformer.js"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import {
|
|||||||
HttpRequestOptions,
|
HttpRequestOptions,
|
||||||
HttpResponse,
|
HttpResponse,
|
||||||
Headers,
|
Headers,
|
||||||
bytesToString,
|
|
||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import { TalerErrorCode } from "@gnu-taler/taler-util";
|
import { TalerErrorCode } from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@
|
|||||||
/**
|
/**
|
||||||
* Imports
|
* Imports
|
||||||
*/
|
*/
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import * as i18nCore from "@gnu-taler/taler-wallet-core";
|
import * as i18nCore from "@gnu-taler/taler-wallet-core";
|
||||||
|
import { Component, ComponentChildren, h, JSX, toChildArray, VNode } from "preact";
|
||||||
/**
|
/**
|
||||||
* Convert template strings to a msgid
|
* Convert template strings to a msgid
|
||||||
*/
|
*/
|
||||||
@ -50,7 +50,7 @@ interface TranslateSwitchProps {
|
|||||||
|
|
||||||
function stringifyChildren(children: any): string {
|
function stringifyChildren(children: any): string {
|
||||||
let n = 1;
|
let n = 1;
|
||||||
const ss = React.Children.map(children, (c) => {
|
const ss = toChildArray(children).map((c) => {
|
||||||
if (typeof c === "string") {
|
if (typeof c === "string") {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -76,10 +76,10 @@ interface TranslateProps {
|
|||||||
|
|
||||||
function getTranslatedChildren(
|
function getTranslatedChildren(
|
||||||
translation: string,
|
translation: string,
|
||||||
children: React.ReactNode,
|
children: ComponentChildren,
|
||||||
): React.ReactNode[] {
|
): ComponentChildren {
|
||||||
const tr = translation.split(/%(\d+)\$s/);
|
const tr = translation.split(/%(\d+)\$s/);
|
||||||
const childArray = React.Children.toArray(children);
|
const childArray = toChildArray(children);
|
||||||
// Merge consecutive string children.
|
// Merge consecutive string children.
|
||||||
const placeholderChildren = [];
|
const placeholderChildren = [];
|
||||||
for (let i = 0; i < childArray.length; i++) {
|
for (let i = 0; i < childArray.length; i++) {
|
||||||
@ -117,15 +117,15 @@ function getTranslatedChildren(
|
|||||||
* </Translate>
|
* </Translate>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export class Translate extends React.Component<TranslateProps, {}> {
|
export class Translate extends Component<TranslateProps, any> {
|
||||||
render(): JSX.Element {
|
render() {
|
||||||
const s = stringifyChildren(this.props.children);
|
const s = stringifyChildren(this.props.children);
|
||||||
const translation: string = i18nCore.jed.ngettext(s, s, 1);
|
const translation: string = i18nCore.jed.ngettext(s, s, 1);
|
||||||
const result = getTranslatedChildren(translation, this.props.children);
|
const result = getTranslatedChildren(translation, this.props.children);
|
||||||
if (!this.props.wrap) {
|
if (!this.props.wrap) {
|
||||||
return <div>{result}</div>;
|
return <div>{result}</div>;
|
||||||
}
|
}
|
||||||
return React.createElement(this.props.wrap, this.props.wrapProps, result);
|
return h(this.props.wrap, this.props.wrapProps, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,16 +141,16 @@ export class Translate extends React.Component<TranslateProps, {}> {
|
|||||||
* </TranslateSwitch>
|
* </TranslateSwitch>
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export class TranslateSwitch extends React.Component<
|
export class TranslateSwitch extends Component<
|
||||||
TranslateSwitchProps,
|
TranslateSwitchProps,
|
||||||
void
|
void
|
||||||
> {
|
> {
|
||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
let singular: React.ReactElement<TranslationPluralProps> | undefined;
|
let singular: VNode<TranslationPluralProps> | undefined;
|
||||||
let plural: React.ReactElement<TranslationPluralProps> | undefined;
|
let plural: VNode<TranslationPluralProps> | undefined;
|
||||||
const children = this.props.children;
|
const children = this.props.children;
|
||||||
if (children) {
|
if (children) {
|
||||||
React.Children.forEach(children, (child: any) => {
|
toChildArray(children).forEach((child: any) => {
|
||||||
if (child.type === TranslatePlural) {
|
if (child.type === TranslatePlural) {
|
||||||
plural = child;
|
plural = child;
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ export class TranslateSwitch extends React.Component<
|
|||||||
}
|
}
|
||||||
if (!singular || !plural) {
|
if (!singular || !plural) {
|
||||||
console.error("translation not found");
|
console.error("translation not found");
|
||||||
return React.createElement("span", {}, ["translation not found"]);
|
return h("span", {}, ["translation not found"]);
|
||||||
}
|
}
|
||||||
singular.props.target = this.props.target;
|
singular.props.target = this.props.target;
|
||||||
plural.props.target = this.props.target;
|
plural.props.target = this.props.target;
|
||||||
@ -178,7 +178,7 @@ interface TranslationPluralProps {
|
|||||||
/**
|
/**
|
||||||
* See [[TranslateSwitch]].
|
* See [[TranslateSwitch]].
|
||||||
*/
|
*/
|
||||||
export class TranslatePlural extends React.Component<
|
export class TranslatePlural extends Component<
|
||||||
TranslationPluralProps,
|
TranslationPluralProps,
|
||||||
void
|
void
|
||||||
> {
|
> {
|
||||||
@ -193,7 +193,7 @@ export class TranslatePlural extends React.Component<
|
|||||||
/**
|
/**
|
||||||
* See [[TranslateSwitch]].
|
* See [[TranslateSwitch]].
|
||||||
*/
|
*/
|
||||||
export class TranslateSingular extends React.Component<
|
export class TranslateSingular extends Component<
|
||||||
TranslationPluralProps,
|
TranslationPluralProps,
|
||||||
void
|
void
|
||||||
> {
|
> {
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* @author Florian Dold <dold@taler.net>
|
* @author Florian Dold <dold@taler.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ReactDOM from "react-dom";
|
import {render} from "preact";
|
||||||
import { createPopup } from "./pages/popup";
|
import { createPopup } from "./pages/popup";
|
||||||
import { createWithdrawPage } from "./pages/withdraw";
|
import { createWithdrawPage } from "./pages/withdraw";
|
||||||
import { createWelcomePage } from "./pages/welcome";
|
import { createWelcomePage } from "./pages/welcome";
|
||||||
@ -63,7 +63,7 @@ function main(): void {
|
|||||||
if (!container) {
|
if (!container) {
|
||||||
throw Error("container not found, can't mount page contents");
|
throw Error("container not found, can't mount page contents");
|
||||||
}
|
}
|
||||||
ReactDOM.render(mainElement, container);
|
render(mainElement, container);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("got error", e);
|
console.error("got error", e);
|
||||||
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
|
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
|
||||||
|
@ -27,7 +27,7 @@ import * as i18n from "../i18n";
|
|||||||
import { renderAmount, ProgressButton } from "../renderHtml";
|
import { renderAmount, ProgressButton } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
|
|
||||||
import { getJsonI18n } from "@gnu-taler/taler-wallet-core";
|
import { getJsonI18n } from "@gnu-taler/taler-wallet-core";
|
||||||
import {
|
import {
|
||||||
@ -39,10 +39,11 @@ import {
|
|||||||
ContractTerms,
|
ContractTerms,
|
||||||
ConfirmPayResultType,
|
ConfirmPayResultType,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import { JSX, VNode } from "preact";
|
||||||
|
|
||||||
function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
||||||
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>();
|
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(undefined);
|
||||||
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>();
|
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
|
||||||
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
||||||
const [numTries, setNumTries] = useState(0);
|
const [numTries, setNumTries] = useState(0);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -66,8 +67,8 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (payStatus.status === PreparePayResultType.PaymentPossible) {
|
if (payStatus.status === PreparePayResultType.PaymentPossible) {
|
||||||
let amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
|
const amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
|
||||||
let amountEffective: AmountJson = Amounts.parseOrThrow(
|
const amountEffective: AmountJson = Amounts.parseOrThrow(
|
||||||
payStatus.amountEffective,
|
payStatus.amountEffective,
|
||||||
);
|
);
|
||||||
totalFees = Amounts.sub(amountEffective, amountRaw).amount;
|
totalFees = Amounts.sub(amountEffective, amountRaw).amount;
|
||||||
@ -95,7 +96,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let contractTerms: ContractTerms = payStatus.contractTerms;
|
const contractTerms: ContractTerms = payStatus.contractTerms;
|
||||||
|
|
||||||
if (!contractTerms) {
|
if (!contractTerms) {
|
||||||
return (
|
return (
|
||||||
@ -105,7 +106,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let merchantName: React.ReactElement;
|
let merchantName: VNode;
|
||||||
if (contractTerms.merchant && contractTerms.merchant.name) {
|
if (contractTerms.merchant && contractTerms.merchant.name) {
|
||||||
merchantName = <strong>{contractTerms.merchant.name}</strong>;
|
merchantName = <strong>{contractTerms.merchant.name}</strong>;
|
||||||
} else {
|
} else {
|
||||||
@ -200,7 +201,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<ProgressButton
|
<ProgressButton
|
||||||
loading={loading}
|
isLoading={loading}
|
||||||
disabled={insufficientBalance}
|
disabled={insufficientBalance}
|
||||||
onClick={() => doPayment()}
|
onClick={() => doPayment()}
|
||||||
>
|
>
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View and edit auditors.
|
* View and edit auditors.
|
||||||
*
|
*
|
||||||
@ -23,7 +25,6 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import * as React from "react";
|
|
||||||
|
|
||||||
export function makePaybackPage(): JSX.Element {
|
export function makePaybackPage(): JSX.Element {
|
||||||
return <div>not implemented</div>;
|
return <div>not implemented</div>;
|
||||||
|
@ -41,18 +41,18 @@ import {
|
|||||||
amountFractionalBase,
|
amountFractionalBase,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
import { abbrev, renderAmount, PageLink } from "../renderHtml";
|
import { renderAmount, PageLink } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
import React, { Fragment, useState, useEffect } from "react";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
|
|
||||||
import moment from "moment";
|
|
||||||
import { PermissionsCheckbox } from "./welcome";
|
import { PermissionsCheckbox } from "./welcome";
|
||||||
|
import { JSXInternal } from "preact/src/jsx";
|
||||||
|
import { Component, ComponentChild, ComponentChildren, JSX, toChildArray, VNode } from "preact";
|
||||||
|
|
||||||
// FIXME: move to newer react functions
|
// FIXME: move to newer react functions
|
||||||
/* eslint-disable react/no-deprecated */
|
|
||||||
|
|
||||||
class Router extends React.Component<any, any> {
|
class Router extends Component<any, any> {
|
||||||
static setRoute(s: string): void {
|
static setRoute(s: string): void {
|
||||||
window.location.hash = s;
|
window.location.hash = s;
|
||||||
}
|
}
|
||||||
@ -85,21 +85,21 @@ class Router extends React.Component<any, any> {
|
|||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
const route = window.location.hash.substring(1);
|
const route = window.location.hash.substring(1);
|
||||||
console.log("rendering route", route);
|
console.log("rendering route", route);
|
||||||
let defaultChild: React.ReactChild | null = null;
|
let defaultChild: ComponentChild | null = null;
|
||||||
let foundChild: React.ReactChild | null = null;
|
let foundChild: ComponentChild | null = null;
|
||||||
React.Children.forEach(this.props.children, (child) => {
|
toChildArray(this.props.children).forEach((child) => {
|
||||||
const childProps: any = (child as any).props;
|
const childProps: any = (child as any).props;
|
||||||
if (!childProps) {
|
if (!childProps) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (childProps.default) {
|
if (childProps.default) {
|
||||||
defaultChild = child as React.ReactChild;
|
defaultChild = child;
|
||||||
}
|
}
|
||||||
if (childProps.route === route) {
|
if (childProps.route === route) {
|
||||||
foundChild = child as React.ReactChild;
|
foundChild = child;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const c: React.ReactChild | null = foundChild || defaultChild;
|
const c: ComponentChild | null = foundChild || defaultChild;
|
||||||
if (!c) {
|
if (!c) {
|
||||||
throw Error("unknown route");
|
throw Error("unknown route");
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ class Router extends React.Component<any, any> {
|
|||||||
|
|
||||||
interface TabProps {
|
interface TabProps {
|
||||||
target: string;
|
target: string;
|
||||||
children?: React.ReactNode;
|
children?: ComponentChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Tab(props: TabProps): JSX.Element {
|
function Tab(props: TabProps): JSX.Element {
|
||||||
@ -118,7 +118,7 @@ function Tab(props: TabProps): JSX.Element {
|
|||||||
if (props.target === Router.getRoute()) {
|
if (props.target === Router.getRoute()) {
|
||||||
cssClass = "active";
|
cssClass = "active";
|
||||||
}
|
}
|
||||||
const onClick = (e: React.MouseEvent<HTMLAnchorElement>): void => {
|
const onClick = (e: JSXInternal.TargetedMouseEvent<HTMLAnchorElement>): void => {
|
||||||
Router.setRoute(props.target);
|
Router.setRoute(props.target);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
@ -129,7 +129,7 @@ function Tab(props: TabProps): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletNavBar extends React.Component<any, any> {
|
class WalletNavBar extends Component<any, any> {
|
||||||
private cancelSubscription: any;
|
private cancelSubscription: any;
|
||||||
|
|
||||||
componentWillMount(): void {
|
componentWillMount(): void {
|
||||||
@ -179,7 +179,7 @@ function EmptyBalanceView(): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletBalanceView extends React.Component<any, any> {
|
class WalletBalanceView extends Component<any, any> {
|
||||||
private balance?: BalancesResponse;
|
private balance?: BalancesResponse;
|
||||||
private gotError = false;
|
private gotError = false;
|
||||||
private canceler: (() => void) | undefined = undefined;
|
private canceler: (() => void) | undefined = undefined;
|
||||||
@ -323,7 +323,7 @@ function TransactionAmount(props: TransactionAmountProps): JSX.Element {
|
|||||||
case "unknown":
|
case "unknown":
|
||||||
sign = "";
|
sign = "";
|
||||||
}
|
}
|
||||||
const style: React.CSSProperties = {
|
const style: JSX.AllCSSProperties = {
|
||||||
marginLeft: "auto",
|
marginLeft: "auto",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
@ -476,7 +476,7 @@ function TransactionItem(props: { tx: Transaction }): JSX.Element {
|
|||||||
function WalletHistory(props: any): JSX.Element {
|
function WalletHistory(props: any): JSX.Element {
|
||||||
const [transactions, setTransactions] = useState<
|
const [transactions, setTransactions] = useState<
|
||||||
TransactionsResponse | undefined
|
TransactionsResponse | undefined
|
||||||
>();
|
>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async (): Promise<void> => {
|
const fetchData = async (): Promise<void> => {
|
||||||
@ -484,7 +484,6 @@ function WalletHistory(props: any): JSX.Element {
|
|||||||
setTransactions(res);
|
setTransactions(res);
|
||||||
};
|
};
|
||||||
fetchData();
|
fetchData();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!transactions) {
|
if (!transactions) {
|
||||||
@ -495,14 +494,14 @@ function WalletHistory(props: any): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{txs.map((tx) => (
|
{txs.map((tx,i) => (
|
||||||
<TransactionItem tx={tx} />
|
<TransactionItem key={i} tx={tx} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletSettings extends React.Component<any, any> {
|
class WalletSettings extends Component<any, any> {
|
||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -522,14 +521,14 @@ function reload(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmReset(): void {
|
async function confirmReset(): Promise<void> {
|
||||||
if (
|
if (
|
||||||
confirm(
|
confirm(
|
||||||
"Do you want to IRREVOCABLY DESTROY everything inside your" +
|
"Do you want to IRREVOCABLY DESTROY everything inside your" +
|
||||||
" wallet and LOSE ALL YOUR COINS?",
|
" wallet and LOSE ALL YOUR COINS?",
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
wxApi.resetDb();
|
await wxApi.resetDb();
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -554,14 +553,14 @@ function openExtensionPage(page: string) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function openTab(page: string) {
|
// function openTab(page: string) {
|
||||||
return (evt: React.SyntheticEvent<any>) => {
|
// return (evt: React.SyntheticEvent<any>) => {
|
||||||
evt.preventDefault();
|
// evt.preventDefault();
|
||||||
chrome.tabs.create({
|
// chrome.tabs.create({
|
||||||
url: page,
|
// url: page,
|
||||||
});
|
// });
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
function makeExtensionUrlWithParams(
|
function makeExtensionUrlWithParams(
|
||||||
url: string,
|
url: string,
|
||||||
|
@ -20,17 +20,18 @@
|
|||||||
* @author Florian Dold
|
* @author Florian Dold
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import { AmountView } from "../renderHtml";
|
import { AmountView } from "../renderHtml";
|
||||||
import {
|
import {
|
||||||
PurchaseDetails,
|
|
||||||
ApplyRefundResponse,
|
ApplyRefundResponse,
|
||||||
Amounts,
|
Amounts,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
// import { h } from 'preact';
|
||||||
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
||||||
const [applyResult, setApplyResult] = useState<ApplyRefundResponse>();
|
const [applyResult, setApplyResult] = useState<ApplyRefundResponse|undefined>(undefined);
|
||||||
const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
|
const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
* @author Florian Dold
|
* @author Florian Dold
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import { Component, JSX } from "preact";
|
||||||
|
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
@ -36,7 +35,7 @@ interface State {
|
|||||||
resetRequired: boolean;
|
resetRequired: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResetNotification extends React.Component<any, State> {
|
class ResetNotification extends Component<any, State> {
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = { checked: false, resetRequired: true };
|
this.state = { checked: false, resetRequired: true };
|
||||||
@ -50,7 +49,7 @@ class ResetNotification extends React.Component<any, State> {
|
|||||||
if (this.state.resetRequired) {
|
if (this.state.resetRequired) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Manual Reset Reqired</h1>
|
<h1>Manual Reset Required</h1>
|
||||||
<p>
|
<p>
|
||||||
The wallet's database in your browser is incompatible with the{" "}
|
The wallet's database in your browser is incompatible with the{" "}
|
||||||
currently installed wallet. Please reset manually.
|
currently installed wallet. Please reset manually.
|
||||||
@ -63,7 +62,9 @@ class ResetNotification extends React.Component<any, State> {
|
|||||||
id="check"
|
id="check"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={this.state.checked}
|
checked={this.state.checked}
|
||||||
onChange={(e) => this.setState({ checked: e.target.checked })}
|
onChange={() => {
|
||||||
|
this.setState(prev => ({ checked: prev.checked }))
|
||||||
|
}}
|
||||||
/>{" "}
|
/>{" "}
|
||||||
<label htmlFor="check">
|
<label htmlFor="check">
|
||||||
I understand that I will lose all my data
|
I understand that I will lose all my data
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return coins to own bank account.
|
* Return coins to own bank account.
|
||||||
*
|
*
|
||||||
@ -23,8 +25,6 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import * as React from "react";
|
|
||||||
|
|
||||||
export function createReturnCoinsPage(): JSX.Element {
|
export function createReturnCoinsPage(): JSX.Element {
|
||||||
return <span>Not implemented yet.</span>;
|
return <span>Not implemented yet.</span>;
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,17 @@
|
|||||||
* @author Florian Dold <dold@taler.net>
|
* @author Florian Dold <dold@taler.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as React from "react";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { PrepareTipResult } from "@gnu-taler/taler-util";
|
import { PrepareTipResult } from "@gnu-taler/taler-util";
|
||||||
import { AmountView } from "../renderHtml";
|
import { AmountView } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
|
function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
|
||||||
const [updateCounter, setUpdateCounter] = useState<number>(0);
|
const [updateCounter, setUpdateCounter] = useState<number>(0);
|
||||||
const [prepareTipResult, setPrepareTipResult] = useState<
|
const [prepareTipResult, setPrepareTipResult] = useState<
|
||||||
PrepareTipResult | undefined
|
PrepareTipResult | undefined
|
||||||
>();
|
>(undefined);
|
||||||
|
|
||||||
const [tipIgnored, setTipIgnored] = useState(false);
|
const [tipIgnored, setTipIgnored] = useState(false);
|
||||||
|
|
||||||
|
@ -20,13 +20,14 @@
|
|||||||
* @author Florian Dold
|
* @author Florian Dold
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
import { getDiagnostics } from "../wxApi";
|
import { getDiagnostics } from "../wxApi";
|
||||||
import { PageLink } from "../renderHtml";
|
import { PageLink } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import { getPermissionsApi } from "../compat";
|
import { getPermissionsApi } from "../compat";
|
||||||
import { extendedPermissions } from "../permissions";
|
import { extendedPermissions } from "../permissions";
|
||||||
import { WalletDiagnostics } from "@gnu-taler/taler-util";
|
import { WalletDiagnostics } from "@gnu-taler/taler-util";
|
||||||
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function Diagnostics(): JSX.Element | null {
|
function Diagnostics(): JSX.Element | null {
|
||||||
const [timedOut, setTimedOut] = useState(false);
|
const [timedOut, setTimedOut] = useState(false);
|
||||||
@ -102,9 +103,9 @@ export function PermissionsCheckbox(): JSX.Element {
|
|||||||
const [extendedPermissionsEnabled, setExtendedPermissionsEnabled] = useState(
|
const [extendedPermissionsEnabled, setExtendedPermissionsEnabled] = useState(
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
async function handleExtendedPerm(requestedVal: boolean): Promise<void> {
|
async function handleExtendedPerm(): Promise<void> {
|
||||||
let nextVal: boolean | undefined;
|
let nextVal: boolean | undefined;
|
||||||
if (requestedVal) {
|
if (extendedPermissionsEnabled) {
|
||||||
const granted = await new Promise<boolean>((resolve, reject) => {
|
const granted = await new Promise<boolean>((resolve, reject) => {
|
||||||
// We set permissions here, since apparently FF wants this to be done
|
// We set permissions here, since apparently FF wants this to be done
|
||||||
// as the result of an input event ...
|
// as the result of an input event ...
|
||||||
@ -141,7 +142,7 @@ export function PermissionsCheckbox(): JSX.Element {
|
|||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
checked={extendedPermissionsEnabled}
|
checked={extendedPermissionsEnabled}
|
||||||
onChange={(x) => handleExtendedPerm(x.target.checked)}
|
onChange={() => handleExtendedPerm()}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="checkbox-perm"
|
id="checkbox-perm"
|
||||||
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }}
|
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }}
|
||||||
|
@ -25,19 +25,20 @@ import * as i18n from "../i18n";
|
|||||||
|
|
||||||
import { renderAmount } from "../renderHtml";
|
import { renderAmount } from "../renderHtml";
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
import {
|
import {
|
||||||
acceptWithdrawal,
|
acceptWithdrawal,
|
||||||
onUpdateNotification,
|
onUpdateNotification,
|
||||||
getWithdrawalDetailsForUri,
|
getWithdrawalDetailsForUri,
|
||||||
} from "../wxApi";
|
} from "../wxApi";
|
||||||
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
|
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
|
||||||
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
||||||
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>();
|
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
|
||||||
const [selectedExchange, setSelectedExchange] = useState<
|
const [selectedExchange, setSelectedExchange] = useState<
|
||||||
string | undefined
|
string | undefined
|
||||||
>();
|
>(undefined);
|
||||||
const talerWithdrawUri = props.talerWithdrawUri;
|
const talerWithdrawUri = props.talerWithdrawUri;
|
||||||
const [cancelled, setCancelled] = useState(false);
|
const [cancelled, setCancelled] = useState(false);
|
||||||
const [selecting, setSelecting] = useState(false);
|
const [selecting, setSelecting] = useState(false);
|
||||||
@ -48,7 +49,6 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
|||||||
return onUpdateNotification(() => {
|
return onUpdateNotification(() => {
|
||||||
setUpdateCounter(updateCounter + 1);
|
setUpdateCounter(updateCounter + 1);
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -23,12 +23,13 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import React from "react";
|
|
||||||
import {
|
import {
|
||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
amountFractionalBase,
|
amountFractionalBase,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import { Component, ComponentChildren, JSX } from "preact";
|
||||||
|
import { JSXInternal } from "preact/src/jsx";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render amount as HTML, which non-breaking space between
|
* Render amount as HTML, which non-breaking space between
|
||||||
@ -87,7 +88,7 @@ interface CollapsibleProps {
|
|||||||
* Component that shows/hides its children when clicking
|
* Component that shows/hides its children when clicking
|
||||||
* a heading.
|
* a heading.
|
||||||
*/
|
*/
|
||||||
export class Collapsible extends React.Component<
|
export class Collapsible extends Component<
|
||||||
CollapsibleProps,
|
CollapsibleProps,
|
||||||
CollapsibleState
|
CollapsibleState
|
||||||
> {
|
> {
|
||||||
@ -139,24 +140,18 @@ export function ExpanderText({ text }: ExpanderTextProps): JSX.Element {
|
|||||||
return <span>{text}</span>;
|
return <span>{text}</span>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LoadingButtonProps {
|
export interface LoadingButtonProps extends JSX.HTMLAttributes<HTMLButtonElement> {
|
||||||
loading: boolean;
|
isLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProgressButton(
|
export function ProgressButton({isLoading, ...rest}: LoadingButtonProps): JSX.Element {
|
||||||
props: React.PropsWithChildren<LoadingButtonProps> &
|
|
||||||
React.DetailedHTMLProps<
|
|
||||||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
||||||
HTMLButtonElement
|
|
||||||
>,
|
|
||||||
): JSX.Element {
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className="pure-button pure-button-primary"
|
className="pure-button pure-button-primary"
|
||||||
type="button"
|
type="button"
|
||||||
{...props}
|
{...rest}
|
||||||
>
|
>
|
||||||
{props.loading ? (
|
{isLoading ? (
|
||||||
<span>
|
<span>
|
||||||
<object
|
<object
|
||||||
className="svg-icon svg-baseline"
|
className="svg-icon svg-baseline"
|
||||||
@ -164,13 +159,13 @@ export function ProgressButton(
|
|||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
) : null}{" "}
|
) : null}{" "}
|
||||||
{props.children}
|
{rest.children}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PageLink(
|
export function PageLink(
|
||||||
props: React.PropsWithChildren<{ pageName: string }>,
|
props: { pageName: string, children?: ComponentChildren },
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const url = chrome.extension.getURL(`/${props.pageName}`);
|
const url = chrome.extension.getURL(`/${props.pageName}`);
|
||||||
return (
|
return (
|
||||||
|
@ -146,7 +146,7 @@ async function dispatch(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
const w = currentWallet;
|
const w = currentWallet;
|
||||||
if (!w) {
|
if (!w) {
|
||||||
r = {
|
r = {
|
||||||
@ -163,6 +163,7 @@ async function dispatch(
|
|||||||
}
|
}
|
||||||
r = await w.handleCoreApiRequest(req.operation, req.id, req.payload);
|
r = await w.handleCoreApiRequest(req.operation, req.id, req.payload);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2021 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This fixed an error related to the CSS and loading gif breaking my Jest test
|
||||||
|
// See https://facebook.github.io/jest/docs/en/webpack.html#handling-static-assets
|
||||||
|
export default 'test-file-stub';
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2021 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
|
*/
|
||||||
|
// fileTransformer.js
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
process(src, filename, config, options) {
|
||||||
|
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2021 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'regenerator-runtime/runtime'
|
||||||
|
import { configure } from 'enzyme';
|
||||||
|
import Adapter from 'enzyme-adapter-preact-pure';
|
||||||
|
|
||||||
|
configure({
|
||||||
|
adapter: new Adapter()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Polyfill for encoding which isn't present globally in jsdom
|
||||||
|
import { TextEncoder, TextDecoder } from 'util'
|
||||||
|
global.TextEncoder = TextEncoder
|
||||||
|
global.TextDecoder = TextDecoder
|
@ -14,12 +14,11 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import test from "ava";
|
// import * as test from "ava";
|
||||||
import { internalSetStrings, str, Translate, strings } from "./i18n";
|
import { internalSetStrings, str, Translate } from "../src/i18n";
|
||||||
import React from "react";
|
import { render, configure } from "enzyme";
|
||||||
import { render } from "enzyme";
|
import Adapter from 'enzyme-adapter-preact-pure';
|
||||||
import { configure } from "enzyme";
|
import { h } from "preact";
|
||||||
import Adapter from "enzyme-adapter-react-16";
|
|
||||||
|
|
||||||
configure({ adapter: new Adapter() });
|
configure({ adapter: new Adapter() });
|
||||||
|
|
||||||
@ -39,30 +38,31 @@ const testStrings = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
test("str translation", (t) => {
|
test("str translation", (done) => {
|
||||||
|
|
||||||
// Alias, so we nly use the function for lookups, not for string extranction.
|
// Alias, so we nly use the function for lookups, not for string extranction.
|
||||||
const strAlias = str;
|
const strAlias = str;
|
||||||
const TranslateAlias = Translate;
|
const TranslateAlias = Translate;
|
||||||
internalSetStrings(testStrings);
|
internalSetStrings(testStrings);
|
||||||
t.is(strAlias`str1`, "foo1");
|
expect(strAlias`str1`).toEqual("foo1");
|
||||||
t.is(strAlias`str2`, "str2");
|
expect(strAlias`str2`).toEqual("str2");
|
||||||
const a = "a";
|
const a = "a";
|
||||||
const b = "b";
|
const b = "b";
|
||||||
t.is(strAlias`str3 ${a} / ${b}`, "foo3 b ; a");
|
expect(strAlias`str3 ${a} / ${b}`).toEqual("foo3 b ; a");
|
||||||
const r = render(<TranslateAlias>str1</TranslateAlias>);
|
const r = render(<TranslateAlias>str1</TranslateAlias>);
|
||||||
t.is(r.text(), "foo1");
|
expect(r.text()).toEqual("foo1");
|
||||||
|
|
||||||
const r2 = render(
|
const r2 = render(
|
||||||
<TranslateAlias>
|
<TranslateAlias>
|
||||||
str3 <span>{a}</span> / <span>{b}</span>
|
str3 <span>{a}</span> / <span>{b}</span>
|
||||||
</TranslateAlias>,
|
</TranslateAlias>,
|
||||||
);
|
);
|
||||||
t.is(r2.text(), "foo3 b ; a");
|
expect(r2.text()).toEqual("foo3 b ; a");
|
||||||
|
|
||||||
t.pass();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("existing str translation", (t) => {
|
// test.default("existing str translation", (t) => {
|
||||||
internalSetStrings(strings);
|
// internalSetStrings(strings);
|
||||||
t.pass();
|
// t.pass();
|
||||||
});
|
// });
|
@ -2,9 +2,9 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
"lib": ["es6", "DOM"],
|
"lib": ["es6", "DOM"],
|
||||||
"jsx": "react",
|
"jsx": "react-jsx",
|
||||||
|
"jsxImportSource": "preact",
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"reactNamespace": "React",
|
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ES6",
|
"target": "ES6",
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
|
13066
pnpm-lock.yaml
13066
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user