<commit_before>var mongoose  = require('mongoose')
  , elastical = require('elastical')
  , should    = require('should')
  , config    = require('./config')
  , Schema    = mongoose.Schema
  , ObjectId  = Schema.ObjectId
  , esClient  = new(require('elastical').Client)
  , mongoosastic = require('../lib/mongoosastic')

// -- simplest indexing... index all fields
var TweetSchema = new Schema({
    user: String
  , post_date: Date
  , message: String
});

TweetSchema.plugin(mongoosastic)
var Tweet = mongoose.model('Tweet', TweetSchema);

// -- Only index specific field
var TalkSchema = new Schema({
    speaker: String
  , title: {type:String, es_indexed:true}
  , abstract: {type:String, es_indexed:true}
  , bio: String
});
TalkSchema.plugin(mongoosastic)

var Talk = mongoose.model("Talk", TalkSchema);

var PersonSchema = new Schema({
    name: {type:String, es_indexed:true}
  , phone: {type:String, es_indexed:true}
  , address: String
});
PersonSchema.plugin(mongoosastic, {
  index:'people'
, type: 'dude'
, hydrate: true
});

var Person = mongoose.model("Person", PersonSchema);

// -- alright let's test this shiznit!
describe('indexing', function(){
  before(function(done){
    mongoose.connect(config.mongoUrl, function(){
      Tweet.remove(function(){
        config.deleteIndexIfExists(['tweets', 'talks', 'people'], done)
      });
    });
  });

  after(function(done){
    Tweet.remove(function(){
      mongoose.disconnect();
      done();
    });
  });

  describe('Default plugin', function(){
    before(function(done){
      createModelAndEnsureIndex(Tweet, {
          user: 'jamescarr'
        , message: "I like Riak better"
        , post_date: new Date()
      }, done);
    });
    it("should use the model's id as ES id", function(done){
      Tweet.findOne({message:"I like Riak better"}, function(err, doc){
        esClient.get('tweets', doc._id.toString(), function(err, res){
          res.message.should.eql(doc.message);
          done()
        });
      });
    });

    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'Riak'}, function(err, results) {
        results.total.should.eql(1)
        results.hits[0]._source.message.should.eql('I like Riak better')
        done()
      });
    });
    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'jamescarr'}, function(err, results) {
        results.total.should.eql(1)
        results.hits[0]._source.message.should.eql('I like Riak better')
        done()
      });
    });
    it('should report errors', function(done){
      Tweet.search({queriez:'jamescarr'}, function(err, results) {
        err.message.should.match(/SearchPhaseExecutionException/);
        should.not.exist(results)
        done()
      });
    });
  });
  describe('Removing', function(){
    var tweet = new Tweet({
      user:'jamescarr'
    , message: 'Saying something I shouldnt'
    });
    before(function(done){
      createModelAndEnsureIndex(Tweet, tweet, done);
    });
    it('should remove from index when model is removed', function(done){
      tweet.remove(function(){
          setTimeout(function(){
            Tweet.search({query:'shouldnt'}, function(err, res){
              res.total.should.eql(0);
              done();
            });
          }, 1100);
      });
    });
    it('should queue for later removal if not in index', function(done){
      // behavior here is to try 3 times and then give up.
      var tweet = new Tweet({
        user:'jamescarr'
      , message: 'ABBA'
      });

      tweet.save(function(){
        tweet.remove();
      });
      tweet.on('es-removed', done);
    });

  });
  describe('Isolated Models', function(){
    before(function(done){
      var talk = new Talk({
          speaker: ''
        , title: "Dude"
        , abstract: ""
        , bio: ''
      });
      var tweet = new Tweet({
          user: 'Dude'
        , message: "Go see the big lebowski"
        , post_date: new Date()
      });
      tweet.save(function(){
        talk.save(function(){
          talk.on('es-indexed', function(err, res){
            setTimeout(done, 1000);
          });
        });
      });
    });

    it('should only find models of type Tweet', function(done){
      Tweet.search({query:'Dude'}, function(err, res){
        res.total.should.eql(1);
        res.hits[0]._source.user.should.eql('Dude');
        done();
      });
    });
    it('should only find models of type Talk', function(done){
      Talk.search({query:'Dude'}, function(err, res){
        res.total.should.eql(1);
        res.hits[0]._source.title.should.eql('Dude');
        done();
      });
    });
  });

  describe('Always hydrate', function(){
    before(function(done){
      createModelAndEnsureIndex(Person, {
          name: 'James Carr'
        , address: "Exampleville, MO"
        , phone: '(555)555-5555'
      }, done);
    });

    it('when gathering search results', function(done){
      Person.search({query:'James'}, function(err, res) {
        res.hits[0].address.should.eql('Exampleville, MO');
        done();
      });
    });
  });
  describe('Subset of Fields', function(){
    before(function(done){
      createModelAndEnsureIndex(Talk,{
          speaker: 'James Carr'
        , title: "Node.js Rocks"
        , abstract: "I told you node.js was cool. Listen to me!"
        , bio: 'One awesome dude.'
      }, done);
    });

    it('should only return indexed fields', function(done){
      Talk.search({query:'cool'}, function(err, res) {
        res.total.should.eql(1);

        var talk = res.hits[0]._source;
        talk.should.have.property('title');
        talk.should.have.property('abstract');
        talk.should.not.have.property('speaker');
        talk.should.not.have.property('bio');
        done();
      });
    });

    it('should hydrate returned documents if desired', function(done){
      Talk.search({query:'cool'}, {hydrate:true}, function(err, res) {
        res.total.should.eql(1)

        var talk = res.hits[0]
        talk.should.have.property('title')
        talk.should.have.property('abstract')
        talk.should.have.property('speaker')
        talk.should.have.property('bio')
        done();
      });
    });
  });
});

function createModelAndEnsureIndex(model, obj, cb){
  var dude = new model(obj);
  dude.save(function(){
    dude.on('es-indexed', function(err, res){
      setTimeout(cb, 1000);
    });
  });
}
<commit_msg>Added test for handling of existing index<commit_after>var mongoose  = require('mongoose')
  , elastical = require('elastical')
  , should    = require('should')
  , config    = require('./config')
  , Schema    = mongoose.Schema
  , ObjectId  = Schema.ObjectId
  , esClient  = new(require('elastical').Client)
  , mongoosastic = require('../lib/mongoosastic')

// -- simplest indexing... index all fields
var TweetSchema = new Schema({
    user: String
  , post_date: Date
  , message: String
});

TweetSchema.plugin(mongoosastic)
var Tweet = mongoose.model('Tweet', TweetSchema);

// -- Only index specific field
var TalkSchema = new Schema({
    speaker: String
  , title: {type:String, es_indexed:true}
  , abstract: {type:String, es_indexed:true}
  , bio: String
});
TalkSchema.plugin(mongoosastic)

var Talk = mongoose.model("Talk", TalkSchema);

var PersonSchema = new Schema({
    name: {type:String, es_indexed:true}
  , phone: {type:String, es_indexed:true}
  , address: String
});
PersonSchema.plugin(mongoosastic, {
  index:'people'
, type: 'dude'
, hydrate: true
});

var Person = mongoose.model("Person", PersonSchema);

// -- alright let's test this shiznit!
describe('indexing', function(){
  before(function(done){
    mongoose.connect(config.mongoUrl, function(){
      Tweet.remove(function(){
        config.deleteIndexIfExists(['tweets', 'talks', 'people'], done)
      });
    });
  });

  after(function(done){
    Tweet.remove(function(){
      mongoose.disconnect();
      done();
    });
  });

  describe('Creating Index', function(){
    it('should create index if none exists', function(done){
      Tweet.createMapping(function(err, response){
        response.should.not.have.property('error');
        done();
      });
    });
    it('should update index if one already exists', function(done){
      Tweet.createMapping(function(err, response){
        response.should.not.have.property('error');
        done();
      });
    });

    after(function(done){
      config.deleteIndexIfExists(['tweets', 'talks', 'people'], done)
    });
  });

  describe('Default plugin', function(){
    before(function(done){
      createModelAndEnsureIndex(Tweet, {
          user: 'jamescarr'
        , message: "I like Riak better"
        , post_date: new Date()
      }, done);
    });
    it("should use the model's id as ES id", function(done){
      Tweet.findOne({message:"I like Riak better"}, function(err, doc){
        esClient.get('tweets', doc._id.toString(), function(err, res){
          res.message.should.eql(doc.message);
          done()
        });
      });
    });

    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'Riak'}, function(err, results) {
        results.total.should.eql(1)
        results.hits[0]._source.message.should.eql('I like Riak better')
        done()
      });
    });
    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'jamescarr'}, function(err, results) {
        results.total.should.eql(1)
        results.hits[0]._source.message.should.eql('I like Riak better')
        done()
      });
    });
    it('should report errors', function(done){
      Tweet.search({queriez:'jamescarr'}, function(err, results) {
        err.message.should.match(/SearchPhaseExecutionException/);
        should.not.exist(results)
        done()
      });
    });
  });
  describe('Removing', function(){
    var tweet = new Tweet({
      user:'jamescarr'
    , message: 'Saying something I shouldnt'
    });
    before(function(done){
      createModelAndEnsureIndex(Tweet, tweet, done);
    });
    it('should remove from index when model is removed', function(done){
      tweet.remove(function(){
          setTimeout(function(){
            Tweet.search({query:'shouldnt'}, function(err, res){
              res.total.should.eql(0);
              done();
            });
          }, 1100);
      });
    });
    it('should queue for later removal if not in index', function(done){
      // behavior here is to try 3 times and then give up.
      var tweet = new Tweet({
        user:'jamescarr'
      , message: 'ABBA'
      });

      tweet.save(function(){
        tweet.remove();
      });
      tweet.on('es-removed', done);
    });

  });
  describe('Isolated Models', function(){
    before(function(done){
      var talk = new Talk({
          speaker: ''
        , title: "Dude"
        , abstract: ""
        , bio: ''
      });
      var tweet = new Tweet({
          user: 'Dude'
        , message: "Go see the big lebowski"
        , post_date: new Date()
      });
      tweet.save(function(){
        talk.save(function(){
          talk.on('es-indexed', function(err, res){
            setTimeout(done, 1000);
          });
        });
      });
    });

    it('should only find models of type Tweet', function(done){
      Tweet.search({query:'Dude'}, function(err, res){
        res.total.should.eql(1);
        res.hits[0]._source.user.should.eql('Dude');
        done();
      });
    });
    it('should only find models of type Talk', function(done){
      Talk.search({query:'Dude'}, function(err, res){
        res.total.should.eql(1);
        res.hits[0]._source.title.should.eql('Dude');
        done();
      });
    });
  });

  describe('Always hydrate', function(){
    before(function(done){
      createModelAndEnsureIndex(Person, {
          name: 'James Carr'
        , address: "Exampleville, MO"
        , phone: '(555)555-5555'
      }, done);
    });

    it('when gathering search results', function(done){
      Person.search({query:'James'}, function(err, res) {
        res.hits[0].address.should.eql('Exampleville, MO');
        done();
      });
    });
  });
  describe('Subset of Fields', function(){
    before(function(done){
      createModelAndEnsureIndex(Talk,{
          speaker: 'James Carr'
        , title: "Node.js Rocks"
        , abstract: "I told you node.js was cool. Listen to me!"
        , bio: 'One awesome dude.'
      }, done);
    });

    it('should only return indexed fields', function(done){
      Talk.search({query:'cool'}, function(err, res) {
        res.total.should.eql(1);

        var talk = res.hits[0]._source;
        talk.should.have.property('title');
        talk.should.have.property('abstract');
        talk.should.not.have.property('speaker');
        talk.should.not.have.property('bio');
        done();
      });
    });

    it('should hydrate returned documents if desired', function(done){
      Talk.search({query:'cool'}, {hydrate:true}, function(err, res) {
        res.total.should.eql(1)

        var talk = res.hits[0]
        talk.should.have.property('title')
        talk.should.have.property('abstract')
        talk.should.have.property('speaker')
        talk.should.have.property('bio')
        done();
      });
    });
  });
});

