package envtest
import (
"context"
"strings"
"github.com/buger/jsonparser"
"github.com/stretchr/testify/require"
sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/ignite/cli/v29/ignite/pkg/multiformatname"
"github.com/ignite/cli/v29/ignite/templates/field"
"github.com/ignite/cli/v29/ignite/templates/field/datatype"
)
func testValue(name datatype.Name) string {
dt, _ := datatype.IsSupportedType(name)
return dt.DefaultTestValue
}
func txArgs(fields field.Fields) []string {
args := make([]string, len(fields))
for i, f := range fields {
args[i] = testValue(f.DatatypeName)
}
return args
}
func (a *App) assertJSONData(data []byte, msgName string, fields field.Fields) {
for _, f := range fields {
dt := testValue(f.DatatypeName)
value, _, _, err := jsonparser.Get(data, msgName, f.Name.Snake)
require.NoError(a.env.T(), err)
if dt == "{}" {
continue
}
v := string(value)
switch {
case f.DatatypeName == datatype.Coin:
c, err := sdktypes.ParseCoinNormalized(dt)
require.NoError(a.env.T(), err)
amount, err := jsonparser.GetString(value, "amount")
require.NoError(a.env.T(), err)
require.EqualValues(a.env.T(), amount, c.Amount.String())
denom, err := jsonparser.GetString(value, "denom")
require.NoError(a.env.T(), err)
require.EqualValues(a.env.T(), denom, c.Denom)
case f.DatatypeName == datatype.Coins || f.DatatypeName == datatype.CoinSliceAlias:
c, err := sdktypes.ParseCoinsNormalized(dt)
require.NoError(a.env.T(), err)
cJSON, err := c.MarshalJSON()
require.NoError(a.env.T(), err)
dt = string(cJSON)
require.JSONEq(a.env.T(), dt, v)
case f.DatatypeName == datatype.DecCoin || f.DatatypeName == datatype.DecCoins || f.DatatypeName == datatype.DecCoinSliceAlias:
c, err := sdktypes.ParseCoinNormalized(dt)
require.NoError(a.env.T(), err)
require.Contains(a.env.T(), v, c.Denom)
require.Contains(a.env.T(), v, c.Amount.String())
case f.IsSlice():
var slice []string
_, err = jsonparser.ArrayEach(value, func(value []byte, _ jsonparser.ValueType, _ int, _ error) {
slice = append(slice, string(value))
})
require.NoError(a.env.T(), err)
v = strings.Join(slice, ",")
require.EqualValues(a.env.T(), dt, v)
default:
require.EqualValues(a.env.T(), dt, v)
}
}
}
func (a *App) assertJSONList(data []byte, msgName string, fields field.Fields) {
value, _, _, err := jsonparser.Get(data, msgName)
require.NoError(a.env.t, err)
a.assertJSONData(value, "[0]", fields)
}
func (a *App) createTx(
servers Hosts,
module string,
name multiformatname.Name,
args ...string,
) {
txResponse := a.CLITx(
servers.RPC,
module,
"create-"+name.Kebab,
args...,
)
require.Equal(a.env.T(), 0, txResponse.Code,
"tx failed code=%d log=%s", txResponse.Code, txResponse.RawLog)
tx := a.CLIQueryTx(
servers.RPC,
txResponse.TxHash,
)
require.Equal(a.env.T(), 0, tx.Code,
"tx failed code=%d log=%s", txResponse.Code, txResponse.RawLog)
}
func (a *App) RunChainAndSimulateTxs(servers Hosts) {
ctx, cancel := context.WithCancel(a.env.ctx)
defer cancel()
go func() {
a.MustServe(ctx)
}()
a.WaitChainUp(ctx, servers.API)
a.RunSimulationTxs(ctx, servers)
}
func (a *App) RunSimulationTxs(ctx context.Context, servers Hosts) {
for _, s := range a.scaffolded {
module := s.module
if module == "" {
module = a.name
}
name, err := multiformatname.NewName(s.name)
require.NoError(a.env.t, err)
switch s.typeName {
case "module":
case "list":
a.SendListTxsAndQueryFirst(ctx, servers, module, name, s.fields)
case "map":
a.SendMapTxsAndQuery(ctx, servers, module, name, s.fields, s.index)
case "single":
a.SendSingleTxsAndQuery(ctx, servers, module, name, s.fields)
case "params":
case "message":
case "query":
case "configs":
case "type":
case "packet":
}
}
}
func (a *App) SendSingleTxsAndQuery(
ctx context.Context,
servers Hosts,
module string,
name multiformatname.Name,
fields field.Fields,
) {
args := txArgs(fields)
a.createTx(servers, module, name, args...)
queryResponse := a.CLIQuery(
servers.RPC,
module,
"get-"+name.Kebab,
)
a.assertJSONData(queryResponse, name.Snake, fields)
apiResponse := a.APIQuery(
ctx,
servers.API,
a.namespace,
module,
name.Snake,
)
a.assertJSONData(apiResponse, name.Snake, fields)
require.JSONEq(a.env.t, string(queryResponse), string(apiResponse))
}
func (a *App) SendListTxsAndQueryFirst(
ctx context.Context,
servers Hosts,
module string,
name multiformatname.Name,
fields field.Fields,
) {
a.SendTxsAndQuery(ctx, servers, module, name, fields, "0")
}
func (a *App) SendMapTxsAndQuery(
ctx context.Context,
servers Hosts,
module string,
name multiformatname.Name,
fields field.Fields,
index field.Field,
) {
a.SendTxsAndQuery(
ctx,
servers,
module,
name,
append(field.Fields{index}, fields...),
testValue(index.DatatypeName),
)
}
func (a *App) SendTxsAndQuery(
ctx context.Context,
servers Hosts,
module string,
name multiformatname.Name,
fields field.Fields,
index string,
) {
args := txArgs(fields)
a.createTx(servers, module, name, args...)
queryResponse := a.CLIQuery(
servers.RPC,
module,
"get-"+name.Kebab,
index,
)
a.assertJSONData(queryResponse, name.Snake, fields)
apiResponse := a.APIQuery(
ctx,
servers.API,
a.namespace,
module,
name.Snake,
index,
)
a.assertJSONData(apiResponse, name.Snake, fields)
queryListResponse := a.CLIQuery(
servers.RPC,
module,
"list-"+name.Kebab,
)
a.assertJSONList(queryListResponse, name.Snake, fields)
apiListResponse := a.APIQuery(
ctx,
servers.API,
a.namespace,
module,
name.Snake,
)
a.assertJSONList(apiListResponse, name.Snake, fields)
}