3
0

Add importer tests

This commit is contained in:
Denis Arh
2019-09-20 11:33:10 +02:00
parent 748caac786
commit c3682ca05c
12 changed files with 346 additions and 75 deletions
+39 -62
View File
@@ -1,82 +1,59 @@
package importer
import (
"fmt"
"os"
"errors"
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/internal/permissions"
)
type (
namespaceMock struct{ set types.NamespaceSet }
moduleMock struct{ set types.ModuleSet }
chartMock struct{ set types.ChartSet }
pageMock struct{ set types.PageSet }
)
func (mock *namespaceMock) FindByHandle(handle string) (o *types.Namespace, err error) {
return
}
func (mock *moduleMock) FindByHandle(namespaceID uint64, handle string) (o *types.Module, err error) {
return
}
func (mock *chartMock) FindByHandle(namespaceID uint64, handle string) (o *types.Chart, err error) {
return
}
func (mock *pageMock) FindByHandle(namespaceID uint64, handle string) (o *types.Page, err error) {
return
}
func TestChartImport_CastSet(t *testing.T) {
var (
namespace = &namespaceMock{}
module = &moduleMock{}
chart = &chartMock{}
page = &pageMock{}
pi = permissions.NewImporter(nil)
imp = NewImporter(namespace, module, chart, page, pi)
ns = &types.Namespace{
ID: 1000000,
Name: "Test",
Slug: "Test",
Enabled: true,
}
impFixTester = func(t *testing.T, name string, fn func(*testing.T, *Chart)) {
t.Run(name, func(t *testing.T) {
var aux interface{}
req := require.New(t)
f, err := os.Open(fmt.Sprintf("testdata/%s.yaml", name))
req.NoError(err)
req.NoError(yaml.NewDecoder(f).Decode(&aux))
req.NotNil(aux)
ci := NewChartImporter(imp, ns)
req.NoError(ci.CastSet(aux))
fn(t, ci)
})
}
)
impFixTester(t, "chart_full_slice", func(t *testing.T, chart *Chart) {
impFixTester(t, "chart_full_slice", func(t *testing.T, imp *Importer) {
req := require.New(t)
req.Len(chart.set, 2)
req.Len(imp.GetChartImporter("test").set, 2)
})
impFixTester(t,
"chart_with_unknown_module",
errors.New(`unknown module "un_kno_wn" referenced from chart "chart1" report config`))
// Pre fill with module that imported chart is referring to
// imp.namespaces.modules[ns.Slug] = &Module{set: []*types.Module{{Handle: "foo"}}}
modules.set = []*types.Module{{NamespaceID: ns.ID, Handle: "foo"}}
impFixTester(t, "chart_full", func(t *testing.T, chart *Chart) {
req := require.New(t)
req.Len(chart.set, 2)
req.Equal(chart.set[0].Handle, "chart1")
req.Equal(chart.set[0].Name, "chart 1")
req.NotNil(chart.set.FindByHandle("chart1"))
req.NotNil(chart.set.FindByHandle("chart2"))
tc := chart.set.FindByHandle("chart1")
req.Equal(tc.Name, "chart 1")
req.Equal(tc.Config, types.ChartConfig{Reports: []*types.ChartConfigReport{
{
Filter: "a=b",
ModuleID: 0,
Metrics: []map[string]interface{}{
{
"backgroundColor": "#e5a83b",
"beginAtZero": true,
"field": "count",
"fixTooltips": true,
"label": "Number of leads",
"type": "bar",
},
},
Dimensions: []map[string]interface{}{
{
"field": "created_at",
},
},
},
}})
})
}
+12
View File
@@ -58,6 +58,18 @@ func (imp *Importer) GetNamespaceImporter() *Namespace {
return imp.namespaces
}
func (imp *Importer) GetModuleImporter(handle string) *Module {
return imp.namespaces.modules[handle]
}
func (imp *Importer) GetPageImporter(handle string) *Page {
return imp.namespaces.pages[handle]
}
func (imp *Importer) GetChartImporter(handle string) *Chart {
return imp.namespaces.charts[handle]
}
func (imp *Importer) Cast(in interface{}) (err error) {
return deinterfacer.Each(in, func(index int, key string, val interface{}) (err error) {
switch key {
+127
View File
@@ -0,0 +1,127 @@
package importer
import (
"fmt"
"os"
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"github.com/cortezaproject/corteza-server/compose/repository"
"github.com/cortezaproject/corteza-server/compose/service"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/internal/permissions"
)
type (
namespaceMock struct{ set types.NamespaceSet }
moduleMock struct{ set types.ModuleSet }
chartMock struct{ set types.ChartSet }
pageMock struct{ set types.PageSet }
)
var (
ns = &types.Namespace{
ID: 1000000,
Name: "Test",
Slug: "test",
Enabled: true,
}
// Add namespace to the stack, make sure importer can find it
namespaces = &namespaceMock{set: types.NamespaceSet{ns}}
modules = &moduleMock{}
charts = &chartMock{}
pages = &pageMock{}
// whitelist = nil, anything can be added
pi = permissions.NewImporter(service.AccessControl(nil).Whitelist())
imp = NewImporter(namespaces, modules, charts, pages, pi)
)
func TestMain(m *testing.M) {
os.Exit(m.Run())
}
func (mock *namespaceMock) FindByHandle(slug string) (o *types.Namespace, err error) {
oo, err := mock.set.Filter(func(o *types.Namespace) (b bool, e error) {
return o.Slug == slug, nil
})
if len(oo) > 0 {
return oo[0], nil
} else {
return nil, repository.ErrNamespaceNotFound
}
}
func (mock *moduleMock) FindByHandle(namespaceID uint64, handle string) (o *types.Module, err error) {
oo, err := mock.set.Filter(func(o *types.Module) (b bool, e error) {
return o.Handle == handle && o.NamespaceID == namespaceID, nil
})
if len(oo) > 0 {
return oo[0], nil
} else {
return nil, repository.ErrModuleNotFound
}
}
func (mock *chartMock) FindByHandle(namespaceID uint64, handle string) (o *types.Chart, err error) {
oo, err := mock.set.Filter(func(o *types.Chart) (b bool, e error) {
return o.Handle == handle && o.NamespaceID == namespaceID, nil
})
if len(oo) > 0 {
return oo[0], nil
} else {
return nil, repository.ErrChartNotFound
}
}
func (mock *pageMock) FindByHandle(namespaceID uint64, handle string) (o *types.Page, err error) {
oo, err := mock.set.Filter(func(o *types.Page) (b bool, e error) {
return o.Handle == handle && o.NamespaceID == namespaceID, nil
})
if len(oo) > 0 {
return oo[0], nil
} else {
return nil, repository.ErrPageNotFound
}
}
func impFixTester(t *testing.T, name string, tester interface{}) {
t.Run(name, func(t *testing.T) {
var aux interface{}
req := require.New(t)
f, err := os.Open(fmt.Sprintf("testdata/%s.yaml", name))
req.NoError(err)
req.NoError(yaml.NewDecoder(f).Decode(&aux))
req.NotNil(aux)
if reqError, ok := tester.(error); ok {
req.EqualError(imp.GetNamespaceImporter().Cast(ns.Slug, aux), reqError.Error())
return
} else {
req.NoError(imp.GetNamespaceImporter().Cast(ns.Slug, aux))
}
switch tester := tester.(type) {
case func(*testing.T, *Namespace):
tester(t, imp.GetNamespaceImporter())
case func(*testing.T, *Module):
tester(t, imp.GetModuleImporter(ns.Slug))
case func(*testing.T, *Chart):
tester(t, imp.GetChartImporter(ns.Slug))
case func(*testing.T, *Page):
tester(t, imp.GetPageImporter(ns.Slug))
case func(*testing.T, *Importer):
tester(t, imp)
default:
panic("unsupported tester function signature")
}
})
}
+1
View File
@@ -204,6 +204,7 @@ func (mImp *Module) castFields(module *types.Module, def interface{}) (err error
}
func (mImp *Module) castFieldOptions(field *types.ModuleField, def interface{}) (err error) {
field.Options = map[string]interface{}{}
return deinterfacer.Each(def, func(_ int, key string, val interface{}) (err error) {
field.Options[key] = deinterfacer.Simplify(val)
return
+31 -1
View File
@@ -2,9 +2,39 @@ package importer
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cortezaproject/corteza-server/compose/types"
)
func TestModuleImport_CastSet(t *testing.T) {
t.Skip()
impFixTester(t, "module_full", func(t *testing.T, module *Module) {
req := require.New(t)
req.Len(module.set, 1)
tc := module.set.FindByHandle("mod1")
req.Equal(tc.Name, "Module with fields")
req.Equal(tc.Fields, types.ModuleFieldSet{
{
Name: "f1",
Kind: "Number",
Label: "f1",
},
{
Name: "f2",
Kind: "String",
Label: "F2",
Place: 1,
Required: true,
Options: map[string]interface{}{
"multiLine": true,
"useRichTextEditor": true,
"multiDelimiter": "\n",
},
},
})
})
}
+24 -3
View File
@@ -165,9 +165,12 @@ func (pImp *Page) castBlocks(page *types.Page, def interface{}) error {
block.Kind = deinterfacer.ToString(val)
case "options":
if block.Options, err = pImp.castBlockOptions(val); err != nil {
return err
}
block.Options, err = pImp.castBlockOptions(val)
return err
case "style":
block.Style, err = pImp.castBlockStyle(page, b, val)
return
case "XYWH", "xywh", "dim", "dimension":
xywh := deinterfacer.ToInts(val)
@@ -203,6 +206,24 @@ func (pImp *Page) castBlockOptions(def interface{}) (opt map[string]interface{},
})
}
func (pImp *Page) castBlockStyle(page *types.Page, n int, def interface{}) (s types.PageBlockStyle, err error) {
s = types.PageBlockStyle{}
return s, deinterfacer.Each(def, func(_ int, key string, val interface{}) (err error) {
switch key {
case "variants":
s.Variants = map[string]string{}
return deinterfacer.Each(val, func(_ int, key string, val interface{}) (err error) {
s.Variants[key] = deinterfacer.ToString(val)
return
})
default:
return fmt.Errorf("unexpected key %q for block #%d on page %q", key, n+1, page.Handle)
}
})
}
func (pImp *Page) Exists(handle string) bool {
handle = importer.NormalizeHandle(handle)
+50 -1
View File
@@ -2,8 +2,57 @@ package importer
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cortezaproject/corteza-server/compose/types"
)
func TestPageImport_CastSet(t *testing.T) {
t.Skip()
impFixTester(t, "page_full", func(t *testing.T, page *Page) {
req := require.New(t)
req.Len(page.set, 4)
root := page.set.FindByHandle("root")
req.NotNil(root)
req.Equal(root.Title, "Root page")
sub1 := page.set.FindByHandle("sub1")
req.NotNil(sub1)
req.Equal(sub1.Title, "Sub page 1")
req.Equal(sub1.Blocks, types.PageBlocks{
{
Title: "B1",
Options: nil,
Style: types.PageBlockStyle{
Variants: map[string]string{"v1": "V1"},
},
Kind: "TheTestingKind",
XYWH: [4]int{1, 2, 3, 4},
},
{
Title: "B2",
Options: nil,
Style: types.PageBlockStyle{},
Kind: "TheTestingKind",
XYWH: [4]int{11, 12, 13, 14},
},
})
sub2 := page.set.FindByHandle("sub2")
req.NotNil(sub2)
req.Equal(sub2.Title, "Sub page 2")
sub21 := page.set.FindByHandle("sub21")
req.NotNil(sub21)
req.Equal(sub21.Title, "Sub-sub page 2.1")
req.Equal(page.tree, map[string][]string{
"": {"root"},
"root": {"sub1", "sub2"},
"sub2": {"sub21"},
})
})
}
+18 -4
View File
@@ -1,4 +1,18 @@
chart1:
name: chart 1
chart2:
name: chart 2
charts:
chart1:
name: chart 1
config:
reports:
- filter: a=b
module: foo
metrics:
- backgroundColor: '#e5a83b'
beginAtZero: true
field: count
fixTooltips: true
label: Number of leads
type: bar
dimensions:
- field: created_at
chart2:
name: chart 2
+5 -4
View File
@@ -1,4 +1,5 @@
- handle: chart1
name: chart 1
- handle: chart2
name: chart 2
charts:
- handle: chart1
name: chart 1
- handle: chart2
name: chart 2
@@ -0,0 +1,6 @@
charts:
chart1:
name: chart 1
config:
reports:
- module: un_kno_wn
+14
View File
@@ -0,0 +1,14 @@
modules:
mod1:
name: Module with fields
fields:
f1: Number
f2:
kind: String
label: F2
required: true
options:
multiLine: true
useRichTextEditor: true
multiDelimiter: |2+
+19
View File
@@ -0,0 +1,19 @@
pages:
root:
title: Root page
pages:
sub1:
title: Sub page 1
blocks:
- title: B1
xywh: [ 1, 2, 3, 4 ]
kind: TheTestingKind
style: { variants: { v1: "V1" } }
- title: B2
xywh: [ 11, 12, 13, 14 ]
kind: TheTestingKind
sub2:
title: Sub page 2
pages:
sub21:
title: Sub-sub page 2.1