gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 09/13: integrate anastasis to the web-utils testing


From: gnunet
Subject: [taler-wallet-core] 09/13: integrate anastasis to the web-utils testing api
Date: Fri, 21 Apr 2023 16:07:06 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

commit f470f167e32d8f7775ad994f09afb1d353b0b300
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Apr 21 10:47:47 2023 -0300

    integrate anastasis to the web-utils testing api
---
 .../components/picker/DurationPicker.stories.tsx   |  12 +-
 packages/anastasis-webui/src/index.test.ts         |  74 +++-
 .../src/pages/home/AddingProviderScreen/state.ts   |  39 +-
 .../pages/home/AddingProviderScreen/stories.tsx    |  10 +-
 .../src/pages/home/AddingProviderScreen/test.ts    |  33 +-
 .../pages/home/AttributeEntryScreen.stories.tsx    |  57 +--
 .../home/AuthenticationEditorScreen.stories.tsx    | 116 +++---
 .../pages/home/BackupFinishedScreen.stories.tsx    |  10 +-
 .../pages/home/ChallengeOverviewScreen.stories.tsx | 145 +++----
 .../pages/home/ChallengePayingScreen.stories.tsx   |   6 +-
 .../home/ContinentSelectionScreen.stories.tsx      |  13 +-
 .../src/pages/home/EditPoliciesScreen.stories.tsx  |  11 +-
 .../pages/home/PoliciesPayingScreen.stories.tsx    |   8 +-
 .../pages/home/RecoveryFinishedScreen.stories.tsx  |   8 +-
 .../pages/home/ReviewPoliciesScreen.stories.tsx    | 457 +++++++++++----------
 .../src/pages/home/SecretEditorScreen.stories.tsx  |  17 +-
 .../pages/home/SecretSelectionScreen.stories.tsx   |  33 +-
 .../src/pages/home/SolveScreen.stories.tsx         |   9 +-
 .../src/pages/home/StartScreen.stories.tsx         |   6 +-
 .../src/pages/home/TruthsPayingScreen.stories.tsx  |   8 +-
 .../authMethod/AuthMethodEmailSetup.stories.tsx    |  15 +-
 .../authMethod/AuthMethodEmailSolve.stories.tsx    |  19 +-
 .../authMethod/AuthMethodIbanSetup.stories.tsx     |  15 +-
 .../authMethod/AuthMethodIbanSolve.stories.tsx     |  13 +-
 .../authMethod/AuthMethodPostSetup.stories.tsx     |  15 +-
 .../authMethod/AuthMethodPostSolve.stories.tsx     |  11 +-
 .../authMethod/AuthMethodQuestionSetup.stories.tsx |  15 +-
 .../authMethod/AuthMethodQuestionSolve.stories.tsx | 220 +++++-----
 .../home/authMethod/AuthMethodSmsSetup.stories.tsx |  15 +-
 .../home/authMethod/AuthMethodSmsSolve.stories.tsx |  11 +-
 .../authMethod/AuthMethodTotpSetup.stories.tsx     |  15 +-
 .../authMethod/AuthMethodTotpSolve.stories.tsx     |  13 +-
 .../{index.storiesNo.tsx => index.stories.tsx}     |   2 +
 packages/anastasis-webui/src/stories.tsx           |   2 +-
 packages/anastasis-webui/src/test-utils.ts         | 205 ---------
 packages/anastasis-webui/src/utils/index.tsx       |  57 +--
 36 files changed, 775 insertions(+), 940 deletions(-)

diff --git 
a/packages/anastasis-webui/src/components/picker/DurationPicker.stories.tsx 
b/packages/anastasis-webui/src/components/picker/DurationPicker.stories.tsx
index 0339c9ec0..b4844c706 100644
--- a/packages/anastasis-webui/src/components/picker/DurationPicker.stories.tsx
+++ b/packages/anastasis-webui/src/components/picker/DurationPicker.stories.tsx
@@ -22,6 +22,7 @@
 import { h, FunctionalComponent } from "preact";
 import { useState } from "preact/hooks";
 import { DurationPicker as TestedComponent } from "./DurationPicker.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   component: TestedComponent,
@@ -31,16 +32,7 @@ export default {
   },
 };
 
