github.com/paweljw/pop/v5@v5.4.6/model_context_test.go (about)

     1  package pop
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/stretchr/testify/require"
    10  )
    11  
    12  type ContextTable struct {
    13  	ID        string    `db:"id"`
    14  	Value     string    `db:"value"`
    15  	CreatedAt time.Time `db:"created_at"`
    16  	UpdatedAt time.Time `db:"updated_at"`
    17  }
    18  
    19  func (t ContextTable) TableName(ctx context.Context) string {
    20  	// This is singular on purpose! It will check if the TableName is properly
    21  	// Respected in slices as well.
    22  	prefix := ctx.Value("prefix").(string)
    23  
    24  	// PostgreSQL and CockroachDB support schemas which work like a prefix. For those cases, we use
    25  	// the schema to ensure that name normalization does not cause query problems.
    26  	//
    27  	// Since this works only for those two databases, we use underscore for the rest.
    28  	//
    29  	// While this schema is hardcoded, it would have been too difficult to add this special
    30  	// case to the migrations.
    31  	switch PDB.Dialect.Name() {
    32  	case nameCockroach:
    33  		fallthrough
    34  	case namePostgreSQL:
    35  		prefix = prefix + "." + prefix
    36  	}
    37  	return "context_prefix_" + prefix + "_table"
    38  }
    39  
    40  func Test_ModelContext(t *testing.T) {
    41  	if PDB == nil {
    42  		t.Skip("skipping integration tests")
    43  	}
    44  
    45  	t.Run("contextless", func(t *testing.T) {
    46  		r := require.New(t)
    47  		r.Panics(func() {
    48  			var c ContextTable
    49  			r.NoError(PDB.Create(&c))
    50  		}, "panics if context prefix is not set")
    51  	})
    52  
    53  	for _, prefix := range []string{"a", "b"} {
    54  		t.Run("prefix="+prefix, func(t *testing.T) {
    55  			r := require.New(t)
    56  
    57  			expected := ContextTable{ID: prefix, Value: prefix}
    58  			c := PDB.WithContext(context.WithValue(context.Background(), "prefix", prefix))
    59  			r.NoError(c.Create(&expected))
    60  
    61  			var actual ContextTable
    62  			r.NoError(c.Find(&actual, expected.ID))
    63  			r.EqualValues(prefix, actual.Value)
    64  			r.EqualValues(prefix, actual.ID)
    65  
    66  			exists, err := c.Where("id = ?", actual.ID).Exists(new(ContextTable))
    67  			r.NoError(err)
    68  			r.True(exists)
    69  
    70  			count, err := c.Where("id = ?", actual.ID).Count(new(ContextTable))
    71  			r.NoError(err)
    72  			r.EqualValues(1, count)
    73  
    74  			expected.Value += expected.Value
    75  			r.NoError(c.Update(&expected))
    76  
    77  			r.NoError(c.Find(&actual, expected.ID))
    78  			r.EqualValues(prefix+prefix, actual.Value)
    79  			r.EqualValues(prefix, actual.ID)
    80  
    81  			var results []ContextTable
    82  			require.NoError(t, c.All(&results))
    83  
    84  			require.NoError(t, c.First(&expected))
    85  			require.NoError(t, c.Last(&expected))
    86  
    87  			r.NoError(c.Destroy(&expected))
    88  		})
    89  	}
    90  
    91  	t.Run("prefix=unknown", func(t *testing.T) {
    92  		r := require.New(t)
    93  		c := PDB.WithContext(context.WithValue(context.Background(), "prefix", "unknown"))
    94  		err := c.Create(&ContextTable{ID: "unknown"})
    95  		r.Error(err)
    96  
    97  		if !strings.Contains(err.Error(), "context_prefix_unknown") { // All other databases
    98  			t.Fatalf("Expected error to contain indicator that table does not exist but got: %s", err.Error())
    99  		}
   100  	})
   101  
   102  	t.Run("cache_busting", func(t *testing.T) {
   103  		r := require.New(t)
   104  
   105  		var expectedA, expectedB ContextTable
   106  		expectedA.ID = "expectedA"
   107  		expectedB.ID = "expectedB"
   108  
   109  		cA := PDB.WithContext(context.WithValue(context.Background(), "prefix", "a"))
   110  		r.NoError(cA.Create(&expectedA))
   111  
   112  		cB := PDB.WithContext(context.WithValue(context.Background(), "prefix", "b"))
   113  		r.NoError(cB.Create(&expectedB))
   114  
   115  		var actualA, actualB []ContextTable
   116  		r.NoError(cA.All(&actualA))
   117  		r.NoError(cB.All(&actualB))
   118  
   119  		r.Len(actualA, 1)
   120  		r.Len(actualB, 1)
   121  
   122  		r.NotEqual(actualA[0].ID, actualB[0].ID, "if these are equal context switching did not work")
   123  	})
   124  }