slender_data 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/app/assets/javascripts/slender_data/entry_store.coffee +10 -10
- data/app/assets/javascripts/slender_data/loading_tracker.coffee +62 -47
- data/app/assets/javascripts/slender_data/persistence_manager.coffee +43 -18
- data/app/assets/javascripts/slender_data/queries/single_query.coffee +1 -1
- data/lib/slender_data/version.rb +1 -1
- data/spec/dummy/log/test.log +29 -826
- data/spec/dummy/spec/javascripts/brest_loader_spec.coffee +12 -25
- data/spec/dummy/spec/javascripts/entry_store_spec.coffee +52 -25
- data/spec/dummy/spec/javascripts/loading_tracker_spec.coffee +120 -89
- data/spec/dummy/spec/javascripts/parameterizable_spec.coffee +2 -2
- data/spec/dummy/spec/javascripts/persistence_manager_spec.coffee +174 -69
- data/spec/dummy/spec/javascripts/queries/multi_query_spec.coffee +6 -6
- data/spec/dummy/spec/javascripts/queries/single_query_spec.coffee +0 -10
- data/spec/dummy/spec/javascripts/query_cache_spec.coffee +11 -19
- data/spec/dummy/spec/javascripts/spec_helper.coffee +27 -0
- data/spec/dummy/spec/javascripts/underscore.js +6 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/124f6816f926ae28ad20cc56425f3c91 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/12ce2414098e368903aeb9923e275ef7 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/1ca8c5b832302c6c94692d0875a59605 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2b22662f42e9f485aafa6a333faaa256 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2ec1baba6d6dc634d091b3acf8127cf7 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/311f68c1b9e342ebab4c92c8cb2b5e54 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/33ea745e7aa9669831758b7d36db1cb4 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3e9a6ed890157d94f18b480f0079d8e1 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3ef50ccfe459d5c89ecc79a448586b49 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/46c298dc2ff12ec748c70c017684fc28 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/476318dd8109fbf173335456cabb4128 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/5602ee157ea76a2f44a43739a83b1a6c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/5b5a66f4eefc591d284af6535ae474ea +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/643d60abdbcc813c95214920f12f09c3 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6c75b81de9afea82a6cbb56749157e3f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6fd5544e52538b06ac40e5b387b020a5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6fed8361766f5ae3cbf781986d6945b2 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/70ffa648dbbe0f2431e7f9307b569354 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/76cd4393e7976d030f4623b8b6b372a0 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/7a400f93bfb71a1a11c59b9804adda6d +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/814ca144649e7dec9e9158b3ec3460f1 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/83de5b2d2c5d49f7737ae1f0316435ec +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/873c5252aa4eab7409b712c5e276bad2 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/87a6ddc523ccbf2673750499bede3fc9 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/98610661915880264fdb51c8f1a14141 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/9a00753cdfb01f357dc39eeada77d0bc +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/9ad3db355e00d28ed3faed6dea5b1bff +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/9cbb3109d489692fd270c77ffa9d9559 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a22afac508f5adc12bf48d2f8333b8f7 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/abf215c8dc45135a91f4f993514c653f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ac1b8c30ad00cc489b7ec78bd6e2fc6c +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/b1950420978c68074fc6fd81d4320bc0 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/b59a10f85562b39fc7dd651965df9cab +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/b8d24bca037cf4b0a9e2979c11c8aea8 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/bc2f15f88df08b4265c83133d6107680 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/c0515d57887926d6e28a0f87da31ee8e +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/cce1f28f0d1f5c2817e6eaf392bac615 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d37cae0bfdf135e6e71bcd0572bef329 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/dc54acb6b8cd4b84b13f440d57db37b1 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/dec2df59b57b3639f89847e50416c924 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/df13b2e8a88a9dcdc4a830fdd8f8d7b8 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/e43bfee690613c316a59f122315314e5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ed1d892145be7053348b0ba28c27b427 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/efec5fde178e0875317a0d380222545d +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f01906d52258e56e92a230dc3e55805d +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f37842723e3572ba18f02519dab4ee77 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f72501aca20f34d765720253853e6105 +0 -0
- data/spec/dummy/tmp/cache/assets/{development → test}/sprockets/f74306735334107c5d17684f524b65cf +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ff445b9646db9910af486791b285b112 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ffa1eaa25729d9d4cd7e2fd666868936 +0 -0
- metadata +40 -311
- data/app/assets/javascripts/slender_data/loading_indicator.coffee +0 -28
- data/lib/tasks/slender_data_tasks.rake +0 -4
- data/spec/dummy/log/development.log +0 -349013
- data/spec/dummy/tmp/cache/assets/development/sprockets/02dabf70b4ae4a034f349ce89b4831d8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/031a6c2e3a4e952151301446bd3fc16d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/0373c4e5507b3195c4ad15224d991609 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/05175bd457a57c3ad73ab9a2c8696c9b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/086e89c7529d5063e771b41793bfe311 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/08b36042c3a4a79ebd9cee8ee1b88e6a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/10513fd445754b59bd6001ea6ee727d9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/124f6816f926ae28ad20cc56425f3c91 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/14eca89f8dccac139fd132de35d22628 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/16c8b12ef6dcb486a7b771e43bbcc117 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/19cdfaa89f900500a03507b86afe1231 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/1b3a4d533a743ca2ccfbca0986613995 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2e2576241d2a4969c9277fe85851c92b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2ec1baba6d6dc634d091b3acf8127cf7 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/2ff315acad8ceec317fd566d792df64f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/311f68c1b9e342ebab4c92c8cb2b5e54 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/324a5040c964d5e8d293564383c49b91 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3310b5a70d0b220782ab3e87642834e9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/33ea745e7aa9669831758b7d36db1cb4 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3999afdceee7ca8dcf53757221c62d71 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3ba03b9f1aab60e78424f36e0e6cce6c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3e9a6ed890157d94f18b480f0079d8e1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/3ef50ccfe459d5c89ecc79a448586b49 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/46c298dc2ff12ec748c70c017684fc28 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/476318dd8109fbf173335456cabb4128 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5602ee157ea76a2f44a43739a83b1a6c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5b390f4782d6b77f5aec7ec56f3ad934 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5b5a66f4eefc591d284af6535ae474ea +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5c41eeb2e98dc0833647e8547880435e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5cd2936d626662390288ab4c07ff3957 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/5fd362891a204d492d9fa57ffee6e114 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/643d60abdbcc813c95214920f12f09c3 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6591bc7545da5a2f5f7dee20b1f110a5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6597f36181468ff92ba4284afe001181 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/69b7946c418b75e7ba78f9fc73d3e9b9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6c75b81de9afea82a6cbb56749157e3f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6e4bc63f9308eb5929a77f7607101af1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6ee2243cf1cf415b6267b84dd7b8ba77 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6f8457b4ba418f572891745381a1e0f5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6fd5544e52538b06ac40e5b387b020a5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/6fed8361766f5ae3cbf781986d6945b2 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/70ffa648dbbe0f2431e7f9307b569354 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/731f0bc492f775825f046d500938fc5a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/76153dd2cc3d0c6e584080efb16e872a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/76cd4393e7976d030f4623b8b6b372a0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/78d5dac5e2f907dd68813ed23a0fd4ac +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7a400f93bfb71a1a11c59b9804adda6d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7abf5e8d9666225cb1d7881798dbd87a +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/7d6f1f3e48f6cc97a9bb4606f8c5a020 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/814ca144649e7dec9e9158b3ec3460f1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/83de5b2d2c5d49f7737ae1f0316435ec +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/84c67faa73fdd082d4bd7f7712cb0499 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/87a6ddc523ccbf2673750499bede3fc9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8a90082fa76a7f37dd92a9b9a9b9f593 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8c5b622a33c6c034ecb4e78f131c5f73 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8c9851849e82bb9670e56f046df437f9 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/8fc1455d3af69de5da04bf2a2a3f0b74 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/96af98519e5badf206b77c3ecaf86d20 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/98610661915880264fdb51c8f1a14141 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9a00753cdfb01f357dc39eeada77d0bc +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/9ad3db355e00d28ed3faed6dea5b1bff +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a22afac508f5adc12bf48d2f8333b8f7 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a49d020ee42c78bf7d22a21e8ee3b80f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a4f4f6c56c368263c0fbcf3f1542aa73 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a56b8266298c4171918ee403aa1c9e0f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/a73a44bfca198fdf779532b644ec8af5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/aa4a22da44bd1b7dbdbb18f983d6c09b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ab0236bf3eac5cd30348c18efce8246b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ac1b8c30ad00cc489b7ec78bd6e2fc6c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ae8bd07980ad64ef8e9ac3fe38413c6d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b1950420978c68074fc6fd81d4320bc0 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b2d6aa1cb303474ebf3bfc571904ad23 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/b8d24bca037cf4b0a9e2979c11c8aea8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bc2f15f88df08b4265c83133d6107680 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/bd7ddfa86995ff5d259ea37e4a90c51c +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c4820232e07d4e298e834c1011a72faa +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c6babc078901541de3f4cb5cc2703bea +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c9635dd5cbd79bdd9c58a89f6ea01595 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/c9962abce37f5a56d5f05afe1edfe1b8 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/cce1f28f0d1f5c2817e6eaf392bac615 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d37cae0bfdf135e6e71bcd0572bef329 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d4956056f6f35287a04295df6e52575d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/dc54acb6b8cd4b84b13f440d57db37b1 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/dd51c50b2d8231175e8da83e8b057120 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/df45b0abc2c323093874639ceb72c012 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e0393ec0ca968f0d4182c82802da79d5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/e43bfee690613c316a59f122315314e5 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ed1d892145be7053348b0ba28c27b427 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ef2b922f05692ba49eb1f68801786b8e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/efec5fde178e0875317a0d380222545d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f01906d52258e56e92a230dc3e55805d +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f1b4ffa23205a95782c5c5050359429f +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f2080a87aa027245a444b1486dce7792 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f37842723e3572ba18f02519dab4ee77 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f72501aca20f34d765720253853e6105 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/f89dc49f90e98b448540556861f0173e +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/feadb1611975b23f2647e1ac656ad90b +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ff445b9646db9910af486791b285b112 +0 -0
- data/spec/dummy/tmp/cache/assets/development/sprockets/ffa1eaa25729d9d4cd7e2fd666868936 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/02dabf70b4ae4a034f349ce89b4831d8 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/031a6c2e3a4e952151301446bd3fc16d +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/0373c4e5507b3195c4ad15224d991609 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/05175bd457a57c3ad73ab9a2c8696c9b +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/086e89c7529d5063e771b41793bfe311 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/08b36042c3a4a79ebd9cee8ee1b88e6a +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/10513fd445754b59bd6001ea6ee727d9 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/14eca89f8dccac139fd132de35d22628 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/16c8b12ef6dcb486a7b771e43bbcc117 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2e2576241d2a4969c9277fe85851c92b +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/2ff315acad8ceec317fd566d792df64f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/324a5040c964d5e8d293564383c49b91 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3310b5a70d0b220782ab3e87642834e9 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/3999afdceee7ca8dcf53757221c62d71 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/5b390f4782d6b77f5aec7ec56f3ad934 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/5cd2936d626662390288ab4c07ff3957 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6597f36181468ff92ba4284afe001181 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6e4bc63f9308eb5929a77f7607101af1 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6ee2243cf1cf415b6267b84dd7b8ba77 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/6f8457b4ba418f572891745381a1e0f5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/7abf5e8d9666225cb1d7881798dbd87a +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/7d6f1f3e48f6cc97a9bb4606f8c5a020 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/8a90082fa76a7f37dd92a9b9a9b9f593 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/8c5b622a33c6c034ecb4e78f131c5f73 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/8c9851849e82bb9670e56f046df437f9 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/8fc1455d3af69de5da04bf2a2a3f0b74 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a4f4f6c56c368263c0fbcf3f1542aa73 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a56b8266298c4171918ee403aa1c9e0f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/a73a44bfca198fdf779532b644ec8af5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/aa4a22da44bd1b7dbdbb18f983d6c09b +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ab0236bf3eac5cd30348c18efce8246b +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ae8bd07980ad64ef8e9ac3fe38413c6d +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/b2d6aa1cb303474ebf3bfc571904ad23 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/c9962abce37f5a56d5f05afe1edfe1b8 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/d4956056f6f35287a04295df6e52575d +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/dd51c50b2d8231175e8da83e8b057120 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/df45b0abc2c323093874639ceb72c012 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/e0393ec0ca968f0d4182c82802da79d5 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/ef2b922f05692ba49eb1f68801786b8e +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f1b4ffa23205a95782c5c5050359429f +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/f2080a87aa027245a444b1486dce7792 +0 -0
- data/spec/dummy/tmp/cache/assets/test/sprockets/feadb1611975b23f2647e1ac656ad90b +0 -0
|
@@ -26,8 +26,7 @@ describe 'BrestLoader', ->
|
|
|
26
26
|
data: { user: { email: 'one@example.com' }}
|
|
27
27
|
|
|
28
28
|
it 'returns the entry from the server as a query', ->
|
|
29
|
-
expect(@callback).to.have.been.
|
|
30
|
-
expect(@callback).to.have.been.calledWith user: @user_1
|
|
29
|
+
expect(@callback).to.have.been.calledOnceWith user: @user_1
|
|
31
30
|
|
|
32
31
|
|
|
33
32
|
|
|
@@ -52,8 +51,7 @@ describe 'BrestLoader', ->
|
|
|
52
51
|
{ email: 'two@example.com' } ] }
|
|
53
52
|
|
|
54
53
|
it 'returns the entry from the server as a multi_query', ->
|
|
55
|
-
expect(@callback).to.have.been.
|
|
56
|
-
expect(@callback).to.have.been.calledWith users: [@user_1, @user_2]
|
|
54
|
+
expect(@callback).to.have.been.calledOnceWith users: [@user_1, @user_2]
|
|
57
55
|
|
|
58
56
|
|
|
59
57
|
|
|
@@ -177,11 +175,8 @@ describe 'BrestLoader', ->
|
|
|
177
175
|
expect(@server_merge_api).to.have.been.calledWithMatch
|
|
178
176
|
data: old_snippet_ids: [1, 2], merged_snippet_data: @merged_user
|
|
179
177
|
|
|
180
|
-
it 'calls the given callback', ->
|
|
181
|
-
expect(@callback).to.have.been.
|
|
182
|
-
|
|
183
|
-
it 'provides the server response to the callback', ->
|
|
184
|
-
expect(@callback).to.have.been.calledWith user: @merged_user
|
|
178
|
+
it 'calls the given callback with the server response', ->
|
|
179
|
+
expect(@callback).to.have.been.calledOnceWith user: @merged_user
|
|
185
180
|
|
|
186
181
|
|
|
187
182
|
describe 'read', ->
|
|
@@ -199,12 +194,10 @@ describe 'BrestLoader', ->
|
|
|
199
194
|
@brest_loader.read user: {username: 'one'}, @callback
|
|
200
195
|
|
|
201
196
|
it 'makes an ajax request to the REST read endpoint', ->
|
|
202
|
-
expect(jQuery.get).to.have.been.
|
|
203
|
-
expect(jQuery.get).to.have.been.calledWith '/users/one.json'
|
|
197
|
+
expect(jQuery.get).to.have.been.calledOnceWith '/users/one.json'
|
|
204
198
|
|
|
205
199
|
it 'returns the entry from the server as a query', ->
|
|
206
|
-
expect(@callback).to.have.been.
|
|
207
|
-
expect(@callback).to.have.been.calledWith user: @user_1
|
|
200
|
+
expect(@callback).to.have.been.calledOnceWith user: @user_1
|
|
208
201
|
|
|
209
202
|
|
|
210
203
|
context 'id query given', ->
|
|
@@ -213,12 +206,10 @@ describe 'BrestLoader', ->
|
|
|
213
206
|
@brest_loader.read username: 'one', @callback
|
|
214
207
|
|
|
215
208
|
it 'makes an ajax request to the REST read endpoint', ->
|
|
216
|
-
expect(jQuery.get).to.have.been.
|
|
217
|
-
expect(jQuery.get).to.have.been.calledWith '/users/one.json'
|
|
209
|
+
expect(jQuery.get).to.have.been.calledOnceWith '/users/one.json'
|
|
218
210
|
|
|
219
211
|
it 'returns the entry from the server as a query', ->
|
|
220
|
-
expect(@callback).to.have.been.
|
|
221
|
-
expect(@callback).to.have.been.calledWith user: @user_1
|
|
212
|
+
expect(@callback).to.have.been.calledOnceWith user: @user_1
|
|
222
213
|
|
|
223
214
|
|
|
224
215
|
describe 'read_many', ->
|
|
@@ -243,8 +234,7 @@ describe 'BrestLoader', ->
|
|
|
243
234
|
expect(jQuery.ajax).to.have.been.calledWithMatch data: {usernames: 'one two'}
|
|
244
235
|
|
|
245
236
|
it 'returns the entry from the server as a multi_query', ->
|
|
246
|
-
expect(@callback).to.have.been.
|
|
247
|
-
expect(@callback).to.have.been.calledWith users: [@user_1, @user_2]
|
|
237
|
+
expect(@callback).to.have.been.calledOnceWith users: [@user_1, @user_2]
|
|
248
238
|
|
|
249
239
|
|
|
250
240
|
context 'ids multi-query given', ->
|
|
@@ -258,8 +248,7 @@ describe 'BrestLoader', ->
|
|
|
258
248
|
expect(jQuery.ajax).to.have.been.calledWithMatch data: {usernames: 'one two three'}
|
|
259
249
|
|
|
260
250
|
it 'returns the entry from the server as a multi_query', ->
|
|
261
|
-
expect(@callback).to.have.been.
|
|
262
|
-
expect(@callback).to.have.been.calledWith users: [@user_1, @user_2]
|
|
251
|
+
expect(@callback).to.have.been.calledOnceWith users: [@user_1, @user_2]
|
|
263
252
|
|
|
264
253
|
|
|
265
254
|
|
|
@@ -283,8 +272,7 @@ describe 'BrestLoader', ->
|
|
|
283
272
|
expect(jQuery.ajax).to.have.been.calledWithMatch data: { user: { email: 'new@example.com' }}
|
|
284
273
|
|
|
285
274
|
it 'returns the entry from the server as a query', ->
|
|
286
|
-
expect(@callback).to.have.been.
|
|
287
|
-
expect(@callback).to.have.been.calledWith user: @user_1
|
|
275
|
+
expect(@callback).to.have.been.calledOnceWith user: @user_1
|
|
288
276
|
|
|
289
277
|
|
|
290
278
|
|
|
@@ -309,6 +297,5 @@ describe 'BrestLoader', ->
|
|
|
309
297
|
{ username: 'two', email: 'two@example.com' } ] }
|
|
310
298
|
|
|
311
299
|
it 'returns the entry from the server as a multi_query', ->
|
|
312
|
-
expect(@callback).to.have.been.
|
|
313
|
-
expect(@callback).to.have.been.calledWith users: [@user_1, @user_2]
|
|
300
|
+
expect(@callback).to.have.been.calledOnceWith users: [@user_1, @user_2]
|
|
314
301
|
|
|
@@ -27,40 +27,69 @@ describe 'EntryStore', ->
|
|
|
27
27
|
result = @entry_store.add server_entry
|
|
28
28
|
expect(@entry_store.get username: 'one').to.eql server_entry
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
it 'returns nothing', ->
|
|
31
|
+
expect(@result).to.be.undefined
|
|
31
32
|
|
|
32
|
-
beforeEach ->
|
|
33
|
-
@test_params.partial_entries = yes
|
|
34
|
-
@entry_store = new slender_data.EntryStore @test_params
|
|
35
33
|
|
|
36
|
-
|
|
34
|
+
describe 'partial entries management', ->
|
|
37
35
|
|
|
38
36
|
beforeEach ->
|
|
39
|
-
@
|
|
37
|
+
@test_params.partial_entries = yes
|
|
38
|
+
@entry_store = new slender_data.EntryStore @test_params
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
@entry_store.add @full_user_1
|
|
43
|
-
expect(@entry_store.get username: 'one').to.eql @full_user_1
|
|
40
|
+
context 'partial entry cached', ->
|
|
44
41
|
|
|
45
|
-
|
|
42
|
+
beforeEach ->
|
|
43
|
+
@entry_store.add @partial_user_1
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
it 'replaces the cached entry with the given full entry', ->
|
|
46
|
+
@entry_store.add @full_user_1
|
|
47
|
+
expect(@entry_store.get username: 'one').to.eql @full_user_1
|
|
48
|
+
|
|
49
|
+
context 'full entry cached', ->
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
beforeEach ->
|
|
52
|
+
@entry_store.add @full_user_1
|
|
53
|
+
|
|
54
|
+
it 'does not replace the cached value with the given partial entry', ->
|
|
55
|
+
@entry_store.add @partial_user_1
|
|
56
|
+
expect(@entry_store.get username: 'one').to.eql @full_user_1
|
|
57
|
+
|
|
58
|
+
describe 'return-editables option', ->
|
|
59
|
+
|
|
60
|
+
it 'returns editable versions of the option is set', ->
|
|
61
|
+
result = @entry_store.add @user_1, yes
|
|
62
|
+
expect(result).to.be.an.editable_version_of @user_1
|
|
63
|
+
|
|
64
|
+
it 'returns nothing if the option is not set', ->
|
|
65
|
+
result = @entry_store.add @user_1, no
|
|
66
|
+
expect(result).to.be.undefined
|
|
53
67
|
|
|
54
68
|
|
|
55
69
|
describe 'add_many', ->
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
@result = @entry_store.add_many [@user_1, @user_2]
|
|
71
|
+
describe 'default behavior', ->
|
|
59
72
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
expect(@entry_store.get user: @user_2).to.eql @user_2
|
|
73
|
+
beforeEach ->
|
|
74
|
+
@result = @entry_store.add_many [@user_1, @user_2]
|
|
63
75
|
|
|
76
|
+
it 'adds the given entries to the cache', ->
|
|
77
|
+
expect(@entry_store.get user: @user_1).to.eql @user_1
|
|
78
|
+
expect(@entry_store.get user: @user_2).to.eql @user_2
|
|
79
|
+
|
|
80
|
+
it 'returns nothing', ->
|
|
81
|
+
expect(@result).to.be.undefined
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
describe 'return_editable_version option', ->
|
|
85
|
+
|
|
86
|
+
it 'returns editable versions of the given data if set', ->
|
|
87
|
+
result = @entry_store.add_many [@user_1, @user_2], yes
|
|
88
|
+
expect(result[0]).to.be.an.editable_version_of @user_1
|
|
89
|
+
expect(result[1]).to.be.an.editable_version_of @user_2
|
|
90
|
+
|
|
91
|
+
it 'returns nothing if not set', ->
|
|
92
|
+
expect(@entry_store.add_many [@user_1, @user_2], no).to.be.undefined
|
|
64
93
|
|
|
65
94
|
|
|
66
95
|
describe 'delete', ->
|
|
@@ -193,8 +222,7 @@ describe 'EntryStore', ->
|
|
|
193
222
|
@entry_store.add @user_1
|
|
194
223
|
|
|
195
224
|
it 'returns a modifiable version of existing unmodified entries', ->
|
|
196
|
-
expect(@entry_store.get user: @user_1).to.
|
|
197
|
-
expect(@entry_store.get user: @user_1).to.not.equal @user_1
|
|
225
|
+
expect(@entry_store.get user: @user_1).to.be.an.editable_version_of @user_1
|
|
198
226
|
|
|
199
227
|
it 'returns modified entries in the modified version', ->
|
|
200
228
|
user = @entry_store.get user: @user_1
|
|
@@ -248,8 +276,7 @@ describe 'EntryStore', ->
|
|
|
248
276
|
expect(@result.found).to.eql [@user_1, @user_2]
|
|
249
277
|
|
|
250
278
|
it 'returns editable versions of the cached entries', ->
|
|
251
|
-
expect(@result.found[0]).to.
|
|
252
|
-
expect(@result.found[0]).to.not.equal @user_1
|
|
279
|
+
expect(@result.found[0]).to.be.an.editable_version_of @user_1
|
|
253
280
|
|
|
254
281
|
it 'returns the missing entries as a MultiQuery', ->
|
|
255
282
|
expect(@result.missing).to.be.an.instanceof slender_data.MultiQuery
|
|
@@ -311,5 +338,5 @@ describe 'EntryStore', ->
|
|
|
311
338
|
expect(@result.found).to.eql [@user_2]
|
|
312
339
|
|
|
313
340
|
it 'reports outdated entries as missing', ->
|
|
314
|
-
expect(@result.missing
|
|
341
|
+
expect(@result.missing).to.eql_query users: [@user_1]
|
|
315
342
|
|
|
@@ -1,95 +1,126 @@
|
|
|
1
1
|
#= require spec_helper
|
|
2
|
+
#= require slender_data/loading_tracker
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
# Domain-specifc matcher for checking if the given
|
|
5
|
-
chai.Assertion.addMethod '
|
|
6
|
-
@assert @_obj.is_loading(
|
|
7
|
-
"""expected
|
|
5
|
+
# Domain-specifc matcher for checking if the given entry is currently loading.
|
|
6
|
+
chai.Assertion.addMethod 'loading', (query) ->
|
|
7
|
+
@assert @_obj.is_loading(query),
|
|
8
|
+
"""expected entry '#{query.username}' to be loading,
|
|
8
9
|
but it was not""",
|
|
9
|
-
"""expected
|
|
10
|
+
"""expected entry '#{query.username}' to not be loading,
|
|
10
11
|
but it is"""
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
13
|
+
|
|
14
|
+
describe 'slender_data.LoadingTracker', ->
|
|
15
|
+
|
|
16
|
+
beforeEach ->
|
|
17
|
+
define_test_data this
|
|
18
|
+
@loading_tracker = new slender_data.LoadingTracker @test_params
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
describe 'entry_arrived', ->
|
|
22
|
+
|
|
23
|
+
beforeEach ->
|
|
24
|
+
@loading_tracker.start_loadings users: [@user_1, @user_2]
|
|
25
|
+
|
|
26
|
+
it 'calls the queued callback with the loaded entry', (done) ->
|
|
27
|
+
@loading_tracker.wait_for_entry_loaded user: @user_1, (entry) =>
|
|
28
|
+
expect(entry).to.equal @user_1
|
|
29
|
+
done()
|
|
30
|
+
@loading_tracker.entry_arrived @user_1
|
|
31
|
+
|
|
32
|
+
it 'unregisters the arrived entrys from the loading list', ->
|
|
33
|
+
@loading_tracker.entry_arrived @user_1
|
|
34
|
+
expect(@loading_tracker).to.not.have.loading user: @user_1
|
|
35
|
+
|
|
36
|
+
it 'does not unregister other loading entries', ->
|
|
37
|
+
@loading_tracker.entry_arrived @user_1
|
|
38
|
+
expect(@loading_tracker).to.have.loading user: @user_2
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
describe 'is_loading', ->
|
|
42
|
+
|
|
43
|
+
it 'returns false if the entry is not loading', ->
|
|
44
|
+
expect(@loading_tracker.is_loading id: 3).to.be.false
|
|
45
|
+
|
|
46
|
+
it 'returns true if the entry is currently loading', ->
|
|
47
|
+
@loading_tracker.start_loading id: 3
|
|
48
|
+
expect(@loading_tracker.is_loading id: 3).to.be.true
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
describe 'start_loading', ->
|
|
52
|
+
|
|
53
|
+
it 'stores the id of the loading query', ->
|
|
54
|
+
@loading_tracker.start_loading @user_1
|
|
55
|
+
expect(@loading_tracker).to.have.loading user: @user_1
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
describe 'start_loadings', ->
|
|
59
|
+
|
|
60
|
+
it 'stores the ids of the loading entries', ->
|
|
61
|
+
@loading_tracker.start_loadings users: [@user_1, @user_3]
|
|
62
|
+
expect(@loading_tracker).to.have.loading user: @user_1
|
|
63
|
+
expect(@loading_tracker).to.not.have.loading user: @user_2
|
|
64
|
+
expect(@loading_tracker).to.have.loading user: @user_3
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
describe 'wait_for_entry_loaded', ->
|
|
68
|
+
|
|
69
|
+
describe 'without a request running', ->
|
|
70
|
+
|
|
71
|
+
beforeEach ->
|
|
72
|
+
@callback = sinon.stub()
|
|
73
|
+
@result = @loading_tracker.wait_for_entry_loaded user: @user_1,
|
|
74
|
+
@callback
|
|
75
|
+
|
|
76
|
+
it 'returns the given query as the function result', ->
|
|
77
|
+
expect(@result).to.eql_query user: @user_1
|
|
78
|
+
|
|
79
|
+
it 'does not call the given callback', ->
|
|
80
|
+
expect(@callback).to.not.have.been.called
|
|
81
|
+
|
|
82
|
+
it 'does not call the given callback when the entry gets loaded later', ->
|
|
83
|
+
@loading_tracker.entry_arrived @user_1
|
|
84
|
+
expect(@callback).to.not.have.been.called
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
describe 'while a request is running', ->
|
|
88
|
+
|
|
89
|
+
beforeEach ->
|
|
90
|
+
@loading_tracker.start_loading user: @user_1
|
|
91
|
+
@callback = sinon.stub()
|
|
92
|
+
@result = @loading_tracker.wait_for_entry_loaded user: @user_1,
|
|
93
|
+
@callback
|
|
94
|
+
|
|
95
|
+
it 'returns nothing', ->
|
|
96
|
+
expect(@result).to.be.undefined
|
|
97
|
+
|
|
98
|
+
it 'does not call the given callback', ->
|
|
99
|
+
expect(@callback).to.not.have.been.called
|
|
100
|
+
|
|
101
|
+
it 'calls the given callback when the entry is loaded later', ->
|
|
102
|
+
@loading_tracker.entry_arrived @user_1
|
|
103
|
+
expect(@callback).to.have.been.calledOnce
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
describe 'wait_for_entries_loaded', ->
|
|
107
|
+
|
|
108
|
+
beforeEach ->
|
|
109
|
+
@loading_tracker.start_loadings users: [@user_1, @user_2]
|
|
110
|
+
@callback = sinon.stub()
|
|
111
|
+
@result = @loading_tracker.wait_for_entries_loaded users: [@user_1, @user_2, @user_3],
|
|
112
|
+
@callback
|
|
113
|
+
|
|
114
|
+
it 'returns a multiquery describing the entries that are not currently loading', ->
|
|
115
|
+
expect(@result).to.eql_query users: [@user_3]
|
|
116
|
+
|
|
117
|
+
it 'does not call the callback if not all entries have been loaded yet', ->
|
|
118
|
+
expect(@callback).to.not.have.been.called
|
|
119
|
+
@loading_tracker.entry_arrived @user_1
|
|
120
|
+
expect(@callback).to.not.have.been.called
|
|
121
|
+
|
|
122
|
+
it 'calls the given callback with the loaded entries when they all have loaded', ->
|
|
123
|
+
@loading_tracker.entry_arrived @user_1
|
|
124
|
+
@loading_tracker.entry_arrived @user_2
|
|
125
|
+
expect(@callback).to.have.been.calledOnceWith [@user_1, @user_2]
|
|
126
|
+
|
|
@@ -84,7 +84,7 @@ describe 'Parameterizable', ->
|
|
|
84
84
|
|
|
85
85
|
it 'returns a query instance for the given hash', ->
|
|
86
86
|
expect(@result).to.be.an.instanceof slender_data.SingleQuery
|
|
87
|
-
expect(@result
|
|
87
|
+
expect(@result).to.eql_query @query_hash
|
|
88
88
|
|
|
89
89
|
it 'configures the created query with the default configuration values of the current query', ->
|
|
90
90
|
expect(@result.versioning).to.be.true
|
|
@@ -118,7 +118,7 @@ describe 'Parameterizable', ->
|
|
|
118
118
|
|
|
119
119
|
it 'returns a query instance for the given hash', ->
|
|
120
120
|
expect(@result).to.be.an.instanceof slender_data.MultiQuery
|
|
121
|
-
expect(@result
|
|
121
|
+
expect(@result).to.eql_query @query_hash
|
|
122
122
|
|
|
123
123
|
it 'configures the created query with the default configuration values of the current query', ->
|
|
124
124
|
expect(@result.versioning).to.be.true
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
#= require spec_helper
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
# Domain-specifc matcher for checking if the PersistenceManager
|
|
5
|
+
# has the given user in the cache (or not).
|
|
6
|
+
chai.Assertion.addMethod 'cached_user', (user) ->
|
|
7
|
+
cached_user = @_obj.get user: user
|
|
8
|
+
if @__flags.negate
|
|
9
|
+
# No cached user expected.
|
|
10
|
+
new chai.Assertion(cached_user,
|
|
11
|
+
'Should not have cached user').to.be.undefined
|
|
12
|
+
else
|
|
13
|
+
# The given cached user expected.
|
|
14
|
+
new chai.Assertion(cached_user,
|
|
15
|
+
'Should have cached user').to.be.eql user
|
|
16
|
+
new chai.Assertion(cached_user,
|
|
17
|
+
'Should have cached user').to.not.be.equal user
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Domain-specifc matcher for checking if the tested object is an array
|
|
21
|
+
# of elements with at least the given properties.
|
|
22
|
+
chai.Assertion.addMethod 'entries_with_matching_properties', (attr_name, expected_values) ->
|
|
23
|
+
expect(@_obj).to.have.length expected_values.length
|
|
24
|
+
obj_values = (obj[attr_name] for obj in @_obj)
|
|
25
|
+
for expected_value in expected_values
|
|
26
|
+
expect(obj_values).to.include expected_value
|
|
27
|
+
|
|
28
|
+
|
|
4
29
|
describe 'PersistenceManager', ->
|
|
5
30
|
|
|
6
31
|
beforeEach ->
|
|
@@ -10,28 +35,53 @@ describe 'PersistenceManager', ->
|
|
|
10
35
|
|
|
11
36
|
describe 'add_to_cache', ->
|
|
12
37
|
|
|
13
|
-
|
|
14
|
-
@result = @persistence_manager.add_to_cache @user_1
|
|
38
|
+
describe 'normal behavior', ->
|
|
15
39
|
|
|
16
|
-
|
|
17
|
-
|
|
40
|
+
beforeEach ->
|
|
41
|
+
@result = @persistence_manager.add_to_cache @user_1
|
|
18
42
|
|
|
19
|
-
|
|
20
|
-
|
|
43
|
+
it 'adds the described entry to the serverside cache', ->
|
|
44
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
21
45
|
|
|
46
|
+
it 'returns nothing', ->
|
|
47
|
+
expect(@result).to.be.undefined
|
|
48
|
+
|
|
49
|
+
describe 'return_editable_version option', ->
|
|
50
|
+
|
|
51
|
+
it 'returns an editable version of the given entry when set', ->
|
|
52
|
+
result = @persistence_manager.add_to_cache @user_1, yes
|
|
53
|
+
expect(result).to.be.an.editable_version_of @user_1
|
|
54
|
+
|
|
55
|
+
it 'returns nothing if not set', ->
|
|
56
|
+
result = @persistence_manager.add_to_cache @user_1, no
|
|
57
|
+
expect(result).to.be.undefined
|
|
22
58
|
|
|
23
59
|
|
|
24
60
|
describe 'add_many_to_cache', ->
|
|
25
61
|
|
|
26
|
-
|
|
27
|
-
@result = @persistence_manager.add_many_to_cache [ @user_1, @user_2 ]
|
|
62
|
+
describe 'normal behavior', ->
|
|
28
63
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
expect(@persistence_manager.get user: @user_2).to.eql @user_2
|
|
64
|
+
beforeEach ->
|
|
65
|
+
@result = @persistence_manager.add_many_to_cache [@user_1, @user_2]
|
|
32
66
|
|
|
33
|
-
|
|
34
|
-
|
|
67
|
+
it 'adds all described entries to the chache', ->
|
|
68
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
69
|
+
expect(@persistence_manager).to.have.cached_user @user_2
|
|
70
|
+
|
|
71
|
+
it 'returns nothing', ->
|
|
72
|
+
expect(@result).to.be.undefined
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
describe 'return_editable_version option', ->
|
|
76
|
+
|
|
77
|
+
it 'returns editable versions of the given entries when set', ->
|
|
78
|
+
result = @persistence_manager.add_many_to_cache [@user_1, @user_2], yes
|
|
79
|
+
expect(result[0]).to.be.an.editable_version_of @user_1
|
|
80
|
+
expect(result[1]).to.be.an.editable_version_of @user_2
|
|
81
|
+
|
|
82
|
+
it 'returns nothing if not set', ->
|
|
83
|
+
result = @persistence_manager.add_many_to_cache [@user_1, @user_2], no
|
|
84
|
+
expect(result).to.be.undefined
|
|
35
85
|
|
|
36
86
|
|
|
37
87
|
|
|
@@ -43,19 +93,17 @@ describe 'PersistenceManager', ->
|
|
|
43
93
|
@result = @persistence_manager.create @user_1
|
|
44
94
|
|
|
45
95
|
it 'creates the entry on the server', ->
|
|
46
|
-
expect(@server_create_api).to.have.been.
|
|
47
|
-
expect(@server_create_api).to.have.been.calledWith @user_1
|
|
96
|
+
expect(@server_create_api).to.have.been.calledOnceWith @user_1
|
|
48
97
|
|
|
49
98
|
it 'adds the server response to the cache', ->
|
|
50
|
-
expect(@persistence_manager
|
|
99
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
51
100
|
|
|
52
101
|
it 'returns nothing', ->
|
|
53
102
|
expect(@result).to.be.undefined
|
|
54
103
|
|
|
55
104
|
it 'calls the given callback with an editable version of the created entry when done', (done) ->
|
|
56
105
|
@persistence_manager.create @user_1, (result) =>
|
|
57
|
-
expect(result).to.
|
|
58
|
-
expect(result).to.not.equal @user_1
|
|
106
|
+
expect(result).to.be.an.editable_version_of @user_1
|
|
59
107
|
done()
|
|
60
108
|
|
|
61
109
|
|
|
@@ -67,12 +115,11 @@ describe 'PersistenceManager', ->
|
|
|
67
115
|
@result = @persistence_manager.create_many [@user_1, @user_2]
|
|
68
116
|
|
|
69
117
|
it 'creates the entries on the server', ->
|
|
70
|
-
expect(@server_create_many_api).to.have.been.
|
|
71
|
-
expect(@server_create_many_api).to.have.been.calledWith [@user_1, @user_2]
|
|
118
|
+
expect(@server_create_many_api).to.have.been.calledOnceWith [@user_1, @user_2]
|
|
72
119
|
|
|
73
120
|
it 'adds the server response to the cache', ->
|
|
74
|
-
expect(@persistence_manager
|
|
75
|
-
expect(@persistence_manager
|
|
121
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
122
|
+
expect(@persistence_manager).to.have.cached_user @user_2
|
|
76
123
|
|
|
77
124
|
it 'returns nothing', ->
|
|
78
125
|
expect(@result).to.be.undefined
|
|
@@ -92,11 +139,10 @@ describe 'PersistenceManager', ->
|
|
|
92
139
|
done()
|
|
93
140
|
|
|
94
141
|
it 'removes the given entry from the cache', ->
|
|
95
|
-
|
|
142
|
+
expect(@persistence_manager).to.not.have.cached_user @user_1
|
|
96
143
|
|
|
97
144
|
it 'removes the given entry from the server', ->
|
|
98
|
-
expect(@server_delete_api).to.have.been.
|
|
99
|
-
expect(@server_delete_api).to.have.been.calledWith @user_1
|
|
145
|
+
expect(@server_delete_api).to.have.been.calledOnceWith @user_1
|
|
100
146
|
|
|
101
147
|
it 'calls the given callback with a description of the deleted entry', ->
|
|
102
148
|
expect(@result).to.eql username: 'one'
|
|
@@ -111,12 +157,11 @@ describe 'PersistenceManager', ->
|
|
|
111
157
|
@persistence_manager.delete_many [@user_1, @user_2], (@result) => done()
|
|
112
158
|
|
|
113
159
|
it 'removes the given entries from the cache', ->
|
|
114
|
-
expect(@persistence_manager
|
|
115
|
-
expect(@persistence_manager
|
|
160
|
+
expect(@persistence_manager).to.not.have.cached_user @user_1
|
|
161
|
+
expect(@persistence_manager).to.not.have.cached_user @user_2
|
|
116
162
|
|
|
117
163
|
it 'removes the given entry from the server', ->
|
|
118
|
-
expect(@server_delete_many_api).to.have.been.
|
|
119
|
-
expect(@server_delete_many_api).to.have.been.calledWith [@user_1, @user_2]
|
|
164
|
+
expect(@server_delete_many_api).to.have.been.calledOnceWith [@user_1, @user_2]
|
|
120
165
|
|
|
121
166
|
it 'calls the given callback with a description of the deleted entries', ->
|
|
122
167
|
expect(@result).to.eql usernames: ['one', 'two']
|
|
@@ -131,7 +176,7 @@ describe 'PersistenceManager', ->
|
|
|
131
176
|
@persistence_manager.add_to_cache @user_1
|
|
132
177
|
|
|
133
178
|
it 'returns the described entry from the cache if it exists there', ->
|
|
134
|
-
expect(@persistence_manager
|
|
179
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
135
180
|
|
|
136
181
|
it 'returns undefined if the described entry is not cached', ->
|
|
137
182
|
expect(@persistence_manager.get user: @user_2).to.be.undefined
|
|
@@ -213,7 +258,7 @@ describe 'PersistenceManager', ->
|
|
|
213
258
|
expect(@result.found).to.eql [@partial_user_1, @full_user_2]
|
|
214
259
|
|
|
215
260
|
it 'returns the ids of missing entries as missing', ->
|
|
216
|
-
expect(@result.missing
|
|
261
|
+
expect(@result.missing).to.eql_query usernames: ['three'], full: no
|
|
217
262
|
|
|
218
263
|
context 'full entries requested', ->
|
|
219
264
|
|
|
@@ -225,7 +270,7 @@ describe 'PersistenceManager', ->
|
|
|
225
270
|
expect(@result.found).to.eql [@full_user_2]
|
|
226
271
|
|
|
227
272
|
it 'returns partial and missing entries as missing', ->
|
|
228
|
-
expect(@result.missing
|
|
273
|
+
expect(@result.missing).to.eql_query usernames: ['one', 'three'], full: yes
|
|
229
274
|
|
|
230
275
|
|
|
231
276
|
describe 'versioning', ->
|
|
@@ -238,7 +283,7 @@ describe 'PersistenceManager', ->
|
|
|
238
283
|
|
|
239
284
|
it 'returns only results of the right version', ->
|
|
240
285
|
expect(@result.found).to.eql [@user_2]
|
|
241
|
-
expect(@result.missing
|
|
286
|
+
expect(@result.missing).to.eql_query users: [@user_1]
|
|
242
287
|
|
|
243
288
|
|
|
244
289
|
describe 'load', ->
|
|
@@ -262,6 +307,26 @@ describe 'PersistenceManager', ->
|
|
|
262
307
|
it 'does not query the server', ->
|
|
263
308
|
expect(@persistence_manager.server_api.read).to.not.have.been.called
|
|
264
309
|
|
|
310
|
+
context 'described entry is currently loading', ->
|
|
311
|
+
|
|
312
|
+
beforeEach ->
|
|
313
|
+
@persistence_manager.loading_tracker.start_loading @user_1
|
|
314
|
+
@callback = sinon.stub()
|
|
315
|
+
@persistence_manager.load user: @user_1, @callback
|
|
316
|
+
|
|
317
|
+
it 'does not make another load operation to the server', ->
|
|
318
|
+
expect(@server_read_api).to.not.have.been.called
|
|
319
|
+
|
|
320
|
+
it 'calls the callback with the entry when the entry returns from the server', ->
|
|
321
|
+
expect(@callback).to.not.have.been.called
|
|
322
|
+
@persistence_manager.loading_tracker.entry_arrived @user_1
|
|
323
|
+
expect(@callback).to.have.been.calledOnceWith @user_1
|
|
324
|
+
|
|
325
|
+
it 'adds the loaded entry to the clientside cache', ->
|
|
326
|
+
@persistence_manager.loading_tracker.entry_arrived @user_1
|
|
327
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
328
|
+
|
|
329
|
+
|
|
265
330
|
context 'described entry is not in the cache', ->
|
|
266
331
|
|
|
267
332
|
beforeEach (done) ->
|
|
@@ -271,15 +336,13 @@ describe 'PersistenceManager', ->
|
|
|
271
336
|
|
|
272
337
|
it 'loads the entry from the server', ->
|
|
273
338
|
server_read_api = @persistence_manager.server_api.read
|
|
274
|
-
expect(server_read_api).to.have.been.
|
|
275
|
-
expect(server_read_api.args[0][0].to_hash()).to.eql user: @user_1
|
|
339
|
+
expect(server_read_api).to.have.been.calledOnceWithQuery user: @user_1
|
|
276
340
|
|
|
277
341
|
it 'adds the loaded entry to the cache', ->
|
|
278
|
-
expect(@persistence_manager
|
|
342
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
279
343
|
|
|
280
344
|
it 'returns an editable copy of the entry loaded from the server', ->
|
|
281
|
-
expect(@result).to.
|
|
282
|
-
expect(@result).to.not.equal @user_1
|
|
345
|
+
expect(@result).to.be.an.editable_version_of @user_1
|
|
283
346
|
|
|
284
347
|
|
|
285
348
|
describe 'partial entry functionality', ->
|
|
@@ -387,16 +450,17 @@ describe 'PersistenceManager', ->
|
|
|
387
450
|
expect(@result).to.eql @user_1
|
|
388
451
|
|
|
389
452
|
it 'updates the cache with the newly loaded entry version', ->
|
|
390
|
-
expect(@persistence_manager
|
|
453
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
391
454
|
|
|
392
455
|
|
|
393
456
|
|
|
394
457
|
describe 'load_many', ->
|
|
395
458
|
|
|
396
|
-
|
|
459
|
+
beforeEach ->
|
|
460
|
+
@server_read_many_api = sinon.stub @persistence_manager.server_api, 'read_many'
|
|
397
461
|
|
|
398
|
-
|
|
399
|
-
|
|
462
|
+
|
|
463
|
+
describe 'normal functionality', ->
|
|
400
464
|
|
|
401
465
|
context 'all snippets are in the cache', ->
|
|
402
466
|
|
|
@@ -422,18 +486,18 @@ describe 'PersistenceManager', ->
|
|
|
422
486
|
@server_read_many_api.yields users: [@user_2_from_server]
|
|
423
487
|
|
|
424
488
|
it 'returns all requested snippets', (done) ->
|
|
425
|
-
@persistence_manager.load_many users: [@user_1,
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
expect(
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
489
|
+
@persistence_manager.load_many users: [@user_1,
|
|
490
|
+
@user_2,
|
|
491
|
+
@user_3], (users) =>
|
|
492
|
+
expect(users).to.have.entries_with_matching_properties 'username',
|
|
493
|
+
[ 'one',
|
|
494
|
+
'two',
|
|
495
|
+
'three' ]
|
|
496
|
+
done()
|
|
432
497
|
|
|
433
498
|
it 'loads the missing snippets from the server', (done) ->
|
|
434
499
|
@persistence_manager.load_many users: [@user_1, @user_2, @user_3], (users) =>
|
|
435
|
-
|
|
436
|
-
expect(server_args).to.eql users: [@user_2]
|
|
500
|
+
expect(@server_read_many_api).to.have.been.calledOnceWithQuery users: [@user_2]
|
|
437
501
|
done()
|
|
438
502
|
|
|
439
503
|
it 'adds the loaded entries to the cache', ->
|
|
@@ -442,7 +506,6 @@ describe 'PersistenceManager', ->
|
|
|
442
506
|
expect(users[0]).to.not.equal @user_2_from_server
|
|
443
507
|
|
|
444
508
|
|
|
445
|
-
|
|
446
509
|
describe 'partial entry functionality', ->
|
|
447
510
|
|
|
448
511
|
beforeEach ->
|
|
@@ -468,12 +531,10 @@ describe 'PersistenceManager', ->
|
|
|
468
531
|
expect(@persistence_manager.get username: 'two').to.eql @full_user_2
|
|
469
532
|
|
|
470
533
|
it 'returns the full entries', ->
|
|
471
|
-
expect(@result).to.have.
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
expect(emails).to.include 'three@example.com'
|
|
476
|
-
|
|
534
|
+
expect(@result).to.have.entries_with_matching_properties 'email',
|
|
535
|
+
[ 'one@example.com',
|
|
536
|
+
'two@example.com',
|
|
537
|
+
'three@example.com' ]
|
|
477
538
|
|
|
478
539
|
context 'partial entries requested', ->
|
|
479
540
|
|
|
@@ -504,13 +565,59 @@ describe 'PersistenceManager', ->
|
|
|
504
565
|
expect(@result).to.eql [@user_2, @user_1]
|
|
505
566
|
|
|
506
567
|
it 'loads only outdated entries from the server', ->
|
|
507
|
-
expect(@server_read_many_api).to.have.been.
|
|
508
|
-
expect(@server_read_many_api.args[0][0].to_hash()).to.eql users: [@user_1]
|
|
568
|
+
expect(@server_read_many_api).to.have.been.calledOnceWithQuery users: [@user_1]
|
|
509
569
|
|
|
510
570
|
it 'adds the loaded entries to the cache', ->
|
|
511
571
|
expect(@persistence_manager.get username: 'one').to.eql @user_1
|
|
512
572
|
|
|
513
573
|
|
|
574
|
+
describe 'loading tracking', ->
|
|
575
|
+
|
|
576
|
+
context 'some entries are currently loading', ->
|
|
577
|
+
|
|
578
|
+
beforeEach ->
|
|
579
|
+
@persistence_manager.loading_tracker.start_loadings users: [@user_1, @user_2]
|
|
580
|
+
@callback = sinon.stub()
|
|
581
|
+
@persistence_manager.load_many users: [@user_1, @user_2], @callback
|
|
582
|
+
|
|
583
|
+
it 'does not make another load operation to the server', ->
|
|
584
|
+
expect(@server_read_many_api).to.not.have.been.called
|
|
585
|
+
|
|
586
|
+
it 'calls the callback with the entries when they arrive', ->
|
|
587
|
+
expect(@callback).to.not.have.been.called
|
|
588
|
+
@persistence_manager.loading_tracker.entries_arrived [@user_1, @user_2]
|
|
589
|
+
expect(@callback).to.have.been.calledOnceWith [@user_1, @user_2]
|
|
590
|
+
|
|
591
|
+
it 'adds the loaded result to the cache', ->
|
|
592
|
+
@persistence_manager.loading_tracker.entries_arrived [@user_1, @user_2]
|
|
593
|
+
expect(@persistence_manager).to.have.cached_user @user_1
|
|
594
|
+
expect(@persistence_manager).to.have.cached_user @user_2
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
describe 'all options working together', ->
|
|
598
|
+
|
|
599
|
+
beforeEach ->
|
|
600
|
+
@persistence_manager.add_to_cache @user_1
|
|
601
|
+
@persistence_manager.loading_tracker.start_loadings users: [@user_2]
|
|
602
|
+
@callback = sinon.stub()
|
|
603
|
+
@server_read_many_api.yields users: [@user_3]
|
|
604
|
+
@persistence_manager.load_many users: [@user_1, @user_2, @user_3],
|
|
605
|
+
@callback
|
|
606
|
+
@persistence_manager.loading_tracker.entries_arrived [@user_2]
|
|
607
|
+
|
|
608
|
+
it 'returns all requested entries', ->
|
|
609
|
+
expect(@callback).to.have.been.calledOnce
|
|
610
|
+
callback_args = @callback.args[0][0]
|
|
611
|
+
expect(callback_args).to.be.entries_with_matching_properties 'username',
|
|
612
|
+
[ 'one',
|
|
613
|
+
'two',
|
|
614
|
+
'three' ]
|
|
615
|
+
|
|
616
|
+
it 'loads only the not currently loading entries from the server', ->
|
|
617
|
+
expect(@server_read_many_api).to.have.been.calledOnceWithQuery users: [@user_3]
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
|
|
514
621
|
describe 'merge', ->
|
|
515
622
|
|
|
516
623
|
beforeEach ->
|
|
@@ -528,9 +635,9 @@ describe 'PersistenceManager', ->
|
|
|
528
635
|
expect(@server_merge_api).to.have.been.calledOnce
|
|
529
636
|
|
|
530
637
|
it 'removes the old users from the client cache', ->
|
|
531
|
-
expect(@persistence_manager
|
|
532
|
-
expect(@persistence_manager
|
|
533
|
-
expect(@persistence_manager
|
|
638
|
+
expect(@persistence_manager).to.not.have.cached_user @user_1
|
|
639
|
+
expect(@persistence_manager).to.not.have.cached_user @user_2
|
|
640
|
+
expect(@persistence_manager).to.have.cached_user @user_3
|
|
534
641
|
|
|
535
642
|
it 'adds the user provided by the server to the client cache', ->
|
|
536
643
|
cached_user = @persistence_manager.get user: @merged_user_server_response
|
|
@@ -541,8 +648,7 @@ describe 'PersistenceManager', ->
|
|
|
541
648
|
|
|
542
649
|
it 'returns the editable user in the callback', ->
|
|
543
650
|
callback_args = @callback.args[0][0]
|
|
544
|
-
expect(callback_args).to.
|
|
545
|
-
expect(callback_args).to.not.equal @merged_user_server_response
|
|
651
|
+
expect(callback_args).to.be.an.editable_version_of @merged_user_server_response
|
|
546
652
|
|
|
547
653
|
|
|
548
654
|
|
|
@@ -577,12 +683,11 @@ describe 'PersistenceManager', ->
|
|
|
577
683
|
@persistence_manager.update @user, (@result) => done()
|
|
578
684
|
|
|
579
685
|
it 'calls the server with only the changed attributes as payload', ->
|
|
580
|
-
expect(@server_update_api).to.have.been.
|
|
581
|
-
expect(@server_update_api).to.have.been.calledWith
|
|
686
|
+
expect(@server_update_api).to.have.been.calledOnceWith
|
|
582
687
|
username: 'one', email: 'new_one@example.com'
|
|
583
688
|
|
|
584
|
-
it 'calls the callback with the
|
|
585
|
-
expect(@result).to.
|
|
689
|
+
it 'calls the callback with the editable version of the updated entry', ->
|
|
690
|
+
expect(@result).to.be.an.editable_version_of @user
|
|
586
691
|
|
|
587
692
|
it 'stores the now persisted changes on the client', (done) ->
|
|
588
693
|
@persistence_manager.update @user, =>
|