<commit_before>/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Observable } from "rxjs/Observable";

import { bytesToStr } from "../../../utils/bytes";
import { resolveURL } from "../../../utils/url";
import request from "../../../utils/request";

import createSmoothStreamingParser from "./parser";
import { parseBif } from "../../parsers/bif";
import { parseSami } from "../../parsers/texttracks/sami.js";
import { parseTTML } from "../../parsers/texttracks/ttml.js";

import mp4Utils from "./mp4.js";
import parsedRequest from "./request.js";
import {
  extractISML,
  extractToken,
  replaceToken,
  resolveManifest,
  buildSegmentURL,
} from "./utils.js";
import extractTimingsInfos from "./isobmff_timings_infos.js";
import generateSegmentLoader from "./segment_loader.js";

const {
  patchSegment,
  getMdat,
} = mp4Utils;

const TT_PARSERS = {
  "application/x-sami":       parseSami,
  "application/smil":         parseSami,
  "application/ttml+xml":     parseTTML,
  "application/ttml+xml+mp4": parseTTML,
  "text/vtt":                 (text) => text,
};

const WSX_REG = /\.wsx?(\?token=\S+)?/;

export default function(options={}) {
  const smoothManifestParser = createSmoothStreamingParser(options);
  const segmentLoader = generateSegmentLoader(options.segmentLoader);

  const manifestPipeline = {
    resolver({ url }) {
      let resolving;
      const token = extractToken(url);

      // TODO Remove WSX logic
      if (WSX_REG.test(url)) {
        resolving = request({
          url: replaceToken(url, ""),
          responseType: "document",
          ignoreProgressEvents: true,
        })
          .map(({ value }) => value)
          .map(extractISML); // TODO remove completely
      }
      else {
        resolving = Observable.of(url);
      }

      return resolving
        .map((url) => ({ url: replaceToken(resolveManifest(url), token) }));
    },

    loader({ url }) {
      return parsedRequest({
        url,
        responseType: "document",
      });
    },

    parser({ response }) {
      const manifest = smoothManifestParser(response.responseData);
      return Observable.of({ manifest, url: response.url });
    },
  };

  const segmentPipeline = {
    loader({ segment, representation, adaptation, manifest }) {
      return segmentLoader({
        segment,
        representation,
        adaptation,
        manifest,
      });
    },

    parser({ segment, response, manifest }) {
      const { responseData } = response;

      if (segment.isInit) {
        // smooth init segments are crafted by hand. Their timescale is the one
        // from the manifest.
        const segmentInfos = {
          timescale: segment.timescale,
          time: -1,
          duration: 0,
        };
        return Observable.of({ segmentData: responseData, segmentInfos });
      }

      const responseBuffer = new Uint8Array(responseData);
      const { nextSegments, segmentInfos } =
        extractTimingsInfos(responseBuffer, segment, manifest.isLive);
      const segmentData = patchSegment(responseBuffer, segmentInfos.time);
      return Observable.of({ segmentData, segmentInfos, nextSegments });
    },
  };

  const textTrackPipeline = {
    loader({ segment, representation }) {
      if (segment.isInit) {
        return Observable.empty();
      }

      const { mimeType } = representation;
      const base = resolveURL(representation.baseURL);
      const url = buildSegmentURL(base, representation, segment);

      if (mimeType.indexOf("mp4") >= 0) {
        // in case of TTML declared inside playlists, the TTML file is
        // embededded inside an mp4 fragment.
        return parsedRequest({ url, responseType: "arraybuffer" });
      } else {
        return parsedRequest({ url, responseType: "text" });
      }
    },

    parser({ response, segment, representation, adaptation, manifest }) {
      const { language } = adaptation;
      const { mimeType } = representation;

      const ttParser = TT_PARSERS[mimeType];
      if (!ttParser) {
        throw new Error(
          `could not find a text-track parser for the type ${mimeType}`
        );
      }

      let responseData = response.responseData;
      let text;
      // in case of TTML declared inside playlists, the TTML file is
      // embededded inside an mp4 fragment.
      if (mimeType.indexOf("mp4") >= 0) {
        responseData = new Uint8Array(responseData);
        text = bytesToStr(getMdat(responseData));
      } else {
        // vod is simple WebVTT or TTML text
        text = responseData;
      }

      const { nextSegments, segmentInfos } =
        extractTimingsInfos(responseData, segment, manifest.isLive);
      const segmentData =
        ttParser(text, language, segment.time / segment.timescale);

      return Observable.of({ segmentData, segmentInfos, nextSegments });
    },
  };

  const imageTrackPipeline = {
    loader({ segment, representation }) {
      if (segment.isInit) {
        return Observable.empty();
      } else {
        const baseURL = resolveURL(representation.baseURL);
        const url = buildSegmentURL(baseURL, representation, segment);
        return parsedRequest({ url, responseType: "arraybuffer" });
      }
    },

    parser({ response }) {
      const responseData = response.responseData;
      const blob = new Uint8Array(responseData);

      const segmentInfos = {
        time: 0,
        duration: Number.MAX_VALUE,
      };

      let segmentData;
      if (blob) {
        const bif = parseBif(blob);
        segmentData = bif.thumbs;
        segmentInfos.timescale = bif.timescale;

        // var firstThumb = blob[0];
        // var lastThumb  = blob[blob.length - 1];

        // segmentInfos = {
        //   time: firstThumb.ts,
        //   duration: lastThumb.ts
        // };
      }

      return Observable.of({ segmentData, segmentInfos });
    },
  };

  return {
    directFile: false,
    manifest: manifestPipeline,
    audio: segmentPipeline,
    video: segmentPipeline,
    text: textTrackPipeline,
    image: imageTrackPipeline,
  };
}
<commit_msg>smooth: fix bug with webvtt subtitles<commit_after>/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { Observable } from "rxjs/Observable";

import { bytesToStr } from "../../../utils/bytes";
import { resolveURL } from "../../../utils/url";
import request from "../../../utils/request";

import createSmoothStreamingParser from "./parser";
import { parseBif } from "../../parsers/bif";
import { parseSami } from "../../parsers/texttracks/sami.js";
import { parseTTML } from "../../parsers/texttracks/ttml.js";

import mp4Utils from "./mp4.js";
import parsedRequest from "./request.js";
import {
  extractISML,
  extractToken,
  replaceToken,
  resolveManifest,
  buildSegmentURL,
} from "./utils.js";
import extractTimingsInfos from "./isobmff_timings_infos.js";
import generateSegmentLoader from "./segment_loader.js";

const {
  patchSegment,
  getMdat,
} = mp4Utils;

const TT_PARSERS = {
  "application/x-sami":       parseSami,
  "application/smil":         parseSami,
  "application/ttml+xml":     parseTTML,
  "application/ttml+xml+mp4": parseTTML,
  "text/vtt":                 (text) => text,
};

const WSX_REG = /\.wsx?(\?token=\S+)?/;

export default function(options={}) {
  const smoothManifestParser = createSmoothStreamingParser(options);
  const segmentLoader = generateSegmentLoader(options.segmentLoader);

  const manifestPipeline = {
    resolver({ url }) {
      let resolving;
      const token = extractToken(url);

      // TODO Remove WSX logic
      if (WSX_REG.test(url)) {
        resolving = request({
          url: replaceToken(url, ""),
          responseType: "document",
          ignoreProgressEvents: true,
        })
          .map(({ value }) => value)
          .map(extractISML); // TODO remove completely
      }
      else {
        resolving = Observable.of(url);
      }

      return resolving
        .map((url) => ({ url: replaceToken(resolveManifest(url), token) }));
    },

    loader({ url }) {
      return parsedRequest({
        url,
        responseType: "document",
      });
    },

    parser({ response }) {
      const manifest = smoothManifestParser(response.responseData);
      return Observable.of({ manifest, url: response.url });
    },
  };

  const segmentPipeline = {
    loader({ segment, representation, adaptation, manifest }) {
      return segmentLoader({
        segment,
        representation,
        adaptation,
        manifest,
      });
    },

    parser({ segment, response, manifest }) {
      const { responseData } = response;

      if (segment.isInit) {
        // smooth init segments are crafted by hand. Their timescale is the one
        // from the manifest.
        const segmentInfos = {
          timescale: segment.timescale,
          time: -1,
          duration: 0,
        };
        return Observable.of({ segmentData: responseData, segmentInfos });
      }

      const responseBuffer = new Uint8Array(responseData);
      const { nextSegments, segmentInfos } =
        extractTimingsInfos(responseBuffer, segment, manifest.isLive);
      const segmentData = patchSegment(responseBuffer, segmentInfos.time);
      return Observable.of({ segmentData, segmentInfos, nextSegments });
    },
  };

  const textTrackPipeline = {
    loader({ segment, representation }) {
      if (segment.isInit) {
        return Observable.empty();
      }

      const { mimeType } = representation;
      const base = resolveURL(representation.baseURL);
      const url = buildSegmentURL(base, representation, segment);

      if (mimeType.indexOf("mp4") >= 0) {
        // in case of TTML declared inside playlists, the TTML file is
        // embededded inside an mp4 fragment.
        return parsedRequest({ url, responseType: "arraybuffer" });
      } else {
        return parsedRequest({ url, responseType: "text" });
      }
    },

    parser({ response, segment, representation, adaptation, manifest }) {
      const { language } = adaptation;
      const { mimeType } = representation;

      const ttParser = TT_PARSERS[mimeType];
      if (!ttParser) {
        throw new Error(
          `could not find a text-track parser for the type ${mimeType}`
        );
      }

      let responseData = response.responseData;
      let text;
      let nextSegments, segmentInfos;

      // in case of TTML declared inside playlists, the TTML file is
      // embededded inside an mp4 fragment.
      if (mimeType.indexOf("mp4") >= 0) {
        responseData = new Uint8Array(responseData);
        text = bytesToStr(getMdat(responseData));
        const timings =
          extractTimingsInfos(responseData, segment, manifest.isLive);

        nextSegments = timings.nextSegments;
        segmentInfos = timings.segmentInfos;
      } else {
        // vod is simple WebVTT or TTML text
        text = responseData;
      }

      const segmentData =
        ttParser(text, language, segment.time / segment.timescale);

      return Observable.of({ segmentData, segmentInfos, nextSegments });
    },
  };

  const imageTrackPipeline = {
    loader({ segment, representation }) {
      if (segment.isInit) {
        return Observable.empty();
      } else {
        const baseURL = resolveURL(representation.baseURL);
        const url = buildSegmentURL(baseURL, representation, segment);
        return parsedRequest({ url, responseType: "arraybuffer" });
      }
    },

    parser({ response }) {
      const responseData = response.responseData;
      const blob = new Uint8Array(responseData);

      const segmentInfos = {
        time: 0,
        duration: Number.MAX_VALUE,
      };

      let segmentData;
      if (blob) {
        const bif = parseBif(blob);
        segmentData = bif.thumbs;
        segmentInfos.timescale = bif.timescale;

        // var firstThumb = blob[0];
        // var lastThumb  = blob[blob.length - 1];

        // segmentInfos = {
        //   time: firstThumb.ts,
        //   duration: lastThumb.ts
        // };
      }

      return Observable.of({ segmentData, segmentInfos });
    },
  };

  return {
    directFile: false,
    manifest: manifestPipeline,
    audio: segmentPipeline,
    video: segmentPipeline,
    text: textTrackPipeline,
    image: imageTrackPipeline,
  };
}
<|endoftext|>


