code: def test_output_handler_both(dirname):
      wrapper = OutputHandler(
          "tag",
          metric_names=["a", "b"],
          output_transform=lambda x: {"loss": x},
      )
      mock_logger = MagicMock(spec=VisdomLogger)
      mock_logger.vis = MagicMock()
      mock_logger.executor = _DummyExecutor()
  
      mock_engine = MagicMock()
      mock_engine.state = State(metrics={"a": 12.23, "b": 23.45})
      mock_engine.state.epoch = 5
      mock_engine.state.output = 12345
  
      wrapper(mock_engine, mock_logger, Events.EPOCH_STARTED)
  
      assert mock_logger.vis.line.call_count == 3
      assert (
          len(wrapper.windows) == 3
          and "tag/a" in wrapper.windows
          and "tag/b" in wrapper.windows
          and "tag/loss" in wrapper.windows
      )
      assert wrapper.windows["tag/a"]["win"] is not None
      assert wrapper.windows["tag/b"]["win"] is not None
      assert wrapper.windows["tag/loss"]["win"] is not None
  
      mock_logger.vis.line.assert_has_calls(
          [
              call(
                  X=[5],
                  Y=[12.23],
                  env=mock_logger.vis.env,
                  win=None,
                  update=None,
                  opts=wrapper.windows["tag/a"]["opts"],
                  name="tag/a",
              ),
              call(
                  X=[5],
                  Y=[23.45],
                  env=mock_logger.vis.env,
                  win=None,
                  update=None,
                  opts=wrapper.windows["tag/b"]["opts"],
                  name="tag/b",
              ),
              call(
                  X=[5],
                  Y=[12345],
                  env=mock_logger.vis.env,
                  win=None,
                  update=None,
                  opts=wrapper.windows["tag/loss"]["opts"],
                  name="tag/loss",
              ),
          ],
          any_order=True,
      )
  
      mock_engine.state.epoch = 6
      wrapper(mock_engine, mock_logger, Events.EPOCH_STARTED)
  
      assert mock_logger.vis.line.call_count == 6
      assert (
          len(wrapper.windows) == 3
          and "tag/a" in wrapper.windows
          and "tag/b" in wrapper.windows
          and "tag/loss" in wrapper.windows
      )
      assert wrapper.windows["tag/a"]["win"] is not None
      assert wrapper.windows["tag/b"]["win"] is not None
      assert wrapper.windows["tag/loss"]["win"] is not None
  
      mock_logger.vis.line.assert_has_calls(
          [
              call(
                  X=[6],
                  Y=[12.23],
                  env=mock_logger.vis.env,
                  win=wrapper.windows["tag/a"]["win"],
                  update="append",
                  opts=wrapper.windows["tag/a"]["opts"],
                  name="tag/a",
              ),
              call(
                  X=[6],
                  Y=[23.45],
                  env=mock_logger.vis.env,
                  win=wrapper.windows["tag/b"]["win"],
                  update="append",
                  opts=wrapper.windows["tag/b"]["opts"],
                  name="tag/b",
              ),
              call(
                  X=[6],
                  Y=[12345],
                  env=mock_logger.vis.env,
                  win=wrapper.windows["tag/loss"]["win"],
                  update="append",
                  opts=wrapper.windows["tag/loss"]["opts"],
                  name="tag/loss",
              ),
          ],
          any_order=True,
      )
  
imports: import sys
  from unittest.mock import ANY, call, MagicMock, patch
  import pytest
  import torch
  from ignite.contrib.handlers.visdom_logger import _DummyExecutor, global_step_from_engine, GradsScalarHandler, OptimizerParamsHandler, OutputHandler, VisdomLogger, WeightsScalarHandler
  from ignite.engine import Engine, Events, State
label_desc: Use image node_id 6 for calling a global function with example usage: test_output_handler_both(dirname) without return types