@prosopo/procaptcha-puzzle 2.14.7 → 2.15.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.
Files changed (36) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +4 -7
  2. package/.turbo/turbo-build$colon$tsc.log +19 -22
  3. package/.turbo/turbo-build.log +5 -11
  4. package/CHANGELOG.md +30 -0
  5. package/LICENSE +201 -0
  6. package/dist/cjs/components/procaptchaWidget.cjs +18 -4
  7. package/dist/cjs/components/puzzleCanvas.cjs +25 -4
  8. package/dist/components/procaptchaWidget.d.ts.map +1 -1
  9. package/dist/components/procaptchaWidget.js +18 -4
  10. package/dist/components/procaptchaWidget.js.map +1 -1
  11. package/dist/components/puzzleCanvas.d.ts +2 -1
  12. package/dist/components/puzzleCanvas.d.ts.map +1 -1
  13. package/dist/components/puzzleCanvas.js +26 -5
  14. package/dist/components/puzzleCanvas.js.map +1 -1
  15. package/dist/tests/procaptchaWidget.unit.test.js +62 -0
  16. package/dist/tests/procaptchaWidget.unit.test.js.map +1 -1
  17. package/dist/tests/puzzleCanvas.unit.test.js +33 -0
  18. package/dist/tests/puzzleCanvas.unit.test.js.map +1 -1
  19. package/package.json +72 -71
  20. package/src/components/procaptchaPuzzle.ts +0 -54
  21. package/src/components/procaptchaWidget.ts +0 -429
  22. package/src/components/puzzleCanvas.ts +0 -658
  23. package/src/index.ts +0 -16
  24. package/src/services/Manager.ts +0 -529
  25. package/src/tests/domHarness.ts +0 -122
  26. package/src/tests/invisibleCanvasVisibility.unit.test.ts +0 -181
  27. package/src/tests/manager.unit.test.ts +0 -840
  28. package/src/tests/managerHarness.ts +0 -169
  29. package/src/tests/procaptchaPuzzle.test-d.ts +0 -212
  30. package/src/tests/procaptchaPuzzle.unit.test.ts +0 -138
  31. package/src/tests/procaptchaWidget.unit.test.ts +0 -777
  32. package/src/tests/puzzleCanvas.unit.test.ts +0 -662
  33. package/tsconfig.cjs.json +0 -43
  34. package/tsconfig.json +0 -44
  35. package/tsconfig.tsbuildinfo +0 -1
  36. package/tsconfig.types.json +0 -9
