├── .babelrc ├── .eslintrc ├── .gitignore ├── .travis.yml ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── __tests__ └── promisepromise.spec.js ├── dist ├── promisepromise.js └── umd │ └── promisepromise.min.js ├── excuses.js ├── index.js ├── package.json ├── rollup.config.js └── rollup.prod.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "xo", 3 | "rules": { 4 | "padded-blocks": ["off"], 5 | "operator-assignment": ["off"], 6 | "eqeqeq": ["error", "allow-null"], 7 | "no-eq-null": ["off"], 8 | "quote-props": ["error", "as-needed"], 9 | "curly": "off" 10 | }, 11 | "env": { 12 | "browser": true, 13 | "node": true, 14 | "jest": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | node_modules/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '7' 4 | - '6' 5 | cache: 6 | yarn: true 7 | directories: 8 | - node_modules 9 | after_success: 10 | - npm run coveralls -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.autoFixOnSave": false, 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/.svn": true, 6 | "**/.hg": true, 7 | "**/.DS_Store": true, 8 | "**/coverage": true, 9 | "**/node_modules": true, 10 | "**/.vscode": true, 11 | "**/dist": true, 12 | "**/.**": false 13 | } 14 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) René Viering (rene.js.org) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![such bull](https://img.shields.io/badge/such-bull-1393d5.svg?style=flat)](https://bullg.it/) 2 | [![much git](https://img.shields.io/badge/very-git-7ED321.svg?style=flat)](https://bullg.it/) 3 | 4 | [![npm version](https://badge.fury.io/js/promise-promise.svg)](http://badge.fury.io/js/promise-promise) 5 | [![Build Status](https://travis-ci.org/bullgit/promise-promise.svg?branch=master)](https://travis-ci.org/bullgit/promise-promise) 6 | [![Coverage Status](https://coveralls.io/repos/github/bullgit/promise-promise/badge.svg?branch=master)](https://coveralls.io/github/bullgit/promise-promise?branch=master) 7 | [![devDependency Status](https://david-dm.org/bullgit/promise-promise/dev-status.svg?theme=shields.io)](https://david-dm.org/bullgit/promise-promise#info=devDependencies) 8 | [![Unicorn](https://img.shields.io/badge/unicorn-approved-ff69b4.svg?style=flat)](https://www.youtube.com/watch?v=qRC4Vk6kisY) 9 | 10 | # promise-promise 11 | 12 | > A funny Promise wrapper for those who can't keep promises. There's a 50:50 chance that the promise will be fulfilled. If not, it rejects with a random developer excuse. 😎😇 Good luck 🙈 13 | 14 | ## Install 15 | 16 | ``` 17 | $ npm install promise-promise --save 18 | ``` 19 | 20 | ## Usage 21 | 22 | ```javascript 23 | import Promise from 'promise-promise'; 24 | 25 | const myAsyncOperation = new Promise(resolve => { 26 | resolve('I should resolve 😱'); 27 | }); 28 | 29 | 30 | myAsyncOperation 31 | .then(response => { 32 | console.log(response); // Sometimes it resolves 33 | }) 34 | .catch(error => { 35 | console.log(err); // Sometimes not 😎 36 | }); 37 | ``` 38 | 39 | ## License 40 | MIT © [René Viering](http://rene.js.org) 41 | -------------------------------------------------------------------------------- /__tests__/promisepromise.spec.js: -------------------------------------------------------------------------------- 1 | import PromisePromise from '../index'; 2 | import excuses from '../excuses'; 3 | 4 | const fakeAsyncOperation = ({ 5 | dataToResolve, 6 | dataToReject, 7 | shouldResolve 8 | }) => { 9 | return (resolve, reject) => { 10 | if (shouldResolve) { 11 | resolve(dataToResolve); 12 | } else { 13 | reject(dataToReject); 14 | } 15 | }; 16 | } 17 | 18 | describe('PromisePromise', () => { 19 | test('it exists', () => { 20 | expect(new PromisePromise(() => {})).toBeDefined(); 21 | }) 22 | 23 | test('makes a random decision about fulfilling or rejecting the promise. If rejecting it returns an excuse', () => { 24 | let countFulfilling = 0; 25 | let countRejecting = 0; 26 | 27 | const times = x => f => { 28 | if (x > 0) { 29 | f() 30 | times(x - 1)(f) 31 | } 32 | } 33 | 34 | const generatePromise = () => { 35 | return new PromisePromise((resolve, reject) => { 36 | resolve('Actually the promise should always be fulfilled!') 37 | }) 38 | .then(() => ++countFulfilling) 39 | .catch(err => { 40 | ++countRejecting; 41 | expect(excuses.includes(err)).toBe(true); 42 | }); 43 | }; 44 | 45 | const promises = []; 46 | times(100)(() => { 47 | promises.push(generatePromise()); 48 | }); 49 | 50 | return Promise.all(promises) 51 | .then(() => { 52 | expect(countFulfilling).toBeGreaterThan(0); 53 | expect(countRejecting).toBeGreaterThan(0); 54 | }); 55 | }); 56 | 57 | test('rejects the promise if it should actually be rejected', () => { 58 | const dataToReject = 'Reject...'; 59 | const shouldResolve = false; 60 | const asyncOperation = fakeAsyncOperation({dataToReject, shouldResolve}) 61 | return new PromisePromise(asyncOperation) 62 | .then(() => {}) 63 | .catch(err => expect(err).toEqual(dataToReject)); 64 | }); 65 | 66 | }); 67 | -------------------------------------------------------------------------------- /dist/promisepromise.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var excuses = ['You must be missing some of the dependencies', 'How is that possible?', 'I couldn\'t find any library that can even do that', 'That wouldn\'t have made economic sense.', 'The project manager told me to do it that way.', 'Try rebooting your router.', 'Are you sure?', 'That\'s a problem with the hosts.', 'It wasn\'t in the spec.', 'The person responsible doesn\'t work here any more.', 'Probably down to the leap year.', 'That code was written by an old developer.', 'Well I\'m surprised it is even working at all.', 'I must have misunderstood.', 'It isn\'t in my ticketing system.', 'Try rebotting.', 'You\'re doing it wrong.', 'It worked fine for me when I developed it.', 'We didn\'t write that part.', 'It\'s always been like that.']; 4 | 5 | var classCallCheck = function (instance, Constructor) { 6 | if (!(instance instanceof Constructor)) { 7 | throw new TypeError("Cannot call a class as a function"); 8 | } 9 | }; 10 | 11 | var getRandomExcuse = function getRandomExcuse() { 12 | return excuses[Math.floor(Math.random() * excuses.length)]; 13 | }; 14 | 15 | var PromisePromise = function PromisePromise(init) { 16 | classCallCheck(this, PromisePromise); 17 | 18 | var promise = new Promise(init); 19 | return new Promise(function (resolve, reject) { 20 | promise.then(function (response) { 21 | var shouldResolve = Math.random() >= 0.5; 22 | if (shouldResolve) { 23 | resolve(response); 24 | } else { 25 | reject(getRandomExcuse()); 26 | } 27 | }).catch(function (err) { 28 | resolve(err); 29 | }); 30 | }); 31 | }; 32 | 33 | module.exports = PromisePromise; 34 | -------------------------------------------------------------------------------- /dist/umd/promisepromise.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.promisePromise=t()}(this,function(){"use strict";var e=["You must be missing some of the dependencies","How is that possible?","I couldn't find any library that can even do that","That wouldn't have made economic sense.","The project manager told me to do it that way.","Try rebooting your router.","Are you sure?","That's a problem with the hosts.","It wasn't in the spec.","The person responsible doesn't work here any more.","Probably down to the leap year.","That code was written by an old developer.","Well I'm surprised it is even working at all.","I must have misunderstood.","It isn't in my ticketing system.","Try rebotting.","You're doing it wrong.","It worked fine for me when I developed it.","We didn't write that part.","It's always been like that."],t=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=function(){return e[Math.floor(Math.random()*e.length)]},o=function e(o){t(this,e);var r=new Promise(o);return new Promise(function(e,t){r.then(function(o){var r=Math.random()>=.5;r?e(o):t(n())}).catch(function(t){e(t)})})};return o}); 2 | -------------------------------------------------------------------------------- /excuses.js: -------------------------------------------------------------------------------- 1 | const excuses = [ 2 | 'You must be missing some of the dependencies', 3 | 'How is that possible?', 4 | 'I couldn\'t find any library that can even do that', 5 | 'That wouldn\'t have made economic sense.', 6 | 'The project manager told me to do it that way.', 7 | 'Try rebooting your router.', 8 | 'Are you sure?', 9 | 'That\'s a problem with the hosts.', 10 | 'It wasn\'t in the spec.', 11 | 'The person responsible doesn\'t work here any more.', 12 | 'Probably down to the leap year.', 13 | 'That code was written by an old developer.', 14 | 'Well I\'m surprised it is even working at all.', 15 | 'I must have misunderstood.', 16 | 'It isn\'t in my ticketing system.', 17 | 'Try rebotting.', 18 | 'You\'re doing it wrong.', 19 | 'It worked fine for me when I developed it.', 20 | 'We didn\'t write that part.', 21 | 'It\'s always been like that.' 22 | ]; 23 | 24 | export default excuses; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import excuses from './excuses'; 2 | 3 | const getRandomExcuse = () => { 4 | return excuses[Math.floor(Math.random() * excuses.length)]; 5 | }; 6 | 7 | export default class PromisePromise { 8 | constructor(init) { 9 | const promise = new Promise(init); 10 | return new Promise((resolve, reject) => { 11 | promise 12 | .then(response => { 13 | const shouldResolve = Math.random() >= 0.5; 14 | if (shouldResolve) { 15 | resolve(response); 16 | } else { 17 | reject(getRandomExcuse()); 18 | } 19 | }) 20 | .catch(err => { 21 | resolve(err); 22 | }); 23 | }); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "promise-promise", 3 | "version": "1.0.6", 4 | "description": "A funny Promise API for those who can't keep promises.", 5 | "main": "dist/promisepromise.js", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "test:dev": "jest --watch", 9 | "test:cov": "jest --coverage", 10 | "build": "rollup -c && rollup -c rollup.prod.config.js", 11 | "build:dev": "rollup -c rollup.prod.config.js", 12 | "build:prod": "rollup -c rollup.prod.config.js", 13 | "coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls" 14 | }, 15 | "files": [ 16 | "dist", 17 | "index.js", 18 | "excuses.js" 19 | ], 20 | "author": "René Viering", 21 | "repository": "bullgit/promise-promise", 22 | "license": "MIT", 23 | "devDependencies": { 24 | "babel-jest": "^18.0.0", 25 | "babel-preset-es2015-rollup": "^3.0.0", 26 | "coveralls": "^2.11.15", 27 | "eslint": "^3.11.1", 28 | "eslint-config-xo": "^0.17.0", 29 | "jest": "^18.1.0", 30 | "rollup": "^0.38.3", 31 | "rollup-plugin-babel": "^2.6.1", 32 | "rollup-plugin-commonjs": "^7.0.0", 33 | "rollup-plugin-node-resolve": "^2.0.0", 34 | "rollup-plugin-sourcemaps": "^0.4.1", 35 | "rollup-plugin-uglify": "^1.0.1" 36 | }, 37 | "keywords": [ 38 | "promises", 39 | "es6", 40 | "funny", 41 | "bullgit" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import resolve from 'rollup-plugin-node-resolve'; 3 | import commonjs from 'rollup-plugin-commonjs'; 4 | import sourcemaps from 'rollup-plugin-sourcemaps'; 5 | 6 | export default { 7 | entry: 'index.js', 8 | dest: 'dist/promisepromise.js', 9 | format: 'cjs', 10 | moduleName: 'promisePromise', 11 | sourceMap: false, 12 | plugins: [ 13 | resolve({ 14 | jsnext: true, 15 | main: true, 16 | browser: true 17 | }), 18 | commonjs(), 19 | babel({ 20 | babelrc: false, 21 | presets: ['es2015-rollup'] 22 | }), 23 | sourcemaps() 24 | ] 25 | }; 26 | -------------------------------------------------------------------------------- /rollup.prod.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import uglify from 'rollup-plugin-uglify'; 3 | import resolve from 'rollup-plugin-node-resolve'; 4 | import commonjs from 'rollup-plugin-commonjs'; 5 | 6 | export default { 7 | entry: 'index.js', 8 | dest: 'dist/umd/promisepromise.min.js', 9 | format: 'umd', 10 | moduleName: 'promisePromise', 11 | plugins: [ 12 | resolve({ 13 | jsnext: true, 14 | main: true, 15 | browser: true 16 | }), 17 | commonjs(), 18 | babel({ 19 | babelrc: false, 20 | presets: ['es2015-rollup'] 21 | }), 22 | uglify() 23 | ] 24 | }; 25 | --------------------------------------------------------------------------------