github.com/expr-lang/expr@v1.16.9/docgen/docgen_test.go (about)

     1  package docgen_test
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/expr-lang/expr/internal/testify/assert"
     9  	"github.com/expr-lang/expr/internal/testify/require"
    10  
    11  	. "github.com/expr-lang/expr/docgen"
    12  )
    13  
    14  type Tweet struct {
    15  	Size    int
    16  	Message string
    17  }
    18  
    19  type Env struct {
    20  	Tweets []Tweet
    21  	Config struct {
    22  		MaxSize int32
    23  	}
    24  	Env map[string]any
    25  	// NOTE: conflicting type name
    26  	TimeWeekday time.Weekday
    27  	Weekday     Weekday
    28  }
    29  
    30  type Weekday int
    31  
    32  func (Weekday) String() string {
    33  	return ""
    34  }
    35  
    36  type Duration int
    37  
    38  func (Duration) String() string {
    39  	return ""
    40  }
    41  
    42  func (*Env) Duration(s string) Duration {
    43  	return Duration(0)
    44  }
    45  
    46  func TestCreateDoc(t *testing.T) {
    47  	Operators = nil
    48  	Builtins = nil
    49  	doc := CreateDoc(&Env{})
    50  	expected := &Context{
    51  		Variables: map[Identifier]*Type{
    52  			"Tweets": {
    53  				Kind: "array",
    54  				Type: &Type{
    55  					Kind: "struct",
    56  					Name: "Tweet",
    57  				},
    58  			},
    59  			"Config": {
    60  				Kind: "struct",
    61  				Fields: map[Identifier]*Type{
    62  					"MaxSize": {Kind: "int"},
    63  				},
    64  			},
    65  			"Env": {
    66  				Kind: "map",
    67  				Key:  &Type{Kind: "string"},
    68  				Type: &Type{Kind: "any"},
    69  			},
    70  			"Duration": {
    71  				Kind: "func",
    72  				Arguments: []*Type{
    73  					{Kind: "string"},
    74  				},
    75  				Return: &Type{Kind: "struct", Name: "Duration"},
    76  			},
    77  			"TimeWeekday": {
    78  				Name: "time.Weekday",
    79  				Kind: "struct",
    80  			},
    81  			"Weekday": {
    82  				Name: "Weekday",
    83  				Kind: "struct",
    84  			},
    85  		},
    86  		Types: map[TypeName]*Type{
    87  			"Tweet": {
    88  				Kind: "struct",
    89  				Fields: map[Identifier]*Type{
    90  					"Size":    {Kind: "int"},
    91  					"Message": {Kind: "string"},
    92  				},
    93  			},
    94  			"Duration": {
    95  				Kind: "struct",
    96  				Fields: map[Identifier]*Type{
    97  					"String": {
    98  						Kind:      "func",
    99  						Arguments: []*Type{},
   100  						Return: &Type{
   101  							Kind: "string",
   102  						},
   103  					},
   104  				},
   105  			},
   106  			"time.Weekday": {
   107  				Kind: "struct",
   108  				Fields: map[Identifier]*Type{
   109  					"String": {
   110  						Kind:      "func",
   111  						Arguments: []*Type{},
   112  						Return: &Type{
   113  							Kind: "string",
   114  						},
   115  					},
   116  				},
   117  			},
   118  			"Weekday": {
   119  				Kind: "struct",
   120  				Fields: map[Identifier]*Type{
   121  					"String": {
   122  						Kind:      "func",
   123  						Arguments: []*Type{},
   124  						Return: &Type{
   125  							Kind: "string",
   126  						},
   127  					},
   128  				},
   129  			},
   130  		},
   131  		PkgPath: "github.com/expr-lang/expr/docgen_test",
   132  	}
   133  
   134  	assert.EqualValues(t, expected, doc)
   135  }
   136  
   137  type A struct {
   138  	AmbiguousField int
   139  	OkField        int
   140  }
   141  type B struct {
   142  	AmbiguousField string
   143  }
   144  
   145  type C struct {
   146  	A
   147  	B
   148  }
   149  type EnvAmbiguous struct {
   150  	A
   151  	B
   152  	C C
   153  }
   154  
   155  func TestCreateDoc_Ambiguous(t *testing.T) {
   156  	doc := CreateDoc(&EnvAmbiguous{})
   157  	expected := &Context{
   158  		Variables: map[Identifier]*Type{
   159  			"A": {
   160  				Kind: "struct",
   161  				Name: "A",
   162  			},
   163  			"B": {
   164  				Kind: "struct",
   165  				Name: "B",
   166  			},
   167  			"OkField": {
   168  				Kind: "int",
   169  			},
   170  			"C": {
   171  				Kind: "struct",
   172  				Name: "C",
   173  			},
   174  		},
   175  		Types: map[TypeName]*Type{
   176  			"A": {
   177  				Kind: "struct",
   178  				Fields: map[Identifier]*Type{
   179  					"AmbiguousField": {Kind: "int"},
   180  					"OkField":        {Kind: "int"},
   181  				},
   182  			},
   183  			"B": {
   184  				Kind: "struct",
   185  				Fields: map[Identifier]*Type{
   186  					"AmbiguousField": {Kind: "string"},
   187  				},
   188  			},
   189  			"C": {
   190  				Kind: "struct",
   191  				Fields: map[Identifier]*Type{
   192  					"A":       {Kind: "struct", Name: "A"},
   193  					"B":       {Kind: "struct", Name: "B"},
   194  					"OkField": {Kind: "int"},
   195  				},
   196  			},
   197  		},
   198  		PkgPath: "github.com/expr-lang/expr/docgen_test",
   199  	}
   200  
   201  	assert.EqualValues(t, expected, doc)
   202  }
   203  
   204  func TestCreateDoc_FromMap(t *testing.T) {
   205  	env := map[string]any{
   206  		"Tweets": []*Tweet{},
   207  		"Config": struct {
   208  			MaxSize int
   209  		}{},
   210  		"Max": math.Max,
   211  	}
   212  	Operators = nil
   213  	Builtins = nil
   214  	doc := CreateDoc(env)
   215  	expected := &Context{
   216  		Variables: map[Identifier]*Type{
   217  			"Tweets": {
   218  				Kind: "array",
   219  				Type: &Type{
   220  					Kind: "struct",
   221  					Name: "docgen_test.Tweet",
   222  				},
   223  			},
   224  			"Config": {
   225  				Kind: "struct",
   226  				Fields: map[Identifier]*Type{
   227  					"MaxSize": {Kind: "int"},
   228  				},
   229  			},
   230  			"Max": {
   231  				Kind: "func",
   232  				Arguments: []*Type{
   233  					{Kind: "float"},
   234  					{Kind: "float"},
   235  				},
   236  				Return: &Type{Kind: "float"},
   237  			},
   238  		},
   239  		Types: map[TypeName]*Type{
   240  			"docgen_test.Tweet": {
   241  				Kind: "struct",
   242  				Fields: map[Identifier]*Type{
   243  					"Size":    {Kind: "int"},
   244  					"Message": {Kind: "string"},
   245  				},
   246  			},
   247  		},
   248  	}
   249  
   250  	require.EqualValues(t, expected, doc)
   251  }
   252  
   253  func TestContext_Markdown(t *testing.T) {
   254  	doc := CreateDoc(&Env{})
   255  	md := doc.Markdown()
   256  	require.True(t, len(md) > 0)
   257  }