diff --git a/packages/browser-sdk/src/client.ts b/packages/browser-sdk/src/client.ts index c1162b98..f002cafd 100644 --- a/packages/browser-sdk/src/client.ts +++ b/packages/browser-sdk/src/client.ts @@ -9,7 +9,6 @@ import { Feedback, feedback, FeedbackOptions, - handleDeprecatedFeedbackOptions, RequestFeedbackData, RequestFeedbackOptions, } from "./feedback/feedback"; @@ -384,11 +383,9 @@ export class BucketClient { enableTracking: opts?.enableTracking ?? defaultConfig.enableTracking, }; - const feedbackOpts = handleDeprecatedFeedbackOptions(opts?.feedback); - this.requestFeedbackOptions = { - position: feedbackOpts?.ui?.position, - translations: feedbackOpts?.ui?.translations, + position: opts?.feedback?.ui?.position, + translations: opts?.feedback?.ui?.translations, }; this.httpClient = new HttpClient(this.publishableKey, { @@ -416,7 +413,7 @@ export class BucketClient { if ( this.context?.user && !isNode && // do not prompt on server-side - feedbackOpts?.enableAutoFeedback !== false // default to on + opts?.feedback?.enableAutoFeedback !== false // default to on ) { if (isMobile) { this.logger.warn( @@ -427,10 +424,10 @@ export class BucketClient { this.config.sseBaseUrl, this.logger, this.httpClient, - feedbackOpts?.autoFeedbackHandler, + opts?.feedback?.autoFeedbackHandler, String(this.context.user?.id), - feedbackOpts?.ui?.position, - feedbackOpts?.ui?.translations, + opts?.feedback?.ui?.position, + opts?.feedback?.ui?.translations, ); } } @@ -438,7 +435,7 @@ export class BucketClient { if (shouldShowToolbar(opts)) { this.logger.info("opening toolbar toggler"); showToolbarToggle({ - bucketClient: this as unknown as BucketClient, + bucketClient: this, position: typeof opts.toolbar === "object" ? opts.toolbar.position : undefined, }); @@ -621,32 +618,28 @@ export class BucketClient { return; } - const featureId = "featureId" in options ? options.featureId : undefined; - const featureKey = "featureKey" in options ? options.featureKey : undefined; - - if (!featureId && !featureKey) { + if (!options.featureKey) { this.logger.error( - "`requestFeedback` call ignored. No `featureId` or `featureKey` provided", + "`requestFeedback` call ignored. No `featureKey` provided", ); return; } const feedbackData = { - featureId, - featureKey, + featureKey: options.featureKey, companyId: options.companyId || (this.context.company?.id ? String(this.context.company?.id) : undefined), source: "widget" as const, - } as Feedback; + } satisfies Feedback; // Wait a tick before opening the feedback form, // to prevent the same click from closing it. setTimeout(() => { feedbackLib.openFeedbackForm({ - key: (featureKey || featureId)!, + key: options.featureKey, title: options.title, position: options.position || this.requestFeedbackOptions.position, translations: diff --git a/packages/browser-sdk/src/feedback/feedback.ts b/packages/browser-sdk/src/feedback/feedback.ts index c649b283..b1666327 100644 --- a/packages/browser-sdk/src/feedback/feedback.ts +++ b/packages/browser-sdk/src/feedback/feedback.ts @@ -45,46 +45,8 @@ export type FeedbackOptions = { */ translations?: Partial; }; - - /** - * @deprecated Use `enableAutoFeedback` instead - */ - enableLiveSatisfaction?: boolean; - - /** - * @deprecated Use `autoFeedbackHandler` instead - */ - liveSatisfactionHandler?: FeedbackPromptHandler; }; -export function handleDeprecatedFeedbackOptions( - opts?: FeedbackOptions, -): FeedbackOptions { - return { - ...opts, - enableAutoFeedback: - opts?.enableAutoFeedback ?? opts?.enableLiveSatisfaction, - autoFeedbackHandler: - opts?.autoFeedbackHandler ?? opts?.liveSatisfactionHandler, - }; -} - -type FeatureIdentifier = - | { - /** - * Bucket feature ID. - * - * @deprecated use `feedbackId` instead. - */ - featureId: string; - } - | { - /** - * Bucket feature key. - */ - featureKey: string; - }; - export type RequestFeedbackData = Omit< OpenFeedbackFormOptions, "key" | "onSubmit" @@ -105,7 +67,12 @@ export type RequestFeedbackData = Omit< * @param data. */ onAfterSubmit?: (data: FeedbackSubmission) => void; -} & FeatureIdentifier; + + /** + * Bucket feature key. + */ + featureKey: string; +}; export type RequestFeedbackOptions = RequestFeedbackData & { /** @@ -115,6 +82,11 @@ export type RequestFeedbackOptions = RequestFeedbackData & { }; export type UnassignedFeedback = { + /** + * Bucket feature key. + */ + featureKey: string; + /** * Bucket feedback ID */ @@ -159,7 +131,7 @@ export type UnassignedFeedback = { * - `sdk` - Feedback submitted via `feedback` */ source?: "prompt" | "sdk" | "widget"; -} & FeatureIdentifier; +}; export type Feedback = UnassignedFeedback & { /** @@ -242,10 +214,17 @@ export const DEFAULT_FEEDBACK_CONFIG = { autoFeedbackEnabled: true, }; +// Payload can include featureId or featureKey, but the public API only exposes featureKey +// We use featureId internally because prompting is based on featureId +type FeedbackPayload = Omit & { + featureId?: string; + featureKey?: string; +}; + export async function feedback( httpClient: HttpClient, logger: Logger, - payload: Feedback, + payload: FeedbackPayload, ) { if (!payload.score && !payload.comment) { logger.error( @@ -435,7 +414,7 @@ export class AutoFeedback { question: reply.question, promptedQuestion: message.question, source: "prompt", - } satisfies Feedback; + } satisfies FeedbackPayload; const response = await feedback( this.httpClient, diff --git a/packages/browser-sdk/src/index.ts b/packages/browser-sdk/src/index.ts index 505b9551..a1044228 100644 --- a/packages/browser-sdk/src/index.ts +++ b/packages/browser-sdk/src/index.ts @@ -1,5 +1,3 @@ -// import "preact/debug"; - export type { Feature, InitOptions, ToolbarOptions } from "./client"; export { BucketClient } from "./client"; export type { BucketContext, CompanyContext, UserContext } from "./context"; diff --git a/packages/browser-sdk/test/e2e/feedback-widget.browser.spec.ts b/packages/browser-sdk/test/e2e/feedback-widget.browser.spec.ts index cfef00c0..13608f30 100644 --- a/packages/browser-sdk/test/e2e/feedback-widget.browser.spec.ts +++ b/packages/browser-sdk/test/e2e/feedback-widget.browser.spec.ts @@ -50,7 +50,7 @@ async function getOpenedWidgetContainer( const bucket = new BucketClient({publishableKey: "${KEY}", user: {id: "foo"}, company: {id: "bar"}, ...${JSON.stringify(initOptions ?? {})}}); await bucket.initialize(); await bucket.requestFeedback({ - featureId: "featureId1", + featureKey: "feature1", title: "baz", }); })() @@ -90,7 +90,7 @@ async function getGiveFeedbackPageContainer( document.querySelector("#give-feedback-button")?.addEventListener("click", () => { console.log("cliked!"); bucket.requestFeedback({ - featureId: "featureId1", + featureKey: "feature1", title: "baz", }); }); @@ -250,7 +250,7 @@ test("Sends a request when choosing a score immediately", async ({ page }) => { .poll(() => sentJSON) .toEqual({ companyId: "bar", - featureId: "featureId1", + key: "feature1", score: expectedScore, question: "baz", userId: "foo", @@ -309,7 +309,7 @@ test("Updates the score on every change", async ({ page }) => { .toEqual({ feedbackId: "123", companyId: "bar", - featureId: "featureId1", + key: "feature1", question: "baz", score: 3, userId: "foo", @@ -369,7 +369,7 @@ test("Sends a request with both the score and comment when submitting", async ({ score: expectedScore, companyId: "bar", question: "baz", - featureId: "featureId1", + key: "feature1", feedbackId: "123", userId: "foo", source: "widget", diff --git a/packages/browser-sdk/test/mocks/handlers.ts b/packages/browser-sdk/test/mocks/handlers.ts index 78d4fcfe..223f8437 100644 --- a/packages/browser-sdk/test/mocks/handlers.ts +++ b/packages/browser-sdk/test/mocks/handlers.ts @@ -89,7 +89,7 @@ export const handlers = [ !data["userId"] || !data["attributes"] ) { - return new HttpResponse(null, { status: 400 }); + return HttpResponse.error(); } return HttpResponse.json({ @@ -106,7 +106,7 @@ export const handlers = [ !data["companyId"] || !data["attributes"] ) { - return new HttpResponse(null, { status: 400 }); + return HttpResponse.error(); } return HttpResponse.json({ @@ -118,7 +118,7 @@ export const handlers = [ const data = await request.json(); if (typeof data !== "object" || !data || !data["userId"]) { - return new HttpResponse(null, { status: 400 }); + return HttpResponse.error(); } return HttpResponse.json({ @@ -130,7 +130,7 @@ export const handlers = [ const data = await request.json(); if (typeof data !== "object" || !data || !data["userId"]) { - return new HttpResponse(null, { status: 400 }); + return HttpResponse.error(); } return HttpResponse.json({ @@ -145,9 +145,9 @@ export const handlers = [ !data || !data["userId"] || typeof data["score"] !== "number" || - (!data["featureId"] && !data["featureKey"]) + (!data["featureId"] && !data["key"]) ) { - return new HttpResponse(null, { status: 400 }); + return HttpResponse.error(); } return HttpResponse.json({ @@ -173,7 +173,7 @@ export const handlers = [ async ({ request }) => { const data = await request.json(); if (typeof data !== "object") { - return new HttpResponse(null, { status: 400 }); + return HttpResponse.error(); } return HttpResponse.json({ diff --git a/packages/browser-sdk/test/usage.test.ts b/packages/browser-sdk/test/usage.test.ts index 1b622ccc..b1b7d9f5 100644 --- a/packages/browser-sdk/test/usage.test.ts +++ b/packages/browser-sdk/test/usage.test.ts @@ -64,7 +64,7 @@ describe("usage", () => { await bucketInstance.track("baz", { baz: true }); await bucketInstance.feedback({ - featureId: "featureId1", + featureKey: "huddles", score: 5, comment: "Sunt bine!", question: "Cum esti?", diff --git a/packages/react-sdk/src/index.tsx b/packages/react-sdk/src/index.tsx index 6c207261..41cb5650 100644 --- a/packages/react-sdk/src/index.tsx +++ b/packages/react-sdk/src/index.tsx @@ -250,7 +250,7 @@ export function useTrack() { * ```ts * const requestFeedback = useRequestFeedback(); * bucket.requestFeedback({ - * featureId: "bucket-feature-id", + * featureKey: "file-uploads", * title: "How satisfied are you with file uploads?", * }); * ``` @@ -269,7 +269,7 @@ export function useRequestFeedback() { * ```ts * const sendFeedback = useSendFeedback(); * sendFeedback({ - * featureId: "fe2323223";; + * featureKey: "huddle"; * question: "How did you like the new huddle feature?"; * score: 5; * comment: "I loved it!"; diff --git a/packages/react-sdk/test/usage.test.tsx b/packages/react-sdk/test/usage.test.tsx index 8254d245..11256dd6 100644 --- a/packages/react-sdk/test/usage.test.tsx +++ b/packages/react-sdk/test/usage.test.tsx @@ -335,15 +335,15 @@ describe("useRequestFeedback", () => { await waitFor(async () => { result.current({ - featureId: "123", + featureKey: "huddles", title: "Test question", companyId: "456", }); expect(requestFeedback).toHaveBeenCalledOnce(); expect(requestFeedback).toHaveBeenCalledWith({ + featureKey: "huddles", companyId: "456", - featureId: "123", title: "Test question", }); });