From 8f2e99dc51a27f26b43ada71ab8f71177fa3f3ca Mon Sep 17 00:00:00 2001
From: Alexander Rose <alexander.rose@weirdbyte.de>
Date: Sat, 30 Oct 2021 14:52:11 -0700
Subject: [PATCH] improve shader tests

- made gl package optional
- skip test if gl package not available
---
 package.json                           |  4 +++-
 src/mol-gl/_spec/cylinders.spec.ts     | 13 +++++-------
 src/mol-gl/_spec/direct-volume.spec.ts | 12 +++++------
 src/mol-gl/_spec/gl.ts                 | 28 ++++++++++++++++++++++++++
 src/mol-gl/_spec/image.spec.ts         | 12 +++++------
 src/mol-gl/_spec/lines.spec.ts         | 12 +++++------
 src/mol-gl/_spec/mesh.spec.ts          | 12 +++++------
 src/mol-gl/_spec/points.spec.ts        | 12 +++++------
 src/mol-gl/_spec/spheres.spec.ts       | 13 +++++-------
 src/mol-gl/_spec/text.spec.ts          | 12 +++++------
 src/mol-gl/_spec/texture-mesh.spec.ts  | 12 +++++------
 src/mol-gl/webgl/context.ts            |  5 ++++-
 12 files changed, 87 insertions(+), 60 deletions(-)
 create mode 100644 src/mol-gl/_spec/gl.ts

diff --git a/package.json b/package.json
index 311b25052..811c6aa53 100644
--- a/package.json
+++ b/package.json
@@ -108,7 +108,6 @@
     "extra-watch-webpack-plugin": "^1.0.3",
     "file-loader": "^6.2.0",
     "fs-extra": "^10.0.0",
-    "gl": "^4.9.2",
     "graphql": "^15.6.0",
     "http-server": "^13.0.2",
     "jest": "^27.2.4",
@@ -153,5 +152,8 @@
     "tslib": "^2.3.1",
     "util.promisify": "^1.1.1",
     "xhr2": "^0.2.1"
+  },
+  "optionalDependencies": {
+    "gl": "^4.9.2"
   }
 }