<commit_before>var express = require('express')();
var http = require('http').Server(express);
var io = require('socket.io')(http);
var dateFormat = require('dateformat');

var PORT = 8000;

var clients = [];

//express http server
express.get('/', function(req, res)
{
	res.sendFile(__dirname + '/index.html');
});

//eventsio
io.on('connection', function(socket)
{
    writeLog('Connection recieved. ' + socket.request.connection.remoteAddress + ":" + socket.request.connection.remotePort + "?id=" + socket.id);

	//all clients are required to identify themselves with a username
	socket.on("client_connect", function(data)
    {
		var user = {};
		user.socket = socket;
		user.socketId = socket.id;
        user.username = data.username;
		clients.push(user);
		writeLog('Client registered. ' + user.username + "@" + user.socketId);
	});

	//client events
	socket.on('disconnect', function()
    {

        writeLog('Client disconnected. id=' + socket.id);

        //remove user
        for (var i = 0; i < clients.length; i++)
        {

			if (clients[i].socketId === socket.id)
            {
				clients.splice(i, 1);
				return;
			}
		}

        //should never be here if client registered
		writeLog("Warning, could not find disconnected user. id=" + socket.id);
    });

	//message from client
	socket.on('message', function(msg)
    {

        writeLog('Message recieved: ' + JSON.stringify(msg));

        var username = msg.username;
        var subject = msg.subject;
        var selfDeliver = msg.selfDeliver;
        var fields = msg.fields;

        //send to self
        if (selfDeliver == true)
        {
            socket.emit('message', msg);
        }

        //forward to appropriate users
        for (var i = 0; i < clients.length; i++)
        {
            var user = clients[i];

            //send to other devices of same username but not to self
            if (user.username == username && user.socketId != socket.id)
            {
                console.log('socket.id = ' + user.socketId);
                user.socket.emit('message', data);
            }
        }

	});

});

//start server
http.listen(PORT, function()
{
	console.log('listening on *:' + PORT);
});

//===============================
//Utility Functions

function writeLog(msg) {
    console.log('[' + timeStamp() + '] ' + msg);
}

function timeStamp()
{
    return dateFormat(new Date(), 'yyyy-mm-dd HH:MM.ss.l');
}<commit_msg>Fix server error with undefined message<commit_after>var express = require('express')();
var http = require('http').Server(express);
var io = require('socket.io')(http);
var dateFormat = require('dateformat');

var PORT = 8000;

var clients = [];

//express http server
express.get('/', function(req, res)
{
	res.sendFile(__dirname + '/index.html');
});

//eventsio
io.on('connection', function(socket)
{
    writeLog('Connection recieved. ' + socket.request.connection.remoteAddress + ":" + socket.request.connection.remotePort + "?id=" + socket.id);

	//all clients are required to identify themselves with a username
	socket.on("client_connect", function(data)
    {
		var user = {};
		user.socket = socket;
		user.socketId = socket.id;
        user.username = data.username;
		clients.push(user);
		writeLog('Client registered. ' + user.username + "@" + user.socketId);
	});

	//client events
	socket.on('disconnect', function()
    {

        writeLog('Client disconnected. id=' + socket.id);

        //remove user
        for (var i = 0; i < clients.length; i++)
        {

			if (clients[i].socketId === socket.id)
            {
				clients.splice(i, 1);
				return;
			}
		}

        //should never be here if client registered
		writeLog("Warning, could not find disconnected user. id=" + socket.id);
    });

	//message from client
	socket.on('message', function(msg)
    {

        writeLog('Message recieved: ' + JSON.stringify(msg));

        var username = msg.username;
        var subject = msg.subject;
        var selfDeliver = msg.selfDeliver;
        var fields = msg.fields;

        //send to self
        if (selfDeliver == true)
        {
            socket.emit('message', msg);
        }

        //forward to appropriate users
        for (var i = 0; i < clients.length; i++)
        {
            var user = clients[i];

            //send to other devices of same username but not to self
            if (user.username == username && user.socketId != socket.id)
            {
                console.log('socket.id = ' + user.socketId);
                user.socket.emit('message', msg);
            }
        }

	});

});

//start server
http.listen(PORT, function()
{
	console.log('listening on *:' + PORT);
});

//===============================
//Utility Functions

function writeLog(msg) {
    console.log('[' + timeStamp() + '] ' + msg);
}

function timeStamp()
{
    return dateFormat(new Date(), 'yyyy-mm-dd HH:MM.ss.l');
}<|endoftext|>


<commit_before>import React from 'react';
import {shallow} from 'enzyme';
import {parse as parseDiff} from 'what-the-diff';

import rawDiff from '../fixtures/diffs/raw-diff';
import {buildMultiFilePatch} from '../../lib/models/patch';
import {getEndpoint} from '../../lib/models/endpoint';

import PullRequestChangedFilesContainer from '../../lib/containers/pr-changed-files-container';
import IssueishDetailItem from '../../lib/items/issueish-detail-item';

describe('PullRequestChangedFilesContainer', function() {
  let diffResponse;

  function buildApp(overrideProps = {}) {
    return (
      <PullRequestChangedFilesContainer
        owner="atom"
        repo="github"
        number={1804}
        token="1234"
        endpoint={getEndpoint('github.com')}
        itemType={IssueishDetailItem}
        destroy={() => {}}
        shouldRefetch={false}
        workspace={{}}
        commands={{}}
        keymaps={{}}
        tooltips={{}}
        config={{}}
        localRepository={{}}
        {...overrideProps}
      />
    );
  }

  function setDiffResponse(body) {
    diffResponse = new window.Response(body, {
      status: 200,
      headers: {'Content-type': 'text/plain'},
    });
  }

  describe('when the data is able to be fetched successfully', function() {
    beforeEach(function() {
      setDiffResponse(rawDiff);
      sinon.stub(window, 'fetch').callsFake(() => Promise.resolve(diffResponse));
    });
    it('renders a loading spinner if data has not yet been fetched', function() {
      const wrapper = shallow(buildApp());
      assert.isTrue(wrapper.find('LoadingView').exists());
    });
    it('passes extra props through to PullRequestChangedFilesController', async function() {
      const extraProp = Symbol('really really extra');

      const wrapper = shallow(buildApp({extraProp}));
      await assert.async.isTrue(wrapper.update().find('MultiFilePatchController').exists());

      const controller = wrapper.find('MultiFilePatchController');
      assert.strictEqual(controller.prop('extraProp'), extraProp);
    });

    it('builds the diff URL', function() {
      const wrapper = shallow(buildApp({
        owner: 'smashwilson',
        repo: 'pushbot',
        number: 12,
        endpoint: getEndpoint('github.com'),
      }));

      const diffURL = wrapper.instance().getDiffURL();
      assert.strictEqual(diffURL, 'https://api.github.com/repos/smashwilson/pushbot/pulls/12');
    });

    it('passes loaded diff data through to the controller', async function() {
      const wrapper = shallow(buildApp({
        token: '4321',
      }));
      await assert.async.isTrue(wrapper.update().find('MultiFilePatchController').exists());

      const controller = wrapper.find('MultiFilePatchController');
      const expected = buildMultiFilePatch(parseDiff(rawDiff));
      assert.isTrue(controller.prop('multiFilePatch').isEqual(expected));

      assert.deepEqual(window.fetch.lastCall.args, [
        'https://api.github.com/repos/atom/github/pulls/1804',
        {
          headers: {
            Accept: 'application/vnd.github.v3.diff',
            Authorization: 'bearer 4321',
          },
        },
      ]);
    });
    it('re fetches data when shouldRefetch is true', async function() {
      const wrapper = shallow(buildApp());
      await assert.async.isTrue(wrapper.update().find('MultiFilePatchController').exists());
      assert.strictEqual(window.fetch.callCount, 1);
      wrapper.setProps({shouldRefetch: true});
      assert.isTrue(wrapper.instance().state.isLoading);
      await assert.async.strictEqual(window.fetch.callCount, 2);
      });
    });

  describe('error states', function() {
    async function assertErrorRendered(expectedErrorMessage, wrapper) {
      await assert.async.deepEqual(wrapper.update().instance().state.error, expectedErrorMessage);
      const errorView = wrapper.find('ErrorView');
      assert.deepEqual(errorView.prop('descriptions'), [expectedErrorMessage]);
    }
    it('renders an error if network request fails', async function() {
      sinon.stub(window, 'fetch').callsFake(() => Promise.reject(new Error('oh shit')));
      const wrapper = shallow(buildApp());
      await assertErrorRendered('Network error encountered at fetching https://api.github.com/repos/atom/github/pulls/1804', wrapper);
    });

    it('renders an error if diff parsing fails', async function() {
      setDiffResponse('bad diff no treat for you');
      sinon.stub(window, 'fetch').callsFake(() => Promise.resolve(diffResponse));
      const wrapper = shallow(buildApp());
      await assertErrorRendered('Unable to parse diff for this pull request.', wrapper);
    });

    it('renders an error if fetch returns a non-ok response', async function() {
      const badResponse = new window.Response(rawDiff, {
        status: 404,
        statusText: 'oh noes',
        headers: {'Content-type': 'text/plain'},
      });
      sinon.stub(window, 'fetch').callsFake(() => Promise.resolve(badResponse));
      const wrapper = shallow(buildApp());
      await assertErrorRendered('Unable to fetch diff for this pull request: oh noes.', wrapper);
    });
  });
});
<commit_msg>:shirt:<commit_after>import React from 'react';
import {shallow} from 'enzyme';
import {parse as parseDiff} from 'what-the-diff';

import rawDiff from '../fixtures/diffs/raw-diff';
import {buildMultiFilePatch} from '../../lib/models/patch';
import {getEndpoint} from '../../lib/models/endpoint';

import PullRequestChangedFilesContainer from '../../lib/containers/pr-changed-files-container';
import IssueishDetailItem from '../../lib/items/issueish-detail-item';