function createModelAndEnsureIndex(model, obj, cb){
  var dude = new model(obj);
  dude.save(function(){
    dude.on('es-indexed', function(err, res){
      setTimeout(cb, 1000);
    });
  });
}
<|endoftext|>


<commit_before>import { override, extend } from 'flarum/extend';
import app from 'flarum/app';
import Composer from 'flarum/components/Composer';
import PostStream from 'flarum/components/PostStream';
import ModalManager from 'flarum/components/ModalManager';
import AlertManager from 'flarum/components/AlertManager';
import PostMeta from 'flarum/components/PostMeta';
import mapRoutes from 'flarum/utils/mapRoutes';
import Pane from 'flarum/utils/Pane';
import Drawer from 'flarum/utils/Drawer';

import DiscussionPage from 'flarum/embed/components/DiscussionPage';

app.initializers.replace('boot', () => {
  m.route.mode = 'pathname';

  override(m, 'route', function(original, root, arg1, arg2, vdom) {
    if (arguments.length === 1) {

    } else if (arguments.length === 4 && typeof arg1 === 'string') {

    } else if (root.addEventListener || root.attachEvent) {
      root.href = vdom.attrs.href;
      root.target = '_blank';

      // TODO: If href leads to a post within this discussion that we have
      // already loaded, then scroll to it?
      return;
    }

    return original.apply(this, Array.prototype.slice.call(arguments, 1));
  });

  // Trim the /embed prefix off of post permalinks
  override(PostMeta.prototype, 'getPermalink', (original, post) => {
    return original(post).replace('/embed', '/d');
  });

  app.pageInfo = m.prop();

  const reposition = function() {
    const info = app.pageInfo();
    this.$().css('top', Math.max(0, info.scrollTop - info.offsetTop));
  };

  extend(ModalManager.prototype, 'show', reposition);
  extend(Composer.prototype, 'show', reposition);

  window.iFrameResizer = {
    readyCallback: function() {
      window.parentIFrame.getPageInfo(app.pageInfo);
    }
  };

  extend(PostStream.prototype, 'goToNumber', function(promise, number) {
    if (number === 'reply' && 'parentIFrame' in window && app.composer.$().css('position') === 'absolute') {
      const itemTop = this.$('.PostStream-item:last').offset().top;
      window.parentIFrame.scrollToOffset(0, itemTop);
    }
  });

  app.pane = new Pane(document.getElementById('app'));
  app.drawer = new Drawer();
  app.composer = m.mount(document.getElementById('composer'), Composer.component());
  app.modal = m.mount(document.getElementById('modal'), ModalManager.component());
  app.alerts = m.mount(document.getElementById('alerts'), AlertManager.component());

  app.viewingDiscussion = function(discussion) {
    return this.current instanceof DiscussionPage && this.current.discussion === discussion;
  };

  delete app.routes['index.filter'];
  app.routes['discussion'] = {path: '/embed/:id', component: DiscussionPage.component()};
  app.routes['discussion.near'] = {path: '/embed/:id/:near', component: DiscussionPage.component()};

  const basePath = app.forum.attribute('basePath');
  m.route.mode = 'pathname';
  m.route(
    document.getElementById('content'),
    basePath + '/',
    mapRoutes(app.routes, basePath)
  );

  // Initialize FastClick, which makes links and buttons much more responsive on
  // touch devices.
  $(() => {
    FastClick.attach(document.body);

    $('body').addClass('ontouchstart' in window ? 'touch' : 'no-touch');
  });

  app.booted = true;
});
<commit_msg>Allow the first post to be hidden<commit_after>import { override, extend } from 'flarum/extend';
import app from 'flarum/app';
import Composer from 'flarum/components/Composer';
import PostStream from 'flarum/components/PostStream';
import ModalManager from 'flarum/components/ModalManager';
import AlertManager from 'flarum/components/AlertManager';
import PostMeta from 'flarum/components/PostMeta';
import mapRoutes from 'flarum/utils/mapRoutes';
import Pane from 'flarum/utils/Pane';
import Drawer from 'flarum/utils/Drawer';

import DiscussionPage from 'flarum/embed/components/DiscussionPage';

app.initializers.replace('boot', () => {
  m.route.mode = 'pathname';

  override(m, 'route', function(original, root, arg1, arg2, vdom) {
    if (arguments.length === 1) {

    } else if (arguments.length === 4 && typeof arg1 === 'string') {

    } else if (root.addEventListener || root.attachEvent) {
      root.href = vdom.attrs.href;
      root.target = '_blank';

      // TODO: If href leads to a post within this discussion that we have
      // already loaded, then scroll to it?
      return;
    }

    return original.apply(this, Array.prototype.slice.call(arguments, 1));
  });

  // Trim the /embed prefix off of post permalinks
  override(PostMeta.prototype, 'getPermalink', (original, post) => {
    return original(post).replace('/embed', '/d');
  });

  app.pageInfo = m.prop();

  const reposition = function() {
    const info = app.pageInfo();
    this.$().css('top', Math.max(0, info.scrollTop - info.offsetTop));
  };

  extend(ModalManager.prototype, 'show', reposition);
  extend(Composer.prototype, 'show', reposition);

  window.iFrameResizer = {
    readyCallback: function() {
      window.parentIFrame.getPageInfo(app.pageInfo);
    }
  };

  extend(PostStream.prototype, 'goToNumber', function(promise, number) {
    if (number === 'reply' && 'parentIFrame' in window && app.composer.$().css('position') === 'absolute') {
      const itemTop = this.$('.PostStream-item:last').offset().top;
      window.parentIFrame.scrollToOffset(0, itemTop);
    }
  });

  app.pane = new Pane(document.getElementById('app'));
  app.drawer = new Drawer();
  app.composer = m.mount(document.getElementById('composer'), Composer.component());
  app.modal = m.mount(document.getElementById('modal'), ModalManager.component());
  app.alerts = m.mount(document.getElementById('alerts'), AlertManager.component());

  app.viewingDiscussion = function(discussion) {
    return this.current instanceof DiscussionPage && this.current.discussion === discussion;
  };

  delete app.routes['index.filter'];
  app.routes['discussion'] = {path: '/embed/:id', component: DiscussionPage.component()};
  app.routes['discussion.near'] = {path: '/embed/:id/:near', component: DiscussionPage.component()};

  const basePath = app.forum.attribute('basePath');
  m.route.mode = 'pathname';
  m.route(
    document.getElementById('content'),
    basePath + '/',
    mapRoutes(app.routes, basePath)
  );

  if (m.route.param('hideFirstPost')) {
    extend(PostStream.prototype, 'view', vdom => {
      if (vdom.children[0].attrs['data-number'] === 1) {
        vdom.children.splice(0, 1);
      }
    });
  }

  // Initialize FastClick, which makes links and buttons much more responsive on
  // touch devices.
  $(() => {
    FastClick.attach(document.body);

    $('body').addClass('ontouchstart' in window ? 'touch' : 'no-touch');
  });

  app.booted = true;
});
<|endoftext|>


<commit_before>import test from 'ava';
import m from './';

let chromeName;

if (process.platform === 'darwin') {
	chromeName = 'google chrome canary';
} else if (process.platform === 'linux') {
	chromeName = 'google-chrome';
} else if (process.platform === 'win32') {
	chromeName = 'Chrome';
}

// tests only checks that opening doesn't return an error
// it has no way make sure that it actually opened anything

// these have to be manually verified

test('open file in default app', async () => {
	await m('index.js');
});

test('not wait for the app to close if wait: false', async () => {
	await m('http://sindresorhus.com', {wait: false});
});

test('open url in default app', async () => {
	await m('http://sindresorhus.com');
});

test('open url in specified app', async () => {
	await m('http://sindresorhus.com', {app: 'firefox'});
});

test('open url in specified app with arguments', async () => {
	await m('http://sindresorhus.com', {app: [chromeName, '--incognito']});
});

test('return the child process when called', async t => {
	const cp = await m('index.js');
	t.ok('stdout' in cp);
});
<commit_msg>upgrade to latest AVA<commit_after>import test from 'ava';
import m from './';

let chromeName;

if (process.platform === 'darwin') {
	chromeName = 'google chrome canary';
} else if (process.platform === 'linux') {
	chromeName = 'google-chrome';
} else if (process.platform === 'win32') {
	chromeName = 'Chrome';
}

// tests only checks that opening doesn't return an error
// it has no way make sure that it actually opened anything

// these have to be manually verified

test('open file in default app', async () => {
	await m('index.js');
});

test('not wait for the app to close if wait: false', async () => {
	await m('http://sindresorhus.com', {wait: false});
});

test('open url in default app', async () => {
	await m('http://sindresorhus.com');
});

test('open url in specified app', async () => {
	await m('http://sindresorhus.com', {app: 'firefox'});
});

test('open url in specified app with arguments', async () => {
	await m('http://sindresorhus.com', {app: [chromeName, '--incognito']});
});

test('return the child process when called', async t => {
	const cp = await m('index.js');
	t.true('stdout' in cp);
});
<|endoftext|>


<commit_before>/* eslint-disable global-require */
const mockdata = require('./mockdata');

const pathToConfig = '../src/config';
// Mock the static config methods
const mockedConfigFunctions = {
	setup: jest.fn(),
	getOutputFilepath: () => 'test-report.html',
	getStylesheetFilepath: () => '../style/defaultTheme.css',
	getPageTitle: jest.fn(),
	getLogo: jest.fn(),
};

describe('index', () => {
	beforeEach(() => {
		// Reset the mocked modules prior to each test case
		jest.resetModules();
	});

	it('should return the jest test data if used with Jest testResultsProcessor configuration', () => {
		// Mocked config
		mockedConfigFunctions.getExecutionMode = () => 'testResultsProcessor';
		jest.mock(pathToConfig, () => (mockedConfigFunctions));
		// The plugin needs to be required after we have mocked the config
		const JestHTMLReporter = require('../src');

		// Trigger the reporter as a testResultsProcessor
		const testResultsProcessorOutput = JestHTMLReporter(mockdata.jestResponse.singleTestResult);
		expect(testResultsProcessorOutput)
			.toEqual(mockdata.jestResponse.singleTestResult);
	});

	it('should return the jest test data if used with Jest reporters configuration', () => {
		// Mocked config
		mockedConfigFunctions.getExecutionMode = () => 'reporter';
		jest.mock(pathToConfig, () => (mockedConfigFunctions));
		// The plugin needs to be required after we have mocked the config
		const JestHTMLReporter = require('../src');

		// When run as a Jest reporter, the plugin will be instantiated as a class
		const ReporterInitiatedByJest = new JestHTMLReporter();
		// Mock the end of a test run
		const reporterOutput = ReporterInitiatedByJest.onRunComplete(null, mockdata.jestResponse.singleTestResult);
		expect(reporterOutput)
			.toEqual(mockdata.jestResponse.singleTestResult);
	});
});
<commit_msg>fix test<commit_after>/* eslint-disable global-require */
const mockdata = require('./mockdata');

const pathToConfig = '../src/config';
// Mock the static config methods
const mockedConfigFunctions = {
	setup: jest.fn(),
	getOutputFilepath: () => 'test-report.html',
	getStylesheetFilepath: () => '../style/defaultTheme.css',
	getPageTitle: jest.fn(),
	getLogo: jest.fn(),
};