diff --git a/src/mol-gl/_spec/cylinders.spec.ts b/src/mol-gl/_spec/cylinders.spec.ts
index 5e27ee679..7b1f0fc8d 100644
--- a/src/mol-gl/_spec/cylinders.spec.ts
+++ b/src/mol-gl/_spec/cylinders.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Cylinders } from '../../mol-geo/geometry/cylinders/cylinders';
@@ -22,18 +21,16 @@ export function createCylinders() {
 }
 
 describe('cylinders', () => {
-    const gl = getGLContext(32, 32);
-    const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32, { fragDepth: true });
 
-    (ctx.extensions.fragDepth ? it : it.skip)('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const cylinders = createCylinders();
         scene.add(cylinders);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/direct-volume.spec.ts b/src/mol-gl/_spec/direct-volume.spec.ts
index e085ec182..8ae6e8092 100644
--- a/src/mol-gl/_spec/direct-volume.spec.ts
+++ b/src/mol-gl/_spec/direct-volume.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { DirectVolume } from '../../mol-geo/geometry/direct-volume/direct-volume';
@@ -22,15 +21,16 @@ export function createDirectVolume() {
 }
 
 describe('direct-volume', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const directVolume = createDirectVolume();
         scene.add(directVolume);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/gl.ts b/src/mol-gl/_spec/gl.ts
new file mode 100644
index 000000000..eadedd998
--- /dev/null
+++ b/src/mol-gl/_spec/gl.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { createContext } from '../webgl/context';
+
+export function getGLContext(width: number, height: number) {
+    const gl = require('gl')(width, height, {
+        alpha: true,
+        depth: true,
+        premultipliedAlpha: true,
+        preserveDrawingBuffer: true,
+        antialias: true,
+    });
+    return createContext(gl);
+}
+
+export function tryGetGLContext(width: number, height: number, requiredExtensions?: { fragDepth?: boolean }) {
+    try {
+        const ctx = getGLContext(width, height);
+        if (requiredExtensions?.fragDepth && !ctx.extensions.fragDepth) return;
+        return ctx;
+    } catch (e) {
+        return;
+    }
+}
\ No newline at end of file
diff --git a/src/mol-gl/_spec/image.spec.ts b/src/mol-gl/_spec/image.spec.ts
index bf5a2e606..aee29d421 100644
--- a/src/mol-gl/_spec/image.spec.ts
+++ b/src/mol-gl/_spec/image.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Image } from '../../mol-geo/geometry/image/image';
@@ -22,15 +21,16 @@ export function createImage() {
 }
 
 describe('image', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const image = createImage();
         scene.add(image);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/lines.spec.ts b/src/mol-gl/_spec/lines.spec.ts
index 07527eb26..c1f88f8d9 100644
--- a/src/mol-gl/_spec/lines.spec.ts
+++ b/src/mol-gl/_spec/lines.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Lines } from '../../mol-geo/geometry/lines/lines';
@@ -22,15 +21,16 @@ export function createLines() {
 }
 
 describe('lines', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const lines = createLines();
         scene.add(lines);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/mesh.spec.ts b/src/mol-gl/_spec/mesh.spec.ts
index 18d2c4260..c1b00f14f 100644
--- a/src/mol-gl/_spec/mesh.spec.ts
+++ b/src/mol-gl/_spec/mesh.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
@@ -22,15 +21,16 @@ export function createMesh() {
 }
 
 describe('mesh', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const mesh = createMesh();
         scene.add(mesh);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/points.spec.ts b/src/mol-gl/_spec/points.spec.ts
index f4b3db772..358b3094d 100644
--- a/src/mol-gl/_spec/points.spec.ts
+++ b/src/mol-gl/_spec/points.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Points } from '../../mol-geo/geometry/points/points';
@@ -22,15 +21,16 @@ export function createPoints() {
 }
 
 describe('points', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const points = createPoints();
         scene.add(points);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/spheres.spec.ts b/src/mol-gl/_spec/spheres.spec.ts
index 0fcf7f959..ecf721aaf 100644
--- a/src/mol-gl/_spec/spheres.spec.ts
+++ b/src/mol-gl/_spec/spheres.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Spheres } from '../../mol-geo/geometry/spheres/spheres';
@@ -22,18 +21,16 @@ export function createSpheres() {
 }
 
 describe('spheres', () => {
-    const gl = getGLContext(32, 32);
-    const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32, { fragDepth: true });
 
-    (ctx.extensions.fragDepth ? it : it.skip)('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const spheres = createSpheres();
         scene.add(spheres);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/text.spec.ts b/src/mol-gl/_spec/text.spec.ts
index 4b0f002a5..c808110eb 100644
--- a/src/mol-gl/_spec/text.spec.ts
+++ b/src/mol-gl/_spec/text.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Text } from '../../mol-geo/geometry/text/text';
@@ -22,15 +21,16 @@ export function createText() {
 }
 
 describe('text', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const text = createText();
         scene.add(text);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/_spec/texture-mesh.spec.ts b/src/mol-gl/_spec/texture-mesh.spec.ts
index ab4736e2d..d30cd59e6 100644
--- a/src/mol-gl/_spec/texture-mesh.spec.ts
+++ b/src/mol-gl/_spec/texture-mesh.spec.ts
@@ -6,9 +6,8 @@
 
 import { createRenderObject } from '../render-object';
 import { Scene } from '../scene';
-import getGLContext from 'gl';
+import { getGLContext, tryGetGLContext } from './gl';
 import { setDebugMode } from '../../mol-util/debug';
-import { createRenderer } from './renderer.spec';
 import { ColorNames } from '../../mol-util/color/names';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { TextureMesh } from '../../mol-geo/geometry/texture-mesh/texture-mesh';
@@ -22,15 +21,16 @@ export function createTextureMesh() {
 }
 
 describe('texture-mesh', () => {
-    it('basic', async () => {
-        const gl = getGLContext(32, 32);
-        const { ctx } = createRenderer(gl);
+    const ctx = tryGetGLContext(32, 32);
+
+    (ctx ? it : it.skip)('basic', async () => {
+        const ctx = getGLContext(32, 32);
         const scene = Scene.create(ctx);
         const textureMesh = createTextureMesh();
         scene.add(textureMesh);
         setDebugMode(true);
         expect(() => scene.commit()).not.toThrow();
         setDebugMode(false);
-        gl.getExtension('STACKGL_destroy_context')?.destroy();
+        ctx.destroy();
     });
 });
\ No newline at end of file
diff --git a/src/mol-gl/webgl/context.ts b/src/mol-gl/webgl/context.ts
index 5ce242b2a..e094bb149 100644
--- a/src/mol-gl/webgl/context.ts
+++ b/src/mol-gl/webgl/context.ts
@@ -358,7 +358,10 @@ export function createContext(gl: GLRenderingContext, props: Partial<{ pixelScal
             unbindResources(gl);
 
             // to aid GC
-            if (!options?.doNotForceWebGLContextLoss) gl.getExtension('WEBGL_lose_context')?.loseContext();
+            if (!options?.doNotForceWebGLContextLoss) {
+                gl.getExtension('WEBGL_lose_context')?.loseContext();
+                gl.getExtension('STACKGL_destroy_context')?.destroy();
+            }
         }
     };
 }
\ No newline at end of file
-- 
GitLab