Compare commits
543 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93437a00dd | |||
| 31afa0345e | |||
| b2c278b00a | |||
| b54037f230 | |||
| 488dcb916a | |||
| 10792b65be | |||
| 390970a73a | |||
| 6f0d0b1fb3 | |||
| dfcd32d54a | |||
| c24cbdc987 | |||
| 68d8c0de51 | |||
| a7b0fa195f | |||
| ab65aa692f | |||
| 198d4df02a | |||
| 6fa2f643fd | |||
| 4d39861b51 | |||
| d4c99b6db6 | |||
| a79dc90a45 | |||
| daa6bd0315 | |||
| 99f2373214 | |||
| 374d528647 | |||
| 8550ca4d29 | |||
| 79f6b59f6e | |||
| e37ad420ce | |||
| 2f9ff92cbd | |||
| 56479e7fbd | |||
| 66e4849553 | |||
| 9e29b44ad9 | |||
| 605488dd47 | |||
| 6c16b4b77e | |||
| 80205dcc67 | |||
| 65d5bf69f6 | |||
| 20792f5455 | |||
| 6fd509df13 | |||
| d7df18a97a | |||
| ff5c44c5a8 | |||
| c929fa1351 | |||
| d30e7b9251 | |||
| c6c6632405 | |||
| e0d9ecca52 | |||
| 78f187f87a | |||
| af047d3c82 | |||
| 20e8f47def | |||
| c496f94c79 | |||
| ad6073220d | |||
| d669db0f9a | |||
| c244fe488d | |||
| aef71db0f5 | |||
| ac566882fe | |||
| 1ad662a090 | |||
| 1db52de45d | |||
| f8cfdfa37d | |||
| ffd36465c9 | |||
| dbb1e3aa18 | |||
| 07ce68c596 | |||
| 4c5d72c96f | |||
| 7121653515 | |||
| ce2b66a2be | |||
| 43e381cfc1 | |||
| ca5161b48a | |||
| 44dec6dc4b | |||
| fb8f0bed43 | |||
| c391de9e86 | |||
| 7a534ab81d | |||
| 32c7f40c4b | |||
| 569fbff244 | |||
| 3fe847f329 | |||
| d52d759733 | |||
| 5e5a755022 | |||
| 8d148b4d69 | |||
| 248b64a43f | |||
| 57ed0f0a10 | |||
| 3455adaef5 | |||
| 4d0295a60d | |||
| a002bc5e20 | |||
| b9d1086e24 | |||
| 412a0ecc8c | |||
| d44c9ea853 | |||
| c44c581265 | |||
| f666f3cd04 | |||
| 236bd6cec4 | |||
| e124c36274 | |||
| d5511a0047 | |||
| 87f003f392 | |||
| 930a869365 | |||
| 809da8add0 | |||
| 1dad176320 | |||
| 1596c6218f | |||
| 0d3aba950a | |||
| f1110e0f89 | |||
| 7273f8f6d9 | |||
| a0ae200a54 | |||
| ca448f081d | |||
| cd27afa9f0 | |||
| 8bc8183895 | |||
| c26c52f1fe | |||
| 8d5becc9ce | |||
| cf7f6e2a67 | |||
| acad3b8873 | |||
| 04f4eb8490 | |||
| 8c8af83dfc | |||
| 86d65956d9 | |||
| 42c5e6c22b | |||
| 79b51a40ce | |||
| 79c3efaf9c | |||
| 74c6a891fc | |||
| 9a5d17f538 | |||
| 070c4a8fbd | |||
| 2bbc4f4f4d | |||
| 39c00ea433 | |||
| dd6c1c764a | |||
| 9b456d1760 | |||
| acf1031317 | |||
| 5d45204d8b | |||
| 37a71924fe | |||
| 9cf2408988 | |||
| 638525f8d8 | |||
| 2c37ba3cee | |||
| ad5b2fe540 | |||
| bfb6daad51 | |||
| 281b8e2b7c | |||
| 3f88ea2378 | |||
| 9c6275d4ab | |||
| fd3c8ddc8b | |||
| 72f47ad4e6 | |||
| 74c9a1b02d | |||
| ffa561473c | |||
| 080ffae4e1 | |||
| e395182c95 | |||
| 68f4275c44 | |||
| 4bf4c3a6c2 | |||
| f00bb29192 | |||
| 016447ec77 | |||
| fa024e071b | |||
| 28fec237fe | |||
| e4bb82768c | |||
| 65eca22407 | |||
| cea1597ee1 | |||
| 3906952154 | |||
| 6169b9d0ae | |||
| 69cac7e504 | |||
| febf3f0024 | |||
| 563f40e4b7 | |||
| e2b06161e1 | |||
| e7de8b8e2f | |||
| a0624d9507 | |||
| cddd0df4f2 | |||
| 220bfb3517 | |||
| 2106a5ebd3 | |||
| bbffa9830b | |||
| caa546eb62 | |||
| 4e83059652 | |||
| 903cdb36ef | |||
| d8128cc3db | |||
| f888e80b01 | |||
| fd7aedbff2 | |||
| 6c5234313d | |||
| 08aa5758b4 | |||
| 1415e344c0 | |||
| 2ce7915f06 | |||
| 838c8b4e08 | |||
| 1590d955cd | |||
| 2690caed35 | |||
| dc2d4fa10b | |||
| 1540ec89ee | |||
| f304d4fe52 | |||
| 023e433a5c | |||
| ef4aeb29ab | |||
| 2b80931202 | |||
| 2950713712 | |||
| 118f3bd1bb | |||
| 69f1343ea8 | |||
| 918ee02d64 | |||
| 0cac34dd26 | |||
| 1c859fc91f | |||
| 857aa5827b | |||
| 28e8ec2d2c | |||
| 856f13d213 | |||
| 121fd38bd1 | |||
| 36d72f5f7a | |||
| f1b8bd80e7 | |||
| 84d2ce6a3f | |||
| 76010e6c8f | |||
| c707b6c99b | |||
| e4bd466cc7 | |||
| 001b8eb894 | |||
| 9abcfe8614 | |||
| bc6102551d | |||
| 959a3ff85b | |||
| 518b874f64 | |||
| 6cc359a935 | |||
| 514d35c0be | |||
| 13da92ea68 | |||
| 03c4d82b7d | |||
| d905ab7f86 | |||
| c6560b6b1b | |||
| c61f660255 | |||
| 2f1b683ec9 | |||
| 47bb217068 | |||
| f49fd05da1 | |||
| b0341aa06f | |||
| b07ec18e33 | |||
| 12930a2bac | |||
| 91f5c47d9d | |||
| fe7850d10f | |||
| c5c2da75bf | |||
| 969607cd3b | |||
| 2a1f52a359 | |||
| 47d9594679 | |||
| 97e40c81f3 | |||
| c8b61a2f7d | |||
| e9543f0d28 | |||
| 77b88490e4 | |||
| 7fc2500bfd | |||
| fb229acb58 | |||
| 6ce83d1fa4 | |||
| 2be4815aea | |||
| 1dbc42f48a | |||
| 89279c8aed | |||
| faedb13598 | |||
| c0c74659c5 | |||
| bf5ad2db1f | |||
| 7d99873960 | |||
| e02ef00397 | |||
| 23c5c4211c | |||
| 69cc134fff | |||
| ffd9400cb7 | |||
| 5be91ef842 | |||
| 3123183e46 | |||
| 49cca7a601 | |||
| 7fbd38d18c | |||
| 1f95376d39 | |||
| 2da0a1e88c | |||
| afacd3e1cf | |||
| a69b9e6705 | |||
| e4e5d10316 | |||
| 27c38bdf45 | |||
| ea24eeb019 | |||
| 55a8eef3e1 | |||
| 92cbb4a07d | |||
| 3f96d05365 | |||
| 0b72f6a613 | |||
| 5e1e6be518 | |||
| 472ec99291 | |||
| 0284e9a4e3 | |||
| 1a0721c078 | |||
| 6b6b548ac5 | |||
| 30f3d786bb | |||
| 07bbba6789 | |||
| 6afb2bd0d4 | |||
| f1a3bd5001 | |||
| 3f6a13d209 | |||
| 3658e41fec | |||
| c69d5c7ae6 | |||
| 747f9e6a99 | |||
| 7755ab090b | |||
| 9ed17df1e3 | |||
| faeb040a83 | |||
| 0a1ae1375e | |||
| 9756030fa2 | |||
| c66172b74b | |||
| 281f6d1806 | |||
| 237095d109 | |||
| fa788f49fc | |||
| 0817cf96e1 | |||
| 97e1d75dce | |||
| 52bf20c27d | |||
| 5dbaf39aba | |||
| 66d402c985 | |||
| 8048146223 | |||
| e2c07e458d | |||
| 90a9e8e192 | |||
| f8039f48a6 | |||
| 04337f8e83 | |||
| 45297f8bf9 | |||
| 6f112c29f2 | |||
| 4d1edb363c | |||
| 4e303cc592 | |||
| 798a975185 | |||
| eb2b46fc5d | |||
| 29854d3bdb | |||
| f8751b002c | |||
| cd545e08d5 | |||
| f69bb4f023 | |||
| 847081d2b2 | |||
| 8112d46ea4 | |||
| d13bded647 | |||
| 1de4ab3612 | |||
| f9f22f313f | |||
| f57eed85a8 | |||
| 10dd3318ab | |||
| cbef83c14a | |||
| 59709a8590 | |||
| f85f2a0c6d | |||
| 605a5a1d5c | |||
| 2d5d786c8e | |||
| 5efe5b7b10 | |||
| 3e92bb22fa | |||
| 1249b9d410 | |||
| 197aafe092 | |||
| 79829ca128 | |||
| adaa1d9a3e | |||
| 3e6691dbbb | |||
| 046761b9aa | |||
| 0b0466b960 | |||
| f8d4a2bd6b | |||
| 1af59a3770 | |||
| bbcb13c91b | |||
| d27dc46c50 | |||
| 679459b83b | |||
| 5a619773d5 | |||
| ad76ab1315 | |||
| 15eb8db925 | |||
| a0e92c5605 | |||
| eac3e36c07 | |||
| 0b8def555b | |||
| 5f5fa5c2eb | |||
| 1eac8bbbbe | |||
| 49c7580cd4 | |||
| dca958f2e2 | |||
| eae5f0d605 | |||
| 6ab091645c | |||
| d66041c280 | |||
| de070a450a | |||
| eaaab35f31 | |||
| 6a63f080ad | |||
| c42f81b629 | |||
| 9a78a7b896 | |||
| 8b70721137 | |||
| 44ffbd716d | |||
| 5bfc3a5ff4 | |||
| 0ba5df4164 | |||
| 52a59c8192 | |||
| c1a860494d | |||
| 395dafa127 | |||
| bab41647f5 | |||
| 8582a67308 | |||
| 0d58fb0fd3 | |||
| 1d2482f8bc | |||
| f4cf906127 | |||
| 559f9b1825 | |||
| c7039bc9ea | |||
| f929d36e1a | |||
| 254d1a3465 | |||
| 442aae8a35 | |||
| bcb0ed0a5c | |||
| a48b8f0e34 | |||
| 7eeeda2aae | |||
| a5ad9c30f0 | |||
| ac732b2c85 | |||
| a56b2d68fb | |||
| 25b0ff38c4 | |||
| dcc06931cc | |||
| bc3ebbd095 | |||
| e5b9581743 | |||
| 4b9fe49e3a | |||
| ab4c8b0a46 | |||
| f6c26fe869 | |||
| 80e9735b28 | |||
| aa6f188bd9 | |||
| e8b7660376 | |||
| 7d76622410 | |||
| 928e5f66c4 | |||
| 6a343535c0 | |||
| f58f6acb44 | |||
| 64754777ed | |||
| 3b5e4b6d84 | |||
| 9383578cb8 | |||
| 474672ec64 | |||
| 25c6691793 | |||
| 3ea7b72024 | |||
| 2d6f05a9a4 | |||
| 28637286d6 | |||
| 874887b790 | |||
| c977e5ebb5 | |||
| f040e668f3 | |||
| 55a15f938c | |||
| 8c4f35daf4 | |||
| 8f38ce3424 | |||
| b8f57a74d0 | |||
| 7ed26c0dbe | |||
| e8f5b26d4d | |||
| 0273648b6b | |||
| b6fdac8885 | |||
| 00e6389672 | |||
| e02c669b61 | |||
| f0cb7c6bf3 | |||
| 571ef0b309 | |||
| 74328d1bcc | |||
| d34a9d828c | |||
| 2fd35b3a40 | |||
| e27512f626 | |||
| dbf9cb3b4e | |||
| 34c1245519 | |||
| f602bfe438 | |||
| 9aa4b8aa64 | |||
| 5a150ebc5b | |||
| cbe1892b50 | |||
| 13df60e0dd | |||
| 3ff7692528 | |||
| 111bba84dc | |||
| b0d2b72b88 | |||
| 696317ea8a | |||
| 593178a46a | |||
| f8fe16482d | |||
| 5108480ec5 | |||
| 95968b1b1c | |||
| 566569af98 | |||
| 6693e9fca9 | |||
| 431bde56d2 | |||
| 7cf17c0e63 | |||
| 49561bfc8c | |||
| 8cbbb58e78 | |||
| 905549e379 | |||
| 5d45c7209a | |||
| 371cddfe17 | |||
| fcfac30caa | |||
| b094fb1e52 | |||
| a2dd82b6db | |||
| e6071610e4 | |||
| bdd0e2bb79 | |||
| 054a9a6f2b | |||
| 35b9ed6273 | |||
| e65277baa5 | |||
| 421bd8624c | |||
| 4562c6422a | |||
| a5cd9f2473 | |||
| 18bbdfa84b | |||
| d8c37f6e2d | |||
| 7f38c61c70 | |||
| 1c018cedb1 | |||
| 80892bd6a8 | |||
| 6801dae75d | |||
| 59e1de6771 | |||
| 5b240a1950 | |||
| 3ec3722038 | |||
| d798ebadfe | |||
| 6cbddef627 | |||
| 016de411c9 | |||
| 2173f53883 | |||
| f2e5bc52e5 | |||
| 393a9290e9 | |||
| ad5045bc09 | |||
| 9b515ebdd1 | |||
| 97bf9ee8e8 | |||
| f5ba636579 | |||
| 4dd7e49552 | |||
| d2f673ef1e | |||
| e198dd551a | |||
| 0bfc9d9516 | |||
| d4e20ee4aa | |||
| a751a367fc | |||
| d323be19c6 | |||
| be3f61a94b | |||
| f1bb2db73b | |||
| a622344d44 | |||
| e279a3550b | |||
| 70aab3059c | |||
| c264e37182 | |||
| b31bc15493 | |||
| ba19c00617 | |||
| 93aa92de7c | |||
| d021680945 | |||
| f9595af8a5 | |||
| d2756278c3 | |||
| 2e2dc179c4 | |||
| acf7b811ab | |||
| d5170251c0 | |||
| c9ba9054e3 | |||
| d4aac1ee4b | |||
| 9615a332a5 | |||
| 417455e5ef | |||
| 136502a110 | |||
| 425887c1e4 | |||
| cfa8a5190f | |||
| df5be81706 | |||
| 08b3491047 | |||
| e73c3147c1 | |||
| a43254000e | |||
| 4e3c984baf | |||
| c112e923f1 | |||
| 540353f024 | |||
| 2b9b5e369e | |||
| cb38475765 | |||
| 8bb92577b0 | |||
| fb26cbd26d | |||
| a0de5cd8f8 | |||
| 9fe10b1818 | |||
| d8dd39422a | |||
| 3f9b710773 | |||
| 8a8bab4be1 | |||
| 2a0747ed72 | |||
| a5196e94f6 | |||
| 009ab26711 | |||
| 3fabf3391f | |||
| 8020990264 | |||
| a2cfeafc02 | |||
| d04a4fb1ed | |||
| aeb86db306 | |||
| 49960c0e32 | |||
| 932cb5cf6a | |||
| 74d6e77504 | |||
| 8400f1786b | |||
| d7bd5dd9f8 | |||
| 3288b0de33 | |||
| c025ffbd10 | |||
| afb5b473a3 | |||
| aeee29f5fa | |||
| 0cca2a07a2 | |||
| 55d94c129a | |||
| 358e1aed22 | |||
| 36241f061f | |||
| b6201a3b75 | |||
| 005f74d918 | |||
| 926e188017 | |||
| 94da808279 | |||
| 7568dd52e9 | |||
| c6e2b78982 | |||
| b6104c3ef3 | |||
| 56b5c960f0 | |||
| 528abf77af | |||
| 8db6b7c6cb | |||
| 578dee59bd | |||
| d40c923e6e | |||
| 3c4c64b023 | |||
| c84d6ba141 | |||
| 5f3b147d2a | |||
| ff08e8b586 | |||
| cb2acbfefd | |||
| b16da35585 | |||
| 826d7b85d7 | |||
| 6bcc6a15e2 | |||
| b600eceb49 | |||
| b83ef872c9 | |||
| 4ebc2e2175 | |||
| 2f4b8c569a | |||
| 85b5b5a62d | |||
| e271e57f63 | |||
| 558fb145b5 | |||
| fc30456b53 | |||
| 68b2d19b04 | |||
| 6d33acccf4 | |||
| acee4bad80 |
@@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
.git
|
||||||
|
website
|
||||||
@@ -14,7 +14,7 @@ files:
|
|||||||
owner: root
|
owner: root
|
||||||
group: users
|
group: users
|
||||||
content: |
|
content: |
|
||||||
$(ls -td /opt/elasticbeanstalk/node-install/node-* | head -1)/bin/npm install -g npm@3
|
$(ls -td /opt/elasticbeanstalk/node-install/node-* | head -1)/bin/npm install -g npm@4
|
||||||
container_commands:
|
container_commands:
|
||||||
01_makeBabel:
|
01_makeBabel:
|
||||||
command: "touch /tmp/.babel.json"
|
command: "touch /tmp/.babel.json"
|
||||||
|
|||||||
+1
-6
@@ -10,7 +10,6 @@ dist-client/
|
|||||||
# Not linted
|
# Not linted
|
||||||
migrations/*
|
migrations/*
|
||||||
website/client-old/
|
website/client-old/
|
||||||
debug-scripts/*
|
|
||||||
scripts/*
|
scripts/*
|
||||||
test/server_side/**/*
|
test/server_side/**/*
|
||||||
test/client-old/spec/**/*
|
test/client-old/spec/**/*
|
||||||
@@ -21,8 +20,4 @@ website/common/browserify.js
|
|||||||
test/content/**/*
|
test/content/**/*
|
||||||
Gruntfile.js
|
Gruntfile.js
|
||||||
gulpfile.js
|
gulpfile.js
|
||||||
gulp
|
gulp
|
||||||
webpack
|
|
||||||
test/client/e2e
|
|
||||||
test/client/unit/index.js
|
|
||||||
test/client/unit/karma.conf.js
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"node": true,
|
"node": true,
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"habitrpg/es6",
|
"habitrpg",
|
||||||
"habitrpg"
|
"habitrpg/esnext"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ Fixes put_issue_url_here
|
|||||||
|
|
||||||
|
|
||||||
[//]: # (Put User ID in here - found in Settings -> API)
|
[//]: # (Put User ID in here - found in Settings -> API)
|
||||||
|
|
||||||
----
|
----
|
||||||
UUID:
|
UUID:
|
||||||
|
|||||||
+27
-11
@@ -1,17 +1,33 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- '4.3.1'
|
- '6'
|
||||||
|
sudo: required
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.8
|
||||||
before_install:
|
before_install:
|
||||||
- "npm install -g npm@3"
|
- $CXX --version
|
||||||
- "npm install -g gulp"
|
- npm install -g npm@4
|
||||||
- "sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10"
|
- if [ $REQUIRES_SERVER ]; then sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10; echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list; sudo apt-get update; sudo apt-get install mongodb-org-server; fi
|
||||||
- "echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list"
|
|
||||||
- "sudo apt-get update"
|
|
||||||
- "sudo apt-get install mongodb-org-server"
|
|
||||||
before_script:
|
before_script:
|
||||||
- 'npm install -g grunt-cli mocha'
|
- npm run test:build
|
||||||
- cp config.json.example config.json
|
- cp config.json.example config.json
|
||||||
- "until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done"
|
- if [ $REQUIRES_SERVER ]; then until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done; export DISPLAY=:99; fi
|
||||||
- "export DISPLAY=:99"
|
|
||||||
after_script:
|
after_script:
|
||||||
- "./node_modules/.bin/lcov-result-merger 'coverage/**/*.info' | ./node_modules/coveralls/bin/coveralls.js"
|
- ./node_modules/.bin/lcov-result-merger 'coverage/**/*.info' | ./node_modules/coveralls/bin/coveralls.js
|
||||||
|
script: npm run $TEST
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- CXX=g++-4.8
|
||||||
|
- DISABLE_REQUEST_LOGGING=true
|
||||||
|
matrix:
|
||||||
|
- TEST="lint"
|
||||||
|
- TEST="test:api-v3" REQUIRES_SERVER=true
|
||||||
|
- TEST="test:sanity"
|
||||||
|
- TEST="test:content"
|
||||||
|
- TEST="test:common"
|
||||||
|
- TEST="test:karma"
|
||||||
|
- TEST="client:unit"
|
||||||
|
|||||||
+6
-4
@@ -17,20 +17,22 @@ RUN apt-get install -y \
|
|||||||
python
|
python
|
||||||
|
|
||||||
# Install NodeJS
|
# Install NodeJS
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
|
RUN curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
||||||
RUN apt-get install -y nodejs
|
RUN apt-get install -y nodejs
|
||||||
|
|
||||||
|
# Install npm@latest
|
||||||
|
RUN curl -sL https://www.npmjs.org/install.sh | sh
|
||||||
|
|
||||||
# Clean up package management
|
# Clean up package management
|
||||||
RUN apt-get clean
|
RUN apt-get clean
|
||||||
RUN rm -rf /var/lib/apt/lists/*
|
RUN rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install global packages
|
# Install global packages
|
||||||
RUN npm install -g npm@3
|
RUN npm install -g gulp grunt-cli bower mocha
|
||||||
RUN npm install -g gulp grunt-cli bower
|
|
||||||
|
|
||||||
# Clone Habitica repo and install dependencies
|
# Clone Habitica repo and install dependencies
|
||||||
WORKDIR /habitrpg
|
WORKDIR /habitrpg
|
||||||
RUN git clone https://github.com/HabitRPG/habitrpg.git /habitrpg
|
RUN git clone https://github.com/HabitRPG/habitica.git /habitrpg
|
||||||
RUN npm install
|
RUN npm install
|
||||||
RUN bower install --allow-root
|
RUN bower install --allow-root
|
||||||
|
|
||||||
|
|||||||
+3
-10
@@ -57,7 +57,7 @@ module.exports = function(grunt) {
|
|||||||
files: [
|
files: [
|
||||||
{expand: true, cwd: 'website/client-old/', src: 'favicon.ico', dest: 'website/build/'},
|
{expand: true, cwd: 'website/client-old/', src: 'favicon.ico', dest: 'website/build/'},
|
||||||
{expand: true, cwd: 'website/client-old/', src: 'favicon_192x192.png', dest: 'website/build/'},
|
{expand: true, cwd: 'website/client-old/', src: 'favicon_192x192.png', dest: 'website/build/'},
|
||||||
{expand: true, cwd: 'website/assets/sprites/dist/', src: 'spritesmith*.png', dest: 'website/build/'},
|
{expand: true, cwd: 'website/assets/sprites/dist/', src: 'spritesmith*.png', dest: 'website/build/static/sprites'},
|
||||||
{expand: true, cwd: 'website/assets/sprites/', src: 'backer-only/*.gif', dest: 'website/build/'},
|
{expand: true, cwd: 'website/assets/sprites/', src: 'backer-only/*.gif', dest: 'website/build/'},
|
||||||
{expand: true, cwd: 'website/assets/sprites/', src: 'npc_ian.gif', dest: 'website/build/'},
|
{expand: true, cwd: 'website/assets/sprites/', src: 'npc_ian.gif', dest: 'website/build/'},
|
||||||
{expand: true, cwd: 'website/assets/sprites/', src: 'quest_*.gif', dest: 'website/build/'},
|
{expand: true, cwd: 'website/assets/sprites/', src: 'quest_*.gif', dest: 'website/build/'},
|
||||||
@@ -78,6 +78,7 @@ module.exports = function(grunt) {
|
|||||||
'website/build/favicon.ico',
|
'website/build/favicon.ico',
|
||||||
'website/build/favicon_192x192.png',
|
'website/build/favicon_192x192.png',
|
||||||
'website/build/*.png',
|
'website/build/*.png',
|
||||||
|
'website/build/static/sprites/*.png',
|
||||||
'website/build/*.gif',
|
'website/build/*.gif',
|
||||||
'website/build/bower_components/bootstrap/dist/fonts/*'
|
'website/build/bower_components/bootstrap/dist/fonts/*'
|
||||||
],
|
],
|
||||||
@@ -126,15 +127,7 @@ module.exports = function(grunt) {
|
|||||||
// Register tasks.
|
// Register tasks.
|
||||||
grunt.registerTask('build:prod', ['loadManifestFiles', 'clean:build', 'uglify', 'stylus', 'cssmin', 'copy:build', 'hashres']);
|
grunt.registerTask('build:prod', ['loadManifestFiles', 'clean:build', 'uglify', 'stylus', 'cssmin', 'copy:build', 'hashres']);
|
||||||
grunt.registerTask('build:dev', ['cssmin', 'stylus']);
|
grunt.registerTask('build:dev', ['cssmin', 'stylus']);
|
||||||
grunt.registerTask('build:test', ['test:prepare:translations', 'build:dev']);
|
grunt.registerTask('build:test', ['build:dev']);
|
||||||
|
|
||||||
grunt.registerTask('test:prepare:translations', function() {
|
|
||||||
var i18n = require('./website/server/libs/i18n'),
|
|
||||||
fs = require('fs');
|
|
||||||
fs.writeFileSync('test/client-old/spec/mocks/translations.js',
|
|
||||||
"if(!window.env) window.env = {};\n" +
|
|
||||||
"window.env.translations = " + JSON.stringify(i18n.translations['en']) + ';');
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load tasks
|
// Load tasks
|
||||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Habitica [](https://travis-ci.org/HabitRPG/habitrpg) [](https://codeclimate.com/github/HabitRPG/habitrpg) [](https://coveralls.io/r/HabitRPG/habitrpg?branch=develop) [](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
Habitica [](https://travis-ci.org/HabitRPG/habitica) [](https://codeclimate.com/github/HabitRPG/habitrpg) [](https://coveralls.io/github/HabitRPG/habitica?branch=develop) [](https://www.bountysource.com/trackers/68393-habitrpg?utm_source=68393&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
||||||
===============
|
===============
|
||||||
|
|
||||||
[Habitica](https://habitica.com) is an open source habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor.
|
[Habitica](https://habitica.com) is an open source habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor.
|
||||||
@@ -10,21 +10,3 @@ For an introduction to the technologies used and how the software is organized,
|
|||||||
To set up a local install of Habitica for development and testing, see [Setting up Habitica Locally](http://habitica.wikia.com/wiki/Setting_up_Habitica_Locally), which contains instructions for Windows, *nix / Mac OS, and Vagrant.
|
To set up a local install of Habitica for development and testing, see [Setting up Habitica Locally](http://habitica.wikia.com/wiki/Setting_up_Habitica_Locally), which contains instructions for Windows, *nix / Mac OS, and Vagrant.
|
||||||
|
|
||||||
Then read [Guidance for Blacksmiths](http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths) for additional instructions and useful tips.
|
Then read [Guidance for Blacksmiths](http://habitica.wikia.com/wiki/Guidance_for_Blacksmiths) for additional instructions and useful tips.
|
||||||
|
|
||||||
## Debug Scripts
|
|
||||||
|
|
||||||
In the `./debug-scripts/` folder, there are a few files. Here's a sample:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
grant-all-equipment.js
|
|
||||||
grant-all-mounts.js
|
|
||||||
grant-all-pets.js
|
|
||||||
```
|
|
||||||
|
|
||||||
You can run them by doing:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node debug-scripts/name-of-script.js
|
|
||||||
```
|
|
||||||
|
|
||||||
If there are more arguments required to make the script work, it will print out the usage and an explanation of what the script does.
|
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@
|
|||||||
"jquery-ui": "1.10.3",
|
"jquery-ui": "1.10.3",
|
||||||
"jquery.cookie": "1.4.0",
|
"jquery.cookie": "1.4.0",
|
||||||
"js-emoji": "snicker/js-emoji#f25d8a303f",
|
"js-emoji": "snicker/js-emoji#f25d8a303f",
|
||||||
"ngInfiniteScroll": "1.0.0",
|
"ngInfiniteScroll": "1.1.0",
|
||||||
"pnotify": "1.3.1",
|
"pnotify": "1.3.1",
|
||||||
"sticky": "1.0.3",
|
"sticky": "1.0.3",
|
||||||
"swagger-ui": "wordnik/swagger-ui#v2.0.24",
|
"swagger-ui": "wordnik/swagger-ui#v2.0.24",
|
||||||
|
|||||||
+11
-4
@@ -2,13 +2,18 @@
|
|||||||
"PORT":3000,
|
"PORT":3000,
|
||||||
"ENABLE_CONSOLE_LOGS_IN_PROD":"false",
|
"ENABLE_CONSOLE_LOGS_IN_PROD":"false",
|
||||||
"IP":"0.0.0.0",
|
"IP":"0.0.0.0",
|
||||||
"CORES":1,
|
"WEB_CONCURRENCY":1,
|
||||||
"BASE_URL":"http://localhost:3000",
|
"BASE_URL":"http://localhost:3000",
|
||||||
"FACEBOOK_ANALYTICS":"1234567890123456",
|
|
||||||
"FACEBOOK_KEY":"123456789012345",
|
"FACEBOOK_KEY":"123456789012345",
|
||||||
"FACEBOOK_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
"FACEBOOK_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
||||||
"GOOGLE_CLIENT_ID":"123456789012345",
|
"GOOGLE_CLIENT_ID":"123456789012345",
|
||||||
"GOOGLE_CLIENT_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
"GOOGLE_CLIENT_SECRET":"aaaabbbbccccddddeeeeffff00001111",
|
||||||
|
"PLAY_API": {
|
||||||
|
"CLIENT_ID": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
|
"CLIENT_SECRET": "aaaabbbbccccddddeeeeffff00001111",
|
||||||
|
"ACCESS_TOKEN":"aaaabbbbccccddddeeeeffff00001111",
|
||||||
|
"REFRESH_TOKEN":"aaaabbbbccccddddeeeeffff00001111"
|
||||||
|
},
|
||||||
"NODE_DB_URI":"mongodb://localhost/habitrpg",
|
"NODE_DB_URI":"mongodb://localhost/habitrpg",
|
||||||
"TEST_DB_URI":"mongodb://localhost/habitrpg_test",
|
"TEST_DB_URI":"mongodb://localhost/habitrpg_test",
|
||||||
"NODE_ENV":"development",
|
"NODE_ENV":"development",
|
||||||
@@ -79,6 +84,8 @@
|
|||||||
},
|
},
|
||||||
"SLACK": {
|
"SLACK": {
|
||||||
"FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
"FLAGGING_URL": "https://hooks.slack.com/services/id/id/id",
|
||||||
"FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/"
|
"FLAGGING_FOOTER_LINK": "https://habitrpg.github.io/flag-o-rama/",
|
||||||
}
|
"SUBSCRIPTIONS_URL": "https://hooks.slack.com/services/id/id/id"
|
||||||
|
},
|
||||||
|
"ITUNES_SHARED_SECRET": "aaaabbbbccccddddeeeeffff00001111"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import { MongoClient as mongo } from 'mongodb';
|
|
||||||
import config from '../config';
|
|
||||||
|
|
||||||
module.exports.updateUser = (_id, path, value) => {
|
|
||||||
mongo.connect(config.NODE_DB_URI, (err, db) => {
|
|
||||||
if (err) throw err;
|
|
||||||
|
|
||||||
let collection = db.collection('users');
|
|
||||||
collection.updateOne(
|
|
||||||
{ _id },
|
|
||||||
{ $set: { [`${path}`]: value } },
|
|
||||||
(updateErr, result) => {
|
|
||||||
if (updateErr) throw updateErr;
|
|
||||||
console.log('done updating', _id);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
require('babel-register');
|
|
||||||
|
|
||||||
let _ = require('lodash');
|
|
||||||
let updateUser = require('./_helper').updateUser;
|
|
||||||
|
|
||||||
let userId = process.argv[2];
|
|
||||||
|
|
||||||
if (!userId) {
|
|
||||||
console.error('USAGE: node debug-scripts/grant-all-equipment.js <user_id>');
|
|
||||||
console.error('EFFECT: Adds all gear to specified user');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let gearFlat = require('../common').content.gear.flat;
|
|
||||||
|
|
||||||
let userGear = {};
|
|
||||||
|
|
||||||
_.each(gearFlat, (piece, key) => {
|
|
||||||
userGear[key] = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
updateUser(userId, 'items.gear.owned', userGear);
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
require('babel-register');
|
|
||||||
|
|
||||||
let _ = require('lodash');
|
|
||||||
let updateUser = require('./_helper').updateUser;
|
|
||||||
let userId = process.argv[2];
|
|
||||||
|
|
||||||
if (!userId) {
|
|
||||||
console.error('USAGE: node debug-scripts/grant-all-mounts.js <user_id>');
|
|
||||||
console.error('EFFECT: Adds all mounts to specified user');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dropMounts = require('../common').content.mounts;
|
|
||||||
let questMounts = require('../common').content.questMounts;
|
|
||||||
let specialMounts = require('../common').content.specialMounts;
|
|
||||||
let premiumMounts = require('../common').content.premiumPets; // premium mounts isn't exposed on the content object
|
|
||||||
|
|
||||||
let userMounts = {};
|
|
||||||
|
|
||||||
_.each([ dropMounts, questMounts, specialMounts, premiumMounts ], (set) => {
|
|
||||||
_.each(set, (pet, key) => {
|
|
||||||
userMounts[key] = true;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
updateUser(userId, 'items.mounts', userMounts);
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
require('babel-register');
|
|
||||||
|
|
||||||
let _ = require('lodash');
|
|
||||||
let updateUser = require('./_helper').updateUser;
|
|
||||||
let userId = process.argv[2];
|
|
||||||
|
|
||||||
if (!userId) {
|
|
||||||
console.error('USAGE: node debug-scripts/grant-all-pets.js <user_id>');
|
|
||||||
console.error('EFFECT: Adds all pets to specified user');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dropPets = require('../common').content.pets;
|
|
||||||
let questPets = require('../common').content.questPets;
|
|
||||||
let specialPets = require('../common').content.specialPets;
|
|
||||||
let premiumPets = require('../common').content.premiumPets;
|
|
||||||
|
|
||||||
let userPets = {};
|
|
||||||
|
|
||||||
_.each([ dropPets, questPets, specialPets, premiumPets ], (set) => {
|
|
||||||
_.each(set, (pet, key) => {
|
|
||||||
userPets[key] = 95;
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
updateUser(userId, 'items.pets', userPets);
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
web:
|
web:
|
||||||
volumes:
|
volumes:
|
||||||
- '.:/habitrpg'
|
- '.:/habitrpg'
|
||||||
|
|||||||
+4
-4
@@ -1,13 +1,13 @@
|
|||||||
web:
|
web:
|
||||||
build: .
|
build: .
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
links:
|
links:
|
||||||
- mongo
|
- mongo
|
||||||
environment:
|
environment:
|
||||||
- NODE_DB_URI=mongodb://mongo/habitrpg
|
- NODE_DB_URI=mongodb://mongo/habitrpg
|
||||||
|
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo
|
image: mongo
|
||||||
ports:
|
ports:
|
||||||
- "27017:27017"
|
- "27017:27017"
|
||||||
|
|||||||
+12
-2
@@ -12,6 +12,9 @@ import {each} from 'lodash';
|
|||||||
const MAX_SPRITESHEET_SIZE = 1024 * 1024 * 3;
|
const MAX_SPRITESHEET_SIZE = 1024 * 1024 * 3;
|
||||||
const DIST_PATH = 'website/assets/sprites/dist/';
|
const DIST_PATH = 'website/assets/sprites/dist/';
|
||||||
|
|
||||||
|
const IMG_DIST_PATH_NEW_CLIENT = 'website/static/sprites/';
|
||||||
|
const CSS_DIST_PATH_NEW_CLIENT = 'website/client/assets/css/sprites/';
|
||||||
|
|
||||||
gulp.task('sprites:compile', ['sprites:clean', 'sprites:main', 'sprites:largeSprites', 'sprites:checkCompiledDimensions']);
|
gulp.task('sprites:compile', ['sprites:clean', 'sprites:main', 'sprites:largeSprites', 'sprites:checkCompiledDimensions']);
|
||||||
|
|
||||||
gulp.task('sprites:main', () => {
|
gulp.task('sprites:main', () => {
|
||||||
@@ -25,7 +28,7 @@ gulp.task('sprites:largeSprites', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sprites:clean', (done) => {
|
gulp.task('sprites:clean', (done) => {
|
||||||
clean(`${DIST_PATH}spritesmith*`, done);
|
clean(`{${DIST_PATH}spritesmith*,${IMG_DIST_PATH_NEW_CLIENT}spritesmith*,${CSS_DIST_PATH_NEW_CLIENT}spritesmith*}`, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('sprites:checkCompiledDimensions', ['sprites:main', 'sprites:largeSprites'], () => {
|
gulp.task('sprites:checkCompiledDimensions', ['sprites:main', 'sprites:largeSprites'], () => {
|
||||||
@@ -66,14 +69,16 @@ function createSpritesStream (name, src) {
|
|||||||
algorithm: 'binary-tree',
|
algorithm: 'binary-tree',
|
||||||
padding: 1,
|
padding: 1,
|
||||||
cssTemplate: 'website/assets/sprites/css/css.template.handlebars',
|
cssTemplate: 'website/assets/sprites/css/css.template.handlebars',
|
||||||
cssVarMap: cssVarMap
|
cssVarMap: cssVarMap,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let imgStream = spriteData.img
|
let imgStream = spriteData.img
|
||||||
.pipe(imagemin())
|
.pipe(imagemin())
|
||||||
|
.pipe(gulp.dest(IMG_DIST_PATH_NEW_CLIENT))
|
||||||
.pipe(gulp.dest(DIST_PATH));
|
.pipe(gulp.dest(DIST_PATH));
|
||||||
|
|
||||||
let cssStream = spriteData.css
|
let cssStream = spriteData.css
|
||||||
|
.pipe(gulp.dest(CSS_DIST_PATH_NEW_CLIENT))
|
||||||
.pipe(gulp.dest(DIST_PATH));
|
.pipe(gulp.dest(DIST_PATH));
|
||||||
|
|
||||||
stream.add(imgStream);
|
stream.add(imgStream);
|
||||||
@@ -148,4 +153,9 @@ function cssVarMap (sprite) {
|
|||||||
}
|
}
|
||||||
if (~sprite.name.indexOf('shirt'))
|
if (~sprite.name.indexOf('shirt'))
|
||||||
sprite.custom.px.offset_y = `-${ sprite.y + 30 }px`; // even more for shirts
|
sprite.custom.px.offset_y = `-${ sprite.y + 30 }px`; // even more for shirts
|
||||||
|
if (~sprite.name.indexOf('hair_base')) {
|
||||||
|
let styleArray = sprite.name.split('_').slice(2,3);
|
||||||
|
if (Number(styleArray[0]) > 14)
|
||||||
|
sprite.custom.px.offset_y = `-${ sprite.y }px`; // don't crop updos
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-5
@@ -13,6 +13,9 @@ import Bluebird from 'bluebird';
|
|||||||
import runSequence from 'run-sequence';
|
import runSequence from 'run-sequence';
|
||||||
import os from 'os';
|
import os from 'os';
|
||||||
import nconf from 'nconf';
|
import nconf from 'nconf';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
const i18n = require('../website/server/libs/i18n');
|
||||||
|
|
||||||
// TODO rewrite
|
// TODO rewrite
|
||||||
|
|
||||||
@@ -72,10 +75,17 @@ gulp.task('test:prepare:server', ['test:prepare:mongo'], () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('test:prepare:build', ['build'], (cb) => {
|
gulp.task('test:prepare:translations', (cb) => {
|
||||||
exec(testBin('grunt build:test'), cb);
|
fs.writeFile(
|
||||||
|
'test/client-old/spec/mocks/translations.js',
|
||||||
|
`if(!window.env) window.env = {};
|
||||||
|
window.env.translations = ${JSON.stringify(i18n.translations['en'])};`, cb);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('test:prepare:build', ['build', 'test:prepare:translations']);
|
||||||
|
// exec(testBin('grunt build:test'), cb);
|
||||||
|
|
||||||
gulp.task('test:prepare:webdriver', (cb) => {
|
gulp.task('test:prepare:webdriver', (cb) => {
|
||||||
exec('npm run test:prepare:webdriver', cb);
|
exec('npm run test:prepare:webdriver', cb);
|
||||||
});
|
});
|
||||||
@@ -270,7 +280,7 @@ gulp.task('test:e2e:safe', ['test:prepare', 'test:prepare:server'], (cb) => {
|
|||||||
|
|
||||||
gulp.task('test:api-v3:unit', (done) => {
|
gulp.task('test:api-v3:unit', (done) => {
|
||||||
let runner = exec(
|
let runner = exec(
|
||||||
testBin('mocha test/api/v3/unit --recursive'),
|
testBin('mocha test/api/v3/unit --recursive --require ./test/helpers/start-server'),
|
||||||
(err, stdout, stderr) => {
|
(err, stdout, stderr) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -288,7 +298,7 @@ gulp.task('test:api-v3:unit:watch', () => {
|
|||||||
|
|
||||||
gulp.task('test:api-v3:integration', (done) => {
|
gulp.task('test:api-v3:integration', (done) => {
|
||||||
let runner = exec(
|
let runner = exec(
|
||||||
testBin('mocha test/api/v3/integration --recursive'),
|
testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server'),
|
||||||
{maxBuffer: 500 * 1024},
|
{maxBuffer: 500 * 1024},
|
||||||
(err, stdout, stderr) => {
|
(err, stdout, stderr) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -308,7 +318,7 @@ gulp.task('test:api-v3:integration:watch', () => {
|
|||||||
|
|
||||||
gulp.task('test:api-v3:integration:separate-server', (done) => {
|
gulp.task('test:api-v3:integration:separate-server', (done) => {
|
||||||
let runner = exec(
|
let runner = exec(
|
||||||
testBin('mocha test/api/v3/integration --recursive', 'LOAD_SERVER=0'),
|
testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
|
||||||
{maxBuffer: 500 * 1024},
|
{maxBuffer: 500 * 1024},
|
||||||
(err, stdout, stderr) => done(err)
|
(err, stdout, stderr) => done(err)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ gulp.task('transifex:malformedStrings', () => {
|
|||||||
let malformedString = `${lang} - ${file} - ${key} - ${translationString}`;
|
let malformedString = `${lang} - ${file} - ${key} - ${translationString}`;
|
||||||
stringsWithMalformedInterpolations.push(malformedString);
|
stringsWithMalformedInterpolations.push(malformedString);
|
||||||
} else if (englishOccurences.length !== translationOccurences.length && !malformedStringExceptions[key]) {
|
} else if (englishOccurences.length !== translationOccurences.length && !malformedStringExceptions[key]) {
|
||||||
let missingInterploationString = `${lang} - ${file} - ${key} - ${translationString}`;
|
let missingInterpolationString = `${lang} - ${file} - ${key} - ${translationString}`;
|
||||||
stringsWithIncorrectNumberOfInterpolations.push(missingInterploationString);
|
stringsWithIncorrectNumberOfInterpolations.push(missingInterpolationString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
var migrationName = '20161030-jackolanterns.js';
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set the newStuff flag in all user accounts so they see a Bailey message
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mongo = require('mongoskin');
|
||||||
|
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
|
||||||
|
var dbUsers = mongo.db(connectionString).collection('users');
|
||||||
|
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'auth.timestamps.loggedin':{$gt:new Date('2016-10-01')} // remove when running migration a second time
|
||||||
|
};
|
||||||
|
|
||||||
|
// specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
var fields = {
|
||||||
|
'migration': 1,
|
||||||
|
'items.pets.JackOLantern-Base': 1,
|
||||||
|
'items.mounts.JackOLantern-Base': 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.warn('Updating users...');
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
||||||
|
if (err) { return exiting(1, 'ERROR! ' + err); }
|
||||||
|
if (!user) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
setTimeout(displayData, 300000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// specify user data to change:
|
||||||
|
var set = {};
|
||||||
|
var inc = {};
|
||||||
|
if (user.migration !== migrationName) {
|
||||||
|
if (user.items.mounts['JackOLantern-Base']) {
|
||||||
|
set = {'migration':migrationName, 'items.pets.JackOLantern-Ghost':5};
|
||||||
|
} else if (user.items.pets['JackOLantern-Base']) {
|
||||||
|
set = {'migration':migrationName, 'items.mounts.JackOLantern-Base':true};
|
||||||
|
} else {
|
||||||
|
set = {'migration':migrationName, 'items.pets.JackOLantern-Base':5};
|
||||||
|
}
|
||||||
|
inc = {
|
||||||
|
'items.food.Candy_Base': 1,
|
||||||
|
'items.food.Candy_CottonCandyBlue': 1,
|
||||||
|
'items.food.Candy_CottonCandyPink': 1,
|
||||||
|
'items.food.Candy_Desert': 1,
|
||||||
|
'items.food.Candy_Golden': 1,
|
||||||
|
'items.food.Candy_Red': 1,
|
||||||
|
'items.food.Candy_Shade': 1,
|
||||||
|
'items.food.Candy_Skeleton': 1,
|
||||||
|
'items.food.Candy_White': 1,
|
||||||
|
'items.food.Candy_Zombie': 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.update({_id:user._id}, {$set:set, $inc:inc});
|
||||||
|
|
||||||
|
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
var migrationName = '20161102_takeThis.js';
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Award Take This ladder items to participants in this month's challenge
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mongo = require('mongoskin');
|
||||||
|
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
|
||||||
|
var dbUsers = mongo.db(connectionString).collection('users');
|
||||||
|
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'migration':{$ne:migrationName},
|
||||||
|
'challenges':{$in:['d1be0965-e909-4d30-82fa-9a0011f885b2']}
|
||||||
|
};
|
||||||
|
|
||||||
|
// specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
var fields = {
|
||||||
|
'items.gear.owned': 1
|
||||||
|
};
|
||||||
|
|
||||||
|
console.warn('Updating users...');
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
||||||
|
if (err) { return exiting(1, 'ERROR! ' + err); }
|
||||||
|
if (!user) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
setTimeout(displayData, 300000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// specify user data to change:
|
||||||
|
var set = {};
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.body_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.head_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.armor_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false};
|
||||||
|
} else {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.update({_id:user._id}, {$set:set});
|
||||||
|
|
||||||
|
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
var migrationName = '20161122_turkey_ladder.js';
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Yearly Turkey Day award. Turkey pet, Turkey mount, Gilded Turkey pet, Gilded Turkey mount
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mongo = require('mongoskin');
|
||||||
|
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
|
||||||
|
var dbUsers = mongo.db(connectionString).collection('users');
|
||||||
|
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'migration':{$ne:migrationName},
|
||||||
|
'auth.timestamps.loggedin':{$gt:new Date('2016-10-31')} // Extend timeframe each run of migration
|
||||||
|
};
|
||||||
|
|
||||||
|
// specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
var fields = {
|
||||||
|
'migration': 1,
|
||||||
|
'items.mounts': 1,
|
||||||
|
'items.pets': 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.warn('Updating users...');
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
||||||
|
if (err) { return exiting(1, 'ERROR! ' + err); }
|
||||||
|
if (!user) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
setTimeout(displayData, 300000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// specify user data to change:
|
||||||
|
var set = {};
|
||||||
|
|
||||||
|
if (user.items.pets['Turkey-Gilded']) {
|
||||||
|
set = {'migration':migrationName, 'items.mounts.Turkey-Gilded':true};
|
||||||
|
} else if (user.items.mounts['Turkey-Base']) {
|
||||||
|
set = {'migration':migrationName, 'items.pets.Turkey-Gilded':5};
|
||||||
|
} else if (user.items.pets['Turkey-Base']) {
|
||||||
|
set = {'migration':migrationName, 'items.mounts.Turkey-Base':true};
|
||||||
|
} else {
|
||||||
|
set = {'migration':migrationName, 'items.pets.Turkey-Base':5};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.update({_id:user._id}, {$set:set});
|
||||||
|
|
||||||
|
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
var migrationName = '20161230_nye_hats.js';
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Yearly New Year's party hat award
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mongo = require('mongoskin');
|
||||||
|
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
|
||||||
|
var dbUsers = mongo.db(connectionString).collection('users');
|
||||||
|
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'migration':{$ne:migrationName},
|
||||||
|
'auth.timestamps.loggedin':{$gt:new Date('2016-11-30')} // Remove after first run
|
||||||
|
};
|
||||||
|
|
||||||
|
// specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
var fields = {
|
||||||
|
'items.gear.owned': 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.warn('Updating users...');
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
||||||
|
if (err) { return exiting(1, 'ERROR! ' + err); }
|
||||||
|
if (!user) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
setTimeout(displayData, 300000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
|
||||||
|
// specify user data to change:
|
||||||
|
var set = {};
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.head_special_nye2015 !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.head_special_nye2016':false};
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_nye2014 !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.head_special_nye2015':false};
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_nye !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.head_special_nye2014':false};
|
||||||
|
} else {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.head_special_nye':false};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.update({_id:user._id}, {$set:set});
|
||||||
|
|
||||||
|
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
var migrationName = '20170120_missing_incentive.js';
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Award missing Royal Purple Hatching Potion to users with 55+ check-ins
|
||||||
|
* Reduce users with impossible check-in counts to a reasonable number
|
||||||
|
*/
|
||||||
|
|
||||||
|
import monk from 'monk';
|
||||||
|
import common from '../website/common';
|
||||||
|
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
|
function processUsers(lastId) {
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'loginIncentives': {$gt:54},
|
||||||
|
'migration': {$ne: migrationName},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.find(query, {
|
||||||
|
sort: {_id: 1},
|
||||||
|
limit: 250,
|
||||||
|
fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, 'ERROR! ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
function updateUsers (users) {
|
||||||
|
if (!users || users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
displayData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userPromises = users.map(updateUser);
|
||||||
|
var lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(function () {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
var language = user.preferences.language || 'en';
|
||||||
|
var set = {'migration': migrationName};
|
||||||
|
var inc = {'items.hatchingPotions.RoyalPurple': 1};
|
||||||
|
if (user.loginIncentives > 58) {
|
||||||
|
set = {'migration': migrationName, 'loginIncentives': 58};
|
||||||
|
}
|
||||||
|
var push = {
|
||||||
|
'notifications': {
|
||||||
|
'type': 'LOGIN_INCENTIVE',
|
||||||
|
'data': {
|
||||||
|
'nextRewardAt': 60,
|
||||||
|
'rewardKey': [
|
||||||
|
'Pet_HatchingPotion_Purple',
|
||||||
|
],
|
||||||
|
'rewardText': common.i18n.t('potion', {potionType: common.i18n.t('hatchingPotionRoyalPurple', language)}, language),
|
||||||
|
'reward': [
|
||||||
|
{
|
||||||
|
'premium': true,
|
||||||
|
'key': 'RoyalPurple',
|
||||||
|
'limited': true,
|
||||||
|
'value': 2,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'message': common.i18n.t('unlockedCheckInReward', language),
|
||||||
|
},
|
||||||
|
'id': common.uuid(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dbUsers.update({_id: user._id}, {$set:set, $push:push, $inc:inc});
|
||||||
|
|
||||||
|
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
var migrationName = '20170131_habit_birthday.js';
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Award 2017 party robes if user has 2016 robes, 2016 robes if they have the 2015 robes,
|
||||||
|
* 2015 robes if they have the 2014 robes, and 2014 robes otherwise. Also cake!
|
||||||
|
*/
|
||||||
|
|
||||||
|
var monk = require('monk');
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
|
function processUsers(lastId) {
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'migration':{$ne:migrationName},
|
||||||
|
'auth.timestamps.loggedin':{$gt:new Date('2017-01-24')}, // remove after first run to cover remaining users
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.find(query, {
|
||||||
|
sort: {_id: 1},
|
||||||
|
limit: 250,
|
||||||
|
fields: [ // specify fields we are interested in to limit retrieved data (empty if we're not reading data)
|
||||||
|
'items.gear.owned'
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, 'ERROR! ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
function updateUsers (users) {
|
||||||
|
if (!users || users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
displayData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userPromises = users.map(updateUser);
|
||||||
|
var lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(function () {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
var set = {'migration':migrationName};
|
||||||
|
if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2016')) {
|
||||||
|
set['items.gear.owned.armor_special_birthday2017'] = false;
|
||||||
|
} else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday2015')) {
|
||||||
|
set['items.gear.owned.armor_special_birthday2016'] = false;
|
||||||
|
} else if (user.items && user.items.gear && user.items.gear.owned && user.items.gear.owned.hasOwnProperty('armor_special_birthday')) {
|
||||||
|
set['items.gear.owned.armor_special_birthday2015'] = false;
|
||||||
|
} else {
|
||||||
|
set['items.gear.owned.armor_special_birthday'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var inc = {
|
||||||
|
'items.food.Cake_Skeleton':1,
|
||||||
|
'items.food.Cake_Base':1,
|
||||||
|
'items.food.Cake_CottonCandyBlue':1,
|
||||||
|
'items.food.Cake_CottonCandyPink':1,
|
||||||
|
'items.food.Cake_Shade':1,
|
||||||
|
'items.food.Cake_White':1,
|
||||||
|
'items.food.Cake_Golden':1,
|
||||||
|
'items.food.Cake_Zombie':1,
|
||||||
|
'items.food.Cake_Desert':1,
|
||||||
|
'items.food.Cake_Red':1,
|
||||||
|
'achievements.habitBirthdays':1
|
||||||
|
};
|
||||||
|
|
||||||
|
dbUsers.update({_id: user._id}, {$set:set, $inc:inc});
|
||||||
|
|
||||||
|
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
require("babel-register");
|
||||||
|
require("babel-polyfill");
|
||||||
|
|
||||||
|
// This file must use ES5, everything required can be in ES6
|
||||||
|
|
||||||
|
function setUpServer () {
|
||||||
|
var nconf = require('nconf');
|
||||||
|
var mongoose = require('mongoose');
|
||||||
|
var Bluebird = require('bluebird');
|
||||||
|
var setupNconf = require('../website/server/libs/setupNconf');
|
||||||
|
setupNconf();
|
||||||
|
// We require src/server and npt src/index because
|
||||||
|
// 1. nconf is already setup
|
||||||
|
// 2. we don't need clustering
|
||||||
|
require('../website/server/server'); // eslint-disable-line global-require
|
||||||
|
}
|
||||||
|
setUpServer();
|
||||||
|
|
||||||
|
// Replace this with your migration
|
||||||
|
var processUsers = require('./new_stuff');
|
||||||
|
processUsers();
|
||||||
@@ -2,7 +2,7 @@ var _id = '';
|
|||||||
var update = {
|
var update = {
|
||||||
$addToSet: {
|
$addToSet: {
|
||||||
'purchased.plan.mysteryItems':{
|
'purchased.plan.mysteryItems':{
|
||||||
$each:['head_mystery_201609','armor_mystery_201609']
|
$each:['head_mystery_201702','back_mystery_201702']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+44
-22
@@ -6,49 +6,69 @@ var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
|||||||
* set the newStuff flag in all user accounts so they see a Bailey message
|
* set the newStuff flag in all user accounts so they see a Bailey message
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var mongo = require('mongoskin');
|
var monk = require('monk');
|
||||||
|
|
||||||
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
var dbUsers = mongo.db(connectionString).collection('users');
|
function processUsers(lastId) {
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'flags.newStuff': {$ne:true},
|
||||||
|
};
|
||||||
|
|
||||||
// specify a query to limit the affected users (empty for all users):
|
if (lastId) {
|
||||||
var query = {
|
query._id = {
|
||||||
'flags.newStuff':{$ne:true}
|
$gt: lastId
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
dbUsers.find(query, {
|
||||||
var fields = {
|
sort: {_id: 1},
|
||||||
};
|
limit: 250,
|
||||||
|
fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, 'ERROR! ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
console.warn('Updating users...');
|
|
||||||
var progressCount = 1000;
|
var progressCount = 1000;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
|
||||||
if (err) { return exiting(1, 'ERROR! ' + err); }
|
function updateUsers (users) {
|
||||||
if (!user) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
setTimeout(displayData, 300000);
|
displayData();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var userPromises = users.map(updateUser);
|
||||||
|
var lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(function () {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
// specify user data to change:
|
var set = {'flags.newStuff': true};
|
||||||
var set = {'flags.newStuff':true};
|
|
||||||
|
|
||||||
dbUsers.update({_id:user._id}, {$set:set});
|
dbUsers.update({_id: user._id}, {$set:set});
|
||||||
|
|
||||||
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
function displayData() {
|
function displayData() {
|
||||||
console.warn('\n' + count + ' users processed\n');
|
console.warn('\n' + count + ' users processed\n');
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function exiting(code, msg) {
|
function exiting(code, msg) {
|
||||||
code = code || 0; // 0 = success
|
code = code || 0; // 0 = success
|
||||||
if (code && !msg) { msg = 'ERROR!'; }
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
@@ -58,3 +78,5 @@ function exiting(code, msg) {
|
|||||||
}
|
}
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
|
|||||||
@@ -6,52 +6,69 @@ var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
|||||||
* Remove flag stating that the Enchanted Armoire is empty, for when new equipment is added
|
* Remove flag stating that the Enchanted Armoire is empty, for when new equipment is added
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var dbserver = 'localhost:27017'; // FOR TEST DATABASE
|
var monk = require('monk');
|
||||||
// var dbserver = 'username:password@ds031379-a0.mongolab.com:31379'; // FOR PRODUCTION DATABASE
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
var dbname = 'habitrpg';
|
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
var mongo = require('mongoskin');
|
function processUsers(lastId) {
|
||||||
var _ = require('lodash');
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'flags.armoireEmpty': true,
|
||||||
|
};
|
||||||
|
|
||||||
var dbUsers = mongo.db(dbserver + '/' + dbname + '?auto_reconnect').collection('users');
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// specify a query to limit the affected users (empty for all users):
|
dbUsers.find(query, {
|
||||||
var query = {
|
sort: {_id: 1},
|
||||||
'flags.armoireEmpty':true
|
limit: 250,
|
||||||
};
|
fields: [] // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, 'ERROR! ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
|
||||||
var fields = {
|
|
||||||
'flags.armoireEmpty':1
|
|
||||||
};
|
|
||||||
|
|
||||||
console.warn('Updating users...');
|
|
||||||
var progressCount = 1000;
|
var progressCount = 1000;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
|
|
||||||
if (err) { return exiting(1, 'ERROR! ' + err); }
|
function updateUsers (users) {
|
||||||
if (!user) {
|
if (!users || users.length === 0) {
|
||||||
console.warn('All appropriate users found and modified.');
|
console.warn('All appropriate users found and modified.');
|
||||||
return displayData();
|
displayData();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var userPromises = users.map(updateUser);
|
||||||
|
var lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(function () {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
// specify user data to change:
|
var set = {'migration': migrationName, 'flags.armoireEmpty': false};
|
||||||
var set = {'migration':migrationName, 'flags.armoireEmpty':false};
|
|
||||||
|
|
||||||
dbUsers.update({_id:user._id}, {$set:set});
|
dbUsers.update({_id: user._id}, {$set:set});
|
||||||
|
|
||||||
if (count%progressCount == 0) console.warn(count + ' ' + user._id);
|
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
function displayData() {
|
function displayData() {
|
||||||
console.warn('\n' + count + ' users processed\n');
|
console.warn('\n' + count + ' users processed\n');
|
||||||
return exiting(0);
|
return exiting(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function exiting(code, msg) {
|
function exiting(code, msg) {
|
||||||
code = code || 0; // 0 = success
|
code = code || 0; // 0 = success
|
||||||
if (code && !msg) { msg = 'ERROR!'; }
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
@@ -61,3 +78,5 @@ function exiting(code, msg) {
|
|||||||
}
|
}
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
var migrationName = 'restore_profile_data.js';
|
||||||
|
var authorName = 'ThehollidayInn'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = ''; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if users have empty profile data in new database and update it with old database info
|
||||||
|
*/
|
||||||
|
|
||||||
|
var monk = require('monk');
|
||||||
|
var connectionString = ''; // FOR TEST DATABASE
|
||||||
|
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
|
var monk2 = require('monk');
|
||||||
|
var oldDbConnectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
var olDbUsers = monk2(oldDbConnectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
|
function processUsers(lastId)
|
||||||
|
{
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
// 'profile.name': 'profile name not found',
|
||||||
|
'profile.blurb': null,
|
||||||
|
// 'auth.timestamps.loggedin': {$gt: new Date('11/30/2016')},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.find(query, {
|
||||||
|
sort: {_id: 1},
|
||||||
|
limit: 250,
|
||||||
|
fields: ['_id', 'profile', 'auth.timestamps.loggedin'] // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, 'ERROR! ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
function updateUsers (users) {
|
||||||
|
if (!users || users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
setTimeout(displayData, 300000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userPaymentPromises = users.map(updateUser);
|
||||||
|
var lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPaymentPromises)
|
||||||
|
.then(function () {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (!user.profile.name || user.profile.name === 'profile name not found' || !user.profile.imageUrl || !user.profile.blurb) {
|
||||||
|
return olDbUsers.findOne({_id: user._id}, '_id profile')
|
||||||
|
.then((oldUserData) => {
|
||||||
|
if (!oldUserData) return;
|
||||||
|
// specify user data to change:
|
||||||
|
var set = {};
|
||||||
|
|
||||||
|
if (oldUserData.profile.name === 'profile name not found') return;
|
||||||
|
|
||||||
|
var userNeedsProfileName = !user.profile.name || user.profile.name === 'profile name not found';
|
||||||
|
if (userNeedsProfileName && oldUserData.profile.name) {
|
||||||
|
set['profile.name'] = oldUserData.profile.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.profile.imageUrl && oldUserData.profile.imageUrl) {
|
||||||
|
set['profile.imageUrl'] = oldUserData.profile.imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.profile.blurb && oldUserData.profile.blurb) {
|
||||||
|
set['profile.blurb'] = oldUserData.profile.blurb;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(set).length !== 0 && set.constructor === Object) {
|
||||||
|
console.log(set)
|
||||||
|
return dbUsers.update({_id: user._id}, {$set:set});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
processUsers()
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
var migrationName = '20170201_takeThis.js'; // Update per month
|
||||||
|
var authorName = 'Sabe'; // in case script author needs to know when their ...
|
||||||
|
var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Award Take This ladder items to participants in this month's challenge
|
||||||
|
*/
|
||||||
|
|
||||||
|
var monk = require('monk');
|
||||||
|
var connectionString = 'mongodb://localhost:27017/habitrpg?auto_reconnect=true'; // FOR TEST DATABASE
|
||||||
|
var dbUsers = monk(connectionString).get('users', { castIds: false });
|
||||||
|
|
||||||
|
function processUsers(lastId) {
|
||||||
|
// specify a query to limit the affected users (empty for all users):
|
||||||
|
var query = {
|
||||||
|
'migration':{$ne:migrationName},
|
||||||
|
'challenges':{$in:['b1d436b5-c784-42e3-9b07-7072479a6f8e']} // Update per month
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastId) {
|
||||||
|
query._id = {
|
||||||
|
$gt: lastId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.find(query, {
|
||||||
|
sort: {_id: 1},
|
||||||
|
limit: 250,
|
||||||
|
fields: [
|
||||||
|
'items.gear.owned',
|
||||||
|
] // specify fields we are interested in to limit retrieved data (empty if we're not reading data):
|
||||||
|
})
|
||||||
|
.then(updateUsers)
|
||||||
|
.catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
return exiting(1, 'ERROR! ' + err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var progressCount = 1000;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
function updateUsers (users) {
|
||||||
|
if (!users || users.length === 0) {
|
||||||
|
console.warn('All appropriate users found and modified.');
|
||||||
|
displayData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userPromises = users.map(updateUser);
|
||||||
|
var lastUser = users[users.length - 1];
|
||||||
|
|
||||||
|
return Promise.all(userPromises)
|
||||||
|
.then(function () {
|
||||||
|
processUsers(lastUser._id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUser (user) {
|
||||||
|
count++;
|
||||||
|
|
||||||
|
var set = {};
|
||||||
|
|
||||||
|
if (typeof user.items.gear.owned.back_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName};
|
||||||
|
} else if (typeof user.items.gear.owned.body_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.back_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.head_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.body_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.armor_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.head_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.weapon_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.armor_special_takeThis':false};
|
||||||
|
} else if (typeof user.items.gear.owned.shield_special_takeThis !== 'undefined') {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.weapon_special_takeThis':false};
|
||||||
|
} else {
|
||||||
|
set = {'migration':migrationName, 'items.gear.owned.shield_special_takeThis':false};
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUsers.update({_id: user._id}, {$set:set});
|
||||||
|
|
||||||
|
if (count % progressCount == 0) console.warn(count + ' ' + user._id);
|
||||||
|
if (user._id == authorUuid) console.warn(authorName + ' processed');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayData() {
|
||||||
|
console.warn('\n' + count + ' users processed\n');
|
||||||
|
return exiting(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exiting(code, msg) {
|
||||||
|
code = code || 0; // 0 = success
|
||||||
|
if (code && !msg) { msg = 'ERROR!'; }
|
||||||
|
if (msg) {
|
||||||
|
if (code) { console.error(msg); }
|
||||||
|
else { console.log( msg); }
|
||||||
|
}
|
||||||
|
process.exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processUsers;
|
||||||
Generated
+5100
-1686
File diff suppressed because it is too large
Load Diff
+54
-47
@@ -1,27 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||||
"version": "3.46.0",
|
"version": "3.78.0",
|
||||||
"main": "./website/server/index.js",
|
"main": "./website/server/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@slack/client": "3.6.0",
|
"@slack/client": "^3.8.1",
|
||||||
"accepts": "^1.3.2",
|
"accepts": "^1.3.2",
|
||||||
"amazon-payments": "0.0.4",
|
"amazon-payments": "0.0.4",
|
||||||
"amplitude": "^2.0.3",
|
"amplitude": "^2.0.3",
|
||||||
"apidoc": "^0.16.0",
|
"apidoc": "^0.17.5",
|
||||||
"apn": "^1.7.6",
|
"apn": "^1.7.6",
|
||||||
"async": "^1.5.0",
|
"async": "^1.5.0",
|
||||||
"autoprefixer": "^6.4.0",
|
"autoprefixer": "^6.4.0",
|
||||||
"aws-sdk": "^2.0.25",
|
"aws-sdk": "^2.0.25",
|
||||||
|
"axios": "^0.15.3",
|
||||||
"babel-core": "^6.0.0",
|
"babel-core": "^6.0.0",
|
||||||
"babel-loader": "^6.0.0",
|
"babel-loader": "^6.0.0",
|
||||||
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
"babel-plugin-transform-async-to-module-method": "^6.8.0",
|
"babel-plugin-transform-async-to-module-method": "^6.8.0",
|
||||||
"babel-plugin-transform-object-rest-spread": "^6.16.0",
|
"babel-plugin-transform-object-rest-spread": "^6.16.0",
|
||||||
|
"babel-plugin-transform-regenerator": "^6.16.1",
|
||||||
"babel-polyfill": "^6.6.1",
|
"babel-polyfill": "^6.6.1",
|
||||||
"babel-preset-es2015": "^6.6.0",
|
"babel-preset-es2015": "^6.6.0",
|
||||||
"babel-register": "^6.6.0",
|
"babel-register": "^6.6.0",
|
||||||
"babel-runtime": "^6.11.6",
|
"babel-runtime": "^6.11.6",
|
||||||
"babelify": "^7.2.0",
|
"babelify": "^7.2.0",
|
||||||
|
"bcrypt": "^1.0.2",
|
||||||
"bluebird": "^3.3.5",
|
"bluebird": "^3.3.5",
|
||||||
"body-parser": "^1.15.0",
|
"body-parser": "^1.15.0",
|
||||||
"bower": "~1.3.12",
|
"bower": "~1.3.12",
|
||||||
@@ -29,17 +33,17 @@
|
|||||||
"compression": "^1.6.1",
|
"compression": "^1.6.1",
|
||||||
"connect-ratelimit": "0.0.7",
|
"connect-ratelimit": "0.0.7",
|
||||||
"cookie-session": "^1.2.0",
|
"cookie-session": "^1.2.0",
|
||||||
"coupon-code": "^0.4.3",
|
"coupon-code": "^0.4.5",
|
||||||
"css-loader": "^0.23.1",
|
"css-loader": "^0.26.1",
|
||||||
"csv-stringify": "^1.0.2",
|
"csv-stringify": "^1.0.2",
|
||||||
"cwait": "^1.0.0",
|
"cwait": "^1.0.0",
|
||||||
"domain-middleware": "~0.1.0",
|
"domain-middleware": "~0.1.0",
|
||||||
"estraverse": "^4.1.1",
|
"estraverse": "^4.1.1",
|
||||||
"express": "~4.13.3",
|
"express": "~4.14.0",
|
||||||
"express-csv": "~0.6.0",
|
"express-csv": "~0.6.0",
|
||||||
"express-validator": "^2.18.0",
|
"express-validator": "^2.18.0",
|
||||||
"extract-text-webpack-plugin": "^1.0.1",
|
"extract-text-webpack-plugin": "^2.0.0-rc.3",
|
||||||
"file-loader": "^0.8.4",
|
"file-loader": "^0.10.0",
|
||||||
"glob": "^4.3.5",
|
"glob": "^4.3.5",
|
||||||
"got": "^6.1.1",
|
"got": "^6.1.1",
|
||||||
"grunt": "~0.4.1",
|
"grunt": "~0.4.1",
|
||||||
@@ -64,70 +68,72 @@
|
|||||||
"image-size": "~0.3.2",
|
"image-size": "~0.3.2",
|
||||||
"in-app-purchase": "^1.1.6",
|
"in-app-purchase": "^1.1.6",
|
||||||
"jade": "~1.11.0",
|
"jade": "~1.11.0",
|
||||||
|
"jquery": "^3.1.1",
|
||||||
"js2xmlparser": "~1.0.0",
|
"js2xmlparser": "~1.0.0",
|
||||||
"json-loader": "^0.5.4",
|
|
||||||
"less": "^2.7.1",
|
"less": "^2.7.1",
|
||||||
"less-loader": "^2.2.3",
|
"less-loader": "^2.2.3",
|
||||||
"lodash": "^3.10.1",
|
"lodash": "^3.10.1",
|
||||||
|
"lodash.pickby": "^4.2.0",
|
||||||
"lodash.setwith": "^4.2.0",
|
"lodash.setwith": "^4.2.0",
|
||||||
"merge-stream": "^1.0.0",
|
"merge-stream": "^1.0.0",
|
||||||
"method-override": "^2.3.5",
|
"method-override": "^2.3.5",
|
||||||
"moment": "^2.13.0",
|
"moment": "^2.13.0",
|
||||||
"mongoose": "^4.4.16",
|
"mongoose": "^4.7.1",
|
||||||
"mongoose-id-autoinc": "~2013.7.14-4",
|
"mongoose-id-autoinc": "~2013.7.14-4",
|
||||||
"morgan": "^1.7.0",
|
"morgan": "^1.7.0",
|
||||||
"nconf": "~0.8.2",
|
"nconf": "~0.8.2",
|
||||||
"newrelic": "^1.27.2",
|
|
||||||
"nib": "^1.1.0",
|
"nib": "^1.1.0",
|
||||||
"node-gcm": "^0.14.4",
|
"node-gcm": "^0.14.4",
|
||||||
"nodemailer": "^2.3.2",
|
"nodemailer": "^2.3.2",
|
||||||
"object-path": "^0.9.2",
|
"object-path": "^0.9.2",
|
||||||
"ora": "^0.2.0",
|
"ora": "^1.1.0",
|
||||||
"pageres": "^4.1.1",
|
"pageres": "^4.1.1",
|
||||||
"passport": "~0.2.1",
|
"passport": "^0.3.2",
|
||||||
"passport-facebook": "2.0.0",
|
"passport-facebook": "^2.0.0",
|
||||||
"passport-google-oauth20": "1.0.0",
|
"passport-google-oauth20": "1.0.0",
|
||||||
"paypal-ipn": "3.0.0",
|
"paypal-ipn": "3.0.0",
|
||||||
"paypal-rest-sdk": "^1.2.1",
|
"paypal-rest-sdk": "^1.2.1",
|
||||||
|
"postcss-easy-import": "^2.0.0",
|
||||||
"pretty-data": "^0.40.0",
|
"pretty-data": "^0.40.0",
|
||||||
"ps-tree": "^1.0.0",
|
"ps-tree": "^1.0.0",
|
||||||
"pug": "^2.0.0-beta6",
|
"pug": "^2.0.0-beta11",
|
||||||
"push-notify": "habitrpg/push-notify#v1.2.0",
|
"push-notify": "habitrpg/push-notify#v1.2.0",
|
||||||
"pusher": "^1.3.0",
|
"pusher": "^1.3.0",
|
||||||
"request": "~2.72.0",
|
"request": "~2.74.0",
|
||||||
"rimraf": "^2.4.3",
|
"rimraf": "^2.4.3",
|
||||||
"run-sequence": "^1.1.4",
|
"run-sequence": "^1.1.4",
|
||||||
"s3-upload-stream": "^1.0.6",
|
"s3-upload-stream": "^1.0.6",
|
||||||
"semantic-ui-less": "~2.2.4",
|
"semantic-ui-less": "~2.2.4",
|
||||||
"serve-favicon": "^2.3.0",
|
"serve-favicon": "^2.3.0",
|
||||||
"shelljs": "^0.6.0",
|
"shelljs": "^0.7.6",
|
||||||
"stripe": "^4.2.0",
|
"stripe": "^4.2.0",
|
||||||
"superagent": "^1.8.3",
|
"superagent": "^3.4.3",
|
||||||
"universal-analytics": "~0.3.2",
|
"universal-analytics": "~0.3.2",
|
||||||
"url-loader": "^0.5.7",
|
"url-loader": "^0.5.7",
|
||||||
"useragent": "2.1.9",
|
"useragent": "^2.1.9",
|
||||||
"uuid": "^2.0.1",
|
"uuid": "^3.0.1",
|
||||||
"validator": "^4.9.0",
|
"validator": "^4.9.0",
|
||||||
"vinyl-buffer": "^1.0.0",
|
"vinyl-buffer": "^1.0.0",
|
||||||
"vinyl-source-stream": "^1.1.0",
|
"vinyl-source-stream": "^1.1.0",
|
||||||
"vue": "^2.0.0-rc.6",
|
"vue": "^2.1.0",
|
||||||
"vue-hot-reload-api": "^1.2.0",
|
"vue-loader": "^11.0.0",
|
||||||
"vue-loader": "^9.4.0",
|
|
||||||
"vue-resource": "^1.0.2",
|
|
||||||
"vue-router": "^2.0.0-rc.5",
|
"vue-router": "^2.0.0-rc.5",
|
||||||
"webpack": "^1.12.2",
|
"vue-style-loader": "^2.0.0",
|
||||||
"webpack-merge": "^0.8.3",
|
"vue-template-compiler": "^2.1.10",
|
||||||
|
"webpack": "^2.2.1",
|
||||||
|
"webpack-merge": "^2.6.1",
|
||||||
"winston": "^2.1.0",
|
"winston": "^2.1.0",
|
||||||
"xml2js": "^0.4.4"
|
"xml2js": "^0.4.4"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^4.3.1",
|
"node": "^6.9.1",
|
||||||
"npm": "^3.8.9"
|
"npm": "^4.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint --ext .js,.vue .",
|
"lint": "eslint --ext .js,.vue .",
|
||||||
"test": "npm run lint && gulp test && npm run client:unit",
|
"test": "npm run lint && gulp test && npm run client:unit",
|
||||||
|
"test:build": "gulp test:prepare:build",
|
||||||
"test:api-v3": "gulp test:api-v3",
|
"test:api-v3": "gulp test:api-v3",
|
||||||
"test:api-v3:unit": "gulp test:api-v3:unit",
|
"test:api-v3:unit": "gulp test:api-v3:unit",
|
||||||
"test:api-v3:integration": "gulp test:api-v3:integration",
|
"test:api-v3:integration": "gulp test:api-v3:integration",
|
||||||
@@ -145,38 +151,37 @@
|
|||||||
"sprites": "gulp sprites:compile",
|
"sprites": "gulp sprites:compile",
|
||||||
"client:dev": "node webpack/dev-server.js",
|
"client:dev": "node webpack/dev-server.js",
|
||||||
"client:build": "node webpack/build.js",
|
"client:build": "node webpack/build.js",
|
||||||
"client:unit": "karma start test/client/unit/karma.conf.js --single-run",
|
"client:unit": "cross-env NODE_ENV=test karma start test/client/unit/karma.conf.js --single-run",
|
||||||
"client:unit:watch": "karma start test/client/unit/karma.conf.js",
|
"client:unit:watch": "cross-env NODE_ENV=test karma start test/client/unit/karma.conf.js",
|
||||||
"client:e2e": "node test/client/e2e/runner.js",
|
"client:e2e": "node test/client/e2e/runner.js",
|
||||||
"client:test": "npm run client:unit && npm run client:e2e",
|
"client:test": "npm run client:unit && npm run client:e2e",
|
||||||
"start": "gulp run:dev",
|
"start": "gulp run:dev",
|
||||||
"postinstall": "bower --config.interactive=false install -f; gulp build; npm run client:build"
|
"postinstall": "bower --config.interactive=false install -f; gulp build; npm run client:build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-eslint": "^6.0.0",
|
"babel-plugin-istanbul": "^4.0.0",
|
||||||
"chai": "^3.4.0",
|
"chai": "^3.4.0",
|
||||||
"chai-as-promised": "^5.1.0",
|
"chai-as-promised": "^5.1.0",
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
"chromedriver": "^2.21.2",
|
"chromedriver": "^2.27.2",
|
||||||
"connect-history-api-fallback": "^1.1.0",
|
"connect-history-api-fallback": "^1.1.0",
|
||||||
"coveralls": "^2.11.2",
|
"coveralls": "^2.11.2",
|
||||||
"cross-spawn": "^2.1.5",
|
"cross-env": "^3.1.4",
|
||||||
|
"cross-spawn": "^5.0.1",
|
||||||
"csv": "~0.3.6",
|
"csv": "~0.3.6",
|
||||||
"deep-diff": "~0.1.4",
|
"deep-diff": "~0.1.4",
|
||||||
"eslint": "~2.12.0",
|
"eslint": "^3.0.0",
|
||||||
"eslint-config-habitrpg": "^1.0.0",
|
"eslint-config-habitrpg": "^2.0.0",
|
||||||
"eslint-friendly-formatter": "^2.0.5",
|
"eslint-friendly-formatter": "^2.0.5",
|
||||||
"eslint-loader": "^1.3.0",
|
"eslint-loader": "^1.3.0",
|
||||||
"eslint-plugin-babel": "^3.0.0",
|
"eslint-plugin-html": "^2.0.0",
|
||||||
"eslint-plugin-html": "^1.3.0",
|
"eslint-plugin-mocha": "^4.7.0",
|
||||||
"eslint-plugin-mocha": "^2.1.0",
|
|
||||||
"event-stream": "^3.2.2",
|
"event-stream": "^3.2.2",
|
||||||
"eventsource-polyfill": "^0.9.6",
|
"eventsource-polyfill": "^0.9.6",
|
||||||
"expect.js": "~0.2.0",
|
"expect.js": "~0.2.0",
|
||||||
"grunt-karma": "~0.12.1",
|
"grunt-karma": "~0.12.1",
|
||||||
"http-proxy-middleware": "^0.12.0",
|
"http-proxy-middleware": "^0.17.0",
|
||||||
"inject-loader": "^2.0.1",
|
"inject-loader": "^3.0.0-beta4",
|
||||||
"isparta-loader": "^2.0.0",
|
|
||||||
"istanbul": "^0.3.14",
|
"istanbul": "^0.3.14",
|
||||||
"karma": "^1.3.0",
|
"karma": "^1.3.0",
|
||||||
"karma-babel-preprocessor": "^6.0.1",
|
"karma-babel-preprocessor": "^6.0.1",
|
||||||
@@ -188,24 +193,26 @@
|
|||||||
"karma-sinon-chai": "^1.2.0",
|
"karma-sinon-chai": "^1.2.0",
|
||||||
"karma-sourcemap-loader": "^0.3.7",
|
"karma-sourcemap-loader": "^0.3.7",
|
||||||
"karma-spec-reporter": "0.0.24",
|
"karma-spec-reporter": "0.0.24",
|
||||||
"karma-webpack": "^1.7.0",
|
"karma-webpack": "^2.0.2",
|
||||||
"lcov-result-merger": "^1.0.2",
|
"lcov-result-merger": "^1.0.2",
|
||||||
"lolex": "^1.4.0",
|
"lolex": "^1.4.0",
|
||||||
"mocha": "^2.3.3",
|
"mocha": "^2.3.3",
|
||||||
"mongodb": "^2.0.46",
|
"mongodb": "^2.0.46",
|
||||||
"mongoskin": "~2.1.0",
|
"mongoskin": "~2.1.0",
|
||||||
"nightwatch": "^0.8.18",
|
"monk": "^4.0.0",
|
||||||
|
"nightwatch": "^0.9.12",
|
||||||
"phantomjs-prebuilt": "^2.1.12",
|
"phantomjs-prebuilt": "^2.1.12",
|
||||||
"protractor": "^3.1.1",
|
"protractor": "^3.1.1",
|
||||||
"require-again": "^2.0.0",
|
"require-again": "^2.0.0",
|
||||||
"rewire": "^2.3.3",
|
"rewire": "^2.3.3",
|
||||||
"selenium-server": "2.53.0",
|
"selenium-server": "^3.0.1",
|
||||||
"sinon": "^1.17.2",
|
"sinon": "^1.17.2",
|
||||||
"sinon-chai": "^2.8.0",
|
"sinon-chai": "^2.8.0",
|
||||||
|
"sinon-stub-promise": "^4.0.0",
|
||||||
"superagent-defaults": "^0.1.13",
|
"superagent-defaults": "^0.1.13",
|
||||||
"vinyl-source-stream": "^1.0.0",
|
|
||||||
"vinyl-transform": "^1.0.0",
|
"vinyl-transform": "^1.0.0",
|
||||||
"webpack-dev-middleware": "^1.4.0",
|
"webpack-bundle-analyzer": "^2.2.1",
|
||||||
"webpack-hot-middleware": "^2.6.0"
|
"webpack-dev-middleware": "^1.10.0",
|
||||||
|
"webpack-hot-middleware": "^2.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": [
|
"extends": [
|
||||||
"habitrpg/mocha",
|
"habitrpg/mocha",
|
||||||
"habitrpg/babel"
|
"habitrpg/esnext"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"node": true,
|
"node": true,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../helpers/api-v3-integration.helper';
|
} from '../../../../helpers/api-v3-integration.helper';
|
||||||
|
|
||||||
describe('GET challenges/group/:groupId', () => {
|
describe('GET challenges/groups/:groupId', () => {
|
||||||
context('Public Guild', () => {
|
context('Public Guild', () => {
|
||||||
let publicGuild, user, nonMember, challenge, challenge2;
|
let publicGuild, user, nonMember, challenge, challenge2;
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,24 @@ describe('POST /chat', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Returns an error when an empty message is provided', async () => {
|
||||||
|
await expect(user.post(`/groups/${groupWithChat._id}/chat`, { message: ' '}))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('invalidReqParams'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Returns an error when an message containing only newlines is provided', async () => {
|
||||||
|
await expect(user.post(`/groups/${groupWithChat._id}/chat`, { message: '\n\n'}))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('invalidReqParams'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Returns an error when group is not found', async () => {
|
it('Returns an error when group is not found', async () => {
|
||||||
await expect(user.post('/groups/invalidID/chat', { message: testMessage})).to.eventually.be.rejected.and.eql({
|
await expect(user.post('/groups/invalidID/chat', { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||||
code: 404,
|
code: 404,
|
||||||
@@ -43,7 +61,7 @@ describe('POST /chat', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Returns an error when chat privileges are revoked', async () => {
|
it('returns an error when chat privileges are revoked when sending a message to a public guild', async () => {
|
||||||
await expect(userWithChatRevoked.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage})).to.eventually.be.rejected.and.eql({
|
await expect(userWithChatRevoked.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage})).to.eventually.be.rejected.and.eql({
|
||||||
code: 404,
|
code: 404,
|
||||||
error: 'NotFound',
|
error: 'NotFound',
|
||||||
@@ -51,6 +69,42 @@ describe('POST /chat', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not error when sending a message to a private guild with a user with revoked chat', async () => {
|
||||||
|
let { group, members } = await createAndPopulateGroup({
|
||||||
|
groupDetails: {
|
||||||
|
name: 'Private Guild',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'private',
|
||||||
|
},
|
||||||
|
members: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
let privateGuildMemberWithChatsRevoked = members[0];
|
||||||
|
await privateGuildMemberWithChatsRevoked.update({'flags.chatRevoked': true});
|
||||||
|
|
||||||
|
let message = await privateGuildMemberWithChatsRevoked.post(`/groups/${group._id}/chat`, { message: testMessage});
|
||||||
|
|
||||||
|
expect(message.message.id).to.exist;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not error when sending a message to a party with a user with revoked chat', async () => {
|
||||||
|
let { group, members } = await createAndPopulateGroup({
|
||||||
|
groupDetails: {
|
||||||
|
name: 'Party',
|
||||||
|
type: 'party',
|
||||||
|
privacy: 'private',
|
||||||
|
},
|
||||||
|
members: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
let privatePartyMemberWithChatsRevoked = members[0];
|
||||||
|
await privatePartyMemberWithChatsRevoked.update({'flags.chatRevoked': true});
|
||||||
|
|
||||||
|
let message = await privatePartyMemberWithChatsRevoked.post(`/groups/${group._id}/chat`, { message: testMessage});
|
||||||
|
|
||||||
|
expect(message.message.id).to.exist;
|
||||||
|
});
|
||||||
|
|
||||||
it('creates a chat', async () => {
|
it('creates a chat', async () => {
|
||||||
let message = await user.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
let message = await user.post(`/groups/${groupWithChat._id}/chat`, { message: testMessage});
|
||||||
|
|
||||||
|
|||||||
@@ -29,14 +29,6 @@ describe('POST /coupons/generate/:event', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an error if event is missing', async () => {
|
|
||||||
await expect(user.post('/coupons/generate')).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 404,
|
|
||||||
error: 'NotFound',
|
|
||||||
message: 'Not found.',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns an error if event is invalid', async () => {
|
it('returns an error if event is invalid', async () => {
|
||||||
await expect(user.post('/coupons/generate/notValid?count=1')).to.eventually.be.rejected.and.eql({
|
await expect(user.post('/coupons/generate/notValid?count=1')).to.eventually.be.rejected.and.eql({
|
||||||
code: 400,
|
code: 400,
|
||||||
|
|||||||
@@ -7,15 +7,21 @@ import {
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
describe('GET /export/history.csv', () => {
|
describe('GET /export/history.csv', () => {
|
||||||
it('should return a valid CSV file with tasks history data', async () => {
|
// TODO disabled because it randomly causes the build to fail
|
||||||
|
xit('should return a valid CSV file with tasks history data', async () => {
|
||||||
let user = await generateUser();
|
let user = await generateUser();
|
||||||
let tasks = await user.post('/tasks/user', [
|
let tasks = await user.post('/tasks/user', [
|
||||||
{type: 'habit', text: 'habit 1'},
|
|
||||||
{type: 'daily', text: 'daily 1'},
|
{type: 'daily', text: 'daily 1'},
|
||||||
|
{type: 'habit', text: 'habit 1'},
|
||||||
{type: 'habit', text: 'habit 2'},
|
{type: 'habit', text: 'habit 2'},
|
||||||
{type: 'todo', text: 'todo 1'},
|
{type: 'todo', text: 'todo 1'},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// to handle occasional inconsistency in task creation order
|
||||||
|
tasks.sort(function (a, b) {
|
||||||
|
return a.text.localeCompare(b.text);
|
||||||
|
});
|
||||||
|
|
||||||
// score all the tasks twice
|
// score all the tasks twice
|
||||||
await user.post(`/tasks/${tasks[0]._id}/score/up`);
|
await user.post(`/tasks/${tasks[0]._id}/score/up`);
|
||||||
await user.post(`/tasks/${tasks[1]._id}/score/up`);
|
await user.post(`/tasks/${tasks[1]._id}/score/up`);
|
||||||
@@ -28,7 +34,7 @@ describe('GET /export/history.csv', () => {
|
|||||||
await user.post(`/tasks/${tasks[3]._id}/score/up`);
|
await user.post(`/tasks/${tasks[3]._id}/score/up`);
|
||||||
|
|
||||||
// adding an history entry to daily 1 manually because cron didn't run yet
|
// adding an history entry to daily 1 manually because cron didn't run yet
|
||||||
await updateDocument('tasks', tasks[1], {
|
await updateDocument('tasks', tasks[0], {
|
||||||
history: [{value: 3.2, date: Number(new Date())}],
|
history: [{value: 3.2, date: Number(new Date())}],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,11 +47,11 @@ describe('GET /export/history.csv', () => {
|
|||||||
let splitRes = res.split('\n');
|
let splitRes = res.split('\n');
|
||||||
|
|
||||||
expect(splitRes[0]).to.equal('Task Name,Task ID,Task Type,Date,Value');
|
expect(splitRes[0]).to.equal('Task Name,Task ID,Task Type,Date,Value');
|
||||||
expect(splitRes[1]).to.equal(`habit 1,${tasks[0]._id},habit,${moment(tasks[0].history[0].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[0].history[0].value}`);
|
expect(splitRes[1]).to.equal(`daily 1,${tasks[0]._id},daily,${moment(tasks[0].history[0].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[0].history[0].value}`);
|
||||||
expect(splitRes[2]).to.equal(`habit 1,${tasks[0]._id},habit,${moment(tasks[0].history[1].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[0].history[1].value}`);
|
expect(splitRes[2]).to.equal(`habit 1,${tasks[1]._id},habit,${moment(tasks[1].history[0].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[1].history[0].value}`);
|
||||||
expect(splitRes[3]).to.equal(`habit 2,${tasks[2]._id},habit,${moment(tasks[2].history[0].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[2].history[0].value}`);
|
expect(splitRes[3]).to.equal(`habit 1,${tasks[1]._id},habit,${moment(tasks[1].history[1].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[1].history[1].value}`);
|
||||||
expect(splitRes[4]).to.equal(`habit 2,${tasks[2]._id},habit,${moment(tasks[2].history[1].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[2].history[1].value}`);
|
expect(splitRes[4]).to.equal(`habit 2,${tasks[2]._id},habit,${moment(tasks[2].history[0].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[2].history[0].value}`);
|
||||||
expect(splitRes[5]).to.equal(`daily 1,${tasks[1]._id},daily,${moment(tasks[1].history[0].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[1].history[0].value}`);
|
expect(splitRes[5]).to.equal(`habit 2,${tasks[2]._id},habit,${moment(tasks[2].history[1].date).format('YYYY-MM-DD HH:mm:ss')},${tasks[2].history[1].value}`);
|
||||||
expect(splitRes[6]).to.equal('');
|
expect(splitRes[6]).to.equal('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import Bluebird from 'bluebird';
|
|||||||
let parseStringAsync = Bluebird.promisify(xml2js.parseString, {context: xml2js});
|
let parseStringAsync = Bluebird.promisify(xml2js.parseString, {context: xml2js});
|
||||||
|
|
||||||
describe('GET /export/userdata.xml', () => {
|
describe('GET /export/userdata.xml', () => {
|
||||||
it('should return a valid XML file with user data', async () => {
|
// TODO disabled because it randomly causes the build to fail
|
||||||
|
xit('should return a valid XML file with user data', async () => {
|
||||||
let user = await generateUser();
|
let user = await generateUser();
|
||||||
let tasks = await user.post('/tasks/user', [
|
let tasks = await user.post('/tasks/user', [
|
||||||
{type: 'habit', text: 'habit 1'},
|
{type: 'habit', text: 'habit 1'},
|
||||||
|
|||||||
@@ -82,8 +82,10 @@ describe('GET /groups/:groupId/members', () => {
|
|||||||
'backer', 'contributor', 'auth', 'items', 'inbox',
|
'backer', 'contributor', 'auth', 'items', 'inbox',
|
||||||
]);
|
]);
|
||||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
||||||
expect(Object.keys(memberRes.preferences).sort()).to.eql(['size', 'hair', 'skin', 'shirt',
|
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||||
'chair', 'costume', 'sleep', 'background'].sort());
|
'size', 'hair', 'skin', 'shirt',
|
||||||
|
'chair', 'costume', 'sleep', 'background',
|
||||||
|
].sort());
|
||||||
|
|
||||||
expect(memberRes.stats.maxMP).to.exist;
|
expect(memberRes.stats.maxMP).to.exist;
|
||||||
expect(memberRes.stats.maxHealth).to.equal(common.maxHealth);
|
expect(memberRes.stats.maxHealth).to.equal(common.maxHealth);
|
||||||
|
|||||||
@@ -134,6 +134,22 @@ describe('POST /group/:groupId/join', () => {
|
|||||||
|
|
||||||
await expect(user.get('/user')).to.eventually.have.deep.property('items.quests.basilist', 1);
|
await expect(user.get('/user')).to.eventually.have.deep.property('items.quests.basilist', 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('notifies inviting user that their invitation was accepted', async () => {
|
||||||
|
await invitedUser.post(`/groups/${guild._id}/join`);
|
||||||
|
|
||||||
|
let inviter = await user.get('/user');
|
||||||
|
let expectedData = {
|
||||||
|
headerText: t('invitationAcceptedHeader'),
|
||||||
|
bodyText: t('invitationAcceptedBody', {
|
||||||
|
username: invitedUser.auth.local.username,
|
||||||
|
groupName: guild.name,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(inviter.notifications[0].type).to.eql('GROUP_INVITE_ACCEPTED');
|
||||||
|
expect(inviter.notifications[0].data).to.eql(expectedData);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -172,6 +188,23 @@ describe('POST /group/:groupId/join', () => {
|
|||||||
await expect(invitedUser.get('/user')).to.eventually.have.deep.property('party._id', party._id);
|
await expect(invitedUser.get('/user')).to.eventually.have.deep.property('party._id', party._id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('notifies inviting user that their invitation was accepted', async () => {
|
||||||
|
await invitedUser.post(`/groups/${party._id}/join`);
|
||||||
|
|
||||||
|
let inviter = await user.get('/user');
|
||||||
|
|
||||||
|
let expectedData = {
|
||||||
|
headerText: t('invitationAcceptedHeader'),
|
||||||
|
bodyText: t('invitationAcceptedBody', {
|
||||||
|
username: invitedUser.auth.local.username,
|
||||||
|
groupName: party.name,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(inviter.notifications[0].type).to.eql('GROUP_INVITE_ACCEPTED');
|
||||||
|
expect(inviter.notifications[0].data).to.eql(expectedData);
|
||||||
|
});
|
||||||
|
|
||||||
it('clears invitation from user when joining party', async () => {
|
it('clears invitation from user when joining party', async () => {
|
||||||
await invitedUser.post(`/groups/${party._id}/join`);
|
await invitedUser.post(`/groups/${party._id}/join`);
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,19 @@ describe('POST /groups/:groupId/leave', () => {
|
|||||||
expect(groupToLeave.leader).to.equal(member._id);
|
expect(groupToLeave.leader).to.equal(member._id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('removes new messages for that group from user', async () => {
|
||||||
|
await member.post(`/groups/${groupToLeave._id}/chat`, { message: 'Some message' });
|
||||||
|
|
||||||
|
await leader.sync();
|
||||||
|
|
||||||
|
expect(leader.newMessages[groupToLeave._id]).to.not.be.empty;
|
||||||
|
|
||||||
|
await leader.post(`/groups/${groupToLeave._id}/leave`);
|
||||||
|
await leader.sync();
|
||||||
|
|
||||||
|
expect(leader.newMessages[groupToLeave._id]).to.be.empty;
|
||||||
|
});
|
||||||
|
|
||||||
context('With challenges', () => {
|
context('With challenges', () => {
|
||||||
let challenge;
|
let challenge;
|
||||||
|
|
||||||
@@ -122,6 +135,8 @@ describe('POST /groups/:groupId/leave', () => {
|
|||||||
privateGuild = group;
|
privateGuild = group;
|
||||||
leader = groupLeader;
|
leader = groupLeader;
|
||||||
invitedUser = invitees[0];
|
invitedUser = invitees[0];
|
||||||
|
|
||||||
|
await leader.post(`/groups/${group._id}/chat`, { message: 'Some message' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('removes a group when the last member leaves', async () => {
|
it('removes a group when the last member leaves', async () => {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
createAndPopulateGroup,
|
createAndPopulateGroup,
|
||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../helpers/api-v3-integration.helper';
|
} from '../../../../helpers/api-v3-integration.helper';
|
||||||
|
import * as email from '../../../../../website/server/libs/email';
|
||||||
|
|
||||||
describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
||||||
let leader;
|
let leader;
|
||||||
@@ -60,6 +61,14 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
context('Guilds', () => {
|
context('Guilds', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
sandbox.spy(email, 'sendTxn');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
it('can remove other members', async () => {
|
it('can remove other members', async () => {
|
||||||
await leader.post(`/groups/${guild._id}/removeMember/${member._id}`);
|
await leader.post(`/groups/${guild._id}/removeMember/${member._id}`);
|
||||||
let memberRemoved = await member.get('/user');
|
let memberRemoved = await member.get('/user');
|
||||||
@@ -80,6 +89,22 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
|||||||
|
|
||||||
expect(_.findIndex(invitedUserWithoutInvite.invitations.guilds, {id: guild._id})).eql(-1);
|
expect(_.findIndex(invitedUserWithoutInvite.invitations.guilds, {id: guild._id})).eql(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends email to user with rescinded invite', async () => {
|
||||||
|
await leader.post(`/groups/${guild._id}/removeMember/${invitedUser._id}`);
|
||||||
|
|
||||||
|
expect(email.sendTxn).to.be.calledOnce;
|
||||||
|
expect(email.sendTxn.args[0][0]._id).to.be.eql(invitedUser._id);
|
||||||
|
expect(email.sendTxn.args[0][1]).to.be.eql('guild-invite-rescinded');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends email to removed user', async () => {
|
||||||
|
await leader.post(`/groups/${guild._id}/removeMember/${member._id}`);
|
||||||
|
|
||||||
|
expect(email.sendTxn).to.be.calledOnce;
|
||||||
|
expect(email.sendTxn.args[0][0]._id).to.be.eql(member._id);
|
||||||
|
expect(email.sendTxn.args[0][1]).to.be.eql('kicked-from-guild');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
context('Party', () => {
|
context('Party', () => {
|
||||||
@@ -87,6 +112,7 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
|||||||
let partyLeader;
|
let partyLeader;
|
||||||
let partyInvitedUser;
|
let partyInvitedUser;
|
||||||
let partyMember;
|
let partyMember;
|
||||||
|
let removedMember;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
let { group, groupLeader, invitees, members } = await createAndPopulateGroup({
|
let { group, groupLeader, invitees, members } = await createAndPopulateGroup({
|
||||||
@@ -96,13 +122,19 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
|||||||
privacy: 'private',
|
privacy: 'private',
|
||||||
},
|
},
|
||||||
invites: 1,
|
invites: 1,
|
||||||
members: 1,
|
members: 2,
|
||||||
});
|
});
|
||||||
|
|
||||||
party = group;
|
party = group;
|
||||||
partyLeader = groupLeader;
|
partyLeader = groupLeader;
|
||||||
partyInvitedUser = invitees[0];
|
partyInvitedUser = invitees[0];
|
||||||
partyMember = members[0];
|
partyMember = members[0];
|
||||||
|
removedMember = members[1];
|
||||||
|
sandbox.spy(email, 'sendTxn');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sandbox.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can remove other members', async () => {
|
it('can remove other members', async () => {
|
||||||
@@ -129,6 +161,18 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
|||||||
expect(invitedUserWithoutInvite.invitations.party).to.be.empty;
|
expect(invitedUserWithoutInvite.invitations.party).to.be.empty;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('removes new messages from a member who is removed', async () => {
|
||||||
|
await partyLeader.post(`/groups/${party._id}/chat`, { message: 'Some message' });
|
||||||
|
await removedMember.sync();
|
||||||
|
|
||||||
|
expect(removedMember.newMessages[party._id]).to.not.be.empty;
|
||||||
|
|
||||||
|
await partyLeader.post(`/groups/${party._id}/removeMember/${removedMember._id}`);
|
||||||
|
await removedMember.sync();
|
||||||
|
|
||||||
|
expect(removedMember.newMessages[party._id]).to.be.empty;
|
||||||
|
});
|
||||||
|
|
||||||
it('removes user from quest when removing user from party after quest starts', async () => {
|
it('removes user from quest when removing user from party after quest starts', async () => {
|
||||||
let petQuest = 'whale';
|
let petQuest = 'whale';
|
||||||
await partyLeader.update({
|
await partyLeader.update({
|
||||||
@@ -173,5 +217,21 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
|
|||||||
expect(party.quest.members[partyLeader._id]).to.be.true;
|
expect(party.quest.members[partyLeader._id]).to.be.true;
|
||||||
expect(party.quest.members[partyMember._id]).to.not.exist;
|
expect(party.quest.members[partyMember._id]).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends email to user with rescinded invite', async () => {
|
||||||
|
await partyLeader.post(`/groups/${party._id}/removeMember/${partyInvitedUser._id}`);
|
||||||
|
|
||||||
|
expect(email.sendTxn).to.be.calledOnce;
|
||||||
|
expect(email.sendTxn.args[0][0]._id).to.be.eql(partyInvitedUser._id);
|
||||||
|
expect(email.sendTxn.args[0][1]).to.be.eql('party-invite-rescinded');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends email to removed user', async () => {
|
||||||
|
await partyLeader.post(`/groups/${party._id}/removeMember/${partyMember._id}`);
|
||||||
|
|
||||||
|
expect(email.sendTxn).to.be.calledOnce;
|
||||||
|
expect(email.sendTxn.args[0][0]._id).to.be.eql(partyMember._id);
|
||||||
|
expect(email.sendTxn.args[0][1]).to.be.eql('kicked-from-party');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -300,6 +300,26 @@ describe('Post /groups/:groupId/invite', () => {
|
|||||||
message: t('userAlreadyInGroup'),
|
message: t('userAlreadyInGroup'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @TODO: Add this after we are able to mock the group plan route
|
||||||
|
xit('returns an error when a non-leader invites to a group plan', async () => {
|
||||||
|
let userToInvite = await generateUser();
|
||||||
|
|
||||||
|
let nonGroupLeader = await generateUser();
|
||||||
|
await inviter.post(`/groups/${group._id}/invite`, {
|
||||||
|
uuids: [nonGroupLeader._id],
|
||||||
|
});
|
||||||
|
await nonGroupLeader.post(`/groups/${group._id}/join`);
|
||||||
|
|
||||||
|
await expect(nonGroupLeader.post(`/groups/${group._id}/invite`, {
|
||||||
|
uuids: [userToInvite._id],
|
||||||
|
}))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('onlyGroupLeaderCanInviteToGroupPlan'),
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('party invites', () => {
|
describe('party invites', () => {
|
||||||
|
|||||||
@@ -40,13 +40,14 @@ describe('PUT /heroes/:heroId', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('updates contributor level, balance, ads, blocked', async () => {
|
it('change contributor level, balance, ads', async () => {
|
||||||
let hero = await generateUser();
|
let hero = await generateUser();
|
||||||
|
let prevBlockState = hero.auth.blocked;
|
||||||
|
let prevSleepState = hero.preferences.sleep;
|
||||||
let heroRes = await user.put(`/hall/heroes/${hero._id}`, {
|
let heroRes = await user.put(`/hall/heroes/${hero._id}`, {
|
||||||
balance: 3,
|
balance: 3,
|
||||||
contributor: {level: 1},
|
contributor: {level: 1},
|
||||||
purchased: {ads: true},
|
purchased: {ads: true},
|
||||||
auth: {blocked: true},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// test response
|
// test response
|
||||||
@@ -61,18 +62,47 @@ describe('PUT /heroes/:heroId', () => {
|
|||||||
expect(heroRes.balance).to.equal(3 + 0.75); // 3+0.75 for first contrib level
|
expect(heroRes.balance).to.equal(3 + 0.75); // 3+0.75 for first contrib level
|
||||||
expect(heroRes.contributor.level).to.equal(1);
|
expect(heroRes.contributor.level).to.equal(1);
|
||||||
expect(heroRes.purchased.ads).to.equal(true);
|
expect(heroRes.purchased.ads).to.equal(true);
|
||||||
expect(heroRes.auth.blocked).to.equal(true);
|
|
||||||
// test hero values
|
// test hero values
|
||||||
await hero.sync();
|
await hero.sync();
|
||||||
expect(hero.balance).to.equal(3 + 0.75); // 3+0.75 for first contrib level
|
expect(hero.balance).to.equal(3 + 0.75); // 3+0.75 for first contrib level
|
||||||
expect(hero.contributor.level).to.equal(1);
|
expect(hero.contributor.level).to.equal(1);
|
||||||
expect(hero.purchased.ads).to.equal(true);
|
expect(hero.purchased.ads).to.equal(true);
|
||||||
expect(hero.auth.blocked).to.equal(true);
|
expect(hero.auth.blocked).to.equal(prevBlockState);
|
||||||
expect(hero.preferences.sleep).to.equal(true);
|
expect(hero.preferences.sleep).to.equal(prevSleepState);
|
||||||
expect(hero.notifications.length).to.equal(1);
|
expect(hero.notifications.length).to.equal(1);
|
||||||
expect(hero.notifications[0].type).to.equal('NEW_CONTRIBUTOR_LEVEL');
|
expect(hero.notifications[0].type).to.equal('NEW_CONTRIBUTOR_LEVEL');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('block a user', async () => {
|
||||||
|
let hero = await generateUser();
|
||||||
|
let heroRes = await user.put(`/hall/heroes/${hero._id}`, {
|
||||||
|
auth: {blocked: true},
|
||||||
|
preferences: {sleep: true},
|
||||||
|
});
|
||||||
|
|
||||||
|
// test response values
|
||||||
|
expect(heroRes.auth.blocked).to.equal(true);
|
||||||
|
// test hero values
|
||||||
|
await hero.sync();
|
||||||
|
expect(hero.auth.blocked).to.equal(true);
|
||||||
|
expect(hero.preferences.sleep).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('unblock a user', async () => {
|
||||||
|
let hero = await generateUser();
|
||||||
|
let prevSleepState = hero.preferences.sleep;
|
||||||
|
let heroRes = await user.put(`/hall/heroes/${hero._id}`, {
|
||||||
|
auth: {blocked: false},
|
||||||
|
});
|
||||||
|
|
||||||
|
// test response values
|
||||||
|
expect(heroRes.auth.blocked).to.equal(false);
|
||||||
|
// test hero values
|
||||||
|
await hero.sync();
|
||||||
|
expect(hero.auth.blocked).to.equal(false);
|
||||||
|
expect(hero.preferences.sleep).to.equal(prevSleepState);
|
||||||
|
});
|
||||||
|
|
||||||
it('updates chatRevoked flag', async () => {
|
it('updates chatRevoked flag', async () => {
|
||||||
let hero = await generateUser();
|
let hero = await generateUser();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../helpers/api-v3-integration.helper';
|
||||||
|
import { v4 as generateUUID } from 'uuid';
|
||||||
|
|
||||||
|
describe('GET /members/:memberId/achievements', () => {
|
||||||
|
let user;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates req.params.memberId', async () => {
|
||||||
|
await expect(user.get('/members/invalidUUID/achievements')).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('invalidReqParams'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns achievements based on given user', async () => {
|
||||||
|
let member = await generateUser({
|
||||||
|
contributor: {level: 1},
|
||||||
|
backer: {tier: 3},
|
||||||
|
});
|
||||||
|
let achievementsRes = await user.get(`/members/${member._id}/achievements`);
|
||||||
|
|
||||||
|
expect(achievementsRes.special.achievements.contributor.earned).to.equal(true);
|
||||||
|
expect(achievementsRes.special.achievements.contributor.value).to.equal(1);
|
||||||
|
|
||||||
|
expect(achievementsRes.special.achievements.kickstarter.earned).to.equal(true);
|
||||||
|
expect(achievementsRes.special.achievements.kickstarter.value).to.equal(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles non-existing members', async () => {
|
||||||
|
let dummyId = generateUUID();
|
||||||
|
await expect(user.get(`/members/${dummyId}/achievements`)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: t('userWithIDNotFound', {userId: dummyId}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -35,8 +35,10 @@ describe('GET /members/:memberId', () => {
|
|||||||
'backer', 'contributor', 'auth', 'items', 'inbox',
|
'backer', 'contributor', 'auth', 'items', 'inbox',
|
||||||
]);
|
]);
|
||||||
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
expect(Object.keys(memberRes.auth)).to.eql(['timestamps']);
|
||||||
expect(Object.keys(memberRes.preferences).sort()).to.eql(['size', 'hair', 'skin', 'shirt',
|
expect(Object.keys(memberRes.preferences).sort()).to.eql([
|
||||||
'chair', 'costume', 'sleep', 'background'].sort());
|
'size', 'hair', 'skin', 'shirt',
|
||||||
|
'chair', 'costume', 'sleep', 'background',
|
||||||
|
].sort());
|
||||||
|
|
||||||
expect(memberRes.stats.maxMP).to.exist;
|
expect(memberRes.stats.maxMP).to.exist;
|
||||||
expect(memberRes.stats.maxHealth).to.equal(common.maxHealth);
|
expect(memberRes.stats.maxHealth).to.equal(common.maxHealth);
|
||||||
|
|||||||
@@ -4,6 +4,14 @@ import {
|
|||||||
} from '../../../../helpers/api-v3-integration.helper';
|
} from '../../../../helpers/api-v3-integration.helper';
|
||||||
import { v4 as generateUUID } from 'uuid';
|
import { v4 as generateUUID } from 'uuid';
|
||||||
|
|
||||||
|
function findMessage (messages, receiverId) {
|
||||||
|
let message = _.find(messages, (inboxMessage) => {
|
||||||
|
return inboxMessage.uuid === receiverId;
|
||||||
|
});
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
describe('POST /members/transfer-gems', () => {
|
describe('POST /members/transfer-gems', () => {
|
||||||
let userToSendMessage;
|
let userToSendMessage;
|
||||||
let receiver;
|
let receiver;
|
||||||
@@ -116,19 +124,14 @@ describe('POST /members/transfer-gems', () => {
|
|||||||
let updatedReceiver = await receiver.get('/user');
|
let updatedReceiver = await receiver.get('/user');
|
||||||
let updatedSender = await userToSendMessage.get('/user');
|
let updatedSender = await userToSendMessage.get('/user');
|
||||||
|
|
||||||
let sendersMessageInReceiversInbox = _.find(updatedReceiver.inbox.messages, (inboxMessage) => {
|
let sendersMessageInReceiversInbox = findMessage(updatedReceiver.inbox.messages, userToSendMessage._id);
|
||||||
return inboxMessage.uuid === userToSendMessage._id;
|
let sendersMessageInSendersInbox = findMessage(updatedSender.inbox.messages, receiver._id);
|
||||||
});
|
|
||||||
|
|
||||||
let sendersMessageInSendersInbox = _.find(updatedSender.inbox.messages, (inboxMessage) => {
|
let messageSentContent = t('privateMessageGiftGemsMessage', {
|
||||||
return inboxMessage.uuid === receiver._id;
|
|
||||||
});
|
|
||||||
|
|
||||||
let messageSentContent = t('privateMessageGiftIntro', {
|
|
||||||
receiverName: receiver.profile.name,
|
receiverName: receiver.profile.name,
|
||||||
senderName: userToSendMessage.profile.name,
|
senderName: userToSendMessage.profile.name,
|
||||||
|
gemAmount,
|
||||||
});
|
});
|
||||||
messageSentContent += t('privateMessageGiftGemsMessage', {gemAmount});
|
|
||||||
messageSentContent = `\`${messageSentContent}\` `;
|
messageSentContent = `\`${messageSentContent}\` `;
|
||||||
messageSentContent += message;
|
messageSentContent += message;
|
||||||
|
|
||||||
@@ -150,19 +153,14 @@ describe('POST /members/transfer-gems', () => {
|
|||||||
let updatedReceiver = await receiver.get('/user');
|
let updatedReceiver = await receiver.get('/user');
|
||||||
let updatedSender = await userToSendMessage.get('/user');
|
let updatedSender = await userToSendMessage.get('/user');
|
||||||
|
|
||||||
let sendersMessageInReceiversInbox = _.find(updatedReceiver.inbox.messages, (inboxMessage) => {
|
let sendersMessageInReceiversInbox = findMessage(updatedReceiver.inbox.messages, userToSendMessage._id);
|
||||||
return inboxMessage.uuid === userToSendMessage._id;
|
let sendersMessageInSendersInbox = findMessage(updatedSender.inbox.messages, receiver._id);
|
||||||
});
|
|
||||||
|
|
||||||
let sendersMessageInSendersInbox = _.find(updatedSender.inbox.messages, (inboxMessage) => {
|
let messageSentContent = t('privateMessageGiftGemsMessage', {
|
||||||
return inboxMessage.uuid === receiver._id;
|
|
||||||
});
|
|
||||||
|
|
||||||
let messageSentContent = t('privateMessageGiftIntro', {
|
|
||||||
receiverName: receiver.profile.name,
|
receiverName: receiver.profile.name,
|
||||||
senderName: userToSendMessage.profile.name,
|
senderName: userToSendMessage.profile.name,
|
||||||
|
gemAmount,
|
||||||
});
|
});
|
||||||
messageSentContent += t('privateMessageGiftGemsMessage', {gemAmount});
|
|
||||||
messageSentContent = `\`${messageSentContent}\` `;
|
messageSentContent = `\`${messageSentContent}\` `;
|
||||||
|
|
||||||
expect(sendersMessageInReceiversInbox).to.exist;
|
expect(sendersMessageInReceiversInbox).to.exist;
|
||||||
@@ -173,4 +171,40 @@ describe('POST /members/transfer-gems', () => {
|
|||||||
expect(sendersMessageInSendersInbox.text).to.equal(messageSentContent);
|
expect(sendersMessageInSendersInbox.text).to.equal(messageSentContent);
|
||||||
expect(updatedSender.balance).to.equal(0);
|
expect(updatedSender.balance).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sends transfer gems message in each participant\'s language', async () => {
|
||||||
|
await receiver.update({
|
||||||
|
'preferences.language': 'es',
|
||||||
|
});
|
||||||
|
await userToSendMessage.update({
|
||||||
|
'preferences.language': 'cs',
|
||||||
|
});
|
||||||
|
await userToSendMessage.post('/members/transfer-gems', {
|
||||||
|
gemAmount,
|
||||||
|
toUserId: receiver._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
let updatedReceiver = await receiver.get('/user');
|
||||||
|
let updatedSender = await userToSendMessage.get('/user');
|
||||||
|
|
||||||
|
let sendersMessageInReceiversInbox = findMessage(updatedReceiver.inbox.messages, userToSendMessage._id);
|
||||||
|
let sendersMessageInSendersInbox = findMessage(updatedSender.inbox.messages, receiver._id);
|
||||||
|
|
||||||
|
let [receieversMessageContent, sendersMessageContent] = ['es', 'cs'].map((lang) => {
|
||||||
|
let messageContent = t('privateMessageGiftGemsMessage', {
|
||||||
|
receiverName: receiver.profile.name,
|
||||||
|
senderName: userToSendMessage.profile.name,
|
||||||
|
gemAmount,
|
||||||
|
}, lang);
|
||||||
|
|
||||||
|
return `\`${messageContent}\` `;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(sendersMessageInReceiversInbox).to.exist;
|
||||||
|
expect(sendersMessageInReceiversInbox.text).to.equal(receieversMessageContent);
|
||||||
|
|
||||||
|
expect(sendersMessageInSendersInbox).to.exist;
|
||||||
|
expect(sendersMessageInSendersInbox.text).to.equal(sendersMessageContent);
|
||||||
|
expect(updatedSender.balance).to.equal(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ describe('GET /models/:model/paths', () => {
|
|||||||
user = await generateUser();
|
user = await generateUser();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an error when model is not accessible or doesn\'t exists', async () => {
|
it('returns an error when model is not accessible or doesn\'t exist', async () => {
|
||||||
await expect(user.get('/models/1234/paths')).to.eventually.be.rejected.and.eql({
|
await expect(user.get('/models/1234/paths')).to.eventually.be.rejected.and.eql({
|
||||||
code: 400,
|
code: 400,
|
||||||
error: 'BadRequest',
|
error: 'BadRequest',
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../helpers/api-v3-integration.helper';
|
||||||
|
import { v4 as generateUUID } from 'uuid';
|
||||||
|
|
||||||
|
describe('POST /notifications/:notificationId/read', () => {
|
||||||
|
let user;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when notification is not found', async () => {
|
||||||
|
let dummyId = generateUUID();
|
||||||
|
await expect(user.post(`/notifications/${dummyId}/read`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: t('messageNotificationNotFound'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('removes a notification', async () => {
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments : amazon #subscribeCancel', () => {
|
|
||||||
let endpoint = '/amazon/subscribe/cancel';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies subscription', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
xdescribe('payments : paypal #checkout', () => {
|
|
||||||
let endpoint = '/paypal/checkout';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies subscription', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
xdescribe('payments : paypal #checkoutSuccess', () => {
|
|
||||||
let endpoint = '/paypal/checkout/success';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies subscription', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
xdescribe('payments : paypal #subscribe', () => {
|
|
||||||
let endpoint = '/paypal/subscribe';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments : paypal #subscribeCancel', () => {
|
|
||||||
let endpoint = '/paypal/subscribe/cancel';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
xdescribe('payments : paypal #subscribeSuccess', () => {
|
|
||||||
let endpoint = '/paypal/subscribe/success';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - stripe - #subscribeCancel', () => {
|
|
||||||
let endpoint = '/stripe/subscribe/cancel';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - amazon - #checkout', () => {
|
|
||||||
let endpoint = '/amazon/checkout';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 400,
|
|
||||||
error: 'BadRequest',
|
|
||||||
message: 'Missing req.body.orderReferenceId',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - amazon - #createOrderReferenceId', () => {
|
|
||||||
let endpoint = '/amazon/createOrderReferenceId';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies billingAgreementId', async (done) => {
|
|
||||||
try {
|
|
||||||
await user.post(endpoint);
|
|
||||||
} catch (e) {
|
|
||||||
// Parameter AWSAccessKeyId cannot be empty.
|
|
||||||
expect(e.error).to.eql('BadRequest');
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - amazon - #subscribe', () => {
|
|
||||||
let endpoint = '/amazon/subscribe';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies subscription code', async () => {
|
|
||||||
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 400,
|
|
||||||
error: 'BadRequest',
|
|
||||||
message: t('missingSubscriptionCode'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - paypal - #ipn', () => {
|
|
||||||
let endpoint = '/paypal/ipn';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
let result = await user.post(endpoint);
|
|
||||||
expect(result).to.eql('OK');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - stripe - #checkout', () => {
|
|
||||||
let endpoint = '/stripe/checkout';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.post(endpoint, {id: 123})).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'Error',
|
|
||||||
message: 'Invalid API Key provided: ****************************1111',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
generateUser,
|
|
||||||
translate as t,
|
|
||||||
} from '../../../../helpers/api-integration/v3';
|
|
||||||
|
|
||||||
describe('payments - stripe - #subscribeEdit', () => {
|
|
||||||
let endpoint = '/stripe/subscribe/edit';
|
|
||||||
let user;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await generateUser();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('verifies credentials', async () => {
|
|
||||||
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
|
||||||
code: 401,
|
|
||||||
error: 'NotAuthorized',
|
|
||||||
message: t('missingSubscription'),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
generateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import amzLib from '../../../../../../website/server/libs/amazonPayments';
|
||||||
|
|
||||||
|
describe('payments : amazon #subscribeCancel', () => {
|
||||||
|
let endpoint = '/amazon/subscribe/cancel?noRedirect=true';
|
||||||
|
let user, group, amazonSubscribeCancelStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws error when there users has no subscription', async () => {
|
||||||
|
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('missingSubscription'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
amazonSubscribeCancelStub = sinon.stub(amzLib, 'cancelSubscription').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
amzLib.cancelSubscription.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a user subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(endpoint);
|
||||||
|
|
||||||
|
expect(amazonSubscribeCancelStub).to.be.calledOnce;
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].groupId).to.eql(undefined);
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a group subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
group = await generateGroup(user, {
|
||||||
|
name: 'test group',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'public',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}&groupId=${group._id}`);
|
||||||
|
|
||||||
|
expect(amazonSubscribeCancelStub).to.be.calledOnce;
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].groupId).to.eql(group._id);
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(amazonSubscribeCancelStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import amzLib from '../../../../../../website/server/libs/amazonPayments';
|
||||||
|
|
||||||
|
describe('payments - amazon - #checkout', () => {
|
||||||
|
let endpoint = '/amazon/checkout';
|
||||||
|
let user, amazonCheckoutStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies credentials', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: 'Missing req.body.orderReferenceId',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
amazonCheckoutStub = sinon.stub(amzLib, 'checkout').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
amzLib.checkout.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purcahse with amazon checkout', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
let gift = {
|
||||||
|
type: 'gems',
|
||||||
|
gems: {
|
||||||
|
amount: 16,
|
||||||
|
uuid: user._id,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let orderReferenceId = 'orderReferenceId-example';
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
gift,
|
||||||
|
orderReferenceId,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(amazonCheckoutStub).to.be.calledOnce;
|
||||||
|
expect(amazonCheckoutStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(amazonCheckoutStub.args[0][0].gift).to.eql(gift);
|
||||||
|
expect(amazonCheckoutStub.args[0][0].orderReferenceId).to.eql(orderReferenceId);
|
||||||
|
expect(amazonCheckoutStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(amazonCheckoutStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
|
||||||
|
describe('payments - amazon - #createOrderReferenceId', () => {
|
||||||
|
let endpoint = '/amazon/createOrderReferenceId';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies billingAgreementId', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: 'Missing req.body.billingAgreementId',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
generateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import amzLib from '../../../../../../website/server/libs/amazonPayments';
|
||||||
|
|
||||||
|
describe('payments - amazon - #subscribe', () => {
|
||||||
|
let endpoint = '/amazon/subscribe';
|
||||||
|
let user, group, subscribeWithAmazonStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies subscription code', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingSubscriptionCode'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let billingAgreementId = 'billingAgreementId-example';
|
||||||
|
let subscription = 'basic_3mo';
|
||||||
|
let coupon;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
subscribeWithAmazonStub = sinon.stub(amzLib, 'subscribe').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
amzLib.subscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a user subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
billingAgreementId,
|
||||||
|
subscription,
|
||||||
|
coupon,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeWithAmazonStub).to.be.calledOnce;
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].billingAgreementId).to.eql(billingAgreementId);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].sub).to.exist;
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].coupon).to.eql(coupon);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].groupId).not.exist;
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a group subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
group = await generateGroup(user, {
|
||||||
|
name: 'test group',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'public',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
billingAgreementId,
|
||||||
|
subscription,
|
||||||
|
coupon,
|
||||||
|
groupId: group._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeWithAmazonStub).to.be.calledOnce;
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].billingAgreementId).to.eql(billingAgreementId);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].sub).to.exist;
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].coupon).to.eql(coupon);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].groupId).to.eql(group._id);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].headers['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeWithAmazonStub.args[0][0].headers['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
generateUser,
|
generateUser,
|
||||||
} from '../../../../helpers/api-integration/v3';
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
|
||||||
describe('payments : amazon', () => {
|
describe('payments : amazon', () => {
|
||||||
let endpoint = '/amazon/verifyAccessToken';
|
let endpoint = '/amazon/verifyAccessToken';
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import {generateUser} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import applePayments from '../../../../../../website/server/libs/applePayments';
|
||||||
|
|
||||||
|
describe('payments : apple #cancelSubscribe', () => {
|
||||||
|
let endpoint = '/iap/ios/subscribe/cancel?noRedirect=true';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let cancelStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
cancelStub = sinon.stub(applePayments, 'cancelSubscribe').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
applePayments.cancelSubscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels the subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.paymentMethod': 'Apple',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(endpoint);
|
||||||
|
|
||||||
|
expect(cancelStub).to.be.calledOnce;
|
||||||
|
expect(cancelStub.args[0][0]._id).to.eql(user._id);
|
||||||
|
expect(cancelStub.args[0][1]['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(cancelStub.args[0][1]['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import {generateUser} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import applePayments from '../../../../../../website/server/libs/applePayments';
|
||||||
|
|
||||||
|
describe('payments : apple #verify', () => {
|
||||||
|
let endpoint = '/iap/ios/verify';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let verifyStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
verifyStub = sinon.stub(applePayments, 'verifyGemPurchase').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
applePayments.verifyGemPurchase.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
transaction: {
|
||||||
|
receipt: 'receipt',
|
||||||
|
}});
|
||||||
|
|
||||||
|
expect(verifyStub).to.be.calledOnce;
|
||||||
|
expect(verifyStub.args[0][0]._id).to.eql(user._id);
|
||||||
|
expect(verifyStub.args[0][1]).to.eql('receipt');
|
||||||
|
expect(verifyStub.args[0][2]['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(verifyStub.args[0][2]['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import {generateUser, translate as t} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import applePayments from '../../../../../../website/server/libs/applePayments';
|
||||||
|
|
||||||
|
describe('payments : apple #subscribe', () => {
|
||||||
|
let endpoint = '/iap/ios/subscribe';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies sub key', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingSubscriptionCode'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let subscribeStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeStub = sinon.stub(applePayments, 'subscribe').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
applePayments.subscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
let sku = 'com.habitrpg.ios.habitica.subscription.3month';
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
receipt: 'receipt',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeStub).to.be.calledOnce;
|
||||||
|
expect(subscribeStub.args[0][0]).to.eql(sku);
|
||||||
|
expect(subscribeStub.args[0][1]._id).to.eql(user._id);
|
||||||
|
expect(subscribeStub.args[0][2]).to.eql('receipt');
|
||||||
|
expect(subscribeStub.args[0][3]['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeStub.args[0][3]['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import {generateUser} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import googlePayments from '../../../../../../website/server/libs/googlePayments';
|
||||||
|
|
||||||
|
describe('payments : google #cancelSubscribe', () => {
|
||||||
|
let endpoint = '/iap/android/subscribe/cancel?noRedirect=true';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let cancelStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
cancelStub = sinon.stub(googlePayments, 'cancelSubscribe').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
googlePayments.cancelSubscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.paymentMethod': 'Google',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(endpoint);
|
||||||
|
|
||||||
|
expect(cancelStub).to.be.calledOnce;
|
||||||
|
expect(cancelStub.args[0][0]._id).to.eql(user._id);
|
||||||
|
expect(cancelStub.args[0][1]['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(cancelStub.args[0][1]['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import {generateUser, translate as t} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import googlePayments from '../../../../../../website/server/libs/googlePayments';
|
||||||
|
|
||||||
|
describe('payments : google #subscribe', () => {
|
||||||
|
let endpoint = '/iap/android/subscribe';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies sub key', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingSubscriptionCode'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let subscribeStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeStub = sinon.stub(googlePayments, 'subscribe').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
googlePayments.subscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
let sku = 'com.habitrpg.android.habitica.subscription.3month';
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
sku,
|
||||||
|
transaction: {receipt: 'receipt', signature: 'signature'},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(subscribeStub).to.be.calledOnce;
|
||||||
|
expect(subscribeStub.args[0][0]).to.eql(sku);
|
||||||
|
expect(subscribeStub.args[0][1]._id).to.eql(user._id);
|
||||||
|
expect(subscribeStub.args[0][2]).to.eql('receipt');
|
||||||
|
expect(subscribeStub.args[0][3]).to.eql('signature');
|
||||||
|
expect(subscribeStub.args[0][4]['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(subscribeStub.args[0][4]['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import {generateUser} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import googlePayments from '../../../../../../website/server/libs/googlePayments';
|
||||||
|
|
||||||
|
describe('payments : google #verify', () => {
|
||||||
|
let endpoint = '/iap/android/verify';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let verifyStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
verifyStub = sinon.stub(googlePayments, 'verifyGemPurchase').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
googlePayments.verifyGemPurchase.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
transaction: {receipt: 'receipt', signature: 'signature'},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(verifyStub).to.be.calledOnce;
|
||||||
|
expect(verifyStub.args[0][0]._id).to.eql(user._id);
|
||||||
|
expect(verifyStub.args[0][1]).to.eql('receipt');
|
||||||
|
expect(verifyStub.args[0][2]).to.eql('signature');
|
||||||
|
expect(verifyStub.args[0][3]['x-api-key']).to.eql(user.apiToken);
|
||||||
|
expect(verifyStub.args[0][3]['x-api-user']).to.eql(user._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import paypalPayments from '../../../../../../website/server/libs/paypalPayments';
|
||||||
|
|
||||||
|
describe('payments : paypal #checkout', () => {
|
||||||
|
let endpoint = '/paypal/checkout';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let checkoutStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
checkoutStub = sinon.stub(paypalPayments, 'checkout').returnsPromise().resolves('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
paypalPayments.checkout.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a purchase link', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}?noRedirect=true`);
|
||||||
|
|
||||||
|
expect(checkoutStub).to.be.calledOnce;
|
||||||
|
expect(checkoutStub.args[0][0].gift).to.eql(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import paypalPayments from '../../../../../../website/server/libs/paypalPayments';
|
||||||
|
|
||||||
|
describe('payments : paypal #checkoutSuccess', () => {
|
||||||
|
let endpoint = '/paypal/checkout/success';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies paymentId', async () => {
|
||||||
|
await expect(user.get(endpoint))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingPaymentId'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies customerId', async () => {
|
||||||
|
await expect(user.get(`${endpoint}?paymentId=test-paymentid`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingCustomerId'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let checkoutSuccessStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
checkoutSuccessStub = sinon.stub(paypalPayments, 'checkoutSuccess').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
paypalPayments.checkoutSuccess.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
let paymentId = 'test-paymentid';
|
||||||
|
let customerId = 'test-customerId';
|
||||||
|
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}?PayerID=${customerId}&paymentId=${paymentId}&noRedirect=true`);
|
||||||
|
|
||||||
|
expect(checkoutSuccessStub).to.be.calledOnce;
|
||||||
|
|
||||||
|
expect(checkoutSuccessStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(checkoutSuccessStub.args[0][0].gift).to.eql(undefined);
|
||||||
|
expect(checkoutSuccessStub.args[0][0].paymentId).to.eql(paymentId);
|
||||||
|
expect(checkoutSuccessStub.args[0][0].customerId).to.eql(customerId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import paypalPayments from '../../../../../../website/server/libs/paypalPayments';
|
||||||
|
import shared from '../../../../../../website/common';
|
||||||
|
|
||||||
|
describe('payments : paypal #subscribe', () => {
|
||||||
|
let endpoint = '/paypal/subscribe';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies sub key', async () => {
|
||||||
|
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingSubKey'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let subscribeStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeStub = sinon.stub(paypalPayments, 'subscribe').returnsPromise().resolves('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
paypalPayments.subscribe.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
let subKey = 'basic_3mo';
|
||||||
|
let sub = shared.content.subscriptionBlocks[subKey];
|
||||||
|
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}?sub=${subKey}&noRedirect=true`);
|
||||||
|
|
||||||
|
expect(subscribeStub).to.be.calledOnce;
|
||||||
|
|
||||||
|
expect(subscribeStub.args[0][0].sub).to.eql(sub);
|
||||||
|
expect(subscribeStub.args[0][0].coupon).to.eql(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import paypalPayments from '../../../../../../website/server/libs/paypalPayments';
|
||||||
|
|
||||||
|
describe('payments : paypal #subscribeCancel', () => {
|
||||||
|
let endpoint = '/paypal/subscribe/cancel';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies credentials', async () => {
|
||||||
|
await expect(user.get(endpoint))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('missingSubscription'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let subscribeCancelStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeCancelStub = sinon.stub(paypalPayments, 'subscribeCancel').returnsPromise().resolves('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
paypalPayments.subscribeCancel.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}?noRedirect=true`);
|
||||||
|
|
||||||
|
expect(subscribeCancelStub).to.be.calledOnce;
|
||||||
|
|
||||||
|
expect(subscribeCancelStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(subscribeCancelStub.args[0][0].groupId).to.eql(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import paypalPayments from '../../../../../../website/server/libs/paypalPayments';
|
||||||
|
|
||||||
|
describe('payments : paypal #subscribeSuccess', () => {
|
||||||
|
let endpoint = '/paypal/subscribe/success';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies Paypal Block', async () => {
|
||||||
|
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 400,
|
||||||
|
error: 'BadRequest',
|
||||||
|
message: t('missingPaypalBlock'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
xdescribe('success', () => {
|
||||||
|
let subscribeSuccessStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
subscribeSuccessStub = sinon.stub(paypalPayments, 'subscribeSuccess').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
paypalPayments.subscribeSuccess.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a subscription', async () => {
|
||||||
|
let token = 'test-token';
|
||||||
|
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}?token=${token}&noRedirect=true`);
|
||||||
|
|
||||||
|
expect(subscribeSuccessStub).to.be.calledOnce;
|
||||||
|
|
||||||
|
expect(subscribeSuccessStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(subscribeSuccessStub.args[0][0].block).to.eql(undefined);
|
||||||
|
expect(subscribeSuccessStub.args[0][0].groupId).to.eql(undefined);
|
||||||
|
expect(subscribeSuccessStub.args[0][0].token).to.eql(token);
|
||||||
|
expect(subscribeSuccessStub.args[0][0].headers).to.exist;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import paypalPayments from '../../../../../../website/server/libs/paypalPayments';
|
||||||
|
|
||||||
|
describe('payments - paypal - #ipn', () => {
|
||||||
|
let endpoint = '/paypal/ipn';
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies credentials', async () => {
|
||||||
|
let result = await user.post(endpoint);
|
||||||
|
expect(result).to.eql('OK');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let ipnStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
ipnStub = sinon.stub(paypalPayments, 'ipn').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
paypalPayments.ipn.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes a purchase', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint);
|
||||||
|
|
||||||
|
expect(ipnStub).to.be.calledOnce;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
generateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import stripePayments from '../../../../../../website/server/libs/stripePayments';
|
||||||
|
|
||||||
|
describe('payments - stripe - #subscribeCancel', () => {
|
||||||
|
let endpoint = '/stripe/subscribe/cancel?redirect=none';
|
||||||
|
let user, group, stripeCancelSubscriptionStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies credentials', async () => {
|
||||||
|
await expect(user.get(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('missingSubscription'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
stripeCancelSubscriptionStub = sinon.stub(stripePayments, 'cancelSubscription').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
stripePayments.cancelSubscription.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a user subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}`);
|
||||||
|
|
||||||
|
expect(stripeCancelSubscriptionStub).to.be.calledOnce;
|
||||||
|
expect(stripeCancelSubscriptionStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(stripeCancelSubscriptionStub.args[0][0].groupId).to.eql(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a group subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
group = await generateGroup(user, {
|
||||||
|
name: 'test group',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'public',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.get(`${endpoint}&groupId=${group._id}`);
|
||||||
|
|
||||||
|
expect(stripeCancelSubscriptionStub).to.be.calledOnce;
|
||||||
|
expect(stripeCancelSubscriptionStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(stripeCancelSubscriptionStub.args[0][0].groupId).to.eql(group._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
generateGroup,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import stripePayments from '../../../../../../website/server/libs/stripePayments';
|
||||||
|
|
||||||
|
describe('payments - stripe - #checkout', () => {
|
||||||
|
let endpoint = '/stripe/checkout';
|
||||||
|
let user, group;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies credentials', async () => {
|
||||||
|
await expect(user.post(endpoint, {id: 123})).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'Error',
|
||||||
|
message: 'Invalid API Key provided: ****************************1111',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let stripeCheckoutSubscriptionStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
stripeCheckoutSubscriptionStub = sinon.stub(stripePayments, 'checkout').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
stripePayments.checkout.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a user subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint);
|
||||||
|
|
||||||
|
expect(stripeCheckoutSubscriptionStub).to.be.calledOnce;
|
||||||
|
expect(stripeCheckoutSubscriptionStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(stripeCheckoutSubscriptionStub.args[0][0].groupId).to.eql(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a group subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
group = await generateGroup(user, {
|
||||||
|
name: 'test group',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'public',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(`${endpoint}?groupId=${group._id}`);
|
||||||
|
|
||||||
|
expect(stripeCheckoutSubscriptionStub).to.be.calledOnce;
|
||||||
|
expect(stripeCheckoutSubscriptionStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(stripeCheckoutSubscriptionStub.args[0][0].groupId).to.eql(group._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
generateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import stripePayments from '../../../../../../website/server/libs/stripePayments';
|
||||||
|
|
||||||
|
describe('payments - stripe - #subscribeEdit', () => {
|
||||||
|
let endpoint = '/stripe/subscribe/edit';
|
||||||
|
let user, group;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
user = await generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies credentials', async () => {
|
||||||
|
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('missingSubscription'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
let stripeEditSubscriptionStub;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
stripeEditSubscriptionStub = sinon.stub(stripePayments, 'editSubscription').returnsPromise().resolves({});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
stripePayments.editSubscription.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a user subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint);
|
||||||
|
|
||||||
|
expect(stripeEditSubscriptionStub).to.be.calledOnce;
|
||||||
|
expect(stripeEditSubscriptionStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(stripeEditSubscriptionStub.args[0][0].groupId).to.eql(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cancels a group subscription', async () => {
|
||||||
|
user = await generateUser({
|
||||||
|
'profile.name': 'sender',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
balance: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
group = await generateGroup(user, {
|
||||||
|
name: 'test group',
|
||||||
|
type: 'guild',
|
||||||
|
privacy: 'public',
|
||||||
|
'purchased.plan.customerId': 'customer-id',
|
||||||
|
'purchased.plan.planId': 'basic_3mo',
|
||||||
|
'purchased.plan.lastBillingDate': new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(endpoint, {
|
||||||
|
groupId: group._id,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(stripeEditSubscriptionStub).to.be.calledOnce;
|
||||||
|
expect(stripeEditSubscriptionStub.args[0][0].user._id).to.eql(user._id);
|
||||||
|
expect(stripeEditSubscriptionStub.args[0][0].groupId).to.eql(group._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -148,5 +148,20 @@ describe('POST /groups/:groupId/quests/accept', () => {
|
|||||||
expect(rejectingMember.party.quest.key).to.not.exist;
|
expect(rejectingMember.party.quest.key).to.not.exist;
|
||||||
expect(rejectingMember.party.quest.completed).to.not.exist;
|
expect(rejectingMember.party.quest.completed).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('begins the quest if accepting the last pending invite and verifies chat', async () => {
|
||||||
|
await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`);
|
||||||
|
await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`);
|
||||||
|
// quest will start after everyone has accepted
|
||||||
|
await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`);
|
||||||
|
|
||||||
|
await questingGroup.sync();
|
||||||
|
expect(questingGroup.chat[0].text).to.exist;
|
||||||
|
expect(questingGroup.chat[0]._meta).to.exist;
|
||||||
|
expect(questingGroup.chat[0]._meta).to.have.all.keys(['participatingMembers']);
|
||||||
|
|
||||||
|
let returnedGroup = await leader.get(`/groups/${questingGroup._id}`);
|
||||||
|
expect(returnedGroup.chat[0]._meta).to.be.undefined;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -231,5 +231,22 @@ describe('POST /groups/:groupId/quests/force-start', () => {
|
|||||||
expect(questingGroup.quest.members[partyMembers[0]._id]).to.exist;
|
expect(questingGroup.quest.members[partyMembers[0]._id]).to.exist;
|
||||||
expect(questingGroup.quest.members[leader._id]).to.exist;
|
expect(questingGroup.quest.members[leader._id]).to.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('allows group leader to force start quest and verifies chat', async () => {
|
||||||
|
let questLeader = partyMembers[0];
|
||||||
|
await questLeader.update({[`items.quests.${PET_QUEST}`]: 1});
|
||||||
|
await questLeader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`);
|
||||||
|
|
||||||
|
await leader.post(`/groups/${questingGroup._id}/quests/force-start`);
|
||||||
|
|
||||||
|
await questingGroup.sync();
|
||||||
|
|
||||||
|
expect(questingGroup.chat[0].text).to.exist;
|
||||||
|
expect(questingGroup.chat[0]._meta).to.exist;
|
||||||
|
expect(questingGroup.chat[0]._meta).to.have.all.keys(['participatingMembers']);
|
||||||
|
|
||||||
|
let returnedGroup = await leader.get(`/groups/${questingGroup._id}`);
|
||||||
|
expect(returnedGroup.chat[0]._meta).to.be.undefined;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -188,5 +188,25 @@ describe('POST /groups/:groupId/quests/invite/:questKey', () => {
|
|||||||
|
|
||||||
expect(group.quest.active).to.eql(true);
|
expect(group.quest.active).to.eql(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('starts quest automatically if user is in a solo party and verifies chat', async () => {
|
||||||
|
let leaderDetails = { balance: 10 };
|
||||||
|
leaderDetails[`items.quests.${PET_QUEST}`] = 1;
|
||||||
|
let { group, groupLeader } = await createAndPopulateGroup({
|
||||||
|
groupDetails: { type: 'party', privacy: 'private' },
|
||||||
|
leaderDetails,
|
||||||
|
});
|
||||||
|
|
||||||
|
await groupLeader.post(`/groups/${group._id}/quests/invite/${PET_QUEST}`);
|
||||||
|
|
||||||
|
await group.sync();
|
||||||
|
|
||||||
|
expect(group.chat[0].text).to.exist;
|
||||||
|
expect(group.chat[0]._meta).to.exist;
|
||||||
|
expect(group.chat[0]._meta).to.have.all.keys(['participatingMembers']);
|
||||||
|
|
||||||
|
let returnedGroup = await groupLeader.get(`/groups/${group._id}`);
|
||||||
|
expect(returnedGroup.chat[0]._meta).to.be.undefined;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
generateUser,
|
generateUser,
|
||||||
} from '../../../../helpers/api-v3-integration.helper';
|
} from '../../../../helpers/api-v3-integration.helper';
|
||||||
import { v4 as generateUUID } from 'uuid';
|
import { v4 as generateUUID } from 'uuid';
|
||||||
|
import { model as Group } from '../../../../../website/server/models/group';
|
||||||
|
|
||||||
describe('POST /groups/:groupId/quests/abort', () => {
|
describe('POST /groups/:groupId/quests/abort', () => {
|
||||||
let questingGroup;
|
let questingGroup;
|
||||||
@@ -89,6 +90,8 @@ describe('POST /groups/:groupId/quests/abort', () => {
|
|||||||
await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`);
|
await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`);
|
||||||
await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`);
|
await partyMembers[1].post(`/groups/${questingGroup._id}/quests/accept`);
|
||||||
|
|
||||||
|
let stub = sandbox.stub(Group.prototype, 'sendChat');
|
||||||
|
|
||||||
let res = await leader.post(`/groups/${questingGroup._id}/quests/abort`);
|
let res = await leader.post(`/groups/${questingGroup._id}/quests/abort`);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
leader.sync(),
|
leader.sync(),
|
||||||
@@ -123,5 +126,9 @@ describe('POST /groups/:groupId/quests/abort', () => {
|
|||||||
},
|
},
|
||||||
members: {},
|
members: {},
|
||||||
});
|
});
|
||||||
|
expect(Group.prototype.sendChat).to.be.calledOnce;
|
||||||
|
expect(Group.prototype.sendChat).to.be.calledWithMatch(/aborted the party quest Wail of the Whale.`/);
|
||||||
|
|
||||||
|
stub.restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -180,5 +180,19 @@ describe('POST /groups/:groupId/quests/reject', () => {
|
|||||||
expect(rejectingMember.party.quest.key).to.not.exist;
|
expect(rejectingMember.party.quest.key).to.not.exist;
|
||||||
expect(rejectingMember.party.quest.completed).to.not.exist;
|
expect(rejectingMember.party.quest.completed).to.not.exist;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('starts the quest when the last user reject and verifies chat', async () => {
|
||||||
|
await leader.post(`/groups/${questingGroup._id}/quests/invite/${PET_QUEST}`);
|
||||||
|
await partyMembers[0].post(`/groups/${questingGroup._id}/quests/accept`);
|
||||||
|
await partyMembers[1].post(`/groups/${questingGroup._id}/quests/reject`);
|
||||||
|
await questingGroup.sync();
|
||||||
|
|
||||||
|
expect(questingGroup.chat[0].text).to.exist;
|
||||||
|
expect(questingGroup.chat[0]._meta).to.exist;
|
||||||
|
expect(questingGroup.chat[0]._meta).to.have.all.keys(['participatingMembers']);
|
||||||
|
|
||||||
|
let returnedGroup = await leader.get(`/groups/${questingGroup._id}`);
|
||||||
|
expect(returnedGroup.chat[0]._meta).to.be.undefined;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ describe('GET /shops/seasonal', () => {
|
|||||||
|
|
||||||
expect(shop.identifier).to.equal('seasonalShop');
|
expect(shop.identifier).to.equal('seasonalShop');
|
||||||
expect(shop.text).to.eql(t('seasonalShop'));
|
expect(shop.text).to.eql(t('seasonalShop'));
|
||||||
expect(shop.notes).to.eql(t('seasonalShopFallText'));
|
expect(shop.notes).to.be.a('string');
|
||||||
expect(shop.imageName).to.be.a('string');
|
expect(shop.imageName).to.be.a('string');
|
||||||
expect(shop.categories).to.be.an('array');
|
expect(shop.categories).to.be.an('array');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ describe('GET /tasks/user', () => {
|
|||||||
for (let i = 0; i < numberOfTodos; i++) {
|
for (let i = 0; i < numberOfTodos; i++) {
|
||||||
let id = todos[i]._id;
|
let id = todos[i]._id;
|
||||||
|
|
||||||
await user.post(`/tasks/${id}/score/up`); // eslint-disable-line babel/no-await-in-loop
|
await user.post(`/tasks/${id}/score/up`); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
await user.sync();
|
await user.sync();
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
} from '../../../../helpers/api-integration/v3';
|
} from '../../../../helpers/api-integration/v3';
|
||||||
|
|
||||||
describe('POST /tasks/clearCompletedTodos', () => {
|
describe('POST /tasks/clearCompletedTodos', () => {
|
||||||
it('deletes all completed todos except the ones from a challenge', async () => {
|
it('deletes all completed todos except the ones from a challenge and group', async () => {
|
||||||
let user = await generateUser({balance: 1});
|
let user = await generateUser({balance: 1});
|
||||||
let guild = await generateGroup(user);
|
let guild = await generateGroup(user);
|
||||||
let challenge = await generateChallenge(user, guild);
|
let challenge = await generateChallenge(user, guild);
|
||||||
@@ -24,12 +24,18 @@ describe('POST /tasks/clearCompletedTodos', () => {
|
|||||||
type: 'todo',
|
type: 'todo',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let groupTask = await user.post(`/tasks/group/${guild._id}`, {
|
||||||
|
text: 'todo 7',
|
||||||
|
type: 'todo',
|
||||||
|
});
|
||||||
|
await user.post(`/tasks/${groupTask._id}/assign/${user._id}`);
|
||||||
|
|
||||||
let tasks = await user.get('/tasks/user?type=todos');
|
let tasks = await user.get('/tasks/user?type=todos');
|
||||||
expect(tasks.length).to.equal(initialTodoCount + 6);
|
expect(tasks.length).to.equal(initialTodoCount + 7);
|
||||||
|
|
||||||
for (let task of tasks) {
|
for (let task of tasks) {
|
||||||
if (['todo 2', 'todo 3', 'todo 6'].indexOf(task.text) !== -1) {
|
if (['todo 2', 'todo 3', 'todo 6'].indexOf(task.text) !== -1) {
|
||||||
await user.post(`/tasks/${task._id}/score/up`); // eslint-disable-line babel/no-await-in-loop
|
await user.post(`/tasks/${task._id}/score/up`); // eslint-disable-line no-await-in-loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +43,7 @@ describe('POST /tasks/clearCompletedTodos', () => {
|
|||||||
let completedTodos = await user.get('/tasks/user?type=completedTodos');
|
let completedTodos = await user.get('/tasks/user?type=completedTodos');
|
||||||
let todos = await user.get('/tasks/user?type=todos');
|
let todos = await user.get('/tasks/user?type=todos');
|
||||||
let allTodos = todos.concat(completedTodos);
|
let allTodos = todos.concat(completedTodos);
|
||||||
expect(allTodos.length).to.equal(initialTodoCount + 4); // + 6 - 3 completed (but one is from challenge)
|
expect(allTodos.length).to.equal(initialTodoCount + 5); // + 7 - 3 completed (but one is from challenge)
|
||||||
expect(allTodos[allTodos.length - 1].text).to.equal('todo 6');
|
expect(allTodos[allTodos.length - 1].text).to.equal('todo 6'); // last completed todo
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ describe('PUT /tasks/:id', () => {
|
|||||||
checklist: [
|
checklist: [
|
||||||
{text: 123, completed: false},
|
{text: 123, completed: false},
|
||||||
],
|
],
|
||||||
|
collapseChecklist: false,
|
||||||
});
|
});
|
||||||
await sleep(2);
|
await sleep(2);
|
||||||
|
|
||||||
@@ -111,6 +112,7 @@ describe('PUT /tasks/:id', () => {
|
|||||||
{text: 123, completed: false},
|
{text: 123, completed: false},
|
||||||
{text: 456, completed: true},
|
{text: 456, completed: true},
|
||||||
],
|
],
|
||||||
|
collapseChecklist: true,
|
||||||
notes: 'new notes',
|
notes: 'new notes',
|
||||||
attribute: 'per',
|
attribute: 'per',
|
||||||
tags: [challengeUserTaskId],
|
tags: [challengeUserTaskId],
|
||||||
@@ -143,6 +145,8 @@ describe('PUT /tasks/:id', () => {
|
|||||||
expect(savedChallengeUserTask.streak).to.equal(25);
|
expect(savedChallengeUserTask.streak).to.equal(25);
|
||||||
expect(savedChallengeUserTask.reminders.length).to.equal(2);
|
expect(savedChallengeUserTask.reminders.length).to.equal(2);
|
||||||
expect(savedChallengeUserTask.checklist.length).to.equal(2);
|
expect(savedChallengeUserTask.checklist.length).to.equal(2);
|
||||||
|
expect(savedChallengeUserTask.alias).to.equal('a-short-task-name');
|
||||||
|
expect(savedChallengeUserTask.collapseChecklist).to.equal(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,17 @@ import {
|
|||||||
translate as t,
|
translate as t,
|
||||||
} from '../../../../../helpers/api-v3-integration.helper';
|
} from '../../../../../helpers/api-v3-integration.helper';
|
||||||
import { v4 as generateUUID } from 'uuid';
|
import { v4 as generateUUID } from 'uuid';
|
||||||
|
import { find } from 'lodash';
|
||||||
|
|
||||||
describe('POST /tasks/challenge/:challengeId', () => {
|
describe('POST /tasks/challenge/:challengeId', () => {
|
||||||
let user;
|
let user;
|
||||||
let guild;
|
let guild;
|
||||||
let challenge;
|
let challenge;
|
||||||
|
|
||||||
|
function findUserChallengeTask (memberTask) {
|
||||||
|
return memberTask.challenge.id === challenge._id;
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await generateUser({balance: 1});
|
user = await generateUser({balance: 1});
|
||||||
guild = await generateGroup(user);
|
guild = await generateGroup(user);
|
||||||
@@ -88,6 +93,9 @@ describe('POST /tasks/challenge/:challengeId', () => {
|
|||||||
});
|
});
|
||||||
let challengeWithTask = await user.get(`/challenges/${challenge._id}`);
|
let challengeWithTask = await user.get(`/challenges/${challenge._id}`);
|
||||||
|
|
||||||
|
let memberTasks = await user.get('/tasks/user');
|
||||||
|
let userChallengeTask = find(memberTasks, findUserChallengeTask);
|
||||||
|
|
||||||
expect(challengeWithTask.tasksOrder.habits.indexOf(task._id)).to.be.above(-1);
|
expect(challengeWithTask.tasksOrder.habits.indexOf(task._id)).to.be.above(-1);
|
||||||
expect(task.challenge.id).to.equal(challenge._id);
|
expect(task.challenge.id).to.equal(challenge._id);
|
||||||
expect(task.text).to.eql('test habit');
|
expect(task.text).to.eql('test habit');
|
||||||
@@ -95,6 +103,8 @@ describe('POST /tasks/challenge/:challengeId', () => {
|
|||||||
expect(task.type).to.eql('habit');
|
expect(task.type).to.eql('habit');
|
||||||
expect(task.up).to.eql(false);
|
expect(task.up).to.eql(false);
|
||||||
expect(task.down).to.eql(true);
|
expect(task.down).to.eql(true);
|
||||||
|
|
||||||
|
expect(userChallengeTask.notes).to.eql(task.notes);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates a todo', async () => {
|
it('creates a todo', async () => {
|
||||||
@@ -105,11 +115,16 @@ describe('POST /tasks/challenge/:challengeId', () => {
|
|||||||
});
|
});
|
||||||
let challengeWithTask = await user.get(`/challenges/${challenge._id}`);
|
let challengeWithTask = await user.get(`/challenges/${challenge._id}`);
|
||||||
|
|
||||||
|
let memberTasks = await user.get('/tasks/user');
|
||||||
|
let userChallengeTask = find(memberTasks, findUserChallengeTask);
|
||||||
|
|
||||||
expect(challengeWithTask.tasksOrder.todos.indexOf(task._id)).to.be.above(-1);
|
expect(challengeWithTask.tasksOrder.todos.indexOf(task._id)).to.be.above(-1);
|
||||||
expect(task.challenge.id).to.equal(challenge._id);
|
expect(task.challenge.id).to.equal(challenge._id);
|
||||||
expect(task.text).to.eql('test todo');
|
expect(task.text).to.eql('test todo');
|
||||||
expect(task.notes).to.eql('1976');
|
expect(task.notes).to.eql('1976');
|
||||||
expect(task.type).to.eql('todo');
|
expect(task.type).to.eql('todo');
|
||||||
|
|
||||||
|
expect(userChallengeTask.notes).to.eql(task.notes);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates a daily', async () => {
|
it('creates a daily', async () => {
|
||||||
@@ -124,6 +139,9 @@ describe('POST /tasks/challenge/:challengeId', () => {
|
|||||||
});
|
});
|
||||||
let challengeWithTask = await user.get(`/challenges/${challenge._id}`);
|
let challengeWithTask = await user.get(`/challenges/${challenge._id}`);
|
||||||
|
|
||||||
|
let memberTasks = await user.get('/tasks/user');
|
||||||
|
let userChallengeTask = find(memberTasks, findUserChallengeTask);
|
||||||
|
|
||||||
expect(challengeWithTask.tasksOrder.dailys.indexOf(task._id)).to.be.above(-1);
|
expect(challengeWithTask.tasksOrder.dailys.indexOf(task._id)).to.be.above(-1);
|
||||||
expect(task.challenge.id).to.equal(challenge._id);
|
expect(task.challenge.id).to.equal(challenge._id);
|
||||||
expect(task.text).to.eql('test daily');
|
expect(task.text).to.eql('test daily');
|
||||||
@@ -132,5 +150,7 @@ describe('POST /tasks/challenge/:challengeId', () => {
|
|||||||
expect(task.frequency).to.eql('daily');
|
expect(task.frequency).to.eql('daily');
|
||||||
expect(task.everyX).to.eql(5);
|
expect(task.everyX).to.eql(5);
|
||||||
expect(new Date(task.startDate)).to.eql(now);
|
expect(new Date(task.startDate)).to.eql(now);
|
||||||
|
|
||||||
|
expect(userChallengeTask.notes).to.eql(task.notes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -69,4 +69,48 @@ describe('DELETE /tasks/:id', () => {
|
|||||||
expect(syncedTask.group.broken).to.equal('TASK_DELETED');
|
expect(syncedTask.group.broken).to.equal('TASK_DELETED');
|
||||||
expect(member2SyncedTask.group.broken).to.equal('TASK_DELETED');
|
expect(member2SyncedTask.group.broken).to.equal('TASK_DELETED');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('prevents a user from deleting a task they are assigned to', async () => {
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await expect(member.del(`/tasks/${syncedTask._id}`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('cantDeleteAssignedGroupTasks'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows a user to delete a broken task', async () => {
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await user.del(`/tasks/${task._id}`);
|
||||||
|
|
||||||
|
await member.del(`/tasks/${syncedTask._id}`);
|
||||||
|
|
||||||
|
await expect(member.get(`/tasks/${syncedTask._id}`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: 'Task not found.',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows a user to delete a task after leaving a group', async () => {
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await member.post(`/groups/${guild._id}/leave`);
|
||||||
|
|
||||||
|
await member.del(`/tasks/${syncedTask._id}`);
|
||||||
|
|
||||||
|
await expect(member.get(`/tasks/${syncedTask._id}`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: 'Task not found.',
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import {
|
||||||
|
createAndPopulateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import { find } from 'lodash';
|
||||||
|
|
||||||
|
describe('GET /approvals/group/:groupId', () => {
|
||||||
|
let user, guild, member, task, syncedTask;
|
||||||
|
|
||||||
|
function findAssignedTask (memberTask) {
|
||||||
|
return memberTask.group.id === guild._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
let {group, members, groupLeader} = await createAndPopulateGroup({
|
||||||
|
groupDetails: {
|
||||||
|
name: 'Test Guild',
|
||||||
|
type: 'guild',
|
||||||
|
},
|
||||||
|
members: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
guild = group;
|
||||||
|
user = groupLeader;
|
||||||
|
member = members[0];
|
||||||
|
|
||||||
|
task = await user.post(`/tasks/group/${guild._id}`, {
|
||||||
|
text: 'test todo',
|
||||||
|
type: 'todo',
|
||||||
|
requiresApproval: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await member.post(`/tasks/${syncedTask._id}/score/up`);
|
||||||
|
} catch (e) {
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when user is not the group leader', async () => {
|
||||||
|
await expect(member.get(`/approvals/group/${guild._id}`))
|
||||||
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('onlyGroupLeaderCanEditTasks'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('gets a list of task that need approval', async () => {
|
||||||
|
let approvals = await user.get(`/approvals/group/${guild._id}`);
|
||||||
|
expect(approvals[0]._id).to.equal(syncedTask._id);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import {
|
||||||
|
createAndPopulateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import { find } from 'lodash';
|
||||||
|
|
||||||
|
describe('POST /tasks/:id/approve/:userId', () => {
|
||||||
|
let user, guild, member, task;
|
||||||
|
|
||||||
|
function findAssignedTask (memberTask) {
|
||||||
|
return memberTask.group.id === guild._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
let {group, members, groupLeader} = await createAndPopulateGroup({
|
||||||
|
groupDetails: {
|
||||||
|
name: 'Test Guild',
|
||||||
|
type: 'guild',
|
||||||
|
},
|
||||||
|
members: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
guild = group;
|
||||||
|
user = groupLeader;
|
||||||
|
member = members[0];
|
||||||
|
|
||||||
|
task = await user.post(`/tasks/group/${guild._id}`, {
|
||||||
|
text: 'test todo',
|
||||||
|
type: 'todo',
|
||||||
|
requiresApproval: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when user is not assigned', async () => {
|
||||||
|
await expect(user.post(`/tasks/${task._id}/approve/${member._id}`))
|
||||||
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: t('taskNotFound'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when user is not the group leader', async () => {
|
||||||
|
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
await expect(member.post(`/tasks/${task._id}/approve/${member._id}`))
|
||||||
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('onlyGroupLeaderCanEditTasks'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('approves an assigned user', async () => {
|
||||||
|
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
await user.post(`/tasks/${task._id}/approve/${member._id}`);
|
||||||
|
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await member.sync();
|
||||||
|
|
||||||
|
expect(member.notifications.length).to.equal(2);
|
||||||
|
expect(member.notifications[0].type).to.equal('GROUP_TASK_APPROVED');
|
||||||
|
expect(member.notifications[0].data.message).to.equal(t('yourTaskHasBeenApproved', {taskText: task.text}));
|
||||||
|
expect(member.notifications[1].type).to.equal('SCORED_TASK');
|
||||||
|
expect(member.notifications[1].data.message).to.equal(t('yourTaskHasBeenApproved', {taskText: task.text}));
|
||||||
|
|
||||||
|
expect(syncedTask.group.approval.approved).to.be.true;
|
||||||
|
expect(syncedTask.group.approval.approvingUser).to.equal(user._id);
|
||||||
|
expect(syncedTask.group.approval.dateApproved).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import {
|
||||||
|
createAndPopulateGroup,
|
||||||
|
translate as t,
|
||||||
|
} from '../../../../../helpers/api-integration/v3';
|
||||||
|
import { find } from 'lodash';
|
||||||
|
|
||||||
|
describe('POST /tasks/:id/score/:direction', () => {
|
||||||
|
let user, guild, member, task;
|
||||||
|
|
||||||
|
function findAssignedTask (memberTask) {
|
||||||
|
return memberTask.group.id === guild._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
let {group, members, groupLeader} = await createAndPopulateGroup({
|
||||||
|
groupDetails: {
|
||||||
|
name: 'Test Guild',
|
||||||
|
type: 'guild',
|
||||||
|
},
|
||||||
|
members: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
guild = group;
|
||||||
|
user = groupLeader;
|
||||||
|
member = members[0];
|
||||||
|
|
||||||
|
task = await user.post(`/tasks/group/${guild._id}`, {
|
||||||
|
text: 'test todo',
|
||||||
|
type: 'todo',
|
||||||
|
requiresApproval: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prevents user from scoring a task that needs to be approved', async () => {
|
||||||
|
await user.update({
|
||||||
|
'preferences.language': 'cs',
|
||||||
|
});
|
||||||
|
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await expect(member.post(`/tasks/${syncedTask._id}/score/up`))
|
||||||
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('taskApprovalHasBeenRequested'),
|
||||||
|
});
|
||||||
|
let updatedTask = await member.get(`/tasks/${syncedTask._id}`);
|
||||||
|
|
||||||
|
await user.sync();
|
||||||
|
|
||||||
|
expect(user.notifications.length).to.equal(1);
|
||||||
|
expect(user.notifications[0].type).to.equal('GROUP_TASK_APPROVAL');
|
||||||
|
expect(user.notifications[0].data.message).to.equal(t('userHasRequestedTaskApproval', {
|
||||||
|
user: member.auth.local.username,
|
||||||
|
taskName: updatedTask.text,
|
||||||
|
}, 'cs')); // This test only works if we have the notification translated
|
||||||
|
expect(user.notifications[0].data.groupId).to.equal(guild._id);
|
||||||
|
|
||||||
|
expect(updatedTask.group.approval.requested).to.equal(true);
|
||||||
|
expect(updatedTask.group.approval.requestedDate).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
|
||||||
|
});
|
||||||
|
|
||||||
|
it('errors when approval has already been requested', async () => {
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await expect(member.post(`/tasks/${syncedTask._id}/score/up`))
|
||||||
|
.to.eventually.be.rejected.and.to.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('taskApprovalHasBeenRequested'),
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(member.post(`/tasks/${syncedTask._id}/score/up`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('taskRequiresApproval'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows a user to score an apporoved task', async () => {
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
await user.post(`/tasks/${task._id}/approve/${member._id}`);
|
||||||
|
|
||||||
|
await member.post(`/tasks/${syncedTask._id}/score/up`);
|
||||||
|
let updatedTask = await member.get(`/tasks/${syncedTask._id}`);
|
||||||
|
|
||||||
|
expect(updatedTask.completed).to.equal(true);
|
||||||
|
expect(updatedTask.dateCompleted).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -74,7 +74,7 @@ describe('POST /tasks/:taskId', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns error when non leader tries to create a task', async () => {
|
it('returns error when non leader tries to create a task', async () => {
|
||||||
await expect(member.post(`/tasks/${task._id}/assign/${member._id}`))
|
await expect(member2.post(`/tasks/${task._id}/assign/${member._id}`))
|
||||||
.to.eventually.be.rejected.and.eql({
|
.to.eventually.be.rejected.and.eql({
|
||||||
code: 401,
|
code: 401,
|
||||||
error: 'NotAuthorized',
|
error: 'NotAuthorized',
|
||||||
@@ -82,6 +82,26 @@ describe('POST /tasks/:taskId', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('allows user to assign themselves (claim)', async () => {
|
||||||
|
await member.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
|
||||||
|
let groupTask = await user.get(`/tasks/group/${guild._id}`);
|
||||||
|
let memberTasks = await member.get('/tasks/user');
|
||||||
|
let syncedTask = find(memberTasks, findAssignedTask);
|
||||||
|
|
||||||
|
expect(groupTask[0].group.assignedUsers).to.contain(member._id);
|
||||||
|
expect(syncedTask).to.exist;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends a message to the group when a user claims a task', async () => {
|
||||||
|
await member.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
|
||||||
|
let updateGroup = await user.get(`/groups/${guild._id}`);
|
||||||
|
|
||||||
|
expect(updateGroup.chat[0].text).to.equal(t('userIsClamingTask', {username: member.profile.name, task: task.text}));
|
||||||
|
expect(updateGroup.chat[0].uuid).to.equal('system');
|
||||||
|
});
|
||||||
|
|
||||||
it('assigns a task to a user', async () => {
|
it('assigns a task to a user', async () => {
|
||||||
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
await user.post(`/tasks/${task._id}/assign/${member._id}`);
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user