describe('PullRequestChangedFilesContainer', function() {
  let diffResponse;

  function buildApp(overrideProps = {}) {
    return (
      <PullRequestChangedFilesContainer
        owner="atom"
        repo="github"
        number={1804}
        token="1234"
        endpoint={getEndpoint('github.com')}
        itemType={IssueishDetailItem}
        destroy={() => {}}
        shouldRefetch={false}
        workspace={{}}
        commands={{}}
        keymaps={{}}
        tooltips={{}}
        config={{}}
        localRepository={{}}
        {...overrideProps}
      />
    );
  }

  function setDiffResponse(body) {
    diffResponse = new window.Response(body, {
      status: 200,
      headers: {'Content-type': 'text/plain'},
    });
  }

  describe('when the data is able to be fetched successfully', function() {
    beforeEach(function() {
      setDiffResponse(rawDiff);
      sinon.stub(window, 'fetch').callsFake(() => Promise.resolve(diffResponse));
    });
    it('renders a loading spinner if data has not yet been fetched', function() {
      const wrapper = shallow(buildApp());
      assert.isTrue(wrapper.find('LoadingView').exists());
    });
    it('passes extra props through to PullRequestChangedFilesController', async function() {
      const extraProp = Symbol('really really extra');

      const wrapper = shallow(buildApp({extraProp}));
      await assert.async.isTrue(wrapper.update().find('MultiFilePatchController').exists());

      const controller = wrapper.find('MultiFilePatchController');
      assert.strictEqual(controller.prop('extraProp'), extraProp);
    });

    it('builds the diff URL', function() {
      const wrapper = shallow(buildApp({
        owner: 'smashwilson',
        repo: 'pushbot',
        number: 12,
        endpoint: getEndpoint('github.com'),
      }));

      const diffURL = wrapper.instance().getDiffURL();
      assert.strictEqual(diffURL, 'https://api.github.com/repos/smashwilson/pushbot/pulls/12');
    });

    it('passes loaded diff data through to the controller', async function() {
      const wrapper = shallow(buildApp({
        token: '4321',
      }));
      await assert.async.isTrue(wrapper.update().find('MultiFilePatchController').exists());

      const controller = wrapper.find('MultiFilePatchController');
      const expected = buildMultiFilePatch(parseDiff(rawDiff));
      assert.isTrue(controller.prop('multiFilePatch').isEqual(expected));

      assert.deepEqual(window.fetch.lastCall.args, [
        'https://api.github.com/repos/atom/github/pulls/1804',
        {
          headers: {
            Accept: 'application/vnd.github.v3.diff',
            Authorization: 'bearer 4321',
          },
        },
      ]);
    });
    it('re fetches data when shouldRefetch is true', async function() {
      const wrapper = shallow(buildApp());
      await assert.async.isTrue(wrapper.update().find('MultiFilePatchController').exists());
      assert.strictEqual(window.fetch.callCount, 1);
      wrapper.setProps({shouldRefetch: true});
      assert.isTrue(wrapper.instance().state.isLoading);
      await assert.async.strictEqual(window.fetch.callCount, 2);
    });
  });

  describe('error states', function() {
    async function assertErrorRendered(expectedErrorMessage, wrapper) {
      await assert.async.deepEqual(wrapper.update().instance().state.error, expectedErrorMessage);
      const errorView = wrapper.find('ErrorView');
      assert.deepEqual(errorView.prop('descriptions'), [expectedErrorMessage]);
    }
    it('renders an error if network request fails', async function() {
      sinon.stub(window, 'fetch').callsFake(() => Promise.reject(new Error('oh shit')));
      const wrapper = shallow(buildApp());
      await assertErrorRendered('Network error encountered at fetching https://api.github.com/repos/atom/github/pulls/1804', wrapper);
    });

    it('renders an error if diff parsing fails', async function() {
      setDiffResponse('bad diff no treat for you');
      sinon.stub(window, 'fetch').callsFake(() => Promise.resolve(diffResponse));
      const wrapper = shallow(buildApp());
      await assertErrorRendered('Unable to parse diff for this pull request.', wrapper);
    });

    it('renders an error if fetch returns a non-ok response', async function() {
      const badResponse = new window.Response(rawDiff, {
        status: 404,
        statusText: 'oh noes',
        headers: {'Content-type': 'text/plain'},
      });
      sinon.stub(window, 'fetch').callsFake(() => Promise.resolve(badResponse));
      const wrapper = shallow(buildApp());
      await assertErrorRendered('Unable to fetch diff for this pull request: oh noes.', wrapper);
    });
  });
});
<|endoftext|>


<commit_before>import Immutable from 'immutable';
import { handleActions } from 'redux-actions';
import * as uuid from 'uuid';
import * as commutable from 'commutable';

import * as constants from '../constants';

export default handleActions({
  [constants.SET_NOTEBOOK]: function setNotebook(state, action) {
    const notebook = action.data;
    let outputStatuses = new Immutable.Map();
    notebook.get('cellOrder').map((cellID) => {
      outputStatuses = outputStatuses.setIn([cellID, 'isHidden'], false);
      return outputStatuses;
    });

    return state.set('notebook', notebook)
                .set('focusedCell', notebook.getIn(['cellOrder', 0]))
                .set('outputStatuses', outputStatuses);
  },
  [constants.FOCUS_CELL]: function focusCell(state, action) {
    return state.set('focusedCell', action.id);
  },
  [constants.FOCUS_NEXT_CELL]: function focusNextCell(state, action) {
    const cellOrder = state.getIn(['notebook', 'cellOrder']);
    const curIndex = cellOrder.findIndex(id => id === action.id);

    const nextIndex = curIndex + 1;

    // When at the end, create a new cell
    if (nextIndex >= cellOrder.size) {
      if (!action.createCellIfUndefined) {
        return state;
      }

      const cellID = uuid.v4();
      // TODO: condition on state.defaultCellType (markdown vs. code)
      const cell = commutable.emptyCodeCell;
      return state.set('focusedCell', cellID)
                  .update('notebook',
                    (notebook) => commutable.insertCellAt(notebook, cell, cellID, nextIndex))
                  .setIn(['outputStatuses', cellID, 'isHidden'], false);
    }

    // When in the middle of the notebook document, move to the next cell
    return state.set('focusedCell', cellOrder.get(nextIndex));
  },
  [constants.FOCUS_PREVIOUS_CELL]: function focusPreviousCell(state, action) {
    const cellOrder = state.getIn(['notebook', 'cellOrder']);
    const curIndex = cellOrder.findIndex(id => id === action.id);
    const nextIndex = Math.max(0, curIndex - 1);

    return state.set('focusedCell', cellOrder.get(nextIndex));
  },
  [constants.TOGGLE_STICKY_CELL]: function toggleStickyCell(state, action) {
    const { id } = action;
    // TODO: Switch this structure to an Immutable.Set
    const stickyCells = state.get('stickyCells');
    if (stickyCells.get(id)) {
      return state.set('stickyCells', stickyCells.delete(id));
    }
    return state.setIn(['stickyCells', id], true);
  },
  [constants.UPDATE_CELL_EXECUTION_COUNT]: function updateExecutionCount(state, action) {
    const { id, count } = action;
    return state.update('notebook',
      (notebook) => commutable.updateExecutionCount(notebook, id, count));
  },
  [constants.MOVE_CELL]: function moveCell(state, action) {
    return state.updateIn(['notebook', 'cellOrder'],
      cellOrder => {
        const oldIndex = cellOrder.findIndex(id => id === action.id);
        const newIndex = cellOrder.findIndex(id => id === action.destinationId)
                          + (action.above ? 0 : 1);
        if (oldIndex === newIndex) {
          return cellOrder;
        }
        return cellOrder
          .splice(oldIndex, 1)
          .splice(newIndex - (oldIndex < newIndex ? 1 : 0), 0, action.id);
      }
    );
  },
  [constants.REMOVE_CELL]: function removeCell(state, action) {
    const { id } = action;
    return state.update('notebook',
      (notebook) => commutable.removeCell(notebook, id)
    );
  },
  [constants.NEW_CELL_AFTER]: function newCellAfter(state, action) {
    const { cellType, id, source } = action;
    const cell = cellType === 'markdown' ? commutable.emptyMarkdownCell :
                                           commutable.emptyCodeCell;
    const cellID = uuid.v4();
    return state.update('notebook', (notebook) => {
      const index = notebook.get('cellOrder').indexOf(id) + 1;
      return commutable.insertCellAt(notebook, cell.set('source', source), cellID, index);
    })
    .setIn(['outputStatuses', cellID, 'isHidden'], false);
  },
  [constants.NEW_CELL_BEFORE]: function newCellBefore(state, action) {
    // Draft API
    const { cellType, id } = action;
    const cell = cellType === 'markdown' ? commutable.emptyMarkdownCell :
                                           commutable.emptyCodeCell;
    const cellID = uuid.v4();
    return state.update('notebook', (notebook) => {
      const index = notebook.get('cellOrder').indexOf(id);
      return commutable.insertCellAt(notebook, cell, cellID, index);
    })
    .setIn(['outputStatuses', cellID, 'isHidden'], false);
  },
  [constants.MERGE_CELL_AFTER]: function mergeCellAfter(state, action) {
    const { id } = action;
    const cellOrder = state.getIn(['notebook', 'cellOrder']);
    const index = cellOrder.indexOf(id);
    // do nothing if this is the last cell
    if (cellOrder.size === index + 1) {
      return state;
    }
    const cellMap = state.getIn(['notebook', 'cellMap']);

    const nextId = cellOrder.get(index + 1);
    const source = cellMap.getIn([id, 'source'])
                          .concat('\n', '\n', cellMap.getIn([nextId, 'source']));

    return state.update('notebook',
      (notebook) => commutable.removeCell(commutable.updateSource(notebook, id, source), nextId)
    );
  },
  [constants.NEW_CELL_APPEND]: function newCellAppend(state, action) {
    // Draft API
    const { cellType } = action;
    const notebook = state.get('notebook');
    const cell = cellType === 'markdown' ? commutable.emptyMarkdownCell :
                                           commutable.emptyCodeCell;
    const index = notebook.get('cellOrder').count();
    const cellID = uuid.v4();
    return state.set('notebook', commutable.insertCellAt(notebook, cell, cellID, index))
                .setIn(['outputStatuses', cellID, 'isHidden'], false);
  },
  [constants.UPDATE_CELL_SOURCE]: function updateSource(state, action) {
    const { id, source } = action;
    return state.update('notebook', (notebook) => commutable.updateSource(notebook, id, source));
  },
  [constants.CLEAR_CELL_OUTPUT]: function clearCellOutput(state, action) {
    const { id } = action;
    return state.update('notebook', (notebook) => commutable.clearCellOutput(notebook, id));
  },
  [constants.SPLIT_CELL]: function splitCell(state, action) {
    const { id, position } = action;
    return state.update('notebook', (notebook) => commutable.splitCell(notebook, id, position));
  },
  [constants.CHANGE_OUTPUT_VISIBILITY]: function changeOutputVisibility(state, action) {
    const { id } = action;
    return state.update('outputStatuses', (outputStatuses) => outputStatuses.setIn([id, 'isHidden'],
          !outputStatuses.getIn([id, 'isHidden'])));
  },
  [constants.UPDATE_CELL_OUTPUTS]: function updateOutputs(state, action) {
    const { id, outputs } = action;
    return state.update('notebook', (notebook) => commutable.updateOutputs(notebook, id, outputs));
  },
  [constants.UPDATE_CELL_PAGERS]: function updateCellPagers(state, action) {
    const { id, pagers } = action;
    return state.setIn(['cellPagers', id], pagers);
  },
  [constants.UPDATE_CELL_STATUS]: function updateCellStatus(state, action) {
    const { id, status } = action;
    return state.setIn(['cellStatuses', id], status);
  },
  [constants.SET_LANGUAGE_INFO]: function setLanguageInfo(state, action) {
    const langInfo = Immutable.fromJS(action.langInfo);
    return state.setIn(['notebook', 'metadata', 'language_info'], langInfo);
  },
  [constants.OVERWRITE_METADATA_FIELD]: function overwriteMetadata(state, action) {
    const { field, value } = action;
    return state.setIn(['notebook', 'metadata', field], Immutable.fromJS(value));
  },
  [constants.ASSOCIATE_CELL_TO_MSG]: function associateCellToMsg(state, action) {
    const { cellId, msgId } = action;

    // Keep a forward and backward mapping of cell and msg ids so we can make
    // sure only one mapping per cell exists at any given time.
    const oldMsgId = state.getIn(['cellMsgAssociations', cellId]);
    const cellMsgAssociations = state.get('cellMsgAssociations').set(cellId, msgId);
    let msgCellAssociations = state.get('msgCellAssociations').set(msgId, cellId);
    if (oldMsgId) {
      msgCellAssociations = msgCellAssociations.delete(oldMsgId);
    }
    return state
      .set('cellMsgAssociations', cellMsgAssociations)
      .set('msgCellAssociations', msgCellAssociations);
  },
  [constants.UPDATE_DOCUMENT]: function undo(state, action) {
    const { newDocument } = action;
    if (newDocument) {
      return newDocument;
    }
    return state;
  },
  [constants.COPY_CELL]: function copyCell(state, action) {
    const { id } = action;
    const cellMap = state.getIn(['notebook', 'cellMap']);
    const cell = cellMap.get(id);
    return state.set('copied', new Immutable.Map({ id, cell }));
  },
  [constants.PASTE_CELL]: function copyCell(state) {
    const copiedCell = state.getIn(['copied', 'cell']);
    const copiedId = state.getIn(['copied', 'id']);
    const id = uuid.v4();

    return state.update('notebook', (notebook) =>
        commutable.insertCellAfter(notebook, copiedCell, id, copiedId));
  },
  [constants.CHANGE_CELL_TYPE]: function changeCellType(state, action) {
    const { id, to } = action;

    if (state.getIn(['notebook', 'cellMap', id, 'cell_type']) === 'markdown') {
      return state.setIn(['notebook', 'cellMap', id, 'cell_type'], to)
                  .setIn(['notebook', 'cellMap', id, 'execution_count'], null)
                  .setIn(['notebook', 'cellMap', id, 'outputs'], new Immutable.List());
    }

    return state.setIn(['notebook', 'cellMap', id, 'cell_type'], to);
  },
}, {});
<commit_msg>Fix cell to markdown conversion<commit_after>import Immutable from 'immutable';
import { handleActions } from 'redux-actions';
import * as uuid from 'uuid';
import * as commutable from 'commutable';