describe('index', () => {
	beforeEach(() => {
		// Reset the mocked modules prior to each test case
		jest.resetModules();
	});

	it('should return the jest test data if used with Jest testResultsProcessor configuration', () => {
		// Mocked config
		mockedConfigFunctions.getExecutionMode = () => 'testResultsProcessor';
		jest.mock(pathToConfig, () => (mockedConfigFunctions));
		// The plugin needs to be required after we have mocked the config
		const JestHTMLReporter = require('../src');

		// Trigger the reporter as a testResultsProcessor
		const testResultsProcessorOutput = JestHTMLReporter(mockdata.jestResponse.singleTestResult);
		expect(testResultsProcessorOutput)
			.toEqual(mockdata.jestResponse.singleTestResult);
	});

	it('should return the jest test data if used with Jest reporters configuration', async () => {
		// Mocked config
		mockedConfigFunctions.getExecutionMode = () => 'reporter';
		jest.mock(pathToConfig, () => (mockedConfigFunctions));
		// The plugin needs to be required after we have mocked the config
		const JestHTMLReporter = require('../src');

		// When run as a Jest reporter, the plugin will be instantiated as a class
		const ReporterInitiatedByJest = new JestHTMLReporter();
		// Mock the end of a test run
		const reporterOutput = await ReporterInitiatedByJest.onRunComplete(null, mockdata.jestResponse.singleTestResult);
		expect(reporterOutput)
			.toEqual(mockdata.jestResponse.singleTestResult);
	});
});
<|endoftext|>


<commit_before>/* global it, afterEach, beforeEach, describe, Promise */

require('es6-promise').polyfill()
var assert = require('assert')
var gutil = require('gulp-util')
var sourceMaps = require('gulp-sourcemaps')
var postcss = require('./index')
var proxyquire = require('proxyquire')
var sinon = require('sinon')

it('should pass file when it isNull()', function (cb) {
  var stream = postcss([ doubler ])
  var emptyFile = {
    isNull: function () { return true }
  }

  stream.once('data', function (data) {
    assert.equal(data, emptyFile)
    cb()
  })

  stream.write(emptyFile)

  stream.end()
})

it('should transform css with multiple processors', function (cb) {

  var stream = postcss(
    [ asyncDoubler, objectDoubler() ]
  )

  stream.on('data', function (file) {
    var result = file.contents.toString('utf8')
    var target = 'a { color: black; color: black; color: black; color: black }'
    assert.equal( result, target )
    cb()
  })

  stream.write(new gutil.File({
    contents: new Buffer('a { color: black }')
  }))

  stream.end()

})

it('should correctly wrap postcss errors', function (cb) {

  var stream = postcss([ doubler ])

  stream.on('error', function (err) {
    assert.ok(err instanceof gutil.PluginError)
    assert.equal(err.plugin, 'gulp-postcss')
    assert.equal(err.showStack, false)
    assert.equal(err.fileName, 'testpath')
    cb()
  })

  stream.write(new gutil.File({
    contents: new Buffer('a {'),
    path: 'testpath'
  }))

  stream.end()

})

it('should respond with error on stream files', function (cb) {

  var stream = postcss([ doubler ])

  stream.on('error', function (err) {
    assert.ok(err instanceof gutil.PluginError)
    assert.equal(err.plugin, 'gulp-postcss')
    assert.equal(err.showStack, true)
    assert.equal(err.fileName, 'testpath')
    cb()
  })

  var streamFile = {
    isStream: function () { return true },
    isNull: function() { return false },
    path: 'testpath'
  };

  stream.write(streamFile)

  stream.end()

})

it('should throw error if processors are not provided', function (cb) {
  assert.throws( function () { postcss() }, gutil.PluginError )
  assert.throws( function () { postcss('') }, gutil.PluginError )
  assert.throws( function () { postcss({}) }, gutil.PluginError )
  cb()
})

it('should generate source maps', function (cb) {

  var init = sourceMaps.init()
  var write = sourceMaps.write()
  var css = postcss(
    [ doubler, asyncDoubler ]
  )

  init
    .pipe(css)
    .pipe(write)

  write.on('data', function (file) {
    assert.equal(file.sourceMap.mappings, 'AAAA,IAAI,aAAY,CAAZ,aAAY,CAAZ,aAAY,CAAZ,YAAY,EAAE')
    assert(/sourceMappingURL=data:application\/json;base64/.test(file.contents.toString()))
    cb()
  })

  init.write(new gutil.File({
    base: __dirname,
    path: __dirname + '/fixture.css',
    contents: new Buffer('a { color: black }')
  }))

  init.end()

})

it('should correctly generate relative source map', function (cb) {

  var init = sourceMaps.init()
  var css = postcss(
    [ doubler, doubler ]
  )

  init.pipe(css)

  css.on('data', function (file) {
    assert.equal(file.sourceMap.file, 'fixture.css')
    assert.deepEqual(file.sourceMap.sources, ['fixture.css'])
    cb()
  })

  init.write(new gutil.File({
    base: __dirname + '/src',
    path: __dirname + '/src/fixture.css',
    contents: new Buffer('a { color: black }')
  }))

  init.end()

})

describe('PostCSS Guidelines', function () {

  var sandbox = sinon.sandbox.create()
  var CssSyntaxError = function (message, sourceCode) {
    this.name = 'CssSyntaxError'
    this.message = message
    this.sourceCode = sourceCode
    this.showSourceCode = function () {
      return this.sourceCode
    }
  }
  var postcssStub = {
    use: function () {}
  , process: function () {}
  }
  var postcss = proxyquire('./index', {
    postcss: function () {
      return postcssStub
    }
  })

  beforeEach(function () {
    sandbox.stub(postcssStub, 'use')
    sandbox.stub(postcssStub, 'process')
  })

  afterEach(function () {
    sandbox.restore()
  })

  it('should set `from` and `to` processing options to `file.path`', function (cb) {

    var stream = postcss([ doubler ])
    var cssPath = __dirname + '/src/fixture.css'
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return []
      }
    }))

    stream.on('data', function () {
      assert.equal(postcssStub.process.getCall(0).args[1].to, cssPath)
      assert.equal(postcssStub.process.getCall(0).args[1].from, cssPath)
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    , path: cssPath
    }))

    stream.end()

  })

  it('should allow override of `to` processing option', function (cb) {

    var stream = postcss([ doubler ], {to: 'overriden'})
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return []
      }
    }))

    stream.on('data', function () {
      assert.equal(postcssStub.process.getCall(0).args[1].to, 'overriden')
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    }))

    stream.end()

  })

  it('should not output js stack trace for `CssSyntaxError`', function (cb) {

    var stream = postcss([ doubler ])
    var cssSyntaxError = new CssSyntaxError('message', 'sourceCode')
    postcssStub.process.returns(Promise.reject(cssSyntaxError))

    stream.on('error', function (error) {
      assert.equal(error.showStack, false)
      assert.equal(error.message, 'message' + '\n\nsourceCode\n')
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    }))

    stream.end()

  })

  it('should display `result.warnings()` content', function (cb) {

    var stream = postcss([ doubler ])
    var cssPath = __dirname + '/src/fixture.css'
    function Warning (msg) {
      this.toSting = function () {
        return msg
      }
    }

    sandbox.stub(gutil, 'log')
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return [new Warning('msg1'), new Warning('msg2')]
      }
    }))

    stream.on('data', function () {
      gutil.log.calledWith('gulp-postcss:', '/src/fixture.css\nmsg1\nmsg2')
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    , path: cssPath
    }))

    stream.end()

  })

  it('should pass options down to PostCSS', function (cb) {

    var customSyntax = function () {}
    var options = {
      syntax: customSyntax
    }

    var stream = postcss([ doubler ], options)
    var cssPath = __dirname + '/src/fixture.css'
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return []
      }
    }))

    stream.on('data', function () {
      var resultOptions = postcssStub.process.getCall(0).args[1]
      // remove automatically set options
      delete resultOptions.from
      delete resultOptions.to
      delete resultOptions.map
      assert.deepEqual(resultOptions, options)
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    , path: cssPath
    }))

    stream.end()

  })

})

function doubler (css) {
  css.walkDecls(function (decl) {
    decl.parent.prepend(decl.clone())
  })
}

function asyncDoubler (css) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      doubler(css)
      resolve()
    })
  })
}

function objectDoubler () {
  var processor = require('postcss')()
  processor.use(doubler)
  return processor
}
<commit_msg>#97 test case fix<commit_after>/* global it, afterEach, beforeEach, describe, Promise */

require('es6-promise').polyfill()
var assert = require('assert')
var gutil = require('gulp-util')
var sourceMaps = require('gulp-sourcemaps')
var postcss = require('./index')
var proxyquire = require('proxyquire')
var sinon = require('sinon')
var path = require('path')

it('should pass file when it isNull()', function (cb) {
  var stream = postcss([ doubler ])
  var emptyFile = {
    isNull: function () { return true }
  }

  stream.once('data', function (data) {
    assert.equal(data, emptyFile)
    cb()
  })

  stream.write(emptyFile)

  stream.end()
})

it('should transform css with multiple processors', function (cb) {

  var stream = postcss(
    [ asyncDoubler, objectDoubler() ]
  )

  stream.on('data', function (file) {
    var result = file.contents.toString('utf8')
    var target = 'a { color: black; color: black; color: black; color: black }'
    assert.equal( result, target )
    cb()
  })

  stream.write(new gutil.File({
    contents: new Buffer('a { color: black }')
  }))

  stream.end()

})

it('should correctly wrap postcss errors', function (cb) {

  var stream = postcss([ doubler ])

  stream.on('error', function (err) {
    assert.ok(err instanceof gutil.PluginError)
    assert.equal(err.plugin, 'gulp-postcss')
    assert.equal(err.showStack, false)
    assert.equal(err.fileName, 'testpath')
    cb()
  })

  stream.write(new gutil.File({
    contents: new Buffer('a {'),
    path: 'testpath'
  }))

  stream.end()

})

it('should respond with error on stream files', function (cb) {

  var stream = postcss([ doubler ])

  stream.on('error', function (err) {
    assert.ok(err instanceof gutil.PluginError)
    assert.equal(err.plugin, 'gulp-postcss')
    assert.equal(err.showStack, true)
    assert.equal(err.fileName, 'testpath')
    cb()
  })

  var streamFile = {
    isStream: function () { return true },
    isNull: function() { return false },
    path: 'testpath'
  };

  stream.write(streamFile)

  stream.end()

})

it('should throw error if processors are not provided', function (cb) {
  assert.throws( function () { postcss() }, gutil.PluginError )
  assert.throws( function () { postcss('') }, gutil.PluginError )
  assert.throws( function () { postcss({}) }, gutil.PluginError )
  cb()
})

it('should generate source maps', function (cb) {

  var init = sourceMaps.init()
  var write = sourceMaps.write()
  var css = postcss(
    [ doubler, asyncDoubler ]
  )

  init
    .pipe(css)
    .pipe(write)

  write.on('data', function (file) {
    assert.equal(file.sourceMap.mappings, 'AAAA,IAAI,aAAY,CAAZ,aAAY,CAAZ,aAAY,CAAZ,YAAY,EAAE')
    assert(/sourceMappingURL=data:application\/json;base64/.test(file.contents.toString()))
    cb()
  })

  init.write(new gutil.File({
    base: __dirname,
    path: __dirname + '/fixture.css',
    contents: new Buffer('a { color: black }')
  }))

  init.end()

})

it('should correctly generate relative source map', function (cb) {

  var init = sourceMaps.init()
  var css = postcss(
    [ doubler, doubler ]
  )

  init.pipe(css)

  css.on('data', function (file) {
    assert.equal(file.sourceMap.file, 'fixture.css')
    assert.deepEqual(file.sourceMap.sources, ['fixture.css'])
    cb()
  })

  init.write(new gutil.File({
    base: __dirname + '/src',
    path: __dirname + '/src/fixture.css',
    contents: new Buffer('a { color: black }')
  }))

  init.end()

})

