88 lines
4.0 KiB
JavaScript
88 lines
4.0 KiB
JavaScript
import { test } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import * as THREE from 'three'
|
|
import './test-support.mjs'
|
|
|
|
const { createCardMaterial, applyMaterialControls } = await import('../src/cardMaterial.ts')
|
|
const {
|
|
captureExperimentMaterialControls, restoreExperimentMaterialControls, isExperimentSnapshot,
|
|
} = await import('../src/experimentSnapshot.ts')
|
|
|
|
const materialControls = {
|
|
finish: 'Foil', substrate: 'Metal', finishStrength: 0.6, roughness: 0.23,
|
|
normalStrength: 0.72, environmentIntensity: 0.7, condition: 0.8, imperfectionSeed: 81251,
|
|
}
|
|
function snapshot(controls = materialControls) {
|
|
return {
|
|
schemaVersion: 2, runtimeRevision: 'runtime-look-v4-2026-09-07',
|
|
name: 'Metal orientation', savedAt: '2026-09-12T00:00:00Z', fixture: 'David',
|
|
...captureExperimentMaterialControls(controls),
|
|
lightingPreset: 'Studio', environment: 'Studio', lightType: 'Point', lightColor: '#fff0d0',
|
|
lightPosition: [2.2, 2.5, 4.4], lightIntensity: 3, exposure: 1,
|
|
cardRotation: [-0.06, 0.12, 0], cameraPosition: [0, 0, 8.2], orbitTarget: [0, 0, 0],
|
|
}
|
|
}
|
|
function material() {
|
|
return createCardMaterial(new THREE.Texture(), new THREE.Texture(), new THREE.Texture(),
|
|
new THREE.CubeTexture(), new THREE.Vector3())
|
|
}
|
|
|
|
test('Metal defaults to vertical; toggling orientation updates uniforms without rebuilding the shader', () => {
|
|
const card = material()
|
|
try {
|
|
assert.equal(card.uniforms.metalBrushHorizontal.value, false)
|
|
applyMaterialControls(card, materialControls)
|
|
const version = card.version
|
|
const shader = card.fragmentShader
|
|
for (const horizontal of [true, false, true]) {
|
|
applyMaterialControls(card, { ...materialControls, metalBrushHorizontal: horizontal })
|
|
assert.equal(card.uniforms.metalBrushHorizontal.value, horizontal)
|
|
assert.equal(card.uniforms.finishMode.value, 1)
|
|
assert.equal(card.uniforms.substrateMode.value, 3)
|
|
assert.equal(card.uniforms.normalStrength.value, 0.72)
|
|
assert.equal(card.version, version)
|
|
assert.equal(card.fragmentShader, shader)
|
|
}
|
|
applyMaterialControls(card, materialControls)
|
|
assert.equal(card.uniforms.metalBrushHorizontal.value, false, 'omitted live controls use the new default')
|
|
} finally { card.dispose() }
|
|
})
|
|
|
|
test('Both metal grain orientations survive experiment JSON save/import and material application', () => {
|
|
const card = material()
|
|
try {
|
|
for (const horizontal of [false, true]) {
|
|
const saved = JSON.parse(JSON.stringify(snapshot({ ...materialControls, metalBrushHorizontal: horizontal })))
|
|
assert.equal(isExperimentSnapshot(saved), true)
|
|
const restored = restoreExperimentMaterialControls(saved)
|
|
assert.deepEqual(restored, { ...materialControls, metalBrushHorizontal: horizontal })
|
|
applyMaterialControls(card, restored)
|
|
assert.equal(card.uniforms.metalBrushHorizontal.value, horizontal)
|
|
assert.equal(card.uniforms.normalStrength.value, 0.72, 'detail above the old 0.45 import limit survives')
|
|
}
|
|
} finally { card.dispose() }
|
|
})
|
|
|
|
test('Legacy experiments without orientation retain horizontal grain and schema 1 wear defaults', () => {
|
|
const legacy = snapshot()
|
|
delete legacy.metalBrushHorizontal
|
|
assert.equal(isExperimentSnapshot(legacy), true)
|
|
assert.equal(restoreExperimentMaterialControls(legacy).metalBrushHorizontal, true)
|
|
legacy.schemaVersion = 1
|
|
delete legacy.condition
|
|
delete legacy.imperfectionSeed
|
|
assert.equal(isExperimentSnapshot(legacy), true)
|
|
assert.deepEqual(restoreExperimentMaterialControls(legacy), {
|
|
...materialControls, metalBrushHorizontal: true, condition: 1, imperfectionSeed: 81251,
|
|
})
|
|
})
|
|
|
|
test('Experiment validation rejects malformed orientation values rather than coercing them', () => {
|
|
for (const value of ['horizontal', 'false', 0, 1, null, {}, []]) {
|
|
assert.equal(isExperimentSnapshot({ ...snapshot(), metalBrushHorizontal: value }), false)
|
|
}
|
|
const bounded = restoreExperimentMaterialControls({ ...snapshot(), normalStrength: 2, roughness: -1 })
|
|
assert.equal(bounded.normalStrength, 1)
|
|
assert.equal(bounded.roughness, 0.05)
|
|
})
|