From 7f8851c72b6fdf73c229d0dcf1fd0b87937a7a69 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Tue, 18 Apr 2017 15:50:50 -0500 Subject: [PATCH] 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 --- .../user/auth/POST-register_local.test.js | 211 ++++++++++++++++-- website/common/locales/en/defaultTasks.json | 15 +- website/common/script/content/index.js | 68 ++++++ website/server/models/user/hooks.js | 17 +- 4 files changed, 293 insertions(+), 18 deletions(-) diff --git a/test/api/v3/integration/user/auth/POST-register_local.test.js b/test/api/v3/integration/user/auth/POST-register_local.test.js index 722e429d10..bb2f588bab 100644 --- a/test/api/v3/integration/user/auth/POST-register_local.test.js +++ b/test/api/v3/integration/user/auth/POST-register_local.test.js @@ -37,23 +37,206 @@ describe('POST /user/auth/local/register', () => { expect(user.newUser).to.eql(true); }); - it('provides default tags and tasks', async () => { - let username = generateRandomUserName(); - let email = `${username}@example.com`; - let password = 'password'; + context('provides default tags and tasks', async () => { + it('for a generic API consumer', async () => { + 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 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(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')); }); - expect(user.tags).to.have.a.lengthOf(7); - expect(user.tasksOrder.todos).to.have.a.lengthOf(1); - expect(user.tasksOrder.dailys).to.have.a.lengthOf(0); - expect(user.tasksOrder.rewards).to.have.a.lengthOf(0); - expect(user.tasksOrder.habits).to.have.a.lengthOf(0); + 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 () => { diff --git a/website/common/locales/en/defaultTasks.json b/website/common/locales/en/defaultTasks.json index 4353943456..7dcacb0b35 100644 --- a/website/common/locales/en/defaultTasks.json +++ b/website/common/locales/en/defaultTasks.json @@ -8,13 +8,26 @@ "defaultHabit3Text": "Take the Stairs/Elevator (Click the pencil to edit)", "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!)", + "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", "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", "defaultTag2": "Exercise", "defaultTag3": "Health + Wellness", diff --git a/website/common/script/content/index.js b/website/common/script/content/index.js index d2dfc40171..a031c96490 100644 --- a/website/common/script/content/index.js +++ b/website/common/script/content/index.js @@ -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.loginIncentives = loginIncentives(api); diff --git a/website/server/models/user/hooks.js b/website/server/models/user/hooks.js index 473970fae4..16ca40dc29 100644 --- a/website/server/models/user/hooks.js +++ b/website/server/models/user/hooks.js @@ -31,10 +31,16 @@ function findTag (user, tagName) { } 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'); if (tagsI !== -1) { - user.tags = _.map(shared.content.userDefaults.tags, (tag) => { + user.tags = _.map(defaultsData.tags, (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 @@ -53,7 +59,7 @@ function _populateDefaultTasks (user, taskTypes) { } _.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); newTask.userId = user._id; @@ -106,12 +112,17 @@ function _setUpNewUser (user) { user.flags.tutorial.common[section] = true; }); } else { - taskTypes = ['todo', 'tag']; user.flags.showTour = false; _.each(iterableFlags.tour, (val, section) => { 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);