mirror of
https://github.com/oxynote/oxynote.git
synced 2026-10-17 02:49:18 +02:00
add internal simulation flag and diff
This commit is contained in:
parent
32fb1c87ac
commit
cdc6cd2204
|
|
@ -1503,9 +1503,12 @@ describe("pmBlockToY", () => {
|
|||
},
|
||||
})
|
||||
|
||||
// the simulation flag is the one metric attribute whose schema
|
||||
// default is not null, so it is written out with the block
|
||||
expect(attrsOf(attached(el))).toEqual({
|
||||
uid: "metric",
|
||||
queries: [{ query: "up", legend: "uptime" }],
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -246,6 +246,28 @@ describe("editor schema", () => {
|
|||
)
|
||||
})
|
||||
|
||||
it("keeps a metric block's simulation flag", ({ expect }) => {
|
||||
const block = metricBlock("m1")
|
||||
|
||||
const result = roundTrip({
|
||||
...block,
|
||||
attrs: {
|
||||
...block.attrs,
|
||||
simulationActive: true,
|
||||
},
|
||||
})
|
||||
|
||||
expect(result.attrs?.simulationActive).toBe(true)
|
||||
})
|
||||
|
||||
it("reads a metric block without a simulation flag as not simulating", ({
|
||||
expect,
|
||||
}) => {
|
||||
const result = roundTrip(metricBlock("m1"))
|
||||
|
||||
expect(result.attrs?.simulationActive).toBe(false)
|
||||
})
|
||||
|
||||
it("keeps a mermaid block's source text", ({ expect }) => {
|
||||
const result = roundTrip({
|
||||
type: "mermaidBlock",
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export const MetricBlock = Node.create({
|
|||
axisBoundsMin: {},
|
||||
axisBoundsMax: {},
|
||||
simulationPreset: {},
|
||||
simulationActive: { default: false },
|
||||
width: {},
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ for free.
|
|||
handler; `decodeHookSettings` switches on type into the processor's own
|
||||
struct.
|
||||
- **A block write reports from the operation, never a re-read** (the
|
||||
realtime service persists on a debounce): `expandForWrite` once, ship the
|
||||
realtime service persists on a debounce): `sanitizeBlock` once, ship the
|
||||
canonical uids, return `blockRows` of the expanded tree.
|
||||
- **Branches are addressed by id, always.** Every content tool requires
|
||||
`branch_id`; listings carry the ids; `FetchDocumentByBranchID` refuses a
|
||||
|
|
@ -65,7 +65,8 @@ for free.
|
|||
`DescribeInput` is its read-only half.
|
||||
- **A write owns its invariants** on the `Input` method that performs it
|
||||
(`MoveDocument` refuses a missing parent or a move under its own subtree),
|
||||
not in `Execute`.
|
||||
not in `Execute`. Block writes go through `ApplyEdit`, so their per-type
|
||||
rules sit in `sanitizeBlock` and `sanitizeBlockAttrs` (`block.go`).
|
||||
- **`Traits()` says what a tool is**; the mixins
|
||||
`plainSummary`/`plainTraits`/`plainTitle` cover the defaults. `Write`
|
||||
gates behind confirmation and protects the result from context
|
||||
|
|
|
|||
|
|
@ -367,12 +367,14 @@ func compactFigma(b document.Block, uid string) Block {
|
|||
}
|
||||
}
|
||||
|
||||
// compactMetric preserves every non-uid attribute on the source
|
||||
// metric block — the configuration shape is opaque to the canonical
|
||||
// layer and the AI sees it through-pass.
|
||||
// compactMetric keeps every attribute of the source metric block except
|
||||
// its uid and its simulation flag. The configuration shape is opaque to
|
||||
// the canonical layer, so it passes through as is. The flag is internal
|
||||
// state that a reader never sees.
|
||||
func compactMetric(b document.Block, uid string) Block {
|
||||
attrs := b.Attrs.Copy()
|
||||
delete(attrs, document.AttrUID)
|
||||
delete(attrs, document.AttrSimulationActive)
|
||||
|
||||
return Block{
|
||||
Type: BlockMetric,
|
||||
|
|
|
|||
|
|
@ -394,12 +394,13 @@ func Test_Compact(t *testing.T) {
|
|||
Attrs: map[string]any{"query": "up", "unit": "%"},
|
||||
},
|
||||
},
|
||||
"Metric keeps an active simulation": {
|
||||
"Metric keeps its preset and hides its simulation flag": {
|
||||
Input: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: map[string]any{
|
||||
"uid": "m1",
|
||||
"simulationPreset": "http_latency",
|
||||
"simulationActive": true,
|
||||
},
|
||||
},
|
||||
Expected: Block{
|
||||
|
|
|
|||
|
|
@ -358,11 +358,18 @@ func expandFigma(b Block) document.Block {
|
|||
// expandMetric builds a metricBlock. All caller-supplied attrs are
|
||||
// passed through unchanged (the metric configuration shape is
|
||||
// opaque to the canonical layer); the uid is taken from Block.UID
|
||||
// or freshly generated.
|
||||
// or freshly generated. A simulation flag the caller sent is dropped.
|
||||
// A block with a preset simulates, and any other does not.
|
||||
func expandMetric(b Block) document.Block {
|
||||
attrs := b.Attrs.Copy()
|
||||
attrs[document.AttrUID] = resolveUID(b.UID)
|
||||
|
||||
delete(attrs, document.AttrSimulationActive)
|
||||
|
||||
if _, ok := attrs.Value(document.AttrSimulationPreset); ok {
|
||||
attrs[document.AttrSimulationActive] = true
|
||||
}
|
||||
|
||||
return document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: attrs,
|
||||
|
|
|
|||
|
|
@ -544,14 +544,46 @@ func Test_Expand(t *testing.T) {
|
|||
Attrs: map[string]any{"query": "up"},
|
||||
},
|
||||
},
|
||||
"Metric keeps an active simulation": {
|
||||
"Metric naming a preset simulates": {
|
||||
Input: Block{
|
||||
Type: BlockMetric,
|
||||
Attrs: map[string]any{"simulationPreset": "http_latency"},
|
||||
},
|
||||
Expected: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: map[string]any{
|
||||
"simulationPreset": "http_latency",
|
||||
"simulationActive": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"Metric naming a preset simulates whatever flag was sent": {
|
||||
Input: Block{
|
||||
Type: BlockMetric,
|
||||
Attrs: map[string]any{
|
||||
"simulationPreset": "http_latency",
|
||||
"simulationActive": false,
|
||||
},
|
||||
},
|
||||
Expected: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: map[string]any{
|
||||
"simulationPreset": "http_latency",
|
||||
"simulationActive": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"Metric naming no preset drops the flag it was sent": {
|
||||
Input: Block{
|
||||
Type: BlockMetric,
|
||||
Attrs: map[string]any{
|
||||
"simulationPreset": nil,
|
||||
"simulationActive": true,
|
||||
},
|
||||
},
|
||||
Expected: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: map[string]any{"simulationPreset": "http_latency"},
|
||||
Attrs: map[string]any{"simulationPreset": nil},
|
||||
},
|
||||
},
|
||||
// the other half of the legacy round trip: what Compact read
|
||||
|
|
|
|||
|
|
@ -96,6 +96,56 @@ func MetricEnums() map[string][]string {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeriveSimulation sets the simulation flag on an attribute update. A
|
||||
// flag the caller sent is dropped. A changed preset switches the
|
||||
// simulation on, and a null preset switches it off. Any other update
|
||||
// leaves the stored flag alone.
|
||||
func DeriveSimulation(update map[string]any, stored document.Attributes) {
|
||||
delete(update, document.AttrSimulationActive)
|
||||
|
||||
preset, named := update[document.AttrSimulationPreset]
|
||||
if !named || preset == stored[document.AttrSimulationPreset] {
|
||||
return
|
||||
}
|
||||
|
||||
update[document.AttrSimulationActive] = preset != nil
|
||||
}
|
||||
|
||||
// KeepSimulation copies the stored simulation flag onto each metric in
|
||||
// next that stored holds with the same uid and preset. A metric re-sent
|
||||
// after its data arrived then does not start simulating again. It
|
||||
// writes to next's attribute maps.
|
||||
func KeepSimulation(next, stored document.Block) {
|
||||
if next.Type != document.BlockNodeMetricBlock {
|
||||
for _, child := range next.Content {
|
||||
KeepSimulation(child, stored)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
uid, ok := next.UID()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
old, found := stored.FindByUID(uid)
|
||||
if !found || old.Type != document.BlockNodeMetricBlock {
|
||||
return
|
||||
}
|
||||
|
||||
preset, ok := next.Attrs.Value(document.AttrSimulationPreset)
|
||||
if !ok || preset != old.Attrs[document.AttrSimulationPreset] {
|
||||
return
|
||||
}
|
||||
|
||||
delete(next.Attrs, document.AttrSimulationActive)
|
||||
|
||||
if active, set := old.Attrs.Value(document.AttrSimulationActive); set {
|
||||
next.Attrs[document.AttrSimulationActive] = active
|
||||
}
|
||||
}
|
||||
|
||||
// validateMetric checks a metric block: no content, and every known
|
||||
// attribute it does carry is well-formed. Only present, non-null values
|
||||
// are checked — the editor stores null for "unset" and an older block
|
||||
|
|
|
|||
|
|
@ -28,6 +28,156 @@ func Test_MetricEnums(t *testing.T) {
|
|||
assert.Equal(t, "line_chart", MetricEnums()[document.AttrVisualizationType][0])
|
||||
}
|
||||
|
||||
func Test_DeriveSimulation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cc := map[string]struct {
|
||||
Update map[string]any
|
||||
Stored document.Attributes
|
||||
Expected map[string]any
|
||||
}{
|
||||
"An update naming no preset leaves the flag alone": {
|
||||
Update: map[string]any{"title": "Requests"},
|
||||
Stored: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false},
|
||||
Expected: map[string]any{"title": "Requests"},
|
||||
},
|
||||
"A flag the caller sent is dropped": {
|
||||
Update: map[string]any{"title": "Requests", "simulationActive": true},
|
||||
Stored: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false},
|
||||
Expected: map[string]any{"title": "Requests"},
|
||||
},
|
||||
"The stored preset sent again leaves the flag alone": {
|
||||
Update: map[string]any{"simulationPreset": "cpu_usage"},
|
||||
Stored: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false},
|
||||
Expected: map[string]any{"simulationPreset": "cpu_usage"},
|
||||
},
|
||||
"A first preset switches the simulation on": {
|
||||
Update: map[string]any{"simulationPreset": "cpu_usage"},
|
||||
Stored: document.Attributes{"simulationPreset": nil},
|
||||
Expected: map[string]any{"simulationPreset": "cpu_usage", "simulationActive": true},
|
||||
},
|
||||
"Another preset switches the simulation on": {
|
||||
Update: map[string]any{"simulationPreset": "error_rate"},
|
||||
Stored: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false},
|
||||
Expected: map[string]any{"simulationPreset": "error_rate", "simulationActive": true},
|
||||
},
|
||||
"A null preset switches the simulation off": {
|
||||
Update: map[string]any{"simulationPreset": nil},
|
||||
Stored: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true},
|
||||
Expected: map[string]any{"simulationPreset": nil, "simulationActive": false},
|
||||
},
|
||||
"A null preset on a block that names none changes nothing": {
|
||||
Update: map[string]any{"simulationPreset": nil},
|
||||
Stored: document.Attributes{},
|
||||
Expected: map[string]any{"simulationPreset": nil},
|
||||
},
|
||||
}
|
||||
|
||||
for cn, c := range cc {
|
||||
t.Run(cn, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
DeriveSimulation(c.Update, c.Stored)
|
||||
|
||||
assert.Equal(t, c.Expected, c.Update)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_KeepSimulation(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
metric := func(uid string, attrs document.Attributes) document.Block {
|
||||
attrs[document.AttrUID] = uid
|
||||
|
||||
return document.Block{Type: document.BlockNodeMetricBlock, Attrs: attrs}
|
||||
}
|
||||
|
||||
grid := func(items ...document.Block) document.Block {
|
||||
return document.Block{Type: document.BlockNodeMetricGrid, Content: items}
|
||||
}
|
||||
|
||||
cc := map[string]struct {
|
||||
Next document.Block
|
||||
Stored document.Block
|
||||
Expected document.Block
|
||||
}{
|
||||
"The same preset keeps a simulation that was switched off": {
|
||||
Next: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
Expected: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
},
|
||||
"The same preset keeps a simulation that is running": {
|
||||
Next: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Expected: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
},
|
||||
"The same preset stored without a flag drops the derived one": {
|
||||
Next: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage"}),
|
||||
Expected: metric("m1", document.Attributes{"simulationPreset": "cpu_usage"}),
|
||||
},
|
||||
"Another preset keeps what was derived": {
|
||||
Next: metric("m1", document.Attributes{"simulationPreset": "error_rate", "simulationActive": true}),
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
Expected: metric("m1", document.Attributes{"simulationPreset": "error_rate", "simulationActive": true}),
|
||||
},
|
||||
"A block naming no preset is left alone": {
|
||||
Next: metric("m1", document.Attributes{"simulationPreset": nil}),
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Expected: metric("m1", document.Attributes{"simulationPreset": nil}),
|
||||
},
|
||||
"A block the stored tree does not hold is left alone": {
|
||||
Next: metric("m2", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
Expected: metric("m2", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
},
|
||||
"A block without a uid is left alone": {
|
||||
Next: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true},
|
||||
},
|
||||
Stored: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
Expected: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true},
|
||||
},
|
||||
},
|
||||
"A uid the stored tree gives to another kind of block is left alone": {
|
||||
Next: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
Stored: document.Block{
|
||||
Type: document.BlockNodeParagraph,
|
||||
Attrs: document.Attributes{document.AttrUID: "m1"},
|
||||
},
|
||||
Expected: metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
},
|
||||
"A grid carries the flag of each metric it holds": {
|
||||
Next: grid(
|
||||
metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": true}),
|
||||
metric("m2", document.Attributes{"simulationPreset": "error_rate", "simulationActive": true}),
|
||||
),
|
||||
Stored: grid(
|
||||
metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
metric("m2", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
),
|
||||
Expected: grid(
|
||||
metric("m1", document.Attributes{"simulationPreset": "cpu_usage", "simulationActive": false}),
|
||||
metric("m2", document.Attributes{"simulationPreset": "error_rate", "simulationActive": true}),
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
for cn, c := range cc {
|
||||
t.Run(cn, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
KeepSimulation(c.Next, c.Stored)
|
||||
|
||||
assert.Equal(t, c.Expected, c.Next)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_validateMetric(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ var _ BlobStore = &BlobStoreMock{}
|
|||
// SetFunc: func(ctx context.Context, key string, value []byte) error {
|
||||
// panic("mock out the Set method")
|
||||
// },
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// panic("mock out the Start method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ var _ HistoryStore = &HistoryStoreMock{}
|
|||
// SetFunc: func(ctx context.Context, key string, value []*schema.Message) error {
|
||||
// panic("mock out the Set method")
|
||||
// },
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// panic("mock out the Start method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ var _ PendingStore = &PendingStoreMock{}
|
|||
// SetFunc: func(ctx context.Context, key string, value PendingConfirm) error {
|
||||
// panic("mock out the Set method")
|
||||
// },
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// panic("mock out the Start method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ var _ persist.BlobStore = &BlobStore{}
|
|||
// SetFunc: func(ctx context.Context, key string, value []byte) error {
|
||||
// panic("mock out the Set method")
|
||||
// },
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// panic("mock out the Start method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ var _ persist.HistoryStore = &HistoryStore{}
|
|||
// SetFunc: func(ctx context.Context, key string, value []*schema.Message) error {
|
||||
// panic("mock out the Set method")
|
||||
// },
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// panic("mock out the Start method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ var _ persist.PendingStore = &PendingStore{}
|
|||
// SetFunc: func(ctx context.Context, key string, value persist.PendingConfirm) error {
|
||||
// panic("mock out the Set method")
|
||||
// },
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// StartFunc: func(ctx context.Context) {
|
||||
// panic("mock out the Start method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -17,7 +17,7 @@ var _ SearchTrigger = &SearchTriggerMock{}
|
|||
//
|
||||
// // make and configure a mocked SearchTrigger
|
||||
// mockedSearchTrigger := &SearchTriggerMock{
|
||||
// TriggerFunc: func() {
|
||||
// TriggerFunc: func() {
|
||||
// panic("mock out the Trigger method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ var _ Tx = &TxMock{}
|
|||
// CommitFunc: func() error {
|
||||
// panic("mock out the Commit method")
|
||||
// },
|
||||
// DeleteDocumentFunc: func(ctx context.Context, id xid.ID, organizationID string) ([]xid.ID, error) {
|
||||
// panic("mock out the DeleteDocument method")
|
||||
// },
|
||||
// InsertDocumentFunc: func(ctx context.Context, doc document.Document) error {
|
||||
// panic("mock out the InsertDocument method")
|
||||
// },
|
||||
|
|
@ -143,6 +146,50 @@ func (mock *TxMock) CommitCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// DeleteDocument calls DeleteDocumentFunc.
|
||||
func (mock *TxMock) DeleteDocument(ctx context.Context, id xid.ID, organizationID string) ([]xid.ID, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
ID: id,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
mock.lockDeleteDocument.Lock()
|
||||
mock.calls.DeleteDocument = append(mock.calls.DeleteDocument, callInfo)
|
||||
mock.lockDeleteDocument.Unlock()
|
||||
if mock.DeleteDocumentFunc == nil {
|
||||
var (
|
||||
iDsOut []xid.ID
|
||||
errOut error
|
||||
)
|
||||
return iDsOut, errOut
|
||||
}
|
||||
return mock.DeleteDocumentFunc(ctx, id, organizationID)
|
||||
}
|
||||
|
||||
// DeleteDocumentCalls gets all the calls that were made to DeleteDocument.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedTx.DeleteDocumentCalls())
|
||||
func (mock *TxMock) DeleteDocumentCalls() []struct {
|
||||
Ctx context.Context
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
}
|
||||
mock.lockDeleteDocument.RLock()
|
||||
calls = mock.calls.DeleteDocument
|
||||
mock.lockDeleteDocument.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// InsertDocument calls InsertDocumentFunc.
|
||||
func (mock *TxMock) InsertDocument(ctx context.Context, doc document.Document) error {
|
||||
callInfo := struct {
|
||||
|
|
@ -297,47 +344,3 @@ func (mock *TxMock) UpsertDocumentMaintainersCalls() []struct {
|
|||
mock.lockUpsertDocumentMaintainers.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// DeleteDocument calls DeleteDocumentFunc.
|
||||
func (mock *TxMock) DeleteDocument(ctx context.Context, id xid.ID, organizationID string) ([]xid.ID, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
ID: id,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
mock.lockDeleteDocument.Lock()
|
||||
mock.calls.DeleteDocument = append(mock.calls.DeleteDocument, callInfo)
|
||||
mock.lockDeleteDocument.Unlock()
|
||||
if mock.DeleteDocumentFunc == nil {
|
||||
var (
|
||||
iDsOut []xid.ID
|
||||
errOut error
|
||||
)
|
||||
return iDsOut, errOut
|
||||
}
|
||||
return mock.DeleteDocumentFunc(ctx, id, organizationID)
|
||||
}
|
||||
|
||||
// DeleteDocumentCalls gets all the calls that were made to DeleteDocument.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedTx.DeleteDocumentCalls())
|
||||
func (mock *TxMock) DeleteDocumentCalls() []struct {
|
||||
Ctx context.Context
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
}
|
||||
mock.lockDeleteDocument.RLock()
|
||||
calls = mock.calls.DeleteDocument
|
||||
mock.lockDeleteDocument.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -5,9 +5,10 @@ package mock
|
|||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/oxynote/oxynote/server/core/internal/assistant/tools"
|
||||
"github.com/oxynote/oxynote/server/core/internal/search"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that Searcher does implement tools.Searcher.
|
||||
|
|
@ -18,14 +19,14 @@ var _ tools.Searcher = &Searcher{}
|
|||
//
|
||||
// func TestSomethingThatUsesSearcher(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked Searcher
|
||||
// // make and configure a mocked tools.Searcher
|
||||
// mockedSearcher := &Searcher{
|
||||
// SearchDocumentBlocksFunc: func(ctx context.Context, organizationID string, query string, limit int) ([]search.Block, error) {
|
||||
// panic("mock out the SearchDocumentBlocks method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedSearcher in code that requires Searcher
|
||||
// // use mockedSearcher in code that requires tools.Searcher
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
|
|
@ -68,10 +69,10 @@ func (mock *Searcher) SearchDocumentBlocks(ctx context.Context, organizationID s
|
|||
mock.lockSearchDocumentBlocks.Unlock()
|
||||
if mock.SearchDocumentBlocksFunc == nil {
|
||||
var (
|
||||
out0 []search.Block
|
||||
errOut error
|
||||
blocksOut []search.Block
|
||||
errOut error
|
||||
)
|
||||
return out0, errOut
|
||||
return blocksOut, errOut
|
||||
}
|
||||
return mock.SearchDocumentBlocksFunc(ctx, organizationID, query, limit)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -313,15 +313,11 @@ func (insertBlock) Execute(inp Input) (string, error) {
|
|||
return "", fmt.Errorf("insert_block: %w", err)
|
||||
}
|
||||
|
||||
if err := inp.CheckDataSources(in.Block.CollectAttributeValues(document.AttrDataSourceID)); err != nil {
|
||||
return "", fmt.Errorf("insert_block: %w", err)
|
||||
}
|
||||
|
||||
// uids are resolved at expansion, so expanding here rather than at
|
||||
// wire time is what lets the tool report what it wrote without
|
||||
// reading the document back, which the debounced persist would not
|
||||
// reliably show yet.
|
||||
expanded, err := block.Expand(in.Block)
|
||||
expanded, err := sanitizeBlock(inp, in.Block, document.Block{})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("insert_block: %w", err)
|
||||
}
|
||||
|
|
@ -462,11 +458,20 @@ func (replaceBlock) Execute(inp Input) (string, error) {
|
|||
return "", fmt.Errorf("replace_block: %w", err)
|
||||
}
|
||||
|
||||
if err := inp.CheckDataSources(in.Block.CollectAttributeValues(document.AttrDataSourceID)); err != nil {
|
||||
content, err := inp.FetchDocumentContent(in.DocumentID, in.BranchID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("replace_block: %w", err)
|
||||
}
|
||||
|
||||
expanded, err := block.Expand(in.Block)
|
||||
// an unknown uid leaves stored empty, so no flag is kept. ApplyEdit
|
||||
// reports the unknown uid.
|
||||
var stored document.Block
|
||||
|
||||
if b, ok := content.Content.FindByUID(in.BlockUID); ok {
|
||||
stored = b
|
||||
}
|
||||
|
||||
expanded, err := sanitizeBlock(inp, in.Block, stored)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("replace_block: %w", err)
|
||||
}
|
||||
|
|
@ -715,15 +720,6 @@ func (updateBlockAttrs) Execute(inp Input) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
// the payload names attributes, not a block type, so a metric's
|
||||
// data source arrives here on its own rather than inside a block
|
||||
// the walk could find it in.
|
||||
if id, ok := in.Attrs[document.AttrDataSourceID].(string); ok && id != "" {
|
||||
if err := inp.CheckDataSources([]string{id}); err != nil {
|
||||
return "", fmt.Errorf("update_block_attrs: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := inp.ValidateAttrUpdate(in.DocumentID, in.BranchID, in.BlockUID, in.Attrs); err != nil {
|
||||
return "", fmt.Errorf("update_block_attrs: %w", err)
|
||||
}
|
||||
|
|
@ -733,6 +729,10 @@ func (updateBlockAttrs) Execute(inp Input) (string, error) {
|
|||
return "", fmt.Errorf("update_block_attrs: %w", err)
|
||||
}
|
||||
|
||||
if err := sanitizeBlockAttrs(inp, in.Attrs, b); err != nil {
|
||||
return "", fmt.Errorf("update_block_attrs: %w", err)
|
||||
}
|
||||
|
||||
if err := inp.ApplyEdit(in.DocumentID, in.BranchID, []edit.Operation{edit.UpdateAttrs(in.BlockUID, in.Attrs)}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -998,3 +998,41 @@ func (moveBlock) Execute(inp Input) (string, error) {
|
|||
|
||||
return result(blockWriteResult{Blocks: blockRows(b)})
|
||||
}
|
||||
|
||||
// sanitizeBlock checks a block before a write and expands it. stored is
|
||||
// the block being replaced, or empty for an insert. A metric that stored
|
||||
// already holds keeps its simulation flag.
|
||||
func sanitizeBlock(inp Input, b block.Block, stored document.Block) (document.Block, error) {
|
||||
if err := inp.CheckDataSources(b.CollectAttributeValues(document.AttrDataSourceID)); err != nil {
|
||||
return document.Block{}, err
|
||||
}
|
||||
|
||||
expanded, err := block.Expand(b)
|
||||
if err != nil {
|
||||
return document.Block{}, err
|
||||
}
|
||||
|
||||
block.KeepSimulation(expanded, stored)
|
||||
|
||||
return expanded, nil
|
||||
}
|
||||
|
||||
// sanitizeBlockAttrs checks an attribute update by the type of the
|
||||
// stored block. For a metric it checks the data source and sets the
|
||||
// simulation flag. It writes to attrs.
|
||||
func sanitizeBlockAttrs(inp Input, attrs map[string]any, stored document.Block) error {
|
||||
if stored.Type != document.BlockNodeMetricBlock {
|
||||
return nil
|
||||
}
|
||||
|
||||
// an empty data source means unset, so there is nothing to check.
|
||||
if id, ok := attrs[document.AttrDataSourceID].(string); ok && id != "" {
|
||||
if err := inp.CheckDataSources([]string{id}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
block.DeriveSimulation(attrs, stored.Attrs)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tools
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/oxynote/oxynote/server/core/internal/assistant/block"
|
||||
|
|
@ -26,10 +27,13 @@ const _stubContentUID = "a"
|
|||
// for the cases that need a block with attributes of its own.
|
||||
const _stubHeadingUID = "h"
|
||||
|
||||
// _stubMetricUID is the uid of the metric stubSimulationDB answers with.
|
||||
const _stubMetricUID = "m"
|
||||
|
||||
// stubContentDB answers content reads with a single paragraph the
|
||||
// placement checks can find.
|
||||
func stubContentDB(err error) *DBMock {
|
||||
root := document.RootBlock{
|
||||
return stubRootDB(document.RootBlock{
|
||||
Content: []document.Block{
|
||||
{
|
||||
Type: document.BlockNodeParagraph,
|
||||
|
|
@ -42,8 +46,35 @@ func stubContentDB(err error) *DBMock {
|
|||
Attrs: document.Attributes{document.AttrUID: _stubHeadingUID, document.AttrLevel: 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
}, err)
|
||||
}
|
||||
|
||||
// stubSimulationDB answers content reads with one metric whose data has
|
||||
// arrived: it still names its preset and its simulation is switched off.
|
||||
func stubSimulationDB() *DBMock {
|
||||
return stubRootDB(document.RootBlock{
|
||||
Content: []document.Block{
|
||||
{
|
||||
Type: document.BlockNodeMetricGrid,
|
||||
Attrs: document.Attributes{document.AttrUID: "g"},
|
||||
Content: []document.Block{
|
||||
{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: document.Attributes{
|
||||
document.AttrUID: _stubMetricUID,
|
||||
document.AttrSimulationPreset: "cpu_usage",
|
||||
document.AttrSimulationActive: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
}
|
||||
|
||||
// stubRootDB answers content reads with the given tree. err makes the
|
||||
// branch fetch fail.
|
||||
func stubRootDB(root document.RootBlock, err error) *DBMock {
|
||||
db := stubDocumentDB()
|
||||
fetch := db.FetchDocumentFunc
|
||||
fetchByBranch := db.FetchDocumentByBranchIDFunc
|
||||
|
|
@ -98,7 +129,11 @@ func metricBlockArgs(dataSourceID string) string {
|
|||
// stubMetricDB answers content reads and resolves exactly one data
|
||||
// source, so only the id under test decides a metric write's outcome.
|
||||
func stubMetricDB() *DBMock {
|
||||
db := stubContentDB(nil)
|
||||
return stubDataSource(stubContentDB(nil))
|
||||
}
|
||||
|
||||
// stubDataSource makes db resolve exactly one data source.
|
||||
func stubDataSource(db *DBMock) *DBMock {
|
||||
db.FetchDataSourceFunc = func(_ context.Context, id xid.ID, orgID string) (*datasource.DataSource, error) {
|
||||
if id != _testDataSourceID || orgID != "org" {
|
||||
return nil, errutil.ErrNotFound
|
||||
|
|
@ -120,7 +155,12 @@ type editCase struct {
|
|||
Runner *datasourceMock.Runner
|
||||
Args string
|
||||
Contains []string
|
||||
Err error
|
||||
|
||||
// Op is the single operation the write should send, as the realtime
|
||||
// service receives it. Empty skips the check.
|
||||
Op string
|
||||
|
||||
Err error
|
||||
}
|
||||
|
||||
// runEdit executes a block tool and asserts the shared outcome.
|
||||
|
|
@ -153,6 +193,21 @@ func runEdit(t *testing.T, tl Tool, name Name, c editCase) {
|
|||
for _, want := range c.Contains {
|
||||
assert.Contains(t, res, want)
|
||||
}
|
||||
|
||||
if c.Op == "" {
|
||||
return
|
||||
}
|
||||
|
||||
require.Len(t, applier.ApplyCalls(), 1)
|
||||
require.Len(t, applier.ApplyCalls()[0].Ops, 1)
|
||||
|
||||
op, err := applier.ApplyCalls()[0].Ops[0]()
|
||||
require.NoError(t, err)
|
||||
|
||||
raw, err := json.Marshal(op)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.JSONEq(t, c.Op, string(raw))
|
||||
}
|
||||
|
||||
func Test_readBlockArgs_Validate(t *testing.T) {
|
||||
|
|
@ -540,6 +595,22 @@ func Test_replaceBlock_Execute(t *testing.T) {
|
|||
`","block":` + metricBlockArgs(_unknownDataSourceID) + `}`,
|
||||
Err: assert.AnError,
|
||||
},
|
||||
// read_block shows a metric with its preset even after its data
|
||||
// arrived. Re-sending it must not start the simulation again.
|
||||
"A metric re-sent with its preset keeps its simulation switched off": {
|
||||
DB: stubSimulationDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID + `","block":` +
|
||||
`{"type":"metric","uid":"` + _stubMetricUID + `","attrs":{"title":"CPU","simulationPreset":"cpu_usage"}}}`,
|
||||
Op: `{"kind":"replace","block_uid":"m","block":{"type":"metricBlock","attrs":` +
|
||||
`{"uid":"m","title":"CPU","simulationPreset":"cpu_usage","simulationActive":false}}}`,
|
||||
},
|
||||
"A metric re-sent with another preset simulates": {
|
||||
DB: stubSimulationDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID + `","block":` +
|
||||
`{"type":"metric","uid":"` + _stubMetricUID + `","attrs":{"simulationPreset":"error_rate"}}}`,
|
||||
Op: `{"kind":"replace","block_uid":"m","block":{"type":"metricBlock","attrs":` +
|
||||
`{"uid":"m","simulationPreset":"error_rate","simulationActive":true}}}`,
|
||||
},
|
||||
}
|
||||
|
||||
for cn, c := range cc {
|
||||
|
|
@ -757,21 +828,46 @@ func Test_updateBlockAttrs_Execute(t *testing.T) {
|
|||
// the payload names attributes, not a block type, so a metric's
|
||||
// data source arrives on its own rather than inside a block.
|
||||
"A data source the organisation owns": {
|
||||
DB: stubMetricDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"a","attrs":{"dataSourceId":"` +
|
||||
DB: stubDataSource(stubSimulationDB()),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID + `","attrs":{"dataSourceId":"` +
|
||||
_testDataSourceID.String() + `"}}`,
|
||||
},
|
||||
"A data source it does not": {
|
||||
DB: stubMetricDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"a","attrs":{"dataSourceId":"` +
|
||||
DB: stubDataSource(stubSimulationDB()),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID + `","attrs":{"dataSourceId":"` +
|
||||
_unknownDataSourceID + `"}}`,
|
||||
Err: assert.AnError,
|
||||
},
|
||||
// an empty data source is the editor's "unset", not a reference
|
||||
// to check, and no other attribute names one at all.
|
||||
"An empty data source is not looked up": {
|
||||
DB: stubMetricDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"a","attrs":{"dataSourceId":""}}`,
|
||||
DB: stubDataSource(stubSimulationDB()),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID + `","attrs":{"dataSourceId":""}}`,
|
||||
},
|
||||
"A simulation flag the caller sent is dropped": {
|
||||
DB: stubSimulationDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID +
|
||||
`","attrs":{"title":"CPU","simulationActive":true}}`,
|
||||
Op: `{"kind":"update_attrs","block_uid":"m","attrs":{"title":"CPU"}}`,
|
||||
},
|
||||
"Another preset switches the simulation on": {
|
||||
DB: stubSimulationDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID +
|
||||
`","attrs":{"simulationPreset":"error_rate"}}`,
|
||||
Op: `{"kind":"update_attrs","block_uid":"m","attrs":{"simulationPreset":"error_rate","simulationActive":true}}`,
|
||||
},
|
||||
"A null preset switches the simulation off": {
|
||||
DB: stubSimulationDB(),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"` + _stubMetricUID +
|
||||
`","attrs":{"simulationPreset":null}}`,
|
||||
Op: `{"kind":"update_attrs","block_uid":"m","attrs":{"simulationPreset":null,"simulationActive":false}}`,
|
||||
},
|
||||
// only metric blocks have the flag, so any other block is sent
|
||||
// unchanged.
|
||||
"A block that is not a metric is sent as given": {
|
||||
DB: stubContentDB(nil),
|
||||
Args: `{` + targetArgs(_stubMainBranchID) + `,"block_uid":"h","attrs":{"level":2}}`,
|
||||
Op: `{"kind":"update_attrs","block_uid":"h","attrs":{"level":2}}`,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -1000,6 +1096,144 @@ func Test_moveBlock_Execute(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func Test_sanitizeBlock(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
metric := func(attrs document.Attributes) block.Block {
|
||||
return block.Block{Type: block.BlockMetric, UID: _stubMetricUID, Attrs: attrs}
|
||||
}
|
||||
|
||||
cc := map[string]struct {
|
||||
Block block.Block
|
||||
Stored document.Block
|
||||
Result document.Attributes
|
||||
Err error
|
||||
}{
|
||||
"Error returned by inp.CheckDataSources": {
|
||||
Block: metric(document.Attributes{document.AttrDataSourceID: _unknownDataSourceID}),
|
||||
Err: assert.AnError,
|
||||
},
|
||||
"Error returned by block.Expand": {
|
||||
Block: block.Block{Type: "nope"},
|
||||
Err: assert.AnError,
|
||||
},
|
||||
"A new metric naming a preset simulates": {
|
||||
Block: metric(document.Attributes{document.AttrSimulationPreset: "cpu_usage"}),
|
||||
Result: document.Attributes{
|
||||
document.AttrUID: _stubMetricUID,
|
||||
document.AttrSimulationPreset: "cpu_usage",
|
||||
document.AttrSimulationActive: true,
|
||||
},
|
||||
},
|
||||
"A stored metric keeps its simulation flag": {
|
||||
Block: metric(document.Attributes{document.AttrSimulationPreset: "cpu_usage"}),
|
||||
Stored: document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: document.Attributes{
|
||||
document.AttrUID: _stubMetricUID,
|
||||
document.AttrSimulationPreset: "cpu_usage",
|
||||
document.AttrSimulationActive: false,
|
||||
},
|
||||
},
|
||||
Result: document.Attributes{
|
||||
document.AttrUID: _stubMetricUID,
|
||||
document.AttrSimulationPreset: "cpu_usage",
|
||||
document.AttrSimulationActive: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for cn, c := range cc {
|
||||
t.Run(cn, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
inp := testInput(testDeps(stubMetricDB(), nil, nil), NameReplaceBlock, `{}`)
|
||||
|
||||
res, err := sanitizeBlock(inp, c.Block, c.Stored)
|
||||
testutil.AssertEqualError(t, c.Err, err)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, document.BlockNodeMetricBlock, res.Type)
|
||||
assert.Equal(t, c.Result, res.Attrs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_sanitizeBlockAttrs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
stored := document.Block{
|
||||
Type: document.BlockNodeMetricBlock,
|
||||
Attrs: document.Attributes{
|
||||
document.AttrUID: _stubMetricUID,
|
||||
document.AttrSimulationPreset: "cpu_usage",
|
||||
document.AttrSimulationActive: false,
|
||||
},
|
||||
}
|
||||
|
||||
cc := map[string]struct {
|
||||
Attrs map[string]any
|
||||
Stored document.Block
|
||||
Result map[string]any
|
||||
Err error
|
||||
}{
|
||||
"Error returned by inp.CheckDataSources": {
|
||||
Attrs: map[string]any{document.AttrDataSourceID: _unknownDataSourceID},
|
||||
Stored: stored,
|
||||
Err: assert.AnError,
|
||||
},
|
||||
"A block that is not a metric is left as given": {
|
||||
Attrs: map[string]any{
|
||||
document.AttrDataSourceID: _unknownDataSourceID,
|
||||
document.AttrSimulationActive: true,
|
||||
},
|
||||
Stored: document.Block{Type: document.BlockNodeParagraph},
|
||||
Result: map[string]any{
|
||||
document.AttrDataSourceID: _unknownDataSourceID,
|
||||
document.AttrSimulationActive: true,
|
||||
},
|
||||
},
|
||||
"An empty data source is not looked up": {
|
||||
Attrs: map[string]any{document.AttrDataSourceID: ""},
|
||||
Stored: stored,
|
||||
Result: map[string]any{document.AttrDataSourceID: ""},
|
||||
},
|
||||
"A metric has its simulation flag derived": {
|
||||
Attrs: map[string]any{
|
||||
document.AttrDataSourceID: _testDataSourceID.String(),
|
||||
document.AttrSimulationPreset: "error_rate",
|
||||
document.AttrSimulationActive: false,
|
||||
},
|
||||
Stored: stored,
|
||||
Result: map[string]any{
|
||||
document.AttrDataSourceID: _testDataSourceID.String(),
|
||||
document.AttrSimulationPreset: "error_rate",
|
||||
document.AttrSimulationActive: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for cn, c := range cc {
|
||||
t.Run(cn, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
inp := testInput(testDeps(stubMetricDB(), nil, nil), NameUpdateBlockAttrs, `{}`)
|
||||
|
||||
err := sanitizeBlockAttrs(inp, c.Attrs, c.Stored)
|
||||
testutil.AssertEqualError(t, c.Err, err)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
assert.Equal(t, c.Result, c.Attrs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_docTarget_validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ type StatusStoreMock struct {
|
|||
UpdateDataSourceStatus []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Id is the id argument value.
|
||||
Id xid.ID
|
||||
// ID is the id argument value.
|
||||
ID xid.ID
|
||||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
// Status is the status argument value.
|
||||
|
|
@ -55,12 +55,12 @@ type StatusStoreMock struct {
|
|||
func (mock *StatusStoreMock) UpdateDataSourceStatus(ctx context.Context, id xid.ID, organizationID string, status processor.ConnectionStatus) error {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Id xid.ID
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
Status processor.ConnectionStatus
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Id: id,
|
||||
ID: id,
|
||||
OrganizationID: organizationID,
|
||||
Status: status,
|
||||
}
|
||||
|
|
@ -82,13 +82,13 @@ func (mock *StatusStoreMock) UpdateDataSourceStatus(ctx context.Context, id xid.
|
|||
// len(mockedStatusStore.UpdateDataSourceStatusCalls())
|
||||
func (mock *StatusStoreMock) UpdateDataSourceStatusCalls() []struct {
|
||||
Ctx context.Context
|
||||
Id xid.ID
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
Status processor.ConnectionStatus
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Id xid.ID
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
Status processor.ConnectionStatus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,62 +17,48 @@ var _ datasource.MySQL = &MySQL{}
|
|||
|
||||
// MySQL is a mock implementation of datasource.MySQL.
|
||||
//
|
||||
// func TestSomethingThatUsesdatasource.MySQL(t *testing.T) {
|
||||
// func TestSomethingThatUsesMySQL(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked datasource.MySQL
|
||||
// mockeddatasource.MySQL := &MySQL{
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// mockedMySQL := &MySQL{
|
||||
// MetadataFunc: func(ctx context.Context) (*processor.SQLMetadataResult, error) {
|
||||
// panic("mock out the Metadata method")
|
||||
// },
|
||||
// QueryLabelsFunc: func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
// panic("mock out the QueryLabels method")
|
||||
// },
|
||||
// QueryFunc: func(ctx context.Context, q string, tr processor.TimeRange) (*processor.MySQLQueryResult, error) {
|
||||
// panic("mock out the Query method")
|
||||
// },
|
||||
// QueryLabelsFunc: func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
// panic("mock out the QueryLabels method")
|
||||
// },
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockeddatasource.MySQL in code that requires datasource.MySQL
|
||||
// // use mockedMySQL in code that requires datasource.MySQL
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type MySQL struct {
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// MetadataFunc mocks the Metadata method.
|
||||
MetadataFunc func(ctx context.Context) (*processor.SQLMetadataResult, error)
|
||||
|
||||
// QueryLabelsFunc mocks the QueryLabels method.
|
||||
QueryLabelsFunc func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error)
|
||||
|
||||
// QueryFunc mocks the Query method.
|
||||
QueryFunc func(ctx context.Context, q string, tr processor.TimeRange) (*processor.MySQLQueryResult, error)
|
||||
|
||||
// QueryLabelsFunc mocks the QueryLabels method.
|
||||
QueryLabelsFunc func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error)
|
||||
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// Metadata holds details about calls to the Metadata method.
|
||||
Metadata []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// QueryLabels holds details about calls to the QueryLabels method.
|
||||
QueryLabels []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Q is the q argument value.
|
||||
Q string
|
||||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// Query holds details about calls to the Query method.
|
||||
Query []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -82,47 +68,25 @@ type MySQL struct {
|
|||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// QueryLabels holds details about calls to the QueryLabels method.
|
||||
QueryLabels []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Q is the q argument value.
|
||||
Q string
|
||||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
}
|
||||
lockTestConnection sync.RWMutex
|
||||
lockMetadata sync.RWMutex
|
||||
lockQueryLabels sync.RWMutex
|
||||
lockQuery sync.RWMutex
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *MySQL) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.MySQL.TestConnectionCalls())
|
||||
func (mock *MySQL) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
lockQueryLabels sync.RWMutex
|
||||
lockTestConnection sync.RWMutex
|
||||
}
|
||||
|
||||
// Metadata calls MetadataFunc.
|
||||
|
|
@ -148,7 +112,7 @@ func (mock *MySQL) Metadata(ctx context.Context) (*processor.SQLMetadataResult,
|
|||
// MetadataCalls gets all the calls that were made to Metadata.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.MySQL.MetadataCalls())
|
||||
// len(mockedMySQL.MetadataCalls())
|
||||
func (mock *MySQL) MetadataCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
|
|
@ -161,50 +125,6 @@ func (mock *MySQL) MetadataCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// QueryLabels calls QueryLabelsFunc.
|
||||
func (mock *MySQL) QueryLabels(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Q: q,
|
||||
Tr: tr,
|
||||
}
|
||||
mock.lockQueryLabels.Lock()
|
||||
mock.calls.QueryLabels = append(mock.calls.QueryLabels, callInfo)
|
||||
mock.lockQueryLabels.Unlock()
|
||||
if mock.QueryLabelsFunc == nil {
|
||||
var (
|
||||
stringToStringOut map[string]string
|
||||
errOut error
|
||||
)
|
||||
return stringToStringOut, errOut
|
||||
}
|
||||
return mock.QueryLabelsFunc(ctx, q, tr)
|
||||
}
|
||||
|
||||
// QueryLabelsCalls gets all the calls that were made to QueryLabels.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.MySQL.QueryLabelsCalls())
|
||||
func (mock *MySQL) QueryLabelsCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
mock.lockQueryLabels.RLock()
|
||||
calls = mock.calls.QueryLabels
|
||||
mock.lockQueryLabels.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// Query calls QueryFunc.
|
||||
func (mock *MySQL) Query(ctx context.Context, q string, tr processor.TimeRange) (*processor.MySQLQueryResult, error) {
|
||||
callInfo := struct {
|
||||
|
|
@ -232,7 +152,7 @@ func (mock *MySQL) Query(ctx context.Context, q string, tr processor.TimeRange)
|
|||
// QueryCalls gets all the calls that were made to Query.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.MySQL.QueryCalls())
|
||||
// len(mockedMySQL.QueryCalls())
|
||||
func (mock *MySQL) QueryCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
|
|
@ -248,3 +168,83 @@ func (mock *MySQL) QueryCalls() []struct {
|
|||
mock.lockQuery.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// QueryLabels calls QueryLabelsFunc.
|
||||
func (mock *MySQL) QueryLabels(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Q: q,
|
||||
Tr: tr,
|
||||
}
|
||||
mock.lockQueryLabels.Lock()
|
||||
mock.calls.QueryLabels = append(mock.calls.QueryLabels, callInfo)
|
||||
mock.lockQueryLabels.Unlock()
|
||||
if mock.QueryLabelsFunc == nil {
|
||||
var (
|
||||
stringToStringOut map[string]string
|
||||
errOut error
|
||||
)
|
||||
return stringToStringOut, errOut
|
||||
}
|
||||
return mock.QueryLabelsFunc(ctx, q, tr)
|
||||
}
|
||||
|
||||
// QueryLabelsCalls gets all the calls that were made to QueryLabels.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedMySQL.QueryLabelsCalls())
|
||||
func (mock *MySQL) QueryLabelsCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
mock.lockQueryLabels.RLock()
|
||||
calls = mock.calls.QueryLabels
|
||||
mock.lockQueryLabels.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *MySQL) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedMySQL.TestConnectionCalls())
|
||||
func (mock *MySQL) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,62 +17,48 @@ var _ datasource.PostgreSQL = &PostgreSQL{}
|
|||
|
||||
// PostgreSQL is a mock implementation of datasource.PostgreSQL.
|
||||
//
|
||||
// func TestSomethingThatUsesdatasource.PostgreSQL(t *testing.T) {
|
||||
// func TestSomethingThatUsesPostgreSQL(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked datasource.PostgreSQL
|
||||
// mockeddatasource.PostgreSQL := &PostgreSQL{
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// mockedPostgreSQL := &PostgreSQL{
|
||||
// MetadataFunc: func(ctx context.Context) (*processor.SQLMetadataResult, error) {
|
||||
// panic("mock out the Metadata method")
|
||||
// },
|
||||
// QueryLabelsFunc: func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
// panic("mock out the QueryLabels method")
|
||||
// },
|
||||
// QueryFunc: func(ctx context.Context, q string, tr processor.TimeRange) (*processor.PostgreSQLQueryResult, error) {
|
||||
// panic("mock out the Query method")
|
||||
// },
|
||||
// QueryLabelsFunc: func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
// panic("mock out the QueryLabels method")
|
||||
// },
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockeddatasource.PostgreSQL in code that requires datasource.PostgreSQL
|
||||
// // use mockedPostgreSQL in code that requires datasource.PostgreSQL
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type PostgreSQL struct {
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// MetadataFunc mocks the Metadata method.
|
||||
MetadataFunc func(ctx context.Context) (*processor.SQLMetadataResult, error)
|
||||
|
||||
// QueryLabelsFunc mocks the QueryLabels method.
|
||||
QueryLabelsFunc func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error)
|
||||
|
||||
// QueryFunc mocks the Query method.
|
||||
QueryFunc func(ctx context.Context, q string, tr processor.TimeRange) (*processor.PostgreSQLQueryResult, error)
|
||||
|
||||
// QueryLabelsFunc mocks the QueryLabels method.
|
||||
QueryLabelsFunc func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error)
|
||||
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// Metadata holds details about calls to the Metadata method.
|
||||
Metadata []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// QueryLabels holds details about calls to the QueryLabels method.
|
||||
QueryLabels []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Q is the q argument value.
|
||||
Q string
|
||||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// Query holds details about calls to the Query method.
|
||||
Query []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -82,47 +68,25 @@ type PostgreSQL struct {
|
|||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// QueryLabels holds details about calls to the QueryLabels method.
|
||||
QueryLabels []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Q is the q argument value.
|
||||
Q string
|
||||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
}
|
||||
lockTestConnection sync.RWMutex
|
||||
lockMetadata sync.RWMutex
|
||||
lockQueryLabels sync.RWMutex
|
||||
lockQuery sync.RWMutex
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *PostgreSQL) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.PostgreSQL.TestConnectionCalls())
|
||||
func (mock *PostgreSQL) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
lockQueryLabels sync.RWMutex
|
||||
lockTestConnection sync.RWMutex
|
||||
}
|
||||
|
||||
// Metadata calls MetadataFunc.
|
||||
|
|
@ -148,7 +112,7 @@ func (mock *PostgreSQL) Metadata(ctx context.Context) (*processor.SQLMetadataRes
|
|||
// MetadataCalls gets all the calls that were made to Metadata.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.PostgreSQL.MetadataCalls())
|
||||
// len(mockedPostgreSQL.MetadataCalls())
|
||||
func (mock *PostgreSQL) MetadataCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
|
|
@ -161,50 +125,6 @@ func (mock *PostgreSQL) MetadataCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// QueryLabels calls QueryLabelsFunc.
|
||||
func (mock *PostgreSQL) QueryLabels(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Q: q,
|
||||
Tr: tr,
|
||||
}
|
||||
mock.lockQueryLabels.Lock()
|
||||
mock.calls.QueryLabels = append(mock.calls.QueryLabels, callInfo)
|
||||
mock.lockQueryLabels.Unlock()
|
||||
if mock.QueryLabelsFunc == nil {
|
||||
var (
|
||||
stringToStringOut map[string]string
|
||||
errOut error
|
||||
)
|
||||
return stringToStringOut, errOut
|
||||
}
|
||||
return mock.QueryLabelsFunc(ctx, q, tr)
|
||||
}
|
||||
|
||||
// QueryLabelsCalls gets all the calls that were made to QueryLabels.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.PostgreSQL.QueryLabelsCalls())
|
||||
func (mock *PostgreSQL) QueryLabelsCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
mock.lockQueryLabels.RLock()
|
||||
calls = mock.calls.QueryLabels
|
||||
mock.lockQueryLabels.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// Query calls QueryFunc.
|
||||
func (mock *PostgreSQL) Query(ctx context.Context, q string, tr processor.TimeRange) (*processor.PostgreSQLQueryResult, error) {
|
||||
callInfo := struct {
|
||||
|
|
@ -232,7 +152,7 @@ func (mock *PostgreSQL) Query(ctx context.Context, q string, tr processor.TimeRa
|
|||
// QueryCalls gets all the calls that were made to Query.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.PostgreSQL.QueryCalls())
|
||||
// len(mockedPostgreSQL.QueryCalls())
|
||||
func (mock *PostgreSQL) QueryCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
|
|
@ -248,3 +168,83 @@ func (mock *PostgreSQL) QueryCalls() []struct {
|
|||
mock.lockQuery.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// QueryLabels calls QueryLabelsFunc.
|
||||
func (mock *PostgreSQL) QueryLabels(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Q: q,
|
||||
Tr: tr,
|
||||
}
|
||||
mock.lockQueryLabels.Lock()
|
||||
mock.calls.QueryLabels = append(mock.calls.QueryLabels, callInfo)
|
||||
mock.lockQueryLabels.Unlock()
|
||||
if mock.QueryLabelsFunc == nil {
|
||||
var (
|
||||
stringToStringOut map[string]string
|
||||
errOut error
|
||||
)
|
||||
return stringToStringOut, errOut
|
||||
}
|
||||
return mock.QueryLabelsFunc(ctx, q, tr)
|
||||
}
|
||||
|
||||
// QueryLabelsCalls gets all the calls that were made to QueryLabels.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedPostgreSQL.QueryLabelsCalls())
|
||||
func (mock *PostgreSQL) QueryLabelsCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
mock.lockQueryLabels.RLock()
|
||||
calls = mock.calls.QueryLabels
|
||||
mock.lockQueryLabels.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *PostgreSQL) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedPostgreSQL.TestConnectionCalls())
|
||||
func (mock *PostgreSQL) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,15 @@ var _ datasource.Prometheus = &Prometheus{}
|
|||
|
||||
// Prometheus is a mock implementation of datasource.Prometheus.
|
||||
//
|
||||
// func TestSomethingThatUsesdatasource.Prometheus(t *testing.T) {
|
||||
// func TestSomethingThatUsesPrometheus(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked datasource.Prometheus
|
||||
// mockeddatasource.Prometheus := &Prometheus{
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// mockedPrometheus := &Prometheus{
|
||||
// LabelNamesFunc: func(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelNamesResult, error) {
|
||||
// panic("mock out the LabelNames method")
|
||||
// },
|
||||
// LabelValuesFunc: func(ctx context.Context, label string, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelValuesResult, error) {
|
||||
// panic("mock out the LabelValues method")
|
||||
// },
|
||||
// MetadataFunc: func(ctx context.Context) (*processor.PrometheusMetadataResult, error) {
|
||||
// panic("mock out the Metadata method")
|
||||
|
|
@ -30,24 +33,24 @@ var _ datasource.Prometheus = &Prometheus{}
|
|||
// QueryRangeFunc: func(ctx context.Context, q string, tr processor.TimeRange) (*processor.PrometheusQueryResult, error) {
|
||||
// panic("mock out the QueryRange method")
|
||||
// },
|
||||
// LabelNamesFunc: func(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelNamesResult, error) {
|
||||
// panic("mock out the LabelNames method")
|
||||
// },
|
||||
// LabelValuesFunc: func(ctx context.Context, label string, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelValuesResult, error) {
|
||||
// panic("mock out the LabelValues method")
|
||||
// },
|
||||
// SeriesFunc: func(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusSeriesResult, error) {
|
||||
// panic("mock out the Series method")
|
||||
// },
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockeddatasource.Prometheus in code that requires datasource.Prometheus
|
||||
// // use mockedPrometheus in code that requires datasource.Prometheus
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type Prometheus struct {
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
// LabelNamesFunc mocks the LabelNames method.
|
||||
LabelNamesFunc func(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelNamesResult, error)
|
||||
|
||||
// LabelValuesFunc mocks the LabelValues method.
|
||||
LabelValuesFunc func(ctx context.Context, label string, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelValuesResult, error)
|
||||
|
||||
// MetadataFunc mocks the Metadata method.
|
||||
MetadataFunc func(ctx context.Context) (*processor.PrometheusMetadataResult, error)
|
||||
|
|
@ -55,36 +58,14 @@ type Prometheus struct {
|
|||
// QueryRangeFunc mocks the QueryRange method.
|
||||
QueryRangeFunc func(ctx context.Context, q string, tr processor.TimeRange) (*processor.PrometheusQueryResult, error)
|
||||
|
||||
// LabelNamesFunc mocks the LabelNames method.
|
||||
LabelNamesFunc func(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelNamesResult, error)
|
||||
|
||||
// LabelValuesFunc mocks the LabelValues method.
|
||||
LabelValuesFunc func(ctx context.Context, label string, matchers []string, tr processor.TimeRange) (*processor.PrometheusLabelValuesResult, error)
|
||||
|
||||
// SeriesFunc mocks the Series method.
|
||||
SeriesFunc func(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusSeriesResult, error)
|
||||
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// Metadata holds details about calls to the Metadata method.
|
||||
Metadata []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// QueryRange holds details about calls to the QueryRange method.
|
||||
QueryRange []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Q is the q argument value.
|
||||
Q string
|
||||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// LabelNames holds details about calls to the LabelNames method.
|
||||
LabelNames []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -105,6 +86,20 @@ type Prometheus struct {
|
|||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// Metadata holds details about calls to the Metadata method.
|
||||
Metadata []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// QueryRange holds details about calls to the QueryRange method.
|
||||
QueryRange []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Q is the q argument value.
|
||||
Q string
|
||||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// Series holds details about calls to the Series method.
|
||||
Series []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -114,129 +109,18 @@ type Prometheus struct {
|
|||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
}
|
||||
lockTestConnection sync.RWMutex
|
||||
lockMetadata sync.RWMutex
|
||||
lockQueryRange sync.RWMutex
|
||||
lockLabelNames sync.RWMutex
|
||||
lockLabelValues sync.RWMutex
|
||||
lockMetadata sync.RWMutex
|
||||
lockQueryRange sync.RWMutex
|
||||
lockSeries sync.RWMutex
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *Prometheus) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Prometheus.TestConnectionCalls())
|
||||
func (mock *Prometheus) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// Metadata calls MetadataFunc.
|
||||
func (mock *Prometheus) Metadata(ctx context.Context) (*processor.PrometheusMetadataResult, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockMetadata.Lock()
|
||||
mock.calls.Metadata = append(mock.calls.Metadata, callInfo)
|
||||
mock.lockMetadata.Unlock()
|
||||
if mock.MetadataFunc == nil {
|
||||
var (
|
||||
prometheusMetadataResultOut *processor.PrometheusMetadataResult
|
||||
errOut error
|
||||
)
|
||||
return prometheusMetadataResultOut, errOut
|
||||
}
|
||||
return mock.MetadataFunc(ctx)
|
||||
}
|
||||
|
||||
// MetadataCalls gets all the calls that were made to Metadata.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Prometheus.MetadataCalls())
|
||||
func (mock *Prometheus) MetadataCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockMetadata.RLock()
|
||||
calls = mock.calls.Metadata
|
||||
mock.lockMetadata.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// QueryRange calls QueryRangeFunc.
|
||||
func (mock *Prometheus) QueryRange(ctx context.Context, q string, tr processor.TimeRange) (*processor.PrometheusQueryResult, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Q: q,
|
||||
Tr: tr,
|
||||
}
|
||||
mock.lockQueryRange.Lock()
|
||||
mock.calls.QueryRange = append(mock.calls.QueryRange, callInfo)
|
||||
mock.lockQueryRange.Unlock()
|
||||
if mock.QueryRangeFunc == nil {
|
||||
var (
|
||||
prometheusQueryResultOut *processor.PrometheusQueryResult
|
||||
errOut error
|
||||
)
|
||||
return prometheusQueryResultOut, errOut
|
||||
}
|
||||
return mock.QueryRangeFunc(ctx, q, tr)
|
||||
}
|
||||
|
||||
// QueryRangeCalls gets all the calls that were made to QueryRange.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Prometheus.QueryRangeCalls())
|
||||
func (mock *Prometheus) QueryRangeCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
mock.lockQueryRange.RLock()
|
||||
calls = mock.calls.QueryRange
|
||||
mock.lockQueryRange.RUnlock()
|
||||
return calls
|
||||
lockTestConnection sync.RWMutex
|
||||
}
|
||||
|
||||
// LabelNames calls LabelNamesFunc.
|
||||
|
|
@ -266,7 +150,7 @@ func (mock *Prometheus) LabelNames(ctx context.Context, matchers []string, tr pr
|
|||
// LabelNamesCalls gets all the calls that were made to LabelNames.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Prometheus.LabelNamesCalls())
|
||||
// len(mockedPrometheus.LabelNamesCalls())
|
||||
func (mock *Prometheus) LabelNamesCalls() []struct {
|
||||
Ctx context.Context
|
||||
Matchers []string
|
||||
|
|
@ -312,7 +196,7 @@ func (mock *Prometheus) LabelValues(ctx context.Context, label string, matchers
|
|||
// LabelValuesCalls gets all the calls that were made to LabelValues.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Prometheus.LabelValuesCalls())
|
||||
// len(mockedPrometheus.LabelValuesCalls())
|
||||
func (mock *Prometheus) LabelValuesCalls() []struct {
|
||||
Ctx context.Context
|
||||
Label string
|
||||
|
|
@ -331,6 +215,86 @@ func (mock *Prometheus) LabelValuesCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// Metadata calls MetadataFunc.
|
||||
func (mock *Prometheus) Metadata(ctx context.Context) (*processor.PrometheusMetadataResult, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockMetadata.Lock()
|
||||
mock.calls.Metadata = append(mock.calls.Metadata, callInfo)
|
||||
mock.lockMetadata.Unlock()
|
||||
if mock.MetadataFunc == nil {
|
||||
var (
|
||||
prometheusMetadataResultOut *processor.PrometheusMetadataResult
|
||||
errOut error
|
||||
)
|
||||
return prometheusMetadataResultOut, errOut
|
||||
}
|
||||
return mock.MetadataFunc(ctx)
|
||||
}
|
||||
|
||||
// MetadataCalls gets all the calls that were made to Metadata.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedPrometheus.MetadataCalls())
|
||||
func (mock *Prometheus) MetadataCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockMetadata.RLock()
|
||||
calls = mock.calls.Metadata
|
||||
mock.lockMetadata.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// QueryRange calls QueryRangeFunc.
|
||||
func (mock *Prometheus) QueryRange(ctx context.Context, q string, tr processor.TimeRange) (*processor.PrometheusQueryResult, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Q: q,
|
||||
Tr: tr,
|
||||
}
|
||||
mock.lockQueryRange.Lock()
|
||||
mock.calls.QueryRange = append(mock.calls.QueryRange, callInfo)
|
||||
mock.lockQueryRange.Unlock()
|
||||
if mock.QueryRangeFunc == nil {
|
||||
var (
|
||||
prometheusQueryResultOut *processor.PrometheusQueryResult
|
||||
errOut error
|
||||
)
|
||||
return prometheusQueryResultOut, errOut
|
||||
}
|
||||
return mock.QueryRangeFunc(ctx, q, tr)
|
||||
}
|
||||
|
||||
// QueryRangeCalls gets all the calls that were made to QueryRange.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedPrometheus.QueryRangeCalls())
|
||||
func (mock *Prometheus) QueryRangeCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
mock.lockQueryRange.RLock()
|
||||
calls = mock.calls.QueryRange
|
||||
mock.lockQueryRange.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// Series calls SeriesFunc.
|
||||
func (mock *Prometheus) Series(ctx context.Context, matchers []string, tr processor.TimeRange) (*processor.PrometheusSeriesResult, error) {
|
||||
callInfo := struct {
|
||||
|
|
@ -358,7 +322,7 @@ func (mock *Prometheus) Series(ctx context.Context, matchers []string, tr proces
|
|||
// SeriesCalls gets all the calls that were made to Series.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Prometheus.SeriesCalls())
|
||||
// len(mockedPrometheus.SeriesCalls())
|
||||
func (mock *Prometheus) SeriesCalls() []struct {
|
||||
Ctx context.Context
|
||||
Matchers []string
|
||||
|
|
@ -374,3 +338,39 @@ func (mock *Prometheus) SeriesCalls() []struct {
|
|||
mock.lockSeries.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *Prometheus) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedPrometheus.TestConnectionCalls())
|
||||
func (mock *Prometheus) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,65 +17,57 @@ var _ datasource.Runner = &Runner{}
|
|||
|
||||
// Runner is a mock implementation of datasource.Runner.
|
||||
//
|
||||
// func TestSomethingThatUsesdatasource.Runner(t *testing.T) {
|
||||
// func TestSomethingThatUsesRunner(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked datasource.Runner
|
||||
// mockeddatasource.Runner := &Runner{
|
||||
// TypeFunc: func() datasource.Type {
|
||||
// panic("mock out the Type method")
|
||||
// },
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// PrometheusFunc: func(ctx context.Context) (datasource.Prometheus, error) {
|
||||
// panic("mock out the Prometheus method")
|
||||
// mockedRunner := &Runner{
|
||||
// MySQLFunc: func(ctx context.Context) (datasource.MySQL, error) {
|
||||
// panic("mock out the MySQL method")
|
||||
// },
|
||||
// PostgreSQLFunc: func(ctx context.Context) (datasource.PostgreSQL, error) {
|
||||
// panic("mock out the PostgreSQL method")
|
||||
// },
|
||||
// MySQLFunc: func(ctx context.Context) (datasource.MySQL, error) {
|
||||
// panic("mock out the MySQL method")
|
||||
// PrometheusFunc: func(ctx context.Context) (datasource.Prometheus, error) {
|
||||
// panic("mock out the Prometheus method")
|
||||
// },
|
||||
// SQLFunc: func(ctx context.Context) (datasource.SQL, error) {
|
||||
// panic("mock out the SQL method")
|
||||
// },
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// TypeFunc: func() datasource.Type {
|
||||
// panic("mock out the Type method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockeddatasource.Runner in code that requires datasource.Runner
|
||||
// // use mockedRunner in code that requires datasource.Runner
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type Runner struct {
|
||||
// TypeFunc mocks the Type method.
|
||||
TypeFunc func() datasource.Type
|
||||
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// PrometheusFunc mocks the Prometheus method.
|
||||
PrometheusFunc func(ctx context.Context) (datasource.Prometheus, error)
|
||||
// MySQLFunc mocks the MySQL method.
|
||||
MySQLFunc func(ctx context.Context) (datasource.MySQL, error)
|
||||
|
||||
// PostgreSQLFunc mocks the PostgreSQL method.
|
||||
PostgreSQLFunc func(ctx context.Context) (datasource.PostgreSQL, error)
|
||||
|
||||
// MySQLFunc mocks the MySQL method.
|
||||
MySQLFunc func(ctx context.Context) (datasource.MySQL, error)
|
||||
// PrometheusFunc mocks the Prometheus method.
|
||||
PrometheusFunc func(ctx context.Context) (datasource.Prometheus, error)
|
||||
|
||||
// SQLFunc mocks the SQL method.
|
||||
SQLFunc func(ctx context.Context) (datasource.SQL, error)
|
||||
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// TypeFunc mocks the Type method.
|
||||
TypeFunc func() datasource.Type
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Type holds details about calls to the Type method.
|
||||
Type []struct {
|
||||
}
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// Prometheus holds details about calls to the Prometheus method.
|
||||
Prometheus []struct {
|
||||
// MySQL holds details about calls to the MySQL method.
|
||||
MySQL []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
|
|
@ -84,8 +76,8 @@ type Runner struct {
|
|||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// MySQL holds details about calls to the MySQL method.
|
||||
MySQL []struct {
|
||||
// Prometheus holds details about calls to the Prometheus method.
|
||||
Prometheus []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
|
|
@ -94,114 +86,56 @@ type Runner struct {
|
|||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// Type holds details about calls to the Type method.
|
||||
Type []struct {
|
||||
}
|
||||
}
|
||||
lockType sync.RWMutex
|
||||
lockTestConnection sync.RWMutex
|
||||
lockPrometheus sync.RWMutex
|
||||
lockPostgreSQL sync.RWMutex
|
||||
lockMySQL sync.RWMutex
|
||||
lockPostgreSQL sync.RWMutex
|
||||
lockPrometheus sync.RWMutex
|
||||
lockSQL sync.RWMutex
|
||||
lockTestConnection sync.RWMutex
|
||||
lockType sync.RWMutex
|
||||
}
|
||||
|
||||
// Type calls TypeFunc.
|
||||
func (mock *Runner) Type() datasource.Type {
|
||||
callInfo := struct {
|
||||
}{}
|
||||
mock.lockType.Lock()
|
||||
mock.calls.Type = append(mock.calls.Type, callInfo)
|
||||
mock.lockType.Unlock()
|
||||
if mock.TypeFunc == nil {
|
||||
var (
|
||||
typeOut datasource.Type
|
||||
)
|
||||
return typeOut
|
||||
}
|
||||
return mock.TypeFunc()
|
||||
}
|
||||
|
||||
// TypeCalls gets all the calls that were made to Type.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Runner.TypeCalls())
|
||||
func (mock *Runner) TypeCalls() []struct {
|
||||
} {
|
||||
var calls []struct {
|
||||
}
|
||||
mock.lockType.RLock()
|
||||
calls = mock.calls.Type
|
||||
mock.lockType.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *Runner) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// MySQL calls MySQLFunc.
|
||||
func (mock *Runner) MySQL(ctx context.Context) (datasource.MySQL, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
mock.lockMySQL.Lock()
|
||||
mock.calls.MySQL = append(mock.calls.MySQL, callInfo)
|
||||
mock.lockMySQL.Unlock()
|
||||
if mock.MySQLFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
mySQLOut datasource.MySQL
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
return mySQLOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
return mock.MySQLFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// MySQLCalls gets all the calls that were made to MySQL.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Runner.TestConnectionCalls())
|
||||
func (mock *Runner) TestConnectionCalls() []struct {
|
||||
// len(mockedRunner.MySQLCalls())
|
||||
func (mock *Runner) MySQLCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// Prometheus calls PrometheusFunc.
|
||||
func (mock *Runner) Prometheus(ctx context.Context) (datasource.Prometheus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockPrometheus.Lock()
|
||||
mock.calls.Prometheus = append(mock.calls.Prometheus, callInfo)
|
||||
mock.lockPrometheus.Unlock()
|
||||
if mock.PrometheusFunc == nil {
|
||||
var (
|
||||
prometheusOut datasource.Prometheus
|
||||
errOut error
|
||||
)
|
||||
return prometheusOut, errOut
|
||||
}
|
||||
return mock.PrometheusFunc(ctx)
|
||||
}
|
||||
|
||||
// PrometheusCalls gets all the calls that were made to Prometheus.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Runner.PrometheusCalls())
|
||||
func (mock *Runner) PrometheusCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockPrometheus.RLock()
|
||||
calls = mock.calls.Prometheus
|
||||
mock.lockPrometheus.RUnlock()
|
||||
mock.lockMySQL.RLock()
|
||||
calls = mock.calls.MySQL
|
||||
mock.lockMySQL.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
|
|
@ -228,7 +162,7 @@ func (mock *Runner) PostgreSQL(ctx context.Context) (datasource.PostgreSQL, erro
|
|||
// PostgreSQLCalls gets all the calls that were made to PostgreSQL.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Runner.PostgreSQLCalls())
|
||||
// len(mockedRunner.PostgreSQLCalls())
|
||||
func (mock *Runner) PostgreSQLCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
|
|
@ -241,39 +175,39 @@ func (mock *Runner) PostgreSQLCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// MySQL calls MySQLFunc.
|
||||
func (mock *Runner) MySQL(ctx context.Context) (datasource.MySQL, error) {
|
||||
// Prometheus calls PrometheusFunc.
|
||||
func (mock *Runner) Prometheus(ctx context.Context) (datasource.Prometheus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockMySQL.Lock()
|
||||
mock.calls.MySQL = append(mock.calls.MySQL, callInfo)
|
||||
mock.lockMySQL.Unlock()
|
||||
if mock.MySQLFunc == nil {
|
||||
mock.lockPrometheus.Lock()
|
||||
mock.calls.Prometheus = append(mock.calls.Prometheus, callInfo)
|
||||
mock.lockPrometheus.Unlock()
|
||||
if mock.PrometheusFunc == nil {
|
||||
var (
|
||||
mySQLOut datasource.MySQL
|
||||
errOut error
|
||||
prometheusOut datasource.Prometheus
|
||||
errOut error
|
||||
)
|
||||
return mySQLOut, errOut
|
||||
return prometheusOut, errOut
|
||||
}
|
||||
return mock.MySQLFunc(ctx)
|
||||
return mock.PrometheusFunc(ctx)
|
||||
}
|
||||
|
||||
// MySQLCalls gets all the calls that were made to MySQL.
|
||||
// PrometheusCalls gets all the calls that were made to Prometheus.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Runner.MySQLCalls())
|
||||
func (mock *Runner) MySQLCalls() []struct {
|
||||
// len(mockedRunner.PrometheusCalls())
|
||||
func (mock *Runner) PrometheusCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockMySQL.RLock()
|
||||
calls = mock.calls.MySQL
|
||||
mock.lockMySQL.RUnlock()
|
||||
mock.lockPrometheus.RLock()
|
||||
calls = mock.calls.Prometheus
|
||||
mock.lockPrometheus.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +234,7 @@ func (mock *Runner) SQL(ctx context.Context) (datasource.SQL, error) {
|
|||
// SQLCalls gets all the calls that were made to SQL.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.Runner.SQLCalls())
|
||||
// len(mockedRunner.SQLCalls())
|
||||
func (mock *Runner) SQLCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
|
|
@ -312,3 +246,69 @@ func (mock *Runner) SQLCalls() []struct {
|
|||
mock.lockSQL.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *Runner) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedRunner.TestConnectionCalls())
|
||||
func (mock *Runner) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// Type calls TypeFunc.
|
||||
func (mock *Runner) Type() datasource.Type {
|
||||
callInfo := struct {
|
||||
}{}
|
||||
mock.lockType.Lock()
|
||||
mock.calls.Type = append(mock.calls.Type, callInfo)
|
||||
mock.lockType.Unlock()
|
||||
if mock.TypeFunc == nil {
|
||||
var (
|
||||
typeOut datasource.Type
|
||||
)
|
||||
return typeOut
|
||||
}
|
||||
return mock.TypeFunc()
|
||||
}
|
||||
|
||||
// TypeCalls gets all the calls that were made to Type.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedRunner.TypeCalls())
|
||||
func (mock *Runner) TypeCalls() []struct {
|
||||
} {
|
||||
var calls []struct {
|
||||
}
|
||||
mock.lockType.RLock()
|
||||
calls = mock.calls.Type
|
||||
mock.lockType.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,42 +17,37 @@ var _ datasource.SQL = &SQL{}
|
|||
|
||||
// SQL is a mock implementation of datasource.SQL.
|
||||
//
|
||||
// func TestSomethingThatUsesdatasource.SQL(t *testing.T) {
|
||||
// func TestSomethingThatUsesSQL(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked datasource.SQL
|
||||
// mockeddatasource.SQL := &SQL{
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// mockedSQL := &SQL{
|
||||
// MetadataFunc: func(ctx context.Context) (*processor.SQLMetadataResult, error) {
|
||||
// panic("mock out the Metadata method")
|
||||
// },
|
||||
// QueryLabelsFunc: func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error) {
|
||||
// panic("mock out the QueryLabels method")
|
||||
// },
|
||||
// TestConnectionFunc: func(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
// panic("mock out the TestConnection method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockeddatasource.SQL in code that requires datasource.SQL
|
||||
// // use mockedSQL in code that requires datasource.SQL
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
type SQL struct {
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// MetadataFunc mocks the Metadata method.
|
||||
MetadataFunc func(ctx context.Context) (*processor.SQLMetadataResult, error)
|
||||
|
||||
// QueryLabelsFunc mocks the QueryLabels method.
|
||||
QueryLabelsFunc func(ctx context.Context, q string, tr processor.TimeRange) (map[string]string, error)
|
||||
|
||||
// TestConnectionFunc mocks the TestConnection method.
|
||||
TestConnectionFunc func(ctx context.Context) (processor.ConnectionStatus, error)
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
// Metadata holds details about calls to the Metadata method.
|
||||
Metadata []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -67,46 +62,15 @@ type SQL struct {
|
|||
// Tr is the tr argument value.
|
||||
Tr processor.TimeRange
|
||||
}
|
||||
// TestConnection holds details about calls to the TestConnection method.
|
||||
TestConnection []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
}
|
||||
}
|
||||
lockTestConnection sync.RWMutex
|
||||
lockMetadata sync.RWMutex
|
||||
lockQueryLabels sync.RWMutex
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *SQL) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.SQL.TestConnectionCalls())
|
||||
func (mock *SQL) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
lockTestConnection sync.RWMutex
|
||||
}
|
||||
|
||||
// Metadata calls MetadataFunc.
|
||||
|
|
@ -132,7 +96,7 @@ func (mock *SQL) Metadata(ctx context.Context) (*processor.SQLMetadataResult, er
|
|||
// MetadataCalls gets all the calls that were made to Metadata.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.SQL.MetadataCalls())
|
||||
// len(mockedSQL.MetadataCalls())
|
||||
func (mock *SQL) MetadataCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
|
|
@ -172,7 +136,7 @@ func (mock *SQL) QueryLabels(ctx context.Context, q string, tr processor.TimeRan
|
|||
// QueryLabelsCalls gets all the calls that were made to QueryLabels.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.SQL.QueryLabelsCalls())
|
||||
// len(mockedSQL.QueryLabelsCalls())
|
||||
func (mock *SQL) QueryLabelsCalls() []struct {
|
||||
Ctx context.Context
|
||||
Q string
|
||||
|
|
@ -188,3 +152,39 @@ func (mock *SQL) QueryLabelsCalls() []struct {
|
|||
mock.lockQueryLabels.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// TestConnection calls TestConnectionFunc.
|
||||
func (mock *SQL) TestConnection(ctx context.Context) (processor.ConnectionStatus, error) {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
}{
|
||||
Ctx: ctx,
|
||||
}
|
||||
mock.lockTestConnection.Lock()
|
||||
mock.calls.TestConnection = append(mock.calls.TestConnection, callInfo)
|
||||
mock.lockTestConnection.Unlock()
|
||||
if mock.TestConnectionFunc == nil {
|
||||
var (
|
||||
connectionStatusOut processor.ConnectionStatus
|
||||
errOut error
|
||||
)
|
||||
return connectionStatusOut, errOut
|
||||
}
|
||||
return mock.TestConnectionFunc(ctx)
|
||||
}
|
||||
|
||||
// TestConnectionCalls gets all the calls that were made to TestConnection.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedSQL.TestConnectionCalls())
|
||||
func (mock *SQL) TestConnectionCalls() []struct {
|
||||
Ctx context.Context
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
}
|
||||
mock.lockTestConnection.RLock()
|
||||
calls = mock.calls.TestConnection
|
||||
mock.lockTestConnection.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,16 +18,16 @@ var _ datasource.StatusStore = &StatusStore{}
|
|||
|
||||
// StatusStore is a mock implementation of datasource.StatusStore.
|
||||
//
|
||||
// func TestSomethingThatUsesdatasource.StatusStore(t *testing.T) {
|
||||
// func TestSomethingThatUsesStatusStore(t *testing.T) {
|
||||
//
|
||||
// // make and configure a mocked datasource.StatusStore
|
||||
// mockeddatasource.StatusStore := &StatusStore{
|
||||
// mockedStatusStore := &StatusStore{
|
||||
// UpdateDataSourceStatusFunc: func(ctx context.Context, id xid.ID, organizationID string, status processor.ConnectionStatus) error {
|
||||
// panic("mock out the UpdateDataSourceStatus method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockeddatasource.StatusStore in code that requires datasource.StatusStore
|
||||
// // use mockedStatusStore in code that requires datasource.StatusStore
|
||||
// // and then make assertions.
|
||||
//
|
||||
// }
|
||||
|
|
@ -41,8 +41,8 @@ type StatusStore struct {
|
|||
UpdateDataSourceStatus []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// Id is the id argument value.
|
||||
Id xid.ID
|
||||
// ID is the id argument value.
|
||||
ID xid.ID
|
||||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
// Status is the status argument value.
|
||||
|
|
@ -56,12 +56,12 @@ type StatusStore struct {
|
|||
func (mock *StatusStore) UpdateDataSourceStatus(ctx context.Context, id xid.ID, organizationID string, status processor.ConnectionStatus) error {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
Id xid.ID
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
Status processor.ConnectionStatus
|
||||
}{
|
||||
Ctx: ctx,
|
||||
Id: id,
|
||||
ID: id,
|
||||
OrganizationID: organizationID,
|
||||
Status: status,
|
||||
}
|
||||
|
|
@ -80,16 +80,16 @@ func (mock *StatusStore) UpdateDataSourceStatus(ctx context.Context, id xid.ID,
|
|||
// UpdateDataSourceStatusCalls gets all the calls that were made to UpdateDataSourceStatus.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockeddatasource.StatusStore.UpdateDataSourceStatusCalls())
|
||||
// len(mockedStatusStore.UpdateDataSourceStatusCalls())
|
||||
func (mock *StatusStore) UpdateDataSourceStatusCalls() []struct {
|
||||
Ctx context.Context
|
||||
Id xid.ID
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
Status processor.ConnectionStatus
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
Id xid.ID
|
||||
ID xid.ID
|
||||
OrganizationID string
|
||||
Status processor.ConnectionStatus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ type Prometheus interface {
|
|||
|
||||
// SQL represents a SQL-based data source processor.
|
||||
//
|
||||
//go:generate ../../scripts/codegen/mock SQL
|
||||
//go:generate ../../scripts/codegen/mock SQL sql
|
||||
type SQL interface {
|
||||
connectionTester
|
||||
|
||||
|
|
@ -300,7 +300,7 @@ type SQL interface {
|
|||
|
||||
// PostgreSQL represents a PostgreSQL data source processor.
|
||||
//
|
||||
//go:generate ../../scripts/codegen/mock PostgreSQL
|
||||
//go:generate ../../scripts/codegen/mock PostgreSQL postgresql
|
||||
type PostgreSQL interface {
|
||||
SQL
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ type PostgreSQL interface {
|
|||
|
||||
// MySQL represents a MySQL data source processor.
|
||||
//
|
||||
//go:generate ../../scripts/codegen/mock MySQL
|
||||
//go:generate ../../scripts/codegen/mock MySQL mysql
|
||||
type MySQL interface {
|
||||
SQL
|
||||
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ func Test_connect(t *testing.T) {
|
|||
|
||||
ff := store.UpdateDataSourceStatusCalls()
|
||||
require.Len(t, ff, 1)
|
||||
assert.Equal(t, r.ds.ID, ff[0].Id)
|
||||
assert.Equal(t, r.ds.ID, ff[0].ID)
|
||||
assert.Equal(t, "org", ff[0].OrganizationID)
|
||||
assert.Equal(t, processor.ConnectionStatusSuccess, ff[0].Status)
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ var ErrNotSimulated = errutil.New(
|
|||
|
||||
// Result is what running a simulated metric block reports back.
|
||||
type Result struct {
|
||||
// Cleared reports whether the block's real data has arrived and the
|
||||
// simulation has been taken off it.
|
||||
// Cleared indicates whether the block's real data has arrived and
|
||||
// the simulation has been switched off.
|
||||
Cleared bool `json:"cleared"`
|
||||
}
|
||||
|
||||
|
|
@ -100,8 +100,8 @@ var _probeSpans = map[string]time.Duration{
|
|||
// rows.
|
||||
const _queryQuery = "query"
|
||||
|
||||
// Checker probes the data source of a simulated metric block and takes
|
||||
// the simulation off the block once real data answers.
|
||||
// Checker probes the data source of a simulated metric block and
|
||||
// switches the simulation off once real data answers.
|
||||
type Checker struct {
|
||||
// log is the component logger.
|
||||
log *slog.Logger
|
||||
|
|
@ -112,7 +112,7 @@ type Checker struct {
|
|||
// runners hands out the client that speaks to a data source.
|
||||
runners Runners
|
||||
|
||||
// applier writes the cleared attribute onto the live document.
|
||||
// applier writes the switched-off flag onto the live document.
|
||||
applier Applier
|
||||
|
||||
// results remembers each block's last verdict for _resultTTL.
|
||||
|
|
@ -141,7 +141,7 @@ func (c *Checker) Start(ctx context.Context) {
|
|||
c.results.Start(ctx)
|
||||
}
|
||||
|
||||
// Check reports whether the simulation was taken off the block, probing
|
||||
// Check reports whether the block's simulation was switched off, probing
|
||||
// the block's data source when no recent verdict is remembered. A data
|
||||
// source that cannot be reached, or that answers with nothing, leaves the
|
||||
// block simulating and is not an error: it is the state the simulation
|
||||
|
|
@ -152,7 +152,7 @@ func (c *Checker) Check(
|
|||
block document.Block,
|
||||
organizationID string,
|
||||
) (Result, error) {
|
||||
if _, simulated := block.Attrs.Value(document.AttrSimulationPreset); !simulated {
|
||||
if !simulated(block) {
|
||||
return Result{}, ErrNotSimulated
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +304,8 @@ func (c *Checker) query(
|
|||
}
|
||||
}
|
||||
|
||||
// clear takes the simulation off the block on the live document.
|
||||
// clear switches the block's simulation off on the live document. The
|
||||
// preset stays, so the block remembers which series it drew.
|
||||
func (c *Checker) clear(
|
||||
ctx context.Context,
|
||||
documentID, branchID xid.ID,
|
||||
|
|
@ -312,7 +313,7 @@ func (c *Checker) clear(
|
|||
) error {
|
||||
res, err := c.applier.Apply(ctx, documentID, branchID, []edit.Operation{
|
||||
edit.UpdateAttrs(blockUID, map[string]any{
|
||||
document.AttrSimulationPreset: nil,
|
||||
document.AttrSimulationActive: false,
|
||||
}),
|
||||
}, true)
|
||||
if err != nil {
|
||||
|
|
@ -342,6 +343,21 @@ func cacheKey(documentID, branchID xid.ID, blockUID string) string {
|
|||
return documentID.String() + "/" + branchID.String() + "/" + blockUID
|
||||
}
|
||||
|
||||
// simulated reports whether the block draws generated data: it names a
|
||||
// preset and its simulation is switched on.
|
||||
func simulated(block document.Block) bool {
|
||||
if _, ok := block.Attrs.Value(document.AttrSimulationPreset); !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
active, ok := block.Attrs.Get(document.AttrSimulationActive)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return active.Bool()
|
||||
}
|
||||
|
||||
// probeSpan reads how far back the block's window reaches.
|
||||
func probeSpan(block document.Block) time.Duration {
|
||||
raw, ok := block.Attrs.Value(document.AttrTimeRange)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ func metricAttrs() document.Attributes {
|
|||
map[string]any{"name": "Query 1", "query": "up", "legendFormat": ""},
|
||||
},
|
||||
document.AttrSimulationPreset: "cpu_usage",
|
||||
document.AttrSimulationActive: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -368,11 +369,26 @@ func Test_Checker_Check(t *testing.T) {
|
|||
}),
|
||||
Prometheus: sampled(),
|
||||
},
|
||||
"The block is not simulating": {
|
||||
"The block names no preset": {
|
||||
Attrs: withoutAttr(document.AttrSimulationPreset),
|
||||
Prometheus: sampled(),
|
||||
Err: ErrNotSimulated,
|
||||
},
|
||||
"The simulation is switched off": {
|
||||
Attrs: withAttr(document.AttrSimulationActive, false),
|
||||
Prometheus: sampled(),
|
||||
Err: ErrNotSimulated,
|
||||
},
|
||||
"The block carries a preset and no flag": {
|
||||
Attrs: withoutAttr(document.AttrSimulationActive),
|
||||
Prometheus: sampled(),
|
||||
Err: ErrNotSimulated,
|
||||
},
|
||||
"The flag is not a boolean": {
|
||||
Attrs: withAttr(document.AttrSimulationActive, "true"),
|
||||
Prometheus: sampled(),
|
||||
Err: ErrNotSimulated,
|
||||
},
|
||||
"The block carries no uid": {
|
||||
Attrs: withoutAttr(document.AttrUID),
|
||||
Prometheus: sampled(),
|
||||
|
|
@ -499,7 +515,7 @@ func Test_Checker_Check(t *testing.T) {
|
|||
|
||||
assert.JSONEq(
|
||||
t,
|
||||
`{"kind":"update_attrs","block_uid":"block-1","attrs":{"simulationPreset":null}}`,
|
||||
`{"kind":"update_attrs","block_uid":"block-1","attrs":{"simulationActive":false}}`,
|
||||
string(raw),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,9 +87,15 @@ const (
|
|||
AttrAxisBoundsMax = "axisBoundsMax"
|
||||
|
||||
// AttrSimulationPreset names the generated series a metric block
|
||||
// draws while its data source has no real data to answer with. It
|
||||
// is unset on a block that queries normally.
|
||||
// draws while AttrSimulationActive is set. It is unset on a block
|
||||
// nobody has simulated. Once set, it stays after the simulation ends.
|
||||
AttrSimulationPreset = "simulationPreset"
|
||||
|
||||
// AttrSimulationActive is true while a metric block draws its
|
||||
// AttrSimulationPreset because its data source has no real data yet.
|
||||
// Only the editor and core use it. Tools and document readers never
|
||||
// see it.
|
||||
AttrSimulationActive = "simulationActive"
|
||||
)
|
||||
|
||||
// MarkComment is the inline mark type anchoring a comment to a range of
|
||||
|
|
|
|||
|
|
@ -5,10 +5,11 @@ package manager
|
|||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/oxynote/oxynote/server/core/internal/document"
|
||||
"github.com/oxynote/oxynote/server/core/internal/search"
|
||||
"github.com/rs/xid"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that DBMock does implement DB.
|
||||
|
|
@ -150,10 +151,10 @@ func (mock *DBMock) FetchDocumentBranchesUnsafe(ctx context.Context, docID xid.I
|
|||
mock.lockFetchDocumentBranchesUnsafe.Unlock()
|
||||
if mock.FetchDocumentBranchesUnsafeFunc == nil {
|
||||
var (
|
||||
out0 []document.BranchSummary
|
||||
errOut error
|
||||
branchSummarysOut []document.BranchSummary
|
||||
errOut error
|
||||
)
|
||||
return out0, errOut
|
||||
return branchSummarysOut, errOut
|
||||
}
|
||||
return mock.FetchDocumentBranchesUnsafeFunc(ctx, docID)
|
||||
}
|
||||
|
|
@ -190,10 +191,10 @@ func (mock *DBMock) FetchDocumentUnsafeByBranchID(ctx context.Context, branchID
|
|||
mock.lockFetchDocumentUnsafeByBranchID.Unlock()
|
||||
if mock.FetchDocumentUnsafeByBranchIDFunc == nil {
|
||||
var (
|
||||
out0 *document.Document
|
||||
errOut error
|
||||
documentOut *document.Document
|
||||
errOut error
|
||||
)
|
||||
return out0, errOut
|
||||
return documentOut, errOut
|
||||
}
|
||||
return mock.FetchDocumentUnsafeByBranchIDFunc(ctx, branchID)
|
||||
}
|
||||
|
|
@ -232,10 +233,10 @@ func (mock *DBMock) FetchSearchJobs(ctx context.Context, offsetID int64, limit i
|
|||
mock.lockFetchSearchJobs.Unlock()
|
||||
if mock.FetchSearchJobsFunc == nil {
|
||||
var (
|
||||
out0 []search.Job
|
||||
errOut error
|
||||
jobsOut []search.Job
|
||||
errOut error
|
||||
)
|
||||
return out0, errOut
|
||||
return jobsOut, errOut
|
||||
}
|
||||
return mock.FetchSearchJobsFunc(ctx, offsetID, limit)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@ package manager
|
|||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/oxynote/oxynote/server/core/internal/search"
|
||||
"github.com/rs/xid"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Ensure, that IndexMock does implement Index.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -17,7 +17,7 @@ var _ SearchTrigger = &SearchTriggerMock{}
|
|||
//
|
||||
// // make and configure a mocked SearchTrigger
|
||||
// mockedSearchTrigger := &SearchTriggerMock{
|
||||
// TriggerFunc: func() {
|
||||
// TriggerFunc: func() {
|
||||
// panic("mock out the Trigger method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ var _ Manager = &ManagerMock{}
|
|||
// ChatFunc: func(ctx context.Context, orgID string, userID string, conn protocol.SessionConn) error {
|
||||
// panic("mock out the Chat method")
|
||||
// },
|
||||
// ConfiguredFunc: func() bool {
|
||||
// panic("mock out the Configured method")
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // use mockedManager in code that requires Manager
|
||||
|
|
@ -30,17 +33,14 @@ var _ Manager = &ManagerMock{}
|
|||
//
|
||||
// }
|
||||
type ManagerMock struct {
|
||||
// ConfiguredFunc mocks the Configured method.
|
||||
ConfiguredFunc func() bool
|
||||
|
||||
// ChatFunc mocks the Chat method.
|
||||
ChatFunc func(ctx context.Context, orgID string, userID string, conn protocol.SessionConn) error
|
||||
|
||||
// ConfiguredFunc mocks the Configured method.
|
||||
ConfiguredFunc func() bool
|
||||
|
||||
// calls tracks calls to the methods.
|
||||
calls struct {
|
||||
// Configured holds details about calls to the Configured method.
|
||||
Configured []struct {
|
||||
}
|
||||
// Chat holds details about calls to the Chat method.
|
||||
Chat []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -52,9 +52,12 @@ type ManagerMock struct {
|
|||
// Conn is the conn argument value.
|
||||
Conn protocol.SessionConn
|
||||
}
|
||||
// Configured holds details about calls to the Configured method.
|
||||
Configured []struct {
|
||||
}
|
||||
}
|
||||
lockConfigured sync.RWMutex
|
||||
lockChat sync.RWMutex
|
||||
lockConfigured sync.RWMutex
|
||||
}
|
||||
|
||||
// Chat calls ChatFunc.
|
||||
|
|
|
|||
|
|
@ -72,10 +72,10 @@ func (mock *RunnerMock) Run(ctx context.Context, documentID xid.ID, branchID xid
|
|||
mock.lockRun.Unlock()
|
||||
if mock.RunFunc == nil {
|
||||
var (
|
||||
ifaceValOut any
|
||||
errOut error
|
||||
vOut any
|
||||
errOut error
|
||||
)
|
||||
return ifaceValOut, errOut
|
||||
return vOut, errOut
|
||||
}
|
||||
return mock.RunFunc(ctx, documentID, branchID, blockUID, organizationID)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ var _ DB = &DBMock{}
|
|||
// DeleteDocumentCommentsByBranchIDFunc: func(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
// panic("mock out the DeleteDocumentCommentsByBranchID method")
|
||||
// },
|
||||
// DetachDocumentHooksByBranchIDFunc: func(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
// panic("mock out the DetachDocumentHooksByBranchID method")
|
||||
// },
|
||||
// FetchBranchReviewerFunc: func(ctx context.Context, branchID xid.ID, userID string, organizationID string) (*documentCore.BranchReviewer, error) {
|
||||
// panic("mock out the FetchBranchReviewer method")
|
||||
// },
|
||||
|
|
@ -118,9 +121,6 @@ var _ DB = &DBMock{}
|
|||
// ReplaceBranchTagsFunc: func(ctx context.Context, organizationID string, fromBranchID xid.ID, toBranchID xid.ID) error {
|
||||
// panic("mock out the ReplaceBranchTags method")
|
||||
// },
|
||||
// DetachDocumentHooksByBranchIDFunc: func(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
// panic("mock out the DetachDocumentHooksByBranchID method")
|
||||
// },
|
||||
// UpdateBranchReviewerFunc: func(ctx context.Context, reviewer documentCore.BranchReviewer) error {
|
||||
// panic("mock out the UpdateBranchReviewer method")
|
||||
// },
|
||||
|
|
@ -176,6 +176,9 @@ type DBMock struct {
|
|||
// DeleteDocumentCommentsByBranchIDFunc mocks the DeleteDocumentCommentsByBranchID method.
|
||||
DeleteDocumentCommentsByBranchIDFunc func(ctx context.Context, branchID xid.ID, organizationID string) error
|
||||
|
||||
// DetachDocumentHooksByBranchIDFunc mocks the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchIDFunc func(ctx context.Context, branchID xid.ID, organizationID string) error
|
||||
|
||||
// FetchBranchReviewerFunc mocks the FetchBranchReviewer method.
|
||||
FetchBranchReviewerFunc func(ctx context.Context, branchID xid.ID, userID string, organizationID string) (*documentCore.BranchReviewer, error)
|
||||
|
||||
|
|
@ -239,9 +242,6 @@ type DBMock struct {
|
|||
// ReplaceBranchTagsFunc mocks the ReplaceBranchTags method.
|
||||
ReplaceBranchTagsFunc func(ctx context.Context, organizationID string, fromBranchID xid.ID, toBranchID xid.ID) error
|
||||
|
||||
// DetachDocumentHooksByBranchIDFunc mocks the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchIDFunc func(ctx context.Context, branchID xid.ID, organizationID string) error
|
||||
|
||||
// UpdateBranchReviewerFunc mocks the UpdateBranchReviewer method.
|
||||
UpdateBranchReviewerFunc func(ctx context.Context, reviewer documentCore.BranchReviewer) error
|
||||
|
||||
|
|
@ -356,6 +356,15 @@ type DBMock struct {
|
|||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
}
|
||||
// DetachDocumentHooksByBranchID holds details about calls to the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchID []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// BranchID is the branchID argument value.
|
||||
BranchID xid.ID
|
||||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
}
|
||||
// FetchBranchReviewer holds details about calls to the FetchBranchReviewer method.
|
||||
FetchBranchReviewer []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -535,15 +544,6 @@ type DBMock struct {
|
|||
// ToBranchID is the toBranchID argument value.
|
||||
ToBranchID xid.ID
|
||||
}
|
||||
// DetachDocumentHooksByBranchID holds details about calls to the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchID []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// BranchID is the branchID argument value.
|
||||
BranchID xid.ID
|
||||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
}
|
||||
// UpdateBranchReviewer holds details about calls to the UpdateBranchReviewer method.
|
||||
UpdateBranchReviewer []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -607,6 +607,7 @@ type DBMock struct {
|
|||
lockDeleteDocument sync.RWMutex
|
||||
lockDeleteDocumentBranchByID sync.RWMutex
|
||||
lockDeleteDocumentCommentsByBranchID sync.RWMutex
|
||||
lockDetachDocumentHooksByBranchID sync.RWMutex
|
||||
lockFetchBranchReviewer sync.RWMutex
|
||||
lockFetchBranchReviewers sync.RWMutex
|
||||
lockFetchDocument sync.RWMutex
|
||||
|
|
@ -628,7 +629,6 @@ type DBMock struct {
|
|||
lockInsertSearchJob sync.RWMutex
|
||||
lockPromoteBranchApprovals sync.RWMutex
|
||||
lockReplaceBranchTags sync.RWMutex
|
||||
lockDetachDocumentHooksByBranchID sync.RWMutex
|
||||
lockUpdateBranchReviewer sync.RWMutex
|
||||
lockUpdateDocument sync.RWMutex
|
||||
lockUpdateDocumentBranchMetadata sync.RWMutex
|
||||
|
|
@ -828,7 +828,9 @@ func (mock *DBMock) CopyBranchTags(ctx context.Context, organizationID string, f
|
|||
mock.calls.CopyBranchTags = append(mock.calls.CopyBranchTags, callInfo)
|
||||
mock.lockCopyBranchTags.Unlock()
|
||||
if mock.CopyBranchTagsFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.CopyBranchTagsFunc(ctx, organizationID, fromBranchID, toBranchID)
|
||||
|
|
@ -1077,6 +1079,49 @@ func (mock *DBMock) DeleteDocumentCommentsByBranchIDCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchID calls DetachDocumentHooksByBranchIDFunc.
|
||||
func (mock *DBMock) DetachDocumentHooksByBranchID(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
BranchID: branchID,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.Lock()
|
||||
mock.calls.DetachDocumentHooksByBranchID = append(mock.calls.DetachDocumentHooksByBranchID, callInfo)
|
||||
mock.lockDetachDocumentHooksByBranchID.Unlock()
|
||||
if mock.DetachDocumentHooksByBranchIDFunc == nil {
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.DetachDocumentHooksByBranchIDFunc(ctx, branchID, organizationID)
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchIDCalls gets all the calls that were made to DetachDocumentHooksByBranchID.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedDB.DetachDocumentHooksByBranchIDCalls())
|
||||
func (mock *DBMock) DetachDocumentHooksByBranchIDCalls() []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.RLock()
|
||||
calls = mock.calls.DetachDocumentHooksByBranchID
|
||||
mock.lockDetachDocumentHooksByBranchID.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// FetchBranchReviewer calls FetchBranchReviewerFunc.
|
||||
func (mock *DBMock) FetchBranchReviewer(ctx context.Context, branchID xid.ID, userID string, organizationID string) (*documentCore.BranchReviewer, error) {
|
||||
callInfo := struct {
|
||||
|
|
@ -1943,7 +1988,9 @@ func (mock *DBMock) ReplaceBranchTags(ctx context.Context, organizationID string
|
|||
mock.calls.ReplaceBranchTags = append(mock.calls.ReplaceBranchTags, callInfo)
|
||||
mock.lockReplaceBranchTags.Unlock()
|
||||
if mock.ReplaceBranchTagsFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.ReplaceBranchTagsFunc(ctx, organizationID, fromBranchID, toBranchID)
|
||||
|
|
@ -1971,49 +2018,6 @@ func (mock *DBMock) ReplaceBranchTagsCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchID calls DetachDocumentHooksByBranchIDFunc.
|
||||
func (mock *DBMock) DetachDocumentHooksByBranchID(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
BranchID: branchID,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.Lock()
|
||||
mock.calls.DetachDocumentHooksByBranchID = append(mock.calls.DetachDocumentHooksByBranchID, callInfo)
|
||||
mock.lockDetachDocumentHooksByBranchID.Unlock()
|
||||
if mock.DetachDocumentHooksByBranchIDFunc == nil {
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.DetachDocumentHooksByBranchIDFunc(ctx, branchID, organizationID)
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchIDCalls gets all the calls that were made to DetachDocumentHooksByBranchID.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedDB.DetachDocumentHooksByBranchIDCalls())
|
||||
func (mock *DBMock) DetachDocumentHooksByBranchIDCalls() []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.RLock()
|
||||
calls = mock.calls.DetachDocumentHooksByBranchID
|
||||
mock.lockDetachDocumentHooksByBranchID.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// UpdateBranchReviewer calls UpdateBranchReviewerFunc.
|
||||
func (mock *DBMock) UpdateBranchReviewer(ctx context.Context, reviewer documentCore.BranchReviewer) error {
|
||||
callInfo := struct {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ var _ SearchTrigger = &SearchTriggerMock{}
|
|||
//
|
||||
// // make and configure a mocked SearchTrigger
|
||||
// mockedSearchTrigger := &SearchTriggerMock{
|
||||
// TriggerFunc: func() {
|
||||
// TriggerFunc: func() {
|
||||
// panic("mock out the Trigger method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ func (mock *SearcherMock) SearchDocuments(ctx context.Context, organizationID st
|
|||
mock.lockSearchDocuments.Unlock()
|
||||
if mock.SearchDocumentsFunc == nil {
|
||||
var (
|
||||
out0 []byte
|
||||
errOut error
|
||||
bytesOut []byte
|
||||
errOut error
|
||||
)
|
||||
return out0, errOut
|
||||
return bytesOut, errOut
|
||||
}
|
||||
return mock.SearchDocumentsFunc(ctx, organizationID, query)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ var _ Tx = &TxMock{}
|
|||
// DeleteDocumentCommentsByBranchIDFunc: func(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
// panic("mock out the DeleteDocumentCommentsByBranchID method")
|
||||
// },
|
||||
// DetachDocumentHooksByBranchIDFunc: func(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
// panic("mock out the DetachDocumentHooksByBranchID method")
|
||||
// },
|
||||
// FetchBranchReviewerFunc: func(ctx context.Context, branchID xid.ID, userID string, organizationID string) (*documentCore.BranchReviewer, error) {
|
||||
// panic("mock out the FetchBranchReviewer method")
|
||||
// },
|
||||
|
|
@ -121,9 +124,6 @@ var _ Tx = &TxMock{}
|
|||
// RollbackFunc: func() error {
|
||||
// panic("mock out the Rollback method")
|
||||
// },
|
||||
// DetachDocumentHooksByBranchIDFunc: func(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
// panic("mock out the DetachDocumentHooksByBranchID method")
|
||||
// },
|
||||
// UpdateBranchReviewerFunc: func(ctx context.Context, reviewer documentCore.BranchReviewer) error {
|
||||
// panic("mock out the UpdateBranchReviewer method")
|
||||
// },
|
||||
|
|
@ -179,6 +179,9 @@ type TxMock struct {
|
|||
// DeleteDocumentCommentsByBranchIDFunc mocks the DeleteDocumentCommentsByBranchID method.
|
||||
DeleteDocumentCommentsByBranchIDFunc func(ctx context.Context, branchID xid.ID, organizationID string) error
|
||||
|
||||
// DetachDocumentHooksByBranchIDFunc mocks the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchIDFunc func(ctx context.Context, branchID xid.ID, organizationID string) error
|
||||
|
||||
// FetchBranchReviewerFunc mocks the FetchBranchReviewer method.
|
||||
FetchBranchReviewerFunc func(ctx context.Context, branchID xid.ID, userID string, organizationID string) (*documentCore.BranchReviewer, error)
|
||||
|
||||
|
|
@ -245,9 +248,6 @@ type TxMock struct {
|
|||
// RollbackFunc mocks the Rollback method.
|
||||
RollbackFunc func() error
|
||||
|
||||
// DetachDocumentHooksByBranchIDFunc mocks the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchIDFunc func(ctx context.Context, branchID xid.ID, organizationID string) error
|
||||
|
||||
// UpdateBranchReviewerFunc mocks the UpdateBranchReviewer method.
|
||||
UpdateBranchReviewerFunc func(ctx context.Context, reviewer documentCore.BranchReviewer) error
|
||||
|
||||
|
|
@ -358,6 +358,15 @@ type TxMock struct {
|
|||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
}
|
||||
// DetachDocumentHooksByBranchID holds details about calls to the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchID []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// BranchID is the branchID argument value.
|
||||
BranchID xid.ID
|
||||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
}
|
||||
// FetchBranchReviewer holds details about calls to the FetchBranchReviewer method.
|
||||
FetchBranchReviewer []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -540,15 +549,6 @@ type TxMock struct {
|
|||
// Rollback holds details about calls to the Rollback method.
|
||||
Rollback []struct {
|
||||
}
|
||||
// DetachDocumentHooksByBranchID holds details about calls to the DetachDocumentHooksByBranchID method.
|
||||
DetachDocumentHooksByBranchID []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
Ctx context.Context
|
||||
// BranchID is the branchID argument value.
|
||||
BranchID xid.ID
|
||||
// OrganizationID is the organizationID argument value.
|
||||
OrganizationID string
|
||||
}
|
||||
// UpdateBranchReviewer holds details about calls to the UpdateBranchReviewer method.
|
||||
UpdateBranchReviewer []struct {
|
||||
// Ctx is the ctx argument value.
|
||||
|
|
@ -612,6 +612,7 @@ type TxMock struct {
|
|||
lockDeleteDocument sync.RWMutex
|
||||
lockDeleteDocumentBranchByID sync.RWMutex
|
||||
lockDeleteDocumentCommentsByBranchID sync.RWMutex
|
||||
lockDetachDocumentHooksByBranchID sync.RWMutex
|
||||
lockFetchBranchReviewer sync.RWMutex
|
||||
lockFetchBranchReviewers sync.RWMutex
|
||||
lockFetchDocument sync.RWMutex
|
||||
|
|
@ -634,7 +635,6 @@ type TxMock struct {
|
|||
lockPromoteBranchApprovals sync.RWMutex
|
||||
lockReplaceBranchTags sync.RWMutex
|
||||
lockRollback sync.RWMutex
|
||||
lockDetachDocumentHooksByBranchID sync.RWMutex
|
||||
lockUpdateBranchReviewer sync.RWMutex
|
||||
lockUpdateDocument sync.RWMutex
|
||||
lockUpdateDocumentBranchMetadata sync.RWMutex
|
||||
|
|
@ -825,7 +825,9 @@ func (mock *TxMock) CopyBranchTags(ctx context.Context, organizationID string, f
|
|||
mock.calls.CopyBranchTags = append(mock.calls.CopyBranchTags, callInfo)
|
||||
mock.lockCopyBranchTags.Unlock()
|
||||
if mock.CopyBranchTagsFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.CopyBranchTagsFunc(ctx, organizationID, fromBranchID, toBranchID)
|
||||
|
|
@ -1074,6 +1076,49 @@ func (mock *TxMock) DeleteDocumentCommentsByBranchIDCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchID calls DetachDocumentHooksByBranchIDFunc.
|
||||
func (mock *TxMock) DetachDocumentHooksByBranchID(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
BranchID: branchID,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.Lock()
|
||||
mock.calls.DetachDocumentHooksByBranchID = append(mock.calls.DetachDocumentHooksByBranchID, callInfo)
|
||||
mock.lockDetachDocumentHooksByBranchID.Unlock()
|
||||
if mock.DetachDocumentHooksByBranchIDFunc == nil {
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.DetachDocumentHooksByBranchIDFunc(ctx, branchID, organizationID)
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchIDCalls gets all the calls that were made to DetachDocumentHooksByBranchID.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedTx.DetachDocumentHooksByBranchIDCalls())
|
||||
func (mock *TxMock) DetachDocumentHooksByBranchIDCalls() []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.RLock()
|
||||
calls = mock.calls.DetachDocumentHooksByBranchID
|
||||
mock.lockDetachDocumentHooksByBranchID.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// FetchBranchReviewer calls FetchBranchReviewerFunc.
|
||||
func (mock *TxMock) FetchBranchReviewer(ctx context.Context, branchID xid.ID, userID string, organizationID string) (*documentCore.BranchReviewer, error) {
|
||||
callInfo := struct {
|
||||
|
|
@ -1940,7 +1985,9 @@ func (mock *TxMock) ReplaceBranchTags(ctx context.Context, organizationID string
|
|||
mock.calls.ReplaceBranchTags = append(mock.calls.ReplaceBranchTags, callInfo)
|
||||
mock.lockReplaceBranchTags.Unlock()
|
||||
if mock.ReplaceBranchTagsFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.ReplaceBranchTagsFunc(ctx, organizationID, fromBranchID, toBranchID)
|
||||
|
|
@ -1998,49 +2045,6 @@ func (mock *TxMock) RollbackCalls() []struct {
|
|||
return calls
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchID calls DetachDocumentHooksByBranchIDFunc.
|
||||
func (mock *TxMock) DetachDocumentHooksByBranchID(ctx context.Context, branchID xid.ID, organizationID string) error {
|
||||
callInfo := struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}{
|
||||
Ctx: ctx,
|
||||
BranchID: branchID,
|
||||
OrganizationID: organizationID,
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.Lock()
|
||||
mock.calls.DetachDocumentHooksByBranchID = append(mock.calls.DetachDocumentHooksByBranchID, callInfo)
|
||||
mock.lockDetachDocumentHooksByBranchID.Unlock()
|
||||
if mock.DetachDocumentHooksByBranchIDFunc == nil {
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.DetachDocumentHooksByBranchIDFunc(ctx, branchID, organizationID)
|
||||
}
|
||||
|
||||
// DetachDocumentHooksByBranchIDCalls gets all the calls that were made to DetachDocumentHooksByBranchID.
|
||||
// Check the length with:
|
||||
//
|
||||
// len(mockedTx.DetachDocumentHooksByBranchIDCalls())
|
||||
func (mock *TxMock) DetachDocumentHooksByBranchIDCalls() []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
} {
|
||||
var calls []struct {
|
||||
Ctx context.Context
|
||||
BranchID xid.ID
|
||||
OrganizationID string
|
||||
}
|
||||
mock.lockDetachDocumentHooksByBranchID.RLock()
|
||||
calls = mock.calls.DetachDocumentHooksByBranchID
|
||||
mock.lockDetachDocumentHooksByBranchID.RUnlock()
|
||||
return calls
|
||||
}
|
||||
|
||||
// UpdateBranchReviewer calls UpdateBranchReviewerFunc.
|
||||
func (mock *TxMock) UpdateBranchReviewer(ctx context.Context, reviewer documentCore.BranchReviewer) error {
|
||||
callInfo := struct {
|
||||
|
|
|
|||
|
|
@ -236,7 +236,9 @@ func (mock *DBMock) AssignBranchTag(ctx context.Context, organizationID string,
|
|||
mock.calls.AssignBranchTag = append(mock.calls.AssignBranchTag, callInfo)
|
||||
mock.lockAssignBranchTag.Unlock()
|
||||
if mock.AssignBranchTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.AssignBranchTagFunc(ctx, organizationID, documentID, branchID, tagID)
|
||||
|
|
@ -593,7 +595,9 @@ func (mock *DBMock) InsertTag(ctx context.Context, t tag.Tag) error {
|
|||
mock.calls.InsertTag = append(mock.calls.InsertTag, callInfo)
|
||||
mock.lockInsertTag.Unlock()
|
||||
if mock.InsertTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.InsertTagFunc(ctx, t)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ var _ SearchTrigger = &SearchTriggerMock{}
|
|||
//
|
||||
// // make and configure a mocked SearchTrigger
|
||||
// mockedSearchTrigger := &SearchTriggerMock{
|
||||
// TriggerFunc: func() {
|
||||
// TriggerFunc: func() {
|
||||
// panic("mock out the Trigger method")
|
||||
// },
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -242,7 +242,9 @@ func (mock *TxMock) AssignBranchTag(ctx context.Context, organizationID string,
|
|||
mock.calls.AssignBranchTag = append(mock.calls.AssignBranchTag, callInfo)
|
||||
mock.lockAssignBranchTag.Unlock()
|
||||
if mock.AssignBranchTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.AssignBranchTagFunc(ctx, organizationID, documentID, branchID, tagID)
|
||||
|
|
@ -590,7 +592,9 @@ func (mock *TxMock) InsertTag(ctx context.Context, t tag.Tag) error {
|
|||
mock.calls.InsertTag = append(mock.calls.InsertTag, callInfo)
|
||||
mock.lockInsertTag.Unlock()
|
||||
if mock.InsertTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.InsertTagFunc(ctx, t)
|
||||
|
|
|
|||
|
|
@ -192,7 +192,9 @@ func (mock *DBMock) AssignBranchTag(ctx context.Context, organizationID string,
|
|||
mock.calls.AssignBranchTag = append(mock.calls.AssignBranchTag, callInfo)
|
||||
mock.lockAssignBranchTag.Unlock()
|
||||
if mock.AssignBranchTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.AssignBranchTagFunc(ctx, organizationID, documentID, branchID, tagID)
|
||||
|
|
@ -237,7 +239,9 @@ func (mock *DBMock) DeleteTag(ctx context.Context, id xid.ID, organizationID str
|
|||
mock.calls.DeleteTag = append(mock.calls.DeleteTag, callInfo)
|
||||
mock.lockDeleteTag.Unlock()
|
||||
if mock.DeleteTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.DeleteTagFunc(ctx, id, organizationID)
|
||||
|
|
@ -281,10 +285,10 @@ func (mock *DBMock) FetchBranchTagIDs(ctx context.Context, organizationID string
|
|||
mock.lockFetchBranchTagIDs.Unlock()
|
||||
if mock.FetchBranchTagIDsFunc == nil {
|
||||
var (
|
||||
idsOut []xid.ID
|
||||
iDsOut []xid.ID
|
||||
errOut error
|
||||
)
|
||||
return idsOut, errOut
|
||||
return iDsOut, errOut
|
||||
}
|
||||
return mock.FetchBranchTagIDsFunc(ctx, organizationID, documentID, branchID)
|
||||
}
|
||||
|
|
@ -368,7 +372,9 @@ func (mock *DBMock) InsertTag(ctx context.Context, t tagCore.Tag) error {
|
|||
mock.calls.InsertTag = append(mock.calls.InsertTag, callInfo)
|
||||
mock.lockInsertTag.Unlock()
|
||||
if mock.InsertTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.InsertTagFunc(ctx, t)
|
||||
|
|
@ -411,7 +417,9 @@ func (mock *DBMock) SetTagVisibility(ctx context.Context, organizationID string,
|
|||
mock.calls.SetTagVisibility = append(mock.calls.SetTagVisibility, callInfo)
|
||||
mock.lockSetTagVisibility.Unlock()
|
||||
if mock.SetTagVisibilityFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.SetTagVisibilityFunc(ctx, organizationID, userID, id, inp)
|
||||
|
|
@ -460,7 +468,9 @@ func (mock *DBMock) UnassignBranchTag(ctx context.Context, organizationID string
|
|||
mock.calls.UnassignBranchTag = append(mock.calls.UnassignBranchTag, callInfo)
|
||||
mock.lockUnassignBranchTag.Unlock()
|
||||
if mock.UnassignBranchTagFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.UnassignBranchTagFunc(ctx, organizationID, documentID, branchID, tagID)
|
||||
|
|
@ -505,7 +515,9 @@ func (mock *DBMock) UpdateTagTree(ctx context.Context, tree tagCore.Summaries, o
|
|||
mock.calls.UpdateTagTree = append(mock.calls.UpdateTagTree, callInfo)
|
||||
mock.lockUpdateTagTree.Unlock()
|
||||
if mock.UpdateTagTreeFunc == nil {
|
||||
var errOut error
|
||||
var (
|
||||
errOut error
|
||||
)
|
||||
return errOut
|
||||
}
|
||||
return mock.UpdateTagTreeFunc(ctx, tree, organizationID)
|
||||
|
|
|
|||
|
|
@ -313,8 +313,65 @@ describe("<MetricMainBlock>", { concurrent: false }, () => {
|
|||
)
|
||||
await nextTick()
|
||||
|
||||
expect(updateAttributes).toHaveBeenCalledTimes(1)
|
||||
expect(updateAttributes).toHaveBeenCalledWith({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: true,
|
||||
})
|
||||
})
|
||||
|
||||
// only the server switches the flag off. An edit that neither starts
|
||||
// nor stops the simulation does not send it
|
||||
it("changes only the preset of a block that is simulating", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const updateAttributes = vi.fn()
|
||||
const uid = nextUid()
|
||||
await mountBlock({
|
||||
uid: uid,
|
||||
updateAttributes: updateAttributes,
|
||||
attrs: {
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
},
|
||||
underTooltipProvider: true,
|
||||
})
|
||||
|
||||
const config = storedConfig(uid)
|
||||
if (config) {
|
||||
config.simulationPreset = MetricSimulationPreset.DiskUsage
|
||||
}
|
||||
|
||||
expect(updateAttributes).toHaveBeenCalledTimes(1)
|
||||
expect(updateAttributes).toHaveBeenCalledWith({
|
||||
simulationPreset: MetricSimulationPreset.DiskUsage,
|
||||
})
|
||||
})
|
||||
|
||||
it("stops a simulation by unsetting the preset and the flag together", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const updateAttributes = vi.fn()
|
||||
const uid = nextUid()
|
||||
await mountBlock({
|
||||
uid: uid,
|
||||
updateAttributes: updateAttributes,
|
||||
attrs: {
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
},
|
||||
underTooltipProvider: true,
|
||||
})
|
||||
|
||||
const config = storedConfig(uid)
|
||||
if (config) {
|
||||
config.simulationPreset = null
|
||||
}
|
||||
|
||||
expect(updateAttributes).toHaveBeenCalledTimes(1)
|
||||
expect(updateAttributes).toHaveBeenCalledWith({
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -325,13 +382,30 @@ describe("<MetricMainBlock>", { concurrent: false }, () => {
|
|||
|
||||
await mountBlock({
|
||||
uid: uid,
|
||||
attrs: { simulationPreset: MetricSimulationPreset.DiskUsage },
|
||||
attrs: {
|
||||
simulationPreset: MetricSimulationPreset.DiskUsage,
|
||||
simulationActive: true,
|
||||
},
|
||||
underTooltipProvider: true,
|
||||
})
|
||||
|
||||
expect(storedConfig(uid)?.simulationPreset).toBe(
|
||||
MetricSimulationPreset.DiskUsage,
|
||||
)
|
||||
expect(storedConfig(uid)?.simulationActive).toBe(true)
|
||||
})
|
||||
|
||||
it("reads a block without a simulation flag as not simulating", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const uid = nextUid()
|
||||
|
||||
await mountBlock({
|
||||
uid: uid,
|
||||
attrs: { simulationPreset: MetricSimulationPreset.DiskUsage },
|
||||
})
|
||||
|
||||
expect(storedConfig(uid)?.simulationActive).toBe(false)
|
||||
})
|
||||
|
||||
it("shows the simulation icon while the visualization simulates", async ({
|
||||
|
|
@ -384,6 +458,8 @@ describe("<MetricMainBlock>", { concurrent: false }, () => {
|
|||
dataSourceId: "ds-1",
|
||||
visualizationType: GenericQueryChartType.Gauge,
|
||||
unitCustom: "req/s",
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
config: null,
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ function migrateLegacyIfNeeded(fieldAttrs: Record<string, any>) {
|
|||
axisBoundsMin: legacy.axisBounds?.min ?? null,
|
||||
axisBoundsMax: legacy.axisBounds?.max ?? null,
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
// overlay caller's edit and clear legacy blob
|
||||
...fieldAttrs,
|
||||
config: null,
|
||||
|
|
@ -231,9 +232,27 @@ const config = reactive({
|
|||
(props.node.attrs.simulationPreset as MetricConfig["simulationPreset"]) ??
|
||||
null,
|
||||
set: (v) => {
|
||||
migrateLegacyIfNeeded({ simulationPreset: v })
|
||||
if (v === null) {
|
||||
migrateLegacyIfNeeded({
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (props.node.attrs.simulationActive === true) {
|
||||
migrateLegacyIfNeeded({ simulationPreset: v })
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
migrateLegacyIfNeeded({ simulationPreset: v, simulationActive: true })
|
||||
},
|
||||
}),
|
||||
simulationActive: computed<MetricConfig["simulationActive"]>(
|
||||
() => props.node.attrs.simulationActive === true,
|
||||
),
|
||||
})
|
||||
|
||||
const otherEditingUsers = editingUsersRef(() => props.node.attrs.uid as string)
|
||||
|
|
|
|||
|
|
@ -433,13 +433,72 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
])
|
||||
})
|
||||
|
||||
it("asks for the preset the block kept from its last simulation", async ({
|
||||
expect,
|
||||
}) => {
|
||||
mockEndpoint("GET", QUERY_URL, () => ({
|
||||
status: GenericQueryResultStatus.NoData,
|
||||
data: [],
|
||||
}))
|
||||
|
||||
const wrapper = await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.ErrorRate }),
|
||||
)
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(wrapper.text()).toContain(
|
||||
t("editor.metrics.status.no-data-loaded.simulate-action-button"),
|
||||
)
|
||||
}, WAIT_FOR_OPTIONS)
|
||||
await findButtonByText(
|
||||
wrapper,
|
||||
t("editor.metrics.status.no-data-loaded.simulate-action-button"),
|
||||
).trigger("click")
|
||||
|
||||
expect(wrapper.emitted("simulate")).toEqual([
|
||||
[MetricSimulationPreset.ErrorRate],
|
||||
])
|
||||
})
|
||||
|
||||
// the preset stays after the simulation ends, so a preset alone does
|
||||
// not mean the block simulates
|
||||
it("queries like any block once its simulation is switched off", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const uid = nextUid()
|
||||
const checks = mockEndpoint("POST", simulationCheckURL(uid), () => ({
|
||||
cleared: false,
|
||||
}))
|
||||
const calls = mockEndpoint("GET", QUERY_URL, () => seriesResult())
|
||||
|
||||
const wrapper = await mountContainer(
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: false,
|
||||
}),
|
||||
{ uid: uid },
|
||||
)
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(
|
||||
wrapper.findComponent({ name: "LineChart" }).props("seriesData"),
|
||||
).toHaveLength(1)
|
||||
}, WAIT_FOR_OPTIONS)
|
||||
expect(calls.length).toBeGreaterThan(0)
|
||||
expect(simulationVisible(wrapper)).toBe(false)
|
||||
expect(checks).toHaveLength(0)
|
||||
})
|
||||
|
||||
it("draws generated data without querying the data source", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const calls = mockEndpoint("GET", QUERY_URL, () => seriesResult())
|
||||
|
||||
const wrapper = await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.HTTPLatency }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
expect(chartNames(wrapper)).toEqual(["LineChart"])
|
||||
|
|
@ -485,6 +544,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
const wrapper = await mountContainer(
|
||||
metricConfig({
|
||||
simulationPreset: "pie_of_the_day" as MetricSimulationPreset,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -510,6 +570,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
const wrapper = await mountContainer(
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -526,7 +587,10 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
mockEndpoint("GET", QUERY_URL, () => seriesResult())
|
||||
|
||||
const wrapper = await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.CPUUsage }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
expect(simulationVisible(wrapper)).toBe(true)
|
||||
|
|
@ -539,6 +603,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
metricConfig({
|
||||
timeRange: TimeRangePreset.Last15Minutes,
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -570,6 +635,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
metricConfig({
|
||||
visualizationType: type,
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
|
|
@ -582,7 +648,10 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
mockEndpoint("GET", QUERY_URL, () => seriesResult())
|
||||
|
||||
const wrapper = await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.CPUUsage }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
)
|
||||
|
||||
expect(simulationVisible(wrapper)).toBe(true)
|
||||
|
|
@ -604,7 +673,10 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
mockEndpoint("GET", QUERY_URL, () => seriesResult())
|
||||
|
||||
await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.CPUUsage }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
{ uid: uid },
|
||||
)
|
||||
|
||||
|
|
@ -627,6 +699,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
metricConfig({
|
||||
refreshInterval: RefreshInterval.D1,
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
{ uid: uid },
|
||||
)
|
||||
|
|
@ -649,7 +722,10 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
useEditorStore().updateActiveBranchId(null)
|
||||
|
||||
await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.CPUUsage }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
{ uid: uid },
|
||||
)
|
||||
|
||||
|
|
@ -669,7 +745,10 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
}))
|
||||
|
||||
await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.CPUUsage }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
{ uid: uid, disableRefresh: true },
|
||||
)
|
||||
|
||||
|
|
@ -692,12 +771,13 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
})
|
||||
const config = metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: true,
|
||||
})
|
||||
|
||||
const wrapper = await mountContainer(config)
|
||||
|
||||
await wrapper.setProps({
|
||||
config: { ...config, simulationPreset: null },
|
||||
config: { ...config, simulationActive: false },
|
||||
})
|
||||
await nextTick()
|
||||
|
||||
|
|
@ -732,12 +812,13 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
{ name: "Query 2", query: "", legendFormat: "" },
|
||||
],
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
})
|
||||
|
||||
const wrapper = await mountContainer(config)
|
||||
|
||||
await wrapper.setProps({
|
||||
config: { ...config, simulationPreset: null },
|
||||
config: { ...config, simulationActive: false },
|
||||
})
|
||||
await nextTick()
|
||||
|
||||
|
|
@ -777,12 +858,13 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
config: {
|
||||
...config,
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
},
|
||||
})
|
||||
await nextTick()
|
||||
|
||||
await wrapper.setProps({
|
||||
config: { ...config, simulationPreset: null },
|
||||
config: { ...config, simulationActive: false },
|
||||
})
|
||||
|
||||
await vi.waitFor(() => {
|
||||
|
|
@ -799,6 +881,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
const calls = mockEndpoint("GET", QUERY_URL, () => seriesResult())
|
||||
const config = metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
})
|
||||
|
||||
const wrapper = await mountContainer(config, { uid: uid })
|
||||
|
|
@ -808,7 +891,7 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
// core removes the attribute on the live document, which reaches
|
||||
// the editor as a node attribute change
|
||||
await wrapper.setProps({
|
||||
config: { ...config, simulationPreset: null },
|
||||
config: { ...config, simulationActive: false },
|
||||
})
|
||||
|
||||
await vi.waitFor(() => {
|
||||
|
|
@ -826,7 +909,10 @@ describe("<VisualizationContainer>", { concurrent: false }, () => {
|
|||
})
|
||||
|
||||
const wrapper = await mountContainer(
|
||||
metricConfig({ simulationPreset: MetricSimulationPreset.CPUUsage }),
|
||||
metricConfig({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
{ uid: uid },
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -58,12 +58,17 @@ const dataSourceUnavailable = computed(() => {
|
|||
return !!dataSource && dataSource.status !== DataSourceStatus.Success
|
||||
})
|
||||
|
||||
// an unknown preset reads as "not simulating", so a block carrying one
|
||||
// falls back to querying instead of breaking the render for every viewer
|
||||
// the preset the block is drawing, null when it queries instead. An
|
||||
// unknown preset reads as "not simulating", so a block carrying one falls
|
||||
// back to querying instead of breaking the render for every viewer
|
||||
const simulationPreset = computed(() => {
|
||||
const preset: unknown = props.config.simulationPreset
|
||||
|
||||
if (dataSourceUnavailable.value || !isSimulationPreset(preset)) {
|
||||
if (
|
||||
!props.config.simulationActive ||
|
||||
dataSourceUnavailable.value ||
|
||||
!isSimulationPreset(preset)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
@ -418,7 +423,9 @@ async function checkSimulation() {
|
|||
}
|
||||
|
||||
function startSimulation() {
|
||||
emit("simulate", DEFAULT_SIMULATION_PRESET)
|
||||
const kept: unknown = props.config.simulationPreset
|
||||
|
||||
emit("simulate", isSimulationPreset(kept) ? kept : DEFAULT_SIMULATION_PRESET)
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
|
|
|
|||
|
|
@ -521,12 +521,27 @@ describe("<ConfigSidebar>", { concurrent: false }, () => {
|
|||
expect(wrapper.findComponent(SimulationPresetSelect).exists()).toBe(false)
|
||||
})
|
||||
|
||||
it("stays hidden once the real data has arrived", async ({ expect }) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: false,
|
||||
}),
|
||||
})
|
||||
|
||||
expect(wrapper.text()).not.toContain(
|
||||
t("editor.metrics.simulation.section-title"),
|
||||
)
|
||||
expect(wrapper.findComponent(SimulationPresetSelect).exists()).toBe(false)
|
||||
})
|
||||
|
||||
it("explains the simulation and shows the chart it draws", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: true,
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
@ -544,6 +559,7 @@ describe("<ConfigSidebar>", { concurrent: false }, () => {
|
|||
it("switches the block to another preset", async ({ expect }) => {
|
||||
const config = configWith({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
})
|
||||
const wrapper = await mountSidebar({ modelValue: config })
|
||||
|
||||
|
|
@ -561,6 +577,7 @@ describe("<ConfigSidebar>", { concurrent: false }, () => {
|
|||
it("turns the simulation off again", async ({ expect }) => {
|
||||
const config = configWith({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
})
|
||||
const wrapper = await mountSidebar({ modelValue: config })
|
||||
|
||||
|
|
@ -572,12 +589,133 @@ describe("<ConfigSidebar>", { concurrent: false }, () => {
|
|||
expect(config.simulationPreset).toBeNull()
|
||||
})
|
||||
|
||||
// a diff compares what each side chose. It shows the preset even
|
||||
// when the simulation is already off
|
||||
it("shows the preset a diff replaced beside the new one", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
simulationPreset: MetricSimulationPreset.DiskUsage,
|
||||
simulationActive: false,
|
||||
}),
|
||||
diffStatus: DiffStatus.Modified,
|
||||
oldConfig: configWith({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: false,
|
||||
}),
|
||||
})
|
||||
|
||||
const selects = wrapper.findAllComponents(SimulationPresetSelect)
|
||||
|
||||
expect(selects).toHaveLength(2)
|
||||
expect(at(selects, 0).text()).toContain(
|
||||
t("editor.metrics.simulation.preset-options.disk_usage"),
|
||||
)
|
||||
expect(at(selects, 0).find("button").classes()).toContain(
|
||||
"bg-diff-field-added",
|
||||
)
|
||||
expect(at(selects, 1).text()).toContain(
|
||||
t("editor.metrics.simulation.preset-options.cpu_usage"),
|
||||
)
|
||||
expect(at(selects, 1).find("button").classes()).toContain(
|
||||
"bg-diff-field-removed",
|
||||
)
|
||||
})
|
||||
|
||||
it("shows only the new side of a preset a diff added", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
simulationPreset: MetricSimulationPreset.DiskUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
diffStatus: DiffStatus.Modified,
|
||||
oldConfig: configWith(),
|
||||
})
|
||||
|
||||
const selects = wrapper.findAllComponents(SimulationPresetSelect)
|
||||
|
||||
expect(selects).toHaveLength(1)
|
||||
expect(at(selects, 0).find("button").classes()).toContain(
|
||||
"bg-diff-field-added",
|
||||
)
|
||||
})
|
||||
|
||||
it("shows only the old side of a preset a diff removed", async ({
|
||||
expect,
|
||||
}) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith(),
|
||||
diffStatus: DiffStatus.Modified,
|
||||
oldConfig: configWith({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
})
|
||||
|
||||
const selects = wrapper.findAllComponents(SimulationPresetSelect)
|
||||
|
||||
expect(wrapper.text()).toContain(
|
||||
t("editor.metrics.simulation.section-title"),
|
||||
)
|
||||
expect(selects).toHaveLength(1)
|
||||
expect(at(selects, 0).text()).toContain(
|
||||
t("editor.metrics.simulation.preset-options.cpu_usage"),
|
||||
)
|
||||
expect(at(selects, 0).find("button").classes()).toContain(
|
||||
"bg-diff-field-removed",
|
||||
)
|
||||
})
|
||||
|
||||
it("leaves a preset both sides share unmarked", async ({ expect }) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
title: "After",
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: false,
|
||||
}),
|
||||
diffStatus: DiffStatus.Modified,
|
||||
oldConfig: configWith({
|
||||
title: "Before",
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
})
|
||||
|
||||
const selects = wrapper.findAllComponents(SimulationPresetSelect)
|
||||
|
||||
expect(selects).toHaveLength(1)
|
||||
expect(at(selects, 0).find("button").classes()).not.toContain(
|
||||
"bg-diff-field-added",
|
||||
)
|
||||
})
|
||||
|
||||
it("does not offer the switch-off button in a diff", async ({ expect }) => {
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
diffStatus: DiffStatus.Unchanged,
|
||||
})
|
||||
|
||||
expect(wrapper.text()).toContain(
|
||||
t("editor.metrics.simulation.section-title"),
|
||||
)
|
||||
expect(wrapper.text()).not.toContain(
|
||||
t("editor.metrics.simulation.stop-button"),
|
||||
)
|
||||
})
|
||||
|
||||
it("does not offer a reader the switch-off button", async ({ expect }) => {
|
||||
useEditorMeta().setEditable(false)
|
||||
|
||||
const wrapper = await mountSidebar({
|
||||
modelValue: configWith({
|
||||
simulationPreset: MetricSimulationPreset.CPUUsage,
|
||||
simulationActive: true,
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,24 @@ const isBoundsMaxModified = computed(() => {
|
|||
props.oldConfig.axisBounds.max !== config.value.axisBounds.max
|
||||
)
|
||||
})
|
||||
const isSimulationPresetModified = computed(() => {
|
||||
return (
|
||||
isDiffModified.value &&
|
||||
!!props.oldConfig &&
|
||||
props.oldConfig.simulationPreset !== config.value.simulationPreset
|
||||
)
|
||||
})
|
||||
// outside a diff the section shows only while the block simulates.
|
||||
// A diff shows it when either side has a preset.
|
||||
const isSimulationSectionVisible = computed(() => {
|
||||
if (props.diffStatus) {
|
||||
return (
|
||||
!!config.value.simulationPreset || !!props.oldConfig?.simulationPreset
|
||||
)
|
||||
}
|
||||
|
||||
return !!config.value.simulationPreset && config.value.simulationActive
|
||||
})
|
||||
|
||||
interface ThresholdEntry {
|
||||
value?: number
|
||||
|
|
@ -287,7 +305,7 @@ function removeThreshold(index: number) {
|
|||
</div>
|
||||
<div class="mt-1 h-px bg-border" />
|
||||
</div>
|
||||
<div v-if="config.simulationPreset">
|
||||
<div v-if="isSimulationSectionVisible">
|
||||
<div class="flex flex-col gap-1 px-1.75">
|
||||
<span class="text-2sm font-medium">
|
||||
{{ $t("editor.metrics.simulation.section-title") }}
|
||||
|
|
@ -301,10 +319,21 @@ function removeThreshold(index: number) {
|
|||
{{ $t("editor.metrics.simulation.preset-label") }}
|
||||
</span>
|
||||
</template>
|
||||
<SimulationPresetSelect v-model="config.simulationPreset" />
|
||||
<SimulationPresetSelect
|
||||
v-if="config.simulationPreset"
|
||||
v-model="config.simulationPreset"
|
||||
:diff-status="isSimulationPresetModified ? DiffStatus.Added : null"
|
||||
/>
|
||||
<SimulationPresetSelect
|
||||
v-if="
|
||||
isSimulationPresetModified && props.oldConfig?.simulationPreset
|
||||
"
|
||||
:model-value="props.oldConfig.simulationPreset"
|
||||
:diff-status="DiffStatus.Removed"
|
||||
/>
|
||||
</ConfigField>
|
||||
<ShadcnUiButton
|
||||
v-if="!isEditingDisabled"
|
||||
v-if="!isEditingDisabled && !props.diffStatus"
|
||||
variant="outline-transparent"
|
||||
size="custom"
|
||||
class="h-[1.775rem]! justify-center px-1.5 text-2sm font-normal"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
<script lang="ts" setup>
|
||||
import { cn } from "~/lib/utils"
|
||||
import { MetricSimulationPreset } from "../utils"
|
||||
import { DiffStatus } from "~/components/editor/diff/position-map"
|
||||
|
||||
const selectedPreset = defineModel<MetricSimulationPreset | null>()
|
||||
const props = defineProps<{
|
||||
diffStatus?: DiffStatus | null
|
||||
}>()
|
||||
const { isEditable } = useEditorMeta()
|
||||
const editorStore = useEditorStore()
|
||||
|
||||
|
|
@ -26,6 +30,8 @@ function selectPreset(preset: MetricSimulationPreset) {
|
|||
cn(
|
||||
'h-[1.775rem]! justify-between gap-1 px-1.5 text-2sm font-normal opacity-100!',
|
||||
isEditingDisabled && 'pointer-events-none select-text',
|
||||
props.diffStatus === DiffStatus.Added && 'bg-diff-field-added',
|
||||
props.diffStatus === DiffStatus.Removed && 'bg-diff-field-removed',
|
||||
)
|
||||
"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -238,6 +238,7 @@ describe("MetricBlock", () => {
|
|||
axisBoundsMin: null,
|
||||
axisBoundsMax: null,
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
width: MetricBlockWidth.Standard,
|
||||
})
|
||||
})
|
||||
|
|
@ -274,6 +275,10 @@ describe("MetricBlock", () => {
|
|||
widthAttribute().renderHTML?.({ width: MetricBlockWidth.Compact }),
|
||||
).toEqual({ "data-width": MetricBlockWidth.Compact })
|
||||
})
|
||||
|
||||
it("keeps the simulation flag out of the rendered HTML", ({ expect }) => {
|
||||
expect(metricAttributes().simulationActive?.rendered).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("insertMetricBlock", () => {
|
||||
|
|
@ -332,42 +337,6 @@ describe("MetricBlock", () => {
|
|||
})
|
||||
})
|
||||
|
||||
// the width attribute owns the only parse/render pair among the block
|
||||
// attributes, so the tests reach it through the declaration
|
||||
function widthAttribute() {
|
||||
const addAttributes = MetricBlock.config.addAttributes
|
||||
|
||||
if (!addAttributes) {
|
||||
throw new Error("MetricBlock declares no attributes")
|
||||
}
|
||||
|
||||
const attributes = addAttributes.call({} as never) as Record<
|
||||
string,
|
||||
{
|
||||
parseHTML?: (element: HTMLElement) => unknown
|
||||
renderHTML?: (attributes: Record<string, unknown>) => unknown
|
||||
}
|
||||
>
|
||||
|
||||
const width = attributes.width
|
||||
|
||||
if (!width) {
|
||||
throw new Error("MetricBlock declares no width attribute")
|
||||
}
|
||||
|
||||
return width
|
||||
}
|
||||
|
||||
function metricBlockCommands() {
|
||||
const addCommands = MetricBlock.config.addCommands
|
||||
|
||||
if (!addCommands) {
|
||||
throw new Error("MetricBlock declares no commands")
|
||||
}
|
||||
|
||||
return addCommands.call({} as never)
|
||||
}
|
||||
|
||||
describe("setUpMetricBlock", () => {
|
||||
it("wraps the metric block in a grid at the document root", ({ expect }) => {
|
||||
const state = EditorState.create({
|
||||
|
|
@ -478,3 +447,42 @@ describe("insertMetricBlock", () => {
|
|||
])
|
||||
})
|
||||
})
|
||||
|
||||
// how an attribute reaches HTML is only visible on its declaration, so the
|
||||
// tests read it from there
|
||||
function metricAttributes() {
|
||||
const addAttributes = MetricBlock.config.addAttributes
|
||||
|
||||
if (!addAttributes) {
|
||||
throw new Error("MetricBlock declares no attributes")
|
||||
}
|
||||
|
||||
return addAttributes.call({} as never) as Record<
|
||||
string,
|
||||
{
|
||||
rendered?: boolean
|
||||
parseHTML?: (element: HTMLElement) => unknown
|
||||
renderHTML?: (attributes: Record<string, unknown>) => unknown
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
function widthAttribute() {
|
||||
const width = metricAttributes().width
|
||||
|
||||
if (!width) {
|
||||
throw new Error("MetricBlock declares no width attribute")
|
||||
}
|
||||
|
||||
return width
|
||||
}
|
||||
|
||||
function metricBlockCommands() {
|
||||
const addCommands = MetricBlock.config.addCommands
|
||||
|
||||
if (!addCommands) {
|
||||
throw new Error("MetricBlock declares no commands")
|
||||
}
|
||||
|
||||
return addCommands.call({} as never)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,6 +114,10 @@ export const MetricBlock = Node.create({
|
|||
axisBoundsMin: { default: defaults.axisBounds.min ?? null },
|
||||
axisBoundsMax: { default: defaults.axisBounds.max ?? null },
|
||||
simulationPreset: { default: defaults.simulationPreset },
|
||||
simulationActive: {
|
||||
default: defaults.simulationActive,
|
||||
rendered: false,
|
||||
},
|
||||
width: {
|
||||
default: MetricBlockWidth.Standard,
|
||||
parseHTML: (element) =>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ export const DEFAULT_SIMULATION_PRESET = MetricSimulationPreset.CPUUsage
|
|||
// metric went live.
|
||||
export const SIMULATION_CHECK_INTERVAL_MS = 10_000
|
||||
|
||||
// the node attribute behind MetricConfig.simulationActive. The server
|
||||
// sets it, not a writer, so a branch diff leaves it out
|
||||
export const SIMULATION_ACTIVE_ATTR = "simulationActive"
|
||||
|
||||
// how many points a simulated series aims for across its time range. The
|
||||
// step derived from it is what buckets are aligned to, so a window that
|
||||
// slides forward keeps the points it already showed.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ describe("defaultMetricConfig", () => {
|
|||
unit: { type: null, custom: null },
|
||||
axisBounds: { min: null, max: null },
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -86,6 +87,7 @@ describe("buildConfigFromNodeAttrs", () => {
|
|||
unit: { type: VisualizationTimeUnit.Seconds, custom: null },
|
||||
axisBounds: { min: 0, max: 100 },
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -113,6 +115,7 @@ describe("buildConfigFromNodeAttrs", () => {
|
|||
unit: { type: null, custom: null },
|
||||
axisBounds: { min: null, max: null },
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -146,6 +149,7 @@ describe("buildConfigFromNodeAttrs", () => {
|
|||
unit: { type: VisualizationDataUnit.Megabytes, custom: "reqs" },
|
||||
axisBounds: { min: -1, max: 1 },
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -157,6 +161,27 @@ describe("buildConfigFromNodeAttrs", () => {
|
|||
).toBe(MetricSimulationPreset.HTTPLatency)
|
||||
})
|
||||
|
||||
it.for([
|
||||
{ name: "a set flag", input: true, expected: true },
|
||||
{ name: "a cleared flag", input: false, expected: false },
|
||||
{
|
||||
name: "a block saved before the flag existed",
|
||||
input: undefined,
|
||||
expected: false,
|
||||
},
|
||||
{ name: "a flag that is not a boolean", input: "true", expected: false },
|
||||
])(
|
||||
"reads $name as simulating: $expected",
|
||||
({ input, expected }, { expect }) => {
|
||||
expect(
|
||||
buildConfigFromNodeAttrs({
|
||||
simulationPreset: MetricSimulationPreset.HTTPLatency,
|
||||
simulationActive: input,
|
||||
}).simulationActive,
|
||||
).toBe(expected)
|
||||
},
|
||||
)
|
||||
|
||||
it("fills defaults when there are no attributes at all", ({ expect }) => {
|
||||
expect(buildConfigFromNodeAttrs({})).toEqual({
|
||||
title: "",
|
||||
|
|
@ -171,6 +196,7 @@ describe("buildConfigFromNodeAttrs", () => {
|
|||
unit: { type: null, custom: null },
|
||||
axisBounds: { min: null, max: null },
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -106,9 +106,13 @@ export interface MetricConfig {
|
|||
min?: number | null
|
||||
max?: number | null
|
||||
}
|
||||
// non-null while the block renders generated data instead of querying
|
||||
// its data source
|
||||
// the generated series the block draws while simulationActive is set.
|
||||
// It stays after the simulation ends, so a block that simulates again
|
||||
// reuses it. Null on a block nobody has simulated
|
||||
simulationPreset: MetricSimulationPreset | null
|
||||
// true while the block renders its preset instead of querying its data
|
||||
// source. The server switches it off once real data answers
|
||||
simulationActive: boolean
|
||||
}
|
||||
|
||||
export function defaultMetricConfig(): MetricConfig {
|
||||
|
|
@ -135,6 +139,7 @@ export function defaultMetricConfig(): MetricConfig {
|
|||
max: null,
|
||||
},
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,6 +176,7 @@ export function buildConfigFromNodeAttrs(
|
|||
},
|
||||
// the legacy blob predates simulation, so it never carries one
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +204,7 @@ export function buildConfigFromNodeAttrs(
|
|||
simulationPreset:
|
||||
(attrs.simulationPreset as MetricSimulationPreset | null | undefined) ??
|
||||
null,
|
||||
simulationActive: attrs.simulationActive === true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,36 @@ describe("computeMergedDocument", () => {
|
|||
])
|
||||
})
|
||||
|
||||
it.for([
|
||||
{
|
||||
name: "a metric block whose only change is its simulation preset as modified",
|
||||
original: { simulationPreset: "cpu_usage", simulationActive: false },
|
||||
modified: { simulationPreset: "error_rate", simulationActive: false },
|
||||
expected: DiffStatus.Modified,
|
||||
},
|
||||
{
|
||||
name: "a metric block whose only change is its simulation flag as unchanged",
|
||||
original: { simulationPreset: "cpu_usage", simulationActive: true },
|
||||
modified: { simulationPreset: "cpu_usage", simulationActive: false },
|
||||
expected: DiffStatus.Unchanged,
|
||||
},
|
||||
])("marks $name", ({ original, modified, expected }) => {
|
||||
const grid = (attrs: Record<string, unknown>): JSONContent => ({
|
||||
type: "metricGrid",
|
||||
attrs: { uid: "g1" },
|
||||
content: [{ type: "metricBlock", attrs: { uid: "m1", ...attrs } }],
|
||||
})
|
||||
|
||||
const result = computeMergedDocument(
|
||||
doc(grid(original)),
|
||||
doc(grid(modified)),
|
||||
)
|
||||
|
||||
expect(result.doc.content?.[0]?.content?.[0]?.attrs?.diffStatus).toBe(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
|
||||
it("matches blocks without uids by content through the LCS fallback", () => {
|
||||
const original = doc(paragraph("same"), paragraph("gone"))
|
||||
const modified = doc(paragraph("same"), paragraph("new"))
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import Paragraph from "@tiptap/extension-paragraph"
|
|||
import HorizontalRule from "@tiptap/extension-horizontal-rule"
|
||||
import { COMMENT_MARK_NAME } from "~/components/editor/mark-names"
|
||||
import { NODE_COMMENT_ID_ATTR } from "~/components/editor/comments/node-comment-extension"
|
||||
import { SIMULATION_ACTIVE_ATTR } from "~/components/editor/blocks/metrics/simulation"
|
||||
import {
|
||||
BulletList,
|
||||
OrderedList,
|
||||
|
|
@ -56,7 +57,7 @@ export const MODIFIED_TEXT_CONTENT_TYPES = new Set<string>([MERMAID_BLOCK_NAME])
|
|||
|
||||
export const DEFAULT_MERGE_OPTIONS: MergeOptions = {
|
||||
excludeMarks: [COMMENT_MARK_NAME],
|
||||
excludeAttributes: [NODE_COMMENT_ID_ATTR],
|
||||
excludeAttributes: [NODE_COMMENT_ID_ATTR, SIMULATION_ACTIVE_ATTR],
|
||||
useUidMatching: true,
|
||||
uidAttribute: "uid",
|
||||
unwrapTypes: [
|
||||
|
|
|
|||
|
|
@ -35,6 +35,42 @@ describe("hashBlockContent", () => {
|
|||
expect(hashBlockContent(commented)).toBe(hashBlockContent(clean))
|
||||
})
|
||||
|
||||
// the server switches a simulation off on whichever branch is open.
|
||||
// That is not a user change, so the hash ignores the flag
|
||||
it("ignores a metric block's simulation flag by default", () => {
|
||||
const simulating = {
|
||||
type: "metricBlock",
|
||||
attrs: {
|
||||
uid: "m1",
|
||||
simulationPreset: "cpu_usage",
|
||||
simulationActive: true,
|
||||
},
|
||||
}
|
||||
const answered = {
|
||||
type: "metricBlock",
|
||||
attrs: {
|
||||
uid: "m1",
|
||||
simulationPreset: "cpu_usage",
|
||||
simulationActive: false,
|
||||
},
|
||||
}
|
||||
|
||||
expect(hashBlockContent(simulating)).toBe(hashBlockContent(answered))
|
||||
})
|
||||
|
||||
it("keeps a metric block's simulation preset significant", () => {
|
||||
const a = {
|
||||
type: "metricBlock",
|
||||
attrs: { uid: "m1", simulationPreset: "cpu_usage" },
|
||||
}
|
||||
const b = {
|
||||
type: "metricBlock",
|
||||
attrs: { uid: "m1", simulationPreset: "error_rate" },
|
||||
}
|
||||
|
||||
expect(hashBlockContent(a)).not.toBe(hashBlockContent(b))
|
||||
})
|
||||
|
||||
it("merges text runs split by a comment boundary", () => {
|
||||
const split = paragraph([
|
||||
text("hel", [{ type: "comment", attrs: { commentId: "c1" } }]),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { JSONContent } from "@tiptap/core"
|
||||
import { COMMENT_MARK_NAME } from "~/components/editor/mark-names"
|
||||
import { NODE_COMMENT_ID_ATTR } from "~/components/editor/comments/node-comment-extension"
|
||||
import { SIMULATION_ACTIVE_ATTR } from "~/components/editor/blocks/metrics/simulation"
|
||||
|
||||
export interface HashOptions {
|
||||
/** mark types to strip before hashing (e.g. ['comment']) */
|
||||
|
|
@ -11,7 +12,7 @@ export interface HashOptions {
|
|||
|
||||
const DEFAULT_OPTIONS: HashOptions = {
|
||||
excludeMarks: [COMMENT_MARK_NAME],
|
||||
excludeAttributes: [NODE_COMMENT_ID_ATTR],
|
||||
excludeAttributes: [NODE_COMMENT_ID_ATTR, SIMULATION_ACTIVE_ATTR],
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ function metricConfig(title: string): MetricConfig {
|
|||
unit: {},
|
||||
axisBounds: {},
|
||||
simulationPreset: null,
|
||||
simulationActive: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user