-function createExample<Props>(
-  Component: FunctionalComponent<Props>,
-  props: Partial<Props>,
-) {
-  const r = (args: any) => <Component {...args} />;
-  r.args = props;
-  return r;
-}
-
-export const Example = createExample(TestedComponent, {
+export const Example = tests.createExample(TestedComponent, {
   days: true,
   minutes: true,
   hours: true,
diff --git a/packages/anastasis-webui/src/index.test.ts 
b/packages/anastasis-webui/src/index.test.ts
index 572ce4a46..f5873f540 100644
--- a/packages/anastasis-webui/src/index.test.ts
+++ b/packages/anastasis-webui/src/index.test.ts
@@ -19,31 +19,63 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 import { setupI18n } from "@gnu-taler/taler-util";
-import { renderNodeOrBrowser } from "./test-utils.js";
-import * as pages from "./pages/home/index.storiesNo.js";
+import { parseGroupImport, tests } from 
"@gnu-taler/web-util/lib/index.browser";
+import * as pages from "./pages/home/index.stories.js";
+import { ComponentChildren, VNode, h as create } from "preact";
+import { AnastasisProvider } from "./context/anastasis.js";
+import { AnastasisReducerApi } from "./hooks/use-anastasis-reducer.js";
+import { ReducerState } from "@gnu-taler/anastasis-core";
 
 setupI18n("en", { en: {} });
 
-function testThisStory(key: string, st: any): any {
-  describe.skip(`render examples for ${key}`, () => {
-    Object.keys(st).forEach((k) => {
-      const Component = (st as any)[k];
-      if (k === "default" || !Component) return;
-
-      it(`example: ${k}`, () => {
-        renderNodeOrBrowser(Component, Component.args);
+describe("All the examples:", () => {
+  const cms = parseGroupImport({ pages });
+  cms.forEach((group) => {
+    describe(`Example for group "${group.title}":`, () => {
+      group.list.forEach((component) => {
+        describe(`Component ${component.name}:`, () => {
+          component.examples.forEach((example) => {
+            it(`should render example: ${example.name}`, () => {
+              tests.renderUI(example.render, DefaultTestingContext);
+            });
+          });
+        });
       });
     });
   });
-}
-
-describe.skip("render every storybook example", () => {
-  Object.entries(pages).forEach(function testAll([key, value]) {
-    const st: any = value;
-    if (Array.isArray(st.default)) {
-      st.default.forEach(testAll);
-    } else {
-      testThisStory(key, st);
-    }
-  });
 });
+
+const noop = async (): Promise<void> => {
+  return;
+};
+
+function DefaultTestingContext({
+  children,
+  ...rest
+}: {
+  children: ComponentChildren;
+}): VNode {
+  //some UI example can specify the state of the reducer
+  const currentReducerState = rest as ReducerState;
+  const value: AnastasisReducerApi = {
+    currentReducerState,
+    discoverMore: noop,
+    discoverStart: noop,
+    discoveryState: {
+      state: "finished",
+    },
+    currentError: undefined,
+    back: noop,
+    dismissError: noop,
+    reset: noop,
+    runTransaction: noop,
+    startBackup: noop,
+    startRecover: noop,
+    transition: noop,
+    exportState: () => {
+      return "{}";
+    },
+    importState: noop,
+  };
+  return create(AnastasisProvider, { value, children });
+}
diff --git 
a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts 
b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts
index 009ab20a2..f80f1c464 100644
--- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts
+++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts
@@ -25,7 +25,11 @@ interface Props {
   notifications?: Notification[];
 }
 
-export default function useComponentState({ providerType, onCancel, 
notifications = [] }: Props): State {
+export default function useComponentState({
+  providerType,
+  onCancel,
+  notifications = [],
+}: Props): State {
   const reducer = useAnastasisContext();
 
   const [providerURL, setProviderURL] = useState("");
@@ -39,9 +43,9 @@ export default function useComponentState({ providerType, 
onCancel, notification
 
   const allAuthProviders =
     !reducer ||
-      !reducer.currentReducerState ||
-      reducer.currentReducerState.reducer_type === "error" ||
-      !reducer.currentReducerState.authentication_providers
+    !reducer.currentReducerState ||
+    reducer.currentReducerState.reducer_type === "error" ||
+    !reducer.currentReducerState.authentication_providers
       ? {}
       : reducer.currentReducerState.authentication_providers;
 
@@ -58,7 +62,12 @@ export default function useComponentState({ providerType, 
onCancel, notification
       prev[p.status].push({ ...p, url });
       return prev;
     },
-    { "not-contacted": [], disabled: [], error: [], ok: [] } as 
AuthProvByStatusMap,
+    {
+      "not-contacted": [],
+      disabled: [],
+      error: [],
+      ok: [],
+    } as AuthProvByStatusMap,
   );
   const authProviders = authProvidersByStatus["ok"].map((p) => p.url);
 
@@ -98,10 +107,10 @@ export default function useComponentState({ providerType, 
onCancel, notification
   const addProvider = async (provider_url: string): Promise<void> => {
     await reducer.transition("add_provider", { provider_url });
     onCancel();
-  }
+  };
   const deleteProvider = async (provider_url: string): Promise<void> => {
     reducer.transition("delete_provider", { provider_url });
-  }
+  };
 
   let errors = !providerURL ? "Add provider URL" : undefined;
   let url: string | undefined;
@@ -110,7 +119,7 @@ export default function useComponentState({ providerType, 
onCancel, notification
   } catch {
     errors = "Check the URL";
   }
-  const _url = url
+  const _url = url;
 
   if (!!error && !errors) {
     errors = error;
@@ -130,21 +139,19 @@ export default function useComponentState({ providerType, 
onCancel, notification
     setProviderURL: async (s: string) => setProviderURL(s),
     errors,
     error,
-    notifications
-  }
+    notifications,
+  };
 
   if (!providerLabel) {
     return {
       status: "without-type",
-      ...commonState
-    }
+      ...commonState,
+    };
   } else {
     return {
       status: "with-type",
       providerLabel,
-      ...commonState
-    }
+      ...commonState,
+    };
   }
-
 }
-
diff --git 
a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx 
b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx
index 268189ed8..6ce22e56c 100644
--- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx
@@ -20,7 +20,7 @@
  */
 
 import { AuthenticationProviderStatusOk } from "@gnu-taler/anastasis-core";
-import { createExampleWithoutAnastasis } from "../../../utils/index.jsx";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 import { WithoutProviderType, WithProviderType } from "./views.jsx";
 
 export default {
@@ -34,7 +34,7 @@ export default {
   },
 };
 
-export const NewProvider = createExampleWithoutAnastasis(WithoutProviderType, {
+export const NewProvider = tests.createExample(WithoutProviderType, {
   authProvidersByStatus: {
     ok: [
       {
@@ -57,7 +57,7 @@ export const NewProvider = 
createExampleWithoutAnastasis(WithoutProviderType, {
   notifications: [],
 });
 
-export const NewProviderWithoutProviderList = createExampleWithoutAnastasis(
+export const NewProviderWithoutProviderList = tests.createExample(
   WithoutProviderType,
   {
     authProvidersByStatus: {
@@ -70,7 +70,7 @@ export const NewProviderWithoutProviderList = 
createExampleWithoutAnastasis(
   },
 );
 
-export const NewSmsProvider = createExampleWithoutAnastasis(WithProviderType, {
+export const NewSmsProvider = tests.createExample(WithProviderType, {
   authProvidersByStatus: {
     ok: [],
     "not-contacted": [],
@@ -81,7 +81,7 @@ export const NewSmsProvider = 
createExampleWithoutAnastasis(WithProviderType, {
   notifications: [],
 });
 
-export const NewIBANProvider = createExampleWithoutAnastasis(WithProviderType, 
{
+export const NewIBANProvider = tests.createExample(WithProviderType, {
   authProvidersByStatus: {
     ok: [],
     "not-contacted": [],
diff --git 
a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts 
b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts
index d051d7c0b..8d0e69111 100644
--- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts
+++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts
@@ -20,23 +20,26 @@
  */
 
 import { expect } from "chai";
-import { mountHook } from "../../../test-utils.js";
 import useComponentState from "./state.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 describe("AddingProviderScreen states", () => {
-  it("should have status 'no-balance' when balance is empty", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
-      mountHook(() =>
-        useComponentState({ onCancel: async () => { null } }),
-      );
-
-    {
-      const { status } = getLastResultOrThrow();
-      expect(status).equal("no-reducer");
-    }
-
-    await assertNoPendingUpdate();
-
+  it("should not load more if has reach the end", async () => {
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        return useComponentState({
+          providerType: "email",
+          async onCancel() {},
+        });
+      },
+      {},
+      [
+        ({ status }) => {
+          expect(status).eq("no-reducer");
+        },
+      ],
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
   });
-
 });
diff --git 
a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
index 38fc1b56b..bc62961a5 100644
--- a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx
@@ -20,7 +20,8 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../utils/index.js";
 import { AttributeEntryScreen as TestedComponent } from 
"./AttributeEntryScreen.js";
 
 export default {
@@ -35,7 +36,7 @@ export default {
   },
 };
 
-export const Backup = createExample(TestedComponent, {
+export const Backup = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.backupAttributeEditing,
   required_attributes: [
     {
@@ -62,7 +63,7 @@ export const Backup = createExample(TestedComponent, {
   ],
 } as ReducerState);
 
-export const Recovery = createExample(TestedComponent, {
+export const Recovery = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.recoveryAttributeEditing,
   required_attributes: [
     {
@@ -89,10 +90,14 @@ export const Recovery = createExample(TestedComponent, {
   ],
 } as ReducerState);
 
-export const WithNoRequiredAttribute = createExample(TestedComponent, {
-  ...reducerStatesExample.backupAttributeEditing,
-  required_attributes: undefined,
-} as ReducerState);
+export const WithNoRequiredAttribute = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.backupAttributeEditing,
+    required_attributes: undefined,
+  } as ReducerState,
+);
 
 const allWidgets = [
   "anastasis_gtk_ia_aadhar_in",
@@ -123,7 +128,7 @@ function typeForWidget(name: string): string {
   return "string";
 }
 
-export const WithAllPosibleWidget = createExample(TestedComponent, {
+export const WithAllPosibleWidget = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.backupAttributeEditing,
   required_attributes: allWidgets.map((w) => ({
     name: w,
@@ -134,19 +139,23 @@ export const WithAllPosibleWidget = 
createExample(TestedComponent, {
   })),
 } as ReducerState);
 
-export const WithAutocompleteFeature = createExample(TestedComponent, {
-  ...reducerStatesExample.backupAttributeEditing,
-  required_attributes: [
-    {
-      name: "ahv_number",
-      label: "AHV Number",
-      type: "string",
-      uuid: "asdasdsa1",
-      widget: "wid",
-      "validation-regex":
-        "^(756)\\.[0-9]{4}\\.[0-9]{4}\\.[0-9]{2}|(756)[0-9]{10}$",
-      "validation-logic": "CH_AHV_check",
-      autocomplete: "???.????.????.??",
-    },
-  ],
-} as ReducerState);
+export const WithAutocompleteFeature = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.backupAttributeEditing,
+    required_attributes: [
+      {
+        name: "ahv_number",
+        label: "AHV Number",
+        type: "string",
+        uuid: "asdasdsa1",
+        widget: "wid",
+        "validation-regex":
+          "^(756)\\.[0-9]{4}\\.[0-9]{4}\\.[0-9]{2}|(756)[0-9]{10}$",
+        "validation-logic": "CH_AHV_check",
+        autocomplete: "???.????.????.??",
+      },
+    ],
+  } as ReducerState,
+);
diff --git 
a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
index ba48e2d5c..23212c184 100644
--- 
a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx
@@ -20,7 +20,8 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../utils/index.js";
 import { AuthenticationEditorScreen as TestedComponent } from 
"./AuthenticationEditorScreen.js";
 
 export default {
@@ -35,63 +36,72 @@ export default {
   },
 };
 
-export const InitialState = createExample(
+export const InitialState = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.authEditing,
 );
-export const OneAuthMethodConfigured = createExample(TestedComponent, {
-  ...reducerStatesExample.authEditing,
-  authentication_methods: [
-    {
-      type: "question",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-  ],
-} as ReducerState);
+export const OneAuthMethodConfigured = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.authEditing,
+    authentication_methods: [
+      {
+        type: "question",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+    ],
+  } as ReducerState,
+);
 
-export const SomeMoreAuthMethodConfigured = createExample(TestedComponent, {
-  ...reducerStatesExample.authEditing,
-  authentication_methods: [
-    {
-      type: "question",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-    {
-      type: "question",
-      instructions: "what time is it?",
-      challenge: "qwe",
-    },
-    {
-      type: "sms",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-    {
-      type: "email",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-    {
-      type: "email",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-    {
-      type: "email",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-    {
-      type: "email",
-      instructions: "what time is it?",
-      challenge: "asd",
-    },
-  ],
-} as ReducerState);
+export const SomeMoreAuthMethodConfigured = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.authEditing,
+    authentication_methods: [
+      {
+        type: "question",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+      {
+        type: "question",
+        instructions: "what time is it?",
+        challenge: "qwe",
+      },
+      {
+        type: "sms",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+      {
+        type: "email",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+      {
+        type: "email",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+      {
+        type: "email",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+      {
+        type: "email",
+        instructions: "what time is it?",
+        challenge: "asd",
+      },
+    ],
+  } as ReducerState,
+);
 
-export const NoAuthMethodProvided = createExample(TestedComponent, {
+export const NoAuthMethodProvided = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.authEditing,
   authentication_providers: {},
   authentication_methods: [],
diff --git 
a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
index 8aeaec25c..fce823bec 100644
--- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { BackupFinishedScreen as TestedComponent } from 
"./BackupFinishedScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Backup finish",
@@ -35,17 +36,18 @@ export default {
   },
 };
 
-export const WithoutName = createExample(
+export const WithoutName = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.backupFinished,
 );
 
-export const WithName = createExample(TestedComponent, {
+export const WithName = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.backupFinished,
   secret_name: "super_secret",
 } as ReducerState);
 
-export const WithDetails = createExample(TestedComponent, {
+export const WithDetails = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.backupFinished,
   secret_name: "super_secret",
   success_details: {
diff --git 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
index d2471755a..f41f894e8 100644
--- 
a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
@@ -24,8 +24,9 @@ import {
   RecoveryStates,
   ReducerState,
 } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { ChallengeOverviewScreen as TestedComponent } from 
"./ChallengeOverviewScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Challenge overview",
@@ -39,7 +40,7 @@ export default {
   },
 };
 
-export const OneUnsolvedPolicy = createExample(TestedComponent, {
+export const OneUnsolvedPolicy = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.challengeSelecting,
   recovery_information: {
     policies: [[{ uuid: "1" }]],
@@ -53,7 +54,7 @@ export const OneUnsolvedPolicy = 
createExample(TestedComponent, {
   },
 } as ReducerState);
 
-export const SomePoliciesOneSolved = createExample(TestedComponent, {
+export const SomePoliciesOneSolved = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.challengeSelecting,
   recovery_information: {
     policies: [[{ uuid: "1" }, { uuid: "2" }], [{ uuid: "uuid-3" }]],
@@ -82,7 +83,7 @@ export const SomePoliciesOneSolved = 
createExample(TestedComponent, {
   },
 } as ReducerState);
 
-export const OneBadConfiguredPolicy = createExample(TestedComponent, {
+export const OneBadConfiguredPolicy = tests.createExample(TestedComponent, {}, 
{
   ...reducerStatesExample.challengeSelecting,
   recovery_information: {
     policies: [[{ uuid: "1" }, { uuid: "2" }]],
@@ -96,71 +97,75 @@ export const OneBadConfiguredPolicy = 
createExample(TestedComponent, {
   },
 } as ReducerState);
 
-export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, {
-  ...reducerStatesExample.challengeSelecting,
-  recovery_information: {
-    policies: [
-      [
-        { uuid: "1" },
-        { uuid: "2" },
-        { uuid: "3" },
-        { uuid: "4" },
-        { uuid: "5" },
-        { uuid: "6" },
-        { uuid: "7" },
-        { uuid: "8" },
-      ],
-    ],
-    challenges: [
-      {
-        instructions: "Does P equals NP?",
-        type: "question",
-        uuid: "1",
-      },
-      {
-        instructions: "SMS to 555-555",
-        type: "sms",
-        uuid: "2",
-      },
-      {
-        instructions: "Email to qwe@asd.com",
-        type: "email",
-        uuid: "3",
-      },
-      {
-        instructions: 'Enter 8 digits code for "Anastasis"',
-        type: "totp",
-        uuid: "4",
-      },
-      {
-        //
-        instructions: "Wire transfer from ASDXCVQWE123123 with holder Florian",
-        type: "iban",
-        uuid: "5",
-      },
-      {
-        instructions: "Join a video call",
-        type: "video", //Enter 8 digits code for "Anastasis"
-        uuid: "7",
-      },
-      {},
-      {
-        instructions: "Letter to address in postal code DE123123",
-        type: "post", //Enter 8 digits code for "Anastasis"
-        uuid: "8",
-      },
-      {
-        instructions: "instruction for an unknown type of challenge",
-        type: "new-type-of-challenge",
-        uuid: "6",
-      },
-    ],
-  },
-} as ReducerState);
-
-export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
+export const OnePolicyWithAllTheChallenges = tests.createExample(
   TestedComponent,
+  {},
   {
+    ...reducerStatesExample.challengeSelecting,
+    recovery_information: {
+      policies: [
+        [
+          { uuid: "1" },
+          { uuid: "2" },
+          { uuid: "3" },
+          { uuid: "4" },
+          { uuid: "5" },
+          { uuid: "6" },
+          { uuid: "7" },
+          { uuid: "8" },
+        ],
+      ],
+      challenges: [
+        {
+          instructions: "Does P equals NP?",
+          type: "question",
+          uuid: "1",
+        },
+        {
+          instructions: "SMS to 555-555",
+          type: "sms",
+          uuid: "2",
+        },
+        {
+          instructions: "Email to qwe@asd.com",
+          type: "email",
+          uuid: "3",
+        },
+        {
+          instructions: 'Enter 8 digits code for "Anastasis"',
+          type: "totp",
+          uuid: "4",
+        },
+        {
+          //
+          instructions:
+            "Wire transfer from ASDXCVQWE123123 with holder Florian",
+          type: "iban",
+          uuid: "5",
+        },
+        {
+          instructions: "Join a video call",
+          type: "video", //Enter 8 digits code for "Anastasis"
+          uuid: "7",
+        },
+        {},
+        {
+          instructions: "Letter to address in postal code DE123123",
+          type: "post", //Enter 8 digits code for "Anastasis"
+          uuid: "8",
+        },
+        {
+          instructions: "instruction for an unknown type of challenge",
+          type: "new-type-of-challenge",
+          uuid: "6",
+        },
+      ],
+    },
+  } as ReducerState,
+);
+
+export const OnePolicyWithAllTheChallengesInDifferentState =
+  tests.createExample(TestedComponent, {}, {
     ...reducerStatesExample.challengeSelecting,
     recovery_state: RecoveryStates.ChallengeSelecting,
     recovery_information: {
@@ -258,9 +263,9 @@ export const OnePolicyWithAllTheChallengesInDifferentState 
= createExample(
       },
       "uuid-10": { state: ChallengeFeedbackStatus.IncorrectAnswer.toString() },
     },
-  } as ReducerState,
-);
-export const NoPolicies = createExample(
+  } as ReducerState);
+export const NoPolicies = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.challengeSelecting,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.stories.tsx
index cd41fe03a..086647791 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengePayingScreen.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../utils/index.js";
 import { ChallengePayingScreen as TestedComponent } from 
"./ChallengePayingScreen.js";
 
 export default {
@@ -34,7 +35,8 @@ export default {
   },
 };
 
-export const Example = createExample(
+export const Example = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.challengePaying,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
index 12a79c56c..524b673a9 100644
--- 
a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { ContinentSelectionScreen as TestedComponent } from 
"./ContinentSelectionScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Continent selection",
@@ -35,22 +36,24 @@ export default {
   },
 };
 
-export const BackupSelectContinent = createExample(
+export const BackupSelectContinent = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.backupSelectContinent,
 );
 
-export const BackupSelectCountry = createExample(TestedComponent, {
+export const BackupSelectCountry = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.backupSelectContinent,
   selected_continent: "Testcontinent",
 } as ReducerState);
 
-export const RecoverySelectContinent = createExample(
+export const RecoverySelectContinent = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.recoverySelectContinent,
 );
 
-export const RecoverySelectCountry = createExample(TestedComponent, {
+export const RecoverySelectCountry = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.recoverySelectContinent,
   selected_continent: "Testcontinent",
 } as ReducerState);
diff --git 
a/packages/anastasis-webui/src/pages/home/EditPoliciesScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/EditPoliciesScreen.stories.tsx
index 1e3650300..e43996222 100644
--- a/packages/anastasis-webui/src/pages/home/EditPoliciesScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/EditPoliciesScreen.stories.tsx
@@ -20,7 +20,8 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../utils/index.js";
 import { EditPoliciesScreen as TestedComponent } from 
"./EditPoliciesScreen.js";
 
 export default {
@@ -35,8 +36,9 @@ export default {
   },
 };
 
-export const EditingAPolicy = createExample(
+export const EditingAPolicy = tests.createExample(
   TestedComponent,
+  { index: 0 },
   {
     ...reducerStatesExample.policyReview,
     policies: [
@@ -84,11 +86,11 @@ export const EditingAPolicy = createExample(
       },
     ],
   } as ReducerState,
-  { index: 0 },
 );
 
-export const CreatingAPolicy = createExample(
+export const CreatingAPolicy = tests.createExample(
   TestedComponent,
+  { index: 3 },
   {
     ...reducerStatesExample.policyReview,
     policies: [
@@ -136,5 +138,4 @@ export const CreatingAPolicy = createExample(
       },
     ],
   } as ReducerState,
-  { index: 3 },
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx
index 56c224d34..aaaae25c9 100644
--- a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { PoliciesPayingScreen as TestedComponent } from 
"./PoliciesPayingScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Policies paying",
@@ -35,11 +36,12 @@ export default {
   },
 };
 
-export const Example = createExample(
+export const Example = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.policyPay,
 );
-export const WithSomePaymentRequest = createExample(TestedComponent, {
+export const WithSomePaymentRequest = tests.createExample(TestedComponent, {}, 
{
   ...reducerStatesExample.policyPay,
   policy_payment_requests: [
     {
diff --git 
a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
index 1eb2ae50c..1a5c41f94 100644
--- a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx
@@ -21,8 +21,9 @@
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
 import { encodeCrock, stringToBytes } from "@gnu-taler/taler-util";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { RecoveryFinishedScreen as TestedComponent } from 
"./RecoveryFinishedScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Recovery Finished",
@@ -36,7 +37,7 @@ export default {
   },
 };
 
-export const GoodEnding = createExample(TestedComponent, {
+export const GoodEnding = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.recoveryFinished,
   recovery_document: {
     secret_name: "the_name_of_the_secret",
@@ -49,7 +50,8 @@ export const GoodEnding = createExample(TestedComponent, {
   },
 } as ReducerState);
 
-export const BadEnding = createExample(
+export const BadEnding = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.recoveryFinished,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
index c5003d6a0..7cde84e0f 100644
--- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { ReviewPoliciesScreen as TestedComponent } from 
"./ReviewPoliciesScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Reviewing Policies",
@@ -35,227 +36,235 @@ export default {
   },
 };
 
-export const HasPoliciesButMethodListIsEmpty = createExample(TestedComponent, {
-  ...reducerStatesExample.policyReview,
-  policies: [
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "asd",
-        },
-        {
-          authentication_method: 1,
-          provider: "asd",
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 1,
-          provider: "asd",
-        },
-      ],
-    },
-  ],
-  authentication_methods: [],
-} as ReducerState);
+export const HasPoliciesButMethodListIsEmpty = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.policyReview,
+    policies: [
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "asd",
+          },
+          {
+            authentication_method: 1,
+            provider: "asd",
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 1,
+            provider: "asd",
+          },
+        ],
+      },
+    ],
+    authentication_methods: [],
+  } as ReducerState,
+);
 
-export const SomePoliciesWithMethods = createExample(TestedComponent, {
-  ...reducerStatesExample.policyReview,
-  policies: [
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 1,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 2,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 1,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 3,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 1,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 4,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 2,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 3,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 2,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 4,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 0,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 3,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-        {
-          authentication_method: 4,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 1,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 2,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 3,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 1,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 2,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 4,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 1,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 3,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-        {
-          authentication_method: 4,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-    {
-      methods: [
-        {
-          authentication_method: 2,
-          provider: "https://kudos.demo.anastasis.lu/";,
-        },
-        {
-          authentication_method: 3,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-        {
-          authentication_method: 4,
-          provider: "https://anastasis.demo.taler.net/";,
-        },
-      ],
-    },
-  ],
-  authentication_methods: [
-    {
-      type: "email",
-      instructions: "Email to qwe@asd.com",
-      challenge: "E5VPA",
-    },
-    {
-      type: "sms",
-      instructions: "SMS to 555-555",
-      challenge: "",
-    },
-    {
-      type: "question",
-      instructions: "Does P equal NP?",
-      challenge: "C5SP8",
-    },
-    {
-      type: "totp",
-      instructions: "Response code for 'Anastasis'",
-      challenge: "E5VPA",
-    },
-    {
-      type: "sms",
-      instructions: "SMS to 6666-6666",
-      challenge: "",
-    },
-    {
-      type: "question",
-      instructions: "How did the chicken cross the road?",
-      challenge: "C5SP8",
-    },
-  ],
-} as ReducerState);
+export const SomePoliciesWithMethods = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.policyReview,
+    policies: [
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 1,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 2,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 1,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 3,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 1,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 4,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 2,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 3,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 2,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 4,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 0,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 3,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+          {
+            authentication_method: 4,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 1,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 2,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 3,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 1,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 2,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 4,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 1,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 3,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+          {
+            authentication_method: 4,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+      {
+        methods: [
+          {
+            authentication_method: 2,
+            provider: "https://kudos.demo.anastasis.lu/";,
+          },
+          {
+            authentication_method: 3,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+          {
+            authentication_method: 4,
+            provider: "https://anastasis.demo.taler.net/";,
+          },
+        ],
+      },
+    ],
+    authentication_methods: [
+      {
+        type: "email",
+        instructions: "Email to qwe@asd.com",
+        challenge: "E5VPA",
+      },
+      {
+        type: "sms",
+        instructions: "SMS to 555-555",
+        challenge: "",
+      },
+      {
+        type: "question",
+        instructions: "Does P equal NP?",
+        challenge: "C5SP8",
+      },
+      {
+        type: "totp",
+        instructions: "Response code for 'Anastasis'",
+        challenge: "E5VPA",
+      },
+      {
+        type: "sms",
+        instructions: "SMS to 6666-6666",
+        challenge: "",
+      },
+      {
+        type: "question",
+        instructions: "How did the chicken cross the road?",
+        challenge: "C5SP8",
+      },
+    ],
+  } as ReducerState,
+);
diff --git 
a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx
index dbf8bf128..b0e32258b 100644
--- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { SecretEditorScreen as TestedComponent } from 
"./SecretEditorScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Secret editor",
@@ -35,11 +36,15 @@ export default {
   },
 };
 
-export const WithSecretNamePreselected = createExample(TestedComponent, {
-  ...reducerStatesExample.secretEdition,
-  secret_name: "someSecretName",
-} as ReducerState);
+export const WithSecretNamePreselected = tests.createExample(
+  TestedComponent,
+  {},
+  {
+    ...reducerStatesExample.secretEdition,
+    secret_name: "someSecretName",
+  } as ReducerState,
+);
 
-export const WithoutName = createExample(TestedComponent, {
+export const WithoutName = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.secretEdition,
 } as ReducerState);
diff --git 
a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx
index 7669668ee..2da80a8bb 100644
--- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx
@@ -20,7 +20,8 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../utils/index.js";
 import {
   SecretSelectionScreen,
   SecretSelectionScreenFound,
@@ -34,16 +35,8 @@ export default {
   },
 };
 
-export const Example = createExample(
+export const Example = tests.createExample(
   SecretSelectionScreenFound,
-  {
-    ...reducerStatesExample.secretSelection,
-    recovery_document: {
-      provider_url: "https://kudos.demo.anastasis.lu/";,
-      secret_name: "secretName",
-      version: 1,
-    },
-  } as ReducerState,
   {
     policies: [
       {
@@ -70,9 +63,21 @@ export const Example = createExample(
       },
     ],
   },
+  {
+    ...reducerStatesExample.secretSelection,
+    recovery_document: {
+      provider_url: "https://kudos.demo.anastasis.lu/";,
+      secret_name: "secretName",
+      version: 1,
+    },
+  } as ReducerState,
 );
 
-export const NoRecoveryDocumentFound = createExample(SecretSelectionScreen, {
-  ...reducerStatesExample.secretSelection,
-  recovery_document: undefined,
-} as ReducerState);
+export const NoRecoveryDocumentFound = tests.createExample(
+  SecretSelectionScreen,
+  {},
+  {
+    ...reducerStatesExample.secretSelection,
+    recovery_document: undefined,
+  } as ReducerState,
+);
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
index 1058ae126..b6d891fdd 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { SolveScreen as TestedComponent } from "./SolveScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Solve Screen",
@@ -35,12 +36,12 @@ export default {
   },
 };
 
-export const NoInformation = createExample(
+export const NoInformation = tests.createExample(
   TestedComponent,
   reducerStatesExample.challengeSolving,
 );
 
-export const NotSupportedChallenge = createExample(TestedComponent, {
+export const NotSupportedChallenge = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.challengeSolving,
   recovery_information: {
     challenges: [
@@ -55,7 +56,7 @@ export const NotSupportedChallenge = 
createExample(TestedComponent, {
   selected_challenge_uuid: "ASDASDSAD!1",
 } as ReducerState);
 
-export const MismatchedChallengeId = createExample(TestedComponent, {
+export const MismatchedChallengeId = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.challengeSolving,
   recovery_information: {
     challenges: [
diff --git a/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx
index 960426098..3745c834b 100644
--- a/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../utils/index.js";
 import { StartScreen as TestedComponent } from "./StartScreen.js";
 
 export default {
@@ -34,7 +35,8 @@ export default {
   },
 };
 
-export const InitialState = createExample(
+export const InitialState = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.initial,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx 
b/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx
index 40ed5117c..dafb4bc58 100644
--- a/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../utils/index.js";
+import { reducerStatesExample } from "../../utils/index.js";
 import { TruthsPayingScreen as TestedComponent } from 
"./TruthsPayingScreen.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Truths Paying",
@@ -35,11 +36,12 @@ export default {
   },
 };
 
-export const Example = createExample(
+export const Example = tests.createExample(
   TestedComponent,
+  {},
   reducerStatesExample.truthsPaying,
 );
-export const WithPaytoList = createExample(TestedComponent, {
+export const WithPaytoList = tests.createExample(TestedComponent, {}, {
   ...reducerStatesExample.truthsPaying,
   payments: ["payto://x-taler-bank/bank/account"],
 } as ReducerState);
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
index 4a2d76ca3..98119700a 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSetup.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
 
 export default {
@@ -36,17 +37,16 @@ export default {
 
 const type: KnownAuthMethods = "email";
 
-export const Empty = createExample(
+export const Empty = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithOneExample = createExample(
+export const WithOneExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -57,11 +57,11 @@ export const WithOneExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithMoreExamples = createExample(
+export const WithMoreExamples = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -78,4 +78,5 @@ export const WithMoreExamples = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
index cc378d8f6..6bf6c2e30 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodEmailSolve.stories.tsx
@@ -23,8 +23,9 @@ import {
   ChallengeFeedbackStatus,
   ReducerState,
 } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Auth method: Email solve",
@@ -40,8 +41,11 @@ export default {
 
 const type: KnownAuthMethods = "email";
 
-export const WithoutFeedback = createExample(
+export const WithoutFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "uuid-1",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -56,13 +60,13 @@ export const WithoutFeedback = createExample(
     },
     selected_challenge_uuid: "uuid-1",
   } as ReducerState,
-  {
-    id: "uuid-1",
-  },
 );
 
-export const PaymentFeedback = createExample(
+export const PaymentFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "uuid-1",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -85,7 +89,4 @@ export const PaymentFeedback = createExample(
       },
     },
   } as ReducerState,
-  {
-    id: "uuid-1",
-  },
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
index dfe3850f1..8dd141b61 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSetup.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
 
 export default {
@@ -36,17 +37,16 @@ export default {
 
 const type: KnownAuthMethods = "iban";
 
-export const Empty = createExample(
+export const Empty = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithOneExample = createExample(
+export const WithOneExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -57,10 +57,10 @@ export const WithOneExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
-export const WithMoreExamples = createExample(
+export const WithMoreExamples = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -77,4 +77,5 @@ export const WithMoreExamples = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx
index 8a9a3f7a0..1aa257259 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodIbanSolve.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
-import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
+import { KnownAuthMethods, authMethods as TestedComponent } from "./index.js";
 
 export default {
   title: "Auth method: IBAN Solve",
@@ -37,8 +38,11 @@ export default {
 
 const type: KnownAuthMethods = "iban";
 
-export const WithoutFeedback = createExample(
+export const WithoutFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "uuid-1",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -53,7 +57,4 @@ export const WithoutFeedback = createExample(
     },
     selected_challenge_uuid: "uuid-1",
   } as ReducerState,
-  {
-    id: "uuid-1",
-  },
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
index 8a32c45c1..9a92ae109 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSetup.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
 
 export default {
@@ -36,17 +37,16 @@ export default {
 
 const type: KnownAuthMethods = "post";
 
-export const Empty = createExample(
+export const Empty = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithOneExample = createExample(
+export const WithOneExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -57,11 +57,11 @@ export const WithOneExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithMoreExamples = createExample(
+export const WithMoreExamples = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -78,4 +78,5 @@ export const WithMoreExamples = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx
index 702ba2810..d28680801 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodPostSolve.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Auth method: Post solve",
@@ -37,8 +38,11 @@ export default {
 
 const type: KnownAuthMethods = "post";
 
-export const WithoutFeedback = createExample(
+export const WithoutFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "uuid-1",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -53,7 +57,4 @@ export const WithoutFeedback = createExample(
     },
     selected_challenge_uuid: "uuid-1",
   } as ReducerState,
-  {
-    id: "uuid-1",
-  },
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
index 2e108b4e6..c365a7e06 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSetup.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
 
 export default {
@@ -36,17 +37,16 @@ export default {
 
 const type: KnownAuthMethods = "question";
 
-export const Empty = createExample(
+export const Empty = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithOneExample = createExample(
+export const WithOneExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -58,11 +58,11 @@ export const WithOneExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithMoreExamples = createExample(
+export const WithMoreExamples = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -80,4 +80,5 @@ export const WithMoreExamples = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
index f7116bf6f..b9dff6363 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodQuestionSolve.stories.tsx
@@ -23,8 +23,9 @@ import {
   ChallengeFeedbackStatus,
   ReducerState,
 } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Auth method: Question solve",
@@ -40,8 +41,11 @@ export default {
 
 const type: KnownAuthMethods = "question";
 
-export const WithoutFeedback = createExample(
+export const WithoutFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "uuid-1",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -56,9 +60,6 @@ export const WithoutFeedback = createExample(
     },
     selected_challenge_uuid: "uuid-1",
   } as ReducerState,
-  {
-    id: "uuid-1",
-  },
 );
 
 const recovery_information = {
@@ -72,45 +73,58 @@ const recovery_information = {
   policies: [],
 };
 
-export const CodeInFileFeedback = createExample(TestedComponent[type].solve, {
-  ...reducerStatesExample.challengeSolving,
-  recovery_information,
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.CodeInFile,
-      filename: "asd",
-      display_hint: "hint",
+export const CodeInFileFeedback = tests.createExample(
+  TestedComponent[type].solve,
+  {},
+  {
+    ...reducerStatesExample.challengeSolving,
+    recovery_information,
+    selected_challenge_uuid: "ASDASDSAD!1",
+    challenge_feedback: {
+      "ASDASDSAD!1": {
+        state: ChallengeFeedbackStatus.CodeInFile,
+        filename: "asd",
+        display_hint: "hint",
+      },
     },
-  },
-} as ReducerState);
-
-export const CodeSentFeedback = createExample(TestedComponent[type].solve, {
-  ...reducerStatesExample.challengeSolving,
-  recovery_information,
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.CodeSent,
-      address_hint: "asdasd",
-      display_hint: "qweqweqw",
+  } as ReducerState,
+);
+
+export const CodeSentFeedback = tests.createExample(
+  TestedComponent[type].solve,
+  {},
+  {
+    ...reducerStatesExample.challengeSolving,
+    recovery_information,
+    selected_challenge_uuid: "ASDASDSAD!1",
+    challenge_feedback: {
+      "ASDASDSAD!1": {
+        state: ChallengeFeedbackStatus.CodeSent,
+        address_hint: "asdasd",
+        display_hint: "qweqweqw",
+      },
     },
-  },
-} as ReducerState);
-
-export const SolvedFeedback = createExample(TestedComponent[type].solve, {
-  ...reducerStatesExample.challengeSolving,
-  recovery_information,
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.Solved,
+  } as ReducerState,
+);
+
+export const SolvedFeedback = tests.createExample(
+  TestedComponent[type].solve,
+  {},
+  {
+    ...reducerStatesExample.challengeSolving,
+    recovery_information,
+    selected_challenge_uuid: "ASDASDSAD!1",
+    challenge_feedback: {
+      "ASDASDSAD!1": {
+        state: ChallengeFeedbackStatus.Solved,
+      },
     },
-  },
-} as ReducerState);
+  } as ReducerState,
+);
 
-export const ServerFailureFeedback = createExample(
+export const ServerFailureFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {},
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information,
@@ -124,45 +138,58 @@ export const ServerFailureFeedback = createExample(
   } as ReducerState,
 );
 
-export const TruthUnknownFeedback = createExample(TestedComponent[type].solve, 
{
-  ...reducerStatesExample.challengeSolving,
-  recovery_information,
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.TruthUnknown,
+export const TruthUnknownFeedback = tests.createExample(
+  TestedComponent[type].solve,
+  {},
+  {
+    ...reducerStatesExample.challengeSolving,
+    recovery_information,
+    selected_challenge_uuid: "ASDASDSAD!1",
+    challenge_feedback: {
+      "ASDASDSAD!1": {
+        state: ChallengeFeedbackStatus.TruthUnknown,
+      },
     },
-  },
-} as ReducerState);
-
-export const TalerPaymentFeedback = createExample(TestedComponent[type].solve, 
{
-  ...reducerStatesExample.challengeSolving,
-  recovery_information,
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.TalerPayment,
-      payment_secret: "secret",
-      provider: "asdasdas",
-      taler_pay_uri: "taler://pay/...",
+  } as ReducerState,
+);
+
+export const TalerPaymentFeedback = tests.createExample(
+  TestedComponent[type].solve,
+  {},
+  {
+    ...reducerStatesExample.challengeSolving,
+    recovery_information,
+    selected_challenge_uuid: "ASDASDSAD!1",
+    challenge_feedback: {
+      "ASDASDSAD!1": {
+        state: ChallengeFeedbackStatus.TalerPayment,
+        payment_secret: "secret",
+        provider: "asdasdas",
+        taler_pay_uri: "taler://pay/...",
+      },
     },
-  },
-} as ReducerState);
-
-export const UnsupportedFeedback = createExample(TestedComponent[type].solve, {
-  ...reducerStatesExample.challengeSolving,
-  recovery_information,
-  selected_challenge_uuid: "ASDASDSAD!1",
-  challenge_feedback: {
-    "ASDASDSAD!1": {
-      state: ChallengeFeedbackStatus.Unsupported,
-      unsupported_method: "method",
+  } as ReducerState,
+);
+
+export const UnsupportedFeedback = tests.createExample(
+  TestedComponent[type].solve,
+  {},
+  {
+    ...reducerStatesExample.challengeSolving,
+    recovery_information,
+    selected_challenge_uuid: "ASDASDSAD!1",
+    challenge_feedback: {
+      "ASDASDSAD!1": {
+        state: ChallengeFeedbackStatus.Unsupported,
+        unsupported_method: "method",
+      },
     },
-  },
-} as ReducerState);
+  } as ReducerState,
+);
 
-export const RateLimitExceededFeedback = createExample(
+export const RateLimitExceededFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {},
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information,
@@ -175,8 +202,9 @@ export const RateLimitExceededFeedback = createExample(
   } as ReducerState,
 );
 
-export const IbanInstructionsFeedback = createExample(
+export const IbanInstructionsFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {},
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information,
@@ -194,8 +222,9 @@ export const IbanInstructionsFeedback = createExample(
   } as ReducerState,
 );
 
-export const IncorrectAnswerFeedback = createExample(
+export const IncorrectAnswerFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {},
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information,
@@ -207,44 +236,3 @@ export const IncorrectAnswerFeedback = createExample(
     },
   } as ReducerState,
 );
-
-// export const AuthIbanFeedback = createExample(TestedComponent[type].solve, {
-//   ...reducerStatesExample.challengeSolving,
-//   recovery_information: {
-//     challenges: [
-//       {
-//         instructions: "does P equals NP?",
-//         type: "question",
-//         uuid: "ASDASDSAD!1",
-//       },
-//     ],
-//     policies: [],
-//   },
-//   selected_challenge_uuid: "ASDASDSAD!1",
-//   challenge_feedback: {
-//     "ASDASDSAD!1": ibanFeedback,
-//   },
-// } as ReducerState);
-
-// export const PaymentFeedback = createExample(TestedComponent[type].solve, {
-//   ...reducerStatesExample.challengeSolving,
-//   recovery_information: {
-//     challenges: [
-//       {
-//         instructions: "does P equals NP?",
-//         type: "question",
-//         uuid: "ASDASDSAD!1",
-//       },
-//     ],
-//     policies: [],
-//   },
-//   selected_challenge_uuid: "ASDASDSAD!1",
-//   challenge_feedback: {
-//     "ASDASDSAD!1": {
-//       state: ChallengeFeedbackStatus.TalerPayment,
-//       taler_pay_uri: "taler://pay/...",
-//       provider: "https://localhost:8080/";,
-//       payment_secret: 
"3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG",
-//     },
-//   },
-// } as ReducerState);
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
index b2c6cb61d..d98a7ec89 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSetup.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
 
 export default {
@@ -36,17 +37,16 @@ export default {
 
 const type: KnownAuthMethods = "sms";
 
-export const Empty = createExample(
+export const Empty = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithOneExample = createExample(
+export const WithOneExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -57,11 +57,11 @@ export const WithOneExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
 
-export const WithMoreExamples = createExample(
+export const WithMoreExamples = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -78,4 +78,5 @@ export const WithMoreExamples = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx
index 2064f12ff..1fb20b6d2 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodSmsSolve.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
 
 export default {
   title: "Auth method: SMS solve",
@@ -37,8 +38,11 @@ export default {
 
 const type: KnownAuthMethods = "sms";
 
-export const WithoutFeedback = createExample(
+export const WithoutFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "AHCC4ZJ3Z1AF8TWBKGVGEKCQ3R7HXHJ51MJ45NHNZMHYZTKJ9NW0",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -54,7 +58,4 @@ export const WithoutFeedback = createExample(
     selected_challenge_uuid:
       "AHCC4ZJ3Z1AF8TWBKGVGEKCQ3R7HXHJ51MJ45NHNZMHYZTKJ9NW0",
   } as ReducerState,
-  {
-    id: "AHCC4ZJ3Z1AF8TWBKGVGEKCQ3R7HXHJ51MJ45NHNZMHYZTKJ9NW0",
-  },
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
index 5582590f7..bb2fa1aeb 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSetup.stories.tsx
@@ -19,7 +19,8 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
 import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
 
 export default {
@@ -36,16 +37,15 @@ export default {
 
 const type: KnownAuthMethods = "totp";
 
-export const Empty = createExample(
+export const Empty = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [],
   },
+  reducerStatesExample.authEditing,
 );
-export const WithOneExample = createExample(
+export const WithOneExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -56,10 +56,10 @@ export const WithOneExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
-export const WithMoreExample = createExample(
+export const WithMoreExample = tests.createExample(
   TestedComponent[type].setup,
-  reducerStatesExample.authEditing,
   {
     configured: [
       {
@@ -76,4 +76,5 @@ export const WithMoreExample = createExample(
       },
     ],
   },
+  reducerStatesExample.authEditing,
 );
diff --git 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx
 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx
index 20cd7e3c9..5f1022247 100644
--- 
a/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx
+++ 
b/packages/anastasis-webui/src/pages/home/authMethod/AuthMethodTotpSolve.stories.tsx
@@ -20,8 +20,9 @@
  */
 
 import { ReducerState } from "@gnu-taler/anastasis-core";
-import { createExample, reducerStatesExample } from "../../../utils/index.js";
-import { authMethods as TestedComponent, KnownAuthMethods } from "./index.js";
+import { tests } from "@gnu-taler/web-util/lib/index.browser";
+import { reducerStatesExample } from "../../../utils/index.js";
+import { KnownAuthMethods, authMethods as TestedComponent } from "./index.js";
 
 export default {
   title: "Auth method: Totp solve",
@@ -37,8 +38,11 @@ export default {
 
 const type: KnownAuthMethods = "totp";
 
-export const WithoutFeedback = createExample(
+export const WithoutFeedback = tests.createExample(
   TestedComponent[type].solve,
+  {
+    id: "uuid-1",
+  },
   {
     ...reducerStatesExample.challengeSolving,
     recovery_information: {
@@ -53,7 +57,4 @@ export const WithoutFeedback = createExample(
     },
     selected_challenge_uuid: "uuid-1",
   } as ReducerState,
-  {
-    id: "uuid-1",
-  },
 );
diff --git a/packages/anastasis-webui/src/pages/home/index.storiesNo.tsx 
b/packages/anastasis-webui/src/pages/home/index.stories.tsx
similarity index 99%
rename from packages/anastasis-webui/src/pages/home/index.storiesNo.tsx
rename to packages/anastasis-webui/src/pages/home/index.stories.tsx
index 0dad73724..b4525b423 100644
--- a/packages/anastasis-webui/src/pages/home/index.storiesNo.tsx
+++ b/packages/anastasis-webui/src/pages/home/index.stories.tsx
@@ -35,6 +35,7 @@ export * as authMethod_AuthMethodSmsSetup from 
"./authMethod/AuthMethodSmsSetup.
 export * as authMethod_AuthMethodSmsSolve from 
"./authMethod/AuthMethodSmsSolve.stories.js";
 export * as authMethod_AuthMethodTotpSetup from 
"./authMethod/AuthMethodTotpSetup.stories.js";
 export * as authMethod_AuthMethodTotpSolve from 
"./authMethod/AuthMethodTotpSolve.stories.js";
+
 export * as BackupFinishedScreen from "./BackupFinishedScreen.stories.js";
 export * as ChallengeOverviewScreen from 
"./ChallengeOverviewScreen.stories.js";
 export * as ChallengePayingScreen from "./ChallengePayingScreen.stories.js";
@@ -42,6 +43,7 @@ export * as ContinentSelectionScreen from 
"./ContinentSelectionScreen.stories.js
 export * as EditPoliciesScreen from "./EditPoliciesScreen.stories.js";
 export * as PoliciesPayingScreen from "./PoliciesPayingScreen.stories.js";
 export * as RecoveryFinishedScreen from "./RecoveryFinishedScreen.stories.js";
+
 export * as ReviewPoliciesScreen from "./ReviewPoliciesScreen.stories.js";
 export * as SecretEditorScreen from "./SecretEditorScreen.stories.js";
 export * as SecretSelectionScreen from "./SecretSelectionScreen.stories.js";
diff --git a/packages/anastasis-webui/src/stories.tsx 
b/packages/anastasis-webui/src/stories.tsx
index f345f082d..52d42577d 100644
--- a/packages/anastasis-webui/src/stories.tsx
+++ b/packages/anastasis-webui/src/stories.tsx
@@ -20,7 +20,7 @@
  */
 import { strings } from "./i18n/strings.js";
 
-import * as pages from "./pages/home/index.storiesNo.js";
+import * as pages from "./pages/home/index.stories.js";
 
 import { renderStories } from "@gnu-taler/web-util/lib/index.browser";
 
diff --git a/packages/anastasis-webui/src/test-utils.ts 
b/packages/anastasis-webui/src/test-utils.ts
deleted file mode 100644
index f220540f1..000000000
--- a/packages/anastasis-webui/src/test-utils.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- This file is part of GNU Anastasis
- (C) 2021-2022 Anastasis SARL
-
- GNU Anastasis is free software; you can redistribute it and/or modify it 
under the
- terms of the GNU Affero General Public License as published by the Free 
Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Anastasis 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 Affero General Public License for more 
details.
-
- You should have received a copy of the GNU Affero General Public License 
along with
- GNU Anastasis; see the file COPYING.  If not, see 
<http://www.gnu.org/licenses/>
- */
-
-import {
-  ComponentChildren,
-  Fragment,
-  FunctionalComponent,
-  h as create,
-  options,
-  render as renderIntoDom,
-  VNode,
-} from "preact";
-import { render as renderToString } from "preact-render-to-string";
-
-// When doing tests we want the requestAnimationFrame to be as fast as 
possible.
-// without this option the RAF will timeout after 100ms making the tests slower
-options.requestAnimationFrame = (fn: () => void) => {
-  // console.log("RAF called")
-  return fn();
-};
-
-export function createExample<Props>(
-  Component: FunctionalComponent<Props>,
-  props: Partial<Props> | (() => Partial<Props>),
-): ComponentChildren {
-  //FIXME: props are evaluated on build time
-  // in some cases we want to evaluated the props on render time so we can get 
some relative timestamp
-  // check how we can build evaluatedProps in render time
-  const evaluatedProps = typeof props === "function" ? props() : props;
-  const Render = (args: any): VNode => create(Component, args);
-  return {
-    component: Render,
-    props: evaluatedProps
-  };
-}
-
-export function createExampleWithCustomContext<Props, ContextProps>(
-  Component: FunctionalComponent<Props>,
-  props: Partial<Props> | (() => Partial<Props>),
-  ContextProvider: FunctionalComponent<ContextProps>,
-  contextProps: Partial<ContextProps>,
-): ComponentChildren {
-  const evaluatedProps = typeof props === "function" ? props() : props;
-  const Render = (args: any): VNode => create(Component, args);
-  const WithContext = (args: any): VNode =>
-    create(ContextProvider, {
-      ...contextProps,
-      children: [Render(args)],
-    } as any);
-  return {
-    component: WithContext,
-    props: evaluatedProps
-  };
-}
-
-export function NullLink({
-  children,
-}: {
-  children?: ComponentChildren;
-}): VNode {
-  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;
-  getLastResultOrThrow: () => T;
-  assertNoPendingUpdate: () => void;
-  waitNextUpdate: (s?: string) => Promise<void>;
-}
-
-const isNode = typeof window === "undefined";
-
-export function mountHook<T>(
-  callback: () => T,
-  Context?: ({ children }: { children: any }) => VNode,
-): Mounted<T> {
-  // const result: { current: T | null } = {
-  //   current: null
-  // }
-  let lastResult: T | Error | null = null;
-
-  const listener: Array<() => void> = [];
-
-  // component that's going to hold the hook
-  function Component(): VNode {
-    try {
-      lastResult = callback();
-    } catch (e) {
-      if (e instanceof Error) {
-        lastResult = e;
-      } else {
-        lastResult = new Error(`mounting the hook throw an exception: ${e}`);
-      }
-    }
-
-    // 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, {})] });
-
-  // waiter callback
-  async function waitNextUpdate(_label = ""): Promise<void> {
-    if (_label) _label = `. label: "${_label}"`;
-    await new Promise((res, rej) => {
-      const tid = setTimeout(() => {
-        rej(
-          Error(`waiting for an update but the hook didn't make one${_label}`),
-        );
-      }, 100);
-
-      listener.push(() => {
-        clearTimeout(tid);
-        res(undefined);
-      });
-    });
-  }
-
-  const customElement = {} as Element;
-  const parentElement = isNode ? customElement : document.createElement("div");
-  if (!isNode) {
-    document.body.appendChild(parentElement);
-  }
-
-  renderIntoDom(vdom, parentElement);
-
-  // clean up callback
-  function unmount(): void {
-    if (!isNode) {
-      document.body.removeChild(parentElement);
-    }
-  }
-
-  function getLastResult(): T | Error | null {
-    const copy = lastResult;
-    lastResult = null;
-    return copy;
-  }
-
-  function getLastResultOrThrow(): T {
-    const r = getLastResult();
-    if (r instanceof Error) throw r;
-    if (!r) throw Error("there was no last result");
-    return r;
-  }
-
-  async function assertNoPendingUpdate(): Promise<void> {
-    await new Promise((res, rej) => {
-      const tid = setTimeout(() => {
-        res(undefined);
-      }, 10);
-
-      listener.push(() => {
-        clearTimeout(tid);
-        rej(
-          Error(`Expecting no pending result but the hook got updated. 
-        If the update was not intended you need to check the hook dependencies 
-        (or dependencies of the internal state) but otherwise make 
-        sure to consume the result before ending the test.`),
-        );
-      });
-    });
-
-    const r = getLastResult();
-    if (r)
-      throw Error(`There are still pending results.
-    This may happen because the hook did a new update but the test didn't 
consume the result using getLastResult`);
-  }
-  return {
-    unmount,
-    getLastResultOrThrow,
-    waitNextUpdate,
-    assertNoPendingUpdate,
-  };
-}
diff --git a/packages/anastasis-webui/src/utils/index.tsx 
b/packages/anastasis-webui/src/utils/index.tsx
index 4cf839473..88bcac551 100644
--- a/packages/anastasis-webui/src/utils/index.tsx
+++ b/packages/anastasis-webui/src/utils/index.tsx
@@ -21,67 +21,12 @@ import {
   ReducerState,
   ReducerStateRecovery,
 } from "@gnu-taler/anastasis-core";
-import { ComponentChildren, FunctionalComponent, h, VNode } from "preact";
-import { AnastasisProvider } from "../context/anastasis.js";
+import { VNode } from "preact";
 
 const noop = async (): Promise<void> => {
   return;
 };
 
-export function createExampleWithoutAnastasis<Props>(
-  Component: FunctionalComponent<Props>,
-  props: Partial<Props> | (() => Partial<Props>),
-): ComponentChildren {
-  //FIXME: props are evaluated on build time
-  // in some cases we want to evaluated the props on render time so we can get 
some relative timestamp
-  // check how we can build evaluatedProps in render time
-  const evaluatedProps = typeof props === "function" ? props() : props;
-  const Render = (args: any): VNode => h(Component, args);
-  return {
-    component: Render,
-    props: evaluatedProps,
-  };
-}
-
-export function createExample<Props>(
-  Component: FunctionalComponent<Props>,
-  currentReducerState?: ReducerState,
-  props?: Partial<Props>,
-): ComponentChildren {
-  const Render = (args: Props): VNode => {
-    return (
-      <AnastasisProvider
-        value={{
-          currentReducerState,
-          discoverMore: noop,
-          discoverStart: noop,
-          discoveryState: {
-            state: "finished",
-          },
-          currentError: undefined,
-          back: noop,
-          dismissError: noop,
-          reset: noop,
-          runTransaction: noop,
-          startBackup: noop,
-          startRecover: noop,
-          transition: noop,
-          exportState: () => {
-            return "{}";
-          },
-          importState: noop,
-        }}
-      >
-        <Component {...(args as any)} />
-      </AnastasisProvider>
-    );
-  };
-  return {
-    component: Render,
-    props: props,
-  };
-}
-
 const base = {
   continents: [
     {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]