mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-05 00:15:32 +00:00
feat(web): extend search-graph test-helper funcs to handle specialized spur types
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
Build-bot: skip build:web Test-bot: skip
This commit is contained in:
parent
09db6a4766
commit
9165e8fc65
3 changed files with 95 additions and 2 deletions
|
|
@ -9,9 +9,13 @@
|
|||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { DeletionQuotientSpur, InsertionQuotientSpur } from '@keymanapp/lm-worker/test-index';
|
||||
|
||||
import { constituentPaths } from "./constituentPaths.js";
|
||||
import { toSpurTypeSequence } from './toSpurTypeSequence.js';
|
||||
import { buildCantLinearFixture } from './buildCantLinearFixture.js';
|
||||
import { buildAlphabeticClusterFixtures } from './buildAlphabeticClusteredFixture.js';
|
||||
import { buildQuotientDocFixture } from './buildQuotientDocFixture.js';
|
||||
|
||||
describe('constituentPaths', () => {
|
||||
it('includes a single entry array when all parents are SearchQuotientSpurs', () => {
|
||||
|
|
@ -42,4 +46,50 @@ describe('constituentPaths', () => {
|
|||
return p;
|
||||
}));
|
||||
});
|
||||
|
||||
describe('for the final quotient-graph doc example', () => {
|
||||
it('handles insertion-only quotient-graph paths', () => {
|
||||
const { sc2 } = buildQuotientDocFixture().nodes;
|
||||
|
||||
const sc2Constituents = constituentPaths(sc2);
|
||||
assert.equal(sc2Constituents.length, 1);
|
||||
sc2Constituents.forEach(s => s.forEach(p => assert.isTrue(p instanceof InsertionQuotientSpur)));
|
||||
});
|
||||
|
||||
it('handles deletion-only quotient-graph paths', () => {
|
||||
const { k2c0 } = buildQuotientDocFixture().nodes;
|
||||
|
||||
const k2c0Constituents = constituentPaths(k2c0);
|
||||
assert.equal(k2c0Constituents.length, 1);
|
||||
k2c0Constituents.forEach(s => s.forEach(p => assert.isTrue(p instanceof DeletionQuotientSpur)));
|
||||
});
|
||||
|
||||
it('does not emit sequences with inserts immediately following deletes', () => {
|
||||
const { k2c3 } = buildQuotientDocFixture().nodes;
|
||||
|
||||
const k2c3Constituents = constituentPaths(k2c3);
|
||||
|
||||
const shouldNotOccur = k2c3Constituents.find((seq) => {
|
||||
const typeSeq = toSpurTypeSequence(seq);
|
||||
return typeSeq.find((type, index) => {
|
||||
return type == 'delete' && typeSeq[index+1] == 'insert';
|
||||
});
|
||||
});
|
||||
assert.isNotOk(shouldNotOccur);
|
||||
});
|
||||
|
||||
it('does emit sequences with deletes immediately following inserts', () => {
|
||||
const { k2c3 } = buildQuotientDocFixture().nodes;
|
||||
|
||||
const k2c3Constituents = constituentPaths(k2c3);
|
||||
|
||||
const shouldOccur = k2c3Constituents.find((seq) => {
|
||||
const typeSeq = toSpurTypeSequence(seq);
|
||||
return typeSeq.find((type, index) => {
|
||||
return type == 'insert' && typeSeq[index+1] == 'delete';
|
||||
});
|
||||
});
|
||||
assert.isNotOk(shouldOccur);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
DeletionQuotientSpur,
|
||||
InsertionQuotientSpur,
|
||||
SearchQuotientCluster,
|
||||
SearchQuotientNode,
|
||||
SearchQuotientRoot,
|
||||
|
|
@ -26,8 +28,29 @@ export function constituentPaths(node: SearchQuotientNode): SearchQuotientSpur[]
|
|||
} else if(node instanceof SearchQuotientCluster) {
|
||||
return node.parents.flatMap((p) => constituentPaths(p));
|
||||
} else if(node instanceof SearchQuotientSpur) {
|
||||
const parentPaths = constituentPaths(node.parents[0]);
|
||||
let pathsToExtend = parentPaths;
|
||||
const parentPaths = constituentPaths(node.parents[0]); let pathsToExtend = parentPaths;
|
||||
|
||||
if(node instanceof InsertionQuotientSpur) {
|
||||
pathsToExtend = pathsToExtend.filter(s => {
|
||||
const tail = s[s.length - 1];
|
||||
|
||||
// Deletion nodes and modules should always be ordered after those for
|
||||
// insertion in order to avoid duplicating search paths. (Insertions may
|
||||
// stick to the right of a root, while deletions always process inputs; they
|
||||
// may thus precede deletions.)
|
||||
//
|
||||
// Also, internally, insertion edges are not built after deletion (or empty) edges.
|
||||
if(tail instanceof DeletionQuotientSpur) {
|
||||
return false;
|
||||
} else if(tail.insertLength == 0 && tail.leftDeleteLength == 0) {
|
||||
// Insertions should also not appear after empty nodes; there's no net
|
||||
// difference between inserting before and inserting after.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
if(parentPaths.length > 0) {
|
||||
return pathsToExtend.map(p => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
import {
|
||||
DeletionQuotientSpur,
|
||||
InsertionQuotientSpur,
|
||||
SearchQuotientNode,
|
||||
SubstitutionQuotientSpur
|
||||
} from "@keymanapp/lm-worker/test-index";
|
||||
|
||||
export function toSpurTypeSequence(spurs: SearchQuotientNode[]): ('insert' | 'delete' | 'substitute' | 'legacy')[] {
|
||||
return spurs.map(s => {
|
||||
if(s instanceof InsertionQuotientSpur) {
|
||||
return 'insert';
|
||||
} else if(s instanceof DeletionQuotientSpur) {
|
||||
return 'delete';
|
||||
} else if(s instanceof SubstitutionQuotientSpur) {
|
||||
return 'substitute';
|
||||
} else {
|
||||
return 'legacy';
|
||||
}
|
||||
})
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue