소스 검색

Spruce up transition tests

Christopher Mullins 6 년 전
부모
커밋
962c896f8c
1개의 변경된 파일163개의 추가작업 그리고 49개의 파일을 삭제
  1. 163 49
      test/remote/spec/transition_spec.rb

+ 163 - 49
test/remote/spec/transition_spec.rb

@@ -124,8 +124,10 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
+      expected_updates = calculate_transition_steps(start_value: 0, end_value: 255, duration: 2000)
+
       expect(last_value).to eq(255)
-      expect(seen_updates).to eq(8) # duration of 2000ms / 300ms period + 1 for initial packet
+      expect(seen_updates).to eq(expected_updates.length)
     end
 
     it 'should transition a field downwards' do
@@ -148,8 +150,10 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
+      expected_updates = calculate_transition_steps(start_value: 0, end_value: 255, duration: 2000)
+
       expect(last_value).to eq(0)
-      expect(seen_updates).to eq(8) # duration of 2000ms / 300ms period + 1 for initial packet
+      expect(seen_updates).to eq(expected_updates.length) # duration of 2000ms / 450ms period + 1 for initial packet
     end
 
     it 'should transition two fields at once if received in the same command' do
@@ -170,10 +174,12 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
+      expected_updates = calculate_transition_steps(start_value: 0, end_value: 250, duration: 2000)
+
       expect(updates['hue'].last).to eq(250)
       expect(updates['brightness'].last).to eq(0)
       expect(updates['hue'].length == updates['brightness'].length).to eq(true), "Should have the same number of updates for both fields"
-      expect(updates['hue'].length).to eq(8)
+      expect(updates['hue'].length).to eq(expected_updates.length)
     end
   end
 
@@ -205,7 +211,14 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
-      expect(seen_updates.map { |x| x['brightness'] }).to eq([0, 64, 128, 191, 255])
+      expected_updates = calculate_transition_steps(start_value: 0, end_value: 255, period: 500, duration: 2000)
+
+      transitions_are_equal(
+        expected: expected_updates,
+        seen: seen_updates.map { |x| x['brightness'] },
+        # Allow some variation for the lossy level -> brightness conversion
+        allowed_variation: 2
+      )
       expect((Time.now - start_time)/4).to be >= 0.5 # Don't count the first update
     end
 
@@ -248,7 +261,12 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
-      expect(seen_updates.map { |x| x['brightness'] }).to eq([0, 64, 128, 191, 255])
+      transitions_are_equal(
+        expected: calculate_transition_steps(start_value: 0, end_value: 255, duration: 2000, period: 500),
+        seen: seen_updates.map { |x| x['brightness'] },
+        # Allow some variation for the lossy level -> brightness conversion
+        allowed_variation: 2
+      )
     end
   end
 
@@ -270,7 +288,12 @@ RSpec.describe 'Transitions' do
       @mqtt_client.wait_for_listeners
 
       expect(seen_updates['state']).to eq(['ON'])
-      expect(seen_updates['brightness']).to eq([0, 64, 128, 191, 255])
+      transitions_are_equal(
+        expected: calculate_transition_steps(start_value: 0, end_value: 255, duration: 1000),
+        seen: seen_updates['brightness'],
+        # Allow some variation for the lossy level -> brightness conversion
+        allowed_variation: 3
+      )
     end
 
     it 'should transition from on -> off' do
@@ -290,7 +313,12 @@ RSpec.describe 'Transitions' do
       @mqtt_client.wait_for_listeners
 
       expect(seen_updates['state']).to eq(['OFF'])
-      expect(seen_updates['brightness']).to eq([255, 191, 128, 64, 0])
+      transitions_are_equal(
+        expected: calculate_transition_steps(start_value: 255, end_value: 0, duration: 1000),
+        seen: seen_updates['brightness'],
+        # Allow some variation for the lossy level -> brightness conversion
+        allowed_variation: 3
+      )
     end
 
     it 'should transition from off -> on with known last brightness' do
