From c4fc2d825da9744c5f34ca8257078ea7b24283af Mon Sep 17 00:00:00 2001 From: Bart Enkelaar Date: Sun, 20 Sep 2020 10:45:56 +0200 Subject: [PATCH 1/4] fix(export) - Issue 12482 - Fix messages in xml export. --- test/api/unit/top-level/dataexport.test.js | 79 +++++++++++++++++++ .../controllers/top-level/dataexport.js | 7 +- website/server/models/user/schema.js | 4 +- 3 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 test/api/unit/top-level/dataexport.test.js diff --git a/test/api/unit/top-level/dataexport.test.js b/test/api/unit/top-level/dataexport.test.js new file mode 100644 index 0000000000..3f6892ee9d --- /dev/null +++ b/test/api/unit/top-level/dataexport.test.js @@ -0,0 +1,79 @@ +import dataexport from '../../../../website/server/controllers/top-level/dataexport'; + +import * as Tasks from '../../../../website/server/models/task'; +import * as inboxLib from '../../../../website/server/libs/inbox'; + +describe('xml export', async () => { + let exported; + + const user = { + toJSON () { + return { + newMessages: { + '283171a5-422c-4991-bc78-95b1b5b51629': { + name: 'The Language Hackers', + value: true, + }, + '283171a6-422c-4991-bc78-95b1b5b51629': { + name: 'The Bug Hackers', + value: false, + }, + }, + inbox: {}, + pinnedItems: [], + unpinnedItems: [], + }; + }, + }; + + const response = { + locals: { user }, + set () {}, + status: () => ({ + send: data => { + exported = data; + }, + }), + }; + + beforeEach(() => { + const tasks = [{ + toJSON: () => ({ a: 'b', type: 'c' }), + }]; + const messages = [{ flags: { content: 'message' } }]; + + sinon.stub(Tasks.Task, 'find').returns({ exec: async () => tasks }); + sinon.stub(inboxLib, 'getUserInbox').resolves(messages); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('maps the newMessages field to have id as a value in a list.', async () => { + await dataexport.exportUserDataXml.handler({}, response); + expect(exported).to.equal(` + + 283171a5-422c-4991-bc78-95b1b5b51629 + The Language Hackers + true + + + 283171a6-422c-4991-bc78-95b1b5b51629 + The Bug Hackers + false + + + + content + + + + + b + c + + +`); + }); +}); diff --git a/website/server/controllers/top-level/dataexport.js b/website/server/controllers/top-level/dataexport.js index 2a17f4e5e4..f1bc60ea28 100644 --- a/website/server/controllers/top-level/dataexport.js +++ b/website/server/controllers/top-level/dataexport.js @@ -112,14 +112,15 @@ async function _getUserDataForExport (user, xmlMode = false) { // object maps cant be parsed userData.inbox.messages = _(userData.inbox.messages) .map(m => { - const flags = Object.keys(m.flags); - m.flags = flags; + m.flags = Object.keys(m.flags); return m; }) .value(); - // _id gets parsed as an bytearray => which gets casted to a chararray => "weird chars" + userData.newMessages = _.map(userData.newMessages, (msg, id) => ({ id, ...msg })); + + // _id gets parsed as a bytearray => which gets cast to a chararray => "weird chars" userData.unpinnedItems = userData.unpinnedItems.map(i => ({ path: i.path, type: i.type, diff --git a/website/server/models/user/schema.js b/website/server/models/user/schema.js index f671479dc9..abc6426a56 100644 --- a/website/server/models/user/schema.js +++ b/website/server/models/user/schema.js @@ -1,4 +1,4 @@ -import mongoose from 'mongoose'; +import { Schema } from 'mongoose'; import validator from 'validator'; import shared from '../../../common'; import { // eslint-disable-line import/no-cycle @@ -10,8 +10,6 @@ import { schema as TagSchema } from '../tag'; import { schema as UserNotificationSchema } from '../userNotification'; import { schema as WebhookSchema } from '../webhook'; -const { Schema } = mongoose; - const RESTRICTED_EMAIL_DOMAINS = Object.freeze(['habitica.com', 'habitrpg.com']); // User schema definition From 8b9c76a2b7fce5b06ff3591b890fdac1578b43eb Mon Sep 17 00:00:00 2001 From: Bart Enkelaar Date: Thu, 24 Sep 2020 00:07:38 +0200 Subject: [PATCH 2/4] fix(12842) - Remove duplication in gulp-tests.js --- gulp/gulp-tests.js | 144 +++++++++++++-------------------------------- 1 file changed, 41 insertions(+), 103 deletions(-) diff --git a/gulp/gulp-tests.js b/gulp/gulp-tests.js index c3445874fa..d61ead1c98 100644 --- a/gulp/gulp-tests.js +++ b/gulp/gulp-tests.js @@ -3,9 +3,7 @@ import { exec } from 'child_process'; import gulp from 'gulp'; import os from 'os'; import nconf from 'nconf'; -import { - pipe, -} from './taskHelper'; +import { pipe } from './taskHelper'; import { getDevelopmentConnectionUrl, getDefaultConnectionOptions, @@ -21,15 +19,16 @@ const TEST_DB_URI = nconf.get('TEST_DB_URI'); const SANITY_TEST_COMMAND = 'npm run test:sanity'; const COMMON_TEST_COMMAND = 'npm run test:common'; const CONTENT_TEST_COMMAND = 'npm run test:content'; -const CONTENT_OPTIONS = { maxBuffer: 1024 * 500 }; +const LIMIT_MAX_BUFFER_OPTIONS = { maxBuffer: 1024 * 500 }; -/* Helper methods for reporting test summary */ +/* Helper method for reporting test summary */ const testResults = []; const testCount = (stdout, regexp) => { const match = stdout.match(regexp); return parseInt(match && (match[1] || 0), 10); }; +/* Helper methods to correctly run child test processes */ const testBin = (string, additionalEnvVariables = '') => { if (os.platform() === 'win32') { if (additionalEnvVariables !== '') { @@ -41,6 +40,15 @@ const testBin = (string, additionalEnvVariables = '') => { return `NODE_ENV=test ${additionalEnvVariables} ${string}`; }; +function runInChildProcess (command, options = {}, envVariables = '') { + return done => pipe(exec(testBin(command, envVariables), options, done)); +} + +function integrationTestCommand (testDir, coverageDir) { + return `istanbul cover --dir coverage/${coverageDir} --report lcovonly node_modules/mocha/bin/_mocha -- ${testDir} --recursive --require ./test/helpers/start-server`; +} + +/* Test task definitions */ gulp.task('test:nodemon', gulp.series(done => { process.env.PORT = TEST_SERVER_PORT; // eslint-disable-line no-process-env process.env.NODE_DB_URI = TEST_DB_URI; // eslint-disable-line no-process-env @@ -82,31 +90,9 @@ gulp.task('test:prepare', gulp.series( done => done(), )); -gulp.task('test:sanity', cb => { - const runner = exec( - testBin(SANITY_TEST_COMMAND), - err => { - if (err) { - process.exit(1); - } - cb(); - }, - ); - pipe(runner); -}); +gulp.task('test:sanity', runInChildProcess(SANITY_TEST_COMMAND)); -gulp.task('test:common', gulp.series('test:prepare:build', cb => { - const runner = exec( - testBin(COMMON_TEST_COMMAND), - err => { - if (err) { - process.exit(1); - } - cb(); - }, - ); - pipe(runner); -})); +gulp.task('test:common', gulp.series('test:prepare:build', runInChildProcess(COMMON_TEST_COMMAND))); gulp.task('test:common:clean', cb => { pipe(exec(testBin(COMMON_TEST_COMMAND), () => cb())); @@ -130,22 +116,11 @@ gulp.task('test:common:safe', gulp.series('test:prepare:build', cb => { pipe(runner); })); -gulp.task('test:content', gulp.series('test:prepare:build', cb => { - const runner = exec( - testBin(CONTENT_TEST_COMMAND), - CONTENT_OPTIONS, - err => { - if (err) { - process.exit(1); - } - cb(); - }, - ); - pipe(runner); -})); +gulp.task('test:content', gulp.series('test:prepare:build', + runInChildProcess(CONTENT_TEST_COMMAND, LIMIT_MAX_BUFFER_OPTIONS))); gulp.task('test:content:clean', cb => { - pipe(exec(testBin(CONTENT_TEST_COMMAND), CONTENT_OPTIONS, () => cb())); + pipe(exec(testBin(CONTENT_TEST_COMMAND), LIMIT_MAX_BUFFER_OPTIONS, () => cb())); }); gulp.task('test:content:watch', gulp.series('test:content:clean', () => gulp.watch(['common/script/content/**', 'test/**'], gulp.series('test:content:clean', done => done())))); @@ -153,7 +128,7 @@ gulp.task('test:content:watch', gulp.series('test:content:clean', () => gulp.wat gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => { const runner = exec( testBin(CONTENT_TEST_COMMAND), - CONTENT_OPTIONS, + LIMIT_MAX_BUFFER_OPTIONS, (err, stdout) => { // eslint-disable-line handle-callback-err testResults.push({ suite: 'Content Specs\t', @@ -167,76 +142,39 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => { pipe(runner); })); -gulp.task('test:api:unit:run', done => { - const runner = exec( - testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'), - err => { - if (err) { - process.exit(1); - } - done(); - }, - ); - - pipe(runner); -}); +gulp.task('test:api:unit:run', + runInChildProcess(integrationTestCommand('test/api/unit', 'coverage/api-unit'))); gulp.task('test:api:unit:watch', () => gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit:run', done => done()))); -gulp.task('test:api-v3:integration', gulp.series('test:prepare:mongo', done => { - const runner = exec( - testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'), - { maxBuffer: 500 * 1024 }, - err => { - if (err) { - process.exit(1); - } - done(); - }, - ); - - pipe(runner); -})); +gulp.task('test:api-v3:integration', gulp.series('test:prepare:mongo', + runInChildProcess( + integrationTestCommand('test/api/v3/integration', 'coverage/api-v3-integration'), + LIMIT_MAX_BUFFER_OPTIONS, + ))); gulp.task('test:api-v3:integration:watch', () => gulp.watch([ 'website/server/controllers/api-v3/**/*', 'common/script/ops/*', 'website/server/libs/*.js', 'test/api/v3/integration/**/*', ], gulp.series('test:api-v3:integration', done => done()))); -gulp.task('test:api-v3:integration:separate-server', done => { - const runner = exec( - testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'), - { maxBuffer: 500 * 1024 }, - err => done(err), - ); +gulp.task('test:api-v3:integration:separate-server', runInChildProcess( + 'mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', + LIMIT_MAX_BUFFER_OPTIONS, + 'LOAD_SERVER=0', +)); - pipe(runner); -}); +gulp.task('test:api-v4:integration', gulp.series('test:prepare:mongo', + runInChildProcess( + integrationTestCommand('test/api/v4', 'api-v4-integration'), + LIMIT_MAX_BUFFER_OPTIONS, + ))); -gulp.task('test:api-v4:integration', gulp.series('test:prepare:mongo', done => { - const runner = exec( - testBin('istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'), - { maxBuffer: 500 * 1024 }, - err => { - if (err) { - process.exit(1); - } - done(); - }, - ); - - pipe(runner); -})); - -gulp.task('test:api-v4:integration:separate-server', done => { - const runner = exec( - testBin('mocha test/api/v4 --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'), - { maxBuffer: 500 * 1024 }, - err => done(err), - ); - - pipe(runner); -}); +gulp.task('test:api-v4:integration:separate-server', runInChildProcess( + 'mocha test/api/v4 --recursive --require ./test/helpers/start-server', + LIMIT_MAX_BUFFER_OPTIONS, + 'LOAD_SERVER=0', +)); gulp.task('test:api:unit', gulp.series( 'test:prepare:mongo', From 6e913266480dcebaf1c00aff0022d690abc2bd79 Mon Sep 17 00:00:00 2001 From: Bart Enkelaar Date: Fri, 25 Sep 2020 08:55:28 +0200 Subject: [PATCH 3/4] fix(dataexport) - 12482 - Extract xml marshalling into library - Add integration test on dataexport endpoint - Add library with unit test for xml marshalling --- test/api/unit/libs/xmlMarshaller.test.js | 44 ++ test/api/unit/top-level/dataexport.test.js | 79 ---- .../api/v3/integration/GET-dataexport.test.js | 424 ++++++++++++++++++ .../controllers/top-level/dataexport.js | 41 +- website/server/libs/xmlMarshaller.js | 32 ++ 5 files changed, 505 insertions(+), 115 deletions(-) create mode 100644 test/api/unit/libs/xmlMarshaller.test.js delete mode 100644 test/api/unit/top-level/dataexport.test.js create mode 100644 test/api/v3/integration/GET-dataexport.test.js create mode 100644 website/server/libs/xmlMarshaller.js diff --git a/test/api/unit/libs/xmlMarshaller.test.js b/test/api/unit/libs/xmlMarshaller.test.js new file mode 100644 index 0000000000..73633a4c30 --- /dev/null +++ b/test/api/unit/libs/xmlMarshaller.test.js @@ -0,0 +1,44 @@ +import * as xmlMarshaller from '../../../../website/server/libs/xmlMarshaller'; + +describe('xml marshaller marshalls user data', () => { + const minimumUser = { + pinnedItems: [], + unpinnedItems: [], + inbox: {}, + }; + + function userDataWith (fields) { + return { ...minimumUser, ...fields }; + } + + it('maps the newMessages field to have id as a value in a list.', () => { + const userData = userDataWith({ + newMessages: { + '283171a5-422c-4991-bc78-95b1b5b51629': { + name: 'The Language Hackers', + value: true, + }, + '283171a6-422c-4991-bc78-95b1b5b51629': { + name: 'The Bug Hackers', + value: false, + }, + }, + }); + + const xml = xmlMarshaller.marshallUserData(userData); + + expect(xml).to.equal(` + + + 283171a5-422c-4991-bc78-95b1b5b51629 + The Language Hackers + true + + + 283171a6-422c-4991-bc78-95b1b5b51629 + The Bug Hackers + false + +`); + }); +}); diff --git a/test/api/unit/top-level/dataexport.test.js b/test/api/unit/top-level/dataexport.test.js deleted file mode 100644 index 3f6892ee9d..0000000000 --- a/test/api/unit/top-level/dataexport.test.js +++ /dev/null @@ -1,79 +0,0 @@ -import dataexport from '../../../../website/server/controllers/top-level/dataexport'; - -import * as Tasks from '../../../../website/server/models/task'; -import * as inboxLib from '../../../../website/server/libs/inbox'; - -describe('xml export', async () => { - let exported; - - const user = { - toJSON () { - return { - newMessages: { - '283171a5-422c-4991-bc78-95b1b5b51629': { - name: 'The Language Hackers', - value: true, - }, - '283171a6-422c-4991-bc78-95b1b5b51629': { - name: 'The Bug Hackers', - value: false, - }, - }, - inbox: {}, - pinnedItems: [], - unpinnedItems: [], - }; - }, - }; - - const response = { - locals: { user }, - set () {}, - status: () => ({ - send: data => { - exported = data; - }, - }), - }; - - beforeEach(() => { - const tasks = [{ - toJSON: () => ({ a: 'b', type: 'c' }), - }]; - const messages = [{ flags: { content: 'message' } }]; - - sinon.stub(Tasks.Task, 'find').returns({ exec: async () => tasks }); - sinon.stub(inboxLib, 'getUserInbox').resolves(messages); - }); - - afterEach(() => { - sinon.restore(); - }); - - it('maps the newMessages field to have id as a value in a list.', async () => { - await dataexport.exportUserDataXml.handler({}, response); - expect(exported).to.equal(` - - 283171a5-422c-4991-bc78-95b1b5b51629 - The Language Hackers - true - - - 283171a6-422c-4991-bc78-95b1b5b51629 - The Bug Hackers - false - - - - content - - - - - b - c - - -`); - }); -}); diff --git a/test/api/v3/integration/GET-dataexport.test.js b/test/api/v3/integration/GET-dataexport.test.js new file mode 100644 index 0000000000..f8e8b0ccc1 --- /dev/null +++ b/test/api/v3/integration/GET-dataexport.test.js @@ -0,0 +1,424 @@ +import moment from 'moment'; + +import { generateUser, requester } from '../../../helpers/api-integration/v3'; +import { Task } from '../../../../website/server/models/task'; + +describe('GET /export/userdata.xml', () => { + let user; + + before(async () => { + user = await generateUser(); + }); + + it('returns the xml for a minimum viable user', async () => { + const xml = await requester(user).get('/export/userdata.xml'); + + const userId = user.id; + const userName = user.auth.local.username; + const dateTime = moment(user.auth.timestamps.created).toDate(); + const taskId = (await Task.findOne({ userId }, 'id').exec())._id; + + expect(xml).to.equal(` + + + ${userName} + ${userName} + ${userName}@example.com + + + ${dateTime} + ${dateTime} + ${dateTime} + + + + + + + + false + false + false + false + + 0 + 0 + + + + + + false + 0 + + + + + true + + + + 0 + 0 + 0 + 0 + + 1 + 0 + 0 + + + + + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + + + + false + false + false + false + false + false + false + false + false + false + false + false + false + false + false + + + false + false + false + false + false + false + false + + + false + false + false + false + false + true + false + false + 0 + 0 + false + 0 + false + true + false + false + false + false + true + + ${dateTime} + + + + + + armor_base_0 + head_base_0 + shield_base_0 + + + armor_base_0 + head_base_0 + shield_base_0 + + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 0 + ${dateTime} + + + + + + + + 1 + + + + + + + + + 0 + 0 + 0 + + + false + + level + ascending + + + + red + 3 + 1 + 0 + 0 + 1 + + + false + true + true + true + true + true + true + true + true + true + true + true + true + true + true + + + false + true + true + true + true + true + true + true + true + true + true + true + true + true + + + false + false + false + false + + + false + false + + 0 + slim + false + 915533 + blue + 0 + rosstavoTheme + none + flat + true + MM/dd/yyyy + false + true + false + false + false + false + false + false + true + en + + violet + + + ${userName} + + + + 0 + 0 + 0 + 0 + 0 + false + false + false + false + false + + + 0 + 0 + 0 + 0 + + 50 + 10 + 0 + 0 + 1 + warrior + 0 + 0 + 0 + 0 + 0 + + + 0 + false + + + ${user.tasksOrder.todos[0]} + + <_v>1 + 0 + 0 + 0 + <_id>${userId} + ${user.apiToken} + ${dateTime} + + ${user.tags[0].id} + Work + + + ${user.tags[1].id} + Exercise + + + ${user.tags[2].id} + Health + Wellness + + + ${user.tags[3].id} + School + + + ${user.tags[4].id} + Teams + + + ${user.tags[5].id} + Chores + + + ${user.tags[6].id} + Creativity + + + + gear.flat.weapon_warrior_0 + marketGear + + + gear.flat.armor_warrior_1 + marketGear + + + gear.flat.shield_warrior_1 + marketGear + + + gear.flat.head_warrior_1 + marketGear + + + potion + potion + + + armoire + armoire + + ${userId} + <_tmp>undefined + + + + + + false + false + false + + singleCompletion + + false + false + todo + You can either complete this To Do, edit it, or remove it. + 0 + 1 + int + false + ${dateTime} + ${dateTime} + <_id>${taskId} + Join Habitica (Check me off!) + ${userId} + ${taskId} + + +`); + }); +}); diff --git a/website/server/controllers/top-level/dataexport.js b/website/server/controllers/top-level/dataexport.js index f1bc60ea28..fd9a10c8bf 100644 --- a/website/server/controllers/top-level/dataexport.js +++ b/website/server/controllers/top-level/dataexport.js @@ -1,14 +1,12 @@ import _ from 'lodash'; import moment from 'moment'; -import * as js2xml from 'js2xmlparser'; // import Pageres from 'pageres'; // import nconf from 'nconf'; // import got from 'got'; import md from 'habitica-markdown'; import csvStringify from '../../libs/csvStringify'; -import { - NotFound, -} from '../../libs/errors'; +import { marshallUserData } from '../../libs/xmlMarshaller'; +import { NotFound } from '../../libs/errors'; import * as Tasks from '../../models/task'; import * as inboxLib from '../../libs/inbox'; // import { model as User } from '../../models/user'; @@ -85,7 +83,7 @@ api.exportUserHistory = { // Convert user to json and attach tasks divided by type and inbox messages // at user.tasks[`${taskType}s`] (user.tasks.{dailys/habits/...}) -async function _getUserDataForExport (user, xmlMode = false) { +async function _getUserDataForExport (user) { const userData = user.toJSON(); userData.tasks = {}; @@ -108,30 +106,6 @@ async function _getUserDataForExport (user, xmlMode = false) { userData.tasks[`${taskType}s`] = tasksPerType; }); - if (xmlMode) { - // object maps cant be parsed - userData.inbox.messages = _(userData.inbox.messages) - .map(m => { - m.flags = Object.keys(m.flags); - - return m; - }) - .value(); - - userData.newMessages = _.map(userData.newMessages, (msg, id) => ({ id, ...msg })); - - // _id gets parsed as a bytearray => which gets cast to a chararray => "weird chars" - userData.unpinnedItems = userData.unpinnedItems.map(i => ({ - path: i.path, - type: i.type, - })); - - userData.pinnedItems = userData.pinnedItems.map(i => ({ - path: i.path, - type: i.type, - })); - } - return userData; } @@ -172,13 +146,8 @@ api.exportUserDataXml = { url: '/export/userdata.xml', middlewares: [authWithSession], async handler (req, res) { - const userData = await _getUserDataForExport(res.locals.user, true); - const xmlData = js2xml.parse('user', userData, { - cdataInvalidChars: true, - declaration: { - include: false, - }, - }); + const userData = await _getUserDataForExport(res.locals.user); + const xmlData = marshallUserData(userData); res.set({ 'Content-Type': 'text/xml', diff --git a/website/server/libs/xmlMarshaller.js b/website/server/libs/xmlMarshaller.js new file mode 100644 index 0000000000..5e7bb96095 --- /dev/null +++ b/website/server/libs/xmlMarshaller.js @@ -0,0 +1,32 @@ +import _ from 'lodash'; +import * as js2xml from 'js2xmlparser'; + +export function marshallUserData (userData) { + // object maps can't be marshalled to XML + userData.inbox.messages = _(userData.inbox.messages) + .map(m => { + m.flags = Object.keys(m.flags); + return m; + }) + .value(); + + userData.newMessages = _.map(userData.newMessages, (msg, id) => ({ id, ...msg })); + + // _id gets parsed as a bytearray => which gets cast to a chararray => "weird chars" + userData.unpinnedItems = userData.unpinnedItems.map(i => ({ + path: i.path, + type: i.type, + })); + + userData.pinnedItems = userData.pinnedItems.map(i => ({ + path: i.path, + type: i.type, + })); + + return js2xml.parse('user', userData, { + cdataInvalidChars: true, + declaration: { + include: false, + }, + }); +} From 8219dfd9e6ed67165aa17586db7925b179e0a371 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Fri, 25 Sep 2020 11:21:24 +0200 Subject: [PATCH 4/4] fix(integration tests): remove duplicate test file --- .../api/v3/integration/GET-dataexport.test.js | 424 ------------------ 1 file changed, 424 deletions(-) delete mode 100644 test/api/v3/integration/GET-dataexport.test.js diff --git a/test/api/v3/integration/GET-dataexport.test.js b/test/api/v3/integration/GET-dataexport.test.js deleted file mode 100644 index f8e8b0ccc1..0000000000 --- a/test/api/v3/integration/GET-dataexport.test.js +++ /dev/null @@ -1,424 +0,0 @@ -import moment from 'moment'; - -import { generateUser, requester } from '../../../helpers/api-integration/v3'; -import { Task } from '../../../../website/server/models/task'; - -describe('GET /export/userdata.xml', () => { - let user; - - before(async () => { - user = await generateUser(); - }); - - it('returns the xml for a minimum viable user', async () => { - const xml = await requester(user).get('/export/userdata.xml'); - - const userId = user.id; - const userName = user.auth.local.username; - const dateTime = moment(user.auth.timestamps.created).toDate(); - const taskId = (await Task.findOne({ userId }, 'id').exec())._id; - - expect(xml).to.equal(` - - - ${userName} - ${userName} - ${userName}@example.com - - - ${dateTime} - ${dateTime} - ${dateTime} - - - - - - - - false - false - false - false - - 0 - 0 - - - - - - false - 0 - - - - - true - - - - 0 - 0 - 0 - 0 - - 1 - 0 - 0 - - - - - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - - - - false - false - false - false - false - false - false - false - false - false - false - false - false - false - false - - - false - false - false - false - false - false - false - - - false - false - false - false - false - true - false - false - 0 - 0 - false - 0 - false - true - false - false - false - false - true - - ${dateTime} - - - - - - armor_base_0 - head_base_0 - shield_base_0 - - - armor_base_0 - head_base_0 - shield_base_0 - - - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - ${dateTime} - - - - - - - - 1 - - - - - - - - - 0 - 0 - 0 - - - false - - level - ascending - - - - red - 3 - 1 - 0 - 0 - 1 - - - false - true - true - true - true - true - true - true - true - true - true - true - true - true - true - - - false - true - true - true - true - true - true - true - true - true - true - true - true - true - - - false - false - false - false - - - false - false - - 0 - slim - false - 915533 - blue - 0 - rosstavoTheme - none - flat - true - MM/dd/yyyy - false - true - false - false - false - false - false - false - true - en - - violet - - - ${userName} - - - - 0 - 0 - 0 - 0 - 0 - false - false - false - false - false - - - 0 - 0 - 0 - 0 - - 50 - 10 - 0 - 0 - 1 - warrior - 0 - 0 - 0 - 0 - 0 - - - 0 - false - - - ${user.tasksOrder.todos[0]} - - <_v>1 - 0 - 0 - 0 - <_id>${userId} - ${user.apiToken} - ${dateTime} - - ${user.tags[0].id} - Work - - - ${user.tags[1].id} - Exercise - - - ${user.tags[2].id} - Health + Wellness - - - ${user.tags[3].id} - School - - - ${user.tags[4].id} - Teams - - - ${user.tags[5].id} - Chores - - - ${user.tags[6].id} - Creativity - - - - gear.flat.weapon_warrior_0 - marketGear - - - gear.flat.armor_warrior_1 - marketGear - - - gear.flat.shield_warrior_1 - marketGear - - - gear.flat.head_warrior_1 - marketGear - - - potion - potion - - - armoire - armoire - - ${userId} - <_tmp>undefined - - - - - - false - false - false - - singleCompletion - - false - false - todo - You can either complete this To Do, edit it, or remove it. - 0 - 1 - int - false - ${dateTime} - ${dateTime} - <_id>${taskId} - Join Habitica (Check me off!) - ${userId} - ${taskId} - - -`); - }); -});