makethisbetter 1.1.2 → 1.1.3

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.
@@ -28,6 +28,7 @@ export declare class ClarifyCard {
28
28
  private stopPolling;
29
29
  private poll;
30
30
  private handleDone;
31
+ private renderConversation;
31
32
  private renderMessages;
32
33
  private appendMessage;
33
34
  private showThinking;
@@ -1 +1 @@
1
- {"version":3,"file":"clarify.d.ts","sourceRoot":"","sources":["../../src/popup/clarify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAO9C,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,YAAY,CAAA;IACtB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAQ;gBAEb,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB;IAmB7D,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,UAAU;YAqBJ,iBAAiB;YAiBjB,WAAW;IAiCzB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,WAAW;YAOL,IAAI;IAelB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IAQpB,OAAO,IAAI,IAAI;CAShB"}
1
+ {"version":3,"file":"clarify.d.ts","sourceRoot":"","sources":["../../src/popup/clarify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAO9C,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,SAAS,CAAA;IACpB,QAAQ,EAAE,YAAY,CAAA;IACtB,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,SAAS,CAAQ;gBAEb,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,kBAAkB;IAmB7D,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,UAAU;YAuBJ,iBAAiB;YAiBjB,WAAW;IAiCzB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,WAAW;YAOL,IAAI;IAelB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,YAAY;IAQpB,OAAO,IAAI,IAAI;CAShB"}
package/dist/types.d.ts CHANGED
@@ -49,6 +49,7 @@ export interface FeedbackResponse {
49
49
  id: string;
50
50
  status: string;
51
51
  project_id: string;
52
+ ai_clarify_available?: boolean;
52
53
  }
53
54
  export interface ClarifyMessage {
54
55
  role: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IACnC,IAAI,CAAC,EAAE;QACL,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IACpB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,cAAc,CAAC,EAAE;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,IAAI,EAAE,OAAO,CAAA;CACd"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAA;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IACnC,IAAI,CAAC,EAAE;QACL,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IACpB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,EAAE,UAAU,EAAE,CAAA;IACzB,cAAc,CAAC,EAAE;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAA;IAC5C,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,IAAI,EAAE,OAAO,CAAA;CACd"}
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/widget/controller.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,oBAAoB,EAAc,MAAM,UAAU,CAAA;AAIhE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAgC;gBAE5C,MAAM,EAAE,oBAAoB;IAcxC,OAAO,CAAC,OAAO;IAgBf,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,SAAS;YAcH,YAAY;IAmC1B,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,OAAO;IAiBf,OAAO,IAAI,IAAI;CAYhB"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../src/widget/controller.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,oBAAoB,EAAc,MAAM,UAAU,CAAA;AAIhE,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,GAAG,CAA2B;IACtC,OAAO,CAAC,GAAG,CAAwB;IACnC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,iBAAiB,CAAqC;IAC9D,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,mBAAmB,CAAmC;IAC9D,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,iBAAiB,CAA0B;IACnD,OAAO,CAAC,gBAAgB,CAAgC;gBAE5C,MAAM,EAAE,oBAAoB;IAcxC,OAAO,CAAC,OAAO;IAgBf,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,uBAAuB;IA6B/B,OAAO,CAAC,SAAS;YAcH,YAAY;IAuC1B,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,OAAO;IAiBf,OAAO,IAAI,IAAI;CAYhB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makethisbetter",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Make This Better JS Widget SDK — embed user feedback collection in any website",
5
5
  "type": "module",
6
6
  "main": "./dist/makethisbetter.cjs.js",
@@ -395,6 +395,109 @@ describe('ClarifyCard', () => {
395
395
  shadow.destroy()
396
396
  })
397
397
 
398
+ it('ignores Enter during IME composition', async () => {
399
+ const startClarification = vi.fn()
400
+ .mockResolvedValueOnce({
401
+ status: 'pending',
402
+ messages: [{ role: 'assistant', content: 'Tell me more' }],
403
+ done: false,
404
+ } satisfies ClarifyResponse)
405
+ .mockResolvedValueOnce({
406
+ status: 'pending',
407
+ messages: [],
408
+ done: false,
409
+ } satisfies ClarifyResponse)
410
+
411
+ const { shadow, card } = setupCard({ startClarification })
412
+ await vi.waitFor(() => {
413
+ expect(startClarification).toHaveBeenCalledOnce()
414
+ })
415
+ await vi.advanceTimersByTimeAsync(0)
416
+
417
+ const input = shadow.root.querySelector<HTMLInputElement>('.mtb-clarify-input')!
418
+ input.value = '导出坏了'
419
+ input.dispatchEvent(new Event('input'))
420
+
421
+ input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', isComposing: true }))
422
+ expect(startClarification).toHaveBeenCalledOnce()
423
+
424
+ const legacyImeEnter = new KeyboardEvent('keydown', { key: 'Enter' })
425
+ Object.defineProperty(legacyImeEnter, 'keyCode', { value: 229 })
426
+ input.dispatchEvent(legacyImeEnter)
427
+ expect(startClarification).toHaveBeenCalledOnce()
428
+
429
+ input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
430
+ await vi.waitFor(() => {
431
+ expect(startClarification).toHaveBeenCalledTimes(2)
432
+ })
433
+ expect(startClarification).toHaveBeenCalledWith('fb_123', '导出坏了')
434
+
435
+ card.destroy()
436
+ shadow.destroy()
437
+ })
438
+
439
+ it('keeps thinking indicator while waiting for the AI reply', async () => {
440
+ const startClarification = vi.fn().mockResolvedValue({
441
+ status: 'pending',
442
+ messages: [],
443
+ done: false,
444
+ } satisfies ClarifyResponse)
445
+ const getClarification = vi.fn().mockResolvedValue({
446
+ status: 'pending',
447
+ messages: [],
448
+ done: false,
449
+ } satisfies ClarifyResponse)
450
+
451
+ const { shadow, card } = setupCard({ startClarification, getClarification })
452
+ await vi.waitFor(() => {
453
+ expect(startClarification).toHaveBeenCalled()
454
+ })
455
+ await vi.advanceTimersByTimeAsync(0)
456
+
457
+ expect(shadow.root.querySelector('.mtb-clarify-thinking')).toBeTruthy()
458
+
459
+ await vi.advanceTimersByTimeAsync(2000)
460
+ await vi.waitFor(() => {
461
+ expect(getClarification).toHaveBeenCalled()
462
+ })
463
+ await vi.advanceTimersByTimeAsync(0)
464
+ expect(shadow.root.querySelector('.mtb-clarify-thinking')).toBeTruthy()
465
+
466
+ card.destroy()
467
+ shadow.destroy()
468
+ })
469
+
470
+ it('removes thinking indicator when the AI reply arrives', async () => {
471
+ const startClarification = vi.fn().mockResolvedValue({
472
+ status: 'pending',
473
+ messages: [],
474
+ done: false,
475
+ } satisfies ClarifyResponse)
476
+ const getClarification = vi.fn().mockResolvedValue({
477
+ status: 'pending',
478
+ messages: [{ role: 'assistant', content: 'What broke?' }],
479
+ done: false,
480
+ } satisfies ClarifyResponse)
481
+
482
+ const { shadow, card } = setupCard({ startClarification, getClarification })
483
+ await vi.waitFor(() => {
484
+ expect(startClarification).toHaveBeenCalled()
485
+ })
486
+ await vi.advanceTimersByTimeAsync(0)
487
+
488
+ await vi.advanceTimersByTimeAsync(2000)
489
+ await vi.waitFor(() => {
490
+ expect(getClarification).toHaveBeenCalled()
491
+ })
492
+ await vi.advanceTimersByTimeAsync(0)
493
+
494
+ expect(shadow.root.querySelector('.mtb-clarify-thinking')).toBeNull()
495
+ expect(shadow.root.querySelector('.mtb-clarify-ai')?.textContent).toBe('What broke?')
496
+
497
+ card.destroy()
498
+ shadow.destroy()
499
+ })
500
+
398
501
  it('stops polling on destroy', async () => {
399
502
  const getClarification = vi.fn().mockResolvedValue({
400
503
  status: 'pending',
@@ -76,6 +76,8 @@ export class ClarifyCard {
76
76
  })
77
77
 
78
78
  this.inputEl.addEventListener('keydown', (e: KeyboardEvent) => {
79
+ // keyCode 229: IME composition fallback for browsers without isComposing
80
+ if (e.isComposing || e.keyCode === 229) return
79
81
  if (e.key === 'Enter') {
80
82
  e.preventDefault()
81
83
  this.sendMessage(m)
@@ -90,7 +92,7 @@ export class ClarifyCard {
90
92
  try {
91
93
  const res = await this.apiClient.startClarification(this.feedbackId)
92
94
  if (this.destroyed) return
93
- this.renderMessages(res.messages)
95
+ this.renderConversation(res.messages, res.done)
94
96
  if (res.done) {
95
97
  this.handleDone()
96
98
  } else {
@@ -118,7 +120,7 @@ export class ClarifyCard {
118
120
  try {
119
121
  const res = await this.apiClient.startClarification(this.feedbackId, text)
120
122
  if (this.destroyed) return
121
- this.renderMessages(res.messages)
123
+ this.renderConversation(res.messages, res.done)
122
124
  if (res.done) {
123
125
  this.handleDone()
124
126
  } else {
@@ -151,7 +153,7 @@ export class ClarifyCard {
151
153
  try {
152
154
  const res = await this.apiClient.getClarification(this.feedbackId)
153
155
  if (this.destroyed) return
154
- this.renderMessages(res.messages)
156
+ this.renderConversation(res.messages, res.done)
155
157
  if (res.done) {
156
158
  this.stopPolling()
157
159
  this.handleDone()
@@ -170,6 +172,12 @@ export class ClarifyCard {
170
172
  }, DONE_DELAY_MS)
171
173
  }
172
174
 
175
+ private renderConversation(messages: ClarifyMessage[], done: boolean): void {
176
+ this.renderMessages(messages)
177
+ const last = messages[messages.length - 1]
178
+ if (!done && (!last || last.role === 'user')) this.showThinking()
179
+ }
180
+
173
181
  private renderMessages(messages: ClarifyMessage[]): void {
174
182
  this.messagesEl.innerHTML = ''
175
183
  for (const msg of messages) {
package/src/types.ts CHANGED
@@ -52,6 +52,7 @@ export interface FeedbackResponse {
52
52
  id: string
53
53
  status: string
54
54
  project_id: string
55
+ ai_clarify_available?: boolean
55
56
  }
56
57
 
57
58
  export interface ClarifyMessage {
@@ -61,4 +61,41 @@ describe('MakeThisBetter widget flow', () => {
61
61
  expect(shadow.querySelector('.mtb-success-title')?.textContent).toBe('Thanks!')
62
62
  }, { timeout: 5000 })
63
63
  })
64
+
65
+ it('skips the AI clarify chat when ai_clarify_available is false', async () => {
66
+ const target = document.createElement('button')
67
+ target.id = 'export-btn'
68
+ target.textContent = 'Export PDF'
69
+ document.body.appendChild(target)
70
+
71
+ document.elementsFromPoint = vi.fn(() => [target])
72
+
73
+ const fetchSpy = vi.spyOn(globalThis, 'fetch').mockImplementation(async () => {
74
+ return new Response(JSON.stringify({ id: 'fb_1', status: 'open', project_id: 'proj_test', ai_clarify_available: false }), { status: 201 })
75
+ })
76
+
77
+ MakeThisBetter.init({
78
+ projectKey: 'proj_test',
79
+ apiUrl: 'https://api.example.com/api/v1',
80
+ })
81
+
82
+ const shadow = document.getElementById('mtb-widget-host')!.shadowRoot!
83
+ shadow.querySelector<HTMLButtonElement>('.mtb-tab')!.click()
84
+
85
+ const overlay = shadow.querySelector<HTMLDivElement>('.mtb-overlay')!
86
+ overlay.dispatchEvent(new MouseEvent('mousedown', { clientX: 20, clientY: 30, bubbles: true }))
87
+ overlay.dispatchEvent(new MouseEvent('mouseup', { clientX: 20, clientY: 30, bubbles: true }))
88
+
89
+ const textarea = shadow.querySelector<HTMLTextAreaElement>('.mtb-textarea')!
90
+ textarea.value = 'Export is broken'
91
+ textarea.dispatchEvent(new Event('input'))
92
+ shadow.querySelector<HTMLButtonElement>('.mtb-submit-btn')!.click()
93
+
94
+ await vi.waitFor(() => {
95
+ expect(shadow.querySelector('.mtb-success-title')?.textContent).toBe('Thanks!')
96
+ }, { timeout: 5000 })
97
+
98
+ expect(shadow.querySelector('.mtb-clarify')).toBeNull()
99
+ expect(fetchSpy).toHaveBeenCalledTimes(1)
100
+ })
64
101
  })
@@ -183,7 +183,11 @@ export class WidgetController {
183
183
  this.session = null
184
184
  this.recordingManager?.destroy()
185
185
  this.recordingManager = null
186
- this.showClarify(feedback.id, feedback.project_id)
186
+ if (feedback.ai_clarify_available === false) {
187
+ this.showSuccess(feedback.project_id)
188
+ } else {
189
+ this.showClarify(feedback.id, feedback.project_id)
190
+ }
187
191
  } catch {
188
192
  this.popup?.setLoading(false)
189
193
  this.popup?.setError(this.messages.error.submit)