@luminati-io/luminati-proxy
Version:
A configurable local proxy for brightdata.com
817 lines (809 loc) • 32 kB
JavaScript
// LICENSE_CODE ZON ISC
'use strict'; /*jslint node:true, mocha:true*/
const assert = require('assert');
const migrate = require('../lib/migration.js');
const migrations = migrate.migrations;
const {migrate_trigger} = require('../util/rules_util.js');
const pkg = require('../package.json');
const tests_run = {};
const assert_default = (a, b)=>{
assert.deepEqual(a._default, b._default);
assert.equal(a.proxies.length, b.proxies.length);
};
const test_edge_cases = v=>it('edge cases', ()=>{
const migration = migrations[v];
migration({});
migration({proxies: []});
migration({_defaults: {}});
});
const describe_version = function(name, tests){
describe(name, function(){
tests_run[this.title] = true;
test_edge_cases(this.title);
tests(this.title);
});
};
const t_rule = (v, _type='post')=>(name, rule, _rule)=>it(name, ()=>{
const {proxies: [_proxy]} = migrations[v]({
proxies: [{port: 24000, rules: {[_type]: [rule]}}]});
assert.deepEqual(_proxy, {port: 24000, rules: {[_type]: [_rule]}});
});
describe('migration', ()=>{
describe_version('1.116.387', v=>{
it('deletes socks field', ()=>{
const conf = {proxies: [{socks: 1234}, {}]};
const _conf = migrations[v](conf);
assert.equal(_conf.socks, undefined);
assert_default(conf, _conf);
});
it('transforms rules', ()=>{
const conf = {proxies: [
{direct_include: 'amazon'},
{null_response: 'facebook', bypass_proxy: 'google'},
]};
const _conf = migrations[v](conf);
assert.deepEqual(_conf.proxies[0], {rules: {pre: [{
trigger_type: 'url',
url: 'amazon',
action: 'direct',
}]}});
assert.deepEqual(_conf.proxies[1], {rules: {pre: [{
trigger_type: 'url',
url: 'facebook',
action: 'null_response',
}, {
trigger_type: 'url',
url: 'google',
action: 'bypass_proxy',
}]}});
assert_default(conf, _conf);
});
it('keep existing rules', ()=>{
const rule = {};
const conf = {proxies: [{
null_response: 'facebook',
rules: {pre: [rule]},
}]};
const _conf = migrations[v](conf);
assert.equal(_conf.proxies[0].rules.pre.length, 2);
assert.equal(_conf.proxies[0].rules.pre[0], rule);
assert_default(conf, _conf);
});
});
describe_version('1.116.548', v=>{
it('transforms keep_alive from number into true', ()=>{
const conf = {proxies: [
{port: 24000, field: 1, keep_alive: 45},
{port: 24001, keep_alive: 50},
{port: 24002, keep_alive: 0},
{port: 24003},
]};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {proxies: [
{port: 24000, field: 1, keep_alive: true},
{port: 24001, keep_alive: true},
{port: 24002},
{port: 24003},
]});
});
});
describe_version('1.116.963', v=>{
it('transforms url object into trigger_code for post', ()=>{
const proxy = {rules: {post: [{
res: [{trigger_type: 'url'}],
url: {code: `code`, regexp: `\\.(svg|jpeg)$`},
}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [
{rules: {post: [{
res: [{trigger_type: 'url'}],
url: `\\.(svg|jpeg)$`,
trigger_code: `code`,
}]}},
]});
});
it('transforms url object into trigger_code for pre', ()=>{
const proxy = {rules: {pre: [{
action: 'null_response',
url: {code: `code`, regexp: `\\.(svg|jpeg|jpg)$`},
}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [
{rules: {pre: [{
action: 'null_response',
url: `\\.(svg|jpeg|jpg)$`,
trigger_code: `code`,
}]}},
]});
});
it('transofrm flat string into trigger_code', ()=>{
const proxy = {rules: {pre: [{
action: 'null_response',
url: 'facebook.com',
}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [
{rules: {pre: [{
action: 'null_response',
url: `facebook.com`,
trigger_code: `function trigger(opt){\n `
+`return /facebook.com/.test(opt.url);\n}`,
}]}},
]});
});
it('transofrm empty regex into trigger_code', ()=>{
const proxy = {rules: {pre: [{
action: 'null_response',
url: '**',
}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [
{rules: {pre: [{
action: 'null_response',
url: '',
trigger_code: `function trigger(opt){\n return true;\n}`,
}]}},
]});
});
});
describe_version('1.116.964', v=>{
it('transforms array res into flat rule', ()=>{
const proxy = {rules: {post: [{
res: [{
trigger_type: 'url',
action: {ban_ip: '10min', retry: true},
action_type: 'ban_ip',
}],
trigger_code: `code`,
}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [
{rules: {post: [{
trigger_type: 'url',
trigger_code: `code`,
action_type: 'ban_ip',
action: {ban_ip: '10min', retry: true},
}]}},
]});
});
it('does nothing to proxies without any rules', ()=>{
const proxy = {port: 24000, param: 'a'};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [proxy]});
});
it('does nothing to proxies without post rules', ()=>{
const proxy = {port: 24000, rules: {pre: [{id: 'rule1'}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [proxy]});
});
it('does nothing to rules without res field', ()=>{
const proxy = {port: 24000, rules: {post: [{id: 'rule1'}]}};
const _conf = migrations[v]({proxies: [proxy]});
assert.deepEqual(_conf, {proxies: [proxy]});
});
});
describe_version('1.117.683', v=>{
const t = (name, _type, rule, type)=>it(name, ()=>{
const {proxies: [_proxy]} = migrations[v]({
proxies: [{port: 24000, rules: {[_type]: [rule]}}]});
assert.deepEqual(_proxy, {port: 24000, rules: {[_type]: [
Object.assign({}, rule, {type}),
]}});
});
t('url -> before_send', 'pre',
{action: 'null_response', url: '\\.(jpeg)$'}, 'before_send');
t('min_req_time -> timeout', 'pre',
{min_req_time: 500, url: '\\.(jpeg)$'}, 'timeout');
t('max_req_time -> after_hdr', 'post',
{max_req_time: 500, url: '\\.(jpeg)$'}, 'after_hdr');
t('status -> after_hdr', 'post',
{status: {}, url: '\\.(jpeg)$'}, 'after_hdr');
t('body -> after_body', 'post',
{body: {}, url: '\\.(jpeg)$'}, 'after_body');
t('body -> after_body', 'post',
{action_type: 'process', url: '\\.(jpeg)$'}, 'after_body');
});
describe_version('1.117.684', v=>{
const t = t_rule(v);
t('reduces status into single value', {url: '\\.(jpeg)$',
type: 'after_hdr', status: {arg: '200 - Success', type: 'in'}},
{url: '\\.(jpeg)$', type: 'after_hdr', status: 200});
const status_rule = {type: 'after_hdr', status: 200};
t('does not change status if it is already simple value', status_rule,
status_rule);
t('reduces body into single value', {url: '\\.(jpeg)$',
type: 'after_body', body: {arg: 'captcha', type: 'in'}},
{url: '\\.(jpeg)$', type: 'after_body', body: 'captcha'});
const body_rule = {type: 'after_body', body: 'test123'};
t('does not change body if it is already simple value', body_rule,
body_rule);
});
describe_version('1.118.284', v=>{
it('flatten logs object into value', ()=>{
const _defaults = {atr: 1, logs: {metric: 'logs', value: 10}};
const _conf = migrations[v]({proxies: [], _defaults});
assert.equal(_conf._defaults.logs, 10);
});
it('does not change config if no logs', ()=>{
const _defaults = {atr: 1};
const _conf = migrations[v]({proxies: [], _defaults});
assert.equal(_conf._defaults.logs, undefined);
});
it('does not change config if logs already simple value', ()=>{
const _defaults = {atr: 1, logs: 100};
const _conf = migrations[v]({proxies: [], _defaults});
assert.equal(_conf._defaults.logs, 100);
});
});
describe_version('1.118.308', v=>{
const t = t_rule(v);
t('transforms ban ip duration into ms', {action: {ban_ip: '55min'}},
{action: {ban_ip: 55*60*1000}});
t('transforms max_req_time into ms', {max_req_time: '500ms'},
{max_req_time: 500});
t('transforms min_req_time into ms', {min_req_time: '1000ms'},
{min_req_time: 1000});
});
describe_version('1.118.309', v=>{
const t = t_rule(v);
t('transforms status into string', {status: 200}, {status: '200'});
t('gets rid of status_custom', {status: '523', status_custom: true},
{status: '523'});
});
describe_version('1.118.310', v=>{
const t = t_rule(v);
t('gets rid of type and trigger_code', {type: 'before_send',
url: 'url', trigger_code: '--code--'}, {url: 'url'});
t('does nothing', {url: 'url'}, {url: 'url'});
});
describe_version('1.118.985', v=>{
const t = t_rule(v, 'pre');
t('moves email and null_response into action object', {
url: 'facebook',
action: 'null_response',
email: 'test@test.com',
}, {
url: 'facebook',
action_type: 'null_response',
action: {email: 'test@test.com', null_response: true},
});
t('moves bypass_proxy into action object',
{url: 'facebook', action: 'bypass_proxy'},
{url: 'facebook', action_type: 'bypass_proxy',
action: {bypass_proxy: true}});
t('moves direct into action object',
{url: 'facebook', action: 'direct'},
{url: 'facebook', action_type: 'direct', action: {direct: true}});
t('switch_port -> retry_port', {
url: 'facebook',
action: 'switch_port',
port: 24001,
retry: 1,
}, {
url: 'facebook',
action_type: 'retry_port',
action: {retry_port: 24001},
});
t('switch_port -> retry_port with email', {
email: 'test@test.com',
url: 'facebook',
action: 'switch_port',
port: 24001,
retry: 1,
}, {
url: 'facebook',
action_type: 'retry_port',
action: {retry_port: 24001, email: 'test@test.com'},
});
});
describe_version('1.119.232', v=>{
const t = (name, proxy, expected)=>it(name, ()=>{
const {proxies: [_proxy]} = migrations[v]({proxies: [proxy]});
assert.deepEqual(_proxy, expected);
});
t('merges pre and post arrays',
{port: 24000, rules: {pre: [{a: 1}, {a: 2}], post: [{b: 1}]}},
{port: 24000, rules: [{a: 1}, {a: 2}, {b: 1}]});
t('takes only pre if post is undefined',
{port: 24000, rules: {pre: [{a: 1}, {a: 2}]}},
{port: 24000, rules: [{a: 1}, {a: 2}]});
t('takes only post if pre is undefined',
{port: 24000, rules: {post: [{a: 1}, {a: 2}]}},
{port: 24000, rules: [{a: 1}, {a: 2}]});
t('skips rules if both pre and post are skipped', {rules: {}}, {});
});
describe_version('1.119.617', v=>{
const t = (name, rule, _rule)=>it(name, ()=>{
const {proxies: [_proxy]} = migrations[v]({
proxies: [{port: 24000, rules: [rule]}]});
assert.deepEqual(_proxy, {port: 24000, rules: [_rule]});
});
t('delete url if its *', {url: '*', action: {null_response: true}},
{action: {null_response: true}});
t('delete url if its **', {url: '**', action: {null_response: true}},
{action: {null_response: true}});
t('does not change if url doesnt exists',
{action: {null_response: true}}, {action: {null_response: true}});
t('does not change if url is correct', {url: 'x',
action: {null_response: true}}, {url: 'x',
action: {null_response: true}});
});
describe('rule -> code transformation', ()=>{
const t = (name, rule, code, _type)=>it(name, ()=>{
const _rule = migrate_trigger(rule);
assert.equal(_rule.trigger_code, code);
assert.equal(_rule.type, _type);
});
t('simple', {}, `function trigger(opt){\n`
+` return true;\n}`, 'before_send');
t('with url', {url: 'facebook'}, `function trigger(opt){\n`
+` if (!new RegExp(String.raw\`facebook\`).test(opt.url))\n`
+` return false;\n`
+` return true;\n}`, 'before_send');
t('min_req_time / retry', {min_req_time: 200, action_type: 'retry',
trigger_type: 'min_req_time'}, `function trigger(opt){\n`
+` opt.timeout = 200;\n`
+` return true;\n}`, 'timeout');
t('min_req_time / retry_port + url', {trigger_type: 'min_req_time',
min_req_time: 200, action_type: 'retry_port', url: 'facebook'},
`function trigger(opt){\n`
+` opt.timeout = 200;\n`
+` if (!new RegExp(String.raw\`facebook\`).test(opt.url))\n`
+` return false;\n`
+` return true;\n}`, 'timeout');
t('min_req_time ban_ip', {min_req_time: 100, action_type: 'ban_ip',
trigger_type: 'min_req_time'}, `function trigger(opt){\n`
+` if (opt.time_passed<100)\n`
+` return false;\n`
+` return true;\n}`, 'after_hdr');
t('status_code', {status: '200'},
`function trigger(opt){\n`
+` if (!new RegExp(String.raw\`200\`).test(opt.status))\n`
+` return false;\n`
+` return true;\n}`, 'after_hdr');
t('status_code with url', {status: '(4|5)..', url: 'facebook'},
`function trigger(opt){\n`
+` if (!new RegExp(String.raw\`(4|5)..\`).test(opt.status))\n`
+` return false;\n`
+` if (!new RegExp(String.raw\`facebook\`).test(opt.url))\n`
+` return false;\n`
+` return true;\n}`, 'after_hdr');
t('max_req_time', {max_req_time: 500}, `function trigger(opt){\n`
+` if (opt.time_passed>500)\n`
+` return false;\n`
+` return true;\n}`, 'after_hdr');
t('http body', {body: 'captcha'}, `function trigger(opt){\n`
+` if (!new RegExp(String.raw\`captcha\`).test(opt.body))\n`
+` return false;\n`
+` return true;\n}`, 'after_body');
});
describe_version('1.136.76', v=>{
it('should migrate preset round_robin -> rotating', ()=>{
const conf = {proxies: [
{port: 24000, field: 1, last_preset_applied: 'round_robin'},
{port: 24001, last_preset_applied: 'other_preset'},
{port: 24003},
]};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {proxies: [
{port: 24000, field: 1, last_preset_applied: 'rotating'},
{port: 24001, last_preset_applied: 'other_preset'},
{port: 24003},
]});
});
it('should migrate pool_type round_robin, sequential -> default', ()=>{
const conf = {proxies: [
{port: 24000, field: 1, pool_type: 'round_robin'},
{port: 24001, pool_type: 'sequential'},
{port: 24002, pool_type: 'long_availability'},
{port: 24003},
]};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {proxies: [
{port: 24000, field: 1},
{port: 24001},
{port: 24002, pool_type: 'long_availability'},
{port: 24003},
]});
});
});
describe_version('1.148.122', v=>{
it('should turn on proxy resolving when pool_size is >= 1', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000, pool_size: 0},
{port: 24001, pool_size: 1},
{port: 24002, pool_size: 100, opt: true},
{port: 24003, opt: true},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000, pool_size: 0},
{port: 24001, pool_size: 1, proxy_resolve: true},
{port: 24002, pool_size: 100, opt: true,
proxy_resolve: true},
{port: 24003, opt: true},
],
});
});
});
describe_version('1.153.222', v=>{
it('should change random user agent truthy values to desktop', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, random_user_agent: 1},
{port: 24002, random_user_agent: true},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, random_user_agent: 'desktop'},
{port: 24002, random_user_agent: 'desktop'},
],
});
});
});
describe_version('1.153.629', v=>{
it('should rename and change secure proxy truthy values to https',
()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, secure_proxy: 1},
{port: 24002, secure_proxy: true},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, proxy_connection_type: 'https'},
{port: 24002, proxy_connection_type: 'https'},
],
});
});
});
describe_version('1.154.55', v=>{
it('should not do anything if preset not set', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, last_preset_applied: 'rotating'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, preset: 'rotating'},
],
});
});
});
describe_version('1.154.56', v=>{
it('should convert high_performance preset -> rotating', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, preset: 'high_performance'},
{port: 24002, preset: 'long_session'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, preset: 'rotating'},
{port: 24002, preset: 'long_session'},
],
});
});
});
describe_version('1.155.263', v=>{
it('should merge random_user_agent and user_agent options', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000},
{port: 24002, random_user_agent: 'desktop'},
{port: 24002, random_user_agent: 'mobile'},
{port: 24002, user_agent: 'Mozilla'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000},
{port: 24002, user_agent: 'random_desktop'},
{port: 24002, user_agent: 'random_mobile'},
{port: 24002, user_agent: 'Mozilla'},
],
});
});
});
describe_version('1.155.264', v=>{
it('should change preset to long availability if pool type set', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, preset: 'high_performance',
pool_type: 'long_availability'},
{port: 24002, preset: 'long_session'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000},
{port: 24001, preset: 'long_availability'},
{port: 24002, preset: 'long_session'},
],
});
});
});
describe_version('1.171.624', v=>{
it('remove extra fields from config', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000, zone: 'z', ips: ['1.1.1.1'], ssl: true,
hosts: ['1.1.1.1'], mobile: true, static: true,
ssl_perm: true, unblock: true},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000, zone: 'z', ips: ['1.1.1.1'], ssl: true}],
});
});
});
describe_version('1.175.938', v=>{
it('renames token -> google_token', ()=>{
const conf = {
_defaults: {customer: 'test', token: 'token123'},
proxies: [],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {customer: 'test', google_token: 'token123'},
proxies: [],
});
});
it('leaves config untouched if there is no token attribute', ()=>{
const conf = {
_defaults: {customer: 'test', password: 'pass'},
proxies: [],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {customer: 'test', password: 'pass'},
proxies: [],
});
});
});
describe_version('1.177.584', v=>{
it('removes preset if long_availability', ()=>{
const conf = {
_defaults: {customer: 'test', token: 'token123'},
proxies: [
{port: 24000, preset: 'long_availability'},
{port: 24001, preset: 'another'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {customer: 'test', token: 'token123'},
proxies: [{port: 24000}, {port: 24001, preset: 'another'}],
});
});
it('rnd_usr_agent_and_cookie_header -> rotating', ()=>{
const conf = {
_defaults: {customer: 'test', token: 'token123'},
proxies: [
{port: 24000, preset: 'rnd_usr_agent_and_cookie_header'},
{port: 24001, preset: 'another'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {customer: 'test', token: 'token123'},
proxies: [
{port: 24000, preset: 'rotating'},
{port: 24001, preset: 'another'},
],
});
});
it('max_requests -> rotate_session', ()=>{
const conf = {
_defaults: {customer: 'test', token: 'token123'},
proxies: [
{port: 24000},
{port: 24001, max_requests: 0},
{port: 24001, max_requests: 1},
{port: 24001, max_requests: 10},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {customer: 'test', token: 'token123'},
proxies: [
{port: 24000},
{port: 24001, rotate_session: false},
{port: 24001, rotate_session: true},
{port: 24001, rotate_session: true},
],
});
});
});
describe_version('1.177.792', v=>{
it('merges session per machine into long single session', ()=>{
const conf = {
_defaults: {},
proxies: [
{port: 24000, preset: 'sticky_ip', sticky_ip: true},
{port: 24001, preset: 'another'},
],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [
{port: 24000, sticky_ip: true},
{port: 24001, preset: 'another'},
],
});
});
});
describe_version('1.182.312', v=>{
it('disables config sync and sets ask_sync_config', ()=>{
const conf = {
_defaults: {},
proxies: [],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {sync_config: false, ask_sync_config: true},
proxies: [],
});
});
it('keeps enabled config sync and not set ask_sync_config', ()=>{
const conf = {
_defaults: {sync_config: true},
proxies: [],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {sync_config: true},
proxies: [],
});
});
});
describe_version('1.185.470', v=>{
it('set sync_config to true if was undefined', ()=>{
const conf = {
_defaults: {},
proxies: [],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {sync_config: true},
proxies: [],
});
});
it('dont change if sync_config was disabled', ()=>{
const conf = {
_defaults: {sync_config: false},
proxies: [],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {sync_config: false},
proxies: [],
});
});
});
it('ensures that each production migration has a test', ()=>{
for (let v in migrations)
{
if (v.startsWith('x'))
continue;
assert.equal(tests_run[v], true);
}
});
describe_version('1.222.563', v=>{
it('does not change if no proxy_count', ()=>{
const conf = {
_defaults: {},
proxies: [{port: 24000, pool: 15}, {port: 24001}],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, conf);
});
it('removes legacy proxy_count attribute', ()=>{
const conf = {
_defaults: {},
proxies: [{port: 24000, proxy_count: 20}, {port: 24001}],
};
const _conf = migrations[v](conf);
assert.deepEqual(_conf, {
_defaults: {},
proxies: [{port: 24000}, {port: 24001}],
});
});
});
it('ensures that each production migration has a test', ()=>{
for (let v in migrations)
{
if (v.startsWith('x'))
continue;
assert.equal(tests_run[v], true);
}
});
});
describe('manager', ()=>{
let executed;
const fake_migrations = {
'1.0.0': c=>{ executed['1.0.0'] = true; return c; },
'2.0.0': c=>{ executed['2.0.0'] = true; return c; },
'2.1.0': c=>{ executed['2.1.0'] = true; return c; },
'2.2.0': c=>{ executed['2.2.0'] = true; return c; },
'x.dev': c=>{ executed['x.dev'] = true; return c; },
};
beforeEach(()=>{
executed = {};
});
it('adds the current version', ()=>{
const conf = {};
const _conf = migrate(conf);
assert.equal(_conf._defaults.version, pkg.version);
});
it('runs all the migrations when version is empty', ()=>{
const conf = {};
migrate(conf, fake_migrations);
assert.deepEqual(executed,
{'1.0.0': true, '2.0.0': true, '2.1.0': true, '2.2.0': true});
});
it('runs migrations starting from specified version', ()=>{
const conf = {_defaults: {version: '2.0.0'}};
migrate(conf, fake_migrations);
assert.deepEqual(executed,
{'2.0.0': true, '2.1.0': true, '2.2.0': true});
});
it('runs migrations after specified version', ()=>{
const conf = {_defaults: {version: '2.0.1'}};
migrate(conf, fake_migrations);
assert.deepEqual(executed, {'2.1.0': true, '2.2.0': true});
});
it('does not run migrations starting with x', ()=>{
const conf = {};
migrate(conf, fake_migrations);
assert.equal(executed['x.dev'], undefined);
});
it('throws error if invalid version and not starting with x', ()=>{
const _migrations = Object.assign({}, fake_migrations, {ver: c=>{
executed.ver = true;
return c;
}});
assert.throws(()=>migrate({}, _migrations), /Invalid Version/);
});
});