From 4baea8a5a5d4799ade46c48687b6897152d4859c Mon Sep 17 00:00:00 2001 From: Jean Date: Sun, 3 Aug 2025 16:43:17 -0700 Subject: [PATCH] Adding unit test script --- metamorpov-test.js | 212 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 213 insertions(+), 1 deletion(-) create mode 100755 metamorpov-test.js diff --git a/metamorpov-test.js b/metamorpov-test.js new file mode 100755 index 0000000..7aa4b30 --- /dev/null +++ b/metamorpov-test.js @@ -0,0 +1,212 @@ +const assert = require('node:assert'); +const metamorpov = require('./metamorpov'); + +const options = { + firstPerson: { + name: "Amy", + preset: "she", + pov: "first" + }, + secondPerson: { + name: "Amy", + preset: "she", + pov: "second" + }, + thirdPerson: { + name: "Amy", + preset: "she", + pov: "third" + }, + thirdPersonPlural: { + name: "Amy", + preset: "they", + pov: "third" + }, + thirdPersonOther: { + name: "Amy", + preset: "other", + pov: "third", + other: { + "subjective": "xie", + "objective": "xer", + "possessive": "xer", + "adjective": "xers", + "reflexive": "xerself", + "honorific-abbr": "Mx.", + "honorific": "mix", + "adult": "person", + "youth": "kid", + "parent": "parent", + "child": "child", + "sibling": "sibling", + "married": "spouse", + "dating": "partner", + "plurality": "singular" + } + }, + also: { + name: "Amy", + preset: "she", + pov: "first", + also: { + "Amy": "Amelia", + "abc": "abc abc", + "cde": "cde", + "slash": "\/" + } + } +} + +/* vrb, vrn */ +assert.equal(metamorpov.translate("vrb/be/", options.firstPerson), "was"); // I was +assert.equal(metamorpov.translate("vrb/be/", options.secondPerson), "were"); // You were +assert.equal(metamorpov.translate("vrb/be/", options.thirdPerson), "was"); // She was +assert.equal(metamorpov.translate("vrb/be/", options.thirdPersonPlural), "were"); // They were +assert.equal(metamorpov.translate("vrb/be/", options.thirdPersonOther), "was"); // Xie was +assert.equal(metamorpov.translate("vrB/be/", options.firstPerson), "was"); // I was +assert.equal(metamorpov.translate("vrB/be/", options.thirdPerson), "was"); // Amy was +assert.equal(metamorpov.translate("Vrb/be/", options.firstPerson), "Was"); // Was I +assert.equal(metamorpov.translate("Vrb/be/", options.secondPerson), "Were"); // Were you +assert.equal(metamorpov.translate("vrb/present/be/", options.firstPerson), "am"); // I am +assert.equal(metamorpov.translate("vrb/present/be/", options.secondPerson), "are"); // You are +assert.equal(metamorpov.translate("vrn/present/be/", options.firstPerson), "is"); // She is +assert.equal(metamorpov.translate("vrn/present/be/", options.thirdPerson), "is"); // She is +assert.equal(metamorpov.translate("vrb/be/ good", options.firstPerson), "was good"); // Should continue after replacing +assert.equal(metamorpov.translate("vrb/be/ vrb/have/", options.firstPerson), "was had"); // Should replace both + +/* pov */ +assert.equal(metamorpov.translate("pov/s", options.firstPerson), "I"); +assert.equal(metamorpov.translate("pov/s", options.secondPerson), "you"); +assert.equal(metamorpov.translate("pov/s", options.thirdPerson), "she"); +assert.equal(metamorpov.translate("pov/s", options.thirdPersonPlural), "they"); +assert.equal(metamorpov.translate("pov/s", options.thirdPersonOther), "xie"); +assert.equal(metamorpov.translate("pov/S", options.firstPerson), "I"); +assert.equal(metamorpov.translate("pov/S", options.thirdPerson), "Amy"); +assert.equal(metamorpov.translate("pov/o", options.firstPerson), "me"); +assert.equal(metamorpov.translate("pov/o", options.secondPerson), "you"); +assert.equal(metamorpov.translate("pov/o", options.thirdPerson), "her"); +assert.equal(metamorpov.translate("pov/o", options.thirdPersonOther), "xer"); +assert.equal(metamorpov.translate("pov/O", options.firstPerson), "me"); +assert.equal(metamorpov.translate("pov/O", options.thirdPerson), "Amy"); +assert.equal(metamorpov.translate("pov/p", options.firstPerson), "my"); +assert.equal(metamorpov.translate("pov/p", options.secondPerson), "your"); +assert.equal(metamorpov.translate("pov/p", options.thirdPerson), "her"); +assert.equal(metamorpov.translate("pov/p", options.thirdPersonOther), "xer"); +assert.equal(metamorpov.translate("pov/a", options.firstPerson), "mine"); +assert.equal(metamorpov.translate("pov/a", options.secondPerson), "yours"); +assert.equal(metamorpov.translate("pov/a", options.thirdPerson), "hers"); +assert.equal(metamorpov.translate("pov/a", options.thirdPersonOther), "xers"); +assert.equal(metamorpov.translate("pov/r", options.firstPerson), "myself"); +assert.equal(metamorpov.translate("pov/r", options.secondPerson), "yourself"); +assert.equal(metamorpov.translate("pov/r", options.thirdPerson), "herself"); +assert.equal(metamorpov.translate("pov/r", options.thirdPersonOther), "xerself"); +assert.equal(metamorpov.translate("pov/s knew", options.firstPerson), "I knew"); // Should continue after replacing +assert.equal(metamorpov.translate("pov/s pov/r", options.firstPerson), "I myself"); // Should replace both + +/* plv */ +assert.equal(metamorpov.translate("plv/s", options.firstPerson), "we"); +assert.equal(metamorpov.translate("plv/s", options.secondPerson), "you"); +assert.equal(metamorpov.translate("plv/s", options.thirdPerson), "they"); +assert.equal(metamorpov.translate("plv/s", options.thirdPersonPlural), "they"); +assert.equal(metamorpov.translate("plv/s", options.thirdPersonOther), "they"); +assert.equal(metamorpov.translate("plv/S", options.firstPerson), "plv/S"); // Reference by name doesn't make sense for a group +assert.equal(metamorpov.translate("plv/s knew", options.firstPerson), "we knew"); // Should continue after replacing +assert.equal(metamorpov.translate("plv/s plv/r", options.firstPerson), "we ourselves"); // Should replace both + +/* y/n */ +assert.equal(metamorpov.translate("Y/n", options.firstPerson), "Amy"); +assert.equal(metamorpov.translate("y/n", options.firstPerson), "Amy"); // All lowercase +assert.equal(metamorpov.translate("Y/N", options.firstPerson), "Amy"); // All uppercase +assert.equal(metamorpov.translate("yn", options.firstPerson), "yn"); // Invalid, ignored +assert.equal(metamorpov.translate("Y/n knew", options.firstPerson), "Amy knew"); // Should continue after replacing +assert.equal(metamorpov.translate("Y/n Y/n", options.firstPerson), "Amy Amy"); // Should replace both + +/* prn */ +assert.equal(metamorpov.translate("prn/s", options.firstPerson), "she"); +assert.equal(metamorpov.translate("prn/s", options.secondPerson), "she"); +assert.equal(metamorpov.translate("prn/s", options.thirdPerson), "she"); +assert.equal(metamorpov.translate("prn/s", options.thirdPersonPlural), "they"); +assert.equal(metamorpov.translate("prn/s", options.thirdPersonOther), "xie"); +assert.equal(metamorpov.translate("prn/s knew", options.firstPerson), "she knew"); // Should continue after replacing +assert.equal(metamorpov.translate("prn/s prn/s", options.firstPerson), "she she"); // Should replace both + +/* also */ +assert.equal(metamorpov.translate("Y/n was here", options.also), "Amelia was here"); // Should run after Y/n +assert.equal(metamorpov.translate("abc", options.also), "abc abc"); // Shouldn't recurse +assert.equal(metamorpov.translate("cde", options.also), "cde"); // Also shouldn't recurse +assert.equal(metamorpov.translate("slash", options.also), "\/"); // Shouldn't crash with special characters +assert.equal(metamorpov.translate("Amy was here", options.also), "Amelia was here"); // Should continue after replacing +assert.equal(metamorpov.translate("abc abc", options.also), "abc abc abc abc"); // Should replace both + +/* alt */ +assert.equal(metamorpov.translate("alt/first/a/", options.firstPerson), "a"); +assert.equal(metamorpov.translate("alt/first/a/", options.secondPerson), ""); +assert.equal(metamorpov.translate("alt/first and second/a/", options.firstPerson), "a"); +assert.equal(metamorpov.translate("alt/first and second/a/", options.secondPerson), "a"); +assert.equal(metamorpov.translate("alt/third and first/a/", options.thirdPerson), "a"); +assert.equal(metamorpov.translate("alt/first or second/a/b/", options.firstPerson), "a"); +assert.equal(metamorpov.translate("alt/first or second/a/b/", options.secondPerson), "b"); +assert.equal(metamorpov.translate("alt/first and second or third/a/b/", options.firstPerson), "a"); +assert.equal(metamorpov.translate("alt/first and second or third/a/b/", options.secondPerson), "a"); +assert.equal(metamorpov.translate("alt/first and second or third/a/b/", options.thirdPerson), "b"); +assert.equal(metamorpov.translate("alt/first and second or third/a/b/", options.thirdPerson), "b"); +assert.equal(metamorpov.translate("alt/first or second or third/a/b/c/", options.thirdPerson), "c"); +assert.equal(metamorpov.translate("alt/a/b/c/", options.thirdPerson), "c"); +assert.equal(metamorpov.translate("alt/first and first/a/", options.firstPerson), "alt/first and first/a/"); // Invalid, ignored +assert.equal(metamorpov.translate("alt/first and second and third/a/", options.firstPerson), "alt/first and second and third/a/"); // Invalid, ignored +assert.equal(metamorpov.translate("alt/first/a/bcdef", options.firstPerson), "abcdef"); // Should continue after replacing +assert.equal(metamorpov.translate("alt/first/a/ alt/first/bc/", options.firstPerson), "a bc"); // Should replace both + +/* if, ife */ +assert.equal(metamorpov.translate("if/prn/n is girl/bestie/", options.firstPerson), "bestie"); // prn/n is "girl" so if +assert.equal(metamorpov.translate("if/prn/n is girl/bestie/", options.thirdPersonPlural), ""); // prn/n is "kid" so nothing +assert.equal(metamorpov.translate("ife/prn/n is girl/bestie/broski/", options.firstPerson), "bestie"); // prn/n is "girl" so if +assert.equal(metamorpov.translate("ife/prn/n is girl/bestie/broski/", options.thirdPersonOther), "broski"); // prn/n is "kid" so else +assert.equal(metamorpov.translate("if/a is a/abc/def", options.firstPerson), "abcdef"); // Should continue after replacing +assert.equal(metamorpov.translate("if/a is a/abc/ if/b is b/def/", options.firstPerson), "abc def"); // Should replace both + +/* cut */ +assert.equal(metamorpov.translate("cut/off first -1/word/", options.firstPerson), "cut/off first -1/word/"); // Ignore negatives +assert.equal(metamorpov.translate("cut/off first 0/word/", options.firstPerson), "cut/off first 0/word/"); // Ignore zero +assert.equal(metamorpov.translate("cut/off first 1/word/", options.firstPerson), "ord"); +assert.equal(metamorpov.translate("cut/off first 2/word/", options.firstPerson), "rd"); +assert.equal(metamorpov.translate("cut/off first 3/word/", options.firstPerson), "d"); +assert.equal(metamorpov.translate("cut/off first 4/word/", options.firstPerson), "d"); // Keep at least one letter +assert.equal(metamorpov.translate("cut/off first 5/word/", options.firstPerson), "d"); // Don't worry about out-of-bounds +assert.equal(metamorpov.translate("cut/off last 1/word/", options.firstPerson), "wor"); +assert.equal(metamorpov.translate("cut/off last 2/word/", options.firstPerson), "wo"); +assert.equal(metamorpov.translate("cut/off last 3/word/", options.firstPerson), "w"); +assert.equal(metamorpov.translate("cut/off last 4/word/", options.firstPerson), "w"); // Keep at least one letter +assert.equal(metamorpov.translate("cut/only first 1/word/", options.firstPerson), "w"); +assert.equal(metamorpov.translate("cut/only first 2/word/", options.firstPerson), "wo"); +assert.equal(metamorpov.translate("cut/only first 3/word/", options.firstPerson), "wor"); +assert.equal(metamorpov.translate("cut/only first 4/word/", options.firstPerson), "wor"); // Cut at least one letter +assert.equal(metamorpov.translate("cut/only last 1/word/", options.firstPerson), "d"); +assert.equal(metamorpov.translate("cut/only last 2/word/", options.firstPerson), "rd"); +assert.equal(metamorpov.translate("cut/only last 3/word/", options.firstPerson), "ord"); +assert.equal(metamorpov.translate("cut/only last 4/word/", options.firstPerson), "ord"); // Cut at least one letter +assert.equal(metamorpov.translate("cut/only first 1/word/oah", options.firstPerson), "woah"); // Should continue after replacing +assert.equal(metamorpov.translate("cut/off last 1/ab/ cut/only last 2/abc/", options.firstPerson), "a bc"); // Should replace both + +/* cap */ +assert.equal(metamorpov.translate("cap/WORD/", options.firstPerson), "word"); // All to lowercase +assert.equal(metamorpov.translate("Cap/word/", options.firstPerson), "Word"); // First letter to capital +assert.equal(metamorpov.translate("CAP/word/", options.firstPerson), "WORD"); // All to capital +assert.equal(metamorpov.translate("Cap/woRD/", options.firstPerson), "WoRD"); // First letter to capital, other letters stay capital +assert.equal(metamorpov.translate("cAP/word/", options.firstPerson), "cAP/word/"); // Avoid case insensitivity +assert.equal(metamorpov.translate("cap/WORD/?", options.firstPerson), "word?"); // Should continue after replacing +assert.equal(metamorpov.translate("cap/NO/ CAP/way/", options.firstPerson), "no WAY"); // Should replace both + +/* mrr */ +assert.equal(metamorpov.translate("mrr/word/", options.firstPerson), "drow"); +assert.equal(metamorpov.translate("mrr/Y/n/", options.firstPerson), "ymA"); // Should run after Y/n +assert.equal(metamorpov.translate("mrr/word/sy", options.firstPerson), "drowsy"); // Should continue after replacing +assert.equal(metamorpov.translate("mrr/word/ mrr/drow/", options.firstPerson), "drow word"); // Should replace both + +/* a/an */ +assert.equal(metamorpov.translate("a/an pear", options.firstPerson), "a pear"); // Starts with a consonant sound +assert.equal(metamorpov.translate("a/an apple", options.firstPerson), "an apple"); // Starts with a vowel sound +assert.equal(metamorpov.translate("a/an hour", options.firstPerson), "an hour"); // Starts with a vowel sound despite consonant letter +assert.equal(metamorpov.translate("a/an 1800s-era", options.firstPerson), "an 1800s-era"); // "Eighteen-hundreds" starts with a vowel sound + +console.log("Test succeeded"); diff --git a/package.json b/package.json index e41c818..63e5681 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "description": "Enables customization of reader-insert stories by replacing author-provided hooks such as Y/n, pov/s, and vrb/do/present/.", "main": "metamorpov.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node metamorpov-test.js" }, "author": "Jean Viscogliosi-Pate", "license": "GPL-3.0-or-later",