<commit_before>var margin = {
  //top: 50,
  //right: 50,
  //bottom: 50,
  //left: 50
  top    : 10,
  right  : 10,
  bottom : 100,
  left   : 40
};

var margin2 = {
  top    : 430,
  right  : 10,
  bottom : 20,
  left   : 40
}
var width = 960 - margin.left - margin.right; // 910
var height = 500 - margin.top - margin.bottom; // 390
var height2 = 500 - margin2.top - margin2.bottom; // 50
var padding = 30;
var dataset = [];

//var bbOverview = {
//  x: 0,
//  y: 10,
//  w: width,
//  h: 50
//}
//
//var bbDetail = {
//  x: 0,
//  y: 100,
//  w: width,
//  h: 300
//}

var parseDate = d3.time.format('%b-%y').parse

/*
 * Set up scales
 */
var xScaleFocus = d3.time.scale()
  .range([padding, width]);

var yScaleFocus = d3.scale.linear()
  .range([height, 0]);

var xScaleContext = d3.time.scale()
  .range([padding, width]);

var yScaleContext = d3.scale.linear()
  .range([height2, 0]);

/*
 * Set up axes
 */
var xAxisFocus = d3.svg.axis()
  .scale(xScaleFocus)
  .orient('bottom');

var yAxisFocus = d3.svg.axis()
  .scale(yScaleFocus)
  .orient('left');

var xAxisContext = d3.svg.axis()
  .scale(xScaleContext)
  .orient('bottom');

var yAxisContext = d3.svg.axis()
  .scale(yScaleContext)
  .orient('left')
  .ticks(3);

/*
 * Set up area function
 */
var areaFocus = d3.svg.area()
  .x(function(d) {
    return xScaleFocus(d.date);
  })
  .y0(height)
  .y1(function(d) {
    return yScaleFocus(d.women);
  })

/*
 * Set up line function
 */
var lineContext = d3.svg.line()
  .x(function(d) {
    return xScaleContext(d.date);
  })
  .y(function(d) {
    return yScaleContext(d.women);
  })

/*
 * Set up brush
 */
var brush = d3.svg.brush()
  .x(xScaleContext)
  .on('brush', brushed)

var svg = d3.select('body')
  .append('svg')
  .attr('height', height + margin.top + margin.bottom) //
  .attr('width', width + margin.left + margin.right)

svg
  .append('defs')
  .append('clipPath')
    .attr('id', 'clip')
  .append('rect')
    .attr('width', width - padding)
    .attr('height', height)
    .attr('transform', 'translate(' + padding + ',0)');

var focus = svg.append('g')
  .attr('class', 'focus')
  .attr('transform', 'translate(' + margin.left + ','
    + margin.top + ')');

var context = svg.append('g')
  .attr('class', 'context')
  .attr('transform', 'translate(' + margin2.left + ','
    + margin2.top + ')');

d3.csv('unHealth-women.csv', function(error, data) {
  data.forEach(function(d) {
    d.date = parseDate(d.date);
    d.women = +d.women;
  });

  dataset = data;

  // define xScaleFocus's domain now because we want to use
  // the data before we reformat it
  xScaleFocus
    .domain(d3.extent(data, function(d) {
      return d.date;
    }));

  console.log(data);

  yScaleFocus
    .domain(d3.extent(data.map(function(d) {
      return d.women;
    })));

  xScaleContext
    .domain(xScaleFocus.domain());

  yScaleContext
    .domain(yScaleFocus.domain());

  createVis();

}); // end d3.csv();

function createVis() {
  focus
    .append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + height + ')')
    .call(xAxisFocus);

  focus
    .append('g')
    .attr('class', 'y axis')
    .attr('transform', 'translate(' + padding + ',0)')
    .call(yAxisFocus)

  focus
    .append('path')
    .datum(dataset)
    .attr('class', 'area')
    .attr('d', areaFocus)

  focus
    .selectAll('circle')
    .data(dataset)
    .enter()
    .append('circle')
    .attr('class', 'circle')
    .attr('r', 2)
    .attr('cx', function(d) {
      return xScaleFocus(d.date);
    })
    .attr('cy', function(d) {
      return yScaleFocus(d.women);
    })

  context
    .append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + height2 + ')')
    .call(xAxisContext)

  context
    .append('g')
    .attr('class', 'y axis')
    .attr('transform', 'translate(' + padding + ',0)')
    .call(yAxisContext)

  context
    .datum(dataset)
    .append('path')
    .attr('class', 'path')
    .attr('d', lineContext)

  context
    .selectAll('circle')
    .data(dataset)
    .enter()
    .append('circle')
    .attr('class', 'circle')
    .attr('r', 2)
    .attr('cx', function(d) {
      return xScaleContext(d.date);
    })
    .attr('cy', function(d) {
      return yScaleContext(d.women);
    })

  context
    .append('g')
    .attr('class', 'brush')
    .call(brush)
    .selectAll('rect')
    .attr('height', height2)

}; // end createVis()

function brushed() {
  xScaleFocus
    .domain(brush.empty() ? xScaleContext.domain() : brush.extent());

  focus
    .select('.area')
    .attr('d', areaFocus);

  focus
    .select('.x.axis')
    .call(xAxisFocus);

  focus
    .selectAll('circle')
    .attr('cx', function(d) {
      return xScaleFocus(d.date);
    })
}
<commit_msg>swaps positions of focus and context<commit_after>var marginContext = {
  //top: 50,
  //right: 50,
  //bottom: 50,
  //left: 50
  top    : 10,
  right  : 10,
  bottom : 430,
  left   : 40
};

var marginFocus = {
  top    : 100,
  right  : 10,
  bottom : 20,
  left   : 40
}
var width = 960 - marginFocus.left - marginFocus.right; // 910
var heightFocus = 500 - marginFocus.top - marginFocus.bottom; // 390
var heightContext = 500 - marginContext.top - marginContext.bottom; // 50
var padding = 30;
var dataset = [];

//var bbOverview = {
//  x: 0,
//  y: 10,
//  w: width,
//  h: 50
//}
//
//var bbDetail = {
//  x: 0,
//  y: 100,
//  w: width,
//  h: 300
//}

var parseDate = d3.time.format('%b-%y').parse

/*
 * Set up scales
 */
var xScaleFocus = d3.time.scale()
  .range([padding, width]);

var yScaleFocus = d3.scale.linear()
  .range([heightFocus, 0]);

var xScaleContext = d3.time.scale()
  .range([padding, width]);

var yScaleContext = d3.scale.linear()
  .range([heightContext, 0]);

/*
 * Set up axes
 */
var xAxisFocus = d3.svg.axis()
  .scale(xScaleFocus)
  .orient('bottom');

var yAxisFocus = d3.svg.axis()
  .scale(yScaleFocus)
  .orient('left');

var xAxisContext = d3.svg.axis()
  .scale(xScaleContext)
  .orient('bottom');

var yAxisContext = d3.svg.axis()
  .scale(yScaleContext)
  .orient('left')
  .ticks(3);

/*
 * Set up area function
 */
var areaFocus = d3.svg.area()
  .x(function(d) {
    return xScaleFocus(d.date);
  })
  .y0(heightFocus)
  .y1(function(d) {
    return yScaleFocus(d.women);
  })

/*
 * Set up line function
 */
var lineContext = d3.svg.line()
  .x(function(d) {
    return xScaleContext(d.date);
  })
  .y(function(d) {
    return yScaleContext(d.women);
  })

/*
 * Set up brush
 */
var brush = d3.svg.brush()
  .x(xScaleContext)
  .on('brush', brushed)

var svg = d3.select('body')
  .append('svg')
  .attr('height', heightFocus + marginFocus.top + marginFocus.bottom) //
  .attr('width', width + marginFocus.left + marginFocus.right)

svg
  .append('defs')
  .append('clipPath')
    .attr('id', 'clip')
  .append('rect')
    .attr('width', width - padding)
    .attr('height', heightFocus)
    .attr('transform', 'translate(' + padding + ',0)');

var focus = svg.append('g')
  .attr('class', 'focus')
  .attr('transform', 'translate(' + marginFocus.left + ','
    + marginFocus.top + ')');

var context = svg.append('g')
  .attr('class', 'context')
  .attr('transform', 'translate(' + marginContext.left + ','
    + marginContext.top + ')');

d3.csv('unHealth-women.csv', function(error, data) {
  data.forEach(function(d) {
    d.date = parseDate(d.date);
    d.women = +d.women;
  });

  dataset = data;

  // define xScaleFocus's domain now because we want to use
  // the data before we reformat it
  xScaleFocus
    .domain(d3.extent(data, function(d) {
      return d.date;
    }));

  console.log(data);

  yScaleFocus
    .domain(d3.extent(data.map(function(d) {
      return d.women;
    })));

  xScaleContext
    .domain(xScaleFocus.domain());

  yScaleContext
    .domain(yScaleFocus.domain());

  createVis();

}); // end d3.csv();

function createVis() {
  focus
    .append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + heightFocus + ')')
    .call(xAxisFocus);

  focus
    .append('g')
    .attr('class', 'y axis')
    .attr('transform', 'translate(' + padding + ',0)')
    .call(yAxisFocus)

  focus
    .append('path')
    .datum(dataset)
    .attr('class', 'area')
    .attr('d', areaFocus)

  focus
    .selectAll('circle')
    .data(dataset)
    .enter()
    .append('circle')
    .attr('class', 'circle')
    .attr('r', 2)
    .attr('cx', function(d) {
      return xScaleFocus(d.date);
    })
    .attr('cy', function(d) {
      return yScaleFocus(d.women);
    })

  context
    .append('g')
    .attr('class', 'x axis')
    .attr('transform', 'translate(0,' + heightContext + ')')
    .call(xAxisContext)

  context
    .append('g')
    .attr('class', 'y axis')
    .attr('transform', 'translate(' + padding + ',0)')
    .call(yAxisContext)

  context
    .datum(dataset)
    .append('path')
    .attr('class', 'path')
    .attr('d', lineContext)

  context
    .selectAll('circle')
    .data(dataset)
    .enter()
    .append('circle')
    .attr('class', 'circle')
    .attr('r', 2)
    .attr('cx', function(d) {
      return xScaleContext(d.date);
    })
    .attr('cy', function(d) {
      return yScaleContext(d.women);
    })

  context
    .append('g')
    .attr('class', 'brush')
    .call(brush)
    .selectAll('rect')
    .attr('height', heightContext)

}; // end createVis()

