Skip to content

Commit 2870145

Browse files
committed
Squashed commit of the following:
commit 28193f8 Author: Phillip Thelen <[email protected]> Date: Fri Jun 21 11:12:18 2024 +0200 Fix serving memoized content commit 877fe48 Author: Phillip Thelen <[email protected]> Date: Thu Jun 20 12:23:24 2024 +0200 correctly memoize conent api commit e0f6f79 Author: Phillip Thelen <[email protected]> Date: Thu Jun 20 10:11:27 2024 +0200 don’t build multiple times on heroku commit f62254d Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 19:40:20 2024 +0200 fix client command commit d054e6f Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 19:36:57 2024 +0200 correct build call commit 7231f69 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 19:32:32 2024 +0200 try setting up with heroku buildpack commit 1dae079 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:50:32 2024 +0200 call gulp build:prod commit f18fbe8 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:40:53 2024 +0200 build client commit 61a6172 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:33:18 2024 +0200 testing commit 93cf30e Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:20:25 2024 +0200 integration fix commit cff08ad Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:13:20 2024 +0200 specify dev docker file commit 4da2ed4 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:10:07 2024 +0200 initialize stub commit 11c5b26 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:08:45 2024 +0200 test heroku file commit ac85bb2 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:03:15 2024 +0200 fix stub reference commit 74dfb27 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 18:01:27 2024 +0200 test fixes commit 8dbd3c3 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 17:37:04 2024 +0200 fix canOwn test commit 74b3b34 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 17:32:31 2024 +0200 fix buy test commit 3386d61 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 17:30:37 2024 +0200 fix debug tests commit 19da145 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 17:05:25 2024 +0200 add chameleon to featured quests commit 254dd80 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 17:05:14 2024 +0200 fix import commit 0bc3f16 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 16:33:22 2024 +0200 add new content to new release file commit 5184973 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 16:33:11 2024 +0200 fix release date tests commit b6accca Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 16:33:06 2024 +0200 fix armoire tests commit fec68e6 Author: Phillip Thelen <[email protected]> Date: Wed Jun 19 16:02:03 2024 +0200 fix tests commit fc63c90 Author: Phillip Thelen <[email protected]> Date: Mon Jun 10 14:44:21 2024 +0200 Improve test coverage commit 3333f8f Author: Phillip Thelen <[email protected]> Date: Mon Jun 10 14:24:59 2024 +0200 allow hatching potions to have a release date commit 89a3ac3 Author: Phillip Thelen <[email protected]> Date: Mon Jun 10 14:11:38 2024 +0200 allow eggs to have a release date # Conflicts: # test/content/armoire.test.js commit 16551ec Merge: f5f4974 2645bf6 Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 15:03:12 2024 -0400 Merge branch '2024-07-content-prebuild' into subs-private commit 2645bf6 Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 15:02:47 2024 -0400 update habitica images commit f5f4974 Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 14:58:13 2024 -0400 update habitica-images commit 162e337 Merge: f2506c3 21a7d36 Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 13:46:03 2024 -0400 Merge branch '2024-07-content-prebuild' into subs-private commit 21a7d36 Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 13:45:09 2024 -0400 update sprites commit f2506c3 Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 13:24:21 2024 -0400 updated sprites css commit d47641e Author: CuriousMagpie <[email protected]> Date: Tue Jun 18 12:46:59 2024 -0400 typo fix commit fb8479a Author: CuriousMagpie <[email protected]> Date: Mon Jun 17 13:44:36 2024 -0400 finish July prebuild commit 3810cf3 Author: CuriousMagpie <[email protected]> Date: Fri Jun 14 10:42:47 2024 -0400 add chameleon quest commit d05da37 Author: CuriousMagpie <[email protected]> Date: Thu Jun 13 17:12:43 2024 -0400 add June background notes commit b8a3440 Author: CuriousMagpie <[email protected]> Date: Thu Jun 13 16:40:04 2024 -0400 fix mystery item and background description commit 44d6303 Author: CuriousMagpie <[email protected]> Date: Thu Jun 13 15:38:23 2024 -0400 add subscriber gear, enchanted armoire, and background commit 9d7da91 Author: CuriousMagpie <[email protected]> Date: Thu Jun 13 14:44:59 2024 -0400 add sprites
1 parent b46e2da commit 2870145

