code: def test_theming_a_document_before_adding_root(self) -> None:
      theme = Theme(
          json={
              "attrs": {
                  "ThemedModel": {
                      "string": "w00t",
                  },
              },
          }
      )
      obj = ThemedModel()
      doc = Document()
      assert "hello" == obj.string
      doc.theme = theme
      assert doc.theme is theme
      changes = dict(calls=[])
  
      def record_trigger(attr, old, new_):
          changes["calls"].append((attr, old, new_))
  
      obj.on_change("string", record_trigger)
      doc.add_root(obj)
      assert "w00t" == obj.string
      doc.remove_root(obj)
      assert "hello" == obj.string
      assert [
          ("string", "hello", "w00t"),
          ("string", "w00t", "hello"),
      ] == changes["calls"]
  
imports: from __future__ import annotations
  import pytest
  import os
  import tempfile
  from bokeh.core.properties import Int, String
  from bokeh.core.property_mixins import FillProps, LineProps, TextProps
  from bokeh.document import Document
  from bokeh.model import Model
  from bokeh.plotting import figure
  from bokeh.util.deprecation import BokehDeprecationWarning
  from bokeh.themes import Theme, built_in_themes, DARK_MINIMAL, LIGHT_MINIMAL
label_desc: Use image node_id 13 for calling the TestThemes obj's underlying member method code with example usage: obj.test_theming_a_document_before_adding_root() without return types