describe('PostCSS Guidelines', function () {

  var sandbox = sinon.sandbox.create()
  var CssSyntaxError = function (message, sourceCode) {
    this.name = 'CssSyntaxError'
    this.message = message
    this.sourceCode = sourceCode
    this.showSourceCode = function () {
      return this.sourceCode
    }
  }
  var postcssStub = {
    use: function () {}
  , process: function () {}
  }
  var postcss = proxyquire('./index', {
    postcss: function () {
      return postcssStub
    }
  })

  beforeEach(function () {
    sandbox.stub(postcssStub, 'use')
    sandbox.stub(postcssStub, 'process')
  })

  afterEach(function () {
    sandbox.restore()
  })

  it('should set `from` and `to` processing options to `file.path`', function (cb) {

    var stream = postcss([ doubler ])
    var cssPath = __dirname + '/src/fixture.css'
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return []
      }
    }))

    stream.on('data', function () {
      assert.equal(postcssStub.process.getCall(0).args[1].to, cssPath)
      assert.equal(postcssStub.process.getCall(0).args[1].from, cssPath)
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    , path: cssPath
    }))

    stream.end()

  })

  it('should allow override of `to` processing option', function (cb) {

    var stream = postcss([ doubler ], {to: 'overriden'})
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return []
      }
    }))

    stream.on('data', function () {
      assert.equal(postcssStub.process.getCall(0).args[1].to, 'overriden')
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    }))

    stream.end()

  })

  it('should not output js stack trace for `CssSyntaxError`', function (cb) {

    var stream = postcss([ doubler ])
    var cssSyntaxError = new CssSyntaxError('message', 'sourceCode')
    postcssStub.process.returns(Promise.reject(cssSyntaxError))

    stream.on('error', function (error) {
      assert.equal(error.showStack, false)
      assert.equal(error.message, 'message' + '\n\nsourceCode\n')
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    }))

    stream.end()

  })

  it('should display `result.warnings()` content', function (cb) {

    var stream = postcss([ doubler ])
    var cssPath = __dirname + '/src/fixture.css'
    function Warning (msg) {
      this.toString = function () {
        return msg
      }
    }

    sandbox.stub(gutil, 'log')
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return [new Warning('msg1'), new Warning('msg2')]
      }
    }))

    stream.on('data', function () {
      assert(gutil.log.calledWith('gulp-postcss:', 'src' +  path.sep + 'fixture.css\nmsg1\nmsg2'))
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    , path: cssPath
    }))

    stream.end()

  })

  it('should pass options down to PostCSS', function (cb) {

    var customSyntax = function () {}
    var options = {
      syntax: customSyntax
    }

    var stream = postcss([ doubler ], options)
    var cssPath = __dirname + '/src/fixture.css'
    postcssStub.process.returns(Promise.resolve({
      css: ''
    , warnings: function () {
        return []
      }
    }))

    stream.on('data', function () {
      var resultOptions = postcssStub.process.getCall(0).args[1]
      // remove automatically set options
      delete resultOptions.from
      delete resultOptions.to
      delete resultOptions.map
      assert.deepEqual(resultOptions, options)
      cb()
    })

    stream.write(new gutil.File({
      contents: new Buffer('a {}')
    , path: cssPath
    }))

    stream.end()

  })

})

function doubler (css) {
  css.walkDecls(function (decl) {
    decl.parent.prepend(decl.clone())
  })
}

function asyncDoubler (css) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      doubler(css)
      resolve()
    })
  })
}

function objectDoubler () {
  var processor = require('postcss')()
  processor.use(doubler)
  return processor
}
<|endoftext|>


<commit_before>/*!
 * relative <https://github.com/jonschlinkert/relative>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

require('should');
var fs = require('fs');
var path = require('path');
var relative = require('./');
var cwd = process.cwd();

function normalize(str) {
  return str.replace(/[\\\/]+/g, '/');
}

function rel() {
  var res = relative.apply(relative, arguments);
  return normalize(res);
}

describe('relative', function() {
  it('should resolve the relative path from a file to a file', function() {
    rel('a/b/c.txt', 'd').should.equal('../../d');
    rel('d', 'a/b/c.txt').should.equal('../a/b/c.txt');
    rel('a/b/c.txt', 'd/e/f.txt').should.equal('../../d/e/f.txt');
    rel('a/b/c.txt', 'a/b/g.txt').should.equal('g.txt');
  });

  it('should resolve the relative path from a file to a directory', function() {
    rel('fixtures/a.txt', 'b/').should.equal('../b/');
    rel('b/', 'fixtures/a.txt').should.equal('../fixtures/a.txt');
    rel('a/b/c.txt', 'd').should.equal('../../d');
    rel('a\\b\\c.txt', 'd').should.equal('../../d');
    rel('a\\b\\c.txt', 'a/b').should.equal('.');
  });

  it('should resolve the relative path from a directory to a directory', function() {
    rel('a', 'a').should.equal('.');
    rel('a/b', 'd').should.equal('../../d');
    rel('a/c', 'a/g').should.equal('../g');
    rel('../a/c', '../a/g').should.equal('../g');
  });

  it('should resolve the relative path from a directory to a file', function() {
    rel('a/b', 'd/c.txt').should.equal('../../d/c.txt');
    rel('a/b', 'a/c.txt').should.equal('../c.txt');
    rel('a-with-dashes', 'a-with-dashes/b/c.txt').should.equal('b/c.txt');
  });

  it('should work when the dirname has dots', function() {
    rel('fixtures/abc/', 'fixtures/abc/b/c.txt').should.equal('b/c.txt');
    rel('fixtures/a.b.c/', 'fixtures/a.b.c/b/c.txt').should.equal('b/c.txt');

    // this should be considered a filename, since the path does not end in a slash
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt').should.equal('a.b.c/b/c.txt');
  });
});

describe('stat', function() {
  it('should use fs.statSync() when `true` is passed as the last arg:', function() {
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt').should.equal('a.b.c/b/c.txt');
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt', true).should.equal('b/c.txt');

    rel('fixtures/a.b.c', 'fixtures').should.equal('.');
    rel('fixtures/a.b.c', 'fixtures', true).should.equal('..');
  });

  it('should use a `stat` object when passed as the last arg:', function() {
    var stat = fs.statSync('fixtures/a.b.c');

    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt').should.equal('a.b.c/b/c.txt');
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt', stat).should.equal('b/c.txt');

    rel('fixtures/LICENSE', 'fixtures').should.equal('..');
    rel('fixtures/LICENSE', 'fixtures', stat).should.equal('..');

    rel('fixtures/a.b.c', 'fixtures').should.equal('.');
    rel('fixtures/a.b.c', 'fixtures', stat).should.equal('..');
  });
});

describe('process.cwd()', function() {
  it('should use process.cwd() when only one argument is passed', function() {
    rel('a/b/c.txt').should.equal('a/b/c.txt');
    rel(process.cwd()).should.equal('.');
    rel('../c').should.equal('../c');
    rel('./').should.equal('.');
  });

  it('should get the relative path TO process.cwd()', function() {
    rel('a/b.txt', process.cwd()).should.equal('..');
    rel('a/b/', process.cwd()).should.equal('../..');
    rel('a/b/c.txt', process.cwd()).should.equal('../..');

    // these will always be wrong unless we provide more information
    rel('a/LICENSE', process.cwd()).should.equal('../..');
    rel('a/b', process.cwd()).should.equal('../..');
  });

  it('should get the relative path FROM process.cwd()', function() {
    rel(process.cwd(), 'a/b/c.txt').should.equal('a/b/c.txt');

    rel(process.cwd(), 'a/b.txt').should.equal('a/b.txt');
    rel(process.cwd(), 'a/b/').should.equal('a/b/');
    rel(process.cwd(), 'a/b/c.txt').should.equal('a/b/c.txt');
    rel(process.cwd(), 'a/LICENSE').should.equal('a/LICENSE');
    rel(process.cwd(), 'a/b').should.equal('a/b');
  });
});

describe('.toBase()', function() {
  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b', 'a/b/d/e/f.txt').should.equal('d/e/f.txt');
  });

  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b/', 'a/b/d/e/f.txt').should.equal('d/e/f.txt');
  });

  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b/', 'a/b/d/e').should.equal('d/e');
    relative.toBase('a/b/', 'a/b/d/e/').should.equal('d/e/');
  });

  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b/', 'a/b/d/e/').should.equal('d/e/');
  });
});
<commit_msg>tests for errors<commit_after>/*!
 * relative <https://github.com/jonschlinkert/relative>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

require('should');
var fs = require('fs');
var path = require('path');
var relative = require('./');
var cwd = process.cwd();

function normalize(str) {
  return str.replace(/[\\\/]+/g, '/');
}

function rel() {
  var res = relative.apply(relative, arguments);
  return normalize(res);
}

describe('relative', function() {
  it('should throw an error on bad args:', function() {
    (function() {
      rel();
    }).should.throw('relative expects a string.');

    (function() {
      rel(null);
    }).should.throw('relative expects a string.');

    (function() {
      rel({});
    }).should.throw('relative expects a string.');

    (function() {
      rel([]);
    }).should.throw('relative expects a string.');
  });

  it('should return an empty string', function() {
    rel('').should.equal('');
  });

  it('should resolve the relative path from a file to a file', function() {
    rel('', 'dir').should.equal('dir');
    rel('a/b/c.txt', 'd').should.equal('../../d');
    rel('d', 'a/b/c.txt').should.equal('../a/b/c.txt');
    rel('a/b/c.txt', 'd/e/f.txt').should.equal('../../d/e/f.txt');
    rel('a/b/c.txt', 'a/b/g.txt').should.equal('g.txt');
  });

  it('should resolve the relative path from a file to a directory', function() {
    rel('fixtures/a.txt', 'b/').should.equal('../b/');
    rel('b/', 'fixtures/a.txt').should.equal('../fixtures/a.txt');
    rel('a/b/c.txt', 'd').should.equal('../../d');
    rel('a\\b\\c.txt', 'd').should.equal('../../d');
    rel('a\\b\\c.txt', 'a/b').should.equal('.');
  });

  it('should resolve the relative path from a directory to a directory', function() {
    rel('a', 'a').should.equal('.');
    rel('a/b', 'd').should.equal('../../d');
    rel('a/c', 'a/g').should.equal('../g');
    rel('../a/c', '../a/g').should.equal('../g');
  });

  it('should resolve the relative path from a directory to a file', function() {
    rel('a/b', 'd/c.txt').should.equal('../../d/c.txt');
    rel('a/b', 'a/c.txt').should.equal('../c.txt');
    rel('a-with-dashes', 'a-with-dashes/b/c.txt').should.equal('b/c.txt');
  });

  it('should work when the dirname has dots', function() {
    rel('fixtures/abc/', 'fixtures/abc/b/c.txt').should.equal('b/c.txt');
    rel('fixtures/a.b.c/', 'fixtures/a.b.c/b/c.txt').should.equal('b/c.txt');

    // this should be considered a filename, since the path does not end in a slash
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt').should.equal('a.b.c/b/c.txt');
  });
});

describe('stat', function() {
  it('should use fs.statSync() when `true` is passed as the last arg:', function() {
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt').should.equal('a.b.c/b/c.txt');
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt', true).should.equal('b/c.txt');

    rel('fixtures/a.b.c', 'fixtures').should.equal('.');
    rel('fixtures/a.b.c', 'fixtures', true).should.equal('..');
  });

  it('should use a `stat` object when passed as the last arg:', function() {
    var stat = fs.statSync('fixtures/a.b.c');

    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt').should.equal('a.b.c/b/c.txt');
    rel('fixtures/a.b.c', 'fixtures/a.b.c/b/c.txt', stat).should.equal('b/c.txt');

    rel('fixtures/LICENSE', 'fixtures').should.equal('..');
    rel('fixtures/LICENSE', 'fixtures', stat).should.equal('..');

    rel('fixtures/a.b.c', 'fixtures').should.equal('.');
    rel('fixtures/a.b.c', 'fixtures', stat).should.equal('..');
  });
});

describe('process.cwd()', function() {
  it('should use process.cwd() when only one argument is passed', function() {
    rel('a/b/c.txt').should.equal('a/b/c.txt');
    rel(process.cwd()).should.equal('.');
    rel('../c').should.equal('../c');
    rel('./').should.equal('.');
  });

  it('should get the relative path TO process.cwd()', function() {
    rel('a/b.txt', process.cwd()).should.equal('..');
    rel('a/b/', process.cwd()).should.equal('../..');
    rel('a/b/c.txt', process.cwd()).should.equal('../..');

    // these will always be wrong unless we provide more information
    rel('a/LICENSE', process.cwd()).should.equal('../..');
    rel('a/b', process.cwd()).should.equal('../..');
  });

  it('should get the relative path FROM process.cwd()', function() {
    rel(process.cwd(), 'a/b/c.txt').should.equal('a/b/c.txt');

    rel(process.cwd(), 'a/b.txt').should.equal('a/b.txt');
    rel(process.cwd(), 'a/b/').should.equal('a/b/');
    rel(process.cwd(), 'a/b/c.txt').should.equal('a/b/c.txt');
    rel(process.cwd(), 'a/LICENSE').should.equal('a/LICENSE');
    rel(process.cwd(), 'a/b').should.equal('a/b');
  });
});

describe('.toBase()', function() {
  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b', 'a/b/d/e/f.txt').should.equal('d/e/f.txt');
  });

  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b/', 'a/b/d/e/f.txt').should.equal('d/e/f.txt');
  });

  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b/', 'a/b/d/e').should.equal('d/e');
    relative.toBase('a/b/', 'a/b/d/e/').should.equal('d/e/');
  });

  it('should resolve the relative path from a base path to a file', function() {
    relative.toBase('a/b/', 'a/b/d/e/').should.equal('d/e/');
  });
});
<|endoftext|>


<commit_before>/**
 * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
 * @author mrdoob / http://mrdoob.com/
 */