@@ -310,7 +338,12 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
-      expect(seen_updates['brightness']).to eq([99, 140, 181, 222, 255])
+      transitions_are_equal(
+        expected: calculate_transition_steps(start_value: 99, end_value: 255, duration: 1000),
+        seen: seen_updates['brightness'],
+        # Allow some variation for the lossy level -> brightness conversion
+        allowed_variation: 4
+      )
     end
 
     it 'should transition from on -> off with known last brightness' do
@@ -329,7 +362,12 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
-      expect(seen_updates['brightness']).to eq([99, 74, 48, 23, 0])
+      transitions_are_equal(
+        expected: calculate_transition_steps(start_value: 99, end_value: 0, duration: 1000),
+        seen: seen_updates['brightness'],
+        # Allow some variation for the lossy level -> brightness conversion
+        allowed_variation: 3
+      )
     end
   end
 
@@ -361,8 +399,11 @@ RSpec.describe 'Transitions' do
 
         @mqtt_client.wait_for_listeners
 
-        expect(seen_updates.length).to eq(5)
-        expect(seen_updates.last[update_field]).to eq(update_max)
+        transitions_are_equal(
+          expected: calculate_transition_steps(start_value: update_min, end_value: update_max, duration: 1000),
+          seen: seen_updates.map{ |x| x[update_field] },
+          allowed_variation: 3
+        )
       end
 
       it "should support field '#{field}' max --> min" do
@@ -379,8 +420,11 @@ RSpec.describe 'Transitions' do
 
         @mqtt_client.wait_for_listeners
 
-        expect(seen_updates.length).to eq(5)
-        expect(seen_updates.last[update_field]).to eq(update_min)
+        transitions_are_equal(
+          expected: calculate_transition_steps(start_value: update_max, end_value: update_min, duration: 1000),
+          seen: seen_updates.map{ |x| x[update_field] },
+          allowed_variation: 3
+        )
       end
     end
   end
@@ -400,17 +444,26 @@ RSpec.describe 'Transitions' do
     it 'should smoothly transition from one color to another' do
       seen_updates = []
 
-      fields = @client.get('/settings')['group_state_fields']
-      @client.put(
-        '/settings',
-        group_state_fields: fields + %w(oh_color),
-        mqtt_state_rate_limit: 1000
-      )
+      end_color = '0,255,0'
+      end_hs = rgb_to_hs(end_color)
+
+      last_hue = nil
+      last_sat = nil
+
+      @mqtt_client.on_update(@id_params) do |id, message|
+        field, value = message.first
+
+        if field == 'hue'
+          last_hue = value
+        elsif field == 'saturation'
+          last_sat = value
+        end
 
