text: import { Color } from "../Source/Cesium.js";
  import { PixelFormat } from "../Source/Cesium.js";
  import { PrimitiveType } from "../Source/Cesium.js";
  import { WebGLConstants } from "../Source/Cesium.js";
  import { Buffer } from "../Source/Cesium.js";
  import { BufferUsage } from "../Source/Cesium.js";
  import { ClearCommand } from "../Source/Cesium.js";
  import { ContextLimits } from "../Source/Cesium.js";
  import { CubeMap } from "../Source/Cesium.js";
  import { DrawCommand } from "../Source/Cesium.js";
  import { Framebuffer } from "../Source/Cesium.js";
  import { PixelDatatype } from "../Source/Cesium.js";
  import { Renderbuffer } from "../Source/Cesium.js";
  import { RenderbufferFormat } from "../Source/Cesium.js";
  import { RenderState } from "../Source/Cesium.js";
  import { ShaderProgram } from "../Source/Cesium.js";
  import { Texture } from "../Source/Cesium.js";
  import { VertexArray } from "../Source/Cesium.js";
  import createContext from "../createContext.js";
  
  describe(
    "Renderer/Framebuffer",
    function () {
      var context;
      var sp;
      var va;
      var framebuffer;
  
      beforeAll(function () {
        context = createContext();
      });
  
      afterAll(function () {
        context.destroyForSpecs();
      });
  
      afterEach(function () {
        sp = sp && sp.destroy();
        va = va && va.destroy();
        framebuffer = framebuffer && framebuffer.destroy();
      });
  
      it("has a color texture attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          ],
        });
        expect(framebuffer.getColorTexture(0)).toBeDefined();
      });
  
      it("has a color renderbuffer attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          colorRenderbuffers: [
            new Renderbuffer({
              context: context,
              format: RenderbufferFormat.RGBA4,
            }),
          ],
        });
        expect(framebuffer.getColorRenderbuffer(0)).toBeDefined();
      });
  
      it("has a depth texture attachment", function () {
        if (context.depthTexture) {
          framebuffer = new Framebuffer({
            context: context,
            depthTexture: new Texture({
              context: context,
              width: 1,
              height: 1,
              pixelFormat: PixelFormat.DEPTH_COMPONENT,
              pixelDatatype: PixelDatatype.UNSIGNED_SHORT,
            }),
          });
          expect(framebuffer.depthTexture).toBeDefined();
        }
      });
  
      it("has a depth renderbuffer attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          depthRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.DEPTH_COMPONENT16,
          }),
        });
        expect(framebuffer.depthRenderbuffer).toBeDefined();
      });
  
      it("has a stencil renderbuffer attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          stencilRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.STENCIL_INDEX8,
          }),
        });
        expect(framebuffer.stencilRenderbuffer).toBeDefined();
      });
  
      it("has a depth-stencil texture attachment", function () {
        if (context.depthTexture) {
          framebuffer = new Framebuffer({
            context: context,
            depthStencilTexture: new Texture({
              context: context,
              width: 1,
              height: 1,
              pixelFormat: PixelFormat.DEPTH_STENCIL,
              pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
            }),
          });
          expect(framebuffer.depthStencilTexture).toBeDefined();
        }
      });
  
      it("has a depth-stencil renderbuffer attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          depthStencilRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.DEPTH_STENCIL,
          }),
        });
        expect(framebuffer.depthStencilRenderbuffer).toBeDefined();
      });
  
      it("has a depth attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
        });
        expect(framebuffer.hasDepthAttachment).toEqual(false);
        framebuffer.destroy();
  
        framebuffer = new Framebuffer({
          context: context,
          depthRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.DEPTH_COMPONENT16,
          }),
        });
        expect(framebuffer.hasDepthAttachment).toEqual(true);
      });
  
      it("clears a color attachment", function () {
        // 1 of 3.  Clear default color buffer to black.
        ClearCommand.ALL.execute(context);
        expect(context).toReadPixels([0, 0, 0, 255]);
  
        // 2 of 3.  Clear framebuffer color attachment to green.
        var colorTexture = new Texture({
          context: context,
          width: 1,
          height: 1,
        });
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [colorTexture],
        });
  
        var clearCommand = new ClearCommand({
          color: new Color(0.0, 1.0, 0.0, 1.0),
          framebuffer: framebuffer,
        });
        clearCommand.execute(context);
  
        // 3 of 3.  Render green to default color buffer by reading from previous color attachment
        var fs =
          "uniform sampler2D u_texture; void main() { gl_FragColor = texture2D(u_texture, vec2(0.0)); }";
        var uniformMap = {
          u_texture: function () {
            return colorTexture;
          },
        };
  
        expect({
          context: context,
          fragmentShader: fs,
          uniformMap: uniformMap,
        }).contextToRender([0, 255, 0, 255]);
      });
  
      it("clears a cube map face color attachment", function () {
        var cubeMap = new CubeMap({
          context: context,
          width: 1,
          height: 1,
        });
  
        // 1 of 3.  Clear default color buffer to black.
        ClearCommand.ALL.execute(context);
        expect(context).toReadPixels([0, 0, 0, 255]);
  
        // 2 of 3.  Clear framebuffer color attachment to green.
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [cubeMap.positiveX],
          destroyAttachments: false,
        });
  
        var clearCommand = new ClearCommand({
          color: new Color(0.0, 1.0, 0.0, 1.0),
          framebuffer: framebuffer,
        });
        clearCommand.execute(context);
  
        // 3 of 3.  Render green to default color buffer by reading from previous color attachment
        var fs =
          "uniform samplerCube u_cubeMap; void main() { gl_FragColor = textureCube(u_cubeMap, vec3(1.0, 0.0, 0.0)); }";
        var uniformMap = {
          u_cubeMap: function () {
            return cubeMap;
          },
        };
  
        expect({
          context: context,
          fragmentShader: fs,
          uniformMap: uniformMap,
        }).contextToRender([0, 255, 0, 255]);
  
        cubeMap = cubeMap.destroy();
      });
  
      function renderColorTexture(framebuffer, color, expectedColor) {
        var vs =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs = "uniform vec4 color; void main() { gl_FragColor = color; }";
        sp = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs,
          fragmentShaderSource: fs,
          attributeLocations: {
            position: 0,
          },
        });
  
        va = new VertexArray({
          context: context,
          attributes: [
            {
              index: 0,
              vertexBuffer: Buffer.createVertexBuffer({
                context: context,
                typedArray: new Float32Array([0, 0, 0, 1]),
                usage: BufferUsage.STATIC_DRAW,
              }),
              componentsPerAttribute: 4,
            },
          ],
        });
  
        var uniformMap = {
          color: function () {
            return color;
          },
        };
  
        var command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp,
          vertexArray: va,
          uniformMap: uniformMap,
          framebuffer: framebuffer,
        });
        command.execute(context);
  
        expect({
          context: context,
          framebuffer: framebuffer,
        }).toReadPixels(expectedColor);
      }
  
      it("draws to a color attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          ],
        });
        renderColorTexture(framebuffer, new Color(0.0, 1.0, 0.0, 1.0), [
          0,
          255,
          0,
          255,
        ]);
      });
  
      it("draws to a floating-point color attachment", function () {
        if (!context.colorBufferFloat) {
          return;
        }
  
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
              pixelDatatype: PixelDatatype.FLOAT,
            }),
          ],
        });
        renderColorTexture(framebuffer, new Color(0.5, 1.5, 2.0, 1.0), [
          0.5,
          1.5,
          2.0,
          1.0,
        ]);
      });
  
      it("draws to a half floating-point color attachment", function () {
        if (!context.colorBufferHalfFloat) {
          return;
        }
  
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
              pixelDatatype: PixelDatatype.HALF_FLOAT,
            }),
          ],
        });
        renderColorTexture(framebuffer, new Color(0.5, 1.5, 2.0, 1.0), [
          14336,
          15872,
          16384,
          15360,
        ]);
      });
  
      function renderDepthAttachment(framebuffer, texture) {
        ClearCommand.ALL.execute(context);
  
        var framebufferClear = new ClearCommand({
          depth: 1.0,
          framebuffer: framebuffer,
        });
  
        framebufferClear.execute(context);
  
        // 1 of 3.  Render green point into color attachment.
        var vs =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs = "void main() { gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }";
        sp = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs,
          fragmentShaderSource: fs,
          attributeLocations: {
            position: 0,
          },
        });
  
        va = new VertexArray({
          context: context,
          attributes: [
            {
              index: 0,
              vertexBuffer: Buffer.createVertexBuffer({
                context: context,
                typedArray: new Float32Array([0, 0, 0, 1]),
                usage: BufferUsage.STATIC_DRAW,
              }),
              componentsPerAttribute: 4,
            },
          ],
        });
  
        var command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp,
          vertexArray: va,
          framebuffer: framebuffer,
          renderState: RenderState.fromCache({
            depthTest: {
              enabled: true,
            },
          }),
        });
        command.execute(context);
  
        // 2 of 3.  Verify default color buffer is still black.
        expect(context).toReadPixels([0, 0, 0, 255]);
  
        // 3 of 3.  Render green to default color buffer by reading from previous color attachment
        var vs2 =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs2 =
          "uniform sampler2D u_texture; void main() { gl_FragColor = texture2D(u_texture, vec2(0.0)).rrrr; }";
        var sp2 = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs2,
          fragmentShaderSource: fs2,
          attributeLocations: {
            position: 0,
          },
        });
        var uniformMap = {
          u_texture: function () {
            return texture;
          },
        };
  
        command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp2,
          vertexArray: va,
          uniformMap: uniformMap,
        });
        command.execute(context);
  
        sp2 = sp2.destroy();
  
        return context.readPixels();
      }
  
      it("draws to a depth texture attachment", function () {
        if (context.depthTexture) {
          framebuffer = new Framebuffer({
            context: context,
            colorTextures: [
              new Texture({
                context: context,
                width: 1,
                height: 1,
              }),
            ],
            depthTexture: new Texture({
              context: context,
              width: 1,
              height: 1,
              pixelFormat: PixelFormat.DEPTH_COMPONENT,
              pixelDatatype: PixelDatatype.UNSIGNED_SHORT,
            }),
          });
  
          if (framebuffer.status === WebGLConstants.FRAMEBUFFER_COMPLETE) {
            expect(
              renderDepthAttachment(framebuffer, framebuffer.depthTexture)
            ).toEqualEpsilon([128, 128, 128, 255], 1);
          }
        }
      });
  
      it("draws to a depth-stencil texture attachment", function () {
        if (context.depthTexture) {
          framebuffer = new Framebuffer({
            context: context,
            colorTextures: [
              new Texture({
                context: context,
                width: 1,
                height: 1,
              }),
            ],
            depthStencilTexture: new Texture({
              context: context,
              width: 1,
              height: 1,
              pixelFormat: PixelFormat.DEPTH_STENCIL,
              pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
            }),
          });
  
          if (framebuffer.status === WebGLConstants.FRAMEBUFFER_COMPLETE) {
            expect(
              renderDepthAttachment(framebuffer, framebuffer.depthStencilTexture)
            ).toEqualEpsilon([128, 128, 128, 255], 1);
          }
        }
      });
  
      it("draws with a depth attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          ],
          depthRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.DEPTH_COMPONENT16,
            width: 1,
            height: 1,
          }),
        });
  
        var vs =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs = "void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }";
        sp = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs,
          fragmentShaderSource: fs,
          attributeLocations: {
            position: 0,
          },
        });
  
        va = new VertexArray({
          context: context,
          attributes: [
            {
              index: 0,
              vertexBuffer: Buffer.createVertexBuffer({
                context: context,
                typedArray: new Float32Array([0, 0, 0, 1]),
                usage: BufferUsage.STATIC_DRAW,
              }),
              componentsPerAttribute: 4,
            },
          ],
        });
  
        // 1 of 3.  Clear framebuffer
        var clearCommand = new ClearCommand({
          color: new Color(0.0, 0.0, 0.0, 0.0),
          depth: 1.0,
          framebuffer: framebuffer,
        });
        clearCommand.execute(context);
        expect({
          context: context,
          framebuffer: framebuffer,
        }).toReadPixels([0, 0, 0, 0]);
  
        // 2 of 3.  Does not pass depth test
        var command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp,
          vertexArray: va,
          framebuffer: framebuffer,
          renderState: RenderState.fromCache({
            depthTest: {
              enabled: true,
              func: WebGLConstants.NEVER,
            },
          }),
        });
        command.execute(context);
        expect({
          context: context,
          framebuffer: framebuffer,
        }).toReadPixels([0, 0, 0, 0]);
  
        // 3 of 3.  Passes depth test
        command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp,
          vertexArray: va,
          framebuffer: framebuffer,
          renderState: RenderState.fromCache({
            depthTest: {
              enabled: true,
              func: WebGLConstants.ALWAYS,
            },
          }),
        });
        command.execute(context);
        expect({
          context: context,
          framebuffer: framebuffer,
        }).toReadPixels([255, 255, 255, 255]);
      });
  
      it("draws with multiple render targets", function () {
        if (!context.drawBuffers) {
          return;
        }
  
        var source = new Uint8Array(4);
        var colorTexture0 = new Texture({
          context: context,
          source: {
            arrayBufferView: source,
            width: 1,
            height: 1,
          },
        });
        var colorTexture1 = new Texture({
          context: context,
          source: {
            arrayBufferView: source,
            width: 1,
            height: 1,
          },
        });
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [colorTexture0, colorTexture1],
        });
  
        // 1 of 5.  Clear default color buffer to black.
        ClearCommand.ALL.execute(context);
        expect(context).toReadPixels([0, 0, 0, 255]);
  
        // 2 of 5.  Render red point into color attachment 0 and green point to color attachment 1.
        var vs =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs =
          "#extension GL_EXT_draw_buffers : enable \n void main() { gl_FragData[0] = vec4(1.0, 0.0, 0.0, 1.0); gl_FragData[1] = vec4(0.0, 1.0, 0.0, 1.0); }";
        sp = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs,
          fragmentShaderSource: fs,
          attributeLocations: {
            position: 0,
          },
        });
  
        va = new VertexArray({
          context: context,
          attributes: [
            {
              index: 0,
              vertexBuffer: Buffer.createVertexBuffer({
                context: context,
                typedArray: new Float32Array([0, 0, 0, 1]),
                usage: BufferUsage.STATIC_DRAW,
              }),
              componentsPerAttribute: 4,
            },
          ],
        });
  
        var command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp,
          vertexArray: va,
          framebuffer: framebuffer,
        });
        command.execute(context);
  
        // 3 of 5.  Verify default color buffer is still black.
        expect(context).toReadPixels([0, 0, 0, 255]);
  
        // 4 of 5.  Render yellow to default color buffer by reading from previous color attachments
        var vs2 =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs2 =
          "uniform sampler2D u_texture0; uniform sampler2D u_texture1; void main() { gl_FragColor = texture2D(u_texture0, vec2(0.0)) + texture2D(u_texture1, vec2(0.0)); }";
        var sp2 = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs2,
          fragmentShaderSource: fs2,
          attributeLocations: {
            position: 0,
          },
        });
        var uniformMap = {
          u_texture0: function () {
            return colorTexture0;
          },
          u_texture1: function () {
            return colorTexture1;
          },
        };
  
        command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp2,
          vertexArray: va,
          uniformMap: uniformMap,
        });
        command.execute(context);
        expect(context).toReadPixels([255, 255, 0, 255]);
  
        // 5 of 5. Verify clearing multiple color attachments
        var clearCommand = new ClearCommand({
          color: new Color(0.0, 0.0, 0.0, 0.0),
          framebuffer: framebuffer,
        });
        clearCommand.execute(context);
  
        command = new DrawCommand({
          primitiveType: PrimitiveType.POINTS,
          shaderProgram: sp2,
          vertexArray: va,
        });
        command.execute(context);
        expect(context).toReadPixels([0, 0, 0, 255]);
  
        sp2 = sp2.destroy();
      });
  
      it("gets the status of a complete framebuffer", function () {
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          ],
          depthRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.DEPTH_COMPONENT16,
            width: 1,
            height: 1,
          }),
        });
        expect(framebuffer.status).toEqual(WebGLConstants.FRAMEBUFFER_COMPLETE);
      });
  
      it("gets the status of a incomplete framebuffer", function () {
        if (!!window.webglStub) {
          return;
        }
  
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          ],
          depthRenderbuffer: new Renderbuffer({
            context: context,
            format: RenderbufferFormat.RGBA4,
            width: 2,
            height: 2,
          }),
        });
        expect(framebuffer.status).not.toEqual(
          WebGLConstants.FRAMEBUFFER_COMPLETE
        );
      });
  
      it("destroys", function () {
        var f = new Framebuffer({
          context: context,
        });
        expect(f.isDestroyed()).toEqual(false);
        f.destroy();
        expect(f.isDestroyed()).toEqual(true);
      });
  
      it("throws when created with color texture and color renderbuffer attachments", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            colorTextures: "not undefined",
            colorRenderbuffers: "not undefined",
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with depth texture and depth renderbuffer attachments", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            depthTexture: "not undefined",
            depthRenderbuffer: "not undefined",
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with depth-stencil texture and depth-stencil renderbuffer attachments", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            depthStencilTexture: "not undefined",
            depthStencilRenderbuffer: "not undefined",
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with depth and depth-stencil attachments", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            depthRenderbuffer: "not undefined",
            depthStencilRenderbuffer: "not undefined",
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with stencil and depth-stencil attachments", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            stencilRenderbuffer: "not undefined",
            depthStencilRenderbuffer: "not undefined",
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with depth and stencil attachments", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            depthRenderbuffer: "not undefined",
            stencilRenderbuffer: "not undefined",
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with a color texture with a non-color pixel format", function () {
        if (context.depthTexture) {
          expect(function () {
            framebuffer = new Framebuffer({
              context: context,
              colorTextures: [
                new Texture({
                  context: context,
                  width: 1,
                  height: 1,
                  pixelFormat: PixelFormat.DEPTH_COMPONENT,
                  pixelDatatype: PixelDatatype.UNSIGNED_SHORT,
                }),
              ],
            });
          }).toThrowDeveloperError();
        }
      });
  
      it("throws when created with a depth texture without a DEPTH_COMPONENT pixel format", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            depthTexture: new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when created with a depth-stencil texture without a DEPTH_STENCIL pixel format", function () {
        expect(function () {
          framebuffer = new Framebuffer({
            context: context,
            depthStencilTexture: new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when the depth test is enabled without an appropriate attachment", function () {
        framebuffer = new Framebuffer({
          context: context,
          colorTextures: [
            new Texture({
              context: context,
              width: 1,
              height: 1,
            }),
          ],
        });
  
        var vs =
          "attribute vec4 position; void main() { gl_PointSize = 1.0; gl_Position = position; }";
        var fs = "void main() { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); }";
        sp = ShaderProgram.fromCache({
          context: context,
          vertexShaderSource: vs,
          fragmentShaderSource: fs,
          attributeLocations: {
            position: 0,
          },
        });
  
        va = new VertexArray({
          context: context,
          attributes: [
            {
              index: 0,
              vertexBuffer: Buffer.createVertexBuffer({
                context: context,
                typedArray: new Float32Array([0, 0, 0, 1]),
                usage: BufferUsage.STATIC_DRAW,
              }),
              componentsPerAttribute: 4,
            },
          ],
        });
  
        expect(function () {
          var command = new DrawCommand({
            primitiveType: PrimitiveType.POINTS,
            shaderProgram: sp,
            vertexArray: va,
            framebuffer: framebuffer,
            renderState: RenderState.fromCache({
              depthTest: {
                enabled: true,
              },
            }),
          });
          command.execute(context);
        }).toThrowDeveloperError();
      });
  
      it("throws when the number of color texture exceeds the number color attachments supported", function () {
        expect(function () {
          return new Framebuffer({
            context: context,
            colorTextures: new Array(ContextLimits.maximumColorAttachments + 1),
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when the number of color renderbuffers exceeds the number color attachments supported", function () {
        expect(function () {
          return new Framebuffer({
            context: context,
            colorRenderbuffers: new Array(
              ContextLimits.maximumColorAttachments + 1
            ),
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when the index to getColorTexture is out of bounds", function () {
        framebuffer = new Framebuffer({
          context: context,
        });
        expect(function () {
          framebuffer.getColorTexture();
        }).toThrowDeveloperError();
  
        expect(function () {
          framebuffer.getColorTexture(-1);
        }).toThrowDeveloperError();
  
        expect(function () {
          framebuffer.getColorTexture(ContextLimits.maximumColorAttachments + 1);
        }).toThrowDeveloperError();
      });
  
      it("throws when the index to getColorRenderbuffer is out of bounds", function () {
        framebuffer = new Framebuffer({
          context: context,
        });
        expect(function () {
          framebuffer.getColorRenderbuffer();
        }).toThrowDeveloperError();
  
        expect(function () {
          framebuffer.getColorRenderbuffer(-1);
        }).toThrowDeveloperError();
  
        expect(function () {
          framebuffer.getColorRenderbuffer(
            ContextLimits.maximumColorAttachments + 1
          );
        }).toThrowDeveloperError();
      });
  
      it("throws when a color attachment has a floating-point datatype but the EXT_color_buffer_float extension is not supported", function () {
        if (context.colorBufferFloat) {
          return;
        }
        expect(function () {
          return new Framebuffer({
            context: context,
            colorTextures: [
              new Texture({
                context: context,
                width: 1,
                height: 1,
                pixelDatatype: PixelDatatype.FLOAT,
              }),
            ],
          });
        }).toThrowDeveloperError();
      });
  
      it("throws when a color attachment has a half floating-point datatype but the EXT_color_buffer_half_float extension is not supported", function () {
        if (context.colorBufferHalfFloat) {
          return;
        }
        expect(function () {
          return new Framebuffer({
            context: context,
            colorTextures: [
              new Texture({
                context: context,
                width: 1,
                height: 1,
                pixelDatatype: PixelDatatype.HALF_FLOAT,
              }),
            ],
          });
        }).toThrowDeveloperError();
      });
  
      it("fails to destroy", function () {
        var f = new Framebuffer({
          context: context,
        });
        f.destroy();
  
        expect(function () {
          f.destroy();
        }).toThrowDeveloperError();
      });
  
      it("throws when there is no context", function () {
        expect(function () {
          return new Framebuffer();
        }).toThrowDeveloperError();
      });
    },
    "WebGL"
  );
  