migrate to preact

This commit is contained in:
Sebastian 2021-05-07 10:38:28 -03:00
parent b414de8533
commit 30f86f8748
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
22 changed files with 10753 additions and 2672 deletions

View File

@ -6,15 +6,8 @@ module.exports = {
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"preact",
],
settings: {
"react": {
"version": "16.9.6",
},
},
rules: {
"no-constant-condition": ["error", { "checkLoops": false }],
"prefer-const": ["warn", { destructuring: "all" }],

View File

@ -9,34 +9,53 @@
"private": false,
"scripts": {
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
"test": "jest ./tests",
"compile": "tsc && rollup -c"
},
"dependencies": {
"moment": "^2.29.1",
"@gnu-taler/taler-wallet-core": "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"
},
"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-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.1.0",
"@rollup/plugin-replace": "^2.3.4",
"@testing-library/preact": "^2.0.1",
"@types/chrome": "^0.0.128",
"@types/enzyme": "^3.10.8",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/jest": "^26.0.23",
"@types/node": "^14.14.22",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"ava": "3.15.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"enzyme": "^3.11.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"enzyme-adapter-preact-pure": "^3.1.0",
"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",
"rollup": "^2.37.1",
"rollup-plugin-ignore": "^1.0.9",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2",
"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"
}
}
}

View File

@ -24,7 +24,6 @@ import {
HttpRequestOptions,
HttpResponse,
Headers,
bytesToString,
} from "@gnu-taler/taler-wallet-core";
import { TalerErrorCode } from "@gnu-taler/taler-util";

View File

