nerdamer-prime
Version:
javascript light-weight symbolic math library
191 lines (156 loc) • 8.16 kB
text/typescript
/**
* Investigation test for vecget return type behavior
*
* This test file specifically investigates the issue described where:
*
* - Vecget should return NerdamerExpression or undefined
* - But actually returns object wrappers with symbol properties
*/
import type nerdamer from '../index';
// Type alias for dynamic property access in investigation tests
type Indexable = Record<string, any>;
describe('vecget Return Type Investigation', () => {
let nerdamerRuntime: typeof nerdamer & Indexable;
beforeAll(async () => {
// Load complete nerdamer with all modules
const module = await import('../all.js');
nerdamerRuntime = module.default || module;
});
it('should investigate vecget return type behavior', () => {
console.log('\n=== vecget Return Type Investigation ===');
// Create test data - polynomial with known coefficients
const expr = nerdamerRuntime('x^2 + 2*x + 1');
const coeffs = nerdamerRuntime.coeffs(expr, 'x');
console.log('Expression:', expr.toString());
console.log('Coefficients:', coeffs.toString());
console.log('Coefficients type:', typeof coeffs);
console.log('Coefficients constructor:', coeffs.constructor.name);
// Test 1: Valid coefficient access (index 0)
console.log('\n--- Test 1: Valid Index (0) ---');
const validResult = nerdamerRuntime.vecget(coeffs, 0);
console.log('Result:', validResult);
console.log('Type:', typeof validResult);
console.log('Constructor:', validResult.constructor.name);
console.log('Has symbol property:', 'symbol' in validResult);
console.log('Has toString method:', typeof validResult.toString === 'function');
console.log('Has text method:', typeof validResult.text === 'function');
if ('symbol' in validResult) {
console.log('NerdamerSymbol property type:', typeof validResult.symbol);
console.log('NerdamerSymbol value:', validResult.symbol);
}
// Test 2: Another valid coefficient access (index 1)
console.log('\n--- Test 2: Valid Index (1) ---');
const validResult2 = nerdamerRuntime.vecget(coeffs, 1);
console.log('Result:', validResult2);
console.log('Type:', typeof validResult2);
console.log('Has symbol property:', 'symbol' in validResult2);
// Test 3: Invalid coefficient access (out of bounds)
console.log('\n--- Test 3: Invalid Index (3) ---');
const invalidResult = nerdamerRuntime.vecget(coeffs, 3);
console.log('Result:', invalidResult);
console.log('Type:', typeof invalidResult);
console.log('Constructor:', invalidResult?.constructor?.name);
console.log('Has symbol property:', 'symbol' in invalidResult);
console.log('Has toString method:', typeof invalidResult?.toString === 'function');
console.log('Has text method:', typeof invalidResult?.text === 'function');
if ('symbol' in invalidResult) {
console.log('NerdamerSymbol property type:', typeof invalidResult.symbol);
console.log('NerdamerSymbol value:', invalidResult.symbol);
console.log('NerdamerSymbol is undefined:', invalidResult.symbol === undefined);
}
// Test 4: Check what a proper NerdamerExpression looks like
console.log('\n--- Test 4: Reference NerdamerExpression ---');
const referenceExpr = nerdamerRuntime('5');
console.log('Reference expression:', referenceExpr);
console.log('Reference type:', typeof referenceExpr);
console.log('Reference constructor:', referenceExpr.constructor.name);
console.log('Reference has symbol:', 'symbol' in referenceExpr);
console.log('Reference toString:', typeof referenceExpr.toString === 'function');
console.log('Reference text:', typeof referenceExpr.text === 'function');
// Verification: Check the specific issue claims
console.log('\n=== Issue Verification ===');
const isValidResultObjectWrapper =
validResult &&
typeof validResult === 'object' &&
'symbol' in validResult &&
validResult.symbol !== undefined;
const isInvalidResultObjectWrapper =
invalidResult &&
typeof invalidResult === 'object' &&
'symbol' in invalidResult &&
invalidResult.symbol === undefined;
console.log('Valid result is object wrapper with symbol:', isValidResultObjectWrapper);
console.log('Invalid result is object wrapper with undefined symbol:', isInvalidResultObjectWrapper);
// Expected vs Actual behavior summary
console.log('\n=== Expected vs Actual Behavior ===');
console.log('EXPECTED: vecget(coeffs, 0) should return NerdamerExpression');
console.log('ACTUAL: vecget(coeffs, 0) returns:', typeof validResult, 'with symbol property');
console.log('EXPECTED: vecget(coeffs, 3) should return undefined');
console.log('ACTUAL: vecget(coeffs, 3) returns:', typeof invalidResult, 'with symbol:', invalidResult?.symbol);
// Assertions to document the current behavior
expect(typeof validResult).toBe('object');
expect('symbol' in validResult).toBe(true);
expect(validResult.symbol).toBeDefined();
expect(typeof invalidResult).toBe('object');
expect('symbol' in invalidResult).toBe(true);
expect(invalidResult.symbol).toBeUndefined();
// The issue: both return objects, but invalid should return undefined
console.log('\n=== ISSUE CONFIRMED ===');
console.log('✓ Valid index returns object wrapper instead of direct NerdamerExpression');
console.log('✓ Invalid index returns object wrapper with undefined symbol instead of undefined');
});
it('should test various vector indices', () => {
console.log('\n=== Testing Various Vector Indices ===');
// Create a longer polynomial to test more coefficients
const expr = nerdamerRuntime('x^3 + 2*x^2 + 3*x + 4');
const coeffs = nerdamerRuntime.coeffs(expr, 'x');
console.log('Expression:', expr.toString());
console.log('Coefficients:', coeffs.toString());
// Test all valid indices
const results = [];
for (let i = 0; i < 4; i++) {
const result = nerdamerRuntime.vecget(coeffs, i);
results.push({
index: i,
result,
type: typeof result,
hasSymbol: 'symbol' in result,
symbolValue: result?.symbol?.toString?.() || result?.symbol,
isUndefined: result === undefined,
});
}
// Test invalid indices
for (let i = 4; i < 7; i++) {
const result = nerdamerRuntime.vecget(coeffs, i);
results.push({
index: i,
result,
type: typeof result,
hasSymbol: 'symbol' in result,
symbolValue: result?.symbol?.toString?.() || result?.symbol,
isUndefined: result === undefined,
});
}
console.log('\nResults summary:');
results.forEach(r => {
console.log(
`Index ${r.index}: type=${r.type}, hasSymbol=${r.hasSymbol}, symbolValue=${r.symbolValue}, isUndefined=${r.isUndefined}`
);
});
// All should be objects (this documents the current behavior)
results.forEach(r => {
expect(r.type).toBe('object');
expect(r.hasSymbol).toBe(true);
expect(r.isUndefined).toBe(false);
});
// Valid indices should have defined symbols
for (let i = 0; i < 4; i++) {
expect(results[i]?.symbolValue).toBeDefined();
expect(results[i]?.symbolValue).not.toBe('undefined');
}
// Invalid indices should have undefined symbols
for (let i = 4; i < 7; i++) {
expect(results[i]?.symbolValue).toBeUndefined();
}
});
});