package api import ( "reflect" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // mock decorated type with capability registry type decoratedMeter struct { Meter caps map[reflect.Type]any } func (d *decoratedMeter) Capability(typ reflect.Type) (any, bool) { c, ok := d.caps[typ] return c, ok } type testMeterEnergyImpl struct{} func (t *testMeterEnergyImpl) TotalEnergy() (float64, error) { return 99.0, nil } type testMeterImpl struct{} func (t *testMeterImpl) CurrentPower() (float64, error) { return 100.0, nil } func TestCap_DirectTypeAssertion(t *testing.T) { // concrete type that directly implements MeterEnergy impl := &testMeterEnergyImpl{} me, ok := Cap[MeterEnergy](impl) require.True(t, ok) energy, err := me.TotalEnergy() assert.NoError(t, err) assert.Equal(t, 99.0, energy) } func TestCap_CapableRegistryLookup(t *testing.T) { base := &testMeterImpl{} decorated := &decoratedMeter{ Meter: base, caps: map[reflect.Type]any{ reflect.TypeFor[MeterEnergy](): &testMeterEnergyImpl{}, }, } // should find MeterEnergy via registry me, ok := Cap[MeterEnergy](decorated) require.True(t, ok) energy, err := me.TotalEnergy() assert.NoError(t, err) assert.Equal(t, 99.0, energy) // should NOT find PhaseCurrents (not registered) _, ok = Cap[PhaseCurrents](decorated) assert.False(t, ok) } func TestCap_NilValue(t *testing.T) { _, ok := Cap[MeterEnergy](nil) assert.False(t, ok) } func TestCap_DirectTakesPrecedence(t *testing.T) { // type that both directly implements AND has registry type directAndCapable struct { testMeterEnergyImpl caps map[reflect.Type]any //nolint:unused } v := &directAndCapable{} me, ok := Cap[MeterEnergy](v) require.True(t, ok) energy, err := me.TotalEnergy() assert.NoError(t, err) assert.Equal(t, 99.0, energy) }