@ -21,9 +21,9 @@
/**
* Imports
*/
import React from "react";
import * as i18nCore from "@gnu-taler/taler-wallet-core";
import { Component, ComponentChildren, h, JSX, toChildArray, VNode } from "preact";
/**
* Convert template strings to a msgid
*/
@ -50,7 +50,7 @@ interface TranslateSwitchProps {
function stringifyChildren(children: any): string {
let n = 1;
const ss = React.Children.map(children, (c) => {
const ss = toChildArray(children).map((c) => {
if (typeof c === "string") {
return c;
}
@ -76,10 +76,10 @@ interface TranslateProps {
function getTranslatedChildren(
translation: string,
children: React.ReactNode,
): React.ReactNode[] {
children: ComponentChildren,
): ComponentChildren {
const tr = translation.split(/%(\d+)\$s/);
const childArray = React.Children.toArray(children);
const childArray = toChildArray(children);
// Merge consecutive string children.
const placeholderChildren = [];
for (let i = 0; i < childArray.length; i++) {
@ -117,15 +117,15 @@ function getTranslatedChildren(
* </Translate>
* ```
*/
export class Translate extends React.Component<TranslateProps, {}> {
render(): JSX.Element {
export class Translate extends Component<TranslateProps, any> {
render() {
const s = stringifyChildren(this.props.children);
const translation: string = i18nCore.jed.ngettext(s, s, 1);
const result = getTranslatedChildren(translation, this.props.children);
if (!this.props.wrap) {
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>
* ```
*/
export class TranslateSwitch extends React.Component<
export class TranslateSwitch extends Component<
TranslateSwitchProps,
void
> {
render(): JSX.Element {
let singular: React.ReactElement<TranslationPluralProps> | undefined;
let plural: React.ReactElement<TranslationPluralProps> | undefined;
let singular: VNode<TranslationPluralProps> | undefined;
let plural: VNode<TranslationPluralProps> | undefined;
const children = this.props.children;
if (children) {
React.Children.forEach(children, (child: any) => {
toChildArray(children).forEach((child: any) => {
if (child.type === TranslatePlural) {
plural = child;
}
@ -161,7 +161,7 @@ export class TranslateSwitch extends React.Component<
}
if (!singular || !plural) {
console.error("translation not found");
return React.createElement("span", {}, ["translation not found"]);
return h("span", {}, ["translation not found"]);
}
singular.props.target = this.props.target;
plural.props.target = this.props.target;
@ -178,7 +178,7 @@ interface TranslationPluralProps {
/**
* See [[TranslateSwitch]].
*/
export class TranslatePlural extends React.Component<
export class TranslatePlural extends Component<
TranslationPluralProps,
void
> {
@ -193,7 +193,7 @@ export class TranslatePlural extends React.Component<
/**
* See [[TranslateSwitch]].
*/
export class TranslateSingular extends React.Component<
export class TranslateSingular extends Component<
TranslationPluralProps,
void
> {

View File

@ -20,7 +20,7 @@
* @author Florian Dold <dold@taler.net>
*/
import ReactDOM from "react-dom";
import {render} from "preact";
import { createPopup } from "./pages/popup";
import { createWithdrawPage } from "./pages/withdraw";
import { createWelcomePage } from "./pages/welcome";
@ -63,7 +63,7 @@ function main(): void {
if (!container) {
throw Error("container not found, can't mount page contents");
}
ReactDOM.render(mainElement, container);
render(mainElement, container);
} catch (e) {
console.error("got error", e);
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;

View File

@ -27,7 +27,7 @@ import * as i18n from "../i18n";
import { renderAmount, ProgressButton } from "../renderHtml";
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 {
@ -39,10 +39,11 @@ import {
ContractTerms,
ConfirmPayResultType,
} from "@gnu-taler/taler-util";
import { JSX, VNode } from "preact";
function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>();
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>();
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(undefined);
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
const [numTries, setNumTries] = useState(0);
const [loading, setLoading] = useState(false);
@ -66,8 +67,8 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
}
if (payStatus.status === PreparePayResultType.PaymentPossible) {
let amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
let amountEffective: AmountJson = Amounts.parseOrThrow(
const amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
const amountEffective: AmountJson = Amounts.parseOrThrow(
payStatus.amountEffective,
);
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) {
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) {
merchantName = <strong>{contractTerms.merchant.name}</strong>;
} else {
@ -200,7 +201,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
) : (
<div>
<ProgressButton
loading={loading}
isLoading={loading}
disabled={insufficientBalance}
onClick={() => doPayment()}
>

View File

@ -14,6 +14,8 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { JSX } from "preact/jsx-runtime";
/**
* View and edit auditors.
*
@ -23,7 +25,6 @@
/**
* Imports.
*/
import * as React from "react";
export function makePaybackPage(): JSX.Element {
return <div>not implemented</div>;

View File

@ -41,18 +41,18 @@ import {
amountFractionalBase,
} from "@gnu-taler/taler-util";
import { abbrev, renderAmount, PageLink } from "../renderHtml";
import { renderAmount, PageLink } from "../renderHtml";
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 { JSXInternal } from "preact/src/jsx";
import { Component, ComponentChild, ComponentChildren, JSX, toChildArray, VNode } from "preact";
// 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 {
window.location.hash = s;
}
@ -85,21 +85,21 @@ class Router extends React.Component<any, any> {
render(): JSX.Element {
const route = window.location.hash.substring(1);
console.log("rendering route", route);
let defaultChild: React.ReactChild | null = null;
let foundChild: React.ReactChild | null = null;
React.Children.forEach(this.props.children, (child) => {
let defaultChild: ComponentChild | null = null;
let foundChild: ComponentChild | null = null;
toChildArray(this.props.children).forEach((child) => {
const childProps: any = (child as any).props;
if (!childProps) {
return;
}
if (childProps.default) {
defaultChild = child as React.ReactChild;
defaultChild = child;
}
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) {
throw Error("unknown route");
}
@ -110,7 +110,7 @@ class Router extends React.Component<any, any> {
interface TabProps {
target: string;
children?: React.ReactNode;
children?: ComponentChildren;
}
function Tab(props: TabProps): JSX.Element {
@ -118,7 +118,7 @@ function Tab(props: TabProps): JSX.Element {
if (props.target === Router.getRoute()) {
cssClass = "active";
}
const onClick = (e: React.MouseEvent<HTMLAnchorElement>): void => {
const onClick = (e: JSXInternal.TargetedMouseEvent<HTMLAnchorElement>): void => {
Router.setRoute(props.target);
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;
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 gotError = false;
private canceler: (() => void) | undefined = undefined;
@ -323,7 +323,7 @@ function TransactionAmount(props: TransactionAmountProps): JSX.Element {
case "unknown":
sign = "";
}
const style: React.CSSProperties = {
const style: JSX.AllCSSProperties = {
marginLeft: "auto",
display: "flex",
flexDirection: "column",
@ -476,7 +476,7 @@ function TransactionItem(props: { tx: Transaction }): JSX.Element {
function WalletHistory(props: any): JSX.Element {
const [transactions, setTransactions] = useState<
TransactionsResponse | undefined
>();
>(undefined);
useEffect(() => {
const fetchData = async (): Promise<void> => {
@ -484,7 +484,6 @@ function WalletHistory(props: any): JSX.Element {
setTransactions(res);
};
fetchData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if (!transactions) {
@ -495,14 +494,14 @@ function WalletHistory(props: any): JSX.Element {
return (
<div>
{txs.map((tx) => (
<TransactionItem tx={tx} />
{txs.map((tx,i) => (
<TransactionItem key={i} tx={tx} />
))}
</div>
);
}
class WalletSettings extends React.Component<any, any> {
class WalletSettings extends Component<any, any> {
render(): JSX.Element {
return (
<div>
@ -522,14 +521,14 @@ function reload(): void {
}
}
function confirmReset(): void {
async function confirmReset(): Promise<void> {
if (
confirm(
"Do you want to IRREVOCABLY DESTROY everything inside your" +
" wallet and LOSE ALL YOUR COINS?",
)
) {
wxApi.resetDb();
await wxApi.resetDb();
window.close();
}
}
@ -554,14 +553,14 @@ function openExtensionPage(page: string) {
};
}
function openTab(page: string) {
return (evt: React.SyntheticEvent<any>) => {
evt.preventDefault();
chrome.tabs.create({
url: page,
});
};
}
// function openTab(page: string) {
// return (evt: React.SyntheticEvent<any>) => {
// evt.preventDefault();
// chrome.tabs.create({
// url: page,
// });
// };
// }
function makeExtensionUrlWithParams(
url: string,

View File

@ -20,17 +20,18 @@
* @author Florian Dold
*/
import React, { useEffect, useState } from "react";
import * as wxApi from "../wxApi";
import { AmountView } from "../renderHtml";
import {
PurchaseDetails,
ApplyRefundResponse,
Amounts,
} 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 {
const [applyResult, setApplyResult] = useState<ApplyRefundResponse>();
const [applyResult, setApplyResult] = useState<ApplyRefundResponse|undefined>(undefined);
const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
useEffect(() => {

View File

@ -20,8 +20,7 @@
* @author Florian Dold
*/
import * as React from "react";
import { Component, JSX } from "preact";
import * as wxApi from "../wxApi";
interface State {
@ -36,7 +35,7 @@ interface State {
resetRequired: boolean;
}
class ResetNotification extends React.Component<any, State> {
class ResetNotification extends Component<any, State> {
constructor(props: any) {
super(props);
this.state = { checked: false, resetRequired: true };
@ -50,7 +49,7 @@ class ResetNotification extends React.Component<any, State> {
if (this.state.resetRequired) {
return (
<div>
<h1>Manual Reset Reqired</h1>
<h1>Manual Reset Required</h1>
<p>
The wallet&apos;s database in your browser is incompatible with the{" "}
currently installed wallet. Please reset manually.
@ -63,7 +62,9 @@ class ResetNotification extends React.Component<any, State> {
id="check"
type="checkbox"
checked={this.state.checked}
onChange={(e) => this.setState({ checked: e.target.checked })}
onChange={() => {
this.setState(prev => ({ checked: prev.checked }))
}}
/>{" "}
<label htmlFor="check">
I understand that I will lose all my data

View File

@ -14,6 +14,8 @@
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.
*
@ -23,8 +25,6 @@
/**
* Imports.
*/
import * as React from "react";
export function createReturnCoinsPage(): JSX.Element {
return <span>Not implemented yet.</span>;
}

View File

@ -20,17 +20,17 @@
* @author Florian Dold <dold@taler.net>
*/
import * as React from "react";
import { useEffect, useState } from "react";
import { useEffect, useState } from "preact/hooks";
import { PrepareTipResult } from "@gnu-taler/taler-util";
import { AmountView } from "../renderHtml";
import * as wxApi from "../wxApi";
import { JSX } from "preact/jsx-runtime";
function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
const [updateCounter, setUpdateCounter] = useState<number>(0);
const [prepareTipResult, setPrepareTipResult] = useState<
PrepareTipResult | undefined
>();
>(undefined);
const [tipIgnored, setTipIgnored] = useState(false);

View File

@ -20,13 +20,14 @@
* @author Florian Dold
*/
import React, { useState, useEffect } from "react";
import { useState, useEffect } from "preact/hooks";
import { getDiagnostics } from "../wxApi";
import { PageLink } from "../renderHtml";
import * as wxApi from "../wxApi";
import { getPermissionsApi } from "../compat";
import { extendedPermissions } from "../permissions";
import { WalletDiagnostics } from "@gnu-taler/taler-util";
import { JSX } from "preact/jsx-runtime";
function Diagnostics(): JSX.Element | null {
const [timedOut, setTimedOut] = useState(false);
@ -102,9 +103,9 @@ export function PermissionsCheckbox(): JSX.Element {
const [extendedPermissionsEnabled, setExtendedPermissionsEnabled] = useState(
false,
);
async function handleExtendedPerm(requestedVal: boolean): Promise<void> {
async function handleExtendedPerm(): Promise<void> {
let nextVal: boolean | undefined;
if (requestedVal) {
if (extendedPermissionsEnabled) {
const granted = await new Promise<boolean>((resolve, reject) => {
// We set permissions here, since apparently FF wants this to be done
// as the result of an input event ...
@ -141,7 +142,7 @@ export function PermissionsCheckbox(): JSX.Element {
<div>
<input
checked={extendedPermissionsEnabled}
onChange={(x) => handleExtendedPerm(x.target.checked)}
onChange={() => handleExtendedPerm()}
type="checkbox"
id="checkbox-perm"
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }}

View File

@ -25,19 +25,20 @@ import * as i18n from "../i18n";
import { renderAmount } from "../renderHtml";
import React, { useState, useEffect } from "react";
import { useState, useEffect } from "preact/hooks";
import {
acceptWithdrawal,
onUpdateNotification,
getWithdrawalDetailsForUri,
} from "../wxApi";
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
import { JSX } from "preact/jsx-runtime";
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>();
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
const [selectedExchange, setSelectedExchange] = useState<
string | undefined
>();
>(undefined);
const talerWithdrawUri = props.talerWithdrawUri;
const [cancelled, setCancelled] = useState(false);
const [selecting, setSelecting] = useState(false);
@ -48,7 +49,6 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
return onUpdateNotification(() => {
setUpdateCounter(updateCounter + 1);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {

View File

@ -23,12 +23,13 @@
/**
* Imports.
*/
import React from "react";
import {
AmountJson,
Amounts,
amountFractionalBase,
} 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
@ -87,7 +88,7 @@ interface CollapsibleProps {
* Component that shows/hides its children when clicking
* a heading.
*/
export class Collapsible extends React.Component<
export class Collapsible extends Component<
CollapsibleProps,
CollapsibleState
> {
@ -139,24 +140,18 @@ export function ExpanderText({ text }: ExpanderTextProps): JSX.Element {
return <span>{text}</span>;
}
export interface LoadingButtonProps {
loading: boolean;
export interface LoadingButtonProps extends JSX.HTMLAttributes<HTMLButtonElement> {
isLoading: boolean;
}
export function ProgressButton(
props: React.PropsWithChildren<LoadingButtonProps> &
React.DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
>,
): JSX.Element {
export function ProgressButton({isLoading, ...rest}: LoadingButtonProps): JSX.Element {
return (
<button
className="pure-button pure-button-primary"
type="button"
{...props}
{...rest}
>
{props.loading ? (
{isLoading ? (
<span>
<object
className="svg-icon svg-baseline"
@ -164,13 +159,13 @@ export function ProgressButton(
/>
</span>
) : null}{" "}
{props.children}
{rest.children}
</button>
);
}
export function PageLink(
props: React.PropsWithChildren<{ pageName: string }>,
props: { pageName: string, children?: ComponentChildren },
): JSX.Element {
const url = chrome.extension.getURL(`/${props.pageName}`);
return (

View File

@ -146,7 +146,7 @@ async function dispatch(
}
break;
}
default:
default: {
const w = currentWallet;
if (!w) {
r = {
@ -163,6 +163,7 @@ async function dispatch(
}
r = await w.handleCoreApiRequest(req.operation, req.id, req.payload);
break;
}
}
try {

View File

@ -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';

View File

@ -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)) + ';';
},
};

View File

@ -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

View File

@ -14,12 +14,11 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import test from "ava";
import { internalSetStrings, str, Translate, strings } from "./i18n";
import React from "react";
import { render } from "enzyme";
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
// import * as test from "ava";
import { internalSetStrings, str, Translate } from "../src/i18n";
import { render, configure } from "enzyme";
import Adapter from 'enzyme-adapter-preact-pure';
import { h } from "preact";
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.
const strAlias = str;
const TranslateAlias = Translate;
internalSetStrings(testStrings);
t.is(strAlias`str1`, "foo1");
t.is(strAlias`str2`, "str2");
expect(strAlias`str1`).toEqual("foo1");
expect(strAlias`str2`).toEqual("str2");
const a = "a";
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>);
t.is(r.text(), "foo1");
expect(r.text()).toEqual("foo1");
const r2 = render(
<TranslateAlias>
str3 <span>{a}</span> / <span>{b}</span>
</TranslateAlias>,
);
t.is(r2.text(), "foo3 b ; a");
expect(r2.text()).toEqual("foo3 b ; a");
t.pass();
done();
});
test("existing str translation", (t) => {
internalSetStrings(strings);
t.pass();
});
// test.default("existing str translation", (t) => {
// internalSetStrings(strings);
// t.pass();
// });

View File

@ -2,9 +2,9 @@
"compilerOptions": {
"composite": true,
"lib": ["es6", "DOM"],
"jsx": "react",
"jsx": "react-jsx",
"jsxImportSource": "preact",
"moduleResolution": "Node",
"reactNamespace": "React",
"module": "ESNext",
"target": "ES6",
"noImplicitAny": true,

File diff suppressed because it is too large Load Diff