-      @mqtt_client.on_state(@id_params) do |id, message|
-        color = message['color']
-        seen_updates << color
-        color == '0,255,0'
+        if !last_hue.nil? && !last_sat.nil?
+          seen_updates << {hue: last_hue, saturation: last_sat}
+        end
+
+        last_hue == end_hs[:hue] && last_sat == end_hs[:saturation]
       end
 
       response = @client.schedule_transition(@id_params, {
@@ -423,9 +476,7 @@ RSpec.describe 'Transitions' do
 
       @mqtt_client.wait_for_listeners
 
-      parts = seen_updates.map { |x| x.split(',').map(&:to_i) }
-
-      # This is less even than you'd expect because RGB -> Hue/Sat is lossy.
+      # This ends up being less even than you'd expect because RGB -> Hue/Sat is lossy.
       # Raw logs show that the right thing is happening:
       #
       #     >>> stepSizes = (-64,64,0)
@@ -435,42 +486,105 @@ RSpec.describe 'Transitions' do
       #     >>> current color = (127,128,0)
       #     >>> current color = (63,192,0)
       #     >>> current color = (0,255,0)
-      expect(parts).to eq([
-        [255, 0, 0],
-        [255, 84, 0],
-        [250, 255, 0],
-        [84, 255, 0],
-        [0, 255, 0]
-      ])
+      expected_updates = calculate_color_transition_steps(start_color: '255,0,0', end_color: '0,255,0', duration: 4000, period: 1000)
+
+      color_transitions_are_equal(
+        expected: expected_updates,
+        seen: seen_updates
+      )
     end
 
     it 'should handle color transitions from known state' do
       seen_updates = []
 
-      fields = @client.get('/settings')['group_state_fields']
-      @client.put(
-        '/settings',
-        group_state_fields: fields + %w(oh_color),
-        mqtt_state_rate_limit: 1000
-      )
       @client.patch_state({status: 'ON', color: '255,0,0'}, @id_params)
+      end_color = '0,0,255'
+      end_hs = rgb_to_hs(end_color)
+
+      last_hue = nil
+      last_sat = nil
 
-      @mqtt_client.on_state(@id_params) do |id, message|
-        color = message['color']
-        seen_updates << color if color
-        color == '0,0,255'
+      @mqtt_client.on_update(@id_params) do |id, message|
+        field, value = message.first
+
+        if field == 'hue'
+          last_hue = value
+        elsif field == 'saturation'
+          last_sat = value
+        end
+
+        if !last_hue.nil? && !last_sat.nil?
+          seen_updates << {hue: last_hue, saturation: last_sat}
+        end
+
+        last_hue == end_hs[:hue] && last_sat == end_hs[:saturation]
       end
 
       @client.patch_state({color: '0,0,255', transition: 2.0}, @id_params)
+
       @mqtt_client.wait_for_listeners
 
-      parts = seen_updates.map { |x| x.split(',').map(&:to_i) }
+      expected_updates = calculate_color_transition_steps(start_color: '255,0,0', end_color: '0,0,255', duration: 2000)
+
+      color_transitions_are_equal(
+        expected: expected_updates,
+        seen: seen_updates
+      )
+    end
+  end
+
+  context 'computed parameters' do
+    # it 'should accept no length parameters' do
+    #   result = @client.schedule_transition(@id_params, field: 'kelvin', end_value: 100)
+
+    #   puts @transition_defaults
+
+    #   expect(result).to eq({'success' => true})
+    # end
+
+    (@transition_defaults = {
+      duration: {default: 4.5, test: 2},
+      num_periods: {default: 10, test: 5},
+      period: {default: 450, test: 225}
+    }).each do |k, params|
+      it "it should compute other parameters given only #{k}" do
+        seen_values = 0
+        gap = 0
+
+        @mqtt_client.on_update(@id_params) do |id, msg|
+          val = msg['brightness']
 
-      expect(parts).to eq([
-        [255,0,0],
-        [161,0,255],
-        [0,0,255]
-      ])
+          if val > 0
+            seen_values += 1
+            last_seen = val
+          end
+
+          if seen_values == 3
+            gap = last_seen/seen_values
+          end
+
+          val == 255
+        end
+
+        t_params = {field: 'level', start_value: 0, end_value: 100}.merge({k => params[:test]})
+
+        start_time = Time.now
+
+        @client.schedule_transition(@id_params, t_params)
+        transitions = @client.transitions
+
+        @mqtt_client.wait_for_listeners
+        duration = Time.now - start_time
+
+        expect(transitions.length).to eq(1), "Should only be one active transition"
+
+        period = transitions.first['period']
+        expected_duration = (k == :duration ? params[:test] : (TransitionHelpers::Defaults::DURATION/1000.0))
+        num_periods = (expected_duration/period.to_f)*1000
+
+        expect(duration).to be_within(1.5).of(expected_duration)
+        expect(gap).to be_within(10).of((255/num_periods).ceil)
+      end
     end
   end
 end