function brushed() {
  xScaleFocus
    .domain(brush.empty() ? xScaleContext.domain() : brush.extent());

  focus
    .select('.area')
    .attr('d', areaFocus);

  focus
    .select('.x.axis')
    .call(xAxisFocus);

  focus
    .selectAll('circle')
    .attr('cx', function(d) {
      return xScaleFocus(d.date);
    })
}
<|endoftext|>


<commit_before>var fs = require('fs');
var reader = require('../index.js');
var tape = require('tape');

tape('GeneratePath [cloudfront]', function(assert) {
    var data = [];
    var generatePath = reader.GeneratePath('cloudfront');
    generatePath.on('data', function(d) {
        data.push(d);
    });
    generatePath.on('end', function() {
        assert.equal(data[0], '/a.json?option=1');
        assert.equal(data.length, 1);
        assert.end();
    });
    generatePath.write('2014-09-05	12:48:00	IAD53	33125	54.236.254.12	GET	d3eju24r2ptc5d.cloudfront.net	/a.json	200	https://www.mapbox.com/	FakeAgent	option=1	-	Miss	FAKE==	example.com	http	784	0.314\n');
    generatePath.write('\n');
    generatePath.end();
});
<commit_msg>start test<commit_after>var fs = require('fs');
var reader = require('../index.js');
var tape = require('tape');

tape('GeneratePath [cloudfront]', function(assert) {
    var data = [];
    var generatePath = reader.GeneratePath('cloudfront');
    generatePath.on('data', function(d) {
        data.push(d);
    });
    generatePath.on('end', function() {
        assert.equal(data[0], '/a.json?option=1');
        assert.equal(data.length, 1);
        assert.end();
    });
    generatePath.write('2014-09-05	12:48:00	IAD53	33125	54.236.254.12	GET	d3eju24r2ptc5d.cloudfront.net	/a.json	200	https://www.mapbox.com/	FakeAgent	option=1	-	Miss	FAKE==	example.com	http	784	0.314\n');
    generatePath.write('\n');
    generatePath.end();
});

