Repository: bokeh/bokeh

Issue:
[BUG] `TileRenderer` ignores the `visible` property
#### ALL software version info (bokeh, python, notebook, OS, browser, any other relevant packages)
Bokeh 2.1.0rc1

#### Description of expected behavior and the observed behavior
`TileRenderer` should take into account the `visible` property. Both if passed to its constructor and if changed in runtime if using Bokeh server.

#### Complete, minimal, self-contained example code that reproduces the issue
```python
from bokeh.io import show
from bokeh.plotting import figure
from bokeh.tile_providers import CARTODBPOSITRON, get_provider

p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000),
           x_axis_type="mercator", y_axis_type="mercator")

p.add_tile(get_provider(CARTODBPOSITRON), visible=False)

show(p)
```
The root cause is that `TileRenderer` just doesn't check `visible` at all. It seems like every renderer checks this property. Maybe it should be checked at a higher level?


Discussion:

Resolving patch:
diff --git a/examples/models/file/latex_extension.py b/examples/models/file/latex_extension.py
--- a/examples/models/file/latex_extension.py
+++ b/examples/models/file/latex_extension.py
@@ -30,7 +30,7 @@ class LatexLabel(Label):
 export class LatexLabelView extends LabelView {
   model: LatexLabel
 
-  render(): void {
+  protected _render(): void {
     // Here because AngleSpec does units tranform and label doesn't support specs
     let angle: number
     switch (this.model.angle_units) {
@@ -59,13 +59,17 @@ class LatexLabel(Label):
     sy -= this.model.y_offset
 
     this._css_text(this.layer.ctx, "", sx, sy, angle)
-    katex.render(this.model.text, this.el, {displayMode: true})
+    katex.render(this.model.text, this.el!, {displayMode: true})
   }
 }
 
 export class LatexLabel extends Label {
   static init_LatexLabel(): void {
     this.prototype.default_view = LatexLabelView
+
+    this.override({
+      render_mode: "css",
+    })
   }
 }
 """)


Test patch:
diff --git a/bokehjs/make/tasks/test.ts b/bokehjs/make/tasks/test.ts
--- a/bokehjs/make/tasks/test.ts
+++ b/bokehjs/make/tasks/test.ts
@@ -7,7 +7,7 @@ import assert from "assert"
 
 import which from "which"
 
-import {task, task2, success, BuildError} from "../task"
+import {task, task2, success, passthrough, BuildError} from "../task"
 import {Linker} from "@compiler/linker"
 import {default_prelude} from "@compiler/prelude"
 import {compile_typescript} from "@compiler/compiler"
@@ -317,7 +317,7 @@ function bundle(name: string): void {
 }
 
 task("test:compile:unit", async () => compile("unit"))
-const unit_bundle = task("test:unit:bundle", ["test:compile:unit"], async () => bundle("unit"))
+const unit_bundle = task("test:unit:bundle", [passthrough("test:compile:unit")], async () => bundle("unit"))
 
 task2("test:unit", [start, unit_bundle], async ([devtools_port, server_port]) => {
   await devtools(devtools_port, server_port, "unit")
@@ -325,7 +325,7 @@ task2("test:unit", [start, unit_bundle], async ([devtools_port, server_port]) =>
 })
 
 task("test:compile:integration", async () => compile("integration"))
-const integration_bundle = task("test:integration:bundle", ["test:compile:integration"], async () => bundle("integration"))
+const integration_bundle = task("test:integration:bundle", [passthrough("test:compile:integration")], async () => bundle("integration"))
 
 task2("test:integration", [start, integration_bundle], async ([devtools_port, server_port]) => {
   await devtools(devtools_port, server_port, "integration", "test/baselines")
@@ -333,7 +333,7 @@ task2("test:integration", [start, integration_bundle], async ([devtools_port, se
 })
 
 task("test:defaults:compile", ["defaults:generate"], async () => compile("defaults"))
-const defaults_bundle = task("test:defaults:bundle", ["test:defaults:compile"], async () => bundle("defaults"))
+const defaults_bundle = task("test:defaults:bundle", [passthrough("test:defaults:compile")], async () => bundle("defaults"))
 
 task2("test:defaults", [start, defaults_bundle], async ([devtools_port, server_port]) => {
   await devtools(devtools_port, server_port, "defaults")
diff --git a/bokehjs/test/devtools/devtools.ts b/bokehjs/test/devtools/devtools.ts
--- a/bokehjs/test/devtools/devtools.ts
+++ b/bokehjs/test/devtools/devtools.ts
@@ -417,7 +417,11 @@ async function run_tests(): Promise<boolean> {
                   }
                 }
               } finally {
-                await evaluate(`Tests.clear(${seq})`)
+                const output = await evaluate(`Tests.clear(${seq})`)
+                if (output instanceof Failure) {
+                  status.errors.push(output.text)
+                  status.failure = true
+                }
               }
 
               return may_retry
diff --git a/bokehjs/test/unit/models/renderers/renderer.ts b/bokehjs/test/unit/models/renderers/renderer.ts
--- a/bokehjs/test/unit/models/renderers/renderer.ts
+++ b/bokehjs/test/unit/models/renderers/renderer.ts
@@ -4,6 +4,8 @@ import {Renderer, RendererView} from "@bokehjs/models/renderers/renderer"
 
 class SomeRendererView extends RendererView {
   model: SomeRenderer
+
+  protected _render(): void {}
 }
 
 class SomeRenderer extends Renderer {}