@@ -520,6 +520,57 @@ describe('Proxy structured producers', function () {
520520 } ) ;
521521 } ) ;
522522
523+ it ( 'normalizes numeric v2ray-plugin mux values across Clash-family YAML producers' , function ( ) {
524+ const buildProxy = ( name , mux ) => ( {
525+ type : 'ss' ,
526+ name,
527+ server : 'ss.example.com' ,
528+ port : 8388 ,
529+ cipher : 'aes-128-gcm' ,
530+ password : 'secret' ,
531+ 'skip-cert-verify' : false ,
532+ plugin : 'v2ray-plugin' ,
533+ 'plugin-opts' : {
534+ mode : 'websocket' ,
535+ host : 'cdn.example.com' ,
536+ path : '/socket' ,
537+ tls : true ,
538+ 'skip-cert-verify' : true ,
539+ mux,
540+ } ,
541+ } ) ;
542+
543+ for ( const platform of [
544+ 'Clash' ,
545+ 'ClashMeta' ,
546+ 'Shadowrocket' ,
547+ 'Stash' ,
548+ ] ) {
549+ const internal = produceInternal ( platform , [
550+ buildProxy ( `${ platform } Mux On` , 1 ) ,
551+ buildProxy ( `${ platform } Mux Off` , 0 ) ,
552+ ] ) ;
553+
554+ expect ( internal , platform ) . to . have . length ( 2 ) ;
555+ expectSubset ( internal [ 0 ] , {
556+ name : `${ platform } Mux On` ,
557+ 'plugin-opts' : {
558+ tls : true ,
559+ 'skip-cert-verify' : true ,
560+ mux : true ,
561+ } ,
562+ } ) ;
563+ expectSubset ( internal [ 1 ] , {
564+ name : `${ platform } Mux Off` ,
565+ 'plugin-opts' : {
566+ tls : true ,
567+ 'skip-cert-verify' : true ,
568+ mux : false ,
569+ } ,
570+ } ) ;
571+ }
572+ } ) ;
573+
523574 it ( 'skips invalid Egern nodes and keeps the rest of the subscription' , function ( ) {
524575 const proxies = [
525576 {
@@ -558,6 +609,55 @@ describe('Proxy structured producers', function () {
558609 } ) ;
559610 } ) ;
560611
612+ it ( 'keeps normalized v2ray-plugin mux state in sing-box plugin opts' , function ( ) {
613+ const buildProxy = ( name , mux ) => ( {
614+ type : 'ss' ,
615+ name,
616+ server : 'ss.example.com' ,
617+ port : 8388 ,
618+ cipher : 'aes-128-gcm' ,
619+ password : 'secret' ,
620+ plugin : 'v2ray-plugin' ,
621+ 'plugin-opts' : {
622+ mode : 'websocket' ,
623+ host : 'cdn.example.com' ,
624+ path : '/socket' ,
625+ tls : true ,
626+ mux,
627+ } ,
628+ } ) ;
629+
630+ const output = loadProducedJson ( 'sing-box' , [
631+ buildProxy ( 'Sing-box Mux On' , 1 ) ,
632+ buildProxy ( 'Sing-box Mux Off' , 0 ) ,
633+ ] ) ;
634+ const muxOn = output . outbounds . find (
635+ ( outbound ) => outbound . tag === 'Sing-box Mux On' ,
636+ ) ;
637+ const muxOff = output . outbounds . find (
638+ ( outbound ) => outbound . tag === 'Sing-box Mux Off' ,
639+ ) ;
640+
641+ expect ( output . outbounds ) . to . have . length ( 2 ) ;
642+ expectSubset ( muxOn , {
643+ tag : 'Sing-box Mux On' ,
644+ type : 'shadowsocks' ,
645+ plugin : 'v2ray-plugin' ,
646+ multiplex : {
647+ enabled : true ,
648+ } ,
649+ } ) ;
650+ expect ( muxOn . plugin_opts ) . to . include ( 'mux=true' ) ;
651+
652+ expectSubset ( muxOff , {
653+ tag : 'Sing-box Mux Off' ,
654+ type : 'shadowsocks' ,
655+ plugin : 'v2ray-plugin' ,
656+ } ) ;
657+ expect ( muxOff ) . to . not . have . property ( 'multiplex' ) ;
658+ expect ( muxOff . plugin_opts ) . to . include ( 'mux=false' ) ;
659+ } ) ;
660+
561661 it ( 'emits sing-box outbounds with reality tls and websocket transport' , function ( ) {
562662 const output = loadProducedJson ( 'sing-box' , {
563663 type : 'vless' ,
0 commit comments