@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.
- package/.turbo/turbo-build$colon$cjs.log +4 -7
- package/.turbo/turbo-build$colon$tsc.log +19 -22
- package/.turbo/turbo-build.log +5 -11
- package/CHANGELOG.md +30 -0
- package/LICENSE +201 -0
- package/dist/cjs/components/procaptchaWidget.cjs +18 -4
- package/dist/cjs/components/puzzleCanvas.cjs +25 -4
- package/dist/components/procaptchaWidget.d.ts.map +1 -1
- package/dist/components/procaptchaWidget.js +18 -4
- package/dist/components/procaptchaWidget.js.map +1 -1
- package/dist/components/puzzleCanvas.d.ts +2 -1
- package/dist/components/puzzleCanvas.d.ts.map +1 -1
- package/dist/components/puzzleCanvas.js +26 -5
- package/dist/components/puzzleCanvas.js.map +1 -1
- package/dist/tests/procaptchaWidget.unit.test.js +62 -0
- package/dist/tests/procaptchaWidget.unit.test.js.map +1 -1
- package/dist/tests/puzzleCanvas.unit.test.js +33 -0
- package/dist/tests/puzzleCanvas.unit.test.js.map +1 -1
- package/package.json +72 -71
- package/src/components/procaptchaPuzzle.ts +0 -54
- package/src/components/procaptchaWidget.ts +0 -429
- package/src/components/puzzleCanvas.ts +0 -658
- package/src/index.ts +0 -16
- package/src/services/Manager.ts +0 -529
- package/src/tests/domHarness.ts +0 -122
- package/src/tests/invisibleCanvasVisibility.unit.test.ts +0 -181
- package/src/tests/manager.unit.test.ts +0 -840
- package/src/tests/managerHarness.ts +0 -169
- package/src/tests/procaptchaPuzzle.test-d.ts +0 -212
- package/src/tests/procaptchaPuzzle.unit.test.ts +0 -138
- package/src/tests/procaptchaWidget.unit.test.ts +0 -777
- package/src/tests/puzzleCanvas.unit.test.ts +0 -662
- package/tsconfig.cjs.json +0 -43
- package/tsconfig.json +0 -44
- package/tsconfig.tsbuildinfo +0 -1
- 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
|
-
});
|