mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 23:27:26 +01:00
New User Tasks for Mobile (#8682)
* feat(mobile): different default tasks * fix(linting): missing space * fix(user): correct client type logic * test(integration): tasks by platform * fix(test): remove only * test(user): deeper checks on tasks * refactor(test): whitespace for readability
This commit is contained in:
@@ -37,7 +37,8 @@ describe('POST /user/auth/local/register', () => {
|
|||||||
expect(user.newUser).to.eql(true);
|
expect(user.newUser).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('provides default tags and tasks', async () => {
|
context('provides default tags and tasks', async () => {
|
||||||
|
it('for a generic API consumer', async () => {
|
||||||
let username = generateRandomUserName();
|
let username = generateRandomUserName();
|
||||||
let email = `${username}@example.com`;
|
let email = `${username}@example.com`;
|
||||||
let password = 'password';
|
let password = 'password';
|
||||||
@@ -49,11 +50,193 @@ describe('POST /user/auth/local/register', () => {
|
|||||||
confirmPassword: password,
|
confirmPassword: password,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(user.tags).to.have.a.lengthOf(7);
|
let requests = new ApiUser(user);
|
||||||
expect(user.tasksOrder.todos).to.have.a.lengthOf(1);
|
|
||||||
expect(user.tasksOrder.dailys).to.have.a.lengthOf(0);
|
let habits = await requests.get('/tasks/user?type=habits');
|
||||||
expect(user.tasksOrder.rewards).to.have.a.lengthOf(0);
|
let dailys = await requests.get('/tasks/user?type=dailys');
|
||||||
expect(user.tasksOrder.habits).to.have.a.lengthOf(0);
|
let todos = await requests.get('/tasks/user?type=todos');
|
||||||
|
let rewards = await requests.get('/tasks/user?type=rewards');
|
||||||
|
let tags = await requests.get('/tags');
|
||||||
|
|
||||||
|
expect(habits).to.have.a.lengthOf(0);
|
||||||
|
|
||||||
|
expect(dailys).to.have.a.lengthOf(0);
|
||||||
|
|
||||||
|
expect(todos).to.have.a.lengthOf(1);
|
||||||
|
expect(todos[0].text).to.eql(t('defaultTodo1Text'));
|
||||||
|
expect(todos[0].notes).to.eql(t('defaultTodoNotes'));
|
||||||
|
|
||||||
|
expect(rewards).to.have.a.lengthOf(0);
|
||||||
|
|
||||||
|
expect(tags).to.have.a.lengthOf(7);
|
||||||
|
expect(tags[0].name).to.eql(t('defaultTag1'));
|
||||||
|
expect(tags[1].name).to.eql(t('defaultTag2'));
|
||||||
|
expect(tags[2].name).to.eql(t('defaultTag3'));
|
||||||
|
expect(tags[3].name).to.eql(t('defaultTag4'));
|
||||||
|
expect(tags[4].name).to.eql(t('defaultTag5'));
|
||||||
|
expect(tags[5].name).to.eql(t('defaultTag6'));
|
||||||
|
expect(tags[6].name).to.eql(t('defaultTag7'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('for Web', async () => {
|
||||||
|
api = requester(
|
||||||
|
null,
|
||||||
|
{'x-client': 'habitica-web'},
|
||||||
|
);
|
||||||
|
let username = generateRandomUserName();
|
||||||
|
let email = `${username}@example.com`;
|
||||||
|
let password = 'password';
|
||||||
|
|
||||||
|
let user = await api.post('/user/auth/local/register', {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
confirmPassword: password,
|
||||||
|
});
|
||||||
|
|
||||||
|
let requests = new ApiUser(user);
|
||||||
|
|
||||||
|
let habits = await requests.get('/tasks/user?type=habits');
|
||||||
|
let dailys = await requests.get('/tasks/user?type=dailys');
|
||||||
|
let todos = await requests.get('/tasks/user?type=todos');
|
||||||
|
let rewards = await requests.get('/tasks/user?type=rewards');
|
||||||
|
let tags = await requests.get('/tags');
|
||||||
|
|
||||||
|
expect(habits).to.have.a.lengthOf(3);
|
||||||
|
expect(habits[0].text).to.eql(t('defaultHabit1Text'));
|
||||||
|
expect(habits[0].notes).to.eql('');
|
||||||
|
expect(habits[1].text).to.eql(t('defaultHabit2Text'));
|
||||||
|
expect(habits[1].notes).to.eql('');
|
||||||
|
expect(habits[2].text).to.eql(t('defaultHabit3Text'));
|
||||||
|
expect(habits[2].notes).to.eql('');
|
||||||
|
|
||||||
|
expect(dailys).to.have.a.lengthOf(0);
|
||||||
|
|
||||||
|
expect(todos).to.have.a.lengthOf(1);
|
||||||
|
expect(todos[0].text).to.eql(t('defaultTodo1Text'));
|
||||||
|
expect(todos[0].notes).to.eql(t('defaultTodoNotes'));
|
||||||
|
|
||||||
|
expect(rewards).to.have.a.lengthOf(1);
|
||||||
|
expect(rewards[0].text).to.eql(t('defaultReward1Text'));
|
||||||
|
expect(rewards[0].notes).to.eql('');
|
||||||
|
|
||||||
|
expect(tags).to.have.a.lengthOf(7);
|
||||||
|
expect(tags[0].name).to.eql(t('defaultTag1'));
|
||||||
|
expect(tags[1].name).to.eql(t('defaultTag2'));
|
||||||
|
expect(tags[2].name).to.eql(t('defaultTag3'));
|
||||||
|
expect(tags[3].name).to.eql(t('defaultTag4'));
|
||||||
|
expect(tags[4].name).to.eql(t('defaultTag5'));
|
||||||
|
expect(tags[5].name).to.eql(t('defaultTag6'));
|
||||||
|
expect(tags[6].name).to.eql(t('defaultTag7'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('for Android', async () => {
|
||||||
|
api = requester(
|
||||||
|
null,
|
||||||
|
{'x-client': 'habitica-android'},
|
||||||
|
);
|
||||||
|
let username = generateRandomUserName();
|
||||||
|
let email = `${username}@example.com`;
|
||||||
|
let password = 'password';
|
||||||
|
|
||||||
|
let user = await api.post('/user/auth/local/register', {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
confirmPassword: password,
|
||||||
|
});
|
||||||
|
|
||||||
|
let requests = new ApiUser(user);
|
||||||
|
|
||||||
|
let habits = await requests.get('/tasks/user?type=habits');
|
||||||
|
let dailys = await requests.get('/tasks/user?type=dailys');
|
||||||
|
let todos = await requests.get('/tasks/user?type=todos');
|
||||||
|
let rewards = await requests.get('/tasks/user?type=rewards');
|
||||||
|
let tags = await requests.get('/tags');
|
||||||
|
|
||||||
|
expect(habits).to.have.a.lengthOf(2);
|
||||||
|
expect(habits[0].text).to.eql(t('defaultHabit4Text'));
|
||||||
|
expect(habits[0].notes).to.eql(t('defaultHabit4Notes'));
|
||||||
|
expect(habits[1].text).to.eql(t('defaultHabit5Text'));
|
||||||
|
expect(habits[1].notes).to.eql(t('defaultHabit5Notes'));
|
||||||
|
|
||||||
|
expect(dailys).to.have.a.lengthOf(1);
|
||||||
|
expect(dailys[0].text).to.eql(t('defaultDaily1Text'));
|
||||||
|
expect(dailys[0].notes).to.eql('');
|
||||||
|
|
||||||
|
expect(todos).to.have.a.lengthOf(2);
|
||||||
|
expect(todos[0].text).to.eql(t('defaultTodo1Text'));
|
||||||
|
expect(todos[0].notes).to.eql(t('defaultTodoNotes'));
|
||||||
|
expect(todos[1].text).to.eql(t('defaultTodo2Text'));
|
||||||
|
expect(todos[1].notes).to.eql(t('defaultTodo2Notes'));
|
||||||
|
|
||||||
|
expect(rewards).to.have.a.lengthOf(1);
|
||||||
|
expect(rewards[0].text).to.eql(t('defaultReward2Text'));
|
||||||
|
expect(rewards[0].notes).to.eql(t('defaultReward2Notes'));
|
||||||
|
|
||||||
|
expect(tags).to.have.a.lengthOf(7);
|
||||||
|
expect(tags[0].name).to.eql(t('defaultTag1'));
|
||||||
|
expect(tags[1].name).to.eql(t('defaultTag2'));
|
||||||
|
expect(tags[2].name).to.eql(t('defaultTag3'));
|
||||||
|
expect(tags[3].name).to.eql(t('defaultTag4'));
|
||||||
|
expect(tags[4].name).to.eql(t('defaultTag5'));
|
||||||
|
expect(tags[5].name).to.eql(t('defaultTag6'));
|
||||||
|
expect(tags[6].name).to.eql(t('defaultTag7'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('for iOS', async () => {
|
||||||
|
api = requester(
|
||||||
|
null,
|
||||||
|
{'x-client': 'habitica-ios'},
|
||||||
|
);
|
||||||
|
let username = generateRandomUserName();
|
||||||
|
let email = `${username}@example.com`;
|
||||||
|
let password = 'password';
|
||||||
|
|
||||||
|
let user = await api.post('/user/auth/local/register', {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
confirmPassword: password,
|
||||||
|
});
|
||||||
|
|
||||||
|
let requests = new ApiUser(user);
|
||||||
|
|
||||||
|
let habits = await requests.get('/tasks/user?type=habits');
|
||||||
|
let dailys = await requests.get('/tasks/user?type=dailys');
|
||||||
|
let todos = await requests.get('/tasks/user?type=todos');
|
||||||
|
let rewards = await requests.get('/tasks/user?type=rewards');
|
||||||
|
let tags = await requests.get('/tags');
|
||||||
|
|
||||||
|
expect(habits).to.have.a.lengthOf(2);
|
||||||
|
expect(habits[0].text).to.eql(t('defaultHabit4Text'));
|
||||||
|
expect(habits[0].notes).to.eql(t('defaultHabit4Notes'));
|
||||||
|
expect(habits[1].text).to.eql(t('defaultHabit5Text'));
|
||||||
|
expect(habits[1].notes).to.eql(t('defaultHabit5Notes'));
|
||||||
|
|
||||||
|
expect(dailys).to.have.a.lengthOf(1);
|
||||||
|
expect(dailys[0].text).to.eql(t('defaultDaily1Text'));
|
||||||
|
expect(dailys[0].notes).to.eql('');
|
||||||
|
|
||||||
|
expect(todos).to.have.a.lengthOf(2);
|
||||||
|
expect(todos[0].text).to.eql(t('defaultTodo1Text'));
|
||||||
|
expect(todos[0].notes).to.eql(t('defaultTodoNotes'));
|
||||||
|
expect(todos[1].text).to.eql(t('defaultTodo2Text'));
|
||||||
|
expect(todos[1].notes).to.eql(t('defaultTodo2Notes'));
|
||||||
|
|
||||||
|
expect(rewards).to.have.a.lengthOf(1);
|
||||||
|
expect(rewards[0].text).to.eql(t('defaultReward2Text'));
|
||||||
|
expect(rewards[0].notes).to.eql(t('defaultReward2Notes'));
|
||||||
|
|
||||||
|
expect(tags).to.have.a.lengthOf(7);
|
||||||
|
expect(tags[0].name).to.eql(t('defaultTag1'));
|
||||||
|
expect(tags[1].name).to.eql(t('defaultTag2'));
|
||||||
|
expect(tags[2].name).to.eql(t('defaultTag3'));
|
||||||
|
expect(tags[3].name).to.eql(t('defaultTag4'));
|
||||||
|
expect(tags[4].name).to.eql(t('defaultTag5'));
|
||||||
|
expect(tags[5].name).to.eql(t('defaultTag6'));
|
||||||
|
expect(tags[6].name).to.eql(t('defaultTag7'));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('enrolls new users in an A/B test', async () => {
|
it('enrolls new users in an A/B test', async () => {
|
||||||
|
|||||||
@@ -8,13 +8,26 @@
|
|||||||
"defaultHabit3Text": "Take the Stairs/Elevator (Click the pencil to edit)",
|
"defaultHabit3Text": "Take the Stairs/Elevator (Click the pencil to edit)",
|
||||||
"defaultHabit3Notes": "Sample Good or Bad Habits: +/- Took Stairs/Elevator ; +/- Drank Water/Soda",
|
"defaultHabit3Notes": "Sample Good or Bad Habits: +/- Took Stairs/Elevator ; +/- Drank Water/Soda",
|
||||||
|
|
||||||
"defaultTodoNotes": "You can either complete this To-Do, edit it, or remove it.",
|
"defaultHabit4Text": "Add a task to Habitica",
|
||||||
|
"defaultHabit4Notes": "Either a Habit, a Daily, or a To-Do",
|
||||||
|
|
||||||
|
"defaultHabit5Text": "Tap here to edit this into a bad habit you'd like to quit",
|
||||||
|
"defaultHabit5Notes": "Or delete from the edit screen",
|
||||||
|
|
||||||
|
"defaultDaily1Text": "Use Habitica to keep track of your tasks",
|
||||||
|
|
||||||
"defaultTodo1Text": "Join Habitica (Check me off!)",
|
"defaultTodo1Text": "Join Habitica (Check me off!)",
|
||||||
|
"defaultTodoNotes": "You can either complete this To-Do, edit it, or remove it.",
|
||||||
|
|
||||||
|
"defaultTodo2Text": "Finish Justin's task walkthrough",
|
||||||
|
"defaultTodo2Notes": "Visit all the sections of the bottom bar",
|
||||||
|
|
||||||
"defaultReward1Text": "15 minute break",
|
"defaultReward1Text": "15 minute break",
|
||||||
"defaultReward1Notes": "Custom rewards can come in many forms. Some people will hold off watching their favorite show unless they have the gold to pay for it.",
|
"defaultReward1Notes": "Custom rewards can come in many forms. Some people will hold off watching their favorite show unless they have the gold to pay for it.",
|
||||||
|
|
||||||
|
"defaultReward2Text": "Reward yourself",
|
||||||
|
"defaultReward2Notes": "Watch TV, play a game, eat a treat, it's up to you!",
|
||||||
|
|
||||||
"defaultTag1": "Work",
|
"defaultTag1": "Work",
|
||||||
"defaultTag2": "Exercise",
|
"defaultTag2": "Exercise",
|
||||||
"defaultTag3": "Health + Wellness",
|
"defaultTag3": "Health + Wellness",
|
||||||
|
|||||||
@@ -3127,6 +3127,74 @@ api.userDefaults = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
api.userDefaultsMobile = {
|
||||||
|
habits: [
|
||||||
|
{
|
||||||
|
type: 'habit',
|
||||||
|
text: t('defaultHabit4Text'),
|
||||||
|
notes: t('defaultHabit4Notes'),
|
||||||
|
up: true,
|
||||||
|
down: false,
|
||||||
|
attribute: 'per',
|
||||||
|
}, {
|
||||||
|
type: 'habit',
|
||||||
|
text: t('defaultHabit5Text'),
|
||||||
|
notes: t('defaultHabit5Notes'),
|
||||||
|
up: false,
|
||||||
|
down: true,
|
||||||
|
attribute: 'con',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dailys: [
|
||||||
|
{
|
||||||
|
type: 'daily',
|
||||||
|
text: t('defaultDaily1Text'),
|
||||||
|
attribute: 'per',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
todos: [
|
||||||
|
{
|
||||||
|
type: 'todo',
|
||||||
|
text: t('defaultTodo1Text'),
|
||||||
|
notes: t('defaultTodoNotes'),
|
||||||
|
completed: false,
|
||||||
|
attribute: 'int',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'todo',
|
||||||
|
text: t('defaultTodo2Text'),
|
||||||
|
notes: t('defaultTodo2Notes'),
|
||||||
|
completed: false,
|
||||||
|
attribute: 'int',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
rewards: [
|
||||||
|
{
|
||||||
|
type: 'reward',
|
||||||
|
text: t('defaultReward2Text'),
|
||||||
|
notes: t('defaultReward2Notes'),
|
||||||
|
value: 20,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
name: t('defaultTag1'),
|
||||||
|
}, {
|
||||||
|
name: t('defaultTag2'),
|
||||||
|
}, {
|
||||||
|
name: t('defaultTag3'),
|
||||||
|
}, {
|
||||||
|
name: t('defaultTag4'),
|
||||||
|
}, {
|
||||||
|
name: t('defaultTag5'),
|
||||||
|
}, {
|
||||||
|
name: t('defaultTag6'),
|
||||||
|
}, {
|
||||||
|
name: t('defaultTag7'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
api.faq = faq;
|
api.faq = faq;
|
||||||
|
|
||||||
api.loginIncentives = loginIncentives(api);
|
api.loginIncentives = loginIncentives(api);
|
||||||
|
|||||||
@@ -31,10 +31,16 @@ function findTag (user, tagName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _populateDefaultTasks (user, taskTypes) {
|
function _populateDefaultTasks (user, taskTypes) {
|
||||||
|
let defaultsData;
|
||||||
|
if (user.registeredThrough === 'habitica-android' || user.registeredThrough === 'habitica-ios') {
|
||||||
|
defaultsData = shared.content.userDefaultsMobile;
|
||||||
|
} else {
|
||||||
|
defaultsData = shared.content.userDefaults;
|
||||||
|
}
|
||||||
let tagsI = taskTypes.indexOf('tag');
|
let tagsI = taskTypes.indexOf('tag');
|
||||||
|
|
||||||
if (tagsI !== -1) {
|
if (tagsI !== -1) {
|
||||||
user.tags = _.map(shared.content.userDefaults.tags, (tag) => {
|
user.tags = _.map(defaultsData.tags, (tag) => {
|
||||||
let newTag = _.cloneDeep(tag);
|
let newTag = _.cloneDeep(tag);
|
||||||
|
|
||||||
// tasks automatically get _id=helpers.uuid() from TaskSchema id.default, but tags are Schema.Types.Mixed - so we need to manually invoke here
|
// tasks automatically get _id=helpers.uuid() from TaskSchema id.default, but tags are Schema.Types.Mixed - so we need to manually invoke here
|
||||||
@@ -53,7 +59,7 @@ function _populateDefaultTasks (user, taskTypes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_.each(taskTypes, (taskType) => {
|
_.each(taskTypes, (taskType) => {
|
||||||
let tasksOfType = _.map(shared.content.userDefaults[`${taskType}s`], (taskDefaults) => {
|
let tasksOfType = _.map(defaultsData[`${taskType}s`], (taskDefaults) => {
|
||||||
let newTask = new Tasks[taskType](taskDefaults);
|
let newTask = new Tasks[taskType](taskDefaults);
|
||||||
|
|
||||||
newTask.userId = user._id;
|
newTask.userId = user._id;
|
||||||
@@ -106,12 +112,17 @@ function _setUpNewUser (user) {
|
|||||||
user.flags.tutorial.common[section] = true;
|
user.flags.tutorial.common[section] = true;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
taskTypes = ['todo', 'tag'];
|
|
||||||
user.flags.showTour = false;
|
user.flags.showTour = false;
|
||||||
|
|
||||||
_.each(iterableFlags.tour, (val, section) => {
|
_.each(iterableFlags.tour, (val, section) => {
|
||||||
user.flags.tour[section] = -2;
|
user.flags.tour[section] = -2;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (user.registeredThrough === 'habitica-android' || user.registeredThrough === 'habitica-ios') {
|
||||||
|
taskTypes = ['habit', 'daily', 'todo', 'reward', 'tag'];
|
||||||
|
} else {
|
||||||
|
taskTypes = ['todo', 'tag'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return _populateDefaultTasks(user, taskTypes);
|
return _populateDefaultTasks(user, taskTypes);
|
||||||
|
|||||||
Reference in New Issue
Block a user