diff --git a/common/web/types/.gitignore b/common/web/types/.gitignore index 2f943a2f4e9..dcb567b832b 100644 --- a/common/web/types/.gitignore +++ b/common/web/types/.gitignore @@ -1,2 +1,3 @@ src/schemas/ -obj/ \ No newline at end of file +obj/ +coverage/ diff --git a/common/web/types/test/ldml-keyboard/test-string-list.ts b/common/web/types/test/ldml-keyboard/test-string-list.ts new file mode 100644 index 00000000000..58365bda66b --- /dev/null +++ b/common/web/types/test/ldml-keyboard/test-string-list.ts @@ -0,0 +1,216 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by Dr Mark C. Sinclair on 2024-11-28 + * + * Test code for string-lists.ts + */ + +import 'mocha'; +import { assert } from 'chai'; +import { StrsItem, StrsOptions, DependencySections, Strs } from '../../src/kmx/kmx-plus/kmx-plus.js'; +import { ListIndex, ListItem } from '../../src/ldml-keyboard/string-list.js'; + +describe('Test of String-List', () => { + describe('Test ListIndex', () => { + it('can construct a ListIndex', () => { + const strsItem = new StrsItem("abc"); + const actual = new ListIndex(strsItem); + assert.deepEqual(actual.value, strsItem); + }); + it('can check two ListIndex for equality', () => { + const listItemOne = new ListIndex(new StrsItem("abc")); + const listItemTwo = new ListIndex(new StrsItem("abc")); + assert.isTrue(listItemOne.isEqual(listItemTwo)); + }); + it('can check two different ListIndex are not equal', () => { + const listItemOne = new ListIndex(new StrsItem("abc")); + const listItemTwo = new ListIndex(new StrsItem("def")); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('can check a ListIndex and string for equality', () => { + const listItem = new ListIndex(new StrsItem("abc")); + const aString = "abc"; + assert.isTrue(listItem.isEqual(aString)); + }); + it('can check a ListIndex and string for inequality', () => { + const listItem = new ListIndex(new StrsItem("abc")); + const aString = "def"; + assert.isFalse(listItem.isEqual(aString)); + }); + it('can provide a correct string representation', () => { + const strsItem = new StrsItem("abc"); + const listItem = new ListIndex(strsItem); + const expected = "abc"; + assert.deepEqual(listItem.toString(), expected); + }); + }); + describe('Test ListItem', () => { + describe('Test fromStrings()', () => { + it('should return an empty ListItem if source is null', () => { + const actual = ListItem.fromStrings(null, null, null); + const expected = new ListItem(); + assert.deepEqual(actual, expected); + }); + it('should return a valid ListItem from a single source string', () => { + const source = ["abc"]; + const sections = { strs: new Strs }; + sections.strs.allocString = stubSectionsStrsAllocString; + const actual = ListItem.fromStrings(source, null, sections); + const expected = initListItem(source); + assert.deepEqual(actual, expected); + }); + it('should return a valid ListItem from a longer source', () => { + const source = ["abc", "def", "ghi"]; + const sections = { strs: new Strs }; + sections.strs.allocString = stubSectionsStrsAllocString; + const actual = ListItem.fromStrings(source, null, sections); + const expected = initListItem(source); + assert.deepEqual(actual, expected); + }); + }); + describe('Test getItemOrder()', () => { + it('should return a valid index for the first item', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + const index = listItem.getItemOrder("abc"); + assert.equal(index, 0); + }); + it('should return a valid index for a later item', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + const index = listItem.getItemOrder("ghi"); + assert.equal(index, 2); + }); + it('should return -1 for a missing item', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + const index = listItem.getItemOrder("jkl"); + assert.equal(index, -1); + }); + }); + describe('Test isEqual()', () => { + it('should return true for two empty ListItems', () => { + const listItemOne = new ListItem(); + const listItemTwo = new ListItem(); + assert.isTrue(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for empty and non-empty ListItems', () => { + const listItemOne = new ListItem(); + const listItemTwo = initListItem(["abc"]); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for non-empty and empty ListItems', () => { + const listItemOne = initListItem(["abc"]); + const listItemTwo = new ListItem(); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return true for identical ListItems', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.isTrue(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for different ListItems', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abd", "def", "ghi"]); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return false for different length ListItems', () => { + const listItemOne = initListItem(["abc", "def"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.isFalse(listItemOne.isEqual(listItemTwo)); + }); + it('should return true for empty ListItem and string[]', () => { + const listItem = new ListItem(); + assert.isTrue(listItem.isEqual([])); + }); + it('should return false for empty ListItem and non-empty string[]', () => { + const listItem = new ListItem(); + assert.isFalse(listItem.isEqual(["abc"])); + }); + it('should return false for non-empty ListItem and empty string[]', () => { + const listItem = initListItem(["abc"]);; + assert.isFalse(listItem.isEqual([])); + }); + it('should return true for identical ListItem and string[]', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + assert.isTrue(listItem.isEqual(["abc", "def", "ghi"])); + }); + it('should return false for different ListItem and string[]', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + assert.isFalse(listItem.isEqual(["abd", "def", "ghi"])); + }); + it('should return false for different length ListItem and string[]', () => { + const listItem = initListItem(["abc", "def"]); + assert.isFalse(listItem.isEqual(["abc", "def", "ghi"])); + }); + }); + describe('Test compareTo()', () => { + it('should return 0 for identical ListItems', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 0); + }); + it('should return -1 for ListItems with different first items (smallest first)', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abd", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), -1); + }); + it('should return 1 for ListItems with different first items (smallest second)', () => { + const listItemOne = initListItem(["abd", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 1); + }); + it('should return -1 for ListItems with different later items (smallest first)', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghj"]); + assert.equal(listItemOne.compareTo(listItemTwo), -1); + }); + it('should return 1 for ListItems with different later items (smallest second)', () => { + const listItemOne = initListItem(["abc", "def", "ghj"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 1); + }); + it('should return -1 for identical ListItems, except shorter first', () => { + const listItemOne = initListItem(["abc", "def", "ghi"]); + const listItemTwo = initListItem(["abc", "def", "ghi", "jkl"]); + assert.equal(listItemOne.compareTo(listItemTwo), -1); + }); + it('should return 1 for identical ListItems, except longer first', () => { + const listItemOne = initListItem(["abc", "def", "ghi", "jkl"]); + const listItemTwo = initListItem(["abc", "def", "ghi"]); + assert.equal(listItemOne.compareTo(listItemTwo), 1); + }); + }); + describe('Test toString()', () => { + it('should return correct string', () => { + const listItem = initListItem(["abc", "def", "ghi"]); + assert.deepEqual(listItem.toString(), "abc def ghi"); + }); + it('should return correct string for empty ListItem', () => { + const listItem = new ListItem; + assert.deepEqual(listItem.toString(), ""); + }); + }); + describe('Test toStringArray()', () => { + it('should return correct string[]', () => { + const source = ["abc", "def", "ghi"]; + const listItem = initListItem(source); + assert.deepEqual(listItem.toStringArray(), source); + }); + it('should return correct string[] for empty ListItem', () => { + const listItem = new ListItem; + assert.deepEqual(listItem.toStringArray(), []); + }); + }); + }); +}); + +function stubSectionsStrsAllocString(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { + return new StrsItem(s); +} + +function initListItem(source: Array): ListItem { + const listItem = new ListItem(); + for (const s of source) { + listItem.push(new ListIndex(new StrsItem(s))); + } + return listItem; +}