replace jest with mocha
This commit is contained in:
parent
2e71117f59
commit
9f8139e09b
@ -45,7 +45,6 @@
|
|||||||
"@storybook/preact": "^6.3.12",
|
"@storybook/preact": "^6.3.12",
|
||||||
"@storybook/preset-scss": "^1.0.3",
|
"@storybook/preset-scss": "^1.0.3",
|
||||||
"@types/enzyme": "^3.10.10",
|
"@types/enzyme": "^3.10.10",
|
||||||
"@types/jest": "^27.0.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
||||||
"@typescript-eslint/parser": "^5.3.0",
|
"@typescript-eslint/parser": "^5.3.0",
|
||||||
"bulma": "^0.9.3",
|
"bulma": "^0.9.3",
|
||||||
@ -55,20 +54,11 @@
|
|||||||
"enzyme-adapter-preact-pure": "^3.2.0",
|
"enzyme-adapter-preact-pure": "^3.2.0",
|
||||||
"eslint": "^8.1.0",
|
"eslint": "^8.1.0",
|
||||||
"eslint-config-preact": "^1.2.0",
|
"eslint-config-preact": "^1.2.0",
|
||||||
"jest": "^27.3.1",
|
|
||||||
"jest-preset-preact": "^4.0.5",
|
|
||||||
"jssha": "^3.2.0",
|
"jssha": "^3.2.0",
|
||||||
"preact-cli": "^3.3.1",
|
"preact-cli": "^3.3.1",
|
||||||
"sass": "1.32.13",
|
"sass": "1.32.13",
|
||||||
"sass-loader": "^10",
|
"sass-loader": "^10",
|
||||||
"sirv-cli": "^1.0.14",
|
"sirv-cli": "^1.0.14",
|
||||||
"typescript": "^4.4.4"
|
"typescript": "^4.4.4"
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"preset": "jest-preset-preact",
|
|
||||||
"setupFiles": [
|
|
||||||
"<rootDir>/tests/__mocks__/browserMocks.ts",
|
|
||||||
"<rootDir>/tests/__mocks__/setupTests.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,14 +48,14 @@ module.exports = {
|
|||||||
webpackFinal: (config) => {
|
webpackFinal: (config) => {
|
||||||
// should be removed after storybook 6.3
|
// should be removed after storybook 6.3
|
||||||
// https://github.com/storybookjs/storybook/issues/12853#issuecomment-821576113
|
// https://github.com/storybookjs/storybook/issues/12853#issuecomment-821576113
|
||||||
// removing workaround since this creates another problem
|
// removing workaround since this creates another problem
|
||||||
// https://github.com/storybookjs/storybook/issues/16623
|
// https://github.com/storybookjs/storybook/issues/16623
|
||||||
// https://github.com/nodejs/node/issues/33460
|
// https://github.com/nodejs/node/issues/33460
|
||||||
// FIXME: remove this comments in 2022 if no problem arise
|
// FIXME: remove this comments in 2022 if no problem arise
|
||||||
// config.resolve.alias = {
|
// config.resolve.alias = {
|
||||||
// react: "preact/compat",
|
// react: "preact/compat",
|
||||||
// "react-dom": "preact/compat",
|
// "react-dom": "preact/compat",
|
||||||
// };
|
// };
|
||||||
|
|
||||||
// we need to add @linaria loader AFTER the babel-loader
|
// we need to add @linaria loader AFTER the babel-loader
|
||||||
// https://github.com/callstack/linaria/blob/master/docs/BUNDLERS_INTEGRATION.md#webpack
|
// https://github.com/callstack/linaria/blob/master/docs/BUNDLERS_INTEGRATION.md#webpack
|
||||||
@ -74,7 +74,7 @@ module.exports = {
|
|||||||
babelOptions: {
|
babelOptions: {
|
||||||
presets: config.module.rules[0].use[0].options.presets,
|
presets: config.module.rules[0].use[0].options.presets,
|
||||||
}
|
}
|
||||||
// Pass the current babel options to linaria's babel instance
|
// Pass the current babel options to linaria's babel instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -21,7 +21,6 @@ import { TranslationProvider } from '../src/context/translation'
|
|||||||
import { PopupBox, WalletBox } from '../src/components/styled'
|
import { PopupBox, WalletBox } from '../src/components/styled'
|
||||||
export const parameters = {
|
export const parameters = {
|
||||||
controls: { expanded: true },
|
controls: { expanded: true },
|
||||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const globalTypes = {
|
export const globalTypes = {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# This file is in the public domain.
|
# This file is in the public domain.
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
mv node_modules{,_saved}
|
||||||
rm -rf dist lib tsconfig.tsbuildinfo
|
rm -rf dist lib tsconfig.tsbuildinfo
|
||||||
(cd ../.. && rm -rf build/web && ./contrib/build-fast-web.sh)
|
(cd ../.. && rm -rf build/web && ./contrib/build-fast-web.sh)
|
||||||
rm -rf extension/
|
rm -rf extension/
|
||||||
@ -9,3 +10,4 @@ rm -rf extension/
|
|||||||
(cd extension/v2 && unzip taler*.zip)
|
(cd extension/v2 && unzip taler*.zip)
|
||||||
(cd extension/v3 && unzip taler*.zip)
|
(cd extension/v3 && unzip taler*.zip)
|
||||||
|
|
||||||
|
mv node_modules{_saved,}
|
||||||
|
@ -9,8 +9,9 @@
|
|||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
||||||
"test": "jest ./tests",
|
"test": "mocha --enable-source-maps 'dist/**/*.test.js'",
|
||||||
"compile": "tsc && rollup -c",
|
"test:coverage": "nyc pnpm test",
|
||||||
|
"compile": "rollup -c -m",
|
||||||
"build-storybook": "build-storybook",
|
"build-storybook": "build-storybook",
|
||||||
"storybook": "start-storybook -s . -p 6006",
|
"storybook": "start-storybook -s . -p 6006",
|
||||||
"pretty": "prettier --write src",
|
"pretty": "prettier --write src",
|
||||||
@ -41,22 +42,21 @@
|
|||||||
"@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",
|
||||||
|
"@rollup/plugin-typescript": "^8.3.0",
|
||||||
"@storybook/addon-a11y": "^6.2.9",
|
"@storybook/addon-a11y": "^6.2.9",
|
||||||
"@storybook/addon-essentials": "^6.2.9",
|
"@storybook/addon-essentials": "^6.2.9",
|
||||||
"@storybook/preact": "^6.2.9",
|
"@storybook/preact": "6.4.9",
|
||||||
"@testing-library/preact": "^2.0.1",
|
"@testing-library/preact": "^2.0.1",
|
||||||
|
"@testing-library/preact-hooks": "^1.1.0",
|
||||||
"@types/chrome": "^0.0.128",
|
"@types/chrome": "^0.0.128",
|
||||||
"@types/enzyme": "^3.10.10",
|
|
||||||
"@types/history": "^4.7.8",
|
"@types/history": "^4.7.8",
|
||||||
"@types/jest": "^26.0.23",
|
"@types/mocha": "^9.0.0",
|
||||||
"@types/node": "^14.14.22",
|
"@types/node": "^14.14.22",
|
||||||
"ava": "3.15.0",
|
"ava": "3.15.0",
|
||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||||
"enzyme": "^3.11.0",
|
"mocha": "^9.1.3",
|
||||||
"enzyme-adapter-preact-pure": "^3.1.0",
|
"nyc": "^15.1.0",
|
||||||
"jest": "^26.6.3",
|
|
||||||
"jest-preset-preact": "^4.0.2",
|
|
||||||
"preact-cli": "^3.0.5",
|
"preact-cli": "^3.0.5",
|
||||||
"preact-render-to-string": "^5.1.19",
|
"preact-render-to-string": "^5.1.19",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
@ -68,17 +68,10 @@
|
|||||||
"storybook-dark-mode": "^1.0.8",
|
"storybook-dark-mode": "^1.0.8",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.3"
|
||||||
},
|
},
|
||||||
"jest": {
|
"nyc": {
|
||||||
"preset": "jest-preset-preact",
|
"include": [
|
||||||
"setupFiles": [
|
"**"
|
||||||
"<rootDir>/tests/__mocks__/setupTests.ts"
|
|
||||||
],
|
],
|
||||||
"moduleNameMapper": {
|
"exclude": []
|
||||||
"\\.(css|less)$": "identity-obj-proxy",
|
|
||||||
"@linaria/react": "<rootDir>/tests/__mocks__/linaria.ts"
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,48 +8,77 @@ import nodeResolve from "@rollup/plugin-node-resolve";
|
|||||||
import replace from "@rollup/plugin-replace";
|
import replace from "@rollup/plugin-replace";
|
||||||
import css from 'rollup-plugin-css-only';
|
import css from 'rollup-plugin-css-only';
|
||||||
import ignore from "rollup-plugin-ignore";
|
import ignore from "rollup-plugin-ignore";
|
||||||
|
import typescript from '@rollup/plugin-typescript';
|
||||||
|
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
function fromDir(startPath, regex) {
|
||||||
|
if (!fs.existsSync(startPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const files = fs.readdirSync(startPath);
|
||||||
|
const result = files.flatMap(file => {
|
||||||
|
const filename = path.join(startPath, file);
|
||||||
|
|
||||||
|
const stat = fs.lstatSync(filename);
|
||||||
|
if (stat.isDirectory()) {
|
||||||
|
return fromDir(filename, regex);
|
||||||
|
}
|
||||||
|
else if (regex.test(filename)) {
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
}).filter(x => !!x)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
const makePlugins = () => [
|
const makePlugins = () => [
|
||||||
alias({
|
typescript({
|
||||||
entries: [
|
outputToFilesystem: false,
|
||||||
{ find: 'react', replacement: 'preact/compat' },
|
}),
|
||||||
{ find: 'react-dom', replacement: 'preact/compat' }
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
|
|
||||||
ignore(["module", "os"]),
|
alias({
|
||||||
nodeResolve({
|
entries: [
|
||||||
browser: true,
|
{ find: 'react', replacement: 'preact/compat' },
|
||||||
preferBuiltins: true,
|
{ find: 'react-dom', replacement: 'preact/compat' }
|
||||||
}),
|
]
|
||||||
|
}),
|
||||||
|
|
||||||
//terser(),
|
ignore(["module", "os"]),
|
||||||
|
nodeResolve({
|
||||||
|
browser: true,
|
||||||
|
preferBuiltins: true,
|
||||||
|
}),
|
||||||
|
|
||||||
|
//terser(),
|
||||||
|
|
||||||
|
|
||||||
replace({
|
replace({
|
||||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||||
"__filename": "'__webextension__'",
|
// "__filename": "'__webextension__'",
|
||||||
}),
|
preventAssignment: true
|
||||||
|
}),
|
||||||
|
|
||||||
commonjs({
|
commonjs({
|
||||||
include: [/node_modules/, /dist/],
|
include: [/node_modules/, /dist/],
|
||||||
extensions: [".js"],
|
extensions: [".js"],
|
||||||
ignoreGlobal: true,
|
ignoreGlobal: true,
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
json(),
|
json(),
|
||||||
image(),
|
image(),
|
||||||
|
|
||||||
linaria({
|
linaria({
|
||||||
sourceMap: process.env.NODE_ENV !== 'production',
|
sourceMap: process.env.NODE_ENV !== 'production',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
const webExtensionWalletEntryPoint = {
|
const webExtensionWalletEntryPoint = {
|
||||||
input: "lib/walletEntryPoint.js",
|
input: "src/walletEntryPoint.tsx",
|
||||||
output: {
|
output: {
|
||||||
file: "dist/walletEntryPoint.js",
|
file: "dist/walletEntryPoint.js",
|
||||||
format: "iife",
|
format: "iife",
|
||||||
@ -60,12 +89,12 @@ const webExtensionWalletEntryPoint = {
|
|||||||
...makePlugins(),
|
...makePlugins(),
|
||||||
css({
|
css({
|
||||||
output: 'walletEntryPoint.css',
|
output: 'walletEntryPoint.css',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const webExtensionPopupEntryPoint = {
|
const webExtensionPopupEntryPoint = {
|
||||||
input: "lib/popupEntryPoint.js",
|
input: "src/popupEntryPoint.tsx",
|
||||||
output: {
|
output: {
|
||||||
file: "dist/popupEntryPoint.js",
|
file: "dist/popupEntryPoint.js",
|
||||||
format: "iife",
|
format: "iife",
|
||||||
@ -76,12 +105,12 @@ const webExtensionPopupEntryPoint = {
|
|||||||
...makePlugins(),
|
...makePlugins(),
|
||||||
css({
|
css({
|
||||||
output: 'popupEntryPoint.css',
|
output: 'popupEntryPoint.css',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const webExtensionBackgroundPageScript = {
|
const webExtensionBackgroundPageScript = {
|
||||||
input: "lib/background.js",
|
input: "src/background.ts",
|
||||||
output: {
|
output: {
|
||||||
file: "dist/background.js",
|
file: "dist/background.js",
|
||||||
format: "iife",
|
format: "iife",
|
||||||
@ -92,7 +121,7 @@ const webExtensionBackgroundPageScript = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const webExtensionCryptoWorker = {
|
const webExtensionCryptoWorker = {
|
||||||
input: "lib/browserWorkerEntry.js",
|
input: "src/browserWorkerEntry.ts",
|
||||||
output: {
|
output: {
|
||||||
file: "dist/browserWorkerEntry.js",
|
file: "dist/browserWorkerEntry.js",
|
||||||
format: "iife",
|
format: "iife",
|
||||||
@ -102,9 +131,26 @@ const webExtensionCryptoWorker = {
|
|||||||
plugins: makePlugins(),
|
plugins: makePlugins(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const tests = fromDir('./src', /.test.ts$/).map(test => ({
|
||||||
|
input: test,
|
||||||
|
output: {
|
||||||
|
file: test.replace(/^src/, 'dist').replace(/\.ts$/, '.js'),
|
||||||
|
format: "iife",
|
||||||
|
exports: "none",
|
||||||
|
name: test,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
...makePlugins(),
|
||||||
|
css({
|
||||||
|
output: 'walletEntryPoint.css',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}))
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
webExtensionPopupEntryPoint,
|
webExtensionPopupEntryPoint,
|
||||||
webExtensionWalletEntryPoint,
|
webExtensionWalletEntryPoint,
|
||||||
webExtensionBackgroundPageScript,
|
webExtensionBackgroundPageScript,
|
||||||
webExtensionCryptoWorker,
|
webExtensionCryptoWorker,
|
||||||
|
...tests,
|
||||||
];
|
];
|
||||||
|
23
packages/taler-wallet-webextension/run-test-in-browser.html
Normal file
23
packages/taler-wallet-webextension/run-test-in-browser.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Mocha Tests</title>
|
||||||
|
<link rel="stylesheet" href="node_modules/mocha/mocha.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="mocha"></div>
|
||||||
|
<script src="node_modules/mocha/mocha.js"></script>
|
||||||
|
<script>mocha.setup('bdd')</script>
|
||||||
|
|
||||||
|
<!-- load code you want to test here -->
|
||||||
|
|
||||||
|
<!-- script src="dist/stories.test.js"></script -->
|
||||||
|
<script src="dist/hooks/useTalerActionURL.test.js"></script>
|
||||||
|
<!-- load your test files here -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
mocha.run();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -37,7 +37,7 @@ export enum Pages {
|
|||||||
deposit = "/deposit/:currency",
|
deposit = "/deposit/:currency",
|
||||||
settings = "/settings",
|
settings = "/settings",
|
||||||
dev = "/dev",
|
dev = "/dev",
|
||||||
cta = "/cta",
|
cta = "/cta/:action",
|
||||||
backup = "/backup",
|
backup = "/backup",
|
||||||
history = "/history",
|
history = "/history",
|
||||||
transaction = "/transaction/:tid",
|
transaction = "/transaction/:tid",
|
||||||
|
24
packages/taler-wallet-webextension/src/api/browser.ts
Normal file
24
packages/taler-wallet-webextension/src/api/browser.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
export async function findTalerUriInActiveTab(): Promise<string | undefined> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.tabs.executeScript(
|
||||||
|
{
|
||||||
|
code: `
|
||||||
|
(() => {
|
||||||
|
let x = document.querySelector("a[href^='taler://'") || document.querySelector("a[href^='taler+http://'");
|
||||||
|
return x ? x.href.toString() : null;
|
||||||
|
})();
|
||||||
|
`,
|
||||||
|
allFrames: false,
|
||||||
|
},
|
||||||
|
(result) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error(chrome.runtime.lastError);
|
||||||
|
resolve(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(result[0]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
@ -1,64 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
(C) 2017 INRIA
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.getPermissionsApi = exports.isNode = exports.isFirefox = void 0;
|
|
||||||
/**
|
|
||||||
* Compatibility helpers needed for browsers that don't implement
|
|
||||||
* WebExtension APIs consistently.
|
|
||||||
*/
|
|
||||||
function isFirefox() {
|
|
||||||
const rt = chrome.runtime;
|
|
||||||
if (typeof rt.getBrowserInfo === "function") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
exports.isFirefox = isFirefox;
|
|
||||||
/**
|
|
||||||
* Check if we are running under nodejs.
|
|
||||||
*/
|
|
||||||
function isNode() {
|
|
||||||
return typeof process !== "undefined" && process.release.name === "node";
|
|
||||||
}
|
|
||||||
exports.isNode = isNode;
|
|
||||||
function getPermissionsApi() {
|
|
||||||
const myBrowser = globalThis.browser;
|
|
||||||
if (
|
|
||||||
typeof myBrowser === "object" &&
|
|
||||||
typeof myBrowser.permissions === "object"
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
addPermissionsListener: () => {
|
|
||||||
// Not supported yet.
|
|
||||||
},
|
|
||||||
contains: myBrowser.permissions.contains,
|
|
||||||
request: myBrowser.permissions.request,
|
|
||||||
remove: myBrowser.permissions.remove,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
addPermissionsListener: chrome.permissions.onAdded.addListener.bind(
|
|
||||||
chrome.permissions.onAdded,
|
|
||||||
),
|
|
||||||
contains: chrome.permissions.contains,
|
|
||||||
request: chrome.permissions.request,
|
|
||||||
remove: chrome.permissions.remove,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exports.getPermissionsApi = getPermissionsApi;
|
|
||||||
//# sourceMappingURL=compat.js.map
|
|
@ -19,7 +19,7 @@ import { h, VNode } from "preact";
|
|||||||
import {
|
import {
|
||||||
ButtonPrimary,
|
ButtonPrimary,
|
||||||
TableWithRoundRows as TableWithRoundedRows,
|
TableWithRoundRows as TableWithRoundedRows,
|
||||||
} from "./styled/index";
|
} from "./styled";
|
||||||
|
|
||||||
export function BalanceTable({
|
export function BalanceTable({
|
||||||
balances,
|
balances,
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
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 { Outlined, StyledCheckboxLabel } from "./styled/index";
|
import { Outlined, StyledCheckboxLabel } from "./styled";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -32,7 +32,8 @@ export function ErrorTalerOperation({
|
|||||||
|
|
||||||
if (!title || !error) return null;
|
if (!title || !error) return null;
|
||||||
// const errorCode: number | undefined = (error.details as any)?.errorResponse?.code
|
// const errorCode: number | undefined = (error.details as any)?.errorResponse?.code
|
||||||
const errorHint: string | undefined = (error.details as any)?.errorResponse?.hint
|
const errorHint: string | undefined = (error.details as any)?.errorResponse
|
||||||
|
?.hint;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ErrorBox style={{ paddingTop: 0, paddingBottom: 0 }}>
|
<ErrorBox style={{ paddingTop: 0, paddingBottom: 0 }}>
|
||||||
@ -53,11 +54,11 @@ export function ErrorTalerOperation({
|
|||||||
<div style={{ padding: 5, textAlign: "left" }}>
|
<div style={{ padding: 5, textAlign: "left" }}>
|
||||||
<div>{error.message}</div>
|
<div>{error.message}</div>
|
||||||
</div>
|
</div>
|
||||||
{errorHint &&
|
{errorHint && (
|
||||||
<div style={{ padding: 5, textAlign: "left" }}>
|
<div style={{ padding: 5, textAlign: "left" }}>
|
||||||
<div>{errorHint}</div>
|
<div>{errorHint}</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
)}
|
||||||
{devMode && (
|
{devMode && (
|
||||||
<div style={{ textAlign: "left", overflowX: "auto" }}>
|
<div style={{ textAlign: "left", overflowX: "auto" }}>
|
||||||
<pre>{JSON.stringify(error, undefined, 2)}</pre>
|
<pre>{JSON.stringify(error, undefined, 2)}</pre>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { NiceSelect } from "./styled/index";
|
import { NiceSelect } from "./styled";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
value?: string;
|
value?: string;
|
||||||
|
@ -34,7 +34,7 @@ import {
|
|||||||
SmallLightText,
|
SmallLightText,
|
||||||
LargeText,
|
LargeText,
|
||||||
LightText,
|
LightText,
|
||||||
} from "./styled/index";
|
} from "./styled";
|
||||||
import { Time } from "./Time";
|
import { Time } from "./Time";
|
||||||
|
|
||||||
export function TransactionItem(props: {
|
export function TransactionItem(props: {
|
||||||
|
49
packages/taler-wallet-webextension/src/context/iocContext.ts
Normal file
49
packages/taler-wallet-webextension/src/context/iocContext.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
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 { createContext, h, VNode } from "preact";
|
||||||
|
import { useContext } from "preact/hooks";
|
||||||
|
import { findTalerUriInActiveTab } from "../api/browser";
|
||||||
|
|
||||||
|
interface Type {
|
||||||
|
findTalerUriInActiveTab: () => Promise<string | undefined>;
|
||||||
|
}
|
||||||
|
const Context = createContext<Type>({
|
||||||
|
findTalerUriInActiveTab: async () => undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inversion of control Context
|
||||||
|
*
|
||||||
|
* This context act as a proxy between API that need to be replaced in
|
||||||
|
* different environments
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const useIocContext = (): Type => useContext(Context);
|
||||||
|
|
||||||
|
export const IoCProviderForTesting = ({ value, children }: { value: Type, children: any }): VNode => {
|
||||||
|
return h(Context.Provider, { value, children });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IoCProviderForRuntime = ({ children }: { children: any }): VNode => {
|
||||||
|
return h(Context.Provider, { value: { findTalerUriInActiveTab }, children });
|
||||||
|
};
|
@ -34,13 +34,13 @@ export const NoBalance = createExample(TestedComponent, {
|
|||||||
status: PreparePayResultType.InsufficientBalance,
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -50,13 +50,13 @@ export const NoEnoughBalance = createExample(TestedComponent, {
|
|||||||
status: PreparePayResultType.InsufficientBalance,
|
status: PreparePayResultType.InsufficientBalance,
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
},
|
},
|
||||||
balance: {
|
balance: {
|
||||||
@ -67,42 +67,40 @@ export const NoEnoughBalance = createExample(TestedComponent, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const PaymentPossible = createExample(TestedComponent, {
|
export const PaymentPossible = createExample(TestedComponent, {
|
||||||
uri:
|
uri: "taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
||||||
"taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.PaymentPossible,
|
status: PreparePayResultType.PaymentPossible,
|
||||||
amountEffective: "USD:10",
|
amountEffective: "USD:10",
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
nonce: "123213123",
|
nonce: "123213123",
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
contractTermsHash: "123456",
|
contractTermsHash: "123456",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PaymentPossibleWithFee = createExample(TestedComponent, {
|
export const PaymentPossibleWithFee = createExample(TestedComponent, {
|
||||||
uri:
|
uri: "taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
||||||
"taler://pay/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0",
|
|
||||||
payStatus: {
|
payStatus: {
|
||||||
status: PreparePayResultType.PaymentPossible,
|
status: PreparePayResultType.PaymentPossible,
|
||||||
amountEffective: "USD:10.20",
|
amountEffective: "USD:10.20",
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
noncePriv: "",
|
noncePriv: "",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
nonce: "123213123",
|
nonce: "123213123",
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
contractTermsHash: "123456",
|
contractTermsHash: "123456",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
},
|
},
|
||||||
@ -113,7 +111,7 @@ export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
|||||||
status: PreparePayResultType.AlreadyConfirmed,
|
status: PreparePayResultType.AlreadyConfirmed,
|
||||||
amountEffective: "USD:10",
|
amountEffective: "USD:10",
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
@ -121,7 +119,7 @@ export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
|||||||
"congratulations! you are looking at the fulfillment message! ",
|
"congratulations! you are looking at the fulfillment message! ",
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
contractTermsHash: "123456",
|
contractTermsHash: "123456",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
paid: false,
|
paid: false,
|
||||||
@ -135,13 +133,13 @@ export const AlreadyConfirmedWithoutFullfilment = createExample(
|
|||||||
status: PreparePayResultType.AlreadyConfirmed,
|
status: PreparePayResultType.AlreadyConfirmed,
|
||||||
amountEffective: "USD:10",
|
amountEffective: "USD:10",
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
contractTermsHash: "123456",
|
contractTermsHash: "123456",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
paid: false,
|
paid: false,
|
||||||
@ -154,7 +152,7 @@ export const AlreadyPaid = createExample(TestedComponent, {
|
|||||||
status: PreparePayResultType.AlreadyConfirmed,
|
status: PreparePayResultType.AlreadyConfirmed,
|
||||||
amountEffective: "USD:10",
|
amountEffective: "USD:10",
|
||||||
amountRaw: "USD:10",
|
amountRaw: "USD:10",
|
||||||
contractTerms: ({
|
contractTerms: {
|
||||||
merchant: {
|
merchant: {
|
||||||
name: "someone",
|
name: "someone",
|
||||||
},
|
},
|
||||||
@ -162,7 +160,7 @@ export const AlreadyPaid = createExample(TestedComponent, {
|
|||||||
"congratulations! you are looking at the fulfillment message! ",
|
"congratulations! you are looking at the fulfillment message! ",
|
||||||
summary: "some beers",
|
summary: "some beers",
|
||||||
amount: "USD:10",
|
amount: "USD:10",
|
||||||
} as Partial<ContractTerms>) as any,
|
} as Partial<ContractTerms> as any,
|
||||||
contractTermsHash: "123456",
|
contractTermsHash: "123456",
|
||||||
proposalId: "proposal1234",
|
proposalId: "proposal1234",
|
||||||
paid: true,
|
paid: true,
|
||||||
|
@ -135,7 +135,9 @@ export function PayPage({
|
|||||||
? Amounts.parseOrThrow(foundBalance.available)
|
? Amounts.parseOrThrow(foundBalance.available)
|
||||||
: undefined;
|
: undefined;
|
||||||
// We use a string here so that dependency tracking for useEffect works properly
|
// We use a string here so that dependency tracking for useEffect works properly
|
||||||
const foundAmountStr = foundAmount ? Amounts.stringify(foundAmount) : undefined;
|
const foundAmountStr = foundAmount
|
||||||
|
? Amounts.stringify(foundAmount)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!talerPayUri) return;
|
if (!talerPayUri) return;
|
||||||
|
@ -35,10 +35,10 @@ export const Complete = createExample(TestedComponent, {
|
|||||||
amountRefundGone: "USD:0",
|
amountRefundGone: "USD:0",
|
||||||
amountRefundGranted: "USD:2",
|
amountRefundGranted: "USD:2",
|
||||||
contractTermsHash: "QWEASDZXC",
|
contractTermsHash: "QWEASDZXC",
|
||||||
info: ({
|
info: {
|
||||||
summary: "tasty cold beer",
|
summary: "tasty cold beer",
|
||||||
contractTermsHash: "QWEASDZXC",
|
contractTermsHash: "QWEASDZXC",
|
||||||
} as Partial<OrderShortInfo>) as any,
|
} as Partial<OrderShortInfo> as any,
|
||||||
pendingAtExchange: false,
|
pendingAtExchange: false,
|
||||||
proposalId: "proposal123",
|
proposalId: "proposal123",
|
||||||
},
|
},
|
||||||
@ -50,10 +50,10 @@ export const Partial = createExample(TestedComponent, {
|
|||||||
amountRefundGone: "USD:1",
|
amountRefundGone: "USD:1",
|
||||||
amountRefundGranted: "USD:2",
|
amountRefundGranted: "USD:2",
|
||||||
contractTermsHash: "QWEASDZXC",
|
contractTermsHash: "QWEASDZXC",
|
||||||
info: ({
|
info: {
|
||||||
summary: "tasty cold beer",
|
summary: "tasty cold beer",
|
||||||
contractTermsHash: "QWEASDZXC",
|
contractTermsHash: "QWEASDZXC",
|
||||||
} as Partial<OrderShortInfo>) as any,
|
} as Partial<OrderShortInfo> as any,
|
||||||
pendingAtExchange: false,
|
pendingAtExchange: false,
|
||||||
proposalId: "proposal123",
|
proposalId: "proposal123",
|
||||||
},
|
},
|
||||||
@ -65,10 +65,10 @@ export const InProgress = createExample(TestedComponent, {
|
|||||||
amountRefundGone: "USD:1",
|
amountRefundGone: "USD:1",
|
||||||
amountRefundGranted: "USD:2",
|
amountRefundGranted: "USD:2",
|
||||||
contractTermsHash: "QWEASDZXC",
|
contractTermsHash: "QWEASDZXC",
|
||||||
info: ({
|
info: {
|
||||||
summary: "tasty cold beer",
|
summary: "tasty cold beer",
|
||||||
contractTermsHash: "QWEASDZXC",
|
contractTermsHash: "QWEASDZXC",
|
||||||
} as Partial<OrderShortInfo>) as any,
|
} as Partial<OrderShortInfo> as any,
|
||||||
pendingAtExchange: true,
|
pendingAtExchange: true,
|
||||||
proposalId: "proposal123",
|
proposalId: "proposal123",
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
WarningBox,
|
WarningBox,
|
||||||
WarningText,
|
WarningText,
|
||||||
} from "../components/styled";
|
} from "../components/styled";
|
||||||
import { TermsState } from "../utils";
|
import { TermsState } from "../utils/index";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
reviewing: boolean;
|
reviewing: boolean;
|
||||||
|
@ -24,12 +24,16 @@ import { createExample } from "../test-utils";
|
|||||||
import { termsHtml, termsPdf, termsPlain, termsXml } from "./termsExample";
|
import { termsHtml, termsPdf, termsPlain, termsXml } from "./termsExample";
|
||||||
import { View as TestedComponent } from "./Withdraw";
|
import { View as TestedComponent } from "./Withdraw";
|
||||||
|
|
||||||
|
function parseFromString(s: string): Document {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return {} as Document;
|
||||||
|
}
|
||||||
|
return new window.DOMParser().parseFromString(s, "text/xml");
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "cta/withdraw",
|
title: "cta/withdraw",
|
||||||
component: TestedComponent,
|
component: TestedComponent,
|
||||||
argTypes: {
|
|
||||||
onSwitchExchange: { action: "onRetry" },
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const exchangeList: ExchangeListItem[] = [
|
const exchangeList: ExchangeListItem[] = [
|
||||||
@ -77,7 +81,7 @@ export const NewTerms = createExample(TestedComponent, {
|
|||||||
terms: {
|
terms: {
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
status: "new",
|
status: "new",
|
||||||
version: "",
|
version: "",
|
||||||
@ -192,7 +196,7 @@ export const TermsReviewingXML = createExample(TestedComponent, {
|
|||||||
terms: {
|
terms: {
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
status: "new",
|
status: "new",
|
||||||
version: "",
|
version: "",
|
||||||
@ -219,7 +223,7 @@ export const NewTermsAccepted = createExample(TestedComponent, {
|
|||||||
terms: {
|
terms: {
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
status: "new",
|
status: "new",
|
||||||
version: "",
|
version: "",
|
||||||
@ -247,7 +251,7 @@ export const TermsShowAgainXML = createExample(TestedComponent, {
|
|||||||
terms: {
|
terms: {
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
version: "",
|
version: "",
|
||||||
status: "new",
|
status: "new",
|
||||||
@ -276,7 +280,7 @@ export const TermsChanged = createExample(TestedComponent, {
|
|||||||
terms: {
|
terms: {
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
version: "",
|
version: "",
|
||||||
status: "changed",
|
status: "changed",
|
||||||
@ -351,7 +355,7 @@ export const WithoutFee = createExample(TestedComponent, {
|
|||||||
terms: {
|
terms: {
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
status: "accepted",
|
status: "accepted",
|
||||||
version: "",
|
version: "",
|
||||||
|
@ -40,7 +40,11 @@ import {
|
|||||||
WalletAction,
|
WalletAction,
|
||||||
} from "../components/styled";
|
} from "../components/styled";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { amountToString, buildTermsOfServiceState, TermsState } from "../utils";
|
import {
|
||||||
|
amountToString,
|
||||||
|
buildTermsOfServiceState,
|
||||||
|
TermsState,
|
||||||
|
} from "../utils/index";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import { TermsOfServiceSection } from "./TermsOfServiceSection";
|
import { TermsOfServiceSection } from "./TermsOfServiceSection";
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ function getStatusPaidOrder(a: ProviderPaymentPaid, b: ProviderPaymentPaid) {
|
|||||||
return a.paidUntil.t_ms === "never"
|
return a.paidUntil.t_ms === "never"
|
||||||
? -1
|
? -1
|
||||||
: b.paidUntil.t_ms === "never"
|
: b.paidUntil.t_ms === "never"
|
||||||
? 1
|
? 1
|
||||||
: a.paidUntil.t_ms - b.paidUntil.t_ms;
|
: a.paidUntil.t_ms - b.paidUntil.t_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useBackupStatus(): BackupStatus | undefined {
|
export function useBackupStatus(): BackupStatus | undefined {
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
import { useTalerActionURL } from "./useTalerActionURL"
|
||||||
|
import { justBrowser_it, mountBrowser } from "../test-utils";
|
||||||
|
import { IoCProviderForTesting } from "../context/iocContext";
|
||||||
|
import { h, VNode } from "preact";
|
||||||
|
import { act } from "preact/test-utils";
|
||||||
|
|
||||||
|
describe('useTalerActionURL hook', () => {
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/expect-expect
|
||||||
|
justBrowser_it('should be set url to undefined when dismiss', async () => {
|
||||||
|
|
||||||
|
const ctx = ({ children }: { children: any }): VNode => {
|
||||||
|
return h(IoCProviderForTesting, {
|
||||||
|
value: {
|
||||||
|
findTalerUriInActiveTab: async () => "asd",
|
||||||
|
}, children
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result, waitNextUpdate } = mountBrowser(useTalerActionURL, ctx)
|
||||||
|
|
||||||
|
{
|
||||||
|
const [url] = result.current!
|
||||||
|
if (url !== undefined) throw Error('invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
await waitNextUpdate()
|
||||||
|
|
||||||
|
{
|
||||||
|
const [url] = result.current!
|
||||||
|
if (url !== "asd") throw Error(`invalid: ${url}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
await act(() => {
|
||||||
|
const [, setDismissed] = result.current!
|
||||||
|
setDismissed(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
{
|
||||||
|
const [url] = result.current!
|
||||||
|
if (url !== undefined) throw Error('invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
@ -14,8 +14,8 @@
|
|||||||
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 { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import { useIocContext } from "../context/iocContext";
|
||||||
|
|
||||||
export function useTalerActionURL(): [
|
export function useTalerActionURL(): [
|
||||||
string | undefined,
|
string | undefined,
|
||||||
@ -25,6 +25,8 @@ export function useTalerActionURL(): [
|
|||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
const [dismissed, setDismissed] = useState(false);
|
const [dismissed, setDismissed] = useState(false);
|
||||||
|
const { findTalerUriInActiveTab } = useIocContext()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function check(): Promise<void> {
|
async function check(): Promise<void> {
|
||||||
const talerUri = await findTalerUriInActiveTab();
|
const talerUri = await findTalerUriInActiveTab();
|
||||||
@ -35,28 +37,3 @@ export function useTalerActionURL(): [
|
|||||||
const url = dismissed ? undefined : talerActionUrl;
|
const url = dismissed ? undefined : talerActionUrl;
|
||||||
return [url, setDismissed];
|
return [url, setDismissed];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findTalerUriInActiveTab(): Promise<string | undefined> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
chrome.tabs.executeScript(
|
|
||||||
{
|
|
||||||
code: `
|
|
||||||
(() => {
|
|
||||||
let x = document.querySelector("a[href^='taler://'") || document.querySelector("a[href^='taler+http://'");
|
|
||||||
return x ? x.href.toString() : null;
|
|
||||||
})();
|
|
||||||
`,
|
|
||||||
allFrames: false,
|
|
||||||
},
|
|
||||||
(result) => {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
console.error(chrome.runtime.lastError);
|
|
||||||
resolve(undefined);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log("got result", result);
|
|
||||||
resolve(result[0]);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import {
|
import { Button, ButtonSuccess, InputWithLabel } from "../components/styled";
|
||||||
Button,
|
|
||||||
ButtonSuccess,
|
|
||||||
InputWithLabel,
|
|
||||||
} from "../components/styled/index";
|
|
||||||
import { actionForTalerUri } from "../utils/index";
|
import { actionForTalerUri } from "../utils/index";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { BalancesResponse, i18n } from "@gnu-taler/taler-util";
|
import { BalancesResponse, i18n } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { BalanceTable } from "../components/BalanceTable";
|
import { BalanceTable } from "../components/BalanceTable";
|
||||||
import { ButtonPrimary, ErrorBox } from "../components/styled/index";
|
import { ButtonPrimary, ErrorBox } from "../components/styled";
|
||||||
import { HookResponse, useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { HookResponse, useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { PageLink } from "../renderHtml";
|
import { PageLink } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
@ -20,7 +20,7 @@ import { format } from "date-fns";
|
|||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { Diagnostics } from "../components/Diagnostics";
|
import { Diagnostics } from "../components/Diagnostics";
|
||||||
import { NotifyUpdateFadeOut } from "../components/styled/index";
|
import { NotifyUpdateFadeOut } from "../components/styled";
|
||||||
import { Time } from "../components/Time";
|
import { Time } from "../components/Time";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { useDiagnostics } from "../hooks/useDiagnostics";
|
import { useDiagnostics } from "../hooks/useDiagnostics";
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { ButtonPrimary } from "../components/styled/index";
|
import { ButtonPrimary } from "../components/styled";
|
||||||
import { TransactionItem } from "../components/TransactionItem";
|
import { TransactionItem } from "../components/TransactionItem";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
@ -133,7 +133,7 @@ export function HistoryView({
|
|||||||
style={{ color: "darkgreen", textDecoration: "none" }}
|
style={{ color: "darkgreen", textDecoration: "none" }}
|
||||||
href={
|
href={
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
chrome.extension
|
typeof chrome !== "undefined" && chrome.extension
|
||||||
? // eslint-disable-next-line no-undef
|
? // eslint-disable-next-line no-undef
|
||||||
chrome.extension.getURL(`/static/wallet.html#/history`)
|
chrome.extension.getURL(`/static/wallet.html#/history`)
|
||||||
: "#"
|
: "#"
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h } from "preact";
|
import { Fragment, h } from "preact";
|
||||||
import { ButtonPrimary, ButtonSuccess } from "../components/styled/index";
|
import { ButtonPrimary, ButtonSuccess } from "../components/styled";
|
||||||
import { actionForTalerUri } from "../utils/index";
|
import { actionForTalerUri } from "../utils/index";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -14,11 +14,16 @@
|
|||||||
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/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This fixed an error related to the CSS and loading gif breaking my Jest test
|
import * as a1 from "./AddNewActionView.stories";
|
||||||
// See https://facebook.github.io/jest/docs/en/webpack.html#handling-static-assets
|
import * as a2 from "./Balance.stories";
|
||||||
export default 'test-file-stub';
|
import * as a3 from "./DeveloperPage.stories";
|
||||||
|
import * as a4 from "./History.stories";
|
||||||
|
import * as a5 from "./Popup.stories";
|
||||||
|
import * as a6 from "./TalerActionFound.stories";
|
||||||
|
|
||||||
|
export default [a1, a2, a3, a4, a5, a6];
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
import { setupI18n } from "@gnu-taler/taler-util";
|
import { setupI18n } from "@gnu-taler/taler-util";
|
||||||
import { createHashHistory } from "history";
|
import { createHashHistory } from "history";
|
||||||
import { render, h } from "preact";
|
import { render, h, VNode, Fragment } from "preact";
|
||||||
import Router, { route, Route } from "preact-router";
|
import Router, { route, Route } from "preact-router";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
import { PopupBox } from "./components/styled";
|
import { PopupBox } from "./components/styled";
|
||||||
@ -39,6 +39,7 @@ import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
|
|||||||
import { SettingsPage } from "./popup/Settings";
|
import { SettingsPage } from "./popup/Settings";
|
||||||
import { TalerActionFound } from "./popup/TalerActionFound";
|
import { TalerActionFound } from "./popup/TalerActionFound";
|
||||||
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
|
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
|
||||||
|
import { IoCProviderForRuntime } from "./context/iocContext";
|
||||||
|
|
||||||
function main(): void {
|
function main(): void {
|
||||||
try {
|
try {
|
||||||
@ -63,87 +64,99 @@ if (document.readyState === "loading") {
|
|||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
|
|
||||||
function Application() {
|
function CheckTalerActionComponent(): VNode {
|
||||||
const [talerActionUrl, setDismissed] = useTalerActionURL();
|
const [talerActionUrl] = useTalerActionURL();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (talerActionUrl) route(Pages.cta);
|
if (talerActionUrl)
|
||||||
|
route(Pages.cta.replace(":action", encodeURIComponent(talerActionUrl)));
|
||||||
}, [talerActionUrl]);
|
}, [talerActionUrl]);
|
||||||
|
|
||||||
|
return <Fragment />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Application() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<DevContextProvider>
|
<DevContextProvider>
|
||||||
<WalletNavBar />
|
<IoCProviderForRuntime>
|
||||||
<PopupBox>
|
<WalletNavBar />
|
||||||
<Router history={createHashHistory()}>
|
<CheckTalerActionComponent />
|
||||||
<Route path={Pages.dev} component={DeveloperPage} />
|
<PopupBox>
|
||||||
|
<Router history={createHashHistory()}>
|
||||||
|
<Route path={Pages.dev} component={DeveloperPage} />
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.balance}
|
path={Pages.balance}
|
||||||
component={BalancePage}
|
component={BalancePage}
|
||||||
goToWalletManualWithdraw={() =>
|
goToWalletManualWithdraw={() =>
|
||||||
goToWalletPage(Pages.manual_withdraw)
|
goToWalletPage(Pages.manual_withdraw)
|
||||||
}
|
}
|
||||||
goToWalletDeposit={(currency: string) =>
|
goToWalletDeposit={(currency: string) =>
|
||||||
goToWalletPage(Pages.deposit.replace(":currency", currency))
|
goToWalletPage(Pages.deposit.replace(":currency", currency))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route path={Pages.settings} component={SettingsPage} />
|
<Route path={Pages.settings} component={SettingsPage} />
|
||||||
<Route
|
<Route
|
||||||
path={Pages.cta}
|
path={Pages.cta}
|
||||||
component={() => (
|
component={function Action({ action }: { action: string }) {
|
||||||
<TalerActionFound
|
const [, setDismissed] = useTalerActionURL();
|
||||||
url={talerActionUrl!}
|
|
||||||
onDismiss={() => {
|
|
||||||
setDismissed(true);
|
|
||||||
route(Pages.balance);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route
|
return (
|
||||||
path={Pages.transaction}
|
<TalerActionFound
|
||||||
component={({ tid }: { tid: string }) =>
|
url={decodeURIComponent(action)}
|
||||||
goToWalletPage(Pages.transaction.replace(":tid", tid))
|
onDismiss={() => {
|
||||||
}
|
setDismissed(true);
|
||||||
/>
|
route(Pages.balance);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route path={Pages.history} component={HistoryPage} />
|
<Route
|
||||||
|
path={Pages.transaction}
|
||||||
|
component={({ tid }: { tid: string }) =>
|
||||||
|
goToWalletPage(Pages.transaction.replace(":tid", tid))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route
|
<Route path={Pages.history} component={HistoryPage} />
|
||||||
path={Pages.backup}
|
|
||||||
component={BackupPage}
|
|
||||||
onAddProvider={() => {
|
|
||||||
route(Pages.provider_add);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path={Pages.provider_detail}
|
|
||||||
component={ProviderDetailPage}
|
|
||||||
onBack={() => {
|
|
||||||
route(Pages.backup);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path={Pages.provider_add}
|
|
||||||
component={ProviderAddPage}
|
|
||||||
onBack={() => {
|
|
||||||
route(Pages.backup);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.exchange_add}
|
path={Pages.backup}
|
||||||
component={ExchangeAddPage}
|
component={BackupPage}
|
||||||
onBack={() => {
|
onAddProvider={() => {
|
||||||
route(Pages.balance);
|
route(Pages.provider_add);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path={Pages.provider_detail}
|
||||||
|
component={ProviderDetailPage}
|
||||||
|
onBack={() => {
|
||||||
|
route(Pages.backup);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={Pages.provider_add}
|
||||||
|
component={ProviderAddPage}
|
||||||
|
onBack={() => {
|
||||||
|
route(Pages.backup);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route default component={Redirect} to={Pages.balance} />
|
<Route
|
||||||
</Router>
|
path={Pages.exchange_add}
|
||||||
</PopupBox>
|
component={ExchangeAddPage}
|
||||||
|
onBack={() => {
|
||||||
|
route(Pages.balance);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route default component={Redirect} to={Pages.balance} />
|
||||||
|
</Router>
|
||||||
|
</PopupBox>
|
||||||
|
</IoCProviderForRuntime>
|
||||||
</DevContextProvider>
|
</DevContextProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
51
packages/taler-wallet-webextension/src/stories.test.ts
Normal file
51
packages/taler-wallet-webextension/src/stories.test.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
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 * as popup from "./popup/index.stories";
|
||||||
|
import * as wallet from "./wallet/index.stories";
|
||||||
|
|
||||||
|
import { setupI18n } from "@gnu-taler/taler-util";
|
||||||
|
import { renderNodeOrBrowser } from "./test-utils";
|
||||||
|
setupI18n("en", { en: {} });
|
||||||
|
|
||||||
|
function testThisStory(st: any): any {
|
||||||
|
describe(`render examples for ${(st as any).default.title}`, () => {
|
||||||
|
Object.keys(st).forEach((k) => {
|
||||||
|
const Component = (st as any)[k];
|
||||||
|
if (k === "default" || !Component) return;
|
||||||
|
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/expect-expect
|
||||||
|
it(`example: ${k}`, () => {
|
||||||
|
renderNodeOrBrowser(Component, Component.args);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("render every storybook example", () => {
|
||||||
|
[popup, wallet].forEach(function testAll(st: any) {
|
||||||
|
if (Array.isArray(st.default)) {
|
||||||
|
st.default.forEach(testAll)
|
||||||
|
} else {
|
||||||
|
testThisStory(st)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -14,13 +14,15 @@
|
|||||||
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 { ComponentChildren, FunctionalComponent, h as render, VNode } from "preact";
|
import { PendingTestFunction, TestFunction } from "mocha";
|
||||||
|
import { ComponentChildren, Fragment, FunctionalComponent, h as create, render as renderIntoDom, VNode } from "preact";
|
||||||
|
import { render as renderToString } from "preact-render-to-string";
|
||||||
|
|
||||||
export function createExample<Props>(
|
export function createExample<Props>(
|
||||||
Component: FunctionalComponent<Props>,
|
Component: FunctionalComponent<Props>,
|
||||||
props: Partial<Props>,
|
props: Partial<Props>,
|
||||||
): ComponentChildren {
|
): ComponentChildren {
|
||||||
const Render = (args: any) => render(Component, args);
|
const Render = (args: any): VNode => create(Component, args);
|
||||||
Render.args = props;
|
Render.args = props;
|
||||||
return Render;
|
return Render;
|
||||||
}
|
}
|
||||||
@ -31,12 +33,89 @@ export function createExampleWithCustomContext<Props, ContextProps>(
|
|||||||
ContextProvider: FunctionalComponent<ContextProps>,
|
ContextProvider: FunctionalComponent<ContextProps>,
|
||||||
contextProps: Partial<ContextProps>,
|
contextProps: Partial<ContextProps>,
|
||||||
): ComponentChildren {
|
): ComponentChildren {
|
||||||
const Render = (args: any): VNode => render(Component, args);
|
const Render = (args: any): VNode => create(Component, args);
|
||||||
const WithContext = (args: any): VNode => render(ContextProvider, { ...contextProps, children: [Render(args)] } as any);
|
const WithContext = (args: any): VNode => create(ContextProvider, { ...contextProps, children: [Render(args)] } as any);
|
||||||
WithContext.args = props
|
WithContext.args = props
|
||||||
return WithContext
|
return WithContext
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NullLink({ children }: { children?: ComponentChildren }) {
|
export function NullLink({ children }: { children?: ComponentChildren }): VNode {
|
||||||
return render("a", { children, href: "javascript:void(0);" });
|
return create("a", { children, href: "javascript:void(0);" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function renderNodeOrBrowser(Component: any, args: any): void {
|
||||||
|
const vdom = create(Component, args);
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
renderToString(vdom);
|
||||||
|
} else {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
document.body.appendChild(div);
|
||||||
|
renderIntoDom(vdom, div);
|
||||||
|
renderIntoDom(null, div);
|
||||||
|
document.body.removeChild(div);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Mounted<T> {
|
||||||
|
unmount: () => void;
|
||||||
|
result: { current: T | null };
|
||||||
|
waitNextUpdate: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mountBrowser<T>(callback: () => T, Context?: ({ children }: { children: any }) => VNode): Mounted<T> {
|
||||||
|
const result: { current: T | null } = {
|
||||||
|
current: null
|
||||||
|
}
|
||||||
|
const listener: Array<() => void> = []
|
||||||
|
|
||||||
|
// component that's going to hold the hook
|
||||||
|
function Component(): VNode {
|
||||||
|
const hookResult = callback()
|
||||||
|
// save the hook result
|
||||||
|
result.current = hookResult
|
||||||
|
// notify to everyone waiting for an update and clean the queue
|
||||||
|
listener.splice(0, listener.length).forEach(cb => cb())
|
||||||
|
return create(Fragment, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the vdom with context if required
|
||||||
|
const vdom = !Context ? create(Component, {}) : create(Context, { children: [create(Component, {})] },);
|
||||||
|
|
||||||
|
// in non-browser environment (server side rendering) just serialize to
|
||||||
|
// string and exit
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
renderToString(vdom);
|
||||||
|
return { unmount: () => null, result } as any
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the render into the DOM
|
||||||
|
const div = document.createElement("div");
|
||||||
|
document.body.appendChild(div);
|
||||||
|
renderIntoDom(vdom, div);
|
||||||
|
|
||||||
|
// clean up callback
|
||||||
|
function unmount(): any {
|
||||||
|
document.body.removeChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
// waiter callback
|
||||||
|
async function waitNextUpdate(): Promise<void> {
|
||||||
|
await new Promise((res, rej) => {
|
||||||
|
const tid = setTimeout(() => {
|
||||||
|
rej(Error("waiting for an update but the hook didn't make one"))
|
||||||
|
}, 100)
|
||||||
|
|
||||||
|
listener.push(() => {
|
||||||
|
clearTimeout(tid)
|
||||||
|
res(undefined)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
unmount, result, waitNextUpdate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const justBrowser_it: PendingTestFunction | TestFunction =
|
||||||
|
typeof window === 'undefined' ? it.skip : it
|
@ -17,7 +17,7 @@
|
|||||||
import { BalancesResponse, i18n } from "@gnu-taler/taler-util";
|
import { BalancesResponse, i18n } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { BalanceTable } from "../components/BalanceTable";
|
import { BalanceTable } from "../components/BalanceTable";
|
||||||
import { ButtonPrimary, Centered, ErrorBox } from "../components/styled/index";
|
import { ButtonPrimary, Centered, ErrorBox } from "../components/styled";
|
||||||
import { HookResponse, useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { HookResponse, useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { PageLink } from "../renderHtml";
|
import { PageLink } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AmountJson, Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
|
import { Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
|
||||||
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
||||||
import { createExample } from "../test-utils";
|
import { createExample } from "../test-utils";
|
||||||
import { View as TestedComponent } from "./DepositPage";
|
import { View as TestedComponent } from "./DepositPage";
|
||||||
|
@ -108,8 +108,13 @@ export function View({
|
|||||||
const currency = balance.currency;
|
const currency = balance.currency;
|
||||||
const amountStr: AmountString = `${currency}:${amount}`;
|
const amountStr: AmountString = `${currency}:${amount}`;
|
||||||
|
|
||||||
const account = knownBankAccounts[accountIdx];
|
const account = knownBankAccounts.length
|
||||||
const accountURI = `payto://${account.targetType}/${account.targetPath}`;
|
? knownBankAccounts[accountIdx]
|
||||||
|
: undefined;
|
||||||
|
const accountURI = !account
|
||||||
|
? ""
|
||||||
|
: `payto://${account.targetType}/${account.targetPath}`;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (amount === undefined) return;
|
if (amount === undefined) return;
|
||||||
onCalculateFee(accountURI, amountStr).then((result) => {
|
onCalculateFee(accountURI, amountStr).then((result) => {
|
||||||
|
@ -23,6 +23,17 @@ import { termsXml } from "../cta/termsExample";
|
|||||||
import { createExample } from "../test-utils";
|
import { createExample } from "../test-utils";
|
||||||
import { View as TestedComponent } from "./ExchangeAddConfirm";
|
import { View as TestedComponent } from "./ExchangeAddConfirm";
|
||||||
|
|
||||||
|
function parseFromString(s: string): Document {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return {
|
||||||
|
querySelector: () => ({
|
||||||
|
children: [],
|
||||||
|
}),
|
||||||
|
} as any;
|
||||||
|
}
|
||||||
|
return new window.DOMParser().parseFromString(s, "text/xml");
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "wallet/exchange add/confirm",
|
title: "wallet/exchange add/confirm",
|
||||||
component: TestedComponent,
|
component: TestedComponent,
|
||||||
@ -60,7 +71,7 @@ export const TermsChanged = createExample(TestedComponent, {
|
|||||||
version: "1",
|
version: "1",
|
||||||
content: {
|
content: {
|
||||||
type: "xml",
|
type: "xml",
|
||||||
document: new DOMParser().parseFromString(termsXml, "text/xml"),
|
document: parseFromString(termsXml),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
onAccept: async () => undefined,
|
onAccept: async () => undefined,
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import { i18n } from "@gnu-taler/taler-util";
|
import { i18n } from "@gnu-taler/taler-util";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import {
|
import { Button, ButtonSuccess, ButtonWarning } from "../components/styled";
|
||||||
Button,
|
|
||||||
ButtonSuccess,
|
|
||||||
ButtonWarning,
|
|
||||||
} from "../components/styled/index";
|
|
||||||
import { TermsOfServiceSection } from "../cta/TermsOfServiceSection";
|
import { TermsOfServiceSection } from "../cta/TermsOfServiceSection";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { buildTermsOfServiceState, TermsState } from "../utils";
|
import { buildTermsOfServiceState, TermsState } from "../utils/index";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { queryToSlashKeys } from "../utils";
|
import { queryToSlashKeys } from "../utils/index";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import { ExchangeAddConfirmPage } from "./ExchangeAddConfirm";
|
import { ExchangeAddConfirmPage } from "./ExchangeAddConfirm";
|
||||||
import { ExchangeSetUrlPage } from "./ExchangeSetUrl";
|
import { ExchangeSetUrlPage } from "./ExchangeSetUrl";
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { createExample } from "../test-utils";
|
import { createExample } from "../test-utils";
|
||||||
import { queryToSlashKeys } from "../utils";
|
import { queryToSlashKeys } from "../utils/index";
|
||||||
import { ExchangeSetUrlPage as TestedComponent } from "./ExchangeSetUrl";
|
import { ExchangeSetUrlPage as TestedComponent } from "./ExchangeSetUrl";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -7,12 +7,7 @@ import {
|
|||||||
import { Fragment, h } from "preact";
|
import { Fragment, h } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { ErrorMessage } from "../components/ErrorMessage";
|
import { ErrorMessage } from "../components/ErrorMessage";
|
||||||
import {
|
import { Button, ButtonPrimary, Input, WarningBox } from "../components/styled";
|
||||||
Button,
|
|
||||||
ButtonPrimary,
|
|
||||||
Input,
|
|
||||||
WarningBox,
|
|
||||||
} from "../components/styled/index";
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
initialValue?: string;
|
initialValue?: string;
|
||||||
|
@ -30,8 +30,8 @@ import {
|
|||||||
Input,
|
Input,
|
||||||
LightText,
|
LightText,
|
||||||
SmallLightText,
|
SmallLightText,
|
||||||
} from "../components/styled/index";
|
} from "../components/styled";
|
||||||
import { queryToSlashConfig } from "../utils";
|
import { queryToSlashConfig } from "../utils/index";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -3,7 +3,7 @@ import { Fragment, h, VNode } from "preact";
|
|||||||
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType";
|
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType";
|
||||||
import { QR } from "../components/QR";
|
import { QR } from "../components/QR";
|
||||||
import { ButtonDestructive, WarningBox } from "../components/styled";
|
import { ButtonDestructive, WarningBox } from "../components/styled";
|
||||||
import { amountToString } from "../utils";
|
import { amountToString } from "../utils/index";
|
||||||
export interface Props {
|
export interface Props {
|
||||||
reservePub: string;
|
reservePub: string;
|
||||||
payto: string;
|
payto: string;
|
||||||
|
@ -29,7 +29,7 @@ import { useBackupDeviceName } from "../hooks/useBackupDeviceName";
|
|||||||
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
|
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
|
||||||
import { useLang } from "../hooks/useLang";
|
import { useLang } from "../hooks/useLang";
|
||||||
import { Pages } from "../NavigationBar";
|
import { Pages } from "../NavigationBar";
|
||||||
import { buildTermsOfServiceStatus } from "../utils";
|
import { buildTermsOfServiceStatus } from "../utils/index";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
export function SettingsPage(): VNode {
|
export function SettingsPage(): VNode {
|
||||||
|
@ -125,12 +125,13 @@ const exampleData = {
|
|||||||
const transactionError = {
|
const transactionError = {
|
||||||
code: 7005,
|
code: 7005,
|
||||||
details: {
|
details: {
|
||||||
requestUrl: "http://merchant-backend.taler:9966/orders/2021.340-02AD5XCC97MQM/pay",
|
requestUrl:
|
||||||
|
"http://merchant-backend.taler:9966/orders/2021.340-02AD5XCC97MQM/pay",
|
||||||
httpStatusCode: 410,
|
httpStatusCode: 410,
|
||||||
errorResponse: {
|
errorResponse: {
|
||||||
code: 2161,
|
code: 2161,
|
||||||
hint: "The payment is too late, the offer has expired."
|
hint: "The payment is too late, the offer has expired.",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
hint: "Error: WALLET_UNEXPECTED_REQUEST_ERROR",
|
hint: "Error: WALLET_UNEXPECTED_REQUEST_ERROR",
|
||||||
message: "Unexpected error code in response",
|
message: "Unexpected error code in response",
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
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 * as a1 from "./Backup.stories";
|
||||||
|
import * as a2 from "./Balance.stories";
|
||||||
|
import * as a3 from "./CreateManualWithdraw.stories";
|
||||||
|
import * as a4 from "./DepositPage.stories";
|
||||||
|
import * as a5 from "./ExchangeAddConfirm.stories";
|
||||||
|
import * as a6 from "./ExchangeAddSetUrl.stories";
|
||||||
|
import * as a7 from "./History.stories";
|
||||||
|
import * as a8 from "./ProviderAddConfirmProvider.stories";
|
||||||
|
import * as a9 from "./ProviderAddSetUrl.stories";
|
||||||
|
import * as a10 from "./ProviderDetail.stories";
|
||||||
|
import * as a11 from "./ReserveCreated.stories";
|
||||||
|
import * as a12 from "./Settings.stories";
|
||||||
|
import * as a13 from "./Transaction.stories";
|
||||||
|
import * as a14 from "./Welcome.stories";
|
||||||
|
|
||||||
|
export default [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14];
|
@ -46,6 +46,7 @@ import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
|
|||||||
import { ProviderAddPage } from "./wallet/ProviderAddPage";
|
import { ProviderAddPage } from "./wallet/ProviderAddPage";
|
||||||
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
|
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
|
||||||
import { DepositPage } from "./wallet/DepositPage";
|
import { DepositPage } from "./wallet/DepositPage";
|
||||||
|
import { IoCProviderForRuntime } from "./context/iocContext";
|
||||||
|
|
||||||
function main(): void {
|
function main(): void {
|
||||||
try {
|
try {
|
||||||
@ -88,103 +89,105 @@ function Application(): VNode {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<DevContextProvider>
|
<DevContextProvider>
|
||||||
<Router history={createHashHistory()}>
|
<IoCProviderForRuntime>
|
||||||
<Route
|
<Router history={createHashHistory()}>
|
||||||
path={Pages.welcome}
|
<Route
|
||||||
component={withLogoAndNavBar(WelcomePage)}
|
path={Pages.welcome}
|
||||||
/>
|
component={withLogoAndNavBar(WelcomePage)}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.history}
|
path={Pages.history}
|
||||||
component={withLogoAndNavBar(HistoryPage)}
|
component={withLogoAndNavBar(HistoryPage)}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.transaction}
|
path={Pages.transaction}
|
||||||
component={withLogoAndNavBar(TransactionPage)}
|
component={withLogoAndNavBar(TransactionPage)}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.balance}
|
path={Pages.balance}
|
||||||
component={withLogoAndNavBar(BalancePage)}
|
component={withLogoAndNavBar(BalancePage)}
|
||||||
goToWalletManualWithdraw={() => route(Pages.manual_withdraw)}
|
goToWalletManualWithdraw={() => route(Pages.manual_withdraw)}
|
||||||
goToWalletDeposit={(currency: string) =>
|
goToWalletDeposit={(currency: string) =>
|
||||||
route(Pages.deposit.replace(":currency", currency))
|
route(Pages.deposit.replace(":currency", currency))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.settings}
|
path={Pages.settings}
|
||||||
component={withLogoAndNavBar(SettingsPage)}
|
component={withLogoAndNavBar(SettingsPage)}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.backup}
|
path={Pages.backup}
|
||||||
component={withLogoAndNavBar(BackupPage)}
|
component={withLogoAndNavBar(BackupPage)}
|
||||||
onAddProvider={() => {
|
onAddProvider={() => {
|
||||||
route(Pages.provider_add);
|
route(Pages.provider_add);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.provider_detail}
|
path={Pages.provider_detail}
|
||||||
component={withLogoAndNavBar(ProviderDetailPage)}
|
component={withLogoAndNavBar(ProviderDetailPage)}
|
||||||
onBack={() => {
|
onBack={() => {
|
||||||
route(Pages.backup);
|
route(Pages.backup);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.provider_add}
|
path={Pages.provider_add}
|
||||||
component={withLogoAndNavBar(ProviderAddPage)}
|
component={withLogoAndNavBar(ProviderAddPage)}
|
||||||
onBack={() => {
|
onBack={() => {
|
||||||
route(Pages.backup);
|
route(Pages.backup);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.exchange_add}
|
path={Pages.exchange_add}
|
||||||
component={withLogoAndNavBar(ExchangeAddPage)}
|
component={withLogoAndNavBar(ExchangeAddPage)}
|
||||||
onBack={() => {
|
onBack={() => {
|
||||||
route(Pages.balance);
|
route(Pages.balance);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.manual_withdraw}
|
path={Pages.manual_withdraw}
|
||||||
component={withLogoAndNavBar(ManualWithdrawPage)}
|
component={withLogoAndNavBar(ManualWithdrawPage)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.deposit}
|
path={Pages.deposit}
|
||||||
component={withLogoAndNavBar(DepositPage)}
|
component={withLogoAndNavBar(DepositPage)}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.reset_required}
|
path={Pages.reset_required}
|
||||||
component={() => <div>no yet implemented</div>}
|
component={() => <div>no yet implemented</div>}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.payback}
|
path={Pages.payback}
|
||||||
component={() => <div>no yet implemented</div>}
|
component={() => <div>no yet implemented</div>}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={Pages.return_coins}
|
path={Pages.return_coins}
|
||||||
component={() => <div>no yet implemented</div>}
|
component={() => <div>no yet implemented</div>}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={Pages.dev}
|
path={Pages.dev}
|
||||||
component={withLogoAndNavBar(DeveloperPage)}
|
component={withLogoAndNavBar(DeveloperPage)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/** call to action */}
|
{/** call to action */}
|
||||||
<Route
|
<Route
|
||||||
path={Pages.pay}
|
path={Pages.pay}
|
||||||
component={PayPage}
|
component={PayPage}
|
||||||
goToWalletManualWithdraw={() =>
|
goToWalletManualWithdraw={() =>
|
||||||
goToWalletPage(Pages.manual_withdraw)
|
goToWalletPage(Pages.manual_withdraw)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route path={Pages.refund} component={RefundPage} />
|
<Route path={Pages.refund} component={RefundPage} />
|
||||||
<Route path={Pages.tips} component={TipPage} />
|
<Route path={Pages.tips} component={TipPage} />
|
||||||
<Route path={Pages.withdraw} component={WithdrawPage} />
|
<Route path={Pages.withdraw} component={WithdrawPage} />
|
||||||
|
|
||||||
<Route default component={Redirect} to={Pages.history} />
|
<Route default component={Redirect} to={Pages.history} />
|
||||||
</Router>
|
</Router>
|
||||||
|
</IoCProviderForRuntime>
|
||||||
</DevContextProvider>
|
</DevContextProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -39,7 +39,7 @@ import {
|
|||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits";
|
||||||
import { ExchangeWithdrawDetails } from "@gnu-taler/taler-wallet-core/src/operations/withdraw";
|
import { ExchangeWithdrawDetails } from "@gnu-taler/taler-wallet-core/src/operations/withdraw";
|
||||||
import { MessageFromBackend } from "./wxBackend.js";
|
import { MessageFromBackend } from "./wxBackend";
|
||||||
|
|
||||||
export interface ExtendedPermissionsResponse {
|
export interface ExtendedPermissionsResponse {
|
||||||
newValue: boolean;
|
newValue: boolean;
|
||||||
@ -75,7 +75,7 @@ async function callBackend(operation: string, payload: any): Promise<any> {
|
|||||||
console.log("Error calling backend");
|
console.log("Error calling backend");
|
||||||
reject(
|
reject(
|
||||||
new Error(
|
new Error(
|
||||||
`Error contacting backend: chrome.runtime.lastError.message`,
|
`Error contacting backend: ${chrome.runtime.lastError.message}`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
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)) + ';';
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
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)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Here we are mocking the linaria runtime since it should not be used in
|
|
||||||
* runtime.
|
|
||||||
*/
|
|
||||||
export const styled = new Proxy(function (tag: any) {
|
|
||||||
return jest.fn(() => `mock-styled.${tag}`);
|
|
||||||
}, {
|
|
||||||
get(o, prop) {
|
|
||||||
return o(prop);
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
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;
|
|
||||||
(global as any).chrome = {};
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2020 Taler Systems SA
|
|
||||||
|
|
||||||
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/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
// import * as test from "ava";
|
|
||||||
import { internalSetStrings, i18n, Translate } from "@gnu-taler/taler-util";
|
|
||||||
import { render, configure } from "enzyme";
|
|
||||||
import { h } from 'preact';
|
|
||||||
import Adapter from 'enzyme-adapter-preact-pure';
|
|
||||||
|
|
||||||
configure({ adapter: new Adapter() });
|
|
||||||
|
|
||||||
const testStrings = {
|
|
||||||
domain: "messages",
|
|
||||||
locale_data: {
|
|
||||||
messages: {
|
|
||||||
str1: ["foo1"],
|
|
||||||
str2: [""],
|
|
||||||
"str3 %1$s / %2$s": ["foo3 %2$s ; %1$s"],
|
|
||||||
"": {
|
|
||||||
domain: "messages",
|
|
||||||
plural_forms: "nplurals=2; plural=(n != 1);",
|
|
||||||
lang: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
test("str translation", (done) => {
|
|
||||||
|
|
||||||
// Alias, so we nly use the function for lookups, not for string extranction.
|
|
||||||
const strAlias = i18n.str;
|
|
||||||
const TranslateAlias = Translate;
|
|
||||||
internalSetStrings(testStrings);
|
|
||||||
expect(strAlias`str1`).toEqual("foo1");
|
|
||||||
expect(strAlias`str2`).toEqual("str2");
|
|
||||||
const a = "a";
|
|
||||||
const b = "b";
|
|
||||||
expect(strAlias`str3 ${a} / ${b}`).toEqual("foo3 b ; a");
|
|
||||||
const r = render(<Translate>str1</Translate>);
|
|
||||||
expect(r.text()).toEqual("foo1");
|
|
||||||
|
|
||||||
const r2 = render(
|
|
||||||
<TranslateAlias>
|
|
||||||
str3 <span>{a}</span> / <span>{b}</span>
|
|
||||||
</TranslateAlias>,
|
|
||||||
);
|
|
||||||
expect(r2.text()).toEqual("foo3 b ; a");
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
// test.default("existing str translation", (t) => {
|
|
||||||
// internalSetStrings(strings);
|
|
||||||
// t.pass();
|
|
||||||
// });
|
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
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 { mount } from 'enzyme';
|
|
||||||
import { h } from 'preact';
|
|
||||||
|
|
||||||
import fs from 'fs';
|
|
||||||
|
|
||||||
function getFiles(dir: string, files_: string[] = []) {
|
|
||||||
const files = fs.readdirSync(dir);
|
|
||||||
for (const i in files) {
|
|
||||||
const name = dir + '/' + files[i];
|
|
||||||
if (fs.statSync(name).isDirectory()) {
|
|
||||||
getFiles(name, files_);
|
|
||||||
} else {
|
|
||||||
files_.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const re = RegExp('.*\.stories.tsx')
|
|
||||||
|
|
||||||
import { setupI18n } from '@gnu-taler/taler-util';
|
|
||||||
setupI18n('en',{'en':{}})
|
|
||||||
|
|
||||||
it('render every story', () => {
|
|
||||||
// jest.spyOn(i18n, 'useTranslationContext').mockImplementation(() => ({ changeLanguage: () => null, lang: 'en' }));
|
|
||||||
|
|
||||||
getFiles('./src').filter(f => re.test(f)).map(f => {
|
|
||||||
// const f = "./src/paths/instance/transfers/list/List.stories.tsx";
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const s = require(`../${f}`)
|
|
||||||
|
|
||||||
delete s.default
|
|
||||||
|
|
||||||
Object.keys(s).forEach(k => {
|
|
||||||
const Component = s[k];
|
|
||||||
expect(() => {
|
|
||||||
try {
|
|
||||||
let p = mount(<Component {...Component.args} /> as any)
|
|
||||||
p.mount()
|
|
||||||
p.unmount()
|
|
||||||
p.mount();
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}).not.toThrow() //`problem rendering ${f} example ${k}`
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
4659
pnpm-lock.yaml
4659
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user