2
0
mirror of https://github.com/iconify/iconify.git synced 2024-12-22 09:48:54 +00:00

Switch api-redundancy package tests to vitest

This commit is contained in:
Vjacheslav Trushkin 2022-07-08 17:25:44 +03:00
parent 859a77b4bf
commit 97e9677fa4
9 changed files with 1108 additions and 21967 deletions

View File

@ -18,9 +18,7 @@
"lint": "eslint src/*.ts",
"prebuild": "pnpm run lint",
"build": "tsup src/index.ts --dts --format esm,cjs",
"test:jest": "jest --runInBand",
"test:jasmine": "cross-env NODE_OPTIONS=--experimental-vm-modules jasmine",
"test": "pnpm run test:jest && pnpm run test:jasmine"
"test": "vitest --config vitest.config.mjs"
},
"bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/",
@ -36,10 +34,7 @@
"@typescript-eslint/parser": "^5.28.0",
"cross-env": "^7.0.3",
"eslint": "^8.18.0",
"eslint-plugin-jasmine": "^4.1.3",
"jasmine": "^4.2.1",
"jest": "28.0.0-alpha.11",
"ts-jest": "28.0.0-next.3",
"tsup": "^5.12.9"
"tsup": "^5.12.9",
"vitest": "^0.17.1"
}
}

View File

@ -1,116 +0,0 @@
import { initRedundancy } from '@iconify/api-redundancy';
describe('Redundancy class', () => {
it('Simple query', (done) => {
const redundancy = initRedundancy({
resources: [
'https://api.local', // Will fail
'https://api-backup1.local', // Success
'https://api-backup2.local',
],
rotate: 20,
timeout: 100,
});
// Premade responses
const responses = {
'https://api-backup1.local/foo': 'foo',
};
let counter = 0;
let doneCallbackCalled = false;
const query = redundancy.query(
'/foo',
(resource, payload, callback) => {
counter++;
expect(counter).toBeLessThan(3); // No more than 2 queries should be executed
// Make URI from resource + payload
const uri = resource + payload;
// Get fake data if it exists
if (responses[uri] === void 0) {
return;
}
// Do something with "data", simulate instant callback
callback('success', responses[uri]);
// Complete test
setTimeout(() => {
expect(counter).toEqual(2);
expect(doneCallbackCalled).toEqual(true);
expect(query().status).toEqual('completed');
expect(redundancy.getIndex()).toEqual(1); // Should have changed to 1 after query
done();
});
},
(data) => {
expect(data).toEqual('foo');
doneCallbackCalled = true;
}
);
// Test find()
expect(redundancy.find((item) => item().payload === '/foo')).toEqual(
query
);
expect(redundancy.find((item) => item().status === 'pending')).toEqual(
query
);
});
it('Different start index', (done) => {
const redundancy = initRedundancy({
resources: [
'https://api.local',
'https://api-backup1.local',
'https://api-backup2.local',
],
rotate: 20,
timeout: 3000,
index: 1,
});
// Premade responses
const responses = {
'https://api-backup1.local/foo': 'foo',
};
let counter = 0;
const query = redundancy.query(
'/foo',
(resource, payload, callback) => {
counter++;
expect(counter).toBeLessThan(2); // Should be success on first call because start index = 1
// Make URI from resource + payload
const uri = resource + payload;
// Get fake data if it exists
if (responses[uri] === void 0) {
return;
}
// Do something with "data", simulate instant callback
callback('success', responses[uri]);
// Complete test
setTimeout(() => {
expect(counter).toEqual(1);
expect(query().status).toEqual('completed');
expect(redundancy.getIndex()).toEqual(1);
done();
});
}
);
// Test find()
expect(redundancy.find((item) => item().payload === '/foo')).toEqual(
query
);
expect(redundancy.find((item) => item().status === 'pending')).toEqual(
query
);
});
});

View File

@ -1,7 +0,0 @@
{
"spec_dir": "spec",
"spec_files": ["**/*[sS]pec.?(m)js"],
"helpers": ["helpers/**/*.?(m)js"],
"stopSpecOnExpectationFailure": false,
"random": true
}

View File

