...

Source file src/oss.terrastruct.com/d2/d2ir/filter_test.go

Documentation: oss.terrastruct.com/d2/d2ir

     1  package d2ir_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"oss.terrastruct.com/util-go/assert"
     7  )
     8  
     9  func testCompileFilters(t *testing.T) {
    10  	t.Parallel()
    11  
    12  	tca := []testCase{
    13  		{
    14  			name: "base",
    15  			run: func(t testing.TB) {
    16  				m, err := compile(t, `jacob: {
    17  	shape: circle
    18  }
    19  jeremy: {
    20  	shape: rectangle
    21  }
    22  *: {
    23  	&shape: rectangle
    24  	label: I'm a rectangle
    25  }`)
    26  				assert.Success(t, err)
    27  				assertQuery(t, m, 1, 0, nil, "jacob")
    28  				assertQuery(t, m, 2, 0, nil, "jeremy")
    29  				assertQuery(t, m, 0, 0, "I'm a rectangle", "jeremy.label")
    30  			},
    31  		},
    32  		{
    33  			name: "order",
    34  			run: func(t testing.TB) {
    35  				m, err := compile(t, `jacob: {
    36  	shape: circle
    37  }
    38  jeremy: {
    39  	shape: rectangle
    40  }
    41  *: {
    42  	label: I'm a rectangle
    43  	&shape: rectangle
    44  }`)
    45  				assert.Success(t, err)
    46  				assertQuery(t, m, 5, 0, nil, "")
    47  				assertQuery(t, m, 1, 0, nil, "jacob")
    48  				assertQuery(t, m, 2, 0, nil, "jeremy")
    49  				assertQuery(t, m, 0, 0, "I'm a rectangle", "jeremy.label")
    50  			},
    51  		},
    52  		{
    53  			name: "array",
    54  			run: func(t testing.TB) {
    55  				m, err := compile(t, `the-little-cannon: {
    56  	class: [server; deployed]
    57  }
    58  dino: {
    59  	class: [internal; deployed]
    60  }
    61  catapult: {
    62  	class: [jacob; server]
    63  }
    64  
    65  *: {
    66  	&class: server
    67  	style.multiple: true
    68  }
    69  `)
    70  				assert.Success(t, err)
    71  				assertQuery(t, m, 10, 0, nil, "")
    72  				assertQuery(t, m, 3, 0, nil, "the-little-cannon")
    73  				assertQuery(t, m, 1, 0, nil, "dino")
    74  				assertQuery(t, m, 3, 0, nil, "catapult")
    75  			},
    76  		},
    77  		{
    78  			name: "edge",
    79  			run: func(t testing.TB) {
    80  				m, err := compile(t, `x -> y: {
    81  	source-arrowhead.shape: diamond
    82  	target-arrowhead.shape: diamond
    83  }
    84  x -> y
    85  
    86  (x -> *)[*]: {
    87  	&source-arrowhead.shape: diamond
    88  	&target-arrowhead.shape: diamond
    89  	label: diamond shape arrowheads
    90  }
    91  `)
    92  				assert.Success(t, err)
    93  				assertQuery(t, m, 7, 2, nil, "")
    94  				assertQuery(t, m, 5, 0, nil, "(x -> y)[0]")
    95  				assertQuery(t, m, 0, 0, "diamond shape arrowheads", "(x -> y)[0].label")
    96  				assertQuery(t, m, 0, 0, nil, "(x -> y)[1]")
    97  			},
    98  		},
    99  		{
   100  			name: "label-filter/1",
   101  			run: func(t testing.TB) {
   102  				m, err := compile(t, `
   103  x
   104  y
   105  p: p
   106  a -> z: delta
   107  
   108  *.style.opacity: 0.1
   109  *: {
   110    &label: x
   111    style.opacity: 1
   112  }
   113  *: {
   114    &label: p
   115    style.opacity: 0.5
   116  }
   117  (* -> *)[*]: {
   118  	&label: delta
   119  	target-arrowhead.shape: diamond
   120  }
   121  `)
   122  				assert.Success(t, err)
   123  				assertQuery(t, m, 17, 1, nil, "")
   124  				assertQuery(t, m, 0, 0, 1, "x.style.opacity")
   125  				assertQuery(t, m, 0, 0, 0.1, "y.style.opacity")
   126  				assertQuery(t, m, 0, 0, 0.5, "p.style.opacity")
   127  				assertQuery(t, m, 0, 0, 0.1, "a.style.opacity")
   128  				assertQuery(t, m, 0, 0, 0.1, "z.style.opacity")
   129  				assertQuery(t, m, 0, 0, "diamond", "(a -> z).target-arrowhead.shape")
   130  			},
   131  		},
   132  		{
   133  			name: "label-filter/2",
   134  			run: func(t testing.TB) {
   135  				m, err := compile(t, `
   136  (* -> *)[*].style.opacity: 0.1
   137  
   138  (* -> *)[*]: {
   139    &label: hi
   140    style.opacity: 1
   141  }
   142  
   143  x -> y: hi
   144  x -> y
   145  `)
   146  				assert.Success(t, err)
   147  				assertQuery(t, m, 6, 2, nil, "")
   148  				assertQuery(t, m, 2, 0, "hi", "(x -> y)[0]")
   149  				assertQuery(t, m, 0, 0, 1, "(x -> y)[0].style.opacity")
   150  				assertQuery(t, m, 0, 0, 0.1, "(x -> y)[1].style.opacity")
   151  			},
   152  		},
   153  		{
   154  			name: "lazy-filter",
   155  			run: func(t testing.TB) {
   156  				m, err := compile(t, `
   157  *: {
   158    &label: a
   159    style.fill: yellow
   160  }
   161  
   162  a
   163  # if i remove this line, the glob applies as expected
   164  b
   165  b.label: a
   166  `)
   167  				assert.Success(t, err)
   168  				assertQuery(t, m, 7, 0, nil, "")
   169  				assertQuery(t, m, 0, 0, "yellow", "a.style.fill")
   170  				assertQuery(t, m, 0, 0, "yellow", "b.style.fill")
   171  			},
   172  		},
   173  		{
   174  			name: "primary-filter",
   175  			run: func(t testing.TB) {
   176  				m, err := compile(t, `
   177  parent: {
   178    a -> b1
   179    a -> b2
   180    a -> b3
   181  
   182    b1 -> c1
   183    b1 -> c2
   184  
   185    c1: {
   186      c1-child.class: hidden
   187    }
   188  
   189    c2: {
   190      C2-child.class: hidden
   191    }
   192    c2.class: hidden
   193    b2.class: hidden
   194  }
   195  
   196  classes: {
   197    hidden: {
   198      style: {
   199        fill: red
   200      }
   201    }
   202  }
   203  
   204  # Error
   205  **: null {
   206    &class: hidden
   207  }
   208  `)
   209  				assert.Success(t, err)
   210  				assertQuery(t, m, 9, 3, nil, "")
   211  			},
   212  		},
   213  	}
   214  
   215  	runa(t, tca)
   216  
   217  	t.Run("errors", func(t *testing.T) {
   218  		tca := []testCase{
   219  			{
   220  				name: "bad-syntax",
   221  				run: func(t testing.TB) {
   222  					_, err := compile(t, `jacob.style: {
   223  	fill: red
   224  	multiple: true
   225  }
   226  
   227  *.&style: {
   228  		fill: red
   229  		multiple: true
   230  }
   231  `)
   232  					assert.ErrorString(t, err, `TestCompile/filters/errors/bad-syntax.d2:6:3: unexpected text after map key
   233  TestCompile/filters/errors/bad-syntax.d2:9:1: unexpected map termination character } in file map`)
   234  				},
   235  			},
   236  			{
   237  				name: "outside-glob",
   238  				run: func(t testing.TB) {
   239  					_, err := compile(t, `jacob.style: {
   240  	fill: red
   241  	multiple: true
   242  }
   243  &a
   244  `)
   245  					assert.ErrorString(t, err, `TestCompile/filters/errors/outside-glob.d2:5:1: glob filters cannot be used outside globs`)
   246  				},
   247  			},
   248  			{
   249  				name: "no-glob",
   250  				run: func(t testing.TB) {
   251  					_, err := compile(t, `jacob.style: {
   252  	fill: red
   253  	multiple: true
   254  }
   255  
   256  jasmine.style: {
   257  		&fill: red
   258  		multiple: false
   259  }
   260  `)
   261  					assert.ErrorString(t, err, `TestCompile/filters/errors/no-glob.d2:7:3: glob filters cannot be used outside globs`)
   262  				},
   263  			},
   264  			{
   265  				name: "composite",
   266  				run: func(t testing.TB) {
   267  					_, err := compile(t, `jacob.style: {
   268  	fill: red
   269  	multiple: true
   270  }
   271  *: {
   272  	&style: {
   273  		fill: red
   274  		multiple: true
   275  	}
   276  }
   277  `)
   278  					assert.ErrorString(t, err, `TestCompile/filters/errors/composite.d2:6:2: glob filters cannot be composites`)
   279  				},
   280  			},
   281  		}
   282  		runa(t, tca)
   283  	})
   284  }
   285  

View as plain text