Skip to content

Commit b7895ca

Browse files
committed
Create basic data model.
* Can add and remove words and tags on words. * Sorts the words by length and alphabetically. * Capitalizes all words in the database.
1 parent 82d5b0f commit b7895ca

2 files changed

Lines changed: 186 additions & 0 deletions

File tree

src/WordStore.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* The data model for the Word Cookies Worksheet.
3+
*/
4+
class WordStore {
5+
#wordsData = [];
6+
7+
_findWord(word) {
8+
return this.#wordsData.find((W) => (W.word === word));
9+
}
10+
11+
/**
12+
* @typedef {Object} WordData a structure containing all the information about a word
13+
* @property {string} word
14+
* @property {string|number} [tag]
15+
*/
16+
17+
/**
18+
* Gets the compiled list of word data.
19+
*
20+
* The words are sorted first by length and then alphabetically.
21+
*
22+
* @returns {WordData[]} sorted list of word structures
23+
*/
24+
get words() {
25+
return this.#wordsData.sort(
26+
(a, b) =>
27+
(a.word.length - b.word.length)
28+
|| (a.word.localeCompare(b.word))
29+
);
30+
}
31+
32+
/**
33+
* Adds words to the list.
34+
* @param {string} words
35+
*/
36+
addWords(...words) {
37+
for (let word of words) {
38+
word = word.toLocaleUpperCase();
39+
let data = this._findWord(word);
40+
if (data === undefined) {
41+
this.#wordsData.push({word});
42+
}
43+
}
44+
}
45+
46+
/**
47+
* Removes words from the list.
48+
* @param {string} words
49+
*/
50+
removeWords(...words) {
51+
for (let word of words) {
52+
word = word.toLocaleUpperCase();
53+
this.#wordsData = this.#wordsData.filter((W) => (W.word !== word));
54+
}
55+
}
56+
57+
/**
58+
* Tags a word.
59+
*
60+
* If the word does not yet exist in the database,
61+
* it is added with the given tag attached.
62+
*
63+
* @param {string} word
64+
* @param {string|number} tag
65+
*/
66+
tagWord(word, tag) {
67+
word = word.toLocaleUpperCase();
68+
let data = this._findWord(word);
69+
if (data === undefined) {
70+
this.#wordsData.push({word, tag});
71+
} else {
72+
data.tag = tag;
73+
}
74+
}
75+
76+
/**
77+
* Removes any tags from the given word.
78+
*
79+
* If the word does not yet exist in the database,
80+
* it is added with no tag attached.
81+
*
82+
* @param {string} word
83+
*/
84+
untagWord(word) {
85+
word = word.toLocaleUpperCase();
86+
let data = this._findWord(word);
87+
if (data === undefined) {
88+
this.addWords(word);
89+
} else {
90+
delete data.tag;
91+
}
92+
}
93+
}
94+
95+
export default WordStore;

src/WordStore.test.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import WordStore from "./WordStore";
2+
3+
4+
function expectedWords(...wordList) {
5+
return wordList
6+
.map(word => ( (typeof word === 'object') ? word : {word} ));
7+
}
8+
9+
10+
test('new data model has no words', () => {
11+
let wd = new WordStore();
12+
expect(wd.words).toEqual([]);
13+
});
14+
15+
test('add a word', () => {
16+
let wd = new WordStore();
17+
wd.addWords('ABC');
18+
expect(wd.words).toEqual(expectedWords('ABC'));
19+
});
20+
21+
test('add multiple words', () => {
22+
let wd = new WordStore();
23+
wd.addWords('ABC', 'DEF');
24+
expect(wd.words).toEqual(expectedWords('ABC', 'DEF'));
25+
})
26+
27+
test('add a duplicate word', () => {
28+
let wd = new WordStore();
29+
wd.addWords('ABC');
30+
wd.addWords('ABC');
31+
expect(wd.words).toEqual(expectedWords('ABC'));
32+
});
33+
34+
test('words are sorted', () => {
35+
let wd = new WordStore();
36+
wd.addWords('QWERTY', 'ABC', 'UIOP', 'XYZ', 'DEF', 'FURBY');
37+
expect(wd.words).toEqual(expectedWords('ABC', 'DEF', 'XYZ', 'UIOP', 'FURBY', 'QWERTY'));
38+
});
39+
40+
test('remove a word', () => {
41+
let wd = new WordStore();
42+
wd.addWords('ABC', 'DEF');
43+
wd.removeWords('ABC');
44+
expect(wd.words).toEqual(expectedWords('DEF'));
45+
});
46+
47+
test('remove multiple words', () => {
48+
let wd = new WordStore();
49+
wd.addWords('ABC', 'DEF', 'XYZ');
50+
wd.removeWords('ABC', 'XYZ');
51+
expect(wd.words).toEqual(expectedWords('DEF'));
52+
});
53+
54+
test('tag a word', () => {
55+
let wd = new WordStore();
56+
wd.addWords('ABC');
57+
wd.tagWord('ABC', 1);
58+
expect(wd.words).toEqual(expectedWords({word: 'ABC', tag: 1}));
59+
});
60+
61+
test('tag a new word', () => {
62+
let wd = new WordStore();
63+
wd.tagWord('ABC', 1);
64+
expect(wd.words).toEqual(expectedWords({word: 'ABC', tag: 1}));
65+
});
66+
67+
test('untag a word', () => {
68+
let wd = new WordStore();
69+
wd.tagWord('ABC', 1);
70+
wd.untagWord('ABC');
71+
expect(wd.words).toEqual(expectedWords('ABC'));
72+
});
73+
74+
test('untag a new word', () => {
75+
let wd = new WordStore();
76+
wd.untagWord('ABC');
77+
expect(wd.words).toEqual(expectedWords('ABC'));
78+
});
79+
80+
test('words are capitalized in all operations', () => {
81+
let wd = new WordStore();
82+
wd.addWords('abc', 'def');
83+
expect(wd.words).toEqual(expectedWords('ABC', 'DEF'));
84+
wd.removeWords('def');
85+
expect(wd.words).toEqual(expectedWords('ABC'));
86+
wd.tagWord('abc', 1);
87+
expect(wd.words).toEqual(expectedWords({word: 'ABC', tag: 1}));
88+
wd.untagWord('abc');
89+
expect(wd.words).toEqual(expectedWords('ABC'));
90+
});
91+

0 commit comments

Comments
 (0)