tape('GeneratePath [elb]', function(assert) {
    var data = [];
    var generatePath = reader.GeneratePath('elb');
    generatePath.on('data', function(d) {
        data.push(d);
    });
    generatePath.on('end', function() {
        assert.equal(data[0], '/a.json?option=1');
        assert.equal(data.length, 1);
        assert.end();
    });
    generatePath.write('\n');
    generatePath.write('\n');
    generatePath.end();
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var help = '';
help += '--- General Purpose ---\n';
help += 'cat \t-- concatenate files.\n';
help += 'cd \t-- change directory.\n';
help += 'ls \t-- list files.\n';
help += 'tree \t-- show directory tree.\n';
help += 'pkg \t-- package management.\n';
help += 'curl \t-- send HTTP/HTTPS requests.\n';
help += 'exit \t-- exit HyperNode.\n';

help += '\n--- File/Folder Management---\n';
help += 'cp \t-- copy a file.\n';
help += 'rm \t-- remove a file.\n';
help += 'rm -r \t-- remove a folder.\n';
help += 'mv \t-- move a file to somewhere.\n';
help += 'mkdir \t-- create a folder.\n';

help += '\n--- File Transfer ---\n';
help += 'push \t-- upload a local file.\n';
help += 'unzip \t-- unzip a zip file.\n';

help += '\n--- Task Management ---\n';
help += 'run \t-- run a long-term task.\n';
help += 'now \t-- run an immediate task.\n';
help += 'tasks \t-- list all running tasks.\n';
help += 'kill \t-- kill a running task.\n';
help += 'show \t-- show stdout of a task.\n';
help += 'error \t-- show stderr of a task.\n';

console.log(help);
<commit_msg>add ifconfig info<commit_after>#!/usr/bin/env node

var help = '';
help += '--- General Purpose ---\n';
help += 'cat \t-- concatenate files.\n';
help += 'cd \t-- change directory.\n';
help += 'ls \t-- list files.\n';
help += 'tree \t-- show directory tree.\n';
help += 'exit \t-- exit HyperNode.\n';

help += '\n--- File/Folder Management---\n';
help += 'cp \t-- copy a file.\n';
help += 'rm \t-- remove a file.\n';
help += 'rm -r \t-- remove a folder.\n';
help += 'mv \t-- move a file to somewhere.\n';
help += 'mkdir \t-- create a folder.\n';

help += '\n--- Networking ---\n';
help += 'pkg \t-- package management.\n';
help += 'curl \t-- send HTTP/HTTPS requests.\n';
help += 'ifconfig \t-- show IP address.\n';

help += '\n--- File Transfer ---\n';
help += 'push \t-- upload a local file.\n';
help += 'unzip \t-- unzip a zip file.\n';

help += '\n--- Task Management ---\n';
help += 'run \t-- run a long-term task.\n';
help += 'now \t-- run an immediate task.\n';
help += 'tasks \t-- list all running tasks.\n';
help += 'kill \t-- kill a running task.\n';
help += 'show \t-- show stdout of a task.\n';
help += 'error \t-- show stderr of a task.\n';

console.log(help);
<|endoftext|>


<commit_before>var _ = require('underscore');
var http = require('http');
var messy = require('messy');
var sinon = require('sinon');
var urlModule = require('url');

function createMockResponse(responseProperties) {
    if (typeof responseProperties === 'object' && responseProperties.body && typeof responseProperties.body === 'string') {
        responseProperties = _.extend({}, responseProperties);
        responseProperties.unchunkedBody = responseProperties.body;
        delete responseProperties.body;
    }
    var mockResponse = new messy.HttpResponse(responseProperties);
    mockResponse.statusCode = mockResponse.statusCode || 200;
    mockResponse.protocolName = mockResponse.protocolName || 'HTTP';
    mockResponse.protocolVersion = mockResponse.protocolVersion || '1.1';
    mockResponse.statusMessage = mockResponse.statusMessage || http.STATUS_CODES[mockResponse.statusCode];
    return mockResponse;
}

function formatHeaderObj(headerObj) {
    var result = {};
    Object.keys(headerObj).forEach(function (headerName) {
        result[messy.formatHeaderName(headerName)] = headerObj[headerName];
    });
    return result;
}

function isTextualHeaders(headers) {
    var message = new messy.Message({headers:{'Content-Type': headers['Content-Type']}});

    return message.hasTextualContentType;
}

function resolveExpectedRequestProperties(expectedRequestProperties) {
    if (typeof expectedRequestProperties === 'string') {
        expectedRequestProperties = { url: expectedRequestProperties };
    } else if (expectedRequestProperties && typeof expectedRequestProperties === 'object') {
        expectedRequestProperties = _.extend({}, expectedRequestProperties);
    }
    if (expectedRequestProperties) {
        if (typeof expectedRequestProperties.url === 'string') {
            var matchMethod = expectedRequestProperties.url.match(/^([A-Z]+) ([\s\S]*)$/);
            if (matchMethod) {
                expectedRequestProperties.method = expectedRequestProperties.method || matchMethod[1];
                expectedRequestProperties.url = matchMethod[2];
            }
        }
    } else {
        expectedRequestProperties = {};
    }
    if (/^https?:\/\//.test(expectedRequestProperties.url)) {
        var urlObj = urlModule.parse(expectedRequestProperties.url);
        expectedRequestProperties.headers = expectedRequestProperties.headers || {};
        if (Object.keys(expectedRequestProperties.headers).every(function (key) {
            return key.toLowerCase() !== 'host';
        })) {
            expectedRequestProperties.headers.Host = urlObj.host;
        }
        expectedRequestProperties.host = expectedRequestProperties.host || urlObj.hostname;
        if (urlObj.port && typeof expectedRequestProperties.port === 'undefined') {
            expectedRequestProperties.port = parseInt(urlObj.port, 10);
        }

        if (urlObj.protocol === 'https:' && typeof expectedRequestProperties.encrypted === 'undefined') {
            expectedRequestProperties.encrypted = true;
        }
        expectedRequestProperties.url = urlObj.path;
    }

    var expectedRequestBody = expectedRequestProperties.body;
    if (Array.isArray(expectedRequestBody) || (expectedRequestBody && typeof expectedRequestBody === 'object')) {
        expectedRequestProperties.headers = expectedRequestProperties.headers || {};
        if (Object.keys(expectedRequestProperties.headers).every(function (key) {
            return key.toLowerCase() !== 'content-type';
        })) {
            expectedRequestProperties.headers['Content-Type'] = 'application/json';
        }
    }
    return expectedRequestProperties;
}

function sendXhrResponse(xhr, mockResponse) {
    var formattedHeaders = formatHeaderObj(mockResponse.headers.valuesByName);
    var responseBody = mockResponse.body;

    if (responseBody && typeof responseBody === 'object') {
        responseBody = JSON.stringify(responseBody);

        if (formattedHeaders['Content-Type'] !== 'application/json') {
            formattedHeaders['Content-Type'] = 'application/json';
        }
    }

    xhr.respond(mockResponse.statusCode, formattedHeaders, responseBody);
}

function stripHeaderCharsetSuffix(headerValue) {
    return headerValue.split(';')[0];
}

function xhrToMockRequest(xhr) {
    var formattedHeaders = formatHeaderObj(xhr.requestHeaders);
    // account for the addition of charset in the sinon fake XHR implementation
    if (formattedHeaders['Content-Type']) {
        var contentType = stripHeaderCharsetSuffix(formattedHeaders['Content-Type']);
        var hasContentTypeSuffix = (formattedHeaders['Content-Type'].length > contentType.length);
        if (hasContentTypeSuffix) {
            formattedHeaders['Content-Type'] = contentType;
        }
    }
    var parsedUrl = urlModule.parse(xhr.url);
    var isEncrypted = (parsedUrl.protocol === 'https:');
    var requestBody = xhr.requestBody;

    // set host in the mock request headers
    if (!formattedHeaders.hasOwnProperty('Host')) {
        formattedHeaders.Host = parsedUrl.hostname;
    }

    if (isTextualHeaders(formattedHeaders)) {
        // make the UInt8Array a Buffer so it is converted by messy
        requestBody = new Buffer(requestBody);
    }

    var requestProperties = {
        method: xhr.method,
        encrypted: isEncrypted,
        host: parsedUrl.hostname,
        path: parsedUrl.path,
        protocolName: 'HTTP',
        protocolVersion: '1.1',
        headers: formattedHeaders,
        unchunkedBody: requestBody
    };

    return new messy.HttpRequest(requestProperties);
}

module.exports = {
    name: 'unexpected-mxhr',
    version: require('../package.json').version,
    installInto: function (expect) {
        expect.use(require('unexpected-messy'));

        expect
            .addAssertion('<any> with xhr mocked out <object|array> <assertion>', function (expect, subject, requestDescriptions) {
                expect.errorMode = 'nested';
                var mockedXhr = sinon.useFakeXMLHttpRequest();

                if (!Array.isArray(requestDescriptions)) {
                    requestDescriptions = [requestDescriptions];
                } else {
                    // duplicate descriptions to allow array consumption
                    requestDescriptions = requestDescriptions.slice(0);
                }

                return expect.promise(function (resolve, reject) {
                    var httpConversation = new messy.HttpConversation();
                    var httpConversationSatisfySpec = {exchanges: []};

                    var __lastError = null;

                    mockedXhr.onCreate = function (xhr) {
                        var requestDescription = requestDescriptions.shift();

                        setTimeout(function () {
                            var expectedRequestProperties;
                            var mockRequest = xhrToMockRequest(xhr);

                            expect.promise(function () {
                                expectedRequestProperties = resolveExpectedRequestProperties(requestDescription && requestDescription.request);
                            }).then(function () {
                                var assertionExchange = new messy.HttpExchange({request: mockRequest});

                                expect.errorMode = 'default';
                                return expect(assertionExchange, 'to satisfy', {request: expectedRequestProperties});
                            }).then(function () {
                                var mockResponse = createMockResponse(requestDescription && requestDescription.response);

                                httpConversation.exchanges.push(new messy.HttpExchange({request: mockRequest, response: mockResponse}));
                                httpConversationSatisfySpec.exchanges.push({request: expectedRequestProperties});

                                sendXhrResponse(xhr, mockResponse);
                            }).caught(function (e) {
                                __lastError = e;

                                // XXX this should be some kind of abort
                                xhr.respond(200);
                            });
                        }, 0);
                    };

                    expect.promise(function () {
                        return expect.shift();
                    }).then(function (fulfilmentValue) {
                        if (__lastError) {
                            return reject(__lastError);
                        }

                        expect.errorMode = 'bubble';
                        expect(httpConversation, 'to satisfy', httpConversationSatisfySpec).then(function () {
                            return fulfilmentValue;
                        }).then(resolve);
                    }).caught(function (e) {
                        if (__lastError) {
                            e = __lastError;
                        }

                        reject(e);
                    });
                }).finally(function () {
                    mockedXhr.restore();
                });
            });
    }
};
<commit_msg>Tie the conversation diff to resolution of the outer assertion.<commit_after>var _ = require('underscore');
var http = require('http');
var messy = require('messy');
var sinon = require('sinon');
var urlModule = require('url');

function createMockResponse(responseProperties) {
    if (typeof responseProperties === 'object' && responseProperties.body && typeof responseProperties.body === 'string') {
        responseProperties = _.extend({}, responseProperties);
        responseProperties.unchunkedBody = responseProperties.body;
        delete responseProperties.body;
    }
    var mockResponse = new messy.HttpResponse(responseProperties);
    mockResponse.statusCode = mockResponse.statusCode || 200;
    mockResponse.protocolName = mockResponse.protocolName || 'HTTP';
    mockResponse.protocolVersion = mockResponse.protocolVersion || '1.1';
    mockResponse.statusMessage = mockResponse.statusMessage || http.STATUS_CODES[mockResponse.statusCode];
    return mockResponse;
}

function formatHeaderObj(headerObj) {
    var result = {};
    Object.keys(headerObj).forEach(function (headerName) {
        result[messy.formatHeaderName(headerName)] = headerObj[headerName];
    });
    return result;
}

function isTextualHeaders(headers) {
    var message = new messy.Message({headers:{'Content-Type': headers['Content-Type']}});

    return message.hasTextualContentType;
}

function resolveExpectedRequestProperties(expectedRequestProperties) {
    if (typeof expectedRequestProperties === 'string') {
        expectedRequestProperties = { url: expectedRequestProperties };
    } else if (expectedRequestProperties && typeof expectedRequestProperties === 'object') {
        expectedRequestProperties = _.extend({}, expectedRequestProperties);
    }
    if (expectedRequestProperties) {
        if (typeof expectedRequestProperties.url === 'string') {
            var matchMethod = expectedRequestProperties.url.match(/^([A-Z]+) ([\s\S]*)$/);
            if (matchMethod) {
                expectedRequestProperties.method = expectedRequestProperties.method || matchMethod[1];
                expectedRequestProperties.url = matchMethod[2];
            }
        }
    } else {
        expectedRequestProperties = {};
    }
    if (/^https?:\/\//.test(expectedRequestProperties.url)) {
        var urlObj = urlModule.parse(expectedRequestProperties.url);
        expectedRequestProperties.headers = expectedRequestProperties.headers || {};
        if (Object.keys(expectedRequestProperties.headers).every(function (key) {
            return key.toLowerCase() !== 'host';
        })) {
            expectedRequestProperties.headers.Host = urlObj.host;
        }
        expectedRequestProperties.host = expectedRequestProperties.host || urlObj.hostname;
        if (urlObj.port && typeof expectedRequestProperties.port === 'undefined') {
            expectedRequestProperties.port = parseInt(urlObj.port, 10);
        }

        if (urlObj.protocol === 'https:' && typeof expectedRequestProperties.encrypted === 'undefined') {
            expectedRequestProperties.encrypted = true;
        }
        expectedRequestProperties.url = urlObj.path;
    }

    var expectedRequestBody = expectedRequestProperties.body;
    if (Array.isArray(expectedRequestBody) || (expectedRequestBody && typeof expectedRequestBody === 'object')) {
        expectedRequestProperties.headers = expectedRequestProperties.headers || {};
        if (Object.keys(expectedRequestProperties.headers).every(function (key) {
            return key.toLowerCase() !== 'content-type';
        })) {
            expectedRequestProperties.headers['Content-Type'] = 'application/json';
        }
    }
    return expectedRequestProperties;
}

function sendXhrResponse(xhr, mockResponse) {
    var formattedHeaders = formatHeaderObj(mockResponse.headers.valuesByName);
    var responseBody = mockResponse.body;

    if (responseBody && typeof responseBody === 'object') {
        responseBody = JSON.stringify(responseBody);

        if (formattedHeaders['Content-Type'] !== 'application/json') {
            formattedHeaders['Content-Type'] = 'application/json';
        }
    }

    xhr.respond(mockResponse.statusCode, formattedHeaders, responseBody);
}

function stripHeaderCharsetSuffix(headerValue) {
    return headerValue.split(';')[0];
}

function xhrToMockRequest(xhr) {
    var formattedHeaders = formatHeaderObj(xhr.requestHeaders);
    // account for the addition of charset in the sinon fake XHR implementation
    if (formattedHeaders['Content-Type']) {
        var contentType = stripHeaderCharsetSuffix(formattedHeaders['Content-Type']);
        var hasContentTypeSuffix = (formattedHeaders['Content-Type'].length > contentType.length);
        if (hasContentTypeSuffix) {
            formattedHeaders['Content-Type'] = contentType;
        }
    }
    var parsedUrl = urlModule.parse(xhr.url);
    var isEncrypted = (parsedUrl.protocol === 'https:');
    var requestBody = xhr.requestBody;

    // set host in the mock request headers
    if (!formattedHeaders.hasOwnProperty('Host')) {
        formattedHeaders.Host = parsedUrl.hostname;
    }

    if (isTextualHeaders(formattedHeaders)) {
        // make the UInt8Array a Buffer so it is converted by messy
        requestBody = new Buffer(requestBody);
    }

    var requestProperties = {
        method: xhr.method,
        encrypted: isEncrypted,
        host: parsedUrl.hostname,
        path: parsedUrl.path,
        protocolName: 'HTTP',
        protocolVersion: '1.1',
        headers: formattedHeaders,
        unchunkedBody: requestBody
    };

    return new messy.HttpRequest(requestProperties);
}

module.exports = {
    name: 'unexpected-mxhr',
    version: require('../package.json').version,
    installInto: function (expect) {
        expect.use(require('unexpected-messy'));

        expect
            .addAssertion('<any> with xhr mocked out <object|array> <assertion>', function (expect, subject, requestDescriptions) {
                expect.errorMode = 'nested';
                var mockedXhr = sinon.useFakeXMLHttpRequest();

                if (!Array.isArray(requestDescriptions)) {
                    requestDescriptions = [requestDescriptions];
                } else {
                    // duplicate descriptions to allow array consumption
                    requestDescriptions = requestDescriptions.slice(0);
                }

                return expect.promise(function (resolve, reject) {
                    var httpConversation = new messy.HttpConversation();
                    var httpConversationSatisfySpec = {exchanges: []};

                    var __lastError = null;

                    mockedXhr.onCreate = function (xhr) {
                        var requestDescription = requestDescriptions.shift();

                        setTimeout(function () {
                            var expectedRequestProperties;
                            var mockRequest = xhrToMockRequest(xhr);

                            expect.promise(function () {
                                expectedRequestProperties = resolveExpectedRequestProperties(requestDescription && requestDescription.request);
                            }).then(function () {
                                var assertionExchange = new messy.HttpExchange({request: mockRequest});

                                expect.errorMode = 'default';
                                return expect(assertionExchange, 'to satisfy', {request: expectedRequestProperties});
                            }).then(function () {
                                var mockResponse = createMockResponse(requestDescription && requestDescription.response);

                                httpConversation.exchanges.push(new messy.HttpExchange({request: mockRequest, response: mockResponse}));
                                httpConversationSatisfySpec.exchanges.push({request: expectedRequestProperties});

                                sendXhrResponse(xhr, mockResponse);
                            }).caught(function (e) {
                                __lastError = e;

                                // XXX this should be some kind of abort
                                xhr.respond(200);
                            });
                        }, 0);
                    };

                    expect.promise(function () {
                        return expect.shift();
                    }).then(function (fulfilmentValue) {
                        if (__lastError) {
                            return reject(__lastError);
                        }

                        resolve([fulfilmentValue, httpConversation, httpConversationSatisfySpec]);
                    }).caught(function (e) {
                        if (__lastError) {
                            e = __lastError;
                        }

                        reject(e);
                    });
                }).spread(function (fulfilmentValue, httpConversation, httpConversationSatisfySpec) {
                    expect.errorMode = 'default';
                    return expect(httpConversation, 'to satisfy', httpConversationSatisfySpec).then(function () {
                        return fulfilmentValue;
                    });
                }).finally(function () {
                    mockedXhr.restore();
                });
            });
    }
};
<|endoftext|>


<commit_before>var moment = require('moment');
var whoAmI = require('./whoAmI');
var config = require('./../config');

var devices = require('./database').devices;

var clearCache = require('./clearCache');

function respond(uuid, callback, sendToken){
  whoAmI(uuid, true, function(check){
    var result = {uuid: uuid};
    if(!check.error){
      result.status = 201;
      result.device = check;
      if(sendToken){
        result.token = check.token;
      }
      callback(result);
    }else{
      result.status = 401;
      callback(result);
    }

  });
}

module.exports = function(socket, callback) {

  var newTimestamp = new Date().getTime();
  if(socket.uuid && socket.token){
    clearCache('DEVICE_'+socket.uuid);

    if (socket.ipAddress){
      try {
        var geoip = require('geoip-lite');
        var geo = geoip.lookup(socket.ipAddress);
      } catch(geoip){
        var geo = null;
      }
    } else {
      var geo = null;
    }

    devices.update({
      uuid: socket.uuid, token: socket.token
    }, {
      $set: {socketid: socket.socketid, online: true, timestamp: moment(newTimestamp).toISOString(), ipAddress: socket.ipAddress, geo: geo, protocol: socket.protocol, secure: socket.secure}
    }, function(err, saved) {

      if(err || saved === 0 || (saved && config.mongo && config.mongo.databaseUrl && !saved.updatedExisting)) {
        console.log('Error: ' + err);
        callback({uuid: socket.uuid, status: 401});
      } else {
        respond(socket.uuid, callback);
      }
    });

  } else {

    if(socket.uuid){
      callback({uuid: socket.uuid, status: 401});
    } else {
      // auto-register device if UUID not provided on authentication
      require('./register')({"autoRegister":true, socketid: socket.socketid, online: true, timestamp: moment(newTimestamp).toISOString(), ipAddress: socket.ipAddress, protocol: socket.protocol, secure: socket.secure}, function(results){
        respond(results.uuid, callback, true);
      });
    }

  }

};
<commit_msg>suppressed mqtt ip address write on authenticate<commit_after>var moment = require('moment');
var whoAmI = require('./whoAmI');
var config = require('./../config');

var devices = require('./database').devices;

var clearCache = require('./clearCache');

function respond(uuid, callback, sendToken){
  whoAmI(uuid, true, function(check){
    var result = {uuid: uuid};
    if(!check.error){
      result.status = 201;
      result.device = check;
      if(sendToken){
        result.token = check.token;
      }
      callback(result);
    }else{
      result.status = 401;
      callback(result);
    }

  });
}

module.exports = function(socket, callback) {

  var newTimestamp = new Date().getTime();
  if(socket.uuid && socket.token){
    clearCache('DEVICE_'+socket.uuid);

    if (socket.ipAddress){
      try {
        var geoip = require('geoip-lite');
        var geo = geoip.lookup(socket.ipAddress);
      } catch(geoip){
        var geo = null;
      }
      var updatedData = {socketid: socket.socketid, online: true, timestamp: moment(newTimestamp).toISOString(), ipAddress: socket.ipAddress, geo: geo, protocol: socket.protocol, secure: socket.secure}
    } else {
      var geo = null;
      var updatedData = {socketid: socket.socketid, online: true, timestamp: moment(newTimestamp).toISOString(), geo: geo, protocol: socket.protocol, secure: socket.secure}
    }

    devices.update({
      uuid: socket.uuid, token: socket.token
    }, {
      $set: updatedData
    }, function(err, saved) {

      if(err || saved === 0 || (saved && config.mongo && config.mongo.databaseUrl && !saved.updatedExisting)) {
        console.log('Error: ' + err);
        callback({uuid: socket.uuid, status: 401});
      } else {
        respond(socket.uuid, callback);
      }
    });

  } else {

    if(socket.uuid){
      callback({uuid: socket.uuid, status: 401});
    } else {
      // auto-register device if UUID not provided on authentication
      require('./register')({"autoRegister":true, socketid: socket.socketid, online: true, timestamp: moment(newTimestamp).toISOString(), ipAddress: socket.ipAddress, protocol: socket.protocol, secure: socket.secure}, function(results){
        respond(results.uuid, callback, true);
      });
    }

  }

};
<|endoftext|>


<commit_before>'use strict';
/* global describe, it, beforeEach */
let assert = require('assert');
let Cycle = require('@cycle/core');
let CycleDOM = require('../../lib/index');
let Rx = require('rx');
let {h, svg, div, p, span, h2, h3, h4, hJSX, select, option, makeDOMDriver} = CycleDOM;

function createRenderTarget(id = null) {
  let element = document.createElement('div');
  element.className = 'cycletest';
  if (id) {
    element.id = id;
  }
  document.body.appendChild(element);
  return element;
}

describe('isolateSource', function () {
  it('should have the same effect as DOM.select()', function (done) {
    function app() {
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            h2('.bar', 'Wrong'),
            div('.cycle-scope-foo', [
              h4('.bar', 'Correct')
            ])
          ])
        )
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });
    const isolatedDOMSource = sources.DOM.isolateSource(sources.DOM, 'foo');

    // Make assertions
    isolatedDOMSource.select('.bar').observable.skip(1).take(1).subscribe(elements => {
      assert.strictEqual(elements.length, 1);
      const correctElement = elements[0];
      assert.notStrictEqual(correctElement, null);
      assert.notStrictEqual(typeof correctElement, 'undefined');
      assert.strictEqual(correctElement.tagName, 'H4');
      assert.strictEqual(correctElement.textContent, 'Correct');
      sources.dispose();
      done();
    });
  });

  it('should return source also with isolateSource and isolateSink', function (done) {
    function app() {
      return {
        DOM: Rx.Observable.just(h('h3.top-most'))
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    const isolatedDOMSource = sources.DOM.isolateSource(sources.DOM, 'top-most');
    // Make assertions
    assert.strictEqual(typeof isolatedDOMSource.isolateSource, 'function');
    assert.strictEqual(typeof isolatedDOMSource.isolateSink, 'function');
    sources.dispose();
    done();
  });
});