THREE.CSS3DObject = function ( element ) {

	THREE.Object3D.call( this );

	this.element = element;
	this.element.style.position = 'absolute';
	this.element.style.WebkitTransformStyle = 'preserve-3d';
	this.element.style.MozTransformStyle = 'preserve-3d';
	this.element.style.oTransformStyle = 'preserve-3d';
	this.element.style.transformStyle = 'preserve-3d';

	this.addEventListener( 'removed', function ( event ) {

		if ( this.element.parentNode !== null ) {

			this.element.parentNode.removeChild( this.element );

			for ( var i = 0, l = this.children.length; i < l; i ++ ) {

				this.children[ i ].dispatchEvent( event );

			}

		}

	} );

};

THREE.CSS3DObject.prototype = Object.create( THREE.Object3D.prototype );

THREE.CSS3DSprite = function ( element ) {

	THREE.CSS3DObject.call( this, element );

};

THREE.CSS3DSprite.prototype = Object.create( THREE.CSS3DObject.prototype );

//

THREE.CSS3DRenderer = function () {

	console.log( 'THREE.CSS3DRenderer', THREE.REVISION );

	var _width, _height;
	var _widthHalf, _heightHalf;

	var matrix = new THREE.Matrix4();

	var domElement = document.createElement( 'div' );
	domElement.style.overflow = 'hidden';

	domElement.style.WebkitTransformStyle = 'preserve-3d';
	domElement.style.MozTransformStyle = 'preserve-3d';
	domElement.style.oTransformStyle = 'preserve-3d';
	domElement.style.transformStyle = 'preserve-3d';

	this.domElement = domElement;

	var cameraElement = document.createElement( 'div' );

	cameraElement.style.WebkitTransformStyle = 'preserve-3d';
	cameraElement.style.MozTransformStyle = 'preserve-3d';
	cameraElement.style.oTransformStyle = 'preserve-3d';
	cameraElement.style.transformStyle = 'preserve-3d';

	domElement.appendChild( cameraElement );

	this.setClearColor = function () {

	};

	this.setSize = function ( width, height ) {

		_width = width;
		_height = height;

		_widthHalf = _width / 2;
		_heightHalf = _height / 2;

		domElement.style.width = width + 'px';
		domElement.style.height = height + 'px';

		cameraElement.style.width = width + 'px';
		cameraElement.style.height = height + 'px';

	};

	var epsilon = function ( value ) {

		return Math.abs( value ) < 0.000001 ? 0 : value;

	};

	var getCameraCSSMatrix = function ( matrix ) {

		var elements = matrix.elements;

		return 'matrix3d(' +
			epsilon( elements[ 0 ] ) + ',' +
			epsilon( - elements[ 1 ] ) + ',' +
			epsilon( elements[ 2 ] ) + ',' +
			epsilon( elements[ 3 ] ) + ',' +
			epsilon( elements[ 4 ] ) + ',' +
			epsilon( - elements[ 5 ] ) + ',' +
			epsilon( elements[ 6 ] ) + ',' +
			epsilon( elements[ 7 ] ) + ',' +
			epsilon( elements[ 8 ] ) + ',' +
			epsilon( - elements[ 9 ] ) + ',' +
			epsilon( elements[ 10 ] ) + ',' +
			epsilon( elements[ 11 ] ) + ',' +
			epsilon( elements[ 12 ] ) + ',' +
			epsilon( - elements[ 13 ] ) + ',' +
			epsilon( elements[ 14 ] ) + ',' +
			epsilon( elements[ 15 ] ) +
		')';

	};

	var getObjectCSSMatrix = function ( matrix ) {

		var elements = matrix.elements;

		return 'translate3d(-50%,-50%,0) matrix3d(' +
			epsilon( elements[ 0 ] ) + ',' +
			epsilon( elements[ 1 ] ) + ',' +
			epsilon( elements[ 2 ] ) + ',' +
			epsilon( elements[ 3 ] ) + ',' +
			epsilon( - elements[ 4 ] ) + ',' +
			epsilon( - elements[ 5 ] ) + ',' +
			epsilon( - elements[ 6 ] ) + ',' +
			epsilon( - elements[ 7 ] ) + ',' +
			epsilon( elements[ 8 ] ) + ',' +
			epsilon( elements[ 9 ] ) + ',' +
			epsilon( elements[ 10 ] ) + ',' +
			epsilon( elements[ 11 ] ) + ',' +
			epsilon( elements[ 12 ] ) + ',' +
			epsilon( elements[ 13 ] ) + ',' +
			epsilon( elements[ 14 ] ) + ',' +
			epsilon( elements[ 15 ] ) +
		')';

	};

	var renderObject = function ( object, camera ) {

		if ( object instanceof THREE.CSS3DObject ) {

			var style;

			if ( object instanceof THREE.CSS3DSprite ) {

				// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/

				matrix.copy( camera.matrixWorldInverse );
				matrix.transpose();
				matrix.copyPosition( object.matrixWorld );
				matrix.scale( object.scale );

				matrix.elements[ 3 ] = 0;
				matrix.elements[ 7 ] = 0;
				matrix.elements[ 11 ] = 0;
				matrix.elements[ 15 ] = 1;

				style = getObjectCSSMatrix( matrix );

			} else {

				style = getObjectCSSMatrix( object.matrixWorld );

			}

			var element = object.element;

			element.style.WebkitTransform = style;
			element.style.MozTransform = style;
			element.style.oTransform = style;
			element.style.transform = style;

			if ( element.parentNode !== cameraElement ) {

				cameraElement.appendChild( element );

			}

		}

		for ( var i = 0, l = object.children.length; i < l; i ++ ) {

			renderObject( object.children[ i ], camera );

		}

	};

	this.render = function ( scene, camera ) {

		var fov = 0.5 / Math.tan( THREE.Math.degToRad( camera.fov * 0.5 ) ) * _height;

		domElement.style.WebkitPerspective = fov + "px";
		domElement.style.MozPerspective = fov + "px";
		domElement.style.oPerspective = fov + "px";
		domElement.style.perspective = fov + "px";

		scene.updateMatrixWorld();

		if ( camera.parent === undefined ) camera.updateMatrixWorld();

		camera.matrixWorldInverse.getInverse( camera.matrixWorld );

		var style = "translate3d(0,0," + fov + "px)" + getCameraCSSMatrix( camera.matrixWorldInverse ) +
			" translate3d(" + _widthHalf + "px," + _heightHalf + "px, 0)";

		cameraElement.style.WebkitTransform = style;
		cameraElement.style.MozTransform = style;
		cameraElement.style.oTransform = style;
		cameraElement.style.transform = style;

		renderObject( scene, camera );

	};

};
<commit_msg>CSS3DRenderer: I don’t think the elements need preserve-3d.<commit_after>/**
 * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
 * @author mrdoob / http://mrdoob.com/
 */

THREE.CSS3DObject = function ( element ) {

	THREE.Object3D.call( this );

	this.element = element;
	this.element.style.position = 'absolute';

	this.addEventListener( 'removed', function ( event ) {

		if ( this.element.parentNode !== null ) {

			this.element.parentNode.removeChild( this.element );

			for ( var i = 0, l = this.children.length; i < l; i ++ ) {

				this.children[ i ].dispatchEvent( event );

			}

		}

	} );

};

THREE.CSS3DObject.prototype = Object.create( THREE.Object3D.prototype );

THREE.CSS3DSprite = function ( element ) {

	THREE.CSS3DObject.call( this, element );

};

THREE.CSS3DSprite.prototype = Object.create( THREE.CSS3DObject.prototype );

//

THREE.CSS3DRenderer = function () {

	console.log( 'THREE.CSS3DRenderer', THREE.REVISION );

	var _width, _height;
	var _widthHalf, _heightHalf;

	var matrix = new THREE.Matrix4();

	var domElement = document.createElement( 'div' );
	domElement.style.overflow = 'hidden';

	domElement.style.WebkitTransformStyle = 'preserve-3d';
	domElement.style.MozTransformStyle = 'preserve-3d';
	domElement.style.oTransformStyle = 'preserve-3d';
	domElement.style.transformStyle = 'preserve-3d';

	this.domElement = domElement;

	var cameraElement = document.createElement( 'div' );

	cameraElement.style.WebkitTransformStyle = 'preserve-3d';
	cameraElement.style.MozTransformStyle = 'preserve-3d';
	cameraElement.style.oTransformStyle = 'preserve-3d';
	cameraElement.style.transformStyle = 'preserve-3d';

	domElement.appendChild( cameraElement );

	this.setClearColor = function () {

	};

	this.setSize = function ( width, height ) {

		_width = width;
		_height = height;

		_widthHalf = _width / 2;
		_heightHalf = _height / 2;

		domElement.style.width = width + 'px';
		domElement.style.height = height + 'px';

		cameraElement.style.width = width + 'px';
		cameraElement.style.height = height + 'px';

	};

	var epsilon = function ( value ) {

		return Math.abs( value ) < 0.000001 ? 0 : value;

	};

	var getCameraCSSMatrix = function ( matrix ) {

		var elements = matrix.elements;

		return 'matrix3d(' +
			epsilon( elements[ 0 ] ) + ',' +
			epsilon( - elements[ 1 ] ) + ',' +
			epsilon( elements[ 2 ] ) + ',' +
			epsilon( elements[ 3 ] ) + ',' +
			epsilon( elements[ 4 ] ) + ',' +
			epsilon( - elements[ 5 ] ) + ',' +
			epsilon( elements[ 6 ] ) + ',' +
			epsilon( elements[ 7 ] ) + ',' +
			epsilon( elements[ 8 ] ) + ',' +
			epsilon( - elements[ 9 ] ) + ',' +
			epsilon( elements[ 10 ] ) + ',' +
			epsilon( elements[ 11 ] ) + ',' +
			epsilon( elements[ 12 ] ) + ',' +
			epsilon( - elements[ 13 ] ) + ',' +
			epsilon( elements[ 14 ] ) + ',' +
			epsilon( elements[ 15 ] ) +
		')';

	};

	var getObjectCSSMatrix = function ( matrix ) {

		var elements = matrix.elements;

		return 'translate3d(-50%,-50%,0) matrix3d(' +
			epsilon( elements[ 0 ] ) + ',' +
			epsilon( elements[ 1 ] ) + ',' +
			epsilon( elements[ 2 ] ) + ',' +
			epsilon( elements[ 3 ] ) + ',' +
			epsilon( - elements[ 4 ] ) + ',' +
			epsilon( - elements[ 5 ] ) + ',' +
			epsilon( - elements[ 6 ] ) + ',' +
			epsilon( - elements[ 7 ] ) + ',' +
			epsilon( elements[ 8 ] ) + ',' +
			epsilon( elements[ 9 ] ) + ',' +
			epsilon( elements[ 10 ] ) + ',' +
			epsilon( elements[ 11 ] ) + ',' +
			epsilon( elements[ 12 ] ) + ',' +
			epsilon( elements[ 13 ] ) + ',' +
			epsilon( elements[ 14 ] ) + ',' +
			epsilon( elements[ 15 ] ) +
		')';

	};

	var renderObject = function ( object, camera ) {

		if ( object instanceof THREE.CSS3DObject ) {

			var style;

			if ( object instanceof THREE.CSS3DSprite ) {

				// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/

				matrix.copy( camera.matrixWorldInverse );
				matrix.transpose();
				matrix.copyPosition( object.matrixWorld );
				matrix.scale( object.scale );

				matrix.elements[ 3 ] = 0;
				matrix.elements[ 7 ] = 0;
				matrix.elements[ 11 ] = 0;
				matrix.elements[ 15 ] = 1;

				style = getObjectCSSMatrix( matrix );

			} else {

				style = getObjectCSSMatrix( object.matrixWorld );

			}

			var element = object.element;

			element.style.WebkitTransform = style;
			element.style.MozTransform = style;
			element.style.oTransform = style;
			element.style.transform = style;

			if ( element.parentNode !== cameraElement ) {

				cameraElement.appendChild( element );

			}

		}

		for ( var i = 0, l = object.children.length; i < l; i ++ ) {

			renderObject( object.children[ i ], camera );

		}

	};

	this.render = function ( scene, camera ) {

		var fov = 0.5 / Math.tan( THREE.Math.degToRad( camera.fov * 0.5 ) ) * _height;

		domElement.style.WebkitPerspective = fov + "px";
		domElement.style.MozPerspective = fov + "px";
		domElement.style.oPerspective = fov + "px";
		domElement.style.perspective = fov + "px";

		scene.updateMatrixWorld();

		if ( camera.parent === undefined ) camera.updateMatrixWorld();

		camera.matrixWorldInverse.getInverse( camera.matrixWorld );

		var style = "translate3d(0,0," + fov + "px)" + getCameraCSSMatrix( camera.matrixWorldInverse ) +
			" translate3d(" + _widthHalf + "px," + _heightHalf + "px, 0)";

		cameraElement.style.WebkitTransform = style;
		cameraElement.style.MozTransform = style;
		cameraElement.style.oTransform = style;
		cameraElement.style.transform = style;

		renderObject( scene, camera );

	};

};
<|endoftext|>


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