import * as constants from '../constants';

export default handleActions({
  [constants.SET_NOTEBOOK]: function setNotebook(state, action) {
    const notebook = action.data;
    let outputStatuses = new Immutable.Map();
    notebook.get('cellOrder').map((cellID) => {
      outputStatuses = outputStatuses.setIn([cellID, 'isHidden'], false);
      return outputStatuses;
    });

    return state.set('notebook', notebook)
                .set('focusedCell', notebook.getIn(['cellOrder', 0]))
                .set('outputStatuses', outputStatuses);
  },
  [constants.FOCUS_CELL]: function focusCell(state, action) {
    return state.set('focusedCell', action.id);
  },
  [constants.FOCUS_NEXT_CELL]: function focusNextCell(state, action) {
    const cellOrder = state.getIn(['notebook', 'cellOrder']);
    const curIndex = cellOrder.findIndex(id => id === action.id);

    const nextIndex = curIndex + 1;

    // When at the end, create a new cell
    if (nextIndex >= cellOrder.size) {
      if (!action.createCellIfUndefined) {
        return state;
      }

      const cellID = uuid.v4();
      // TODO: condition on state.defaultCellType (markdown vs. code)
      const cell = commutable.emptyCodeCell;
      return state.set('focusedCell', cellID)
                  .update('notebook',
                    (notebook) => commutable.insertCellAt(notebook, cell, cellID, nextIndex))
                  .setIn(['outputStatuses', cellID, 'isHidden'], false);
    }

    // When in the middle of the notebook document, move to the next cell
    return state.set('focusedCell', cellOrder.get(nextIndex));
  },
  [constants.FOCUS_PREVIOUS_CELL]: function focusPreviousCell(state, action) {
    const cellOrder = state.getIn(['notebook', 'cellOrder']);
    const curIndex = cellOrder.findIndex(id => id === action.id);
    const nextIndex = Math.max(0, curIndex - 1);

    return state.set('focusedCell', cellOrder.get(nextIndex));
  },
  [constants.TOGGLE_STICKY_CELL]: function toggleStickyCell(state, action) {
    const { id } = action;
    // TODO: Switch this structure to an Immutable.Set
    const stickyCells = state.get('stickyCells');
    if (stickyCells.get(id)) {
      return state.set('stickyCells', stickyCells.delete(id));
    }
    return state.setIn(['stickyCells', id], true);
  },
  [constants.UPDATE_CELL_EXECUTION_COUNT]: function updateExecutionCount(state, action) {
    const { id, count } = action;
    return state.update('notebook',
      (notebook) => commutable.updateExecutionCount(notebook, id, count));
  },
  [constants.MOVE_CELL]: function moveCell(state, action) {
    return state.updateIn(['notebook', 'cellOrder'],
      cellOrder => {
        const oldIndex = cellOrder.findIndex(id => id === action.id);
        const newIndex = cellOrder.findIndex(id => id === action.destinationId)
                          + (action.above ? 0 : 1);
        if (oldIndex === newIndex) {
          return cellOrder;
        }
        return cellOrder
          .splice(oldIndex, 1)
          .splice(newIndex - (oldIndex < newIndex ? 1 : 0), 0, action.id);
      }
    );
  },
  [constants.REMOVE_CELL]: function removeCell(state, action) {
    const { id } = action;
    return state.update('notebook',
      (notebook) => commutable.removeCell(notebook, id)
    );
  },
  [constants.NEW_CELL_AFTER]: function newCellAfter(state, action) {
    const { cellType, id, source } = action;
    const cell = cellType === 'markdown' ? commutable.emptyMarkdownCell :
                                           commutable.emptyCodeCell;
    const cellID = uuid.v4();
    return state.update('notebook', (notebook) => {
      const index = notebook.get('cellOrder').indexOf(id) + 1;
      return commutable.insertCellAt(notebook, cell.set('source', source), cellID, index);
    })
    .setIn(['outputStatuses', cellID, 'isHidden'], false);
  },
  [constants.NEW_CELL_BEFORE]: function newCellBefore(state, action) {
    // Draft API
    const { cellType, id } = action;
    const cell = cellType === 'markdown' ? commutable.emptyMarkdownCell :
                                           commutable.emptyCodeCell;
    const cellID = uuid.v4();
    return state.update('notebook', (notebook) => {
      const index = notebook.get('cellOrder').indexOf(id);
      return commutable.insertCellAt(notebook, cell, cellID, index);
    })
    .setIn(['outputStatuses', cellID, 'isHidden'], false);
  },
  [constants.MERGE_CELL_AFTER]: function mergeCellAfter(state, action) {
    const { id } = action;
    const cellOrder = state.getIn(['notebook', 'cellOrder']);
    const index = cellOrder.indexOf(id);
    // do nothing if this is the last cell
    if (cellOrder.size === index + 1) {
      return state;
    }
    const cellMap = state.getIn(['notebook', 'cellMap']);

    const nextId = cellOrder.get(index + 1);
    const source = cellMap.getIn([id, 'source'])
                          .concat('\n', '\n', cellMap.getIn([nextId, 'source']));

    return state.update('notebook',
      (notebook) => commutable.removeCell(commutable.updateSource(notebook, id, source), nextId)
    );
  },
  [constants.NEW_CELL_APPEND]: function newCellAppend(state, action) {
    // Draft API
    const { cellType } = action;
    const notebook = state.get('notebook');
    const cell = cellType === 'markdown' ? commutable.emptyMarkdownCell :
                                           commutable.emptyCodeCell;
    const index = notebook.get('cellOrder').count();
    const cellID = uuid.v4();
    return state.set('notebook', commutable.insertCellAt(notebook, cell, cellID, index))
                .setIn(['outputStatuses', cellID, 'isHidden'], false);
  },
  [constants.UPDATE_CELL_SOURCE]: function updateSource(state, action) {
    const { id, source } = action;
    return state.update('notebook', (notebook) => commutable.updateSource(notebook, id, source));
  },
  [constants.CLEAR_CELL_OUTPUT]: function clearCellOutput(state, action) {
    const { id } = action;
    return state.update('notebook', (notebook) => commutable.clearCellOutput(notebook, id));
  },
  [constants.SPLIT_CELL]: function splitCell(state, action) {
    const { id, position } = action;
    return state.update('notebook', (notebook) => commutable.splitCell(notebook, id, position));
  },
  [constants.CHANGE_OUTPUT_VISIBILITY]: function changeOutputVisibility(state, action) {
    const { id } = action;
    return state.update('outputStatuses', (outputStatuses) => outputStatuses.setIn([id, 'isHidden'],
          !outputStatuses.getIn([id, 'isHidden'])));
  },
  [constants.UPDATE_CELL_OUTPUTS]: function updateOutputs(state, action) {
    const { id, outputs } = action;
    return state.update('notebook', (notebook) => commutable.updateOutputs(notebook, id, outputs));
  },
  [constants.UPDATE_CELL_PAGERS]: function updateCellPagers(state, action) {
    const { id, pagers } = action;
    return state.setIn(['cellPagers', id], pagers);
  },
  [constants.UPDATE_CELL_STATUS]: function updateCellStatus(state, action) {
    const { id, status } = action;
    return state.setIn(['cellStatuses', id], status);
  },
  [constants.SET_LANGUAGE_INFO]: function setLanguageInfo(state, action) {
    const langInfo = Immutable.fromJS(action.langInfo);
    return state.setIn(['notebook', 'metadata', 'language_info'], langInfo);
  },
  [constants.OVERWRITE_METADATA_FIELD]: function overwriteMetadata(state, action) {
    const { field, value } = action;
    return state.setIn(['notebook', 'metadata', field], Immutable.fromJS(value));
  },
  [constants.ASSOCIATE_CELL_TO_MSG]: function associateCellToMsg(state, action) {
    const { cellId, msgId } = action;

    // Keep a forward and backward mapping of cell and msg ids so we can make
    // sure only one mapping per cell exists at any given time.
    const oldMsgId = state.getIn(['cellMsgAssociations', cellId]);
    const cellMsgAssociations = state.get('cellMsgAssociations').set(cellId, msgId);
    let msgCellAssociations = state.get('msgCellAssociations').set(msgId, cellId);
    if (oldMsgId) {
      msgCellAssociations = msgCellAssociations.delete(oldMsgId);
    }
    return state
      .set('cellMsgAssociations', cellMsgAssociations)
      .set('msgCellAssociations', msgCellAssociations);
  },
  [constants.UPDATE_DOCUMENT]: function undo(state, action) {
    const { newDocument } = action;
    if (newDocument) {
      return newDocument;
    }
    return state;
  },
  [constants.COPY_CELL]: function copyCell(state, action) {
    const { id } = action;
    const cellMap = state.getIn(['notebook', 'cellMap']);
    const cell = cellMap.get(id);
    return state.set('copied', new Immutable.Map({ id, cell }));
  },
  [constants.PASTE_CELL]: function copyCell(state) {
    const copiedCell = state.getIn(['copied', 'cell']);
    const copiedId = state.getIn(['copied', 'id']);
    const id = uuid.v4();

    return state.update('notebook', (notebook) =>
        commutable.insertCellAfter(notebook, copiedCell, id, copiedId));
  },
  [constants.CHANGE_CELL_TYPE]: function changeCellType(state, action) {
    const { id, to } = action;
    const from = state.getIn(['notebook', 'cellMap', id, 'cell_type']);

    if (from === to) {
      return state;
    } else if  (from === 'markdown') {
      return state.setIn(['notebook', 'cellMap', id, 'cell_type'], to)
                  .setIn(['notebook', 'cellMap', id, 'execution_count'], null)
                  .setIn(['notebook', 'cellMap', id, 'outputs'], new Immutable.List());
    } else {
      return state.setIn(['notebook', 'cellMap', id, 'cell_type'], to)
                  .delete(['notebook', 'cellMap', id, 'execution_count'])
                  .delete(['notebook', 'cellMap', id, 'outputs']);
    }
  },
}, {});
<|endoftext|>


