-
Notifications
You must be signed in to change notification settings - Fork 23
/
model.go
133 lines (117 loc) · 3.08 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package suite
import (
"fmt"
"io/fs"
"strings"
"github.com/gobuffalo/envy"
"github.com/gobuffalo/plush/v4"
"github.com/gobuffalo/pop/v6"
"github.com/gobuffalo/suite/v4/fix"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
// Model suite
type Model struct {
suite.Suite
*require.Assertions
DB *pop.Connection
Fixtures fs.FS
}
// SetupTest clears database
func (m *Model) SetupTest() {
m.Assertions = require.New(m.T())
if m.DB != nil {
err := m.CleanDB()
m.NoError(err)
}
}
// TearDownTest will be called after tests finish
func (m *Model) TearDownTest() {}
// DBDelta checks database table count change for a passed table name.
func (m *Model) DBDelta(delta int, name string, fn func()) {
sc, err := m.DB.Count(name)
m.NoError(err)
fn()
ec, err := m.DB.Count(name)
m.NoError(err)
m.Equal(sc+delta, ec)
}
// LoadFixture loads a named fixture into the database.
func (m *Model) LoadFixture(name string) {
sc, err := fix.Find(name)
m.NoError(err)
db := m.DB.Store
for _, table := range sc.Tables {
for _, row := range table.Row {
q := "insert into " + table.Name
keys := []string{}
skeys := []string{}
for k := range row {
keys = append(keys, k)
skeys = append(skeys, ":"+k)
}
q = q + fmt.Sprintf(" (%s) values (%s)", strings.Join(keys, ","), strings.Join(skeys, ","))
_, err = db.NamedExec(q, row)
m.NoError(err)
}
}
}
// NewModel creates a new model suite
func NewModel() *Model {
m := &Model{}
c, err := pop.Connect(envy.Get("GO_ENV", "test"))
if err == nil {
m.DB = c
}
return m
}
// NewModelWithFixturesAndContext creates a new model suite with fixtures and a passed context.
func NewModelWithFixturesAndContext(fsys fs.FS, ctx *plush.Context) (*Model, error) {
m := NewModel()
m.Fixtures = fsys
return m, fix.InitWithContext(fsys, ctx)
}
// NewModelWithFixtures creates a new model with passed fixtures box
func NewModelWithFixtures(fsys fs.FS) (*Model, error) {
m := NewModel()
m.Fixtures = fsys
return m, fix.Init(fsys)
}
func (m *Model) Run(name string, subtest func()) bool {
return m.Suite.Run(name, func() {
m.Assertions = require.New(m.Suite.T())
subtest()
})
}
// CleanDB clears records from the database, this function is
// useful to run before tests to ensure other tests are not
// affecting the one running.
func (m *Model) CleanDB() error {
if m.DB == nil {
return nil
}
switch m.DB.Dialect.Name() {
case "postgres":
deleteAllQuery := `DO
$func$
DECLARE
_tbl text;
_sch text;
BEGIN
FOR _sch, _tbl IN
SELECT schemaname, tablename
FROM pg_tables
WHERE tablename <> '%s' AND schemaname NOT IN ('pg_catalog', 'information_schema') AND tableowner = current_user
LOOP
EXECUTE format('ALTER TABLE %%I.%%I DISABLE TRIGGER ALL;', _sch, _tbl);
EXECUTE format('DELETE FROM %%I.%%I CASCADE', _sch, _tbl);
EXECUTE format('ALTER TABLE %%I.%%I ENABLE TRIGGER ALL;', _sch, _tbl);
END LOOP;
END
$func$;`
q := m.DB.RawQuery(fmt.Sprintf(deleteAllQuery, m.DB.MigrationTableName()))
return q.Exec()
default:
return m.DB.TruncateAll()
}
}