
- Complete NestJS TypeScript implementation with WebSocket support - Direct messaging (DM) and group chat functionality - End-to-end encryption with AES encryption and key pairs - Media file support (images, videos, audio, documents) up to 100MB - Push notifications with Firebase Cloud Messaging integration - Mention alerts and real-time typing indicators - User authentication with JWT and Passport - SQLite database with TypeORM entities and relationships - Comprehensive API documentation with Swagger/OpenAPI - File upload handling with secure access control - Online/offline status tracking and presence management - Message editing, deletion, and reply functionality - Notification management with automatic cleanup - Health check endpoint for monitoring - CORS configuration for cross-origin requests - Environment-based configuration management - Structured for Flutter SDK integration Features implemented: ✅ Real-time messaging with Socket.IO ✅ User registration and authentication ✅ Direct messages and group chats ✅ Media file uploads and management ✅ End-to-end encryption ✅ Push notifications ✅ Mention alerts ✅ Typing indicators ✅ Message read receipts ✅ Online status tracking ✅ File access control ✅ Comprehensive API documentation Ready for Flutter SDK development and production deployment.
264 lines
7.2 KiB
JavaScript
264 lines
7.2 KiB
JavaScript
'use strict';
|
|
|
|
var expect = require('expect.js');
|
|
var promiseRetry = require('../');
|
|
var promiseDelay = require('sleep-promise');
|
|
|
|
describe('promise-retry', function () {
|
|
it('should call fn again if retry was called', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry) {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
if (count <= 2) {
|
|
retry(new Error('foo'));
|
|
}
|
|
|
|
return 'final';
|
|
});
|
|
}, { factor: 1 })
|
|
.then(function (value) {
|
|
expect(value).to.be('final');
|
|
expect(count).to.be(3);
|
|
}, function () {
|
|
throw new Error('should not fail');
|
|
});
|
|
});
|
|
|
|
it('should call fn with the attempt number', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry, number) {
|
|
count += 1;
|
|
expect(count).to.equal(number);
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
if (count <= 2) {
|
|
retry(new Error('foo'));
|
|
}
|
|
|
|
return 'final';
|
|
});
|
|
}, { factor: 1 })
|
|
.then(function (value) {
|
|
expect(value).to.be('final');
|
|
expect(count).to.be(3);
|
|
}, function () {
|
|
throw new Error('should not fail');
|
|
});
|
|
});
|
|
|
|
it('should not retry on fulfillment if retry was not called', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function () {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
return 'final';
|
|
});
|
|
})
|
|
.then(function (value) {
|
|
expect(value).to.be('final');
|
|
expect(count).to.be(1);
|
|
}, function () {
|
|
throw new Error('should not fail');
|
|
});
|
|
});
|
|
|
|
it('should not retry on rejection if retry was not called', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function () {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
throw new Error('foo');
|
|
});
|
|
})
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err.message).to.be('foo');
|
|
expect(count).to.be(1);
|
|
});
|
|
});
|
|
|
|
it('should not retry on rejection if nr of retries is 0', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry) {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
throw new Error('foo');
|
|
})
|
|
.catch(retry);
|
|
}, { retries : 0 })
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err.message).to.be('foo');
|
|
expect(count).to.be(1);
|
|
});
|
|
});
|
|
|
|
it('should reject the promise if the retries were exceeded', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry) {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
throw new Error('foo');
|
|
})
|
|
.catch(retry);
|
|
}, { retries: 2, factor: 1 })
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err.message).to.be('foo');
|
|
expect(count).to.be(3);
|
|
});
|
|
});
|
|
|
|
it('should pass options to the underlying retry module', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry) {
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
if (count < 2) {
|
|
count += 1;
|
|
retry(new Error('foo'));
|
|
}
|
|
|
|
return 'final';
|
|
});
|
|
}, { retries: 1, factor: 1 })
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err.message).to.be('foo');
|
|
});
|
|
});
|
|
|
|
it('should convert direct fulfillments into promises', function () {
|
|
return promiseRetry(function () {
|
|
return 'final';
|
|
}, { factor: 1 })
|
|
.then(function (value) {
|
|
expect(value).to.be('final');
|
|
}, function () {
|
|
throw new Error('should not fail');
|
|
});
|
|
});
|
|
|
|
it('should convert direct rejections into promises', function () {
|
|
promiseRetry(function () {
|
|
throw new Error('foo');
|
|
}, { retries: 1, factor: 1 })
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err.message).to.be('foo');
|
|
});
|
|
});
|
|
|
|
it('should not crash on undefined rejections', function () {
|
|
return promiseRetry(function () {
|
|
throw undefined;
|
|
}, { retries: 1, factor: 1 })
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err).to.be(undefined);
|
|
})
|
|
.then(function () {
|
|
return promiseRetry(function (retry) {
|
|
retry();
|
|
}, { retries: 1, factor: 1 });
|
|
})
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err).to.be(undefined);
|
|
});
|
|
});
|
|
|
|
it('should retry if retry() was called with undefined', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry) {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
if (count <= 2) {
|
|
retry();
|
|
}
|
|
|
|
return 'final';
|
|
});
|
|
}, { factor: 1 })
|
|
.then(function (value) {
|
|
expect(value).to.be('final');
|
|
expect(count).to.be(3);
|
|
}, function () {
|
|
throw new Error('should not fail');
|
|
});
|
|
});
|
|
|
|
it('should work with several retries in the same chain', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry(function (retry) {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
retry(new Error('foo'));
|
|
})
|
|
.catch(function (err) {
|
|
retry(err);
|
|
});
|
|
}, { retries: 1, factor: 1 })
|
|
.then(function () {
|
|
throw new Error('should not succeed');
|
|
}, function (err) {
|
|
expect(err.message).to.be('foo');
|
|
expect(count).to.be(2);
|
|
});
|
|
});
|
|
|
|
it('should allow options to be passed first', function () {
|
|
var count = 0;
|
|
|
|
return promiseRetry({ factor: 1 }, function (retry) {
|
|
count += 1;
|
|
|
|
return promiseDelay(10)
|
|
.then(function () {
|
|
if (count <= 2) {
|
|
retry(new Error('foo'));
|
|
}
|
|
|
|
return 'final';
|
|
});
|
|
}).then(function (value) {
|
|
expect(value).to.be('final');
|
|
expect(count).to.be(3);
|
|
}, function () {
|
|
throw new Error('should not fail');
|
|
});
|
|
});
|
|
});
|