const https = require('https')
const child = require('child_process')
const fs = require('fs/promises')
const { createWriteStream: createFileWriteStream } = require('fs')
const stream = require('stream')
const path = require('path')
const os = require('os')

const IS_WINDOWS = process.platform === 'win32'
const VERSION = '1.0.18'
const VS = 'v141'

const UNIX = `https://download.libsodium.org/libsodium/releases/libsodium-${VERSION}.tar.gz`
const WIN = `https://download.libsodium.org/libsodium/releases/libsodium-${VERSION}-msvc.zip`

const UNIX_OUT = path.join(__dirname, 'unix')
const WIN_OUT = path.join(__dirname, 'win')

const TMP = path.join(__dirname, 'tmp')
const TMP_ZIP = path.join(TMP, 'win.zip')
const TMP_OUT = path.join(TMP, 'out')
const TMP_SRC = path.join(TMP, 'src')

const SRC = path.join(__dirname, 'libsodium-' + VERSION)

const ARCH = arg('arch') || process.env.PREBUILD_ARCH || os.arch()
const WARCH = ARCH === 'x64' ? 'x64' : 'Win32'
const QUIET = arg('print-include') || arg('print-lib') || arg('print-arch') || arg('quiet')

if (arg('print-arch')) {
  console.log(ARCH)
  process.exit(0)
}

const build = arg('clean')
  ? clean
  : arg('all')
    ? all
    : (IS_WINDOWS ? win : unix)

start()

async function start () {
  await rmf(TMP)
  try {
    await build()
  } catch (err) {
    console.error(err.stack)
    process.exit(1)
  }
  await rmf(TMP)
  if (arg('gyp')) {
    await nodeGyp()
  }
}

async function all () {
  await unix()
  await win()
}

async function unix () {
  await fetchUnix()
  await buildUnix()

  if (arg('print-lib')) {
    console.log(path.join(UNIX_OUT, 'lib/libsodium.a'))
  }

  if (arg('print-include')) {
    console.log(path.join(UNIX_OUT, 'include'))
  }
}

async function win () {
  await fetchWin()

  if (arg('print-lib')) {
    const vs = arg('vs') || VS
    const out = path.join(WIN_OUT, WARCH, 'Release')
    let found = null
    for (const version of await fs.readdir(out)) {
      if (vs) {
        if (vs === version) {
          found = version
          break
        }
      } else {
        if (!found || Number(version.replace('v', '')) > Number(found.replace('v', ''))) {
          found = version
        }
      }
    }

    if (!found) throw new Error('Could not find valid static library')

    console.log(path.join(out, found, 'static', 'libsodium.lib'))
  }

  if (arg('print-include')) {
    console.log(path.join(WIN_OUT, 'include'))
  }
}

async function nodeGyp () {
  await run(['node-gyp' + (IS_WINDOWS ? '.cmd' : ''), 'rebuild', '-v'], { cwd: path.join(__dirname, '..') })
}

async function buildUnix () {
  if (!(await flag('build', UNIX_OUT))) return

  await run(['./configure', '--prefix=' + TMP_OUT, '--enable-static', '--with-pic', '--disable-pie'], { cwd: SRC })
  await run(['make', 'clean'], { cwd: SRC })
  await run(['make', 'install'], { cwd: SRC })

  await rmf(UNIX_OUT)
  await fs.rename(TMP_OUT, UNIX_OUT)
}

async function fetchUnix () {
  if (!(await flag('fetch', SRC))) return

  await fs.mkdir(TMP_SRC, { recursive: true })
  const tar = await fetch(UNIX)
  await run(['tar', 'xzv'], { cwd: TMP_SRC, stdin: tar })

  // Atomically store it here
  await rmf(SRC)
  await fs.rename(path.join(TMP_SRC, 'libsodium-' + VERSION), SRC)
}

async function fetchWin () {
  if (!(await flag('fetch', WIN_OUT))) return

  const zip = await fetch(WIN)

  await fs.mkdir(TMP, { recursive: true })
  await new Promise((resolve, reject) => {
    stream.pipeline(zip, createFileWriteStream(TMP_ZIP), function (err) {
      if (err) reject(err)
      else resolve()
    })
  })

  if (process.platform === 'win32') {
    await run(['powershell', '-command', 'Expand-Archive win.zip out'], { cwd: TMP })
  } else {
    await run(['unzip', '-d', 'out', 'win.zip'], { cwd: TMP })
  }

  await fs.rename(path.join(TMP_OUT, 'libsodium'), WIN_OUT)
}

async function flag (name, folder) {
  if (process.argv.includes('--' + name)) return true
  if (process.argv.includes('--no-' + name)) return false

  try {
    await fs.stat(folder)
    return false
  } catch {
    return true
  }
}

async function clean () {
  await rmf(TMP)
  await rmf(SRC)
  await rmf(UNIX_OUT)
  await rmf(WIN_OUT)
}

async function rmf (dir) {
  try {
    await fs.stat(dir)
    await fs.rm(dir, { recursive: true })
  } catch {
    // do nothing
  }
}

function fetch (url) {
  return new Promise((resolve, reject) => {
    if (!QUIET) console.error('Fetching', url)
    https.get(url, function (res) {
      if (res.statusCode !== 200) return reject(new Error('Could not download ' + url + ' (' + res.statusCode + ')'))
      resolve(res)
    })
  })
}

function arg (name) {
  const i = process.argv.indexOf('--' + name)
  if (i === -1) return false
  if (process.argv.length <= i + 1 || process.argv[i + 1][0] === '-') return true
  return process.argv[i + 1]
}

function run (cmd, opts = {}) {
  return new Promise((resolve) => {
    const proc = child.spawn(cmd[0], cmd.slice(1), {
      cwd: opts.cwd || __dirname,
      stdio: [
        opts.stdin ? 'pipe' : 'ignore',
        QUIET ? 'ignore' : 2,
        QUIET ? 'ignore' : 2
      ]
    })

    if (opts.stdin) {
      opts.stdin.pipe(proc.stdin)
    }

    proc.on('exit', function (code) {
      if (code) process.exit(code)
      else resolve()
    })
  })
}
<commit_msg>fix mac builds<commit_after>#!/usr/bin/env node

const https = require('https')
const child = require('child_process')
const fs = require('fs/promises')
const { createWriteStream: createFileWriteStream } = require('fs')
const stream = require('stream')
const path = require('path')
const os = require('os')

const IS_WINDOWS = process.platform === 'win32'
const VERSION = '1.0.18'
const VS = 'v141'
const MACOSX_DEPLOYMENT_TARGET = '10.10'

const UNIX = `https://download.libsodium.org/libsodium/releases/libsodium-${VERSION}.tar.gz`
const WIN = `https://download.libsodium.org/libsodium/releases/libsodium-${VERSION}-msvc.zip`

const UNIX_OUT = path.join(__dirname, 'unix')
const WIN_OUT = path.join(__dirname, 'win')

const TMP = path.join(__dirname, 'tmp')
const TMP_ZIP = path.join(TMP, 'win.zip')
const TMP_OUT = path.join(TMP, 'out')
const TMP_SRC = path.join(TMP, 'src')

const SRC = path.join(__dirname, 'libsodium-' + VERSION)

const ARCH = arg('arch') || process.env.PREBUILD_ARCH || os.arch()
const WARCH = ARCH === 'x64' ? 'x64' : 'Win32'
const QUIET = arg('print-include') || arg('print-lib') || arg('print-arch') || arg('quiet')

if (arg('print-arch')) {
  console.log(ARCH)
  process.exit(0)
}

const build = arg('clean')
  ? clean
  : arg('all')
    ? all
    : (IS_WINDOWS ? win : unix)

start()

async function start () {
  await rmf(TMP)
  try {
    await build()
  } catch (err) {
    console.error(err.stack)
    process.exit(1)
  }
  await rmf(TMP)
  if (arg('gyp')) {
    await nodeGyp()
  }
}

async function all () {
  await unix()
  await win()
}

async function unix () {
  await fetchUnix()
  await buildUnix()

  if (arg('print-lib')) {
    console.log(path.join(UNIX_OUT, 'lib/libsodium.a'))
  }

  if (arg('print-include')) {
    console.log(path.join(UNIX_OUT, 'include'))
  }
}

async function win () {
  await fetchWin()

  if (arg('print-lib')) {
    const vs = arg('vs') || VS
    const out = path.join(WIN_OUT, WARCH, 'Release')
    let found = null
    for (const version of await fs.readdir(out)) {
      if (vs) {
        if (vs === version) {
          found = version
          break
        }
      } else {
        if (!found || Number(version.replace('v', '')) > Number(found.replace('v', ''))) {
          found = version
        }
      }
    }

    if (!found) throw new Error('Could not find valid static library')

    console.log(path.join(out, found, 'static', 'libsodium.lib'))
  }

  if (arg('print-include')) {
    console.log(path.join(WIN_OUT, 'include'))
  }
}

async function nodeGyp () {
  await run(['node-gyp' + (IS_WINDOWS ? '.cmd' : ''), 'rebuild', '-v'], { cwd: path.join(__dirname, '..') })
}

async function buildUnix () {
  if (!(await flag('build', UNIX_OUT))) return

  await run(['./configure', '--prefix=' + TMP_OUT, '--enable-static', '--with-pic', '--disable-pie'], { cwd: SRC })
  await run(['make', 'clean'], { cwd: SRC })
  await run(['make', 'install'], { cwd: SRC })

  await rmf(UNIX_OUT)
  await fs.rename(TMP_OUT, UNIX_OUT)
}