describe('isolateSink', function () {
  it('should add a className to the vtree sink', function (done) {
    function app(sources) {
      const vtree$ = Rx.Observable.just(h3('.top-most'));
      return {
        DOM: sources.DOM.isolateSink(vtree$, 'foo'),
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    sources.DOM.select(':root').observable.skip(1).take(1)
      .subscribe(function (root) {
        const element = root.querySelector('.top-most');
        assert.notStrictEqual(element, null);
        assert.notStrictEqual(typeof element, 'undefined');
        assert.strictEqual(element.tagName, 'H3');
        assert.strictEqual(element.className, 'top-most cycle-scope-foo');
        sources.dispose();
        done();
      });
  });

  it('should add a className to a vtree sink that had no className', function (done) {
    function app(sources) {
      const vtree$ = Rx.Observable.just(h3());
      return {
        DOM: sources.DOM.isolateSink(vtree$, 'foo'),
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    sources.DOM.select(':root').observable.skip(1).take(1)
      .subscribe(function (root) {
        const element = root.querySelector('h3');
        assert.notStrictEqual(element, null);
        assert.notStrictEqual(typeof element, 'undefined');
        assert.strictEqual(element.tagName, 'H3');
        assert.strictEqual(element.className, 'cycle-scope-foo');
        sources.dispose();
        done();
      });
  });

  it('should not redundantly repeat the scope className', function (done) {
    function app(sources) {
      const vtree1$ = Rx.Observable.just(span({className: 'tab1'}, 'Hi'));
      const vtree2$ = Rx.Observable.just(span({className: 'tab2'}, 'Hello'));
      const first$ = sources.DOM.isolateSink(vtree1$, '1');
      const second$ = sources.DOM.isolateSink(vtree2$, '2');
      const switched$ = Rx.Observable.concat(
        Rx.Observable.just(1).delay(50),
        Rx.Observable.just(2).delay(50),
        Rx.Observable.just(1).delay(50),
        Rx.Observable.just(2).delay(50),
        Rx.Observable.just(1).delay(50),
        Rx.Observable.just(2).delay(50)
      ).flatMapLatest(i => i === 1 ? first$ : second$);
      return {
        DOM: switched$
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    sources.DOM.select(':root').observable.skip(5).take(1)
      .subscribe(function (root) {
        const element = root.querySelector('span');
        assert.notStrictEqual(element, null);
        assert.notStrictEqual(typeof element, 'undefined');
        assert.strictEqual(element.tagName, 'SPAN');
        assert.strictEqual(element.className, 'tab1 cycle-scope-1');
        sources.dispose();
        done();
      });
  });
});

describe('isolation', function () {
  it('should prevent parent from DOM.selecting() inside the isolation', function (done) {
    function app(sources) {
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            sources.DOM.isolateSink(Rx.Observable.just(
              div('.foo', [
                h4('.bar', 'Wrong')
              ])
            ), 'ISOLATION'),
            h2('.bar', 'Correct'),
          ])
        )
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    sources.DOM.select('.bar').observable.skip(1).take(1).subscribe(function (elements) {
      assert.strictEqual(Array.isArray(elements), true);
      assert.strictEqual(elements.length, 1);
      const correctElement = elements[0];
      assert.notStrictEqual(correctElement, null);
      assert.notStrictEqual(typeof correctElement, 'undefined');
      assert.strictEqual(correctElement.tagName, 'H2');
      assert.strictEqual(correctElement.textContent, 'Correct');
      done();
    });
  });

  it('should allow parent to DOM.select() in its own isolation island', function (done) {
    function app(sources) {
      const {isolateSource, isolateSink} = sources.DOM;
      const islandElement$ = isolateSource(sources.DOM, 'island')
        .select('.bar').observable;
      const islandVTree$ = isolateSink(
        Rx.Observable.just(div([h3('.bar', 'Correct')])), 'island'
      );
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            sources.DOM.isolateSink(Rx.Observable.just(
              div('.foo', [
                islandVTree$,
                h4('.bar', 'Wrong')
              ])
            ), 'ISOLATION'),
          ])
        ),
        island: islandElement$
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    sinks.island.skip(1).take(1).subscribe(function (elements) {
      assert.strictEqual(Array.isArray(elements), true);
      assert.strictEqual(elements.length, 1);
      const correctElement = elements[0];
      assert.notStrictEqual(correctElement, null);
      assert.notStrictEqual(typeof correctElement, 'undefined');
      assert.strictEqual(correctElement.tagName, 'H3');
      assert.strictEqual(correctElement.textContent, 'Correct');
      done();
    });
  });

  it('should isolate DOM.select between parent and (wrapper) child', function (done) {
    function Frame(sources) {
      const click$ = sources.DOM.select('.foo').events('click');
      const vtree$ = Rx.Observable.just(
        h4('.foo.frame', {style: {backgroundColor: 'lightblue'}}, [
          sources.content$
        ])
      );
      return {
        DOM: vtree$,
        click$
      };
    }

    function Monalisa(sources) {
      const {isolateSource, isolateSink} = sources.DOM;

      const islandDOMSource = isolateSource(sources.DOM, 'island');
      const click$ = islandDOMSource.select('.foo').events('click');
      const islandDOMSink$ = isolateSink(
        Rx.Observable.just(span('.foo.monalisa', 'Monalisa')),
        'island'
      );

      const frameDOMSource = isolateSource(sources.DOM, 'myFrame');
      const frame = Frame({ DOM: frameDOMSource, content$: islandDOMSink$ });
      const outerVTree$ = isolateSink(frame.DOM, 'myFrame');

      return {
        DOM: outerVTree$,
        frameClick: frame.click$,
        monalisaClick: click$
      };
    }

    const {sources, sinks} = Cycle.run(Monalisa, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    const frameClick$ = sinks.frameClick.map(ev => ({
      type: ev.type,
      tagName: ev.target.tagName
    }));

    const monalisaClick$ = sinks.monalisaClick.map(ev => ({
      type: ev.type,
      tagName: ev.target.tagName
    }));

    // Stop the propagtion of the first click
    sinks.monalisaClick.first().subscribe(ev => ev.stopPropagation());

    // The frame should be notified about 2 clicks:
    //  1. the second click on monalisa (whose propagation has not stopped)
    //  2. the only click on the frame itself
    frameClick$.take(2).sequenceEqual(
      Rx.Observable.fromArray([
        {type: 'click', tagName: 'SPAN'},
        {type: 'click', tagName: 'H4'},
      ])
    ).subscribe(isEqual => {
      assert.strictEqual(isEqual, true);
      sources.dispose();
      done();
    });

    // Monalisa should receive two clicks
    monalisaClick$.take(2).sequenceEqual(
      Rx.Observable.fromArray([
        {type: 'click', tagName: 'SPAN'},
        {type: 'click', tagName: 'SPAN'},
      ])
    ).subscribe(isEqual => {
      assert.strictEqual(isEqual, true);
    });

    sources.DOM.select(':root').observable.skip(1).take(1).subscribe(root => {
      const frameFoo = root.querySelector('.foo.frame');
      const monalisaFoo = root.querySelector('.foo.monalisa');
      assert.notStrictEqual(frameFoo, null);
      assert.notStrictEqual(monalisaFoo, null);
      assert.notStrictEqual(typeof frameFoo, 'undefined');
      assert.notStrictEqual(typeof monalisaFoo, 'undefined');
      assert.strictEqual(frameFoo.tagName, 'H4');
      assert.strictEqual(monalisaFoo.tagName, 'SPAN');
      assert.doesNotThrow(() => {
        monalisaFoo.click();
        monalisaFoo.click();
        setTimeout(() => frameFoo.click(), 0);
      });
    });
  });

  it('should allow a child component to DOM.select() its own root', function (done) {
    function app(sources) {
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            sources.DOM.isolateSink(Rx.Observable.just(
              span('.foo', [
                h4('.bar', 'Wrong')
              ])
            ), 'ISOLATION')
          ])
        )
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    const {isolateSource} = sources.DOM;

    isolateSource(sources.DOM, 'ISOLATION')
      .select('.foo').observable
      .skip(1).take(1)
      .subscribe(function (elements) {
        assert.strictEqual(Array.isArray(elements), true);
        assert.strictEqual(elements.length, 1);
        const correctElement = elements[0];
        assert.notStrictEqual(correctElement, null);
        assert.notStrictEqual(typeof correctElement, 'undefined');
        assert.strictEqual(correctElement.tagName, 'SPAN');
        done();
      });
  });

  it('should allow DOM.selecting svg elements', function (done) {
    function App(sources) {
      const triangleElement$ = sources.DOM.select('.triangle').observable;

      const svgTriangle = svg('svg', {width: 150, height: 150}, [
        svg('polygon', {
          class: 'triangle',
          attributes: {
            points: '20 0 20 150 150 20'
          }
        }),
      ]);

      return {
        DOM: Rx.Observable.just(svgTriangle),
        triangleElement: triangleElement$
      };
    }

    function IsolatedApp(sources) {
      const {isolateSource, isolateSink} = sources.DOM
      const isolatedDOMSource = isolateSource(sources.DOM, 'ISOLATION');
      const app = App({DOM: isolatedDOMSource});
      const isolateDOMSink = isolateSink(app.DOM, 'ISOLATION');
      return {
        DOM: isolateDOMSink,
        triangleElement: app.triangleElement
      };
    }

    const {sinks, sources} = Cycle.run(IsolatedApp, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    const selection = sinks.triangleElement.skip(1).take(1).subscribe(elements => {
      assert.strictEqual(elements.length, 1);
      const triangleElement = elements[0];
      assert.notStrictEqual(triangleElement, null);
      assert.notStrictEqual(typeof triangleElement, 'undefined');
      assert.strictEqual(triangleElement.tagName, 'polygon');
      done();
    });
  });
});
<commit_msg>Adapt an isolation test case for snabbdom<commit_after>'use strict';
/* global describe, it, beforeEach */
let assert = require('assert');
let Cycle = require('@cycle/core');
let CycleDOM = require('../../lib/index');
let Rx = require('rx');
let {h, svg, div, p, span, h2, h3, h4, hJSX, select, option, makeDOMDriver} = CycleDOM;

function createRenderTarget(id = null) {
  let element = document.createElement('div');
  element.className = 'cycletest';
  if (id) {
    element.id = id;
  }
  document.body.appendChild(element);
  return element;
}

describe('isolateSource', function () {
  it('should have the same effect as DOM.select()', function (done) {
    function app() {
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            h2('.bar', 'Wrong'),
            div('.cycle-scope-foo', [
              h4('.bar', 'Correct')
            ])
          ])
        )
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });
    const isolatedDOMSource = sources.DOM.isolateSource(sources.DOM, 'foo');

    // Make assertions
    isolatedDOMSource.select('.bar').observable.skip(1).take(1).subscribe(elements => {
      assert.strictEqual(elements.length, 1);
      const correctElement = elements[0];
      assert.notStrictEqual(correctElement, null);
      assert.notStrictEqual(typeof correctElement, 'undefined');
      assert.strictEqual(correctElement.tagName, 'H4');
      assert.strictEqual(correctElement.textContent, 'Correct');
      sources.dispose();
      done();
    });
  });

  it('should return source also with isolateSource and isolateSink', function (done) {
    function app() {
      return {
        DOM: Rx.Observable.just(h('h3.top-most'))
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    const isolatedDOMSource = sources.DOM.isolateSource(sources.DOM, 'top-most');
    // Make assertions
    assert.strictEqual(typeof isolatedDOMSource.isolateSource, 'function');
    assert.strictEqual(typeof isolatedDOMSource.isolateSink, 'function');
    sources.dispose();
    done();
  });
});