<commit_before>const assert = require('assert')
const child_process = require('child_process')
const fs = require('fs')
const path = require('path')
const os = require('os')
const {remote} = require('electron')

describe('node feature', function () {
  var fixtures = path.join(__dirname, 'fixtures')

  describe('child_process', function () {
    describe('child_process.fork', function () {
      it('works in current process', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'ping.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('preserves args', function (done) {
        var args = ['--expose_gc', '-test', '1']
        var child = child_process.fork(path.join(fixtures, 'module', 'process_args.js'), args)
        child.on('message', function (msg) {
          assert.deepEqual(args, msg.slice(2))
          done()
        })
        child.send('message')
      })

      it('works in forked process', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('works in forked process when options.env is specifed', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], {
          path: process.env['PATH']
        })
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('works in browser process', function (done) {
        var fork = remote.require('child_process').fork
        var child = fork(path.join(fixtures, 'module', 'ping.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('has String::localeCompare working in script', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js'))
        child.on('message', function (msg) {
          assert.deepEqual(msg, [0, -1, 1])
          done()
        })
        child.send('message')
      })

      it('has setImmediate working in script', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'ok')
          done()
        })
        child.send('message')
      })

      it('pipes stdio', function (done) {
        let child = child_process.fork(path.join(fixtures, 'module', 'process-stdout.js'), {silent: true})
        let data = ''
        child.stdout.on('data', (chunk) => {
          data += String(chunk)
        })
        child.on('exit', (code) => {
          assert.equal(code, 0)
          assert.equal(data, 'pipes stdio')
          done()
        })
      })
    })
  })

  describe('contexts', function () {
    describe('setTimeout in fs callback', function () {
      if (process.env.TRAVIS === 'true') {
        return
      }

      it('does not crash', function (done) {
        fs.readFile(__filename, function () {
          setTimeout(done, 0)
        })
      })
    })

    describe('throw error in node context', function () {
      it('gets caught', function (done) {
        var error = new Error('boo!')
        var lsts = process.listeners('uncaughtException')
        process.removeAllListeners('uncaughtException')
        process.on('uncaughtException', function () {
          var i, len, lst
          process.removeAllListeners('uncaughtException')
          for (i = 0, len = lsts.length; i < len; i++) {
            lst = lsts[i]
            process.on('uncaughtException', lst)
          }
          done()
        })
        fs.readFile(__filename, function () {
          throw error
        })
      })
    })

    describe('setTimeout called under Chromium event loop in browser process', function () {
      it('can be scheduled in time', function (done) {
        remote.getGlobal('setTimeout')(done, 0)
      })
    })

    describe('setInterval called under Chromium event loop in browser process', function () {
      it('can be scheduled in time', function (done) {
        var clear, interval
        clear = function () {
          remote.getGlobal('clearInterval')(interval)
          done()
        }
        interval = remote.getGlobal('setInterval')(clear, 10)
      })
    })
  })

  describe('message loop', function () {
    describe('process.nextTick', function () {
      it('emits the callback', function (done) {
        process.nextTick(done)
      })

      it('works in nested calls', function (done) {
        process.nextTick(function () {
          process.nextTick(function () {
            process.nextTick(done)
          })
        })
      })
    })

    describe('setImmediate', function () {
      it('emits the callback', function (done) {
        setImmediate(done)
      })

      it('works in nested calls', function (done) {
        setImmediate(function () {
          setImmediate(function () {
            setImmediate(done)
          })
        })
      })
    })
  })

  describe('net.connect', function () {
    if (process.platform !== 'darwin') {
      return
    }

    it('emit error when connect to a socket path without listeners', function (done) {
      var socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock')
      var script = path.join(fixtures, 'module', 'create_socket.js')
      var child = child_process.fork(script, [socketPath])
      child.on('exit', function (code) {
        assert.equal(code, 0)
        var client = require('net').connect(socketPath)
        client.on('error', function (error) {
          assert.equal(error.code, 'ECONNREFUSED')
          done()
        })
      })
    })
  })

  describe('Buffer', function () {
    it('can be created from WebKit external string', function () {
      var p = document.createElement('p')
      p.innerText = '闲云潭影日悠悠，物换星移几度秋'
      var b = new Buffer(p.innerText)
      assert.equal(b.toString(), '闲云潭影日悠悠，物换星移几度秋')
      assert.equal(Buffer.byteLength(p.innerText), 45)
    })

    it('correctly parses external one-byte UTF8 string', function () {
      var p = document.createElement('p')
      p.innerText = 'Jøhänñéß'
      var b = new Buffer(p.innerText)
      assert.equal(b.toString(), 'Jøhänñéß')
      assert.equal(Buffer.byteLength(p.innerText), 13)
    })

    it('does not crash when creating large Buffers', function () {
      new Buffer(new Array(4096).join(' '));
      new Buffer(new Array(4097).join(' '));
    })
  })

  describe('process.stdout', function () {
    it('should not throw exception', function () {
      process.stdout
    })

    it('should not throw exception when calling write()', function () {
      process.stdout.write('test')
    })

    it('should have isTTY defined', function () {
      assert.equal(typeof process.stdout.isTTY, 'boolean')
    })
  })

  describe('process.version', function () {
    it('should not have -pre', function () {
      assert(!process.version.endsWith('-pre'))
    })
  })

  describe('vm.createContext', function () {
    it('should not crash', function () {
      require('vm').runInNewContext('')
    })
  })
})
<commit_msg>spec: Suppress isCI test on CI<commit_after>const assert = require('assert')
const child_process = require('child_process')
const fs = require('fs')
const path = require('path')
const os = require('os')
const {remote} = require('electron')

const isCI = remote.getGlobal('isCi')

describe('node feature', function () {
  var fixtures = path.join(__dirname, 'fixtures')

  describe('child_process', function () {
    describe('child_process.fork', function () {
      it('works in current process', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'ping.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('preserves args', function (done) {
        var args = ['--expose_gc', '-test', '1']
        var child = child_process.fork(path.join(fixtures, 'module', 'process_args.js'), args)
        child.on('message', function (msg) {
          assert.deepEqual(args, msg.slice(2))
          done()
        })
        child.send('message')
      })

      it('works in forked process', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('works in forked process when options.env is specifed', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], {
          path: process.env['PATH']
        })
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('works in browser process', function (done) {
        var fork = remote.require('child_process').fork
        var child = fork(path.join(fixtures, 'module', 'ping.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'message')
          done()
        })
        child.send('message')
      })

      it('has String::localeCompare working in script', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js'))
        child.on('message', function (msg) {
          assert.deepEqual(msg, [0, -1, 1])
          done()
        })
        child.send('message')
      })

      it('has setImmediate working in script', function (done) {
        var child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js'))
        child.on('message', function (msg) {
          assert.equal(msg, 'ok')
          done()
        })
        child.send('message')
      })

      it('pipes stdio', function (done) {
        let child = child_process.fork(path.join(fixtures, 'module', 'process-stdout.js'), {silent: true})
        let data = ''
        child.stdout.on('data', (chunk) => {
          data += String(chunk)
        })
        child.on('exit', (code) => {
          assert.equal(code, 0)
          assert.equal(data, 'pipes stdio')
          done()
        })
      })
    })
  })

  describe('contexts', function () {
    describe('setTimeout in fs callback', function () {
      if (process.env.TRAVIS === 'true') {
        return
      }

      it('does not crash', function (done) {
        fs.readFile(__filename, function () {
          setTimeout(done, 0)
        })
      })
    })

    describe('throw error in node context', function () {
      it('gets caught', function (done) {
        var error = new Error('boo!')
        var lsts = process.listeners('uncaughtException')
        process.removeAllListeners('uncaughtException')
        process.on('uncaughtException', function () {
          var i, len, lst
          process.removeAllListeners('uncaughtException')
          for (i = 0, len = lsts.length; i < len; i++) {
            lst = lsts[i]
            process.on('uncaughtException', lst)
          }
          done()
        })
        fs.readFile(__filename, function () {
          throw error
        })
      })
    })

    describe('setTimeout called under Chromium event loop in browser process', function () {
      it('can be scheduled in time', function (done) {
        remote.getGlobal('setTimeout')(done, 0)
      })
    })

    describe('setInterval called under Chromium event loop in browser process', function () {
      it('can be scheduled in time', function (done) {
        var clear, interval
        clear = function () {
          remote.getGlobal('clearInterval')(interval)
          done()
        }
        interval = remote.getGlobal('setInterval')(clear, 10)
      })
    })
  })

  describe('message loop', function () {
    describe('process.nextTick', function () {
      it('emits the callback', function (done) {
        process.nextTick(done)
      })

      it('works in nested calls', function (done) {
        process.nextTick(function () {
          process.nextTick(function () {
            process.nextTick(done)
          })
        })
      })
    })

    describe('setImmediate', function () {
      it('emits the callback', function (done) {
        setImmediate(done)
      })

      it('works in nested calls', function (done) {
        setImmediate(function () {
          setImmediate(function () {
            setImmediate(done)
          })
        })
      })
    })
  })

  describe('net.connect', function () {
    if (process.platform !== 'darwin') {
      return
    }

    it('emit error when connect to a socket path without listeners', function (done) {
      var socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock')
      var script = path.join(fixtures, 'module', 'create_socket.js')
      var child = child_process.fork(script, [socketPath])
      child.on('exit', function (code) {
        assert.equal(code, 0)
        var client = require('net').connect(socketPath)
        client.on('error', function (error) {
          assert.equal(error.code, 'ECONNREFUSED')
          done()
        })
      })
    })
  })

  describe('Buffer', function () {
    it('can be created from WebKit external string', function () {
      var p = document.createElement('p')
      p.innerText = '闲云潭影日悠悠，物换星移几度秋'
      var b = new Buffer(p.innerText)
      assert.equal(b.toString(), '闲云潭影日悠悠，物换星移几度秋')
      assert.equal(Buffer.byteLength(p.innerText), 45)
    })

    it('correctly parses external one-byte UTF8 string', function () {
      var p = document.createElement('p')
      p.innerText = 'Jøhänñéß'
      var b = new Buffer(p.innerText)
      assert.equal(b.toString(), 'Jøhänñéß')
      assert.equal(Buffer.byteLength(p.innerText), 13)
    })

    it('does not crash when creating large Buffers', function () {
      new Buffer(new Array(4096).join(' '));
      new Buffer(new Array(4097).join(' '));
    })
  })

  describe('process.stdout', function () {
    it('should not throw exception', function () {
      process.stdout
    })

    it('should not throw exception when calling write()', function () {
      process.stdout.write('test')
    })

    it('should have isTTY defined', function () {
      if (isCI) return

      assert.equal(typeof process.stdout.isTTY, 'boolean')
    })
  })

  describe('process.version', function () {
    it('should not have -pre', function () {
      assert(!process.version.endsWith('-pre'))
    })
  })

  describe('vm.createContext', function () {
    it('should not crash', function () {
      require('vm').runInNewContext('')
    })
  })
})
<|endoftext|>