async function fetchUnix () {
  if (!(await flag('fetch', SRC))) return

  await fs.mkdir(TMP_SRC, { recursive: true })
  const tar = await fetch(UNIX)
  await run(['tar', 'xzv'], { cwd: TMP_SRC, stdin: tar })

  // Atomically store it here
  await rmf(SRC)
  await fs.rename(path.join(TMP_SRC, 'libsodium-' + VERSION), SRC)
}

async function fetchWin () {
  if (!(await flag('fetch', WIN_OUT))) return

  const zip = await fetch(WIN)

  await fs.mkdir(TMP, { recursive: true })
  await new Promise((resolve, reject) => {
    stream.pipeline(zip, createFileWriteStream(TMP_ZIP), function (err) {
      if (err) reject(err)
      else resolve()
    })
  })

  if (process.platform === 'win32') {
    await run(['powershell', '-command', 'Expand-Archive win.zip out'], { cwd: TMP })
  } else {
    await run(['unzip', '-d', 'out', 'win.zip'], { cwd: TMP })
  }

  await fs.rename(path.join(TMP_OUT, 'libsodium'), WIN_OUT)
}

async function flag (name, folder) {
  if (process.argv.includes('--' + name)) return true
  if (process.argv.includes('--no-' + name)) return false

  try {
    await fs.stat(folder)
    return false
  } catch {
    return true
  }
}

async function clean () {
  await rmf(TMP)
  await rmf(SRC)
  await rmf(UNIX_OUT)
  await rmf(WIN_OUT)
}

async function rmf (dir) {
  try {
    await fs.stat(dir)
    await fs.rm(dir, { recursive: true })
  } catch {
    // do nothing
  }
}

function fetch (url) {
  return new Promise((resolve, reject) => {
    if (!QUIET) console.error('Fetching', url)
    https.get(url, function (res) {
      if (res.statusCode !== 200) return reject(new Error('Could not download ' + url + ' (' + res.statusCode + ')'))
      resolve(res)
    })
  })
}

function arg (name) {
  const i = process.argv.indexOf('--' + name)
  if (i === -1) return false
  if (process.argv.length <= i + 1 || process.argv[i + 1][0] === '-') return true
  return process.argv[i + 1]
}

function run (cmd, opts = {}) {
  return new Promise((resolve) => {
    const proc = child.spawn(cmd[0], cmd.slice(1), {
      cwd: opts.cwd || __dirname,
      stdio: [
        opts.stdin ? 'pipe' : 'ignore',
        QUIET ? 'ignore' : 2,
        QUIET ? 'ignore' : 2
      ],
      env: { MACOSX_DEPLOYMENT_TARGET, ...process.env }
    })

    if (opts.stdin) {
      opts.stdin.pipe(proc.stdin)
    }

    proc.on('exit', function (code) {
      if (code) process.exit(code)
      else resolve()
    })
  })
}
<|endoftext|>


<commit_before>import { React, useObserver, styled } from 'vendor';
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
import AsyncButton from 'shared/components/buttons/async-button';
import { Icon } from 'shared';
import { colors } from 'theme';
import SettingsIcon from '../../components/icons/settings';

const Bar = styled.div`
  display: flex;
  justify-content: space-between;
  padding: 1rem 2.4rem;
  border-top: 1px solid ${colors.neutral.pale};
  border-bottom: 1px solid ${colors.neutral.pale};
`;

const StyledSettingsIcon = styled(SettingsIcon)`
    border: 1px solid ${colors.neutral.pale};
    padding: 10px;
    margin-left: 20px;
`;

const QuestionWrapper = styled.button`
  border: 1px solid ${colors.neutral.pale};
  width: 6rem;
  height: 6rem;
  font-size: 1.2rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: ${colors.neutral.thin};
  background-color: ${({ current }) => current ? colors.neutral.light : 'white'};
  h6 {
    color: ${colors.link};
  }
  & + & {
    border-left: 0;
  }
`;

const QuestionsWrapper = styled.div`
  display: flex;

`;

const Controls = styled.div`
  display: flex;
  align-items: center;
  & .btn.btn-plain {
    border: 1px solid ${colors.neutral.pale};
    padding: 10px;
    margin-left: 20px;
    color: ${colors.neutral.grayblue}
  }
`;

const StyledPublishButton = styled(AsyncButton).attrs(props => ({
  disabled: props.isdisabled,
  variant: props.isdisabled ? 'plain' : 'primary',
}))`
  &&& {
    padding: 10px;
    pointer-events: none;
  }
`;

const Question = ({ heading, ux, index }) => useObserver(() => {
  const stats = heading.gradedStats;
  return (
    <QuestionWrapper current={ux.selectedHeadingIndex == index} onClick={() => ux.goToQuestionHeading(index)} data-test-id={`question-${index}`}>

{heading.title}

      {stats.complete ? <Icon type="check" color="green" /> : {heading.gradedProgress}}
    </QuestionWrapper>
  );
});

