code: def test_echo_single(echo):
      # we always echo multiple changes back in 1 update
      class ValueWidget(Widget):
          value = Float().tag(sync=True)
          square = Float().tag(sync=True)
  
          @observe("value")
          def _square(self, change):
              self.square = self.value**2
  
      widget = ValueWidget(value=1)
      assert widget.value == 1
  
      widget._send = mock.MagicMock()
      # this mimics a value coming from the front end
      widget._handle_msg(
          {
              "content": {
                  "data": {
                      "method": "update",
                      "state": {
                          "value": 8,
                      },
                  }
              }
          }
      )
      assert widget.value == 8
      assert widget.square == 64
  
      # we expect this to be echoed
      # note that only value is echoed, not square
      msg = {
          "method": "echo_update",
          "state": {"value": 8.0},
          "buffer_paths": [],
      }
      call = mock.call(msg, buffers=[])
  
      msg = {
          "method": "update",
          "state": {"square": 64},
          "buffer_paths": [],
      }
      call2 = mock.call(msg, buffers=[])
  
      calls = [call, call2] if echo else [call2]
      widget._send.assert_has_calls(calls)
  
imports: import pytest
  from traitlets import Bool, Tuple, List, Instance, CFloat, CInt, Float, Int, TraitError, observe
  from .utils import setup, teardown
  import ipywidgets
  from ipywidgets import Widget
label_desc: Use image node_id 20 for calling a global function with example usage: test_echo_single(echo) without return types