<commit_before>/*
 * highlight-patch.js
 * Copyright (C) 2015 KuoE0 <kuoe0.tw@gmail.com>
 *
 * Distributed under terms of the MIT license.
 */

'use strict';

var pre_elem = document.getElementsByTagName('pre');
for (var i = 0; i < pre_elem.length; ++i) {
	hljs.highlightBlock(pre_elem[i]);
}

<commit_msg>force to set syntax as diff<commit_after>/*
 * highlight-patch.js
 * Copyright (C) 2015 KuoE0 <kuoe0.tw@gmail.com>
 *
 * Distributed under terms of the MIT license.
 */

'use strict';
hljs.configure({
	languages: ['diff']
});

var pre_elem = document.getElementsByTagName('pre');

for (var i = 0; i < pre_elem.length; ++i) {
	hljs.highlightBlock(pre_elem[i]);
}

<|endoftext|>


<commit_before>rules = {
  red: "color",
  blue: "color",
  green: "color",
  mix: "color",
  hue: "color",
  saturation: "color",
  lightness: "color",
  complement: "color",
  invert: "color",
  alpha: "color",
  "adjust-color": "color",
  "scale-color": "color",
  "change-color": "color",
  "ie-hex-str": "color",
  "map-get": "map",
  "map-merge": "map",
  "map-remove": "map",
  "map-keys": "map",
  "map-values": "map",
  "map-has-key": "map",
  unquote: "string",
  quote: "string",
  "str-length": "string",
  "str-insert": "string",
  "str-index": "string",
  "str-slice": "string",
  "to-upper-case": "string",
  "to-lower-case": "string",
  "unique-id": "string",
  percentage: "math",
  round: "math",
  ceil: "math",
  floor: "math",
  abs: "math",
  min: "math",
  max: "math",
  random: "math",
  unit: "math",
  unitless: "math",
  comparable: "math",
  length: "list",
  nth: "list",
  "set-nth": "list",
  join: "list",
  append: "list",
  zip: "list",
  index: "list",
  "list-separator": "list",
  "feature-exists": "meta",
  "variable-exists": "meta",
  "global-variable-exists": "meta",
  "function-exists": "meta",
  "mixin-exists": "meta",
  inspect: "meta",
  "get-function": "meta",
  "type-of": "meta",
  call: "meta",
  "content-exists": "meta",
  keywords: "meta",
  "selector-nest": "selector",
  "selector-append": "selector",
  "selector-replace": "selector",
  "selector-unify": "selector",
  "is-superselector": "selector",
  "simple-selectors": "selector",
  "selector-parse": "selector",
  "selector-extend": "selector"
};

new_rule_names = {
  "adjust-color": "adjust",
  "scale-color": "scale",
  "change-color": "change",
  "map-get": "get",
  "map-merge": "merge",
  "map-remove": "remove",
  "map-keys": "keys",
  "map-values": "values",
  "map-has-key": "has-key",
  "str-length": "length",
  "str-insert": "insert",
  "str-index": "index",
  "str-slice": "slice",
  unitless: "is-unitless",
  comparable: "compatible",
  "list-separator": "separator",
  "selector-nest": "nest",
  "selector-append": "append",
  "selector-replace": "replace",
  "selector-unify": "unify",
  "selector-parse": "parse",
  "selector-extend": "extend"
};

import { utils } from "stylelint";
import { atRuleBaseName, namespace } from "../../utils";

export const ruleName = namespace("no-duplicate-mixins");

export const messages = utils.ruleMessages(ruleName, {
  rejected: mixin => `Unexpected duplicate mixin ${mixin}`
});

export default function(value) {
  return (root, result) => {
    const validOptions = utils.validateOptions(result, ruleName, {
      actual: value
    });

    if (!validOptions) {
      return;
    }

    const mixins = {};

    root.walkAtRules(decl => {
      const isMixin = decl.name === "mixin";

      if (!isMixin) {
        return;
      }

      const mixinName = atRuleBaseName(decl);

      if (mixins[mixinName]) {
        utils.report({
          message: messages.rejected(mixinName),
          node: decl,
          result,
          ruleName
        });
      }

      mixins[mixinName] = true;
    });
  };
}
<commit_msg>written the things<commit_after>rules = {
  red: "color",
  blue: "color",
  green: "color",
  mix: "color",
  hue: "color",
  saturation: "color",
  lightness: "color",
  complement: "color",
  invert: "color",
  alpha: "color",
  "adjust-color": "color",
  "scale-color": "color",
  "change-color": "color",
  "ie-hex-str": "color",
  "map-get": "map",
  "map-merge": "map",
  "map-remove": "map",
  "map-keys": "map",
  "map-values": "map",
  "map-has-key": "map",
  unquote: "string",
  quote: "string",
  "str-length": "string",
  "str-insert": "string",
  "str-index": "string",
  "str-slice": "string",
  "to-upper-case": "string",
  "to-lower-case": "string",
  "unique-id": "string",
  percentage: "math",
  round: "math",
  ceil: "math",
  floor: "math",
  abs: "math",
  min: "math",
  max: "math",
  random: "math",
  unit: "math",
  unitless: "math",
  comparable: "math",
  length: "list",
  nth: "list",
  "set-nth": "list",
  join: "list",
  append: "list",
  zip: "list",
  index: "list",
  "list-separator": "list",
  "feature-exists": "meta",
  "variable-exists": "meta",
  "global-variable-exists": "meta",
  "function-exists": "meta",
  "mixin-exists": "meta",
  inspect: "meta",
  "get-function": "meta",
  "type-of": "meta",
  call: "meta",
  "content-exists": "meta",
  keywords: "meta",
  "selector-nest": "selector",
  "selector-append": "selector",
  "selector-replace": "selector",
  "selector-unify": "selector",
  "is-superselector": "selector",
  "simple-selectors": "selector",
  "selector-parse": "selector",
  "selector-extend": "selector"
};

new_rule_names = {
  "adjust-color": "adjust",
  "scale-color": "scale",
  "change-color": "change",
  "map-get": "get",
  "map-merge": "merge",
  "map-remove": "remove",
  "map-keys": "keys",
  "map-values": "values",
  "map-has-key": "has-key",
  "str-length": "length",
  "str-insert": "insert",
  "str-index": "index",
  "str-slice": "slice",
  unitless: "is-unitless",
  comparable: "compatible",
  "list-separator": "separator",
  "selector-nest": "nest",
  "selector-append": "append",
  "selector-replace": "replace",
  "selector-unify": "unify",
  "selector-parse": "parse",
  "selector-extend": "extend"
};

import { utils } from "stylelint";
import { atRuleBaseName, namespace } from "../../utils";

export const ruleName = namespace("no-duplicate-mixins");

export const messages = utils.ruleMessages(ruleName, {
  rejected: name => errorMessage(name)
});

function errorMessage(name) {
  sass_package = rules[name];
  rename = new_rule_names[name];

  if (rename) {
    return "Expected ${sass_package}.${rename} instead of ${name}";
  } else {
    return "Expected ${sass_package}.${name} instead of ${name}";
  }
}

export default function(value) {
  return (root, result) => {
    const validOptions = utils.validateOptions(result, ruleName, {
      actual: value
    });

    if (!validOptions) {
      return;
    }

    const mixins = {};

    root.walkDecls(decl => {
      valueParser(decl.value).walk(node => {
        // Verify that we're only looking at functions.
        if (node.type !== "function" || node.value === "") {
          return;
        }

        if (rules.keys.includes(node.value)) {
          utils.report({
            message: messages.rejected(node.value),
            node: decl,
            result,
            ruleName
          });
        }
      });
    });
  };
}
<|endoftext|>


<commit_before>
describe('JSPipe.Pipe', function() {
    var p;

    beforeEach(function() {
        debugger;
        p = new JSPipe.Pipe();
    });

    describe('put', function() {

        describe('return value', function() {

            it('is a function', function() {
                var ret = p.put();
                expect(typeof ret).toEqual('function');
            });

        });

    });

    describe('get', function() {

        describe('return value', function() {

            it('is a function', function() {
                var ret = p.get();
                expect(typeof ret).toEqual('function');
            });

        });

    });

    describe('send', function() {

        it('calls put', function() {
            spyOn(p, 'put').andCallThrough();
            p.send('test');
            expect(p.put).toHaveBeenCalledWith('test');
        });

    });

    describe('close', function() {

        it('sets the "isOpen" flag to false', function() {
            var expected = [true, false],
                actual = [];

            actual.push(p.isOpen);
            p.close();
            actual.push(p.isOpen);
            expect(actual).toEqual(expected);

        });

    });

    describe('_rendezvous', function() {

    });
});

<commit_msg>fleshes out more unit tests for Pipe<commit_after>/*globals describe, beforeEach, it, expect, spyOn, JSPipe */

describe('JSPipe.Pipe', function() {
    var p;

    beforeEach(function() {
        debugger;
        p = new JSPipe.Pipe();
    });

    describe('put', function() {

        describe('return value', function() {

            it('is a function', function() {
                var ret = p.put();
                expect(typeof ret).toEqual('function');
            });

            describe('invocation', function() {

                it('pushes data argument and resume argument into the inbox', function() {
                    var ret = p.put('data');
                    ret('resume');
                    expect(p.inbox).toEqual(['data', 'resume']);
                });

                it('calls _rendezvous()', function() {
                    var ret = p.put();
                    spyOn(p, '_rendezvous').andCallThrough();
                    ret();
                    expect(p._rendezvous).toHaveBeenCalled();
                });
            });

        });

    });

    describe('get', function() {

        describe('return value', function() {

            it('is a function', function() {
                var ret = p.get();
                expect(typeof ret).toEqual('function');
            });

            describe('invocation', function() {

                it('pushes resume argument into the outbox', function() {
                    var ret = p.get();
                    ret('getResume');
                    expect(p.outbox).toEqual(['getResume']);
                });

                it('calls _rendezvous()', function() {
                    var ret = p.get();
                    spyOn(p, '_rendezvous').andCallThrough();
                    ret();
                    expect(p._rendezvous).toHaveBeenCalled();
                });
            });

        });

    });

    describe('send', function() {

        it('pushes the data into the inbox and an undefined resume', function() {
            var expected = ['test', undefined];
            p.send('test');
            expect(p.inbox).toEqual(expected);
        });

        it('calls _rendezvous()', function() {
            spyOn(p, '_rendezvous').andCallThrough();
            p.send('some data');
            expect(p._rendezvous).toHaveBeenCalled();
        });

    });

    describe('close', function() {

        it('sets the "isOpen" flag to false', function() {
            var expected = [true, false],
                actual = [];

            actual.push(p.isOpen);
            p.close();
            actual.push(p.isOpen);
            expect(actual).toEqual(expected);

        });

    });

    describe('_rendezvous', function() {
        var data = 'some data',
            senderExpected,
            receiverExpected,
            senderActual,
            receiverActual;

        function notify() {
            senderActual.push('didSend');
        }

        function send(data) {
            receiverActual.push(data);
        }

        beforeEach(function() {
            senderExpected = ['didSend'];
            receiverExpected = [data];
            senderActual = [];
            receiverActual = [];

            p.inbox = [data, notify];
            p.outbox = [send];
        });

        it('sends data placed in the inbox to the function in the outbox', function() {
            p._rendezvous();
            expect(receiverActual).toEqual(receiverExpected);
        });

        it('notifies the sender that the data was delivered', function() {
            p._rendezvous();
            expect(senderActual).toEqual(senderExpected);
        });

    });
});