@@ -1,181 +0,0 @@
1
- // Copyright 2021-2026 Prosopo (UK) Ltd.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
-
15
- import type { Ti18n } from "@prosopo/locale";
16
- import {
17
- type GetPuzzleCaptchaResponse,
18
- ModeEnum,
19
- type ProcaptchaProps,
20
- type ProcaptchaState,
21
- type PuzzleEvent,
22
- } from "@prosopo/types";
23
- import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
24
- import {
25
- type ProcaptchaPuzzleHandle,
26
- mountProcaptchaPuzzleWidget,
27
- } from "../components/procaptchaWidget.js";
28
- import { type Mounted, fire, mount, settle } from "./domHarness.js";
29
- import { challengeResponse, config, frictionless } from "./managerHarness.js";
30
-
31
- // The canvas is deliberately NOT mocked here: the point of this suite is
32
- // whether the overlay the user has to drag actually becomes visible. The
33
- // widget suite stubs the canvas, so it asserts the challenge was handed over,
34
- // not that anything reached the screen.
35
- const mocks = vi.hoisted(() => {
36
- const start =
37
- vi.fn<
38
- (x?: number, y?: number) => Promise<GetPuzzleCaptchaResponse | undefined>
39
- >();
40
- const submitSolution =
41
- vi.fn<(x: number, y: number, events: PuzzleEvent[]) => Promise<boolean>>();
42
- const resetState = vi.fn<() => void>();
43
- const dispose = vi.fn<() => void>();
44
- return { start, submitSolution, resetState, dispose };
45
- });
46
-
47
- vi.mock("../services/Manager.js", () => ({
48
- Manager: (
49
- _config: unknown,
50
- _state: ProcaptchaState,
51
- _updateState: (next: Partial<ProcaptchaState>) => void,
52
- ) => ({
53
- start: mocks.start,
54
- submitSolution: mocks.submitSolution,
55
- resetState: mocks.resetState,
56
- dispose: mocks.dispose,
57
- }),
58
- }));
59
-
60
- vi.mock("@prosopo/locale", async (importOriginal) => ({
61
- ...(await importOriginal<typeof import("@prosopo/locale")>()),
62
- loadI18next: vi.fn(async () => undefined),
63
- }));
64
-
65
- const i18nStub = {
66
- isInitialized: true,
67
- language: "en",
68
- t: (key: string) => key,
69
- changeLanguage: vi.fn(),
70
- hasLoadedNamespace: () => true,
71
- on: () => undefined,
72
- off: () => undefined,
73
- } as unknown as Ti18n;
74
-
75
- const props = (overrides: Partial<ProcaptchaProps> = {}): ProcaptchaProps =>
76
- ({
77
- config: config({ mode: ModeEnum.visible }),
78
- callbacks: {},
79
- i18n: i18nStub,
80
- frictionlessState: frictionless(),
81
- ...overrides,
82
- }) as unknown as ProcaptchaProps;
83
-
84
- let mounted: Mounted;
85
- let handle: ProcaptchaPuzzleHandle | undefined;
86
-
87
- // Class names are hashed by the CSS-module build, so the surface is addressed
88
- // through the `data-cy` hooks the components ship for exactly this reason.
89
- const surface = (): HTMLElement | null =>
90
- document.querySelector<HTMLElement>('[data-cy="challenge-surface"]');
91
-
92
- // The panel carrying the entrance animation is the only element under the
93
- // surface with an inline opacity of its own.
94
- const panelOpacity = (): string | undefined => {
95
- const content = document.querySelector('[data-cy="challenge-content"]');
96
- if (!content) return undefined;
97
- return Array.from(
98
- content.querySelectorAll<HTMLElement>("[style*='opacity']"),
99
- ).at(-1)?.style.opacity;
100
- };
101
-
102
- // The entrance animation flips opacity inside a requestAnimationFrame, so a
103
- // test has to let a frame run before reading it.
104
- const frame = async (): Promise<void> => {
105
- await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()));
106
- await settle();
107
- };
108
-
109
- beforeEach(() => {
110
- mocks.start.mockResolvedValue(challengeResponse());
111
- mounted = mount();
112
- });
113
-
114
- afterEach(() => {
115
- handle?.destroy();
116
- handle = undefined;
117
- mounted.unmount();
118
- for (const layer of Array.from(
119
- document.querySelectorAll(".prosopo-challenge-surface"),
120
- )) {
121
- layer.remove();
122
- }
123
- vi.clearAllMocks();
124
- });
125
-
126
- describe("the puzzle overlay actually reaches the screen", () => {
127
- test("visible mode: the panel is opaque after the entrance frame", async () => {
128
- handle = mountProcaptchaPuzzleWidget(mounted.container, props());
129
- const checkbox = mounted.container.querySelector("input");
130
- expect(checkbox, "the visible widget renders a checkbox").not.toBeNull();
131
- if (checkbox) fire(checkbox, "click");
132
- await settle();
133
- await frame();
134
-
135
- expect(mocks.start).toHaveBeenCalledTimes(1);
136
- expect(surface(), "the overlay is mounted").not.toBeNull();
137
- expect(panelOpacity()).toBe("1");
138
- });
139
-
140
- // Invisible mode has no checkbox, so the overlay is opened by the host
141
- // page's execute(). It still has to reach the screen: the piece is dragged
142
- // by hand, and a panel left at opacity 0 is a challenge nobody can solve.
143
- test("invisible mode: the panel is opaque after the entrance frame", async () => {
144
- handle = mountProcaptchaPuzzleWidget(
145
- mounted.container,
146
- props({ config: config({ mode: ModeEnum.invisible }) }),
147
- );
148
- document.dispatchEvent(new Event("procaptcha:execute"));
149
- await settle();
150
- await frame();
151
-
152
- expect(mocks.start).toHaveBeenCalledTimes(1);
153
- expect(surface(), "the overlay is mounted").not.toBeNull();
154
- expect(panelOpacity()).toBe("1");
155
- });
156
-
157
- // The entrance frame is cancelled on teardown, so a canvas destroyed and
158
- // remounted before it runs would stay transparent for good.
159
- test("invisible mode: a remounted overlay still becomes opaque", async () => {
160
- handle = mountProcaptchaPuzzleWidget(
161
- mounted.container,
162
- props({ config: config({ mode: ModeEnum.invisible }) }),
163
- );
164
- document.dispatchEvent(new Event("procaptcha:execute"));
165
- await settle();
166
- await frame();
167
- expect(panelOpacity()).toBe("1");
168
-
169
- handle.destroy();
170
- handle = mountProcaptchaPuzzleWidget(
171
- mounted.container,
172
- props({ config: config({ mode: ModeEnum.invisible }) }),
173
- );
174
- document.dispatchEvent(new Event("procaptcha:execute"));
175
- await settle();
176
- await frame();
177
-
178
- expect(surface(), "the overlay is mounted again").not.toBeNull();
179
- expect(panelOpacity()).toBe("1");
180
- });
181
- });