github.com/cosmos/cosmos-sdk@v0.50.10/x/gov/client/cli/tx_test.go (about)

     1  package cli_test
     2  
     3  import (
     4  	"encoding/base64"
     5  	"fmt"
     6  	"io"
     7  	"testing"
     8  
     9  	abci "github.com/cometbft/cometbft/abci/types"
    10  	rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
    11  	"github.com/stretchr/testify/suite"
    12  
    13  	sdkmath "cosmossdk.io/math"
    14  
    15  	"github.com/cosmos/cosmos-sdk/client"
    16  	"github.com/cosmos/cosmos-sdk/client/flags"
    17  	"github.com/cosmos/cosmos-sdk/crypto/keyring"
    18  	"github.com/cosmos/cosmos-sdk/testutil"
    19  	clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
    20  	sdk "github.com/cosmos/cosmos-sdk/types"
    21  	testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"
    22  	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
    23  	"github.com/cosmos/cosmos-sdk/x/gov"
    24  	"github.com/cosmos/cosmos-sdk/x/gov/client/cli"
    25  	govclitestutil "github.com/cosmos/cosmos-sdk/x/gov/client/testutil"
    26  	"github.com/cosmos/cosmos-sdk/x/gov/types"
    27  	v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
    28  	"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
    29  )
    30  
    31  type CLITestSuite struct {
    32  	suite.Suite
    33  
    34  	kr        keyring.Keyring
    35  	encCfg    testutilmod.TestEncodingConfig
    36  	baseCtx   client.Context
    37  	clientCtx client.Context
    38  }
    39  
    40  func TestCLITestSuite(t *testing.T) {
    41  	suite.Run(t, new(CLITestSuite))
    42  }
    43  
    44  func (s *CLITestSuite) SetupSuite() {
    45  	s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{})
    46  	s.kr = keyring.NewInMemory(s.encCfg.Codec)
    47  	s.baseCtx = client.Context{}.
    48  		WithKeyring(s.kr).
    49  		WithTxConfig(s.encCfg.TxConfig).
    50  		WithCodec(s.encCfg.Codec).
    51  		WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}).
    52  		WithAccountRetriever(client.MockAccountRetriever{}).
    53  		WithOutput(io.Discard).
    54  		WithChainID("test-chain")
    55  
    56  	ctxGen := func() client.Context {
    57  		bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{})
    58  		c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
    59  			Value: bz,
    60  		})
    61  		return s.baseCtx.WithClient(c)
    62  	}
    63  	s.clientCtx = ctxGen()
    64  
    65  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
    66  
    67  	// create a proposal with deposit
    68  	_, err := govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(),
    69  		"Text Proposal 1", "Where is the title!?", v1beta1.ProposalTypeText,
    70  		fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin("stake", v1.DefaultMinDepositTokens).String()))
    71  	s.Require().NoError(err)
    72  
    73  	// vote for proposal
    74  	_, err = govclitestutil.MsgVote(s.clientCtx, val[0].Address.String(), "1", "yes")
    75  	s.Require().NoError(err)
    76  
    77  	// create a proposal without deposit
    78  	_, err = govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(),
    79  		"Text Proposal 2", "Where is the title!?", v1beta1.ProposalTypeText)
    80  	s.Require().NoError(err)
    81  
    82  	// create a proposal3 with deposit
    83  	_, err = govclitestutil.MsgSubmitLegacyProposal(s.clientCtx, val[0].Address.String(),
    84  		"Text Proposal 3", "Where is the title!?", v1beta1.ProposalTypeText,
    85  		fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin("stake", v1.DefaultMinDepositTokens).String()))
    86  	s.Require().NoError(err)
    87  
    88  	// vote for proposal3 as val
    89  	_, err = govclitestutil.MsgVote(s.clientCtx, val[0].Address.String(), "3", "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05")
    90  	s.Require().NoError(err)
    91  }
    92  
    93  func (s *CLITestSuite) TestNewCmdSubmitProposal() {
    94  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
    95  
    96  	// Create a legacy proposal JSON, make sure it doesn't pass this new CLI
    97  	// command.
    98  	invalidProp := `{
    99  		"title": "",
   100  		"description": "Where is the title!?",
   101  		"type": "Text",
   102  		"deposit": "-324foocoin"
   103  	}`
   104  	invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp)
   105  	defer invalidPropFile.Close()
   106  
   107  	// Create a valid new proposal JSON.
   108  	propMetadata := []byte{42}
   109  	validProp := fmt.Sprintf(`
   110  	{
   111  		"messages": [
   112  			{
   113  				"@type": "/cosmos.gov.v1.MsgExecLegacyContent",
   114  				"authority": "%s",
   115  				"content": {
   116  					"@type": "/cosmos.gov.v1beta1.TextProposal",
   117  					"title": "My awesome title",
   118  					"description": "My awesome description"
   119  				}
   120  			}
   121  		],
   122  		"title": "My awesome title",
   123  		"summary": "My awesome description",
   124  		"metadata": "%s",
   125  		"deposit": "%s"
   126  	}`, authtypes.NewModuleAddress(types.ModuleName), base64.StdEncoding.EncodeToString(propMetadata), sdk.NewCoin("stake", sdkmath.NewInt(5431)))
   127  	validPropFile := testutil.WriteToNewTempFile(s.T(), validProp)
   128  	defer validPropFile.Close()
   129  
   130  	testCases := []struct {
   131  		name         string
   132  		args         []string
   133  		expectErrMsg string
   134  	}{
   135  		{
   136  			"invalid proposal",
   137  			[]string{
   138  				invalidPropFile.Name(),
   139  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   140  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   141  			},
   142  			"invalid decimal coin expression",
   143  		},
   144  		{
   145  			"valid proposal",
   146  			[]string{
   147  				validPropFile.Name(),
   148  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   149  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   150  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   151  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   152  			},
   153  			"",
   154  		},
   155  	}
   156  
   157  	for _, tc := range testCases {
   158  		tc := tc
   159  
   160  		s.Run(tc.name, func() {
   161  			cmd := cli.NewCmdSubmitProposal()
   162  
   163  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   164  			if tc.expectErrMsg != "" {
   165  				s.Require().Error(err)
   166  				s.Require().Contains(err.Error(), tc.expectErrMsg)
   167  			} else {
   168  				s.Require().NoError(err)
   169  				msg := &sdk.TxResponse{}
   170  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String())
   171  			}
   172  		})
   173  	}
   174  }
   175  
   176  func (s *CLITestSuite) TestNewCmdSubmitLegacyProposal() {
   177  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   178  
   179  	invalidProp := `{
   180  	  "title": "",
   181  		"description": "Where is the title!?",
   182  		"type": "Text",
   183  	  "deposit": "-324foocoin"
   184  	}`
   185  	invalidPropFile := testutil.WriteToNewTempFile(s.T(), invalidProp)
   186  	defer invalidPropFile.Close()
   187  	validProp := fmt.Sprintf(`{
   188  	  "title": "Text Proposal",
   189  		"description": "Hello, World!",
   190  		"type": "Text",
   191  	  "deposit": "%s"
   192  	}`, sdk.NewCoin("stake", sdkmath.NewInt(5431)))
   193  	validPropFile := testutil.WriteToNewTempFile(s.T(), validProp)
   194  	defer validPropFile.Close()
   195  
   196  	testCases := []struct {
   197  		name         string
   198  		args         []string
   199  		expectErrMsg string
   200  	}{
   201  		{
   202  			"invalid proposal (file)",
   203  			[]string{
   204  				fmt.Sprintf("--%s=%s", cli.FlagProposal, invalidPropFile.Name()),
   205  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   206  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   207  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   208  			},
   209  			"failed to parse proposal: proposal title is required",
   210  		},
   211  		{
   212  			"invalid proposal",
   213  			[]string{
   214  				fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription),
   215  				fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText),
   216  				fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin("stake", sdkmath.NewInt(5431)).String()),
   217  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   218  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   219  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   220  			},
   221  			"failed to parse proposal: proposal title is required",
   222  		},
   223  		{
   224  			"valid transaction (file)",
   225  
   226  			[]string{
   227  				fmt.Sprintf("--%s=%s", cli.FlagProposal, validPropFile.Name()),
   228  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   229  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   230  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   231  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   232  			},
   233  			"",
   234  		},
   235  		{
   236  			"valid transaction",
   237  			[]string{
   238  				fmt.Sprintf("--%s='Text Proposal'", cli.FlagTitle),
   239  				fmt.Sprintf("--%s='Where is the title!?'", cli.FlagDescription),
   240  				fmt.Sprintf("--%s=%s", cli.FlagProposalType, v1beta1.ProposalTypeText),
   241  				fmt.Sprintf("--%s=%s", cli.FlagDeposit, sdk.NewCoin("stake", sdkmath.NewInt(5431)).String()),
   242  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   243  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   244  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   245  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   246  			},
   247  			"",
   248  		},
   249  	}
   250  
   251  	for _, tc := range testCases {
   252  		tc := tc
   253  
   254  		s.Run(tc.name, func() {
   255  			cmd := cli.NewCmdSubmitLegacyProposal()
   256  
   257  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   258  			if tc.expectErrMsg != "" {
   259  				s.Require().Error(err)
   260  				s.Require().Contains(err.Error(), tc.expectErrMsg)
   261  			} else {
   262  				s.Require().NoError(err)
   263  				msg := &sdk.TxResponse{}
   264  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), msg), out.String())
   265  			}
   266  		})
   267  	}
   268  }
   269  
   270  func (s *CLITestSuite) TestNewCmdDeposit() {
   271  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   272  
   273  	testCases := []struct {
   274  		name         string
   275  		args         []string
   276  		expectErrMsg string
   277  	}{
   278  		{
   279  			"invalid proposal id",
   280  			[]string{
   281  				"abc",
   282  				sdk.NewCoin("stake", sdkmath.NewInt(10)).String(), // 10stake
   283  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   284  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   285  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   286  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   287  			},
   288  			"proposal-id abc not a valid uint, please input a valid proposal-id",
   289  		},
   290  		{
   291  			"without deposit amount",
   292  			[]string{
   293  				"1",
   294  				"invalidCoin",
   295  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   296  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   297  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   298  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   299  			},
   300  			"invalid decimal coin expression: invalidCoin",
   301  		},
   302  		{
   303  			"deposit on a proposal",
   304  			[]string{
   305  				"10",
   306  				sdk.NewCoin("stake", sdkmath.NewInt(10)).String(), // 10stake
   307  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   308  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   309  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   310  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   311  			},
   312  			"",
   313  		},
   314  	}
   315  
   316  	for _, tc := range testCases {
   317  		tc := tc
   318  
   319  		s.Run(tc.name, func() {
   320  			cmd := cli.NewCmdDeposit()
   321  
   322  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   323  			if tc.expectErrMsg != "" {
   324  				s.Require().Error(err)
   325  				s.Require().Contains(err.Error(), tc.expectErrMsg)
   326  			} else {
   327  				s.Require().NoError(err)
   328  				resp := &sdk.TxResponse{}
   329  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), resp), out.String())
   330  			}
   331  		})
   332  	}
   333  }
   334  
   335  func (s *CLITestSuite) TestNewCmdVote() {
   336  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   337  
   338  	testCases := []struct {
   339  		name         string
   340  		args         []string
   341  		expectErrMsg string
   342  	}{
   343  		{
   344  			"vote for invalid proposal",
   345  			[]string{
   346  				"abc",
   347  				"yes",
   348  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   349  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   350  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   351  				fmt.Sprintf("--metadata=%s", "AQ=="),
   352  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   353  			},
   354  			"proposal-id abc not a valid int, please input a valid proposal-id",
   355  		},
   356  		{
   357  			"invalid vote",
   358  			[]string{
   359  				"1",
   360  				"AYE",
   361  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   362  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   363  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   364  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   365  			},
   366  			"'AYE' is not a valid vote option",
   367  		},
   368  		{
   369  			"valid vote",
   370  			[]string{
   371  				"1",
   372  				"yes",
   373  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   374  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   375  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   376  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   377  			},
   378  			"",
   379  		},
   380  		{
   381  			"valid vote with metadata",
   382  			[]string{
   383  				"1",
   384  				"yes",
   385  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   386  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   387  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   388  				fmt.Sprintf("--metadata=%s", "AQ=="),
   389  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   390  			},
   391  			"",
   392  		},
   393  	}
   394  
   395  	for _, tc := range testCases {
   396  		tc := tc
   397  		s.Run(tc.name, func() {
   398  			cmd := cli.NewCmdVote()
   399  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   400  
   401  			if tc.expectErrMsg != "" {
   402  				s.Require().Error(err)
   403  				s.Require().Contains(err.Error(), tc.expectErrMsg)
   404  			} else {
   405  				s.Require().NoError(err)
   406  				resp := &sdk.TxResponse{}
   407  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), resp), out.String())
   408  			}
   409  		})
   410  	}
   411  }
   412  
   413  func (s *CLITestSuite) TestNewCmdWeightedVote() {
   414  	val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
   415  
   416  	testCases := []struct {
   417  		name         string
   418  		args         []string
   419  		expectErrMsg string
   420  	}{
   421  		{
   422  			"vote for invalid proposal",
   423  			[]string{
   424  				"abc",
   425  				"yes",
   426  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   427  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   428  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   429  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   430  			},
   431  			"proposal-id abc not a valid int, please input a valid proposal-id",
   432  		},
   433  		{
   434  			"invalid vote",
   435  			[]string{
   436  				"1",
   437  				"AYE",
   438  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   439  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   440  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   441  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   442  			},
   443  			"'AYE' is not a valid vote option",
   444  		},
   445  		{
   446  			"valid vote",
   447  			[]string{
   448  				"1",
   449  				"yes",
   450  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   451  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   452  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   453  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   454  			},
   455  			"",
   456  		},
   457  		{
   458  			"valid vote with metadata",
   459  			[]string{
   460  				"1",
   461  				"yes",
   462  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   463  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   464  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   465  				fmt.Sprintf("--metadata=%s", "AQ=="),
   466  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   467  			},
   468  			"",
   469  		},
   470  		{
   471  			"invalid valid split vote string",
   472  			[]string{
   473  				"1",
   474  				"yes/0.6,no/0.3,abstain/0.05,no_with_veto/0.05",
   475  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   476  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   477  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   478  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   479  			},
   480  			"'yes/0.6' is not a valid vote option",
   481  		},
   482  		{
   483  			"valid split vote",
   484  			[]string{
   485  				"1",
   486  				"yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05",
   487  				fmt.Sprintf("--%s=%s", flags.FlagFrom, val[0].Address.String()),
   488  				fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation),
   489  				fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync),
   490  				fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(10))).String()),
   491  			},
   492  			"",
   493  		},
   494  	}
   495  
   496  	for _, tc := range testCases {
   497  		tc := tc
   498  		s.Run(tc.name, func() {
   499  			cmd := cli.NewCmdWeightedVote()
   500  			out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args)
   501  			if tc.expectErrMsg != "" {
   502  				s.Require().Error(err)
   503  				s.Require().Contains(err.Error(), tc.expectErrMsg)
   504  			} else {
   505  				s.Require().NoError(err)
   506  				resp := &sdk.TxResponse{}
   507  				s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), resp), out.String())
   508  			}
   509  		})
   510  	}
   511  }