<|endoftext|>


<commit_before>'use strict';
//Old dog, new tricks
var myUrl = 'http://www.memrise.com/ajax/thing/cell/upload_file/';
var uploader = $('multi-upload:first');
//------------------------------------------------------
function uploadFile(url, file, obj, targetColumn, token, cookie) {

    var formData = new FormData();
    formData.append(
        'thing_id',
        obj.id
    );
    formData.append(
        'cell_id',
        targetColumn
    );
    formData.append(
        'cell_type',
        'column'
    );
    formData.append(
        'csrfmiddlewaretoken',
        token
    );
    formData.append(
        'f',
        file
    );
    var xhr = new XMLHttpRequest();
    xhr.open(
        'POST',
        url,
        true
    );
    xhr.setRequestHeader(
        'Cookie',
        cookie
    );
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            console.log(xhr.responseText);
        } else {
            console.log(xhr.status);
        }
    };
    xhr.send(formData);  // multipart/form-data
}
//--------------------------------------------------------

self.port.on('list avaible', function(obj){
        $('#upload-button').on( 'click', function (e) {
            e.preventDefault();
            let filesToUpload = uploader.files;
            let numFiles = filesToUpload.length;
            for (let i = 0; i < numFiles; ++i) {
                let file = filesToUpload.item(i);
                let name = file.name.split(['.'],[1])[0].toLowerCase();

                if( obj.hasOwnProperty(name) && !obj[name].hasFile ) {
                    uploadFile(
                        myUrl,
                        file,
                        obj[name],
                        obj.targetColumn,
                        document.cookie.slice(10,42),
                        document.cookie
                    );
                }
            }
            self.port.emit('Uploaded');
    },
    false);
});
<commit_msg>major refactoring<commit_after>'use strict';
//Old dog, new tricks
var myUrl = 'http://www.memrise.com/ajax/thing/cell/upload_file/';
var targetColumn = null;
//------------------------------------------------------
function uploadFile(url, file, obj, targetColumn) {

    var formData = new FormData();
    formData.append(
        'thing_id',
        obj.id
    );
    formData.append(
        'cell_id',
        targetColumn
    );
    formData.append(
        'cell_type',
        'column'
    );
    formData.append(
        'csrfmiddlewaretoken',
        document.cookie.match(/\bcsrftoken=(.{1,32})/)[1]
    );
    formData.append(
        'f',
        file
    );
    var xhr = new XMLHttpRequest();
    xhr.open(
        'POST',
        url,
        true
    );
    xhr.setRequestHeader(
        'Cookie',
        document.cookie
    );
    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4 && xhr.status === 200) {
            console.log(xhr.responseText);
        } else {
            console.log(xhr.status);
        }
    };
    xhr.send(formData);  // multipart/form-data
}
//--------------------------------------------------------

self.port.on('list avaiable', function (data) {
    var uploader = document.getElementById('multi-upload');
    var filesToUpload = uploader.files;
    var numFiles = filesToUpload.length;
    for (let i = 0; i < numFiles; ++i) {
        // we need a reference to the file currently uploading
        let file = filesToUpload.item(i);
        var name = file.name.split(['.'], [1])[0].toLowerCase();
        console.log(name);
        console.log(JSON.stringify(data));
        if( data.hasOwnProperty(name) && !data[name].hasFile ) {
            uploadFile(
                myUrl,
                file,
                data[name],
                targetColumn
            );
        }
    }
    self.port.emit('Uploaded', data);
});
self.port.on('populate', function (data) {
    targetColumn = data.targetColumn;
});<|endoftext|>


<commit_before>/*global describe,it,element,by,takeScreenshot,expect,browser,protractor*/

