Skip to content

Commit bbfc7a4

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into add-transaction-to-challenge-join
2 parents c999c76 + e801547 commit bbfc7a4

File tree

188 files changed

+1956
-849
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

188 files changed

+1956
-849
lines changed

README.md

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1-
Habitica ![Build Status](https://github.com/HabitRPG/habitica/workflows/Test/badge.svg) [![Code Climate](https://codeclimate.com/github/HabitRPG/habitrpg.svg)](https://codeclimate.com/github/HabitRPG/habitrpg) [![Bountysource](https://api.bountysource.com/badge/tracker?tracker_id=68393)](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE)
1+
Habitica ![Build Status](https://github.com/HabitRPG/habitica/workflows/Test/badge.svg)
22
===============
33

4-
[Habitica](https://habitica.com) is an open-source habit-building program that treats your life like a role-playing game. Level up as you succeed, lose HP as you fail, and earn money to buy weapons and armor.
4+
[Habitica](https://habitica.com) is an open-source habit-building program that treats your life like a role-playing game. Level up as you succeed, lose HP as you fail, and earn Gold to buy weapons and armor!
55

6-
**We need more programmers!** Your assistance will be greatly appreciated. The wiki pages below and the additional pages they link to will tell you how to get started on contributing code and where you can go to seek further help or ask questions:
6+
**Want to contribute code to Habitica?** We're always looking for assistance on any issues in our repo with the "Help Wanted" label. The wiki pages below and the additional linked pages will tell you how to start contributing code and where you can seek further help or ask questions:
77
* [Guidance for Blacksmiths](https://habitica.fandom.com/wiki/Guidance_for_Blacksmiths) - an introduction to the technologies used and how the software is organized.
8-
* [Setting up Habitica Locally](https://habitica.fandom.com/wiki/Setting_up_Habitica_Locally) - how to set up a local install of Habitica for development and testing on various platforms.
8+
* [Setting up Habitica Locally](https://github.com/HabitRPG/habitica/wiki/Setting-Up-Habitica-for-Local-Development) - how to set up a local install of Habitica for development and testing.
9+
10+
**Interested in contributing to Habitica’s mobile apps?** Visit the links below for our mobile repositories.
11+
* **Android:** https://github.com/HabitRPG/habitica-android
12+
* **iOS:** https://github.com/HabitRPG/habitica-ios
913

1014
Habitica's code is licensed as described at https://github.com/HabitRPG/habitica/blob/develop/LICENSE
1115

12-
**Found a bug?** Please report it to [admin email](mailto:[email protected]) rather than creating an issue (an admin will advise you if a new issue is necessary; usually it is not).
16+
**Found a bug?** Please report it to [admin email](mailto:[email protected]) rather than create an issue (an admin will advise you if a new issue is necessary; usually it is not).
17+
18+
**Creating a third-party tool?** Please review our [API Usage Guidelines](https://github.com/HabitRPG/habitica/wiki/API-Usage-Guidelines) to ensure that your tool is compliant and maintains the best experience for Habitica players.
1319

14-
**Have any questions about Habitica or its community?** See the links in the [habitica.com](https://habitica.com) website's Help menu or drop in to [Guilds > Tavern Chat](https://habitica.com/groups/tavern) to ask questions or chat socially!
20+
**Have any questions about Habitica or contributing?** See the links in the [Habitica](https://habitica.com) website's Help menu. There’s FAQ’s, guides, and the option to reach out to us with any further questions!

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "habitica",
33
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
4-
"version": "5.26.1",
4+
"version": "5.27.0",
55
"main": "./website/server/index.js",
66
"dependencies": {
77
"@babel/core": "^7.22.10",

test/api/v3/integration/chat/GET-chat.test.js

+31
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
createAndPopulateGroup,
44
translate as t,
55
} from '../../../../helpers/api-integration/v3';
6+
import { model as Group } from '../../../../../website/server/models/group';
67

78
describe('GET /groups/:groupId/chat', () => {
89
let user;
@@ -37,4 +38,34 @@ describe('GET /groups/:groupId/chat', () => {
3738
});
3839
});
3940
});
41+
42+
context('public Guild', () => {
43+
let group;
44+
before(async () => {
45+
({ group } = await createAndPopulateGroup({
46+
groupDetails: {
47+
name: 'test group',
48+
type: 'guild',
49+
privacy: 'private',
50+
},
51+
members: 1,
52+
upgradeToGroupPlan: true,
53+
chat: [
54+
'Hello',
55+
'Welcome to the Guild',
56+
],
57+
}));
58+
59+
// Creation API is shut down, we need to simulate an extant public group
60+
await Group.updateOne({ _id: group._id }, { $set: { privacy: 'public' }, $unset: { 'purchased.plan': 1 } }).exec();
61+
});
62+
63+
it('returns error if user attempts to fetch a sunset Guild', async () => {
64+
await expect(user.get(`/groups/${group._id}/chat`)).to.eventually.be.rejected.and.eql({
65+
code: 400,
66+
error: 'BadRequest',
67+
message: t('featureRetired'),
68+
});
69+
});
70+
});
4071
});

test/api/v3/integration/chat/POST-chat.like.test.js

+15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
createAndPopulateGroup,
55
translate as t,
66
} from '../../../../helpers/api-integration/v3';
7+
import { model as Group } from '../../../../../website/server/models/group';
78

89
describe('POST /chat/:chatId/like', () => {
910
let user;
@@ -111,4 +112,18 @@ describe('POST /chat/:chatId/like', () => {
111112
message: t('groupNotFound'),
112113
});
113114
});
115+
116+
it('does not like a message that belongs to a sunset public group', async () => {
117+
const message = await anotherUser.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage });
118+
119+
// Creation API is shut down, we need to simulate an extant public group
120+
await Group.updateOne({ _id: groupWithChat._id }, { $set: { privacy: 'public' }, $unset: { 'purchased.plan': 1 } }).exec();
121+
122+
await expect(user.post(`/groups/${groupWithChat._id}/chat/${message.message.id}/like`))
123+
.to.eventually.be.rejected.and.eql({
124+
code: 400,
125+
error: 'BadRequest',
126+
message: t('featureRetired'),
127+
});
128+
});
114129
});

test/api/v3/integration/world-state/GET-world-state.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ describe('GET /world-state', () => {
123123

124124
const res = await requester().get('/world-state');
125125

126-
expect(res.npcImageSuffix).to.equal('winter');
126+
expect(res.npcImageSuffix).to.equal('fall');
127127
});
128128
});
129129
});

