@launchmenu/core
Version:
An environment for visual keyboard controlled applets
204 lines • 22.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const seededRandom_helper_1 = require("../../../../_tests/seededRandom.helper");
const TextAlterationTools_1 = require("../TextAlterationTools");
describe("TextAlterationTools", () => {
describe("TextAlterationTools.mergeAlterations", () => {
it("Should update the index to represent the index before the base alterations were made", () => {
const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars
[{ start: 20, end: 20, text: "orange" }]);
expect(combined).toEqual([
{ start: 10, end: 15, text: "hi" },
{ start: 23, end: 23, text: "orange" },
]);
const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([
{ start: 2, end: 2, text: "oran" },
{ start: 10, end: 15, text: "hi" },
{ start: 24, end: 28, text: "hi" },
], [{ start: 20, end: 20, text: "orange" }]);
expect(combined2).toEqual([
{ start: 2, end: 2, text: "oran" },
{ start: 10, end: 15, text: "hi" },
{ start: 19, end: 19, text: "orange" },
{ start: 24, end: 28, text: "hi" },
]);
});
describe("Should merge adjacent alterations", () => {
it("Should merge properly at the start", () => {
const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars, partially after
[{ start: 11, end: 11, text: "orange" }]);
expect(combined).toEqual([{ start: 10, end: 15, text: "horangei" }]);
const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([
{ start: 2, end: 2, text: "oran" },
{ start: 10, end: 15, text: "hi" },
{ start: 24, end: 28, text: "hi" },
], [{ start: 15, end: 18, text: "orange" }]);
expect(combined2).toEqual([
{ start: 2, end: 2, text: "oran" },
{ start: 10, end: 17, text: "horange" },
{ start: 24, end: 28, text: "hi" },
]);
/*
1. __________=====_________====__
2. __oran________hi_________hi__
3. __oran________horange_______hi__
*/
});
it("Should merge properly at the end", () => {
const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars, partially after
[{ start: 8, end: 11, text: "orange" }]);
expect(combined).toEqual([{ start: 8, end: 15, text: "orangei" }]);
const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([
{ start: 2, end: 2, text: "oran" },
{ start: 10, end: 15, text: "hi" },
{ start: 24, end: 28, text: "hi" },
], [{ start: 8, end: 15, text: "orange" }]);
expect(combined2).toEqual([
{ start: 2, end: 2, text: "oran" },
{ start: 4, end: 15, text: "orangei" },
{ start: 24, end: 28, text: "hi" },
]);
/*
1. __________=====_________====__
2. __oran________hi_________hi__
3. __oran__orangei_________hi__
*/
});
it("Should merge properly when replacing a whole change", () => {
const combined = TextAlterationTools_1.TextAlterationTools.mergeAlterations([{ start: 10, end: 15, text: "hi" }], // - 3 chars
[{ start: 8, end: 13, text: "orange" }]);
expect(combined).toEqual([{ start: 8, end: 16, text: "orange" }]);
const combined2 = TextAlterationTools_1.TextAlterationTools.mergeAlterations([
{ start: 2, end: 2, text: "oran" },
{ start: 10, end: 15, text: "hi" },
{ start: 24, end: 28, text: "hi" },
], [{ start: 8, end: 20, text: "orange" }]);
expect(combined2).toEqual([
{ start: 2, end: 2, text: "oran" },
{ start: 4, end: 19, text: "orange" },
{ start: 24, end: 28, text: "hi" },
]);
/*
1. __________=====_________====__
2. __oran________hi_________hi__
3. __oran__orange_____hi__
*/
});
});
describe("Should deal with complex scenarios", () => {
it("Should work properly with advanced alterations", () => {
const inpText = "oranges are cool stuff when bought in a set of 56. That's a magical number that will allow you to not eat them all at once, cus it be a ton of oranges.";
const baseAlterations = [
{ start: 5, end: 8, text: "POTATOES" },
{ start: 8, end: 14, text: "" },
{ start: 19, end: 19, text: "BOB" },
{ start: 35, end: 45, text: "TOMATO" },
];
const alterations = [
{ start: 5, end: 10, text: "" },
{ start: 13, end: 20, text: "ORANGE" },
{ start: 22, end: 22, text: "PURPLE" },
{ start: 45, end: 48, text: "PANTS" },
];
testAlterationMerge(inpText, baseAlterations, alterations);
});
it("Should work properly with advanced alterations (Generated #663)", () => {
const inpText = "nqpkfgqeaarytfdobkyezicujqbyqxjzcdlgspkfmdwmkoywuaqtlrmcdkucvduudrryoxvvgqjefdsbqzgpyovbepkqhxzayhfsiomkgtaocrgrkjqgbrbjwqpkoxhm";
const baseAlterations = [
{ start: 18, end: 18, text: "QOSRB" },
];
const alterations = [
{ start: 21, end: 21, text: "RPZWBSPDQFMHMYGP" },
{ start: 21, end: 33, text: "" },
];
testAlterationMerge(inpText, baseAlterations, alterations);
});
it(`Should work properly on advanced alterations (Generated tests)`, () => {
for (let i = 1; i < 1e3; i++) {
executeRandomAlterationMergeTest(i);
}
});
});
});
});
/**
* Performs a test alteration merge test, for the given inputs
* @param input The input text
* @param baseAlterations The base alterations to merge
* @param alterations The alterations to merge into the base alterations
*/
function testAlterationMerge(inpText, baseAlterations, alterations) {
// Execute the 2 steps of alterations separately
const intermediateText = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, baseAlterations);
const finalText = TextAlterationTools_1.TextAlterationTools.performAlterations(intermediateText, alterations);
// Combine the 2 steps, and perform them at once
const combinedAlterations = TextAlterationTools_1.TextAlterationTools.mergeAlterations(baseAlterations, alterations);
const finalTextMerged = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, combinedAlterations);
// Check these 2 things are equal
expect(finalTextMerged).toEqual(finalText);
}
/**
* Generates a random alteration merging test
* @param seed The seed to generate the test with
*/
function executeRandomAlterationMergeTest(seed) {
const random = seededRandom_helper_1.getSeededRandom(seed);
// Generate the input text
const inpLength = Math.floor(30 + random() * 200);
const chars = "abcdefghijklmnopqrstuvwxyz";
const inpText = new Array(inpLength)
.fill(0)
.map(() => chars[Math.floor(random() * chars.length)])
.join("");
// Generate the base alterations
const baseAlterations = generateAlterations(inpLength, random);
// Get the intermediate text representation when these changes are applied
const intermediateText = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, baseAlterations);
// Generate the further alterations
const alterations = generateAlterations(intermediateText.length, random);
// Obtain the final text
const finalText = TextAlterationTools_1.TextAlterationTools.performAlterations(intermediateText, alterations);
// Combine the base and further alterations
const combinedAlterations = TextAlterationTools_1.TextAlterationTools.mergeAlterations(baseAlterations, alterations);
const finalTextMerged = TextAlterationTools_1.TextAlterationTools.performAlterations(inpText, combinedAlterations);
// Check if the direct and are indirect approach yield equivalent results
const testID = `#${seed.toString()}-`;
try {
expect(testID + finalTextMerged).toEqual(testID + finalText);
}
catch (e) {
e.message += `\n text: "${inpText}" \n baseAlterations: ${JSON.stringify(baseAlterations)} \n alterations: ${JSON.stringify(alterations)}`;
throw e;
}
}
/**
* Generates text alterations in a given range
* @param inpLength The range in which alterations are allowed
* @param random The function to use to create random values
* @returns The alterations
*/
function generateAlterations(inpLength, random) {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const alterations = [];
let index = 0;
while (index < inpLength) {
// Generate some start and end indices
index += Math.floor(random() * 30);
const start = index;
index += random() > 0.5 ? 0 : Math.floor(random() * 15); // 50% chance of being a text insert
const end = index;
// Make sure the range is valid
if (end < inpLength) {
// Generate the replacement text, with 50% probability of being nothing
const repLength = random() > 0.5 && end != start ? 0 : Math.floor(random() * 25);
const text = new Array(repLength)
.fill(0)
.map(() => chars[Math.floor(random() * chars.length)])
.join("");
// Add the alteration
alterations.push({ start, end, text });
}
}
return alterations;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGV4dEFsdGVyYXRpb25Ub29scy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy90ZXh0RmllbGRzL2ludGVyYWN0aW9uL2NvbW1hbmRzL190ZXN0cy9UZXh0QWx0ZXJhdGlvblRvb2xzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsZ0ZBQXVFO0FBQ3ZFLGdFQUEyRDtBQUczRCxRQUFRLENBQUMscUJBQXFCLEVBQUUsR0FBRyxFQUFFO0lBQ2pDLFFBQVEsQ0FBQyxzQ0FBc0MsRUFBRSxHQUFHLEVBQUU7UUFDbEQsRUFBRSxDQUFDLHNGQUFzRixFQUFFLEdBQUcsRUFBRTtZQUM1RixNQUFNLFFBQVEsR0FBRyx5Q0FBbUIsQ0FBQyxnQkFBZ0IsQ0FDakQsQ0FBQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUMsRUFBRSxZQUFZO1lBQ2hELENBQUMsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBQyxDQUFDLENBQ3pDLENBQUM7WUFFRixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDO2dCQUNyQixFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFDO2dCQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFDO2FBQ3ZDLENBQUMsQ0FBQztZQUVILE1BQU0sU0FBUyxHQUFHLHlDQUFtQixDQUFDLGdCQUFnQixDQUNsRDtnQkFDSSxFQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFDO2dCQUNoQyxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFF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