describe("sap.m.Popover", function () {
	"use strict";

	function executeSpecs(sMode) {
		var bPhone = null;
		var _resolvePopover = function () {
			return bPhone ? "__dialog1" : "overflowing-popover";
		};

		it("Should load test page", function () {
			browser.executeScript(function () {
				return sap.ui.Device.system.phone;
			}).then(function (response) {
				bPhone = response;
			});

			//click over a button that hides the caret when a popover is opened from an input
			element(by.id("customCssButton")).click();
			expect(takeScreenshot()).toLookAs("initial" + "-" + sMode);
		});

		it("Should open Popover Right", function () {
			element(by.id("btn1")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input

			expect(takeScreenshot()).toLookAs("popover-right" + "-" + sMode);
		});

		it("Should open Popover Bottom", function () {
			element(by.id("btn0")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input

			expect(takeScreenshot()).toLookAs("popover-bottom" + "-" + sMode);
		});

		it("Should open Popover Top", function () {
			element(by.id("btn3")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input

			expect(takeScreenshot()).toLookAs("popover-top" + "-" + sMode);
		});

		it("Should open Popover Left", function () {
			element(by.id("btn2")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input

			expect(takeScreenshot()).toLookAs("popover-left" + "-" + sMode);
		});

		it("Should open Popover Vertical", function () {
			element(by.id("btn4")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input

			expect(takeScreenshot()).toLookAs("popover-vertical" + "-" + sMode);
		});

		it("Should open Popover with header and footer", function () {
			element(by.id("with-h-with-f")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-header-footer" + "-" + sMode);
		});

		it("Should open Popover without header and with footer", function () {
			element(by.id("no-h-with-f")).click();
			element(by.id("__item0-__list0-0")).click(); // Remove the focus from input

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-footer" + "-" + sMode);
		});

		it("Should open Popover Horizontal", function () {
			element(by.id("btn6")).click();
			expect(takeScreenshot()).toLookAs("popover-horizontal" + "-" + sMode);
		});

		it("Should open Popover with header and no footer", function () {
			element(by.id("with-h-no-f")).click();
			element(by.id("pop1-title-inner")).click(); // Remove the focus from input
			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-header" + "-" + sMode);
		});

		it("Should open Popover without header and footer", function () {
			element(by.id("no-h-no-f")).click();
			element(by.id("__item0-__list0-0")).click(); // Remove the focus from input

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-no-header-footer" + "-" + sMode);
		});

		it("Should open Popover with responsive paddings", function () {
			element(by.id("change-fiori-theme")).click();
			element(by.id("btn11")).click();
			expect(takeScreenshot()).toLookAs("popover-with-responsive-paddings" + "-" + sMode);
			//cleanup
			element(by.id("change-belize-theme")).click();
		});

		it("Should resize Popover to 700px with responsive paddings", function () {
			element(by.id("btn11")).click();
			element(by.id("btn-set-width-700")).click();
			expect(takeScreenshot()).toLookAs("popover-700-responsive-paddings" + "-" + sMode);
			//cleanup
			element(by.id("change-belize-theme")).click();
		});

		it("Should resize Popover to 1024px with responsive paddings", function () {
			element(by.id("change-fiori-theme")).click();
			element(by.id("btn11")).click();
			element(by.id("btn-set-width-1024")).click();
			expect(takeScreenshot()).toLookAs("popover-1024-responsive-paddings" + "-" + sMode);
			//cleanup
			element(by.id("change-belize-theme")).click();
		});

		it("Should open Popover with checkboxes and check one of them", function () {
			element(by.id("btn15")).click();
			element(by.id("popover12CheckBox1")).click();
			expect(takeScreenshot()).toLookAs("popover-with-checkboxes" + "-" + sMode);
		});

		// This test will open Dialog on mobile devices and Popover on desktops.
		// This will make it harder to determine how to close it so it can be left last
		it("Should open an overflowing popover which should be displayed with a visible scrollbar", function () {
			element(by.id("overflowing-popover-arrow")).click();
			expect(takeScreenshot(element(by.id(_resolvePopover())))).toLookAs("overflowing-popover" + "-" + sMode);
		});

		it("Should dismiss only the inner popover with ESC when there's a case with nested Popovers", function () {
			element(by.id("btn10")).click();
			element(by.id("selectInPopover-arrow")).click();

			expect(takeScreenshot()).toLookAs("popover-nested-popovers" + "-" + sMode);

			browser.actions().sendKeys(protractor.Key.ESCAPE).perform();

			expect(takeScreenshot()).toLookAs("popover-nested-popovers-outer-closed" + "-" + sMode);
		});
	}

	executeSpecs("window");

	it("Should enable withinAreaMode", function () {
		//click over a button that hides the caret when a popover is opened from an input
		element(by.id("customWithin")).click();
		expect(takeScreenshot()).toLookAs("customWithin");
	});

	executeSpecs("withinArea");
});<commit_msg>[INTERNAL] sap.m.Popover: Visual tests adjusted<commit_after>/*global describe,it,element,by,takeScreenshot,expect,browser,protractor*/

describe("sap.m.Popover", function () {
	"use strict";

	function executeSpecs(sMode) {
		var bPhone = null;
		var _resolvePopover = function () {
			return bPhone ? "__dialog1" : "overflowing-popover";
		};

		it("Should load test page", function () {
			browser.executeScript(function () {
				return sap.ui.Device.system.phone;
			}).then(function (response) {
				bPhone = response;
			});

			//click over a button that hides the caret when a popover is opened from an input
			element(by.id("customCssButton")).click();
			expect(takeScreenshot()).toLookAs("initial" + "-" + sMode);
		});

		it("Should open Popover Right", function () {
			element(by.id("btn1")).click();

			expect(takeScreenshot()).toLookAs("popover-right" + "-" + sMode);
		});

		it("Should open Popover Bottom", function () {
			element(by.id("btn0")).click();

			expect(takeScreenshot()).toLookAs("popover-bottom" + "-" + sMode);
		});

		it("Should open Popover Top", function () {
			element(by.id("btn3")).click();

			expect(takeScreenshot()).toLookAs("popover-top" + "-" + sMode);
		});

		it("Should open Popover Left", function () {
			element(by.id("btn2")).click();

			expect(takeScreenshot()).toLookAs("popover-left" + "-" + sMode);
		});

		it("Should open Popover Vertical", function () {
			element(by.id("btn4")).click();

			expect(takeScreenshot()).toLookAs("popover-vertical" + "-" + sMode);
		});

		it("Should open Popover with header and footer", function () {
			element(by.id("with-h-with-f")).click();

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-header-footer" + "-" + sMode);
		});

		it("Should open Popover without header and with footer", function () {
			element(by.id("no-h-with-f")).click();

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-footer" + "-" + sMode);
		});

		it("Should open Popover Horizontal", function () {
			element(by.id("btn6")).click();
			expect(takeScreenshot()).toLookAs("popover-horizontal" + "-" + sMode);
		});

		it("Should open Popover with header and no footer", function () {
			element(by.id("with-h-no-f")).click();

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-header" + "-" + sMode);
		});

		it("Should open Popover without header and footer", function () {
			element(by.id("no-h-no-f")).click();
			element(by.id("__item0-__list0-0")).click(); // Remove the focus from input

			expect(takeScreenshot(element(by.id("pop1")))).toLookAs("popover-no-header-footer" + "-" + sMode);
		});

		it("Should open Popover with responsive paddings", function () {
			element(by.id("change-fiori-theme")).click();
			element(by.id("btn11")).click();
			expect(takeScreenshot()).toLookAs("popover-responsivePaddings" + "-" + sMode);
			//cleanup
			element(by.id("change-belize-theme")).click();
		});

		it("Should resize Popover to 700px with responsive paddings", function () {
			element(by.id("btn11")).click();
			element(by.id("btn-set-width-700")).click();
			expect(takeScreenshot()).toLookAs("700px-responsivePaddings" + "-" + sMode);
			//cleanup
			element(by.id("change-belize-theme")).click();
		});

		it("Should resize Popover to 1024px with responsive paddings", function () {
			element(by.id("change-fiori-theme")).click();
			element(by.id("btn11")).click();
			element(by.id("btn-set-width-1024")).click();
			expect(takeScreenshot()).toLookAs("1024px-responsivePaddings" + "-" + sMode);
			//cleanup
			element(by.id("change-belize-theme")).click();
		});

		it("Should open Popover with checkboxes and check one of them", function () {
			element(by.id("btn15")).click();
			element(by.id("popover12CheckBox1")).click();
			expect(takeScreenshot()).toLookAs("popover-with-checkboxes" + "-" + sMode);
		});

		// This test will open Dialog on mobile devices and Popover on desktops.
		// This will make it harder to determine how to close it so it can be left last
		it("Should open an overflowing popover which should be displayed with a visible scrollbar", function () {
			element(by.id("overflowing-popover-arrow")).click();
			expect(takeScreenshot(element(by.id(_resolvePopover())))).toLookAs("overflowing-popover" + "-" + sMode);
		});

		it("Should dismiss only the inner popover with ESC when there's a case with nested Popovers", function () {
			element(by.id("btn10")).click();
			element(by.id("selectInPopover-arrow")).click();

			expect(takeScreenshot()).toLookAs("popover-nested-popovers" + "-" + sMode);

			browser.actions().sendKeys(protractor.Key.ESCAPE).perform();

			expect(takeScreenshot()).toLookAs("nested-popovers-inner-closed" + "-" + sMode);
		});
	}

	executeSpecs("window");

	it("Should enable withinAreaMode", function () {
		//click over a button that hides the caret when a popover is opened from an input
		element(by.id("customWithin")).click();
		expect(takeScreenshot()).toLookAs("customWithin");
	});

	executeSpecs("withinArea");
});<|endoftext|>


<commit_before>import React from 'react/addons';

import Board       from '../../models/board';
import BoardAction from '../../actions/board';

import Dialog           from '../../components/dialog';
import BackgroundSelect from '../../components/background-select';

/**
 *
 */
export default React.createClass({
	mixins: [ React.addons.PureRenderMixin, React.addons.LinkedStateMixin ],

	propTypes: {
		board: (props) => {
			if(!props.board instanceof Board) throw new Error();
		},
		onDismiss: React.PropTypes.func.isRequired
	},

	getInitialState() {
		return {
			name:             this.props.board.name,
			background:       this.props.board.background,
			customBackground: this.props.board.customBackground,
			width:            this.props.board.size.width,
			height:           this.props.board.size.height
		}
	},

	validateNumberOnly() {
		console.log("Hello");
	},

	submit(event) {
		event.preventDefault();

		let size = {
			"width": this.state.width,
			"height": this.state.height
		};

		if(size.width < 1 || size.height < 1 ) {
			size.width = this.props.board.size.width;
			size.height = this.props.board.size.height;
		}

		BoardAction.update({
			id:               this.props.board.id,
			name:             this.state.name,
			background:       this.state.background,
			customBackground: this.state.customBackground,
			size:             size
		});
		return this.props.onDismiss();
	},

	render() {
		return (
			<Dialog className="dialog-edit-board"
					onDismiss={this.props.onDismiss}>

					Edit Board

					Board Name
					<input name="board-name" placeholder="Board Name"
						valueLink={this.linkState('name')} autoFocus={true} />

					<BackgroundSelect background={this.linkState('background')}
						customBackground={this.linkState('customBackground')} />

								Board Width
								<input name="board-width" placeholder="Board Width"
									   valueLink={this.linkState('width')}
									   type="number" min="1" />

							Board Length
								<input name="board-height" placeholder="Board Length"
									   valueLink={this.linkState('height')}
									   type="number" min="1"/>

					<button className="btn-primary" onClick={this.submit}>
						Done
					</button>

			</Dialog>
		);
	}
});
<commit_msg>Clean up code according to lint rules, numeric validation to size<commit_after>import React from 'react/addons';

import Board       from '../../models/board';
import BoardAction from '../../actions/board';

import Dialog           from '../../components/dialog';
import BackgroundSelect from '../../components/background-select';

/**
 *
 */
export default React.createClass({
	mixins: [ React.addons.PureRenderMixin, React.addons.LinkedStateMixin ],

	propTypes: {
		board: (props) => {
			if(!props.board instanceof Board) throw new Error();
		},
		onDismiss: React.PropTypes.func.isRequired
	},

	getInitialState() {
		return {
			name:             this.props.board.name,
			background:       this.props.board.background,
			customBackground: this.props.board.customBackground,
			width:            this.props.board.size.width,
			height:           this.props.board.size.height
		}
	},

	submit(event) {
		event.preventDefault();

		let size = {
			"width": this.state.width,
			"height": this.state.height
		};

		if (!isNaN(size.width) && !isNaN(size.height)) {

			if (size.width < 1 || size.height < 1) {
				size.width = this.props.board.size.width;
				size.height = this.props.board.size.height;
			}

			BoardAction.update({
				id: this.props.board.id,
				name: this.state.name,
				background: this.state.background,
				customBackground: this.state.customBackground,
				size: size
			});
		}
		return this.props.onDismiss();
	},

	render() {
		return (
			<Dialog className="dialog-edit-board"
					onDismiss={this.props.onDismiss}>

					Edit Board

					Board Name
					<input name="board-name" placeholder="Board Name"
						valueLink={this.linkState('name')} autoFocus={true} />

					<BackgroundSelect background={this.linkState('background')}
						customBackground={this.linkState('customBackground')} />

								Board Width
								<input name="board-width"
                                       placeholder="Board Width"
                                       valueLink={this.linkState('width')}
                                       type="number" min="1" />

							Board Length
								<input name="board-height"
                                       placeholder="Board Length"
                                       valueLink={this.linkState('height')}
                                       type="number" min="1"/>

					<button className="btn-primary" onClick={this.submit}>
						Done
					</button>

			</Dialog>
		);
	}
});
<|endoftext|>


<commit_before>import { expect } from "chai";
import { createVueField } from "../util";

import Vue from "vue";
import fieldVueMultiSelect from "src/fields/fieldVueMultiSelect.vue";

Vue.component("fieldVueMultiSelect", fieldVueMultiSelect);

// eslint-disable-next-line
let el, vm, field;

function createField(schema = {}, model = null, disabled = false, options) {
	[ el, vm, field ] = createVueField("fieldVueMultiSelect", schema, model, disabled, options);
}

describe("fieldVueMultiSelect.vue", () => {

	describe("check template", () => {
		let schema = {
			type: "vueMultiSelect",
			label: "Cities",
			model: "city",
			multiSelect: false,
			required: false,
			values: [
				"London",
				"Paris",
				"Rome",
				"Berlin"
			],
			selectOptions: {}
		};
		let model = { city: "Paris" };
		let input;

		before( () => {
			createField(schema, model, false);
			input = el.getElementsByTagName("select")[0];
		});

		it("should contain a select element", () => {
			expect(field).to.be.exist;
			expect(field.$el).to.be.exist;

			expect(input).to.be.defined;
			// expect(input.classList.contains("form-control")).to.be.false;
			// expect(input.disabled).to.be.false;
		});
	});
});<commit_msg>test: improve unit testing of vueMultiSelect<commit_after>import { expect } from "chai";
import { createVueField, trigger } from "../util";

import Vue from "vue";
import fieldVueMultiSelect from "src/fields/fieldVueMultiSelect.vue";

Vue.component("fieldVueMultiSelect", fieldVueMultiSelect);

// eslint-disable-next-line
let el, vm, field;

function createField(schema = {}, model = null, disabled = false, options) {
	[ el, vm, field ] = createVueField("fieldVueMultiSelect", schema, model, disabled, options);
}

describe("fieldVueMultiSelect.vue", () => {

	describe("check template", () => {
		let schema = {
			type: "vueMultiSelect",
			label: "Cities",
			model: "city",
			multiSelect: true,
			required: false,
			values: [
				"London",
				"Paris",
				"Rome",
				"Berlin"
			],
			selectOptions: {}
		};
		let model = { city: "Paris" };
		let input;

		before( () => {
			createField(schema, model, false);
			vm.$appendTo(document.body);
			input = el.querySelector(".multiselect");
		});

		it("should contain a select element", () => {
			expect(field).to.be.exist;
			expect(field.$el).to.be.exist;

			expect(input).to.be.defined;
			expect(input.classList.contains("form-control")).to.be.false;
			expect(input.classList.contains("multiselect--disabled")).to.be.false;
		});

		it("should contain option elements", () => {
			let options = input.querySelectorAll("li.multiselect__option");
			console.log(options);
			expect(options.length).to.be.equal(schema.values.length);
			expect(options[1].querySelector("span").textContent).to.be.equal("Paris");
			expect(options[1].classList.contains("multiselect__option--selected")).to.be.true;
		});

		it("should set disabled", (done) => {
			field.disabled = true;
			vm.$nextTick( () => {
				expect(input.classList.contains("multiselect--disabled")).to.be.true;
				field.disabled = false;
				done();
			});
		});

		it("input value should be the model value after changed", (done) => {
			model.city = "Rome";
			vm.$nextTick( () => {
				let options = input.querySelectorAll("li.multiselect__option");
				expect(options[2].querySelector("span").textContent).to.be.equal("Rome");
				expect(options[2].classList.contains("multiselect__option--selected")).to.be.true;
				done();
			});
		});

		it("input value should be the model value after changed (multiselection)", (done) => {
			model.city = ["Paris","Rome"];
			vm.$nextTick( () => {
				let options = input.querySelectorAll("li.multiselect__option");
				expect(options[1].querySelector("span").textContent).to.be.equal("Paris");
				expect(options[1].classList.contains("multiselect__option--selected")).to.be.true;
				expect(options[2].querySelector("span").textContent).to.be.equal("Rome");
				expect(options[2].classList.contains("multiselect__option--selected")).to.be.true;
				done();
			});
		});

		it("model value should be the input value if changed", (done) => {
			let options = input.querySelectorAll("li.multiselect__option");
			trigger(options[2], "mousedown");

			vm.$nextTick( () => {
				expect(model.city[0]).to.be.equal("Paris");
				done();
			});

		});
	});
});<|endoftext|>