@prosopo/procaptcha-pow 2.12.7 → 2.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$cjs.log +5 -5
- package/.turbo/turbo-build$colon$tsc.log +19 -19
- package/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +43 -0
- package/dist/cjs/components/procaptchaPoW.cjs +22 -0
- package/dist/cjs/components/procaptchaWidget.cjs +143 -0
- package/dist/cjs/index.cjs +5 -2
- package/dist/components/procaptchaPoW.d.ts +7 -0
- package/dist/components/procaptchaPoW.d.ts.map +1 -0
- package/dist/components/procaptchaPoW.js +21 -0
- package/dist/components/procaptchaPoW.js.map +1 -0
- package/dist/components/procaptchaWidget.d.ts +7 -0
- package/dist/components/procaptchaWidget.d.ts.map +1 -0
- package/dist/components/procaptchaWidget.js +143 -0
- package/dist/components/procaptchaWidget.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -2
- package/dist/tests/domHarness.d.ts +20 -0
- package/dist/tests/domHarness.d.ts.map +1 -0
- package/dist/tests/domHarness.js +56 -0
- package/dist/tests/domHarness.js.map +1 -0
- package/dist/tests/procaptchaPoW.unit.test.js +46 -30
- package/dist/tests/procaptchaPoW.unit.test.js.map +1 -1
- package/dist/tests/procaptchaPow.test-d.js +5 -5
- package/dist/tests/procaptchaPow.test-d.js.map +1 -1
- package/dist/tests/procaptchaWidget.unit.test.js +79 -137
- package/dist/tests/procaptchaWidget.unit.test.js.map +1 -1
- package/package.json +9 -13
- package/src/components/procaptchaPoW.ts +53 -0
- package/src/components/procaptchaWidget.ts +281 -0
- package/src/index.ts +2 -2
- package/src/tests/domHarness.ts +122 -0
- package/src/tests/procaptchaPoW.unit.test.ts +59 -36
- package/src/tests/procaptchaPow.test-d.ts +15 -9
- package/src/tests/procaptchaWidget.unit.test.ts +105 -171
- package/tsconfig.cjs.json +1 -2
- package/tsconfig.json +1 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/components/ProcaptchaPoW.cjs +0 -7
- package/dist/cjs/components/ProcaptchaWidget.cjs +0 -130
- package/dist/components/ProcaptchaPoW.d.ts +0 -3
- package/dist/components/ProcaptchaPoW.d.ts.map +0 -1
- package/dist/components/ProcaptchaPoW.js +0 -7
- package/dist/components/ProcaptchaPoW.js.map +0 -1
- package/dist/components/ProcaptchaWidget.d.ts +0 -4
- package/dist/components/ProcaptchaWidget.d.ts.map +0 -1
- package/dist/components/ProcaptchaWidget.js +0 -131
- package/dist/components/ProcaptchaWidget.js.map +0 -1
- package/src/components/ProcaptchaPoW.tsx +0 -39
- package/src/components/ProcaptchaWidget.tsx +0 -231
|
@@ -14,33 +14,42 @@
|
|
|
14
14
|
|
|
15
15
|
import type { Ti18n } from "@prosopo/locale";
|
|
16
16
|
import type { ProcaptchaProps } from "@prosopo/types";
|
|
17
|
-
import { type ReactElement, act, createElement } from "react";
|
|
18
|
-
import { type Root, createRoot } from "react-dom/client";
|
|
19
17
|
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
18
|
+
import type { ProcaptchaPowHandle } from "../components/procaptchaWidget.js";
|
|
20
19
|
import * as entrypoint from "../index.js";
|
|
20
|
+
import { type Mounted, mount, settle } from "./domHarness.js";
|
|
21
21
|
import { config } from "./managerHarness.js";
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* The outer
|
|
24
|
+
* The outer entry point exists only to lazy-load the widget and hand it the
|
|
25
25
|
* props it was given — which it once did by naming them one at a time, quietly
|
|
26
26
|
* dropping `onEscalate` and `autoStart`.
|
|
27
27
|
*/
|
|
28
28
|
const mocks = vi.hoisted(() => ({
|
|
29
29
|
received: [] as ProcaptchaProps[],
|
|
30
|
+
destroyed: { count: 0 },
|
|
30
31
|
}));
|
|
31
32
|
|
|
32
|
-
vi.mock("../components/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
vi.mock("../components/procaptchaWidget.js", () => ({
|
|
34
|
+
mountProcaptchaPowWidget: (
|
|
35
|
+
container: HTMLElement,
|
|
36
|
+
props: ProcaptchaProps,
|
|
37
|
+
): ProcaptchaPowHandle => {
|
|
38
|
+
mocks.received.push(props);
|
|
39
|
+
const element = document.createElement("div");
|
|
40
|
+
element.setAttribute("data-testid", "widget");
|
|
41
|
+
container.appendChild(element);
|
|
42
|
+
return {
|
|
43
|
+
destroy: () => {
|
|
44
|
+
element.remove();
|
|
45
|
+
mocks.destroyed.count += 1;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
41
50
|
|
|
42
|
-
let
|
|
43
|
-
let
|
|
51
|
+
let mounted: Mounted;
|
|
52
|
+
let widget: ProcaptchaPowHandle | undefined;
|
|
44
53
|
|
|
45
54
|
const props = (overrides: Partial<ProcaptchaProps> = {}): ProcaptchaProps => ({
|
|
46
55
|
config: config(),
|
|
@@ -50,33 +59,29 @@ const props = (overrides: Partial<ProcaptchaProps> = {}): ProcaptchaProps => ({
|
|
|
50
59
|
});
|
|
51
60
|
|
|
52
61
|
const render = async (widgetProps: ProcaptchaProps): Promise<void> => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
createElement(entrypoint.ProcaptchaPow, widgetProps) as ReactElement,
|
|
56
|
-
);
|
|
57
|
-
});
|
|
62
|
+
widget = entrypoint.mountProcaptchaPow(mounted.container, widgetProps);
|
|
63
|
+
await settle();
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
beforeEach(() => {
|
|
61
67
|
mocks.received.length = 0;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
root = createRoot(container);
|
|
66
|
-
});
|
|
68
|
+
mocks.destroyed.count = 0;
|
|
69
|
+
widget = undefined;
|
|
70
|
+
mounted = mount();
|
|
67
71
|
});
|
|
68
72
|
|
|
69
73
|
afterEach(() => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
container.remove();
|
|
74
|
+
widget?.destroy();
|
|
75
|
+
widget = undefined;
|
|
76
|
+
mounted.unmount();
|
|
74
77
|
});
|
|
75
78
|
|
|
76
|
-
describe("
|
|
79
|
+
describe("mountProcaptchaPow", () => {
|
|
77
80
|
test("renders the widget once it has loaded", async () => {
|
|
78
81
|
await render(props());
|
|
79
|
-
expect(
|
|
82
|
+
expect(
|
|
83
|
+
mounted.container.querySelector('[data-testid="widget"]'),
|
|
84
|
+
).not.toBeNull();
|
|
80
85
|
});
|
|
81
86
|
|
|
82
87
|
test("passes on the props the widget needs but never names", async () => {
|
|
@@ -107,14 +112,32 @@ describe("ProcaptchaPow", () => {
|
|
|
107
112
|
expect(mocks.received[0]?.callbacks).toBe(callbacks);
|
|
108
113
|
expect(mocks.received[0]?.config).toEqual(config());
|
|
109
114
|
});
|
|
115
|
+
|
|
116
|
+
test("tears the loaded widget down", async () => {
|
|
117
|
+
await render(props());
|
|
118
|
+
widget?.destroy();
|
|
119
|
+
widget = undefined;
|
|
120
|
+
expect(mocks.destroyed.count).toBe(1);
|
|
121
|
+
expect(
|
|
122
|
+
mounted.container.querySelector('[data-testid="widget"]'),
|
|
123
|
+
).toBeNull();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("cancels a mount that is still loading", async () => {
|
|
127
|
+
// Otherwise a widget torn down mid-load reappears as an orphan that
|
|
128
|
+
// nothing holds a handle to.
|
|
129
|
+
widget = entrypoint.mountProcaptchaPow(mounted.container, props());
|
|
130
|
+
widget.destroy();
|
|
131
|
+
widget = undefined;
|
|
132
|
+
await settle();
|
|
133
|
+
expect(mocks.received).toHaveLength(0);
|
|
134
|
+
});
|
|
110
135
|
});
|
|
111
136
|
|
|
112
137
|
describe("the package entrypoint", () => {
|
|
113
|
-
test("exports the
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
expect(typeof entrypoint.ProcaptchaPow).toBe("function");
|
|
118
|
-
expect(Object.keys(entrypoint)).toEqual(["ProcaptchaPow"]);
|
|
138
|
+
test("exports the mount functions a consumer needs", () => {
|
|
139
|
+
expect(typeof entrypoint.mountProcaptchaPow).toBe("function");
|
|
140
|
+
expect(typeof entrypoint.loadProcaptchaPow).toBe("function");
|
|
141
|
+
expect(typeof entrypoint.mountProcaptchaPowWidget).toBe("function");
|
|
119
142
|
});
|
|
120
143
|
});
|
|
@@ -22,10 +22,9 @@ import type {
|
|
|
22
22
|
ProcaptchaState,
|
|
23
23
|
ProcaptchaStateUpdateFn,
|
|
24
24
|
} from "@prosopo/types";
|
|
25
|
-
import type { ReactElement } from "react";
|
|
26
25
|
import { assertType, describe, expectTypeOf, test } from "vitest";
|
|
27
26
|
import type * as entrypoint from "../index.js";
|
|
28
|
-
import {
|
|
27
|
+
import { mountProcaptchaPow } from "../index.js";
|
|
29
28
|
import { Manager } from "../services/Manager.js";
|
|
30
29
|
import { config, frictionless, state } from "./managerHarness.js";
|
|
31
30
|
|
|
@@ -33,15 +32,22 @@ import { config, frictionless, state } from "./managerHarness.js";
|
|
|
33
32
|
const i18n = (): Ti18n => undefined as unknown as Ti18n;
|
|
34
33
|
|
|
35
34
|
describe("the package entrypoint's types", () => {
|
|
36
|
-
test("
|
|
37
|
-
expectTypeOf(
|
|
38
|
-
|
|
35
|
+
test("mountProcaptchaPow takes a host element and the shared widget props", () => {
|
|
36
|
+
expectTypeOf(mountProcaptchaPow).parameters.toEqualTypeOf<
|
|
37
|
+
[HTMLElement, ProcaptchaProps]
|
|
38
|
+
>();
|
|
39
|
+
expectTypeOf(mountProcaptchaPow).returns.toExtend<{
|
|
40
|
+
destroy: () => void;
|
|
41
|
+
}>();
|
|
39
42
|
});
|
|
40
43
|
|
|
41
|
-
test("the
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
|
|
44
|
+
test("the entrypoint exposes the lazy wrapper and the widget itself", () => {
|
|
45
|
+
// The lazy wrapper is what works without a code-splitting bundler; the
|
|
46
|
+
// direct mount is what ProcaptchaFrictionless imports once it has already
|
|
47
|
+
// paid for the dynamic import of this package.
|
|
48
|
+
expectTypeOf<keyof typeof entrypoint>().toEqualTypeOf<
|
|
49
|
+
"mountProcaptchaPow" | "loadProcaptchaPow" | "mountProcaptchaPowWidget"
|
|
50
|
+
>();
|
|
45
51
|
});
|
|
46
52
|
|
|
47
53
|
test("config, callbacks and i18n are all required", () => {
|