test/common/libs/shops.test.js

+10
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,16 @@ describe('shops', () => {
341341
const backgrounds = shopCategories.find(cat => cat.identifier === 'backgrounds').items;
342342
expect(backgrounds.length).to.be.greaterThan(0);
343343
});
344+
345+
it('does not add an end date to steampunk gear', () => {
346+
const categories = shopCategories.filter(cat => cat.identifier.startsWith('30'));
347+
categories.forEach(category => {
348+
expect(category.end).to.not.exist;
349+
category.items.forEach(item => {
350+
expect(item.end).to.not.exist;
351+
});
352+
});
353+
});
344354
});
345355

346356
describe('customizationShop', () => {

test/common/ops/buy/purchase.test.js

+11
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,17 @@ describe('shared.ops.purchase', () => {
233233
expect(user.items.hatchingPotions[key]).to.eql(1);
234234
});
235235

236+
it('purchases event hatching potion', async () => {
237+
clock.restore();
238+
clock = sandbox.useFakeTimers(moment('2022-04-10').valueOf());
239+
const type = 'hatchingPotions';
240+
const key = 'Veggie';
241+
242+
await purchase(user, { params: { type, key } });
243+
244+
expect(user.items.hatchingPotions[key]).to.eql(1);
245+
});
246+
236247
it('purchases hatching potion if user completed quest', async () => {
237248
const type = 'hatchingPotions';
238249
const key = 'Bronze';

test/content/index.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('content index', () => {
4747
const junePets = content.petInfo;
4848
expect(junePets['Chameleon-Base']).to.not.exist;
4949
clock.restore();
50-
clock = sinon.useFakeTimers(new Date('2024-07-10'));
50+
clock = sinon.useFakeTimers(new Date('2024-07-20'));
5151
const julyPets = content.petInfo;
5252
expect(julyPets['Chameleon-Base']).to.exist;
5353
expect(Object.keys(junePets).length, '').to.equal(Object.keys(julyPets).length - 10);
@@ -58,7 +58,7 @@ describe('content index', () => {
5858
const juneMounts = content.mountInfo;
5959
expect(juneMounts['Chameleon-Base']).to.not.exist;
6060
clock.restore();
61-
clock = sinon.useFakeTimers(new Date('2024-07-10'));
61+
clock = sinon.useFakeTimers(new Date('2024-07-20'));
6262
const julyMounts = content.mountInfo;
6363
expect(julyMounts['Chameleon-Base']).to.exist;
6464
expect(Object.keys(juneMounts).length, '').to.equal(Object.keys(julyMounts).length - 10);

test/content/schedule.test.js

+21-9
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,18 @@ describe('Content Schedule', () => {
123123
expect(matchers.seasonalGear.end).to.eql(moment.utc(`2024-06-21T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate());
124124
});
125125

126+
it('sets the end date for a winter gala', () => {
127+
const date = new Date('2024-12-22');
128+
const matchers = getAllScheduleMatchingGroups(date);
129+
expect(matchers.seasonalGear.end).to.eql(moment.utc(`2025-03-21T${String(switchoverTime).padStart(2, '0')}:00:00.000Z`).toDate());
130+
});
131+
126132
it('contains content for repeating events', () => {
127133
const date = new Date('2024-04-15');
128134
const matchers = getAllScheduleMatchingGroups(date);
129135
expect(matchers.premiumHatchingPotions).to.exist;
130-
expect(matchers.premiumHatchingPotions.items.length).to.equal(4);
131-
expect(matchers.premiumHatchingPotions.items.indexOf('Garden')).to.not.equal(-1);
136+
expect(matchers.premiumHatchingPotions.items.length).to.equal(5);
137+
expect(matchers.premiumHatchingPotions.items.indexOf('Veggie')).to.not.equal(-1);
132138
expect(matchers.premiumHatchingPotions.items.indexOf('Porcelain')).to.not.equal(-1);
133139
});
134140

@@ -245,27 +251,33 @@ describe('Content Schedule', () => {
245251
it('allows sets matching the month', () => {
246252
const date = new Date('2024-07-08');
247253
const matcher = getAllScheduleMatchingGroups(date).timeTravelers;
248-
expect(matcher.match('202307')).to.be.true;
249-
expect(matcher.match('202207')).to.be.true;
254+
expect(matcher.match('202307'), '202307').to.be.true;
255+
expect(matcher.match('202207'), '202207').to.be.true;
250256
});
251257

252258
it('disallows sets not matching the month', () => {
253259
const date = new Date('2024-07-08');
254260
const matcher = getAllScheduleMatchingGroups(date).timeTravelers;
255-
expect(matcher.match('202306')).to.be.false;
256-
expect(matcher.match('202402')).to.be.false;
261+
expect(matcher.match('202306'), '202306').to.be.false;
262+
expect(matcher.match('202402'), '202402').to.be.false;
257263
});
258264

259265
it('disallows sets from current month', () => {
260266
const date = new Date('2024-07-08');
261267
const matcher = getAllScheduleMatchingGroups(date).timeTravelers;
262-
expect(matcher.match('202407')).to.be.false;
268+
expect(matcher.match('202407'), '202407').to.be.false;
263269
});
264270

265271
it('disallows sets from the future', () => {
266272
const date = new Date('2024-07-08');
267-
const matcher = getAllScheduleMatchingGroups(date).backgrounds;
268-
expect(matcher.match('202507')).to.be.false;
273+
const matcher = getAllScheduleMatchingGroups(date).timeTravelers;
274+
expect(matcher.match('202507'), '202507').to.be.false;
275+
});
276+
277+
it('matches sets released in the earlier half of the year', () => {
278+
const date = new Date('2024-07-08');
279+
const matcher = getAllScheduleMatchingGroups(date).timeTravelers;
280+
expect(matcher.match('202401'), '202401').to.be.true;
269281
});
270282
});
271283
});
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)