describe('isolateSink', function () {
  it('should add a className to the vtree sink', function (done) {
    function app(sources) {
      const vtree$ = Rx.Observable.just(h3('.top-most'));
      return {
        DOM: sources.DOM.isolateSink(vtree$, 'foo'),
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    sources.DOM.select(':root').observable.skip(1).take(1)
      .subscribe(function (root) {
        const element = root.querySelector('.top-most');
        assert.notStrictEqual(element, null);
        assert.notStrictEqual(typeof element, 'undefined');
        assert.strictEqual(element.tagName, 'H3');
        assert.strictEqual(element.className, 'top-most cycle-scope-foo');
        sources.dispose();
        done();
      });
  });

  it('should add a className to a vtree sink that had no className', function (done) {
    function app(sources) {
      const vtree$ = Rx.Observable.just(h3());
      return {
        DOM: sources.DOM.isolateSink(vtree$, 'foo'),
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    sources.DOM.select(':root').observable.skip(1).take(1)
      .subscribe(function (root) {
        const element = root.querySelector('h3');
        assert.notStrictEqual(element, null);
        assert.notStrictEqual(typeof element, 'undefined');
        assert.strictEqual(element.tagName, 'H3');
        assert.strictEqual(element.className, 'cycle-scope-foo');
        sources.dispose();
        done();
      });
  });

  it('should not redundantly repeat the scope className', function (done) {
    function app(sources) {
      const vtree1$ = Rx.Observable.just(span('.tab1', 'Hi'));
      const vtree2$ = Rx.Observable.just(span('.tab2', 'Hello'));
      const first$ = sources.DOM.isolateSink(vtree1$, '1');
      const second$ = sources.DOM.isolateSink(vtree2$, '2');
      const switched$ = Rx.Observable.concat(
        Rx.Observable.just(1).delay(50),
        Rx.Observable.just(2).delay(50),
        Rx.Observable.just(1).delay(50),
        Rx.Observable.just(2).delay(50),
        Rx.Observable.just(1).delay(50),
        Rx.Observable.just(2).delay(50)
      ).flatMapLatest(i => i === 1 ? first$ : second$);
      return {
        DOM: switched$
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    sources.DOM.select(':root').observable.skip(5).take(1)
      .subscribe(function (root) {
        const element = root.querySelector('span');
        assert.notStrictEqual(element, null);
        assert.notStrictEqual(typeof element, 'undefined');
        assert.strictEqual(element.tagName, 'SPAN');
        assert.strictEqual(element.className, 'tab1 cycle-scope-1');
        sources.dispose();
        done();
      });
  });
});

describe('isolation', function () {
  it('should prevent parent from DOM.selecting() inside the isolation', function (done) {
    function app(sources) {
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            sources.DOM.isolateSink(Rx.Observable.just(
              div('.foo', [
                h4('.bar', 'Wrong')
              ])
            ), 'ISOLATION'),
            h2('.bar', 'Correct'),
          ])
        )
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    sources.DOM.select('.bar').observable.skip(1).take(1).subscribe(function (elements) {
      assert.strictEqual(Array.isArray(elements), true);
      assert.strictEqual(elements.length, 1);
      const correctElement = elements[0];
      assert.notStrictEqual(correctElement, null);
      assert.notStrictEqual(typeof correctElement, 'undefined');
      assert.strictEqual(correctElement.tagName, 'H2');
      assert.strictEqual(correctElement.textContent, 'Correct');
      done();
    });
  });

  it('should allow parent to DOM.select() in its own isolation island', function (done) {
    function app(sources) {
      const {isolateSource, isolateSink} = sources.DOM;
      const islandElement$ = isolateSource(sources.DOM, 'island')
        .select('.bar').observable;
      const islandVTree$ = isolateSink(
        Rx.Observable.just(div([h3('.bar', 'Correct')])), 'island'
      );
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            sources.DOM.isolateSink(Rx.Observable.just(
              div('.foo', [
                islandVTree$,
                h4('.bar', 'Wrong')
              ])
            ), 'ISOLATION'),
          ])
        ),
        island: islandElement$
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    sinks.island.skip(1).take(1).subscribe(function (elements) {
      assert.strictEqual(Array.isArray(elements), true);
      assert.strictEqual(elements.length, 1);
      const correctElement = elements[0];
      assert.notStrictEqual(correctElement, null);
      assert.notStrictEqual(typeof correctElement, 'undefined');
      assert.strictEqual(correctElement.tagName, 'H3');
      assert.strictEqual(correctElement.textContent, 'Correct');
      done();
    });
  });

  it('should isolate DOM.select between parent and (wrapper) child', function (done) {
    function Frame(sources) {
      const click$ = sources.DOM.select('.foo').events('click');
      const vtree$ = Rx.Observable.just(
        h4('.foo.frame', {style: {backgroundColor: 'lightblue'}}, [
          sources.content$
        ])
      );
      return {
        DOM: vtree$,
        click$
      };
    }

    function Monalisa(sources) {
      const {isolateSource, isolateSink} = sources.DOM;

      const islandDOMSource = isolateSource(sources.DOM, 'island');
      const click$ = islandDOMSource.select('.foo').events('click');
      const islandDOMSink$ = isolateSink(
        Rx.Observable.just(span('.foo.monalisa', 'Monalisa')),
        'island'
      );

      const frameDOMSource = isolateSource(sources.DOM, 'myFrame');
      const frame = Frame({ DOM: frameDOMSource, content$: islandDOMSink$ });
      const outerVTree$ = isolateSink(frame.DOM, 'myFrame');

      return {
        DOM: outerVTree$,
        frameClick: frame.click$,
        monalisaClick: click$
      };
    }

    const {sources, sinks} = Cycle.run(Monalisa, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    const frameClick$ = sinks.frameClick.map(ev => ({
      type: ev.type,
      tagName: ev.target.tagName
    }));

    const monalisaClick$ = sinks.monalisaClick.map(ev => ({
      type: ev.type,
      tagName: ev.target.tagName
    }));

    // Stop the propagtion of the first click
    sinks.monalisaClick.first().subscribe(ev => ev.stopPropagation());

    // The frame should be notified about 2 clicks:
    //  1. the second click on monalisa (whose propagation has not stopped)
    //  2. the only click on the frame itself
    frameClick$.take(2).sequenceEqual(
      Rx.Observable.fromArray([
        {type: 'click', tagName: 'SPAN'},
        {type: 'click', tagName: 'H4'},
      ])
    ).subscribe(isEqual => {
      assert.strictEqual(isEqual, true);
      sources.dispose();
      done();
    });

    // Monalisa should receive two clicks
    monalisaClick$.take(2).sequenceEqual(
      Rx.Observable.fromArray([
        {type: 'click', tagName: 'SPAN'},
        {type: 'click', tagName: 'SPAN'},
      ])
    ).subscribe(isEqual => {
      assert.strictEqual(isEqual, true);
    });

    sources.DOM.select(':root').observable.skip(1).take(1).subscribe(root => {
      const frameFoo = root.querySelector('.foo.frame');
      const monalisaFoo = root.querySelector('.foo.monalisa');
      assert.notStrictEqual(frameFoo, null);
      assert.notStrictEqual(monalisaFoo, null);
      assert.notStrictEqual(typeof frameFoo, 'undefined');
      assert.notStrictEqual(typeof monalisaFoo, 'undefined');
      assert.strictEqual(frameFoo.tagName, 'H4');
      assert.strictEqual(monalisaFoo.tagName, 'SPAN');
      assert.doesNotThrow(() => {
        monalisaFoo.click();
        monalisaFoo.click();
        setTimeout(() => frameFoo.click(), 0);
      });
    });
  });

  it('should allow a child component to DOM.select() its own root', function (done) {
    function app(sources) {
      return {
        DOM: Rx.Observable.just(
          h3('.top-most', [
            sources.DOM.isolateSink(Rx.Observable.just(
              span('.foo', [
                h4('.bar', 'Wrong')
              ])
            ), 'ISOLATION')
          ])
        )
      };
    }

    const {sinks, sources} = Cycle.run(app, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    const {isolateSource} = sources.DOM;

    isolateSource(sources.DOM, 'ISOLATION')
      .select('.foo').observable
      .skip(1).take(1)
      .subscribe(function (elements) {
        assert.strictEqual(Array.isArray(elements), true);
        assert.strictEqual(elements.length, 1);
        const correctElement = elements[0];
        assert.notStrictEqual(correctElement, null);
        assert.notStrictEqual(typeof correctElement, 'undefined');
        assert.strictEqual(correctElement.tagName, 'SPAN');
        done();
      });
  });

  it('should allow DOM.selecting svg elements', function (done) {
    function App(sources) {
      const triangleElement$ = sources.DOM.select('.triangle').observable;

      const svgTriangle = svg('svg', {width: 150, height: 150}, [
        svg('polygon', {
          class: 'triangle',
          attributes: {
            points: '20 0 20 150 150 20'
          }
        }),
      ]);

      return {
        DOM: Rx.Observable.just(svgTriangle),
        triangleElement: triangleElement$
      };
    }

    function IsolatedApp(sources) {
      const {isolateSource, isolateSink} = sources.DOM
      const isolatedDOMSource = isolateSource(sources.DOM, 'ISOLATION');
      const app = App({DOM: isolatedDOMSource});
      const isolateDOMSink = isolateSink(app.DOM, 'ISOLATION');
      return {
        DOM: isolateDOMSink,
        triangleElement: app.triangleElement
      };
    }

    const {sinks, sources} = Cycle.run(IsolatedApp, {
      DOM: makeDOMDriver(createRenderTarget())
    });

    // Make assertions
    const selection = sinks.triangleElement.skip(1).take(1).subscribe(elements => {
      assert.strictEqual(elements.length, 1);
      const triangleElement = elements[0];
      assert.notStrictEqual(triangleElement, null);
      assert.notStrictEqual(typeof triangleElement, 'undefined');
      assert.strictEqual(triangleElement.tagName, 'polygon');
      done();
    });
  });
});
<|endoftext|>


<commit_before>var Promise = require('bluebird');
var eval = require('./evaluation.js');
var utils = require('./utilities.js');

module.exports.evalForAllInputSizes = function(req, res, next) {
  var userInput = req.body.data;
  var dataType = req.params.dataType || null;

  return new Promise(function(resolve, reject) {
    var data = eval.evalAlg(userInput, dataType);
    resolve(data)
  })
  .then(function(data) {
    res.body = {};

    // TODO: integrate jon's bigO module
    res.body.bigO = null;

    res.body.name = utils.getFuncName(userInput);
    res.body.eq = eval.runRegression(data, null);
    var coords = eval.getJSONCoords(data);
    res.body.coords = coords;
    next();
  });
};

module.exports.testAlgo = function(req, res, next) {
  var userInput = req.body.data;
  var testArray = [10,9,8,7,6,5,4,3,2,1];
  var ordArray = [1,2,3,4,5,6,7,8,9,10];

  // Test if UserInput can be built
  try {
    console.log('Try One');
    var param = userInput.slice(userInput.indexOf('(') + 1, userInput.indexOf(')'));
    var algString = userInput.slice(userInput.indexOf('{') + 1, userInput.lastIndexOf('}'));
    var userAlg = new Function(param, algString);
    if (!algString || !param) res.status(200).send("Error! No param or function body.");
  } catch(e) {
    if (e instanceof SyntaxError) {
      console.log('caught Syntax error, couldn\'t make function');
      console.log(e);
      res.status(200).send("Error! Your code is not a function");
    }
    return;
  }
  // Test if Built function can be run
  try {
    console.log('try2');
    var userAlg = utils.memoBuild(userInput);
    userAlg(testArray)
  } catch(e) {
    if (e instanceof SyntaxError) {
      console.log('caught Syntax error, function didn\'t run');
      console.log(e);
      res.status(200).send("Error! That is not an executable function.")
    }
    return;
  }
  var result = userAlg(testArray);
  if (result.join() === ordArray.join()) {
    console.log('alg passed');
    next();
  } else {
    res.status(200).send("Error! Your function doesn't sort.");
  }
};
<commit_msg>[feature] error handling edge case<commit_after>var Promise = require('bluebird');
var eval = require('./evaluation.js');
var utils = require('./utilities.js');

module.exports.evalForAllInputSizes = function(req, res, next) {
  var userInput = req.body.data;
  var dataType = req.params.dataType || null;

  return new Promise(function(resolve, reject) {
    var data = eval.evalAlg(userInput, dataType);
    resolve(data)
  })
  .then(function(data) {
    res.body = {};

    // TODO: integrate jon's bigO module
    res.body.bigO = null;

    res.body.name = utils.getFuncName(userInput);
    res.body.eq = eval.runRegression(data, null);
    var coords = eval.getJSONCoords(data);
    res.body.coords = coords;
    next();
  });
};

module.exports.testAlgo = function(req, res, next) {
  var userInput = req.body.data;
  var testArray = [10,9,8,7,6,5,4,3,2,1];
  var ordArray = [1,2,3,4,5,6,7,8,9,10];

  // Test if UserInput can be built
  try {
    console.log('Try One');
    var param = userInput.slice(userInput.indexOf('(') + 1, userInput.indexOf(')'));
    var algString = userInput.slice(userInput.indexOf('{') + 1, userInput.lastIndexOf('}'));
    var userAlg = new Function(param, algString);
    if (!algString || !param) res.status(200).send("Error! No param or function body.");
  } catch(e) {
    if (e instanceof SyntaxError) {
      console.log('caught Syntax error, couldn\'t make function');
      console.log(e);
      res.status(200).send("Error! Your code is not a function");
    }
    return;
  }
  // Test if Built function can be run
  try {
    console.log('try2');
    // utils.memoBuild(userInput);
    // userAlg(testArray);
    var param = userInput.slice(userInput.indexOf('(') + 1, userInput.indexOf(')'));
    var algString = userInput.slice(userInput.indexOf('{') + 1, userInput.lastIndexOf('}'));
    var userAlg = new Function(param, algString);
    userAlg(testArray);
  } catch(e) {
    if (e instanceof SyntaxError) {
      console.log('caught Syntax error, function didn\'t run');
      console.log(e);
      res.status(200).send("Error! That is not an executable function.")
    }
    return;
  }
  var result = userAlg(testArray);
  if (result.join() === ordArray.join()) {
    console.log('alg passed');
    next();
  } else {
    res.status(200).send("Error! Your function doesn't sort.");
  }
};
<|endoftext|>


<commit_before>// Anytime you change the schema of one of the collection in a non-backward
// compatible way you have to write a migration in this file using the following
// API:
//
//   Migrations.add(name, migrationCallback, optionalOrder);

// Note that we have extra migrations defined in `sandstorm.js` that are
// exclusive to Sandstorm and shouldn’t be executed in the general case.
// XXX I guess if we had ES6 modules we could
// `import { isSandstorm } from sandstorm.js` and define the migration here as
// well, but for now I want to avoid definied too many globals.

// In the context of migration functions we don't want to validate database
// mutation queries against the current (ie, latest) collection schema. Doing
// that would work at the time we write the migration but would break in the
// future when we'll update again the concerned collection schema.
//
// To prevent this bug we always have to disable the schema validation and
// argument transformations. We generally use the shorthandlers defined below.
const noValidate = {
  validate: false,
  filter: false,
  autoConvert: false,
  removeEmptyStrings: false,
  getAutoValues: false,
};
const noValidateMulti = { ...noValidate, multi: true };

Migrations.add('board-background-color', () => {
  const defaultColor = '#16A085';
  Boards.update({
    background: {
      $exists: false,
    },
  }, {
    $set: {
      background: {
        type: 'color',
        color: defaultColor,
      },
    },
  }, noValidateMulti);
});

Migrations.add('lowercase-board-permission', () => {
  ['Public', 'Private'].forEach((permission) => {
    Boards.update(
      { permission },
      { $set: { permission: permission.toLowerCase() } },
      noValidateMulti
    );
  });
});

// Security migration: see https://github.com/wekan/wekan/issues/99
Migrations.add('change-attachments-type-for-non-images', () => {
  const newTypeForNonImage = 'application/octet-stream';
  Attachments.find().forEach((file) => {
    if (!file.isImage()) {
      Attachments.update(file._id, {
        $set: {
          'original.type': newTypeForNonImage,
          'copies.attachments.type': newTypeForNonImage,
        },
      }, noValidate);
    }
  });
});

Migrations.add('card-covers', () => {
  Cards.find().forEach((card) => {
    const cover =  Attachments.findOne({ cardId: card._id, cover: true });
    if (cover) {
      Cards.update(card._id, {$set: {coverId: cover._id}}, noValidate);
    }
  });
  Attachments.update({}, {$unset: {cover: ''}}, noValidateMulti);
});

Migrations.add('use-css-class-for-boards-colors', () => {
  const associationTable = {
    '#27AE60': 'nephritis',
    '#C0392B': 'pomegranate',
    '#2980B9': 'belize',
    '#8E44AD': 'wisteria',
    '#2C3E50': 'midnight',
    '#E67E22': 'pumpkin',
  };
  Boards.find().forEach((board) => {
    const oldBoardColor = board.background.color;
    const newBoardColor = associationTable[oldBoardColor];
    Boards.update(board._id, {
      $set: { color: newBoardColor },
      $unset: { background: '' },
    }, noValidate);
  });
});

Migrations.add('denormalize-star-number-per-board', () => {
  Boards.find().forEach((board) => {
    const nStars = Users.find({'profile.starredBoards': board._id}).count();
    Boards.update(board._id, {$set: {stars: nStars}}, noValidate);
  });
});

// We want to keep a trace of former members so we can efficiently publish their
// infos in the general board publication.
Migrations.add('add-member-isactive-field', () => {
  Boards.find({}, {fields: {members: 1}}).forEach((board) => {
    const allUsersWithSomeActivity = _.chain(
      Activities.find({ boardId: board._id }, { fields:{ userId:1 }}).fetch())
      .pluck('userId')
      .uniq()
      .value();
    const currentUsers = _.pluck(board.members, 'userId');
    const formerUsers = _.difference(allUsersWithSomeActivity, currentUsers);

    const newMemberSet = [];
    board.members.forEach((member) => {
      member.isActive = true;
      newMemberSet.push(member);
    });
    formerUsers.forEach((userId) => {
      newMemberSet.push({
        userId,
        isAdmin: false,
        isActive: false,
      });
    });
    Boards.update(board._id, {$set: {members: newMemberSet}}, noValidate);
  });
});

Migrations.add('add-sort-checklists', () => {
  Checklists.find().forEach((checklist, index) => {
    if (!checklist.hasOwnProperty('sort')) {
      Checklists.direct.update(
        checklist._id,
        { $set: { sort: index } },
        noValidate
      );
    }
    checklist.items.forEach((item, index) => {
      if (!item.hasOwnProperty('sort')) {
        Checklists.direct.update(
          { _id: checklist._id, 'items._id': item._id },
          { $set: { 'items.$.sort': index } },
          noValidate
        );
      }
    });
  });
});

Migrations.add('add-swimlanes', () => {
  Boards.forEach((board) => {
    const swimlaneId = board.getDefaultSwimline()._id;
    Cards.find({ boardId: board._id }).forEach((card) => {
      if (!card.hasOwnProperty('swimlaneId')) {
        Cards.direct.update(
          { _id: card._id },
          { $set: { swimlaneId } },
          noValidate
        );
      }
    });
  });
});

Migrations.add('add-views', () => {
  Boards.find().forEach((board) => {
    if (!board.hasOwnProperty('view')) {
      Boards.direct.update(
        { _id: board._id },
        { $set: { view: 'board-view-swimlanes' } },
        noValidate
      );
    }
  });
});

Migrations.add('add-checklist-items', () => {
  Checklists.find().forEach((checklist) => {
    // Create new items
    _.sortBy(checklist.items, 'sort').forEach((item, index) => {
      ChecklistItems.direct.insert({
        title: item.title,
        sort: index,
        isFinished: item.isFinished,
        checklistId: checklist._id,
        cardId: checklist.cardId,
      });
    });

    // Delete old ones
    Checklists.direct.update({ _id: checklist._id },
      { $unset: { items : 1 } },
      noValidate
    );
  });
});

Migrations.add('add-profile-view', () => {
  Users.find().forEach((user) => {
    if (!user.hasOwnProperty('profile.boardView')) {
      // Set default view
      Users.direct.update(
        { _id: user._id },
        { $set: { 'profile.boardView': 'board-view-lists' } },
        noValidate
      );
    }
  });
});

Migrations.add('add-custom-fields-to-cards', () => {
  Cards.update({
    customFields: {
      $exists: false,
    },
  }, {
    $set: {
      customFields:[],
    },
  }, noValidateMulti);
});

Migrations.add('add-requester-field', () => {
  Cards.update({
    requestedBy: {
      $exists: false,
    },
  }, {
    $set: {
      requestedBy:'',
    },
  }, noValidateMulti);
});

Migrations.add('add-assigner-field', () => {
  Cards.update({
    assignedBy: {
      $exists: false,
    },
  }, {
    $set: {
      assignedBy:'',
    },
  }, noValidateMulti);
});

Migrations.add('add-parent-field-to-cards', () => {
  Cards.update({
    parentId: {
      $exists: false,
    },
  }, {
    $set: {
      parentId:'',
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-boards', () => {
  Boards.update({
    subtasksDefaultBoardId: {
      $exists: false,
    },
  }, {
    $set: {
      subtasksDefaultBoardId: null,
      subtasksDefaultListId: null,
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-sort', () => {
  Boards.update({
    subtaskSort: {
      $exists: false,
    },
  }, {
    $set: {
      subtaskSort: -1,
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-allowed', () => {
  Boards.update({
    allowsSubtasks: {
      $exists: false,
    },
  }, {
    $set: {
      allowsSubtasks: true,
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-allowed', () => {
  Boards.update({
    presentParentTask: {
      $exists: false,
    },
  }, {
    $set: {
      presentParentTask: 'no-parent',
    },
  }, noValidateMulti);
});
<commit_msg>- Fix: Boards.forEach is not function.<commit_after>// Anytime you change the schema of one of the collection in a non-backward
// compatible way you have to write a migration in this file using the following
// API:
//
//   Migrations.add(name, migrationCallback, optionalOrder);

// Note that we have extra migrations defined in `sandstorm.js` that are
// exclusive to Sandstorm and shouldn’t be executed in the general case.
// XXX I guess if we had ES6 modules we could
// `import { isSandstorm } from sandstorm.js` and define the migration here as
// well, but for now I want to avoid definied too many globals.

// In the context of migration functions we don't want to validate database
// mutation queries against the current (ie, latest) collection schema. Doing
// that would work at the time we write the migration but would break in the
// future when we'll update again the concerned collection schema.
//
// To prevent this bug we always have to disable the schema validation and
// argument transformations. We generally use the shorthandlers defined below.
const noValidate = {
  validate: false,
  filter: false,
  autoConvert: false,
  removeEmptyStrings: false,
  getAutoValues: false,
};
const noValidateMulti = { ...noValidate, multi: true };

Migrations.add('board-background-color', () => {
  const defaultColor = '#16A085';
  Boards.update({
    background: {
      $exists: false,
    },
  }, {
    $set: {
      background: {
        type: 'color',
        color: defaultColor,
      },
    },
  }, noValidateMulti);
});

Migrations.add('lowercase-board-permission', () => {
  ['Public', 'Private'].forEach((permission) => {
    Boards.update(
      { permission },
      { $set: { permission: permission.toLowerCase() } },
      noValidateMulti
    );
  });
});

// Security migration: see https://github.com/wekan/wekan/issues/99
Migrations.add('change-attachments-type-for-non-images', () => {
  const newTypeForNonImage = 'application/octet-stream';
  Attachments.find().forEach((file) => {
    if (!file.isImage()) {
      Attachments.update(file._id, {
        $set: {
          'original.type': newTypeForNonImage,
          'copies.attachments.type': newTypeForNonImage,
        },
      }, noValidate);
    }
  });
});

Migrations.add('card-covers', () => {
  Cards.find().forEach((card) => {
    const cover =  Attachments.findOne({ cardId: card._id, cover: true });
    if (cover) {
      Cards.update(card._id, {$set: {coverId: cover._id}}, noValidate);
    }
  });
  Attachments.update({}, {$unset: {cover: ''}}, noValidateMulti);
});

Migrations.add('use-css-class-for-boards-colors', () => {
  const associationTable = {
    '#27AE60': 'nephritis',
    '#C0392B': 'pomegranate',
    '#2980B9': 'belize',
    '#8E44AD': 'wisteria',
    '#2C3E50': 'midnight',
    '#E67E22': 'pumpkin',
  };
  Boards.find().forEach((board) => {
    const oldBoardColor = board.background.color;
    const newBoardColor = associationTable[oldBoardColor];
    Boards.update(board._id, {
      $set: { color: newBoardColor },
      $unset: { background: '' },
    }, noValidate);
  });
});

Migrations.add('denormalize-star-number-per-board', () => {
  Boards.find().forEach((board) => {
    const nStars = Users.find({'profile.starredBoards': board._id}).count();
    Boards.update(board._id, {$set: {stars: nStars}}, noValidate);
  });
});

// We want to keep a trace of former members so we can efficiently publish their
// infos in the general board publication.
Migrations.add('add-member-isactive-field', () => {
  Boards.find({}, {fields: {members: 1}}).forEach((board) => {
    const allUsersWithSomeActivity = _.chain(
      Activities.find({ boardId: board._id }, { fields:{ userId:1 }}).fetch())
      .pluck('userId')
      .uniq()
      .value();
    const currentUsers = _.pluck(board.members, 'userId');
    const formerUsers = _.difference(allUsersWithSomeActivity, currentUsers);

    const newMemberSet = [];
    board.members.forEach((member) => {
      member.isActive = true;
      newMemberSet.push(member);
    });
    formerUsers.forEach((userId) => {
      newMemberSet.push({
        userId,
        isAdmin: false,
        isActive: false,
      });
    });
    Boards.update(board._id, {$set: {members: newMemberSet}}, noValidate);
  });
});

Migrations.add('add-sort-checklists', () => {
  Checklists.find().forEach((checklist, index) => {
    if (!checklist.hasOwnProperty('sort')) {
      Checklists.direct.update(
        checklist._id,
        { $set: { sort: index } },
        noValidate
      );
    }
    checklist.items.forEach((item, index) => {
      if (!item.hasOwnProperty('sort')) {
        Checklists.direct.update(
          { _id: checklist._id, 'items._id': item._id },
          { $set: { 'items.$.sort': index } },
          noValidate
        );
      }
    });
  });
});

Migrations.add('add-swimlanes', () => {
  Boards.find().forEach((board) => {
    const swimlaneId = board.getDefaultSwimline()._id;
    Cards.find({ boardId: board._id }).forEach((card) => {
      if (!card.hasOwnProperty('swimlaneId')) {
        Cards.direct.update(
          { _id: card._id },
          { $set: { swimlaneId } },
          noValidate
        );
      }
    });
  });
});

Migrations.add('add-views', () => {
  Boards.find().forEach((board) => {
    if (!board.hasOwnProperty('view')) {
      Boards.direct.update(
        { _id: board._id },
        { $set: { view: 'board-view-swimlanes' } },
        noValidate
      );
    }
  });
});

Migrations.add('add-checklist-items', () => {
  Checklists.find().forEach((checklist) => {
    // Create new items
    _.sortBy(checklist.items, 'sort').forEach((item, index) => {
      ChecklistItems.direct.insert({
        title: item.title,
        sort: index,
        isFinished: item.isFinished,
        checklistId: checklist._id,
        cardId: checklist.cardId,
      });
    });

    // Delete old ones
    Checklists.direct.update({ _id: checklist._id },
      { $unset: { items : 1 } },
      noValidate
    );
  });
});

Migrations.add('add-profile-view', () => {
  Users.find().forEach((user) => {
    if (!user.hasOwnProperty('profile.boardView')) {
      // Set default view
      Users.direct.update(
        { _id: user._id },
        { $set: { 'profile.boardView': 'board-view-lists' } },
        noValidate
      );
    }
  });
});

Migrations.add('add-custom-fields-to-cards', () => {
  Cards.update({
    customFields: {
      $exists: false,
    },
  }, {
    $set: {
      customFields:[],
    },
  }, noValidateMulti);
});

Migrations.add('add-requester-field', () => {
  Cards.update({
    requestedBy: {
      $exists: false,
    },
  }, {
    $set: {
      requestedBy:'',
    },
  }, noValidateMulti);
});

Migrations.add('add-assigner-field', () => {
  Cards.update({
    assignedBy: {
      $exists: false,
    },
  }, {
    $set: {
      assignedBy:'',
    },
  }, noValidateMulti);
});

Migrations.add('add-parent-field-to-cards', () => {
  Cards.update({
    parentId: {
      $exists: false,
    },
  }, {
    $set: {
      parentId:'',
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-boards', () => {
  Boards.update({
    subtasksDefaultBoardId: {
      $exists: false,
    },
  }, {
    $set: {
      subtasksDefaultBoardId: null,
      subtasksDefaultListId: null,
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-sort', () => {
  Boards.update({
    subtaskSort: {
      $exists: false,
    },
  }, {
    $set: {
      subtaskSort: -1,
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-allowed', () => {
  Boards.update({
    allowsSubtasks: {
      $exists: false,
    },
  }, {
    $set: {
      allowsSubtasks: true,
    },
  }, noValidateMulti);
});

Migrations.add('add-subtasks-allowed', () => {
  Boards.update({
    presentParentTask: {
      $exists: false,
    },
  }, {
    $set: {
      presentParentTask: 'no-parent',
    },
  }, noValidateMulti);
});
<|endoftext|>


<commit_before>"use strict";

var utils = require('./../../../utils');

var mdash = require('mdash');
var yandex = require('yandex-translate');

mdash.endpoint = 'http://nko.io/mdash';

function typographer(text) {
  return function(fn) {
    mdash.apply(text, fn);
  };
}

function translate(text, key) {
  return function(fn) {
    yandex(text, {to: 'en', key: key}, fn);
  };
}

// yamb.prototype.save()

module.exports = function(priv, opts) {
  return function *save() {
    if (this.id && utils.empty(this.json(true))) {
      // nothing to update
      return this;
    }

    if (!this.title) {
      // TODO: fix error message
      throw new Error('Fill title field');
    }

    if (!this.preview) {
      // TODO: fix error message
      throw new Error('Fill preview field');
    }

    if (!this.text) {
      // TODO: fix error message
      throw new Error('Fill text field');
    }

    var typo = {};
    if (this[priv.flags].title) {
      typo.title = this.title;
    }

    if (this[priv.flags].preview) {
      typo.preview = this.preview;
    }

    if (this[priv.flags].text) {
      typo.text = this.text;
    }

    var async = {};
    if (!utils.empty(typo)) {
      async.typo = typographer(typo);
    }

    if (!this.uri && opts.yapi) {
      async.slug = translate(this.title, opts.yapi);
    }

    if (!utils.empty(async)) {
      var data = yield async;

      if (data.typo) {
        if (data.typo.title) {
          this.title = data.typo.title;
        }

        if (data.typo.preview) {
          this.preview = data.typo.preview;
        }

        if (data.typo.text) {
          this.text = data.typo.text;
        }
      }

      if (data.slug) {
        this.uri = data.slug.text && data.slug.text[0] || '';
      }
    }

    if (!this.uri) {
      // TODO: fix error message
      throw new Error('Uri not exists');
    }

    if (this[priv.flags].related && !utils.empty(this.related)) {
      var posts = yield opts.storage.find({id: {$in: this.related}}, {sort: {created: -1}});
      var related = [];

      if (!utils.empty(posts)) {
        for (var i=0, length=posts.length; i<length; i++) {
          related[related.length] = '' + (posts[i]._id || posts[i].id);
        }
      }

      this[priv.symbl].related = related;
    }

    if (!this.publish && this.active) {
      this.publish = new Date();
    }

    var result;

    if (this.id) {
      result = yield opts.storage.update({id: this.id}, {$set: this.json(true)});
    } else {
      result = yield opts.storage.save(this.json());
    }

    if (result === false) {
      return false;
    }

    if (!this.id && (result._id || result.id)) {
      this[priv.symbl].id = result._id || result.id;
    }

    return this.reset();
  };
};<commit_msg>Remove sort for related checks<commit_after>"use strict";

var utils = require('./../../../utils');

var mdash = require('mdash');
var yandex = require('yandex-translate');

mdash.endpoint = 'http://nko.io/mdash';

function typographer(text) {
  return function(fn) {
    mdash.apply(text, fn);
  };
}

function translate(text, key) {
  return function(fn) {
    yandex(text, {to: 'en', key: key}, fn);
  };
}

// yamb.prototype.save()

module.exports = function(priv, opts) {
  return function *save() {
    if (this.id && utils.empty(this.json(true))) {
      // nothing to update
      return this;
    }

    if (!this.title) {
      // TODO: fix error message
      throw new Error('Fill title field');
    }

    if (!this.preview) {
      // TODO: fix error message
      throw new Error('Fill preview field');
    }

    if (!this.text) {
      // TODO: fix error message
      throw new Error('Fill text field');
    }

    var typo = {};
    if (this[priv.flags].title) {
      typo.title = this.title;
    }

    if (this[priv.flags].preview) {
      typo.preview = this.preview;
    }

    if (this[priv.flags].text) {
      typo.text = this.text;
    }

    var async = {};
    if (!utils.empty(typo)) {
      async.typo = typographer(typo);
    }

    if (!this.uri && opts.yapi) {
      async.slug = translate(this.title, opts.yapi);
    }

    if (!utils.empty(async)) {
      var data = yield async;

      if (data.typo) {
        if (data.typo.title) {
          this.title = data.typo.title;
        }

        if (data.typo.preview) {
          this.preview = data.typo.preview;
        }

        if (data.typo.text) {
          this.text = data.typo.text;
        }
      }

      if (data.slug) {
        this.uri = data.slug.text && data.slug.text[0] || '';
      }
    }

    if (!this.uri) {
      // TODO: fix error message
      throw new Error('Uri not exists');
    }

    if (this[priv.flags].related && !utils.empty(this.related)) {
      var posts = yield opts.storage.find({id: {$in: this.related}});
      var related = [];

      if (!utils.empty(posts)) {
        for (var i=0, length=posts.length; i<length; i++) {
          related[related.length] = '' + (posts[i]._id || posts[i].id);
        }
      }

      this[priv.symbl].related = related;
    }

    if (!this.publish && this.active) {
      this.publish = new Date();
    }

    var result;

    if (this.id) {
      result = yield opts.storage.update({id: this.id}, {$set: this.json(true)});
    } else {
      result = yield opts.storage.save(this.json());
    }

    if (result === false) {
      return false;
    }

    if (!this.id && (result._id || result.id)) {
      this[priv.symbl].id = '' + (result._id || result.id);
    }

    return this.reset();
  };
};<|endoftext|>