mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 05:42:43 +00:00
Implement Yoga.Config methods and add comprehensive test suite
This commit is contained in:
committed by
Jarred Sumner
parent
68851427a4
commit
cc258f6bf8
@@ -94,6 +94,7 @@ src/bun.js/bindings/JSX509CertificateConstructor.cpp
|
||||
src/bun.js/bindings/JSX509CertificatePrototype.cpp
|
||||
src/bun.js/bindings/JSYogaConfig.cpp
|
||||
src/bun.js/bindings/JSYogaConstructor.cpp
|
||||
src/bun.js/bindings/JSYogaExports.cpp
|
||||
src/bun.js/bindings/JSYogaNode.cpp
|
||||
src/bun.js/bindings/JSYogaPrototype.cpp
|
||||
src/bun.js/bindings/linux_perf_tracing.cpp
|
||||
|
||||
@@ -16,8 +16,10 @@ JSYogaConfig::JSYogaConfig(JSC::VM& vm, JSC::Structure* structure)
|
||||
|
||||
JSYogaConfig::~JSYogaConfig()
|
||||
{
|
||||
// Only free if not already freed via free() method
|
||||
if (m_config) {
|
||||
YGConfigFree(m_config);
|
||||
m_config = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
DECLARE_INFO;
|
||||
|
||||
YGConfigRef internal() { return m_config; }
|
||||
void clearInternal() { m_config = nullptr; }
|
||||
|
||||
private:
|
||||
JSYogaConfig(JSC::VM&, JSC::Structure*);
|
||||
|
||||
@@ -28,6 +28,9 @@ void JSYogaConfigConstructor::finishCreation(JSC::VM& vm, JSC::JSObject* prototy
|
||||
{
|
||||
Base::finishCreation(vm, 0, "Config"_s);
|
||||
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
|
||||
|
||||
// Add static methods - create() is an alias for the constructor
|
||||
putDirectNativeFunction(vm, this->globalObject(), JSC::Identifier::fromString(vm, "create"_s), 0, constructJSYogaConfig, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
|
||||
}
|
||||
|
||||
// Node Constructor implementation
|
||||
@@ -42,6 +45,9 @@ void JSYogaNodeConstructor::finishCreation(JSC::VM& vm, JSC::JSObject* prototype
|
||||
{
|
||||
Base::finishCreation(vm, 1, "Node"_s); // 1 for optional config parameter
|
||||
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
|
||||
|
||||
// Add static methods - create() is an alias for the constructor
|
||||
putDirectNativeFunction(vm, this->globalObject(), JSC::Identifier::fromString(vm, "create"_s), 1, constructJSYogaNode, ImplementationVisibility::Public, NoIntrinsic, JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly);
|
||||
}
|
||||
|
||||
// Constructor functions
|
||||
|
||||
17
src/bun.js/bindings/JSYogaExports.cpp
Normal file
17
src/bun.js/bindings/JSYogaExports.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "root.h"
|
||||
#include "JSYogaConstructor.h"
|
||||
#include "ZigGlobalObject.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
JSC::EncodedJSValue Bun__JSYogaConfigConstructor(Zig::GlobalObject* globalObject)
|
||||
{
|
||||
return JSValue::encode(globalObject->m_JSYogaConfigClassStructure.constructor(globalObject));
|
||||
}
|
||||
|
||||
JSC::EncodedJSValue Bun__JSYogaNodeConstructor(Zig::GlobalObject* globalObject)
|
||||
{
|
||||
return JSValue::encode(globalObject->m_JSYogaNodeClassStructure.constructor(globalObject));
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "JSYogaNode.h"
|
||||
#include <JavaScriptCore/FunctionPrototype.h>
|
||||
#include <JavaScriptCore/JSCInlines.h>
|
||||
#include <yoga/Yoga.h>
|
||||
|
||||
namespace Bun {
|
||||
|
||||
@@ -16,7 +17,11 @@ static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncUseWebDefaults);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncSetExperimentalFeatureEnabled);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncIsExperimentalFeatureEnabled);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncSetPointScaleFactor);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncGetPointScaleFactor);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncSetErrata);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncGetErrata);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncIsEnabledForNodes);
|
||||
static JSC_DECLARE_HOST_FUNCTION(jsYogaConfigProtoFuncFree);
|
||||
|
||||
// Hash table for Config prototype properties
|
||||
static const JSC::HashTableValue JSYogaConfigPrototypeTableValues[] = {
|
||||
@@ -25,7 +30,11 @@ static const JSC::HashTableValue JSYogaConfigPrototypeTableValues[] = {
|
||||
{ "setExperimentalFeatureEnabled"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncSetExperimentalFeatureEnabled, 2 } },
|
||||
{ "isExperimentalFeatureEnabled"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncIsExperimentalFeatureEnabled, 1 } },
|
||||
{ "setPointScaleFactor"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncSetPointScaleFactor, 1 } },
|
||||
{ "getPointScaleFactor"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncGetPointScaleFactor, 0 } },
|
||||
{ "setErrata"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncSetErrata, 1 } },
|
||||
{ "getErrata"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncGetErrata, 0 } },
|
||||
{ "isEnabledForNodes"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncIsEnabledForNodes, 1 } },
|
||||
{ "free"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), JSC::NoIntrinsic, { JSC::HashTableValue::NativeFunctionType, jsYogaConfigProtoFuncFree, 0 } },
|
||||
};
|
||||
|
||||
void JSYogaConfigPrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
|
||||
@@ -61,34 +70,193 @@ void JSYogaNodePrototype::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globa
|
||||
JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
|
||||
}
|
||||
|
||||
// Placeholder implementations for now - these will be filled in Phase 2/3
|
||||
// Config method implementations
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncSetUseWebDefaults, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "setUseWebDefaults"_s));
|
||||
}
|
||||
|
||||
bool enabled = true;
|
||||
if (callFrame->argumentCount() > 0) {
|
||||
enabled = callFrame->uncheckedArgument(0).toBoolean(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
}
|
||||
|
||||
YGConfigSetUseWebDefaults(thisObject->internal(), enabled);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncUseWebDefaults, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "useWebDefaults"_s));
|
||||
}
|
||||
|
||||
// Legacy method - same as setUseWebDefaults(true)
|
||||
YGConfigSetUseWebDefaults(thisObject->internal(), true);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncSetExperimentalFeatureEnabled, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "setExperimentalFeatureEnabled"_s));
|
||||
}
|
||||
|
||||
if (callFrame->argumentCount() < 2) {
|
||||
throwTypeError(globalObject, scope, "setExperimentalFeatureEnabled requires 2 arguments"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t feature = callFrame->uncheckedArgument(0).toInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
bool enabled = callFrame->uncheckedArgument(1).toBoolean(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
YGConfigSetExperimentalFeatureEnabled(thisObject->internal(), static_cast<YGExperimentalFeature>(feature), enabled);
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncIsExperimentalFeatureEnabled, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "isExperimentalFeatureEnabled"_s));
|
||||
}
|
||||
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
throwTypeError(globalObject, scope, "isExperimentalFeatureEnabled requires 1 argument"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t feature = callFrame->uncheckedArgument(0).toInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
bool enabled = YGConfigIsExperimentalFeatureEnabled(thisObject->internal(), static_cast<YGExperimentalFeature>(feature));
|
||||
return JSC::JSValue::encode(JSC::jsBoolean(enabled));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncSetPointScaleFactor, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "setPointScaleFactor"_s));
|
||||
}
|
||||
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
throwTypeError(globalObject, scope, "setPointScaleFactor requires 1 argument"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
double scaleFactor = callFrame->uncheckedArgument(0).toNumber(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
YGConfigSetPointScaleFactor(thisObject->internal(), static_cast<float>(scaleFactor));
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncIsEnabledForNodes, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "isEnabledForNodes"_s));
|
||||
}
|
||||
|
||||
// This method checks if a config is actively being used by any nodes
|
||||
// In the future, we might track this, but for now always return true if valid config
|
||||
return JSC::JSValue::encode(JSC::jsBoolean(thisObject->internal() != nullptr));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncGetPointScaleFactor, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "getPointScaleFactor"_s));
|
||||
}
|
||||
|
||||
float scaleFactor = YGConfigGetPointScaleFactor(thisObject->internal());
|
||||
return JSC::JSValue::encode(JSC::jsNumber(scaleFactor));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncSetErrata, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "setErrata"_s));
|
||||
}
|
||||
|
||||
if (callFrame->argumentCount() < 1) {
|
||||
throwTypeError(globalObject, scope, "setErrata requires 1 argument"_s);
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t errata = callFrame->uncheckedArgument(0).toInt32(globalObject);
|
||||
RETURN_IF_EXCEPTION(scope, {});
|
||||
|
||||
YGConfigSetErrata(thisObject->internal(), static_cast<YGErrata>(errata));
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncGetErrata, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "getErrata"_s));
|
||||
}
|
||||
|
||||
YGErrata errata = YGConfigGetErrata(thisObject->internal());
|
||||
return JSC::JSValue::encode(JSC::jsNumber(static_cast<int32_t>(errata)));
|
||||
}
|
||||
|
||||
JSC_DEFINE_HOST_FUNCTION(jsYogaConfigProtoFuncFree, (JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame))
|
||||
{
|
||||
JSC::VM& vm = globalObject->vm();
|
||||
auto scope = DECLARE_THROW_SCOPE(vm);
|
||||
|
||||
auto* thisObject = jsDynamicCast<JSYogaConfig*>(callFrame->thisValue());
|
||||
if (UNLIKELY(!thisObject)) {
|
||||
return JSC::JSValue::encode(Bun::throwThisTypeError(*globalObject, scope, "Yoga.Config"_s, "free"_s));
|
||||
}
|
||||
|
||||
// Mark the config as freed by setting internal pointer to nullptr
|
||||
// The actual cleanup will happen in the destructor
|
||||
if (thisObject->internal()) {
|
||||
YGConfigFree(thisObject->internal());
|
||||
thisObject->clearInternal();
|
||||
}
|
||||
|
||||
return JSC::JSValue::encode(JSC::jsUndefined());
|
||||
}
|
||||
|
||||
|
||||
100
test/js/bun/yoga-config.test.js
Normal file
100
test/js/bun/yoga-config.test.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
describe("Yoga.Config", () => {
|
||||
test("Config constructor", () => {
|
||||
const config = new Yoga.Config();
|
||||
expect(config).toBeDefined();
|
||||
expect(config.constructor.name).toBe("Config");
|
||||
});
|
||||
|
||||
test("Config.create() static method", () => {
|
||||
const config = Yoga.Config.create();
|
||||
expect(config).toBeDefined();
|
||||
expect(config.constructor.name).toBe("Config");
|
||||
});
|
||||
|
||||
test("setUseWebDefaults", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Should not throw
|
||||
expect(() => config.setUseWebDefaults(true)).not.toThrow();
|
||||
expect(() => config.setUseWebDefaults(false)).not.toThrow();
|
||||
expect(() => config.setUseWebDefaults()).not.toThrow(); // defaults to true
|
||||
});
|
||||
|
||||
test("useWebDefaults (legacy)", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Should not throw
|
||||
expect(() => config.useWebDefaults()).not.toThrow();
|
||||
});
|
||||
|
||||
test("setPointScaleFactor and getPointScaleFactor", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
config.setPointScaleFactor(2.0);
|
||||
expect(config.getPointScaleFactor()).toBe(2.0);
|
||||
|
||||
config.setPointScaleFactor(0); // disable pixel rounding
|
||||
expect(config.getPointScaleFactor()).toBe(0);
|
||||
|
||||
config.setPointScaleFactor(3.5);
|
||||
expect(config.getPointScaleFactor()).toBe(3.5);
|
||||
});
|
||||
|
||||
test("setErrata and getErrata", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Test with different errata values
|
||||
config.setErrata(Yoga.Errata.None);
|
||||
expect(config.getErrata()).toBe(Yoga.Errata.None);
|
||||
|
||||
config.setErrata(Yoga.Errata.Classic);
|
||||
expect(config.getErrata()).toBe(Yoga.Errata.Classic);
|
||||
|
||||
config.setErrata(Yoga.Errata.All);
|
||||
expect(config.getErrata()).toBe(Yoga.Errata.All);
|
||||
});
|
||||
|
||||
test("setExperimentalFeatureEnabled and isExperimentalFeatureEnabled", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Test with a hypothetical experimental feature
|
||||
const feature = 0; // Assuming 0 is a valid experimental feature
|
||||
|
||||
config.setExperimentalFeatureEnabled(feature, true);
|
||||
expect(config.isExperimentalFeatureEnabled(feature)).toBe(true);
|
||||
|
||||
config.setExperimentalFeatureEnabled(feature, false);
|
||||
expect(config.isExperimentalFeatureEnabled(feature)).toBe(false);
|
||||
});
|
||||
|
||||
test("isEnabledForNodes", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Should return true for a valid config
|
||||
expect(config.isEnabledForNodes()).toBe(true);
|
||||
});
|
||||
|
||||
test("free", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Should not throw
|
||||
expect(() => config.free()).not.toThrow();
|
||||
|
||||
// After free, methods should throw or handle gracefully
|
||||
// This depends on implementation - for now just test it doesn't crash
|
||||
expect(() => config.free()).not.toThrow(); // double free should be safe
|
||||
});
|
||||
|
||||
test("error handling", () => {
|
||||
const config = new Yoga.Config();
|
||||
|
||||
// Test invalid arguments
|
||||
expect(() => config.setErrata()).toThrow();
|
||||
expect(() => config.setExperimentalFeatureEnabled()).toThrow();
|
||||
expect(() => config.setExperimentalFeatureEnabled(0)).toThrow(); // missing second arg
|
||||
expect(() => config.isExperimentalFeatureEnabled()).toThrow();
|
||||
expect(() => config.setPointScaleFactor()).toThrow();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user