@@ -5,6 +5,7 @@ import path from "node:path";
55import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts" ;
66import { afterAll , afterEach , beforeEach , describe , expect , it , vi } from "vitest" ;
77import {
8+ createRichMenu ,
89 createDefaultMenuConfig ,
910 createGridLayout ,
1011 datetimePickerAction ,
@@ -14,19 +15,33 @@ import {
1415 uriAction ,
1516} from "./rich-menu.js" ;
1617
17- const { setRichMenuImageMock, MessagingApiBlobClientMock } = vi . hoisted ( ( ) => {
18+ const {
19+ createRichMenuMock,
20+ setRichMenuImageMock,
21+ MessagingApiClientMock,
22+ MessagingApiBlobClientMock,
23+ } = vi . hoisted ( ( ) => {
24+ const createRichMenuMockLocal = vi . fn ( ) ;
1825 const setRichMenuImageMockLocal = vi . fn ( ) ;
26+ const MessagingApiClientMockLocal = vi . fn ( function ( ) {
27+ return { createRichMenu : createRichMenuMockLocal } ;
28+ } ) ;
1929 const MessagingApiBlobClientMockLocal = vi . fn ( function ( ) {
2030 return { setRichMenuImage : setRichMenuImageMockLocal } ;
2131 } ) ;
2232 return {
33+ createRichMenuMock : createRichMenuMockLocal ,
2334 setRichMenuImageMock : setRichMenuImageMockLocal ,
35+ MessagingApiClientMock : MessagingApiClientMockLocal ,
2436 MessagingApiBlobClientMock : MessagingApiBlobClientMockLocal ,
2537 } ;
2638} ) ;
2739
2840vi . mock ( "@line/bot-sdk" , ( ) => ( {
29- messagingApi : { MessagingApiBlobClient : MessagingApiBlobClientMock } ,
41+ messagingApi : {
42+ MessagingApiClient : MessagingApiClientMock ,
43+ MessagingApiBlobClient : MessagingApiBlobClientMock ,
44+ } ,
3045} ) ) ;
3146
3247afterAll ( ( ) => {
@@ -241,6 +256,37 @@ const richMenuUploadCfg: OpenClawConfig = {
241256 } ,
242257} ;
243258
259+ describe ( "createRichMenu" , ( ) => {
260+ beforeEach ( ( ) => {
261+ createRichMenuMock . mockReset ( ) ;
262+ createRichMenuMock . mockResolvedValue ( { richMenuId : "rich-menu-1" } ) ;
263+ MessagingApiClientMock . mockClear ( ) ;
264+ } ) ;
265+
266+ it ( "truncates names and chat bar text by grapheme cluster" , async ( ) => {
267+ const emoji = "😀" ;
268+ const familyEmoji = "👨👩👧👦" ;
269+
270+ await createRichMenu (
271+ {
272+ size : { width : 2500 , height : 843 } ,
273+ name : emoji . repeat ( 301 ) ,
274+ chatBarText : familyEmoji . repeat ( 15 ) ,
275+ areas : [ ] ,
276+ } ,
277+ { cfg : richMenuUploadCfg } ,
278+ ) ;
279+
280+ expect ( MessagingApiClientMock ) . toHaveBeenCalledWith ( { channelAccessToken : "line-token" } ) ;
281+ expect ( createRichMenuMock ) . toHaveBeenCalledWith (
282+ expect . objectContaining ( {
283+ name : emoji . repeat ( 300 ) ,
284+ chatBarText : familyEmoji . repeat ( 14 ) ,
285+ } ) ,
286+ ) ;
287+ } ) ;
288+ } ) ;
289+
244290describe ( "uploadRichMenuImage" , ( ) => {
245291 let tempRoot : string ;
246292
0 commit comments