const QuestionsBar = ({ ux }) => useObserver(() => {
  return (
    <Bar data-test-id="questions-bar" className="questions-bar">
      <QuestionsWrapper>
        {ux.headings.map((heading, index) => <Question key={index} heading={heading} ux={ux} index={index} />)}
      </QuestionsWrapper>
      <Controls>
        <OverlayTrigger
          placement="top"
          delay={{ show: 250, hide: 400 }}
          overlay={
            <Tooltip>
              {!ux.hasUnpublishedScores || ux.planScores.isManualGradingGrade && 'All scores have already been published.'}
            </Tooltip>
          }
        >

        </OverlayTrigger>

        </OverlayTrigger>


<commit_before>var fs = require('fs')
var os = require('os')
var path = require('path')
var test = require('ava').test
var rimraf = require('rimraf')
var nodeginx = require('./nodeginx')

const TEMP_FOLDER = os.tmpdir()
const AVAILABLE = path.join(TEMP_FOLDER, nodeginx.constants.sitesAvailableStr)
const ENABLED = path.join(TEMP_FOLDER, nodeginx.constants.sitesEnabledStr)

// test objects
const staticSiteObj = {
  askAddSite: 'use static template',
  tplPort: '80',
  tplServerName: 'panda',
  tplSiteRoot: '/home/user/panda'
}

const proxySiteObj = {
  askAddSite: 'use proxy template',
  tplPort: '80',
  tplServerName: 'otter',
  proxyServerIp: '127.0.0.1',
  proxyServerPort: '8080'
}

// helpers
function fileExists (path, callback) {
  fs.stat(path, function (err) {
    return callback(!Boolean(err))
  })
}

function makefolder (folder) {
  return new Promise(function (resolve, reject) {
    fs.mkdir(folder, function(err) {
      if(err) return reject(err)
      resolve()
    })
  })
}

function deletefolder (folder) {
  return new Promise(function (resolve, reject) {
    rimraf(folder, function (err) {
      if (err) return reject(err)
      resolve()
    })
  })
}

// tests
test.before(async function (t) {
  await makefolder(AVAILABLE)
    .then(makefolder(ENABLED))
})

test.after.always( async function () {
  await deletefolder(AVAILABLE)
    .then(deletefolder(ENABLED))
})

test.cb('add static site', function (t) {
  nodeginx.addStaticSite(staticSiteObj, function(err, message) {
    if (err) t.end(err)
    fileExists(path.join(AVAILABLE, staticSiteObj.tplServerName),
      function (exists) {
        if (!exists) return t.end(new Error('Failed to add static site'))
        t.end()
      }
    )
  })
})

test.cb('enable a site', function (t) {
  nodeginx.enableSite(staticSiteObj.tplServerName, function (err) {
    if (err) return t.end(err)
    fs.lstat(path.join(ENABLED, staticSiteObj.tplServerName),
      function (err, stats) {
        if (err) return t.end(err)
        t.truthy(stats.isSymbolicLink(stats))
        t.end()
      }
    )
  })
})

test.cb('disable a site', function (t) {
  nodeginx.disableSite(staticSiteObj.tplServerName, function (err) {
    if (err) return t.end(err)
    fileExists(path.join(ENABLED, staticSiteObj.tplServerName),
      function (exists) {
        if (exists) return t.end(new Error('Failed to disable site'))
        t.end()
      }
    )
  })
})

test.cb('remove site', function (t) {
  nodeginx.removeSite(staticSiteObj.tplServerName, function (err) {
    if (err) return t.end(err)
    fileExists(path.join(AVAILABLE, staticSiteObj.tplServerName),
      function (exists) {
        if (exists) return t.end(new Error('Failed to remove static site'))
        t.end()
      }
    )
  })
})

test.cb('add proxy site', function (t) {
  nodeginx.addProxySite(proxySiteObj, function(err, message) {
    if (err) return t.end(err)
    fs.stat(path.join(AVAILABLE, proxySiteObj.tplServerName),
      function (err) {
        if (err) return t.end(err)
        t.end()
      }
    )
  })
})

test.cb(`make sure site is disabled before it's removed`, function (t) {
  nodeginx.enableSite(proxySiteObj.tplServerName, function (err) {
    if (err) return t.end('Failed to enable site befort test')
    nodeginx.removeSite(proxySiteObj.tplServerName, function (err) {
        if (err) return t.end(err)
        fileExists(path.join(ENABLED, proxySiteObj.tplServerName),
        function (exists) {
          if (exists) return t.end(new Error('Failed to remove proxy site'))
          t.end()
        }
      )
    })
  })
})

test.cb('test nodeginx.manageNginx("stop")', function (t) {
  nodeginx.manageNginx('stop', function (err) {
    require('child_process').exec('ps aux | grep nginx | grep "master process"',
      function (err, stdout, stderr) {
        var processIsRunning = stdout.trim().split('\n').length > 1
        if (err) return t.end(err)
        if(processIsRunning)
          return t.end(new Error('process should not be running'))
        t.end()
      }
    )
  })
})

test.cb('test nodeginx.manageNginx("start")', function (t) {
  nodeginx.manageNginx('start', function (err) {
    require('child_process').exec('ps aux | grep nginx | grep "master process"',
      function (err, stdout, stderr) {
        var processIsRunning = stdout.trim().split('\n').length > 1
        if (err) return t.end(err)
        if(!processIsRunning)
          return t.end(new Error('process should be running'))
        t.end()
      }
    )
  })
})

test.todo('add site from user template')
test.todo('use temp folder instead of /etc/nginx')
<commit_msg>add test for adding site from user config file<commit_after>var fs = require('fs')
var os = require('os')
var path = require('path')
var exec = require('child_process').exec
var rimraf = require('rimraf')
var test = require('ava').test
var nodeginx = require('./nodeginx')
const TEMP_FOLDER = os.tmpdir()
const AVAILABLE = path.join(TEMP_FOLDER, nodeginx.constants.sitesAvailableStr)
const ENABLED = path.join(TEMP_FOLDER, nodeginx.constants.sitesEnabledStr)

// test objects
const staticSiteObj = {
  askAddSite: 'use static template',
  tplPort: '80',
  tplServerName: 'panda',
  tplSiteRoot: '/home/user/panda'
}

const proxySiteObj = {
  askAddSite: 'use proxy template',
  tplPort: '80',
  tplServerName: 'otter',
  proxyServerIp: '127.0.0.1',
  proxyServerPort: '8080'
}

var userSiteTemplateObj = { askAddSiteConfig: path.join(TEMP_FOLDER, 'wombat') }

// helpers
function fileExists (path, callback) {
  fs.stat(path, function (err) {
    return callback(!Boolean(err))
  })
}

function makefolder (folder) {
  return new Promise(function (resolve, reject) {
    fs.mkdir(folder, function(err) {
      if(err) return reject(err)
      resolve()
    })
  })
}

function deletefolder (folder) {
  return new Promise(function (resolve, reject) {
    rimraf(folder, function (err) {
      if (err) return reject(err)
      resolve()
    })
  })
}

function makeUserSiteFile (filename) {
  return new Promise (function (resolve, reject) {
    fs.writeFile(filename, 'testfile', 'utf8', function (err) {
      if (err) return reject(err)
      resolve()
    })
  })
}

function deleteUserSiteFile (filename) {
  return new Promise (function (resolve, reject) {
    fs.unlink(filename, function (err) {
      if (err) return reject(err)
      resolve()
    })
  })
}

// tests
test.before(async function (t) {
  await makefolder(AVAILABLE)
    .then(makefolder(ENABLED))
    .then(makeUserSiteFile(userSiteTemplateObj.askAddSiteConfig))
})

test.after.always( async function () {
  await deletefolder(AVAILABLE)
    .then(deletefolder(ENABLED))
    .then(deleteUserSiteFile(userSiteTemplateObj.askAddSiteConfig))
})

test.cb('add static site', function (t) {
  nodeginx.addStaticSite(staticSiteObj, function(err, message) {
    if (err) t.end(err)
    fileExists(path.join(AVAILABLE, staticSiteObj.tplServerName),
      function (exists) {
        if (!exists) return t.end(new Error('Failed to add static site'))
        t.end()
      }
    )
  })
})

test.cb('enable a site', function (t) {
  nodeginx.enableSite(staticSiteObj.tplServerName, function (err) {
    if (err) return t.end(err)
    fs.lstat(path.join(ENABLED, staticSiteObj.tplServerName),
      function (err, stats) {
        if (err) return t.end(err)
        t.truthy(stats.isSymbolicLink(stats))
        t.end()
      }
    )
  })
})

test.cb('disable a site', function (t) {
  nodeginx.disableSite(staticSiteObj.tplServerName, function (err) {
    if (err) return t.end(err)
    fileExists(path.join(ENABLED, staticSiteObj.tplServerName),
      function (exists) {
        if (exists) return t.end(new Error('Failed to disable site'))
        t.end()
      }
    )
  })
})

test.cb('remove site', function (t) {
  nodeginx.removeSite(staticSiteObj.tplServerName, function (err) {
    if (err) return t.end(err)
    fileExists(path.join(AVAILABLE, staticSiteObj.tplServerName),
      function (exists) {
        if (exists) return t.end(new Error('Failed to remove static site'))
        t.end()
      }
    )
  })
})

test.cb('add proxy site', function (t) {
  nodeginx.addProxySite(proxySiteObj, function(err, message) {
    if (err) return t.end(err)
    fs.stat(path.join(AVAILABLE, proxySiteObj.tplServerName),
      function (err) {
        if (err) return t.end(err)
        t.end()
      }
    )
  })
})

test.cb(`make sure site is disabled before it's removed`, function (t) {
  nodeginx.enableSite(proxySiteObj.tplServerName, function (err) {
    if (err) return t.end('Failed to enable site befort test')
    nodeginx.removeSite(proxySiteObj.tplServerName, function (err) {
        if (err) return t.end(err)
        fileExists(path.join(ENABLED, proxySiteObj.tplServerName),
        function (exists) {
          if (exists) return t.end(new Error('Failed to remove proxy site'))
          t.end()
        }
      )
    })
  })
})

test.cb('test nodeginx.manageNginx("stop")', function (t) {
  nodeginx.manageNginx('stop', function (err) {
    exec('ps aux | grep nginx | grep "master process"',
      function (err, stdout, stderr) {
        var processIsRunning = stdout.trim().split('\n').length > 1
        if (err) return t.end(err)
        if(processIsRunning)
          return t.end(new Error('process should not be running'))
        t.end()
      }
    )
  })
})

test.cb('test nodeginx.manageNginx("start")', function (t) {
  nodeginx.manageNginx('start', function (err) {
    exec('ps aux | grep nginx | grep "master process"',
      function (err, stdout, stderr) {
        var processIsRunning = stdout.trim().split('\n').length > 1
        if (err) return t.end(err)
        if(!processIsRunning)
          return t.end(new Error('process should be running'))
        t.end()
      }
    )
  })
})

test.cb('add site from user config', function (t) {
  nodeginx.addSiteFromUserFile(userSiteTemplateObj, function (err) {
    if (err) return t.end(err)
    var filename = path.parse(userSiteTemplateObj.askAddSiteConfig).name
    fileExists(path.join(AVAILABLE, filename), function (exists) {
        if (!exists)
          return t.end(new Error('failed to create site from user config'))
        t.end()
      }
    )
  })
})
<|endoftext|>


<commit_before>'use strict';

const util = require('util');
const expect = require('expect.js');
const UserError = require('..');

describe('UserError', function() {

  it('should be exported', function() {
    expect(UserError).to.be.a('function');
  });

  describe('constructor', function() {

    it('should be an instance of UserError', function() {
      var err = new UserError();
      expect(err).to.be.a(UserError);
    });

    it('should be an instance of Error', function() {
      var err = new UserError();
      expect(err).to.be.an(Error);
    });

    it('should set name to "UserError"', function() {
      var err = new UserError();
      expect(err).to.have.property('name', 'UserError');
    });

    it('should set message to null if none is given', function() {
      var err = new UserError();
      expect(err).to.have.property('message', null);
    });

    it('should set message', function() {
      var err = new UserError('foo bar');
      expect(err).to.have.property('message', 'foo bar');
    });

    it('should set additional properties', function() {
      var err = new UserError(null, {foo: 'bar'});
      expect(err).to.have.property('foo', 'bar');
    });

    it('should accept properties as first argument', function() {
      var err = new UserError({foo: 'bar'});
      expect(err).to.have.property('message', null);
      expect(err).to.have.property('foo', 'bar');
    });

    it('should set name from properties', function() {
      var err = new UserError({name: 'FooError'});
      expect(err).to.have.property('name', 'FooError');
    });

    it('should set name from constructor', function() {
      function CustomError() {
        UserError.call(this);
      }
      util.inherits(CustomError, UserError);
      let err = new CustomError();
      expect(err).to.have.property('name', 'CustomError');
    });

    it('should set message from properties', function() {
      var err = new UserError({message: 'foo'});
      expect(err).to.have.property('message', 'foo');
    });

    it('should prefer explicit message over properties', function() {
      var err = new UserError('foo', {message: 'bar'});
      expect(err).to.have.property('message', 'foo');
    });

    it('should set stack', function() {
      var err = new UserError('foo');
      expect(err).to.have.property('stack');
      let stack = err.stack.split(/\n\s*/);
      expect(stack[0]).to.equal('UserError: foo');
      expect(stack[1]).to.contain('test/index.test.js');
    });

    it('should set stack from properties', function() {
      let stack = {};
      var err = new UserError({stack});
      expect(err).to.have.property('stack', stack);
    });

  });

  describe('toString()', function() {

    it('should return correctly formatted string for null message', function() {
      var err = new UserError();
      expect(err.toString()).to.equal('UserError: null');
    });

    it('should return correctly formatted string', function() {
      var err = new UserError('test');
      expect(err.toString()).to.equal('UserError: test');
    });

  });

});

<commit_msg>Replace var with let in index.test.js<commit_after>'use strict';

const util = require('util');
const expect = require('expect.js');
const UserError = require('..');

describe('UserError', function() {

  it('should be exported', function() {
    expect(UserError).to.be.a('function');
  });

  describe('constructor', function() {

    it('should be an instance of UserError', function() {
      let err = new UserError();
      expect(err).to.be.a(UserError);
    });

    it('should be an instance of Error', function() {
      let err = new UserError();
      expect(err).to.be.an(Error);
    });

    it('should set name to "UserError"', function() {
      let err = new UserError();
      expect(err).to.have.property('name', 'UserError');
    });

    it('should set message to null if none is given', function() {
      let err = new UserError();
      expect(err).to.have.property('message', null);
    });

    it('should set message', function() {
      let err = new UserError('foo bar');
      expect(err).to.have.property('message', 'foo bar');
    });

    it('should set additional properties', function() {
      let err = new UserError(null, {foo: 'bar'});
      expect(err).to.have.property('foo', 'bar');
    });

    it('should accept properties as first argument', function() {
      let err = new UserError({foo: 'bar'});
      expect(err).to.have.property('message', null);
      expect(err).to.have.property('foo', 'bar');
    });

    it('should set name from properties', function() {
      let err = new UserError({name: 'FooError'});
      expect(err).to.have.property('name', 'FooError');
    });

    it('should set name from constructor', function() {
      function CustomError() {
        UserError.call(this);
      }
      util.inherits(CustomError, UserError);
      let err = new CustomError();
      expect(err).to.have.property('name', 'CustomError');
    });

    it('should set message from properties', function() {
      let err = new UserError({message: 'foo'});
      expect(err).to.have.property('message', 'foo');
    });

    it('should prefer explicit message over properties', function() {
      let err = new UserError('foo', {message: 'bar'});
      expect(err).to.have.property('message', 'foo');
    });

    it('should set stack', function() {
      let err = new UserError('foo');
      expect(err).to.have.property('stack');
      let stack = err.stack.split(/\n\s*/);
      expect(stack[0]).to.equal('UserError: foo');
      expect(stack[1]).to.contain('test/index.test.js');
    });

    it('should set stack from properties', function() {
      let stack = {};
      let err = new UserError({stack});
      expect(err).to.have.property('stack', stack);
    });

  });

  describe('toString()', function() {

    it('should return correctly formatted string for null message', function() {
      let err = new UserError();
      expect(err.toString()).to.equal('UserError: null');
    });

    it('should return correctly formatted string', function() {
      let err = new UserError('test');
      expect(err.toString()).to.equal('UserError: test');
    });

  });

});

<|endoftext|>


<commit_before>/**
 * @author sunag / http://www.sunag.com.br/
 */

import { TempNode } from '../core/TempNode.js';
import { NodeLib } from '../core/NodeLib.js';

var vertexDict = [ 'uv', 'uv2' ],
	fragmentDict = [ 'vUv', 'vUv2' ];

function UVNode( index ) {

	TempNode.call( this, 'v2', { shared: false } );

	this.index = index || 0;

}

UVNode.prototype = Object.create( TempNode.prototype );
UVNode.prototype.constructor = UVNode;
UVNode.prototype.nodeType = "UV";

UVNode.prototype.generate = function ( builder, output ) {

	builder.requires.uv[ this.index ] = true;

	var result = builder.isShader( 'vertex' ) ? vertexDict[ this.index ] : fragmentDict[ this.index ];

	return builder.format( result, this.getType( builder ), output );

};

UVNode.prototype.copy = function ( source ) {

	TempNode.prototype.copy.call( this, source );

	this.index = source.index;

	return this;

};

UVNode.prototype.toJSON = function ( meta ) {

	var data = this.getJSONNode( meta );

	if ( ! data ) {

		data = this.createJSONNode( meta );

		data.index = this.index;

	}

	return data;

};

NodeLib.addKeyword( 'uv', function () {

	return new UVNode();

} );

NodeLib.addKeyword( 'uv2', function () {

	return new UVNode( 1 );

} );

export { UVNode };
<commit_msg>Updated to handle uv index greater than 1<commit_after>/**
 * @author sunag / http://www.sunag.com.br/
 */

import { TempNode } from '../core/TempNode.js';
import { NodeLib } from '../core/NodeLib.js';

function UVNode( index ) {

	TempNode.call( this, 'v2', { shared: false } );

	this.index = index || 0;

}

UVNode.prototype = Object.create( TempNode.prototype );
UVNode.prototype.constructor = UVNode;
UVNode.prototype.nodeType = "UV";

UVNode.prototype.generate = function ( builder, output ) {

	builder.requires.uv[ this.index ] = true;

	var uvIndex = this.index > 0 ? this.index + 1 : '';
	var result = builder.isShader( 'vertex' ) ? 'uv' + uvIndex : 'vUv' + uvIndex;

	return builder.format( result, this.getType( builder ), output );

};

UVNode.prototype.copy = function ( source ) {

	TempNode.prototype.copy.call( this, source );

	this.index = source.index;

	return this;

};

UVNode.prototype.toJSON = function ( meta ) {

	var data = this.getJSONNode( meta );

	if ( ! data ) {

		data = this.createJSONNode( meta );

		data.index = this.index;

	}

	return data;

};

NodeLib.addKeyword( 'uv', function () {

	return new UVNode();

} );

NodeLib.addKeyword( 'uv2', function () {

	return new UVNode( 1 );

} );

export { UVNode };
<|endoftext|>