diff --git a/src/topic/__tests__/TopicMolecule.setProchiralHydrogenLabels.test.js b/src/topic/__tests__/TopicMolecule.setProchiralHydrogenLabels.test.js index e346f40..5591b14 100644 --- a/src/topic/__tests__/TopicMolecule.setProchiralHydrogenLabels.test.js +++ b/src/topic/__tests__/TopicMolecule.setProchiralHydrogenLabels.test.js @@ -1,5 +1,5 @@ import { Molecule } from 'openchemlib'; -import { expect, test } from 'vitest'; +import { expect, onTestFinished, test, vi } from 'vitest'; import { TopicMolecule } from '../TopicMolecule'; @@ -204,30 +204,35 @@ test('canonizedProchiralities is transferred across TopicMolecule instances with // (e.g. after expanding hydrogens) should not recompute CIP. const molecule = Molecule.fromSmiles('CC(Cl)CC'); const original = new TopicMolecule(molecule); - const labels = original.prochiralities; - const labelledCount = labels.filter((l) => l !== undefined).length; - expect(labelledCount).toBe(2); + // Compute the original labels once, populating its prochirality cache. + expect( + original.prochiralities.filter((l) => l !== undefined).toSorted(), + ).toStrictEqual(['r', 's']); - const oclModule = molecule.getOCL().Molecule; - let cipCalls = 0; - const originalEnsure = oclModule.prototype.ensureHelperArrays; - oclModule.prototype.ensureHelperArrays = function spy(bits) { - if (bits === oclModule.cHelperCIP) cipCalls++; - return originalEnsure.call(this, bits); - }; + // Count only the dedicated CIP computation (the exact cHelperCIP bit); + // composite requests that merely include that bit are unrelated. + const oclMolecule = molecule.getOCL().Molecule; + const spy = vi.spyOn(oclMolecule.prototype, 'ensureHelperArrays'); + onTestFinished(() => spy.mockRestore()); - try { - const reused = original.fromMolecule(molecule); - const reusedLabels = reused.prochiralities; + const reused = original.fromMolecule(molecule); - expect( - reusedLabels.filter((l) => l !== undefined).toSorted(), - ).toStrictEqual(['r', 's']); - expect(cipCalls).toBe(0); - } finally { - oclModule.prototype.ensureHelperArrays = originalEnsure; - } + // The transferred entry is the very same object: that shared reference is the + // whole optimisation — there is nothing to recompute. + expect(reused.cache.prochiralityByEnantioID).toBe( + original.cache.prochiralityByEnantioID, + ); + + expect( + reused.prochiralities.filter((l) => l !== undefined).toSorted(), + ).toStrictEqual(['r', 's']); + + const cipCalls = spy.mock.calls.filter( + ([bits]) => bits === oclMolecule.cHelperCIP, + ).length; + + expect(cipCalls).toBe(0); }); test('CC(Cl)CC: implicit-H molecule gets no labels, only moleculeWithH does', () => { diff --git a/src/topic/__tests__/getCanonizedDiaIDs.test.js b/src/topic/__tests__/getCanonizedDiaIDs.test.js index 5eee4de..215e641 100644 --- a/src/topic/__tests__/getCanonizedDiaIDs.test.js +++ b/src/topic/__tests__/getCanonizedDiaIDs.test.js @@ -1,5 +1,5 @@ import { Molecule } from 'openchemlib'; -import { expect, test } from 'vitest'; +import { expect, onTestFinished, test, vi } from 'vitest'; import { TopicMolecule } from '../TopicMolecule'; @@ -10,22 +10,14 @@ test('symmetric atoms with the same heterotopic rank share a cached diaID (no re const topicMolecule = new TopicMolecule(molecule); const oclModule = molecule.getOCL().Molecule; - let canonizationCalls = 0; - const originalGetCanonizedIDCode = oclModule.prototype.getCanonizedIDCode; - oclModule.prototype.getCanonizedIDCode = function spy(...args) { - canonizationCalls++; - return originalGetCanonizedIDCode.apply(this, args); - }; - - try { - const diaIDs = topicMolecule.diaIDs; - - expect(diaIDs).toHaveLength(12); - expect(canonizationCalls).toBe(2); - expect(new Set(diaIDs).size).toBe(2); - } finally { - oclModule.prototype.getCanonizedIDCode = originalGetCanonizedIDCode; - } + const spy = vi.spyOn(oclModule.prototype, 'getCanonizedIDCode'); + onTestFinished(() => spy.mockRestore()); + + const diaIDs = topicMolecule.diaIDs; + + expect(diaIDs).toHaveLength(12); + expect(spy).toHaveBeenCalledTimes(2); + expect(new Set(diaIDs).size).toBe(2); }); test('a molecule with all-distinct atoms still gets one canonization per atom', () => {