@ -3,461 +3,473 @@ import type { QueryModuleResponse } from '../src/query';
import { sendQuery } from '../src/query';
describe('Advanced queries with multiple resources', () => {
it('Simple query, time out on first, success on second after third is called, ignore third (~70ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2', 'api3'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 50,
random: false,
dataAfterTimeout: false,
};
it('Simple query, time out on first, success on second after third is called, ignore third (~70ms)', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const resources = ['api1', 'api2', 'api3'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 50,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let secondCallback: QueryModuleResponse;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let secondCallback: QueryModuleResponse;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Query should be executed 3 times
expect(sentQuery).toBeLessThan(3);
expect(resource).toEqual(resources[sentQuery]);
// Query should be executed 3 times
expect(sentQuery).toBeLessThan(3);
expect(resource).toEqual(resources[sentQuery]);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Bump counter
sentQuery++;
// Bump counter
sentQuery++;
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Fail in 20ms
setTimeout(() => {
// Status should not have changed
const status = getStatus();
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Fail
callback('next', true);
}, 20);
return;
// Fail in 20ms
setTimeout(() => {
// Status should not have changed
const status = getStatus();
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
case 2:
// Only second query should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(1);
// Fail
callback('next', true);
}, 20);
return;
// Save item
secondCallback = callback;
return;
case 2:
// Only second query should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(1);
case 3:
// 2nd and 3rd queries should be pending
expect(status.queriesSent).toEqual(3);
expect(status.queriesPending).toEqual(2);
// Save item
secondCallback = callback;
return;
// Complete second item
secondCallback('success', result);
return;
case 3:
// 2nd and 3rd queries should be pending
expect(status.queriesSent).toEqual(3);
expect(status.queriesPending).toEqual(2);
default:
done('This code should not have been reached');
// Complete second item
secondCallback('success', result);
return;
default:
reject('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(3);
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(3);
expect(status.queriesPending).toEqual(0);
// 20ms from first query failing, 50ms from delay between second and third
const diff = Date.now() - startTime;
expect(diff > 50 && diff < 90).toEqual(true);
fulfill(true);
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(3);
);
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(3);
expect(status.queriesPending).toEqual(0);
// 20ms from first query failing, 50ms from delay between second and third
const diff = Date.now() - startTime;
expect(diff > 50 && diff < 90).toEqual(true);
done();
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Multiple delayed responses (~100ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const result1 = {};
const result2 = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 50,
random: false,
dataAfterTimeout: false,
};
it('Multiple delayed responses (~100ms)', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const resources = ['api1', 'api2'];
const result1 = {};
const result2 = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 50,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let firstCallback: QueryModuleResponse;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let firstCallback: QueryModuleResponse;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Query should be executed 2 times
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Query should be executed 2 times
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Bump counter
sentQuery++;
// Bump counter
sentQuery++;
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Store callback
firstCallback = callback;
return;
// Store callback
firstCallback = callback;
return;
case 2:
// Both queries should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(2);
// Complete first item in 20ms (70ms from start), then second item
setTimeout(() => {
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
case 2:
// Both queries should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(2);
firstCallback('success', result1);
// Complete second item in 30 ms
// Complete first item in 20ms (70ms from start), then second item
setTimeout(() => {
// Should not change anything because query is already complete
callback('success', result2);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(2);
// Finish test
done();
}, 30);
}, 20);
return;
firstCallback('success', result1);
default:
done('This code should not have been reached');
// Complete second item in 30 ms
setTimeout(() => {
// Should not change anything because query is already complete
callback('success', result2);
// Finish test
fulfill(true);
}, 30);
}, 20);
return;
default:
reject('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Validate data
expect(data).toEqual(result1);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// 50ms delay between queries, 20ms delay by test timer
const diff = Date.now() - startTime;
expect(diff > 50 && diff < 90).toEqual(true);
// Do not finish: second item is still pending
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
);
// Validate data
expect(data).toEqual(result1);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// 50ms delay between queries, 20ms delay by test timer
const diff = Date.now() - startTime;
expect(diff > 50 && diff < 90).toEqual(true);
// Do not finish: second item is still pending
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Ignored response after time out (~150ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 100,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
it('Ignored response after time out (~150ms)', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 100,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let firstCallback: QueryModuleResponse;
let completeCount = 0;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let firstCallback: QueryModuleResponse;
let completeCount = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Query should be executed 2 times
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Query should be executed 2 times
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Bump counter
sentQuery++;
// Bump counter
sentQuery++;
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Store callback
firstCallback = callback;
return;
// Store callback
firstCallback = callback;
return;
case 2:
// Both queries should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(2);
return;
default:
done('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Bump couneter
completeCount++;
switch (completeCount) {
case 1:
// First call: time out
((): void => {
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
case 2:
// Both queries should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
expect(status.queriesPending).toEqual(2);
return;
// 25ms delay between queries * 2 + 100ms timeout
const diff = Date.now() - startTime;
expect(diff > 130 && diff < 170).toEqual(true);
default:
reject('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Send data from first query, which should be ignored because dataAfterTimeout is false
firstCallback('success', result);
// Bump couneter
completeCount++;
switch (completeCount) {
case 1:
// First call: time out
((): void => {
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Complete test
done();
})();
return;
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
default:
done('Callback should have been called only once');
// 25ms delay between queries * 2 + 100ms timeout
const diff = Date.now() - startTime;
expect(diff > 130 && diff < 170).toEqual(true);
// Send data from first query, which should be ignored because dataAfterTimeout is false
firstCallback('success', result);
// Complete test
fulfill(true);
})();
return;
default:
reject(
'Callback should have been called only once'
);
}
}
}
);
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Response after time out (~150ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 100,
rotate: 25,
random: false,
dataAfterTimeout: true,
};
it('Response after time out (~150ms)', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 100,
rotate: 25,
random: false,
dataAfterTimeout: true,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let firstCallback: QueryModuleResponse;
let completeCount = 0;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
let firstCallback: QueryModuleResponse;
let completeCount = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Query should be executed 2 times
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Query should be executed 2 times
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Bump counter
sentQuery++;
// Bump counter
sentQuery++;
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Tests specific to each query
switch (sentQuery) {
case 1:
// First query
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Store callback
firstCallback = callback;
return;
// Store callback
firstCallback = callback;
return;
case 2:
// Both queries should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(2);
return;
default:
done('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Bump couneter
completeCount++;
switch (completeCount) {
case 1:
// First call: time out
((): void => {
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
case 2:
// Both queries should be pending
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
expect(status.queriesPending).toEqual(2);
return;
// 25ms delay between queries * 2 + 100ms timeout
const diff = Date.now() - startTime;
expect(diff > 130 && diff < 170).toEqual(true);
default:
reject('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Send data from first query
firstCallback('success', result);
})();
return;
// Bump couneter
completeCount++;
switch (completeCount) {
case 1:
// First call: time out
((): void => {
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
case 2:
// Second call: data
((): void => {
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// 25ms delay between queries * 2 + 100ms timeout
const diff = Date.now() - startTime;
expect(diff > 130 && diff < 170).toEqual(true);
// Same as few lines above
const diff = Date.now() - startTime;
expect(diff > 130 && diff < 170).toEqual(true);
// Send data from first query
firstCallback('success', result);
})();
return;
// Done
done();
})();
return;
case 2:
// Second call: data
((): void => {
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
default:
done('Callback should have been called only twice');
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// Same as few lines above
const diff = Date.now() - startTime;
expect(diff > 130 && diff < 170).toEqual(true);
// Done
fulfill(true);
})();
return;
default:
reject(
'Callback should have been called only twice'
);
}
}
}
);
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
});

View File

@ -2,312 +2,324 @@ import type { RedundancyConfig } from '../src/config';
import { sendQuery } from '../src/query';
describe('Basic queries', () => {
it('Empty query', (done) => {
const payload = {};
const config: RedundancyConfig = {
resources: [],
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
it('Empty query', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const config: RedundancyConfig = {
resources: [],
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
// Tracking
let isSync = true;
const startTime = Date.now();
// Send query
const getStatus = sendQuery(
config,
payload,
() => {
done('Query should not be called when resources list is empty');
},
(data, error) => {
expect(isSync).toEqual(false);
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Send query
const getStatus = sendQuery(
config,
payload,
() => {
reject(
'Query should not be called when resources list is empty'
);
},
(data, error) => {
expect(isSync).toEqual(false);
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Should be almost instant: no items in queue
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(50);
// Should be almost instant: no items in queue
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(50);
done();
}
);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Simple query', (done) => {
const payload = {};
const resources = ['test1'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
it('Simple query', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['test1'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = false;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = false;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Complete
callback('success', result);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Complete
callback('success', result);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Should be almost instant
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(50);
// Should be almost instant
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(50);
done();
}
);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Failing query', (done) => {
const payload = {};
const resources = ['api1'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
it('Failing query', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['api1'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = false;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = false;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Fail
callback('next', result);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Fail
callback('next', result);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Validate data
expect(data).toBeUndefined();
expect(error).toEqual(result);
// Validate data
expect(data).toBeUndefined();
expect(error).toEqual(result);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Should be almost instant
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(40);
// Should be almost instant
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(40);
done();
}
);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Timed out query (~300ms)', (done) => {
const payload = {};
const resources = ['api1'];
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
it('Timed out query (~300ms)', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['api1'];
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = false;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = false;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Do not do anything
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Do not do anything
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Should have been config.rotate + config.timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(250);
// Should have been config.rotate + config.timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(250);
done();
}
);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Abort query', (done) => {
const payload = {};
const resources = ['api1', 'api2', 'api3'];
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
it('Abort query', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['api1', 'api2', 'api3'];
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
let sentQuery = false;
// Tracking
let isSync = true;
let sentQuery = false;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual(resources[0]);
expect(queryPayload).toEqual(payload);
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Make sure query was executed only once
expect(sentQuery).toEqual(false);
sentQuery = true;
// Abort
callback('abort', 404);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Abort
callback('abort', 404);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(true);
// Validate data
expect(data).toBeUndefined();
expect(error).toBe(404);
// Validate data
expect(data).toBeUndefined();
expect(error).toBe(404);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
done();
}
);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
});

View File

@ -2,366 +2,376 @@ import type { RedundancyConfig } from '../src/config';
import { sendQuery } from '../src/query';
describe('Multiple resources', () => {
it('Simple query, success on first attempt', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
it('Simple query, success on first attempt', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual('api1');
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(resource).toEqual('api1');
expect(queryPayload).toEqual(payload);
// Query should be executed only once because it should finish before second attempt
expect(sentQuery).toEqual(0);
sentQuery++;
// Query should be executed only once because it should finish before second attempt
expect(sentQuery).toEqual(0);
sentQuery++;
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(1);
// Complete
callback('success', result);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(1);
// Complete
callback('success', result);
},
(data, error) => {
// Make sure query was sent
expect(sentQuery).toEqual(1);
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(1);
expect(status.queriesPending).toEqual(0);
// Should be almost instant
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(50);
// Should be almost instant
const diff = Date.now() - startTime;
expect(diff).toBeLessThan(50);
done();
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
});
it('Simple query, time out on first, success on second (~100ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Query should be executed twice
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Bump counter
sentQuery++;
// All queries should be pending
expect(status.queriesSent).toEqual(sentQuery);
expect(status.queriesPending).toEqual(sentQuery);
// Time out first, complete second
switch (sentQuery) {
case 1:
// Do nothing, let it time out
return;
case 2:
// Send result
callback('success', result);
return;
default:
done('This code should not have been reached');
fulfill(true);
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
);
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// Delay between first and second queries
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(50);
expect(diff).toBeLessThan(150);
done();
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Time out all queries (~100ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 50,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
it('Simple query, time out on first, success on second (~100ms)', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const resources = ['api1', 'api2'];
const result = {};
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 200,
rotate: 100,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload, callback) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Query should be executed twice
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Query should be executed twice
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Bump counter
sentQuery++;
// Bump counter
sentQuery++;
// All queries should be pending
expect(status.queriesSent).toEqual(sentQuery);
expect(status.queriesPending).toEqual(sentQuery);
// All queries should be pending
expect(status.queriesSent).toEqual(sentQuery);
expect(status.queriesPending).toEqual(sentQuery);
// Add abort functions
switch (sentQuery) {
case 1:
case 2:
// Do not send anything
return;
// Time out first, complete second
switch (sentQuery) {
case 1:
// Do nothing, let it time out
return;
default:
done('This code should not have been reached');
case 2:
// Send result
callback('success', result);
return;
default:
reject('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Validate data
expect(data).toEqual(result);
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('completed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// Delay between first and second queries
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(50);
expect(diff).toBeLessThan(150);
fulfill(true);
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
);
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// rotate * 2 + timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(90);
expect(diff).toBeLessThan(120);
done();
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
isSync = false;
});
});
it('Start with second resource (~100ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2'];
const config: RedundancyConfig = {
resources,
index: 1,
timeout: 50,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
it('Time out all queries (~100ms)', () => {
return new Promise((fulfill, reject) => {
const payload = {};
const resources = ['api1', 'api2'];
const config: RedundancyConfig = {
resources,
index: 0,
timeout: 50,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Resource order should be: 1, 0
expect(resource).not.toEqual(resources[sentQuery]);
expect(resource).toEqual(resources[1 - sentQuery]);
// Query should be executed twice
expect(sentQuery).toBeLessThan(2);
expect(resource).toEqual(resources[sentQuery]);
// Bump counter
sentQuery++;
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.payload).toEqual(payload);
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Bump counter
sentQuery++;
// rotate * 2 + timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(90);
expect(diff).toBeLessThan(120);
// All queries should be pending
expect(status.queriesSent).toEqual(sentQuery);
expect(status.queriesPending).toEqual(sentQuery);
done();
}
);
// Add abort functions
switch (sentQuery) {
case 1:
case 2:
// Do not send anything
return;
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
default:
reject('This code should not have been reached');
}
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
isSync = false;
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Check status
const status = getStatus();
expect(status.status).toEqual('failed');
expect(status.queriesSent).toEqual(2);
expect(status.queriesPending).toEqual(0);
// rotate * 2 + timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(90);
expect(diff).toBeLessThan(120);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
});
});
it('Start with last resource (~150ms)', (done) => {
const payload = {};
const resources = ['api1', 'api2', 'api3', 'api4'];
const config: RedundancyConfig = {
resources,
index: 3,
timeout: 50,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
it('Start with second resource (~100ms)', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['api1', 'api2'];
const config: RedundancyConfig = {
resources,
index: 1,
timeout: 50,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
let sentQuery = 0;
const startTime = Date.now();
// Tracking
let isSync = true;
const startTime = Date.now();
let sentQuery = 0;
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Resource order should be: 3, 0, 1, 2
expect(resource).not.toEqual(resources[sentQuery]);
// Resource order should be: 1, 0
expect(resource).not.toEqual(resources[sentQuery]);
expect(resource).toEqual(resources[1 - sentQuery]);
const expectedIndex = sentQuery === 0 ? 3 : sentQuery - 1;
expect(resource).toEqual(resources[expectedIndex]);
// Bump counter
sentQuery++;
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(2);
// Bump counter
sentQuery++;
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(4);
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// rotate * 2 + timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(90);
expect(diff).toBeLessThan(120);
// rotate * 4 + timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(140);
expect(diff).toBeLessThan(170);
fulfill(true);
}
);
done();
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
});
});
isSync = false;
it('Start with last resource (~150ms)', () => {
return new Promise((fulfill) => {
const payload = {};
const resources = ['api1', 'api2', 'api3', 'api4'];
const config: RedundancyConfig = {
resources,
index: 3,
timeout: 50,
rotate: 25,
random: false,
dataAfterTimeout: false,
};
// Tracking
let isSync = true;
let sentQuery = 0;
const startTime = Date.now();
// Send query
const getStatus = sendQuery(
config,
payload,
(resource, queryPayload) => {
expect(isSync).toEqual(false);
expect(queryPayload).toEqual(payload);
// Resource order should be: 3, 0, 1, 2
expect(resource).not.toEqual(resources[sentQuery]);
const expectedIndex = sentQuery === 0 ? 3 : sentQuery - 1;
expect(resource).toEqual(resources[expectedIndex]);
// Bump counter
sentQuery++;
},
(data, error) => {
// Make sure queries were sent
expect(sentQuery).toEqual(4);
// Validate data
expect(data).toBeUndefined();
expect(error).toBeUndefined();
// rotate * 4 + timeout
const diff = Date.now() - startTime;
expect(diff).toBeGreaterThan(140);
expect(diff).toBeLessThan(170);
fulfill(true);
}
);
// Check status
const status = getStatus();
expect(status.status).toEqual('pending');
expect(status.queriesSent).toEqual(0);
expect(status.queriesPending).toEqual(0);
isSync = false;
});
});
});

View File

@ -3,116 +3,120 @@ import { initRedundancy } from '../src/index';
type DummyResponses = Record<string, string>;
describe('Redundancy class', () => {
it('Simple query', (done) => {
const redundancy = initRedundancy({
resources: [
'https://api.local', // Will fail
'https://api-backup1.local', // Success
'https://api-backup2.local',
],
rotate: 20,
timeout: 100,
});
it('Simple query', () => {
return new Promise((fulfill) => {
const redundancy = initRedundancy({
resources: [
'https://api.local', // Will fail
'https://api-backup1.local', // Success
'https://api-backup2.local',
],
rotate: 20,
timeout: 100,
});
// Premade responses
const responses: DummyResponses = {
'https://api-backup1.local/foo': 'foo',
};
let counter = 0;
let doneCallbackCalled = false;
// Premade responses
const responses: DummyResponses = {
'https://api-backup1.local/foo': 'foo',
};
let counter = 0;
let doneCallbackCalled = false;
const query = redundancy.query(
'/foo',
(resource, payload, callback) => {
counter++;
expect(counter).toBeLessThan(3); // No more than 2 queries should be executed
const query = redundancy.query(
'/foo',
(resource, payload, callback) => {
counter++;
expect(counter).toBeLessThan(3); // No more than 2 queries should be executed
// Make URI from resource + payload
const uri = (resource as string) + (payload as string);
// Make URI from resource + payload
const uri = (resource as string) + (payload as string);
// Get fake data if it exists
if (responses[uri] === void 0) {
return;
// Get fake data if it exists
if (responses[uri] === void 0) {
return;
}
// Do something with "data", simulate instant callback
callback('success', responses[uri]);
// Complete test
setTimeout(() => {
expect(counter).toEqual(2);
expect(doneCallbackCalled).toEqual(true);
expect(query().status).toEqual('completed');
expect(redundancy.getIndex()).toEqual(1); // Should have changed to 1 after query
fulfill(true);
});
},
(data) => {
expect(data).toEqual('foo');
doneCallbackCalled = true;
}
);
// Do something with "data", simulate instant callback
callback('success', responses[uri]);
// Complete test
setTimeout(() => {
expect(counter).toEqual(2);
expect(doneCallbackCalled).toEqual(true);
expect(query().status).toEqual('completed');
expect(redundancy.getIndex()).toEqual(1); // Should have changed to 1 after query
done();
});
},
(data) => {
expect(data).toEqual('foo');
doneCallbackCalled = true;
}
);
// Test find()
expect(
redundancy.find((item) => (item().payload as string) === '/foo')
).toEqual(query);
expect(redundancy.find((item) => item().status === 'pending')).toEqual(
query
);
// Test find()
expect(
redundancy.find((item) => (item().payload as string) === '/foo')
).toEqual(query);
expect(
redundancy.find((item) => item().status === 'pending')
).toEqual(query);
});
});
it('Different start index', (done) => {
const redundancy = initRedundancy({
resources: [
'https://api.local',
'https://api-backup1.local',
'https://api-backup2.local',
],
rotate: 20,
timeout: 3000,
index: 1,
});
it('Different start index', () => {
return new Promise((fulfill) => {
const redundancy = initRedundancy({
resources: [
'https://api.local',
'https://api-backup1.local',
'https://api-backup2.local',
],
rotate: 20,
timeout: 3000,
index: 1,
});
// Premade responses
const responses: DummyResponses = {
'https://api-backup1.local/foo': 'foo',
};
let counter = 0;
// Premade responses
const responses: DummyResponses = {
'https://api-backup1.local/foo': 'foo',
};
let counter = 0;
const query = redundancy.query(
'/foo',
(resource, payload, callback) => {
counter++;
expect(counter).toBeLessThan(2); // Should be success on first call because start index = 1
const query = redundancy.query(
'/foo',
(resource, payload, callback) => {
counter++;
expect(counter).toBeLessThan(2); // Should be success on first call because start index = 1
// Make URI from resource + payload
const uri = (resource as string) + (payload as string);
// Make URI from resource + payload
const uri = (resource as string) + (payload as string);
// Get fake data if it exists
if (responses[uri] === void 0) {
return;
// Get fake data if it exists
if (responses[uri] === void 0) {
return;
}
// Do something with "data", simulate instant callback
callback('success', responses[uri]);
// Complete test
setTimeout(() => {
expect(counter).toEqual(1);
expect(query().status).toEqual('completed');
expect(redundancy.getIndex()).toEqual(1);
fulfill(true);
});
}
);
// Do something with "data", simulate instant callback
callback('success', responses[uri]);
// Complete test
setTimeout(() => {
expect(counter).toEqual(1);
expect(query().status).toEqual('completed');
expect(redundancy.getIndex()).toEqual(1);
done();
});
}
);
// Test find()
expect(redundancy.find((item) => item().payload === '/foo')).toEqual(
query
);
expect(redundancy.find((item) => item().status === 'pending')).toEqual(
query
);
// Test find()
expect(
redundancy.find((item) => item().payload === '/foo')
).toEqual(query);
expect(
redundancy.find((item) => item().status === 'pending')
).toEqual(query);
});
});
});

View File

@ -0,0 +1,9 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
watch: false,
include: ['**/tests/*-test.ts'],
},
});

File diff suppressed because it is too large Load Diff