From 57e91c9fd52b42a7fb63970f09f449799d2d9bb8 Mon Sep 17 00:00:00 2001 From: Mikalai Silivonik Date: Tue, 23 Jun 2026 10:53:24 -0400 Subject: [PATCH 1/2] Fix stale lens removal after cancelled apply --- src/useApplyLens.test.ts | 55 ++++++++++++++++++++++++++++++++-------- src/useApplyLens.ts | 5 +--- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/useApplyLens.test.ts b/src/useApplyLens.test.ts index a059058..d94fa2c 100644 --- a/src/useApplyLens.test.ts +++ b/src/useApplyLens.test.ts @@ -1,4 +1,4 @@ -import { renderHook, waitFor } from "@testing-library/react"; +import { act, renderHook, waitFor } from "@testing-library/react"; import hash from "stable-hash"; import { useApplyLens } from "./useApplyLens"; import { useInternalCameraKit } from "./CameraKitProvider"; @@ -15,6 +15,16 @@ const mockUseInternalCameraKit = useInternalCameraKit as jest.MockedFunction; const mockReportCount = metricsReporter.reportCount as jest.Mock; +function deferred() { + let resolve: (value: T) => void = () => {}; + let reject: (reason?: unknown) => void = () => {}; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve, reject }; +} + describe("useApplyLens", () => { let mockApplyLens: jest.Mock; let mockRemoveLens: jest.Mock; @@ -387,14 +397,9 @@ describe("useApplyLens", () => { }); describe("Cancellation handling", () => { - it("should remove lens if component unmounts during application", async () => { - let resolveApply: any; - mockApplyLens.mockImplementation( - () => - new Promise((resolve) => { - resolveApply = resolve; - }), - ); + it("should not remove lens again if component unmounts during application", async () => { + const apply = deferred(); + mockApplyLens.mockReturnValue(apply.promise); const { unmount } = renderHook(() => useApplyLens("lens-123", "group-456")); @@ -403,11 +408,39 @@ describe("useApplyLens", () => { }); unmount(); - resolveApply(true); + await act(async () => { + apply.resolve(true); + await apply.promise; + }); + + expect(mockRemoveLens).toHaveBeenCalledTimes(1); + }); + + it("should not remove the current lens when a superseded apply resolves late", async () => { + const firstApply = deferred(); + mockApplyLens.mockImplementationOnce(() => firstApply.promise).mockResolvedValueOnce(true); + + const { rerender } = renderHook(({ lensId }) => useApplyLens(lensId, "group-1"), { + initialProps: { lensId: "lens-1" }, + }); + + await waitFor(() => { + expect(mockApplyLens).toHaveBeenCalledWith("lens-1", "group-1", undefined, undefined); + }); + + rerender({ lensId: "lens-2" }); await waitFor(() => { - expect(mockRemoveLens).toHaveBeenCalledTimes(2); // Once after apply, once on unmount + expect(mockApplyLens).toHaveBeenCalledWith("lens-2", "group-1", undefined, undefined); }); + expect(mockRemoveLens).toHaveBeenCalledTimes(1); + + await act(async () => { + firstApply.resolve(true); + await firstApply.promise; + }); + + expect(mockRemoveLens).toHaveBeenCalledTimes(1); }); }); diff --git a/src/useApplyLens.ts b/src/useApplyLens.ts index 0c9a559..1d3f893 100644 --- a/src/useApplyLens.ts +++ b/src/useApplyLens.ts @@ -71,10 +71,7 @@ export function useApplyLens( (async () => { try { await applyLens(lensId, lensGroupId, safeLaunchData, guardRef.current); - if (cancelled) { - await removeLens(); - return; - } + if (cancelled) return; log.info("apply_success", { lensId, groupId: lensGroupId, From bb6b14b3ad07384903df994b63d579b8621c29a6 Mon Sep 17 00:00:00 2001 From: Mikalai Silivonik Date: Tue, 23 Jun 2026 10:54:41 -0400 Subject: [PATCH 2/2] 0.3.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a303325..9ba73f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@snap/react-camera-kit", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@snap/react-camera-kit", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "dependencies": { "stable-hash": "^0.0.6" diff --git a/package.json b/package.json index c714a2f..1fbc716 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@snap/react-camera-kit", - "version": "0.3.0", + "version": "0.3.1", "description": "React Camera Kit for web applications", "type": "module", "main": "./dist/cjs/index.js",