Add importer tests
This commit is contained in:
@@ -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",
|
||||
},
|
||||
},
|
||||
},
|
||||
}})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user