31 files changed

+974
-466
lines changed

Dockerfile-Dev

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ FROM node:20
33
# Install global packages
44
RUN npm install -g gulp-cli mocha
55

6-
# Copy package.json and package-lock.json into image, then install
7-
# dependencies.
6+
# Copy package.json and package-lock.json into image
87
WORKDIR /usr/src/habitica
98
COPY ["package.json", "package-lock.json", "./"]
109
# Copy the remaining source files in.
1110
COPY . /usr/src/habitica
11+
# Install dependencies
1212
RUN npm install
13+
RUN npm run postinstall
14+
RUN npm run client:build
15+
RUN gulp build:prod

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,9 @@
107107
"debug": "gulp nodemon --inspect",
108108
"mongo:dev": "run-rs -v 5.0.23 -l ubuntu1804 --keep --dbpath mongodb-data --number 1 --quiet",
109109
"postinstall": "git config --global url.\"https://\".insteadOf git:// && gulp build && cd website/client && npm install",
110-
"apidoc": "gulp apidoc"
110+
"apidoc": "gulp apidoc",
111+
112+
"heroku-postbuild": "npm run client:build"
111113
},
112114
"devDependencies": {
113115
"axios": "^1.4.0",

test/api/unit/libs/content.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('contentLib', () => {
5555
beforeEach(() => {
5656
resSpy = generateRes();
5757
if (fs.existsSync(contentLib.CONTENT_CACHE_PATH)) {
58-
fs.rmdirSync(contentLib.CONTENT_CACHE_PATH, { recursive: true });
58+
fs.rmSync(contentLib.CONTENT_CACHE_PATH, { recursive: true });
5959
}
6060
fs.mkdirSync(contentLib.CONTENT_CACHE_PATH);
6161
});

test/common/ops/armoireCanOwn.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import armoireSet from '../../../website/common/script/content/gear/sets/armoire
33
describe('armoireSet items', () => {
44
it('checks if canOwn has the same id', () => {
55
Object.keys(armoireSet).forEach(type => {
6+
if (type === 'all') return;
67
Object.keys(armoireSet[type]).forEach(itemKey => {
78
const ownedKey = `${type}_armoire_${itemKey}`;
89
expect(armoireSet[type][itemKey].canOwn({

test/content/armoire.test.js

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,26 @@ import forEach from 'lodash/forEach';
33
import {
44
expectValidTranslationString,
55
} from '../helpers/content.helper';
6-
7-
function makeArmoireIitemList () {
8-
const armoire = require('../../website/common/script/content/gear/sets/armoire').default;
9-
const items = [];
10-
items.push(...Object.values(armoire.armor));
11-
items.push(...Object.values(armoire.body));
12-
items.push(...Object.values(armoire.eyewear));
13-
items.push(...Object.values(armoire.head));
14-
items.push(...Object.values(armoire.headAccessory));
15-
items.push(...Object.values(armoire.shield));
16-
items.push(...Object.values(armoire.weapon));
17-
return items;
18-
}
6+
import armoire from '../../website/common/script/content/gear/sets/armoire';
197

208
describe('armoire', () => {
219
let clock;
22-
beforeEach(() => {
23-
delete require.cache[require.resolve('../../website/common/script/content/gear/sets/armoire')];
24-
});
2510
afterEach(() => {
26-
clock.restore();
11+
if (clock) {
12+
clock.restore();
13+
}
2714
});
15+
2816
it('does not return unreleased gear', async () => {
2917
clock = sinon.useFakeTimers(new Date('2024-01-02'));
30-
const items = makeArmoireIitemList();
18+
const items = armoire.all;
3119
expect(items.length).to.equal(377);
3220
expect(items.filter(item => item.set === 'pottersSet' || item.set === 'optimistSet' || item.set === 'schoolUniform')).to.be.an('array').that.is.empty;
3321
});
3422

3523
it('released gear has all required properties', async () => {
3624
clock = sinon.useFakeTimers(new Date('2024-05-08'));
37-
const items = makeArmoireIitemList();
25+
const items = armoire.all;
3826
expect(items.length).to.equal(396);
3927
forEach(items, item => {
4028
if (item.set !== undefined) {
@@ -48,29 +36,30 @@ describe('armoire', () => {
4836

4937
it('releases gear when appropriate', async () => {
5038
clock = sinon.useFakeTimers(new Date('2024-01-01T00:00:00.000Z'));
51-
const items = makeArmoireIitemList();
39+
const items = armoire.all;
5240
expect(items.length).to.equal(377);
5341
clock.restore();
5442
delete require.cache[require.resolve('../../website/common/script/content/gear/sets/armoire')];
5543
clock = sinon.useFakeTimers(new Date('2024-01-08'));
56-
const januaryItems = makeArmoireIitemList();
44+
const januaryItems = armoire.all;
5745
expect(januaryItems.length).to.equal(381);
5846
clock.restore();
5947
delete require.cache[require.resolve('../../website/common/script/content/gear/sets/armoire')];
6048
clock = sinon.useFakeTimers(new Date('2024-02-07'));
61-
const januaryItems2 = makeArmoireIitemList();
49+
const januaryItems2 = armoire.all;
6250
expect(januaryItems2.length).to.equal(381);
6351
clock.restore();
6452
delete require.cache[require.resolve('../../website/common/script/content/gear/sets/armoire')];
65-
clock = sinon.useFakeTimers(new Date('2024-02-07T16:00:00.000Z'));
66-
const febuaryItems = makeArmoireIitemList();
53+
clock = sinon.useFakeTimers(new Date('2024-02-07T09:00:00.000Z'));
54+
const febuaryItems = armoire.all;
6755
expect(febuaryItems.length).to.equal(384);
6856
});
6957

7058
it('sets have at least 2 items', () => {
71-
const armoire = makeArmoireIitemList();
7259
const setMap = {};
73-
forEach(armoire, item => {
60+
forEach(armoire.all, item => {
61+
// Gotta have one outlier
62+
if (!item.set || item.set.startsWith('armoire-')) return;
7463
if (setMap[item.set] === undefined) {
7564
setMap[item.set] = 0;
7665
}

test/content/eggs.test.js

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,51 @@ import {
55
expectValidTranslationString,
66
} from '../helpers/content.helper';
77

8-
import * as eggs from '../../website/common/script/content/eggs';
8+
import eggs from '../../website/common/script/content/eggs';
99

1010
describe('eggs', () => {
11-
describe('all', () => {
12-
it('is a combination of drop and quest eggs', () => {
13-
const dropNumber = Object.keys(eggs.drops).length;
14-
const questNumber = Object.keys(eggs.quests).length;
15-
const allNumber = Object.keys(eggs.all).length;
11+
let clock;
1612

17-
expect(allNumber).to.be.greaterThan(0);
18-
expect(allNumber).to.equal(dropNumber + questNumber);
19-
});
13+
afterEach(() => {
14+
if (clock) {
15+
clock.restore();
16+
}
17+
});
2018

21-
it('contains basic information about each egg', () => {
22-
each(eggs.all, (egg, key) => {
23-
expectValidTranslationString(egg.text);
24-
expectValidTranslationString(egg.adjective);
25-
expectValidTranslationString(egg.mountText);
26-
expectValidTranslationString(egg.notes);
27-
expect(egg.canBuy).to.be.a('function');
28-
expect(egg.value).to.be.a('number');
29-
expect(egg.key).to.equal(key);
19+
const eggTypes = [
20+
'drops',
21+
'quests',
22+
];
23+
24+
eggTypes.forEach(eggType => {
25+
describe(eggType, () => {
26+
it('contains basic information about each egg', () => {
27+
each(eggs[eggType], (egg, key) => {
28+
expectValidTranslationString(egg.text);
29+
expectValidTranslationString(egg.adjective);
30+
expectValidTranslationString(egg.mountText);
31+
expectValidTranslationString(egg.notes);
32+
expect(egg.canBuy).to.be.a('function');
33+
expect(egg.value).to.be.a('number');
34+
expect(egg.key).to.equal(key);
35+
});
3036
});
3137
});
3238
});
39+
40+
it('does not contain unreleased eggs', () => {
41+
clock = sinon.useFakeTimers(new Date('2024-05-20'));
42+
const questEggs = eggs.quests;
43+
expect(questEggs.Giraffe).to.not.exist;
44+
});
45+
46+
it('Releases eggs when appropriate without needing restarting', () => {
47+
clock = sinon.useFakeTimers(new Date('2024-05-20'));
48+
const mayEggs = eggs.quests;
49+
clock.restore();
50+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
51+
const juneEggs = eggs.quests;
52+
expect(juneEggs.Giraffe).to.exist;
53+
expect(Object.keys(mayEggs).length).to.equal(Object.keys(juneEggs).length - 1);
54+
});
3355
});

test/content/index.test.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import content from '../../website/common/script/content';
2+
3+
describe('content index', () => {
4+
let clock;
5+
6+
afterEach(() => {
7+
if (clock) {
8+
clock.restore();
9+
}
10+
});
11+
12+
it('Releases eggs when appropriate without needing restarting', () => {
13+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
14+
const mayEggs = content.eggs;
15+
expect(mayEggs.Chameleon).to.not.exist;
16+
clock.restore();
17+
clock = sinon.useFakeTimers(new Date('2024-07-20'));
18+
const juneEggs = content.eggs;
19+
expect(juneEggs.Chameleon).to.exist;
20+
expect(Object.keys(mayEggs).length, '').to.equal(Object.keys(juneEggs).length - 1);
21+
});
22+
23+
it('Releases hatching potions when appropriate without needing restarting', () => {
24+
clock = sinon.useFakeTimers(new Date('2024-05-20'));
25+
const mayHatchingPotions = content.hatchingPotions;
26+
expect(mayHatchingPotions.Koi).to.not.exist;
27+
clock.restore();
28+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
29+
const juneHatchingPotions = content.hatchingPotions;
30+
expect(juneHatchingPotions.Koi).to.exist;
31+
expect(Object.keys(mayHatchingPotions).length, '').to.equal(Object.keys(juneHatchingPotions).length - 1);
32+
});
33+
34+
it('Releases armoire gear when appropriate without needing restarting', () => {
35+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
36+
const juneGear = content.gear.flat;
37+
expect(juneGear.armor_armoire_corsairsCoatAndCape).to.not.exist;
38+
clock.restore();
39+
clock = sinon.useFakeTimers(new Date('2024-07-10'));
40+
const julyGear = content.gear.flat;
41+
expect(julyGear.armor_armoire_corsairsCoatAndCape).to.exist;
42+
expect(Object.keys(juneGear).length, '').to.equal(Object.keys(julyGear).length - 3);
43+
});
44+
45+
it('Releases pets gear when appropriate without needing restarting', () => {
46+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
47+
const junePets = content.petInfo;
48+
expect(junePets['Chameleon-Base']).to.not.exist;
49+
clock.restore();
50+
clock = sinon.useFakeTimers(new Date('2024-07-10'));
51+
const julyPets = content.petInfo;
52+
expect(julyPets['Chameleon-Base']).to.exist;
53+
expect(Object.keys(junePets).length, '').to.equal(Object.keys(julyPets).length - 10);
54+
});
55+
56+
it('Releases mounts gear when appropriate without needing restarting', () => {
57+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
58+
const juneMounts = content.mountInfo;
59+
expect(juneMounts['Chameleon-Base']).to.not.exist;
60+
clock.restore();
61+
clock = sinon.useFakeTimers(new Date('2024-07-10'));
62+
const julyMounts = content.mountInfo;
63+
expect(julyMounts['Chameleon-Base']).to.exist;
64+
expect(Object.keys(juneMounts).length, '').to.equal(Object.keys(julyMounts).length - 10);
65+
});
66+
67+
it('marks regular food as buyable and droppable without any events', () => {
68+
clock = sinon.useFakeTimers(new Date('2024-06-20'));
69+
const { food } = content;
70+
Object.keys(food).forEach(key => {
71+
if (key === 'Saddle') {
72+
expect(food[key].canBuy(), `${key} canBuy`).to.be.true;
73+
expect(food[key].canDrop, `${key} canDrop`).to.be.false;
74+
return;
75+
}
76+
let expected = true;
77+
if (key.startsWith('Cake_')) {
78+
expected = false;
79+
} else if (key.startsWith('Candy_')) {
80+
expected = false;
81+
} else if (key.startsWith('Pie_')) {
82+
expected = false;
83+
}
84+
expect(food[key].canBuy(), `${key} canBuy`).to.equal(expected);
85+
expect(food[key].canDrop, `${key} canDrop`).to.equal(expected);
86+
});
87+
});
88+
89+
it('marks candy as buyable and droppable during habitoween', () => {
90+
clock = sinon.useFakeTimers(new Date('2024-10-31'));
91+
const { food } = content;
92+
Object.keys(food).forEach(key => {
93+
if (key === 'Saddle') {
94+
expect(food[key].canBuy(), `${key} canBuy`).to.be.true;
95+
expect(food[key].canDrop, `${key} canDrop`).to.be.false;
96+
return;
97+
}
98+
let expected = false;
99+
if (key.startsWith('Cake_')) {
100+
expected = false;
101+
} else if (key.startsWith('Candy_')) {
102+
expected = true;
103+
} else if (key.startsWith('Pie_')) {
104+
expected = false;
105+
}
106+
expect(food[key].canBuy(), `${key} canBuy`).to.equal(expected);
107+
expect(food[key].canDrop, `${key} canDrop`).to.equal(expected);
108+
});
109+
});
110+
111+
it('marks cake as buyable and droppable during birthday', () => {
112+
clock = sinon.useFakeTimers(new Date('2024-01-31'));
113+
const { food } = content;
114+
Object.keys(food).forEach(key => {
115+
if (key === 'Saddle') {
116+
expect(food[key].canBuy(), `${key} canBuy`).to.be.true;
117+
expect(food[key].canDrop, `${key} canDrop`).to.be.false;
118+
return;
119+
}
120+
let expected = false;
121+
if (key.startsWith('Cake_')) {
122+
expected = true;
123+
} else if (key.startsWith('Candy_')) {
124+
expected = false;
125+
} else if (key.startsWith('Pie_')) {
126+
expected = false;
127+
}
128+
expect(food[key].canBuy(), `${key} canBuy`).to.equal(expected);
129+
expect(food[key].canDrop, `${key} canDrop`).to.equal(expected);
130+
});
131+
});
132+
133+
it('marks pie as buyable and droppable during pi day', () => {
134+
clock = sinon.useFakeTimers(new Date('2024-03-14'));
135+
const { food } = content;
136+
Object.keys(food).forEach(key => {
137+
if (key === 'Saddle') {
138+
expect(food[key].canBuy(), `${key} canBuy`).to.be.true;
139+
expect(food[key].canDrop, `${key} canDrop`).to.be.false;
140+
return;
141+
}
142+
let expected = false;
143+
if (key.startsWith('Cake_')) {
144+
expected = false;
145+
} else if (key.startsWith('Candy_')) {
146+
expected = false;
147+
} else if (key.startsWith('Pie_')) {
148+
expected = true;
149+
}
150+
expect(food[key].canBuy(), `${key} canBuy`).to.equal(expected);
151+
expect(food[key].canDrop, `${key} canDrop`).to.equal(expected);
152+
});
153+
});
154+
});

0 commit comments

Comments
 (0)