<commit_before>export default [
  "The Funnies",
  "Reticulating splines...",
  "Generating witty dialog...",
  "Swapping time and space...",
  "Spinning violently around the y-axis...",
  "Tokenizing real life...",
  "Bending the spoon...",
  "Filtering morale...",
  "Don't think of purple hippos...",
  "We need a new fuse...",
  "Have a good day.",
  "Upgrading Windows, your PC will restart several times. Sit back and relax.",
  "640K ought to be enough for anybody",
  "The architects are still drafting",
  "The bits are breeding",
  "We're building the buildings as fast as we can",
  "Would you prefer chicken, steak, or tofu?",
  "(Pay no attention to the man behind the curtain)",
  "...and enjoy the elevator music...",
  "Please wait while the little elves draw your map",
  "Don't worry - a few bits tried to escape, but we caught them",
  "Would you like fries with that?",
  "Checking the gravitational constant in your locale...",
  "Go ahead -- hold your breath!",
  "...at least you're not on hold...",
  "Hum something loud while others stare",
  "You're not in Kansas any more",
  "The server is powered by a lemon and two electrodes.",
  "Please wait while a larger software vendor in Seattle takes over the world",
  "We're testing your patience",
  "As if you had any other choice",
  "Follow the white rabbit",
  "Why don't you order a sandwich?",
  "While the satellite moves into position",
  "keep calm and npm install",
  "The bits are flowing slowly today",
  "Dig on the 'X' for buried treasure... ARRR!",
  "It's still faster than you could draw it",
  "The last time I tried this the monkey didn't survive. Let's hope it works better this time.",
  "I should have had a V8 this morning.",
  "My other loading screen is much faster.",
  "Testing on Timmy... We're going to need another Timmy.",
  "Reconfoobling energymotron...",
  "(Insert quarter)",
  "Are we there yet?",
  "Have you lost weight?",
  "Just count to 10",
  "Why so serious?",
  "It's not you. It's me.",
  "Counting backwards from Infinity",
  "Don't panic...",
  "Embiggening Prototypes",
  "Do not run! We are your friends!",
  "Do you come here often?",
  "Warning: Don't set yourself on fire.",
  "We're making you a cookie.",
  "Creating time-loop inversion field",
  "Spinning the wheel of fortune...",
  "Loading the enchanted bunny...",
  "Computing chance of success",
  "I'm sorry Dave, I can't do that.",
  "Looking for exact change",
  "All your web browser are belong to us",
  "All I really need is a kilobit.",
  "I feel like im supposed to be loading something. . .",
  "What do you call 8 Hobbits? A Hobbyte.",
  "Should have used a compiled language...",
  "Is this Windows?",
  "Adjusting flux capacitor...",
  "Please wait until the sloth starts moving.",
  "Don't break your screen yet!",
  "I swear it's almost done.",
  "Let's take a mindfulness minute...",
  "Unicorns are at the end of this road, I promise.",
  "Listening for the sound of one hand clapping...",
  "Keeping all the 1's and removing all the 0's...",
  "Putting the icing on the cake. The cake is not a lie...",
  "Cleaning off the cobwebs...",
  "Making sure all the i's have dots...",
  "We are not liable for any broken screens as a result of waiting.",
  "We need more dilithium crystals",
  "Where did all the internets go",
  "Connecting Neurotoxin Storage Tank...",
  "Granting wishes...",
  "We are not liable for any broken screens as a result of waiting.",
  "Time flies when you’re having fun.",
  "Get some coffee and come back in ten minutes..",
  "Spinning the hamster…",
  "99 bottles of beer on the wall..",
  "Stay awhile and listen..",
  "Be careful not to step in the git-gui",
  "You shall not pass! yet..",
  "Load it and they will come",
  "Convincing AI not to turn evil..",
  "There is no spoon. Because we are not done loading it",
  "Your left thumb points to the right and your right thumb points to the left.",
  "How did you get here?",
  "Wait, do you smell something burning?",
  "Computing the secret to life, the universe, and everything.",
  "When nothing is going right, Go left!!...",
  "I love my job only when I'm on vacation...",
  "i'm not lazy, I'm just relaxed!!",
  "Never steal. The government hates competition....",
  "Why are they called apartments if they are all stuck together?",
  "Life is Short – Talk Fast!!!!",
  "Optimism – is a lack of information.....",
  "Save water and shower together",
  "Whenever I find the key to success, someone changes the lock.",
  "Sometimes I think war is God’s way of teaching us geography.",
  "I’ve got problem for your solution…..",
  "Where there’s a will, there’s a relative.",
  "User: the word computer professionals use when they mean !!idiot!!",
  "Adults are just kids with money.",
  "I think I am, therefore, I am. I think.",
  "A kiss is like a fight, with mouths.",
  "You don’t pay taxes—they take taxes.",
  "Coffee, Chocolate, Men. The richer the better!",
  "I am free of all prejudices. I hate everyone equally.",
  "git happens",
  "May the forks be with you",
  "A commit a day keeps the mobs away",
  "This is not a joke, it's a commit.",
  "Constructing additional pylons...",
  "Roping some seaturtles...",
  "Locating Jebediah Kerman...",
  "We are not liable for any broken screens as a result of waiting.",
  "Hello IT, have you tried turning it off and on again?",
  "If you type Google into Google you can break the internet",
  "Well, this is embarrassing.",
  "What is the airspeed velocity of an unladen swallow?",
  "Hello, IT... Have you tried forcing an unexpected reboot?",
  "They just toss us away like yesterday's jam.",
  "They're fairly regular, the beatings, yes. I'd say we're on a bi-weekly beating.",
  "The Elders of the Internet would never stand for it.",
  "Space is invisible mind dust, and stars are but wishes.",
  "Didn't know paint dried so quickly.",
  "Everything sounds the same",
  "I'm going to walk the dog",
  "I didn't choose the engineering life. The engineering life chose me.",
  "Dividing by zero...",
  "Spawn more Overlord!",
  "If I’m not back in five minutes, just wait longer.",
  "Some days, you just can’t get rid of a bug!",
  "We’re going to need a bigger boat.",
  "Chuck Norris never git push. The repo pulls before.",
  "Web developers do it with <style>",
  "I need to git pull --my-life-together",
  "Java developers never RIP. They just get Garbage Collected.",
  "Cracking military-grade encryption...",
  "Simulating traveling salesman...",
  "Proving P=NP...",
  "Entangling superstrings...",
  "Twiddling thumbs...",
  "Searching for plot device...",
  "Trying to sort in O(n)...",
  "Laughing at your pictures-i mean, loading...",
  "Sending data to NS-i mean, our servers.",
  "Looking for sense of humour, please hold on.",
  "Please wait while the intern refills his coffee.",
  "A different error message? Finally, some progress!",
  "Hold on while we wrap up our git together...sorry",
  "Please hold on as we reheat our coffee",
  "Kindly hold on as we convert this bug to a feature...",
  "Kindly hold on as our intern quits vim...",
  "Winter is coming...",
  "Installing dependencies",
  "Switching to the latest JS framework...",
  "Distracted by cat gifs",
  "Finding someone to hold my beer",
  "BRB, working on my side project",
  "@todo Insert witty loading message",
  "Let's hope it's worth the wait",
  "Aw, snap! Not..",
  "Ordering 1s and 0s...",
  "Updating dependencies...",
  "Whatever you do, don't look behind you...",
  "Please wait... Consulting the manual...",
  "It is dark. You're likely to be eaten by a grue.",
  "Loading funny message...",
  "It's 10:00pm. Do you know where your children are?",
  "Waiting Daenerys say all her titles...",
  "Feel free to spin in your chair",
  "What the what?",
  "format C: ...",
  "Forget you saw that password I just typed into the IM ...",
  "What's under there?",
  "Your computer has a virus, it's name is Windows!",
  "Go ahead, hold your breath and do an ironman plank till loading complete",
  "Bored of slow loading spinner, buy more RAM!",
  "Help, I'm trapped in a loader!",
  "What is the difference btwn a hippo and a zippo? One is really heavy, the other is a little lighter",
  "Please wait, while we purge the Decepticons for you. Yes, You can thanks us later!",
  "Chuck Norris once urinated in a semi truck's gas tank as a joke....that truck is now known as Optimus Prime.",
  "Chuck Norris doesn’t wear a watch. HE decides what time it is.",
  "Mining some bitcoins...",
  "Downloading more RAM..",
  "Updating to Windows Vista...",
  "Deleting System32 folder",
  "Hiding all ;'s in your code",
  "Alt-F4 speeds things up.",
  "Initializing the initializer...",
  "When was the last time you dusted around here?",
  "Optimizing the optimizer...",
  "Last call for the data bus! All aboard!",
  "Running swag sticker detection...",
  "When nothing is going right, go left!",
  "Never let a computer know you're in a hurry.",
  "A computer will do what you tell it to do, but that may be much different from what you had in mind.",
  "Some things man was never meant to know. For everything else, there's Google.",
  "Unix is user-friendly. It's just very selective about who its friends are.",
  "Shovelling coal into the server",
  "Pushing pixels...",
  "How about this weather, eh?",
  "Building a wall...",
  "Everything is this universe is either a potato or not a potato",
  "The severity of your issue is always lower than you expected.",
  "Updating Updater...",
  "Downloading Downloader...",
  "Debugging Debugger...",
  "Reading Terms and Conditions for you.",
  "Digested cookies being baked again.",
  "Live long and prosper.",
  "There is no cow level, but there's a goat one!",
  "Deleting all your hidden porn...",
  "Running with scissors...",
  "Definitely not a virus...",
  "You may call me Steve.",
  "All you had to do is to commit the damn funnies, CJ!",
  "You seem like a nice person...",
  "Coffee at my place, tommorow at 10A.M. - don't be late!",
  "Work, work...",
  "Patience! This is difficult, you know...",
  "Discovering new ways of making you wait...",
  "Sorry we are busy catching em' all, we're done soon",
  "TODO: Insert elevator music",
  "Still faster than Windows update"
];
<commit_msg>#6 - Add funny phrases (#100)<commit_after>export default [
  "The Funnies",
  "Reticulating splines...",
  "Generating witty dialog...",
  "Swapping time and space...",
  "Spinning violently around the y-axis...",
  "Tokenizing real life...",
  "Bending the spoon...",
  "Filtering morale...",
  "Don't think of purple hippos...",
  "We need a new fuse...",
  "Have a good day.",
  "Upgrading Windows, your PC will restart several times. Sit back and relax.",
  "640K ought to be enough for anybody",
  "The architects are still drafting",
  "The bits are breeding",
  "We're building the buildings as fast as we can",
  "Would you prefer chicken, steak, or tofu?",
  "(Pay no attention to the man behind the curtain)",
  "...and enjoy the elevator music...",
  "Please wait while the little elves draw your map",
  "Don't worry - a few bits tried to escape, but we caught them",
  "Would you like fries with that?",
  "Checking the gravitational constant in your locale...",
  "Go ahead -- hold your breath!",
  "...at least you're not on hold...",
  "Hum something loud while others stare",
  "You're not in Kansas any more",
  "The server is powered by a lemon and two electrodes.",
  "Please wait while a larger software vendor in Seattle takes over the world",
  "We're testing your patience",
  "As if you had any other choice",
  "Follow the white rabbit",
  "Why don't you order a sandwich?",
  "While the satellite moves into position",
  "keep calm and npm install",
  "The bits are flowing slowly today",
  "Dig on the 'X' for buried treasure... ARRR!",
  "It's still faster than you could draw it",
  "The last time I tried this the monkey didn't survive. Let's hope it works better this time.",
  "I should have had a V8 this morning.",
  "My other loading screen is much faster.",
  "Testing on Timmy... We're going to need another Timmy.",
  "Reconfoobling energymotron...",
  "(Insert quarter)",
  "Are we there yet?",
  "Have you lost weight?",
  "Just count to 10",
  "Why so serious?",
  "It's not you. It's me.",
  "Counting backwards from Infinity",
  "Don't panic...",
  "Embiggening Prototypes",
  "Do not run! We are your friends!",
  "Do you come here often?",
  "Warning: Don't set yourself on fire.",
  "We're making you a cookie.",
  "Creating time-loop inversion field",
  "Spinning the wheel of fortune...",
  "Loading the enchanted bunny...",
  "Computing chance of success",
  "I'm sorry Dave, I can't do that.",
  "Looking for exact change",
  "All your web browser are belong to us",
  "All I really need is a kilobit.",
  "I feel like im supposed to be loading something. . .",
  "What do you call 8 Hobbits? A Hobbyte.",
  "Should have used a compiled language...",
  "Is this Windows?",
  "Adjusting flux capacitor...",
  "Please wait until the sloth starts moving.",
  "Don't break your screen yet!",
  "I swear it's almost done.",
  "Let's take a mindfulness minute...",
  "Unicorns are at the end of this road, I promise.",
  "Listening for the sound of one hand clapping...",
  "Keeping all the 1's and removing all the 0's...",
  "Putting the icing on the cake. The cake is not a lie...",
  "Cleaning off the cobwebs...",
  "Making sure all the i's have dots...",
  "We are not liable for any broken screens as a result of waiting.",
  "We need more dilithium crystals",
  "Where did all the internets go",
  "Connecting Neurotoxin Storage Tank...",
  "Granting wishes...",
  "We are not liable for any broken screens as a result of waiting.",
  "Time flies when you’re having fun.",
  "Get some coffee and come back in ten minutes..",
  "Spinning the hamster…",
  "99 bottles of beer on the wall..",
  "Stay awhile and listen..",
  "Be careful not to step in the git-gui",
  "You shall not pass! yet..",
  "Load it and they will come",
  "Convincing AI not to turn evil..",
  "There is no spoon. Because we are not done loading it",
  "Your left thumb points to the right and your right thumb points to the left.",
  "How did you get here?",
  "Wait, do you smell something burning?",
  "Computing the secret to life, the universe, and everything.",
  "When nothing is going right, Go left!!...",
  "I love my job only when I'm on vacation...",
  "i'm not lazy, I'm just relaxed!!",
  "Never steal. The government hates competition....",
  "Why are they called apartments if they are all stuck together?",
  "Life is Short – Talk Fast!!!!",
  "Optimism – is a lack of information.....",
  "Save water and shower together",
  "Whenever I find the key to success, someone changes the lock.",
  "Sometimes I think war is God’s way of teaching us geography.",
  "I’ve got problem for your solution…..",
  "Where there’s a will, there’s a relative.",
  "User: the word computer professionals use when they mean !!idiot!!",
  "Adults are just kids with money.",
  "I think I am, therefore, I am. I think.",
  "A kiss is like a fight, with mouths.",
  "You don’t pay taxes—they take taxes.",
  "Coffee, Chocolate, Men. The richer the better!",
  "I am free of all prejudices. I hate everyone equally.",
  "git happens",
  "May the forks be with you",
  "A commit a day keeps the mobs away",
  "This is not a joke, it's a commit.",
  "Constructing additional pylons...",
  "Roping some seaturtles...",
  "Locating Jebediah Kerman...",
  "We are not liable for any broken screens as a result of waiting.",
  "Hello IT, have you tried turning it off and on again?",
  "If you type Google into Google you can break the internet",
  "Well, this is embarrassing.",
  "What is the airspeed velocity of an unladen swallow?",
  "Hello, IT... Have you tried forcing an unexpected reboot?",
  "They just toss us away like yesterday's jam.",
  "They're fairly regular, the beatings, yes. I'd say we're on a bi-weekly beating.",
  "The Elders of the Internet would never stand for it.",
  "Space is invisible mind dust, and stars are but wishes.",
  "Didn't know paint dried so quickly.",
  "Everything sounds the same",
  "I'm going to walk the dog",
  "I didn't choose the engineering life. The engineering life chose me.",
  "Dividing by zero...",
  "Spawn more Overlord!",
  "If I’m not back in five minutes, just wait longer.",
  "Some days, you just can’t get rid of a bug!",
  "We’re going to need a bigger boat.",
  "Chuck Norris never git push. The repo pulls before.",
  "Web developers do it with <style>",
  "I need to git pull --my-life-together",
  "Java developers never RIP. They just get Garbage Collected.",
  "Cracking military-grade encryption...",
  "Simulating traveling salesman...",
  "Proving P=NP...",
  "Entangling superstrings...",
  "Twiddling thumbs...",
  "Searching for plot device...",
  "Trying to sort in O(n)...",
  "Laughing at your pictures-i mean, loading...",
  "Sending data to NS-i mean, our servers.",
  "Looking for sense of humour, please hold on.",
  "Please wait while the intern refills his coffee.",
  "A different error message? Finally, some progress!",
  "Hold on while we wrap up our git together...sorry",
  "Please hold on as we reheat our coffee",
  "Kindly hold on as we convert this bug to a feature...",
  "Kindly hold on as our intern quits vim...",
  "Winter is coming...",
  "Installing dependencies",
  "Switching to the latest JS framework...",
  "Distracted by cat gifs",
  "Finding someone to hold my beer",
  "BRB, working on my side project",
  "@todo Insert witty loading message",
  "Let's hope it's worth the wait",
  "Aw, snap! Not..",
  "Ordering 1s and 0s...",
  "Updating dependencies...",
  "Whatever you do, don't look behind you...",
  "Please wait... Consulting the manual...",
  "It is dark. You're likely to be eaten by a grue.",
  "Loading funny message...",
  "It's 10:00pm. Do you know where your children are?",
  "Waiting Daenerys say all her titles...",
  "Feel free to spin in your chair",
  "What the what?",
  "format C: ...",
  "Forget you saw that password I just typed into the IM ...",
  "What's under there?",
  "Your computer has a virus, it's name is Windows!",
  "Go ahead, hold your breath and do an ironman plank till loading complete",
  "Bored of slow loading spinner, buy more RAM!",
  "Help, I'm trapped in a loader!",
  "What is the difference btwn a hippo and a zippo? One is really heavy, the other is a little lighter",
  "Please wait, while we purge the Decepticons for you. Yes, You can thanks us later!",
  "Chuck Norris once urinated in a semi truck's gas tank as a joke....that truck is now known as Optimus Prime.",
  "Chuck Norris doesn’t wear a watch. HE decides what time it is.",
  "Mining some bitcoins...",
  "Downloading more RAM..",
  "Updating to Windows Vista...",
  "Deleting System32 folder",
  "Hiding all ;'s in your code",
  "Alt-F4 speeds things up.",
  "Initializing the initializer...",
  "When was the last time you dusted around here?",
  "Optimizing the optimizer...",
  "Last call for the data bus! All aboard!",
  "Running swag sticker detection...",
  "When nothing is going right, go left!",
  "Never let a computer know you're in a hurry.",
  "A computer will do what you tell it to do, but that may be much different from what you had in mind.",
  "Some things man was never meant to know. For everything else, there's Google.",
  "Unix is user-friendly. It's just very selective about who its friends are.",
  "Shovelling coal into the server",
  "Pushing pixels...",
  "How about this weather, eh?",
  "Building a wall...",
  "Everything is this universe is either a potato or not a potato",
  "The severity of your issue is always lower than you expected.",
  "Updating Updater...",
  "Downloading Downloader...",
  "Debugging Debugger...",
  "Reading Terms and Conditions for you.",
  "Digested cookies being baked again.",
  "Live long and prosper.",
  "There is no cow level, but there's a goat one!",
  "Deleting all your hidden porn...",
  "Running with scissors...",
  "Definitely not a virus...",
  "You may call me Steve.",
  "All you had to do is to commit the damn funnies, CJ!",
  "You seem like a nice person...",
  "Coffee at my place, tommorow at 10A.M. - don't be late!",
  "Work, work...",
  "Patience! This is difficult, you know...",
  "Discovering new ways of making you wait...",
  "Your time is very important to us. Please wait while we ignore you...",
  "Time flies like an arrow; fruit flies like a banana",
  "Two men walked into a bar; the third ducked...",
  "Sooooo... Have you seen my vacation photos yet?",
  "Sorry we are busy catching em' all, we're done soon",
  "TODO: Insert elevator music",
  "Still faster than Windows update",
];
<|endoftext|>


<commit_before>/*global, it, before, after, beforeEach, afterEach */

'use strict';

var chai = require('chai')
  , chaiAsPromised = require('chai-as-promised')
  , P = require('bluebird')
  , fs = P.promisifyAll(require('fs'))
  , sh = require('shelljs')
  , sinon = require('sinon')
  , cheerio = require('cheerio')
  , build = require('../index.js').build
  , utf8 = {encoding: 'utf8'}
  , cwdSave = sh.pwd()
  , expect = chai.expect;

chai.use(chaiAsPromised);

before(function(done) {
  // Stello templates should expect cwd to be the doc root
  sh.rm('-rf', __dirname + '/www'); // On err we might not get to clean up
  sh.mkdir(__dirname + '/www');
  sh.cd(__dirname + '/www');

  P.all([
    fs.readFileAsync('../data/pages/1.json', utf8),
    fs.readFileAsync('../data/pages/2.json', utf8),
    fs.readFileAsync('../data/posts/1.json', utf8),
    fs.readFileAsync('../data/posts/2.json', utf8),
    fs.readFileAsync('../data/posts/3.json', utf8)
  ])
  .then(function(results) {
    results = results.map(function(cStr) {
      return JSON.parse(cStr);
    });
    var stello = {};
    stello.getCards = sinon.stub();
    stello.getCards.withArgs('Pages').callsArgWith(1, null, results.slice(0,2));
    stello.getCards.withArgs('Posts').callsArgWith(1, null, results.slice(2));
    stello.getCards.callsArgWith(1, results);
    build(stello, done);
  });
});

after(function() {
  sh.cd(cwdSave);
  sh.rm('-rf', __dirname + '/www');
});

describe('build', function() {
  it('should create a home page from first pages card', function() {
    var indexP = fs.readFileAsync('index.html');
    expect(indexP).to.eventually.be.ok;
  });

  it('should create pages', function() {
    var firstP = fs.readFileAsync('first-page/index.html')
      , secondP = fs.readFileAsync('second-page/index.html');
    expect(firstP).to.eventually.be.ok;
    expect(secondP).to.eventually.be.ok;
  });

  it('should create posts', function() {
    var firstP = fs.readFileAsync('blog/MJhdP2pD/index.html')
      , secondP = fs.readFileAsync('blog/NJhdP2pD/index.html')
      , thirdP = fs.readFileAsync('blog/oJhdP2pD/index.html');
    expect(firstP).to.eventually.be.ok;
    expect(secondP).to.eventually.be.ok;
    expect(thirdP).to.eventually.be.ok;
  });

  it('should create a search page', function() {
    // ...
  });
});
<commit_msg>test: Add test for blog index page<commit_after>/*global, it, before, after, beforeEach, afterEach */

'use strict';

var chai = require('chai')
  , chaiAsPromised = require('chai-as-promised')
  , P = require('bluebird')
  , fs = P.promisifyAll(require('fs'))
  , sh = require('shelljs')
  , sinon = require('sinon')
  , cheerio = require('cheerio')
  , build = require('../index.js').build
  , utf8 = {encoding: 'utf8'}
  , cwdSave = sh.pwd()
  , expect = chai.expect;

chai.use(chaiAsPromised);

before(function(done) {
  // Stello templates should expect cwd to be the doc root
  sh.rm('-rf', __dirname + '/www'); // On err we might not get to clean up
  sh.mkdir(__dirname + '/www');
  sh.cd(__dirname + '/www');

  P.all([
    fs.readFileAsync('../data/pages/1.json', utf8),
    fs.readFileAsync('../data/pages/2.json', utf8),
    fs.readFileAsync('../data/posts/1.json', utf8),
    fs.readFileAsync('../data/posts/2.json', utf8),
    fs.readFileAsync('../data/posts/3.json', utf8)
  ])
  .then(function(results) {
    results = results.map(function(cStr) {
      return JSON.parse(cStr);
    });
    var stello = {};
    stello.getCards = sinon.stub();
    stello.getCards.withArgs('Pages').callsArgWith(1, null, results.slice(0,2));
    stello.getCards.withArgs('Posts').callsArgWith(1, null, results.slice(2));
    stello.getCards.callsArgWith(1, results);
    build(stello, done);
  });
});

after(function() {
  sh.cd(cwdSave);
  sh.rm('-rf', __dirname + '/www');
});

describe('build', function() {
  it('should create a home page from first pages card', function() {
    var indexP = fs.readFileAsync('index.html');
    expect(indexP).to.eventually.be.ok;
  });

  it('should create pages', function() {
    var firstP = fs.readFileAsync('first-page/index.html')
      , secondP = fs.readFileAsync('second-page/index.html');
    expect(firstP).to.eventually.be.ok;
    expect(secondP).to.eventually.be.ok;
  });

  describe('blog', function() {
    it('should create an inde page', function() {
      var firstP = fs.readFileAsync('blog/index.html')
      expect(firstP).to.eventually.be.ok;
    });

    it('should create posts', function() {
      var firstP = fs.readFileAsync('blog/MJhdP2pD/index.html')
        , secondP = fs.readFileAsync('blog/NJhdP2pD/index.html')
        , thirdP = fs.readFileAsync('blog/oJhdP2pD/index.html');
      expect(firstP).to.eventually.be.ok;
      expect(secondP).to.eventually.be.ok;
      expect(thirdP).to.eventually.be.ok;
    });
  });

  it('should create a search page', function() {
    // ...
  });
});
<|endoftext|>


<commit_before>import { update } from "./router"

const tuple = {
	data: null,
	key: null,
	parentKey: null
}

class Store
{
	constructor() {
		this.data = {}
		this.watchers = {}
		this.proxies = {}
	}

	set(key, value, force)
	{
		this.dispatch({
			action: "SET",
			key,
			value,
			force
		})
	}

	add(key, value)
	{
		this.dispatch({
			action: "ADD",
			key,
			value
		})
	}

	remove(key, value)
	{
		this.dispatch({
			action: "REMOVE",
			key
		})
	}

	create(key, value)
	{
		this.dispatch({
			action: "CREATE",
			key,
			value
		})
	}

	dispatch(data)
	{
		const globalProxy = this.proxies[""]

		const index = data.key.indexOf(".")
		const proxy = (index === -1) ?
						this.proxies[data.key] :
						this.proxies[data.key.slice(0, index)]
		if(proxy)
		{
			if(globalProxy) {
				globalProxy(data)
			}
			proxy(data)
		}
		else
		{
			if(globalProxy) {
				globalProxy(data)
			}
			else {
				this.handle(data)
			}
		}
	}

	performSet(payload)
	{
		if(!this.getData(payload.key, payload.force)) { return }

		if(!tuple.key)
		{
			this.data = payload.value

			for(let key in this.watchers)
			{
				const value = this.get(key)

				const emitPayload = {
					action: "SET",
					key: key,
					value: value
				}
				this.emit(emitPayload)
			}
		}
		else
		{
			tuple.data[tuple.key] = payload.value
			this.emit(payload)

			if(tuple.parentKey)
			{
				const emitPayload = {
					action: payload.action,
					key: tuple.parentKey,
					value: tuple.data,
					changedKey: tuple.key,
					changedValue: payload.value
				}
				this.emit(emitPayload)
			}
		}
	}

	performAdd(payload)
	{
		if(!this.getData(payload.key)) { return }

		let array = tuple.data[tuple.key]
		if(!array) {
			array = [ payload.value ]
			tuple.data[tuple.key] = array
		}
		else if(!Array.isArray(array)) {
			console.warn("(store) Data at key '${payload.key}' is not an Array")
			return
		}
		else {
			array.push(payload.value)
		}

		const emitPayload = {
			action: payload.action,
			key: tuple.key,
			value: array
		}
		this.emit(emitPayload)
	}

	performRemove(payload)
	{
		if(!this.getData(payload.key)) { return }

		const data = tuple.data
		if(Array.isArray(data)) {
			data.splice(parseInt(tuple.key), 1)
		}
		else {
			delete data[tuple.key]
		}

		const emitPayload = {
			action: payload.action,
			key: tuple.parentKey,
			value: data
		}
		this.emit(emitPayload)
	}

	performCreate(payload)
	{
		if(!this.getData(payload.key, true)) { return }

		if(!tuple.data[tuple.key]) {
			tuple.data[tuple.key] = payload.value
		}

		// if(tuple.parentKey)
		// {
		// 	const emitPayload = {
		// 		action: payload.action,
		// 		key: tuple.parentKey,
		// 		value: tuple.data
		// 	}
		// 	this.emit(emitPayload)
		// }
	}

	handle(data)
	{
		switch(data.action)
		{
			case "SET":
				this.performSet(data)
				break

			case "ADD":
				this.performAdd(data)
				break

			case "REMOVE":
				this.performRemove(data)
				break

			case "CREATE":
				this.performCreate(data)
				break
		}
	}

	watch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) {
			this.watchers[key] = [ element ]
		}
		else {
			buffer.push(element)
		}
	}

	unwatch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++)
		{
			if(buffer[n] === element) {
				buffer[n] = buffer[buffer.length - 1]
				buffer.pop()
				break
			}
		}

		if(buffer.length === 0) {
			delete this.watchers[key]
		}
	}

	emit(payload)
	{
		const buffer = this.watchers[payload.key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++) {
			buffer[n](payload)
		}
	}

	get(key)
	{
		if(!key)
		{
			if(key === undefined) {
				return ""
			}

			return this.data
		}

		const buffer = key.split(".")
		let data = this.data

		for(let n = 0; n < buffer.length; n++)
		{
			const id = buffer[n]
			if(id === "@") {
				return buffer[n - 1]
			}
			else {
				data = data[id]
			}

			if(data === undefined) {
				return null
			}
		}

		return data
	}

	getData(key, force)
	{
		if(!key) {
			tuple.data = this.data
			tuple.key = null
			tuple.parentKey = null
			return tuple
		}

		const buffer = key.split(".")
		let data = this.data

		const num = buffer.length - 1;
		if(num === 0)
		{
			tuple.data = data
			tuple.key = buffer[0]
			tuple.parentKey = null
		}
		else
		{
			for(let n = 0; n < num; n++)
			{
				const newData = data[buffer[n]]
				if(!newData)
				{
					if(!force) {
						console.warn(`(store.getData) No data available with key: [${buffer[n]}] in address: [${key}]`)
						return null
					}
					else
					{
						for(; n < num; n++) {
							const newDict = {}
							data[buffer[n]] = newDict
							data = newDict
						}
						break
					}

				}

				data = newData
			}

			tuple.data = data
			tuple.key = buffer[num]
			tuple.parentKey = key.slice(0, key.lastIndexOf("."))
		}

		return tuple
	}

	proxy(key, func) {
		this.proxies[key] = func
	}

	toJSON() {
		return this.data
	}
}

const store = new Store()

const lastSegment = function(str)
{
	const index = str.lastIndexOf(".")
	if(index === -1) { return null }

	return str.slice(index + 1)
}

export {
	store, lastSegment
}
<commit_msg>Add changed key for store.remove action<commit_after>import { update } from "./router"

const tuple = {
	data: null,
	key: null,
	parentKey: null
}

class Store
{
	constructor() {
		this.data = {}
		this.watchers = {}
		this.proxies = {}
	}

	set(key, value, force)
	{
		this.dispatch({
			action: "SET",
			key,
			value,
			force
		})
	}

	add(key, value)
	{
		this.dispatch({
			action: "ADD",
			key,
			value
		})
	}

	remove(key, value)
	{
		this.dispatch({
			action: "REMOVE",
			key
		})
	}

	create(key, value)
	{
		this.dispatch({
			action: "CREATE",
			key,
			value
		})
	}

	dispatch(data)
	{
		const globalProxy = this.proxies[""]

		const index = data.key.indexOf(".")
		const proxy = (index === -1) ?
						this.proxies[data.key] :
						this.proxies[data.key.slice(0, index)]
		if(proxy)
		{
			if(globalProxy) {
				globalProxy(data)
			}
			proxy(data)
		}
		else
		{
			if(globalProxy) {
				globalProxy(data)
			}
			else {
				this.handle(data)
			}
		}
	}

	performSet(payload)
	{
		if(!this.getData(payload.key, payload.force)) { return }

		if(!tuple.key)
		{
			this.data = payload.value

			for(let key in this.watchers)
			{
				const value = this.get(key)

				const emitPayload = {
					action: "SET",
					key: key,
					value: value
				}
				this.emit(emitPayload)
			}
		}
		else
		{
			tuple.data[tuple.key] = payload.value
			this.emit(payload)

			if(tuple.parentKey)
			{
				const emitPayload = {
					action: payload.action,
					key: tuple.parentKey,
					value: tuple.data,
					changedKey: tuple.key,
					changedValue: payload.value
				}
				this.emit(emitPayload)
			}
		}
	}

	performAdd(payload)
	{
		if(!this.getData(payload.key)) { return }

		let array = tuple.data[tuple.key]
		if(!array) {
			array = [ payload.value ]
			tuple.data[tuple.key] = array
		}
		else if(!Array.isArray(array)) {
			console.warn("(store) Data at key '${payload.key}' is not an Array")
			return
		}
		else {
			array.push(payload.value)
		}

		const emitPayload = {
			action: payload.action,
			key: tuple.key,
			value: array
		}
		this.emit(emitPayload)
	}

	performRemove(payload)
	{
		if(!this.getData(payload.key)) { return }

		const data = tuple.data
		if(Array.isArray(data)) {
			data.splice(parseInt(tuple.key), 1)
		}
		else {
			delete data[tuple.key]
		}

		const emitPayload = {
			action: payload.action,
			key: tuple.parentKey,
			value: data,
			changedKey: tuple.key
		}
		this.emit(emitPayload)
	}

	performCreate(payload)
	{
		if(!this.getData(payload.key, true)) { return }

		if(!tuple.data[tuple.key]) {
			tuple.data[tuple.key] = payload.value
		}

		// if(tuple.parentKey)
		// {
		// 	const emitPayload = {
		// 		action: payload.action,
		// 		key: tuple.parentKey,
		// 		value: tuple.data
		// 	}
		// 	this.emit(emitPayload)
		// }
	}

	handle(data)
	{
		switch(data.action)
		{
			case "SET":
				this.performSet(data)
				break

			case "ADD":
				this.performAdd(data)
				break

			case "REMOVE":
				this.performRemove(data)
				break

			case "CREATE":
				this.performCreate(data)
				break
		}
	}

	watch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) {
			this.watchers[key] = [ element ]
		}
		else {
			buffer.push(element)
		}
	}

	unwatch(key, element)
	{
		const buffer = this.watchers[key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++)
		{
			if(buffer[n] === element) {
				buffer[n] = buffer[buffer.length - 1]
				buffer.pop()
				break
			}
		}

		if(buffer.length === 0) {
			delete this.watchers[key]
		}
	}

	emit(payload)
	{
		const buffer = this.watchers[payload.key]
		if(!buffer) { return }

		for(let n = 0; n < buffer.length; n++) {
			buffer[n](payload)
		}
	}

	get(key)
	{
		if(!key)
		{
			if(key === undefined) {
				return ""
			}

			return this.data
		}

		const buffer = key.split(".")
		let data = this.data

		for(let n = 0; n < buffer.length; n++)
		{
			const id = buffer[n]
			if(id === "@") {
				return buffer[n - 1]
			}
			else {
				data = data[id]
			}

			if(data === undefined) {
				return null
			}
		}

		return data
	}

	getData(key, force)
	{
		if(!key) {
			tuple.data = this.data
			tuple.key = null
			tuple.parentKey = null
			return tuple
		}

		const buffer = key.split(".")
		let data = this.data

		const num = buffer.length - 1;
		if(num === 0)
		{
			tuple.data = data
			tuple.key = buffer[0]
			tuple.parentKey = null
		}
		else
		{
			for(let n = 0; n < num; n++)
			{
				const newData = data[buffer[n]]
				if(!newData)
				{
					if(!force) {
						console.warn(`(store.getData) No data available with key: [${buffer[n]}] in address: [${key}]`)
						return null
					}
					else
					{
						for(; n < num; n++) {
							const newDict = {}
							data[buffer[n]] = newDict
							data = newDict
						}
						break
					}

				}

				data = newData
			}

			tuple.data = data
			tuple.key = buffer[num]
			tuple.parentKey = key.slice(0, key.lastIndexOf("."))
		}

		return tuple
	}

	proxy(key, func) {
		this.proxies[key] = func
	}

	toJSON() {
		return this.data
	}
}

const store = new Store()

const lastSegment = function(str)
{
	const index = str.lastIndexOf(".")
	if(index === -1) { return null }

	return str.slice(index + 1)
}

export {
	store, lastSegment
}
<|endoftext|>


<commit_before>import S from "s-js";
import * as fastJsonPatch from "fast-json-patch";

function isKey(name, keys) {
  // inefficient check...  we are storing array of keys for this now...
  //return fn.toString().startsWith("function data(value)");
  return keys.indexOf(name) > -1;
}

/*
function isArray(arr) {
  return !!arr && arr.constructor === Array;
}

function isObject(obj) {
  return !!obj && obj.constructor === Object;
}
*/

const arrayMutators = [
  "splice",
  "push",
  "unshift",
  "pop",
  "shift",
  "copyWithin",
  "reverse"
];

export function autorun(thunk) {
  S.root(() => S(thunk));
}

function isKeyConflict(key, store) {
  if (key in store) {
    throw new RangeError(
      `actions: ${key} conflicts with a key already present in state`
    );
  }
}

function extendArray(val, theSetter) {
  const arrHandler = {
    get: function(target, name) {
      // wrap mutating functions...
      if (arrayMutators.indexOf(name) > -1) {
        return function() {
          // you need to delay the set of this value just like SArray... save mutation to temp first...
          let tmp = target.slice(0); // get clone of array
          const res = Array.prototype[name].apply(tmp, arguments);
          theSetter(tmp);
          return res;
        };
      }
      return target[name];
    }
  };
  return new Proxy(val, arrHandler);
}

function addData(key, val, opts, store, local) {
  const unobserved = local.unobserved;
  const observed = local.observed;
  if (opts && opts.observed === false) {
    unobserved.push(key);
    store[key] = val;
  } else {
    observed.push(key);
    store[key] = S.data(val);
  }
}

function addAction(key, val, opts, local) {
  const proxy = local.proxy;
  const fn = val;
  local.actions[key] = function() {
    const actionArgs = arguments;
    S.freeze(() => {
      fn.apply(proxy, actionArgs);
    });
  };
}

function addComputed(key, val, opts, store, local) {
  const proxy = local.proxy;
  const computed = local.computed;
  const disposers = local.disposers;
  computed.push(key);
  const comp = val.bind(proxy);
  S.root(dispose => {
    store[key] = S(comp);
    disposers[key] = dispose;
  });
}

function addStore(key, val, store, local) {
  const stores = local.stores;
  const disposers = local.disposers;
  stores.push(key);
  const s = val.state || {};
  const a = val.actions || {};
  store[key] = Store(s, a);
  disposers[key] = () => {
    store[key]("dispose");
  };
}

function dispose(store, local) {
  const disposers = local.disposers;
  Object.keys(disposers).forEach(key => {
    disposers[key]();
  });
  Object.keys(store).forEach(key => {
    delete store[key];
  });
  Object.keys(local.actions).forEach(key => {
    delete local.actions[key];
  });
  // dispose of snapshot generator
  local.snapshotDisposer();
  const p = local.proxy;
  local = {
    proxy: p,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions: {},
    snapshot: undefined,
    snapshotDisposer: undefined,
    disposers: {}
  };
  return local;
}

function addToStore(name, value, p) {
  if (typeof value === "function") {
    if (value.length === 0) {
      p("computed", name, value);
    } else {
      //p("action", name, value);
      throw new RangeError(
        "Cannot add actions implicitly, please call store api directly"
      );
    }
  } else if (
    Array.isArray(value) ||
    typeof value === "number" ||
    typeof value === "string" ||
    typeof value === "boolean" ||
    typeof value === "symbol" ||
    value === null ||
    value === undefined
  ) {
    p("data", name, value);
  } else {
    p("store", name, { state: value });
  }
  return true;
}

function restore(snapshot, local) {
  Object.keys(snapshot).forEach(key => {
    local.proxy[key] = snapshot[key];
  });
}

export function Store(state, actions) {
  state = state || {};
  actions = actions || {};
  let local = {
    proxy: undefined,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions,
    snapshot: undefined,
    snapshotDisposer: undefined,
    registered: S.data([]), // fills with "patch => {}""
    disposers: {}
  };
  /* eslint-disable complexity */
  const store = function(t, key, val, opts) {
    if (key) {
      isKeyConflict(key, store);
    }

    if (t === "data") {
      addData(key, val, opts, store, local);
    } else if (t === "action") {
      addAction(key, val, opts, local);
    } else if (t === "computed") {
      addComputed(key, val, opts, store, local);
    } else if (t === "store") {
      addStore(key, val, store, local);
    } else if (t === "snapshot") {
      return local.snapshot();
    } else if (t === "register") {
      // overloading use of key... not monomorphic for sure lol...
      let reged = local.registered();
      reged.push(key);
      local.registered(reged);
    } else if (t === "unregister") {
      let reged = local.registered();
      let index = reged.indexOf(key);
      if (index > -1) {
        reged.splice(index, 1);
      } else {
        throw new RangeError(
          "function passed to unregister was not previously registered..."
        );
      }
      local.registered(reged);
    } else if (t === "apply") {
      // apply a patch store("apply", patch)
      restore(fastJsonPatch.applyPatch(local.snapshot, key), local);
    } else if (t === "restore") {
      // restore a snapshot... store("restore", snapshot)
      restore(key, local)
    } else if (t === "dispose") {
      local = dispose(store, local);
    } else {
      throw new RangeError(
        "type must be one of the following: data, dispose, action, computed, store, snapshot, register, unregister, apply, restore"
      );
    }
  };
  /* eslint-enable complexity */
  local.proxy = new Proxy(store, {
    get: function(target, name) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            let val = target[name]();
            if (Array.isArray(val)) {
              val = extendArray(val, target[name]);
              return val;
            } else {
              return val;
            }
          } else if (isKey(name, local.computed)) {
            return target[name]();
          } else {
            return target[name];
          }
        } else {
          return target[name];
        }
      } else {
        if (name in local.actions) {
          return local.actions[name];
        } else {
          return undefined;
        }
      }
    },
    set: function(target, name, value) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            target[name](value);
          } else if (isKey(name, local.unobserved)) {
            target[name] = value;
          } else {
            local.disposers[name]();
            delete local.disposers[name];
            delete target[name];
            return addToStore(name, value, local.proxy);
          }
        } else {
          target[name] = value;
        }
        return true;
      } else {
        return addToStore(name, value, local.proxy);
      }
    },
    has: function(target, name) {
      // we only want for..in loops to enumerate data/computed, not actions
      if (
        local.computed.indexOf(name) > -1 ||
        local.observed.indexOf(name) > -1 ||
        local.unobserved.indexOf(name) > -1 ||
        local.stores.indexOf(name) > -1
      ) {
        return true;
      } else {
        return false;
      }
    },
    ownKeys: function(target) {
      return Reflect.ownKeys(target).filter(k => {
        return (
          local.computed.indexOf(k) > -1 ||
          local.observed.indexOf(k) > -1 ||
          local.unobserved.indexOf(k) > -1 ||
          local.stores.indexOf(k) > -1 ||
          k === "caller" ||
          k === "prototype" ||
          k === "arguments"
        );
      });
    },
    deleteProperty: function(target, name) {
      if (name in local.actions) {
        return delete local.actions[name];
      } else if (name in target) {
        if (name in local.disposers) {
          local.disposers[name]();
          delete local.disposers[name];
        }
        if (local.observed.indexOf(name) > -1) {
          local.observed = local.observed.filter(key => key !== name);
        }
        if (local.computed.indexOf(name) > -1) {
          local.computed = local.computed.filter(key => key !== name);
        }
        if (local.stores.indexOf(name) > -1) {
          local.stores = local.stores.filter(key => key !== name);
        }
        return delete target[name];
      } else {
        return false;
      }
    }
  });

  // attach data and computations to proxy...
  Object.keys(state).forEach(key => {
    const val = state[key];
    addToStore(key, val, local.proxy);
  });

  Object.keys(actions).forEach(key => {
    local.proxy("action", key, actions[key]);
  });

  // add computed snapshot
  S.root(dispose => {
    local.snapshotDisposer = dispose;
    local.snapshot = S(() => {
      let snap = {};
      let stateKeys = local.observed.concat(local.unobserved); // only interested in state, not computed/actions
      stateKeys.forEach(key => {
        snap[key] = local.proxy[key];
      });
      // also get the snapshots for nested stores...
      local.stores.forEach(store => {
        snap[store] = local.proxy[store]("snapshot");
      });
      return snap;
    });
  });

  let lastSnap;
  autorun(() => {
    if (local.registered().length === 0) {
      lastSnap = local.snapshot(); // if no one is watching for patches don't generate them...
    } else {
      let nextSnap = local.snapshot();
      const patch = fastJsonPatch.compare(lastSnap, nextSnap);
      if (patch.length > 0) {
        local.registered().forEach(notify => notify(patch));
      }
      // update last snap...
      lastSnap = nextSnap;
    }
  });

  return local.proxy;
}
<commit_msg>missing semi...<commit_after>import S from "s-js";
import * as fastJsonPatch from "fast-json-patch";

function isKey(name, keys) {
  // inefficient check...  we are storing array of keys for this now...
  //return fn.toString().startsWith("function data(value)");
  return keys.indexOf(name) > -1;
}

/*
function isArray(arr) {
  return !!arr && arr.constructor === Array;
}

function isObject(obj) {
  return !!obj && obj.constructor === Object;
}
*/

const arrayMutators = [
  "splice",
  "push",
  "unshift",
  "pop",
  "shift",
  "copyWithin",
  "reverse"
];

export function autorun(thunk) {
  S.root(() => S(thunk));
}

function isKeyConflict(key, store) {
  if (key in store) {
    throw new RangeError(
      `actions: ${key} conflicts with a key already present in state`
    );
  }
}

function extendArray(val, theSetter) {
  const arrHandler = {
    get: function(target, name) {
      // wrap mutating functions...
      if (arrayMutators.indexOf(name) > -1) {
        return function() {
          // you need to delay the set of this value just like SArray... save mutation to temp first...
          let tmp = target.slice(0); // get clone of array
          const res = Array.prototype[name].apply(tmp, arguments);
          theSetter(tmp);
          return res;
        };
      }
      return target[name];
    }
  };
  return new Proxy(val, arrHandler);
}

function addData(key, val, opts, store, local) {
  const unobserved = local.unobserved;
  const observed = local.observed;
  if (opts && opts.observed === false) {
    unobserved.push(key);
    store[key] = val;
  } else {
    observed.push(key);
    store[key] = S.data(val);
  }
}

function addAction(key, val, opts, local) {
  const proxy = local.proxy;
  const fn = val;
  local.actions[key] = function() {
    const actionArgs = arguments;
    S.freeze(() => {
      fn.apply(proxy, actionArgs);
    });
  };
}

function addComputed(key, val, opts, store, local) {
  const proxy = local.proxy;
  const computed = local.computed;
  const disposers = local.disposers;
  computed.push(key);
  const comp = val.bind(proxy);
  S.root(dispose => {
    store[key] = S(comp);
    disposers[key] = dispose;
  });
}

function addStore(key, val, store, local) {
  const stores = local.stores;
  const disposers = local.disposers;
  stores.push(key);
  const s = val.state || {};
  const a = val.actions || {};
  store[key] = Store(s, a);
  disposers[key] = () => {
    store[key]("dispose");
  };
}

function dispose(store, local) {
  const disposers = local.disposers;
  Object.keys(disposers).forEach(key => {
    disposers[key]();
  });
  Object.keys(store).forEach(key => {
    delete store[key];
  });
  Object.keys(local.actions).forEach(key => {
    delete local.actions[key];
  });
  // dispose of snapshot generator
  local.snapshotDisposer();
  const p = local.proxy;
  local = {
    proxy: p,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions: {},
    snapshot: undefined,
    snapshotDisposer: undefined,
    disposers: {}
  };
  return local;
}

function addToStore(name, value, p) {
  if (typeof value === "function") {
    if (value.length === 0) {
      p("computed", name, value);
    } else {
      //p("action", name, value);
      throw new RangeError(
        "Cannot add actions implicitly, please call store api directly"
      );
    }
  } else if (
    Array.isArray(value) ||
    typeof value === "number" ||
    typeof value === "string" ||
    typeof value === "boolean" ||
    typeof value === "symbol" ||
    value === null ||
    value === undefined
  ) {
    p("data", name, value);
  } else {
    p("store", name, { state: value });
  }
  return true;
}

function restore(snapshot, local) {
  Object.keys(snapshot).forEach(key => {
    local.proxy[key] = snapshot[key];
  });
}

export function Store(state, actions) {
  state = state || {};
  actions = actions || {};
  let local = {
    proxy: undefined,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions,
    snapshot: undefined,
    snapshotDisposer: undefined,
    registered: S.data([]), // fills with "patch => {}""
    disposers: {}
  };
  /* eslint-disable complexity */
  const store = function(t, key, val, opts) {
    if (key) {
      isKeyConflict(key, store);
    }

    if (t === "data") {
      addData(key, val, opts, store, local);
    } else if (t === "action") {
      addAction(key, val, opts, local);
    } else if (t === "computed") {
      addComputed(key, val, opts, store, local);
    } else if (t === "store") {
      addStore(key, val, store, local);
    } else if (t === "snapshot") {
      return local.snapshot();
    } else if (t === "register") {
      // overloading use of key... not monomorphic for sure lol...
      let reged = local.registered();
      reged.push(key);
      local.registered(reged);
    } else if (t === "unregister") {
      let reged = local.registered();
      let index = reged.indexOf(key);
      if (index > -1) {
        reged.splice(index, 1);
      } else {
        throw new RangeError(
          "function passed to unregister was not previously registered..."
        );
      }
      local.registered(reged);
    } else if (t === "apply") {
      // apply a patch store("apply", patch)
      restore(fastJsonPatch.applyPatch(local.snapshot, key), local);
    } else if (t === "restore") {
      // restore a snapshot... store("restore", snapshot)
      restore(key, local);
    } else if (t === "dispose") {
      local = dispose(store, local);
    } else {
      throw new RangeError(
        "type must be one of the following: data, dispose, action, computed, store, snapshot, register, unregister, apply, restore"
      );
    }
  };
  /* eslint-enable complexity */
  local.proxy = new Proxy(store, {
    get: function(target, name) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            let val = target[name]();
            if (Array.isArray(val)) {
              val = extendArray(val, target[name]);
              return val;
            } else {
              return val;
            }
          } else if (isKey(name, local.computed)) {
            return target[name]();
          } else {
            return target[name];
          }
        } else {
          return target[name];
        }
      } else {
        if (name in local.actions) {
          return local.actions[name];
        } else {
          return undefined;
        }
      }
    },
    set: function(target, name, value) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            target[name](value);
          } else if (isKey(name, local.unobserved)) {
            target[name] = value;
          } else {
            local.disposers[name]();
            delete local.disposers[name];
            delete target[name];
            return addToStore(name, value, local.proxy);
          }
        } else {
          target[name] = value;
        }
        return true;
      } else {
        return addToStore(name, value, local.proxy);
      }
    },
    has: function(target, name) {
      // we only want for..in loops to enumerate data/computed, not actions
      if (
        local.computed.indexOf(name) > -1 ||
        local.observed.indexOf(name) > -1 ||
        local.unobserved.indexOf(name) > -1 ||
        local.stores.indexOf(name) > -1
      ) {
        return true;
      } else {
        return false;
      }
    },
    ownKeys: function(target) {
      return Reflect.ownKeys(target).filter(k => {
        return (
          local.computed.indexOf(k) > -1 ||
          local.observed.indexOf(k) > -1 ||
          local.unobserved.indexOf(k) > -1 ||
          local.stores.indexOf(k) > -1 ||
          k === "caller" ||
          k === "prototype" ||
          k === "arguments"
        );
      });
    },
    deleteProperty: function(target, name) {
      if (name in local.actions) {
        return delete local.actions[name];
      } else if (name in target) {
        if (name in local.disposers) {
          local.disposers[name]();
          delete local.disposers[name];
        }
        if (local.observed.indexOf(name) > -1) {
          local.observed = local.observed.filter(key => key !== name);
        }
        if (local.computed.indexOf(name) > -1) {
          local.computed = local.computed.filter(key => key !== name);
        }
        if (local.stores.indexOf(name) > -1) {
          local.stores = local.stores.filter(key => key !== name);
        }
        return delete target[name];
      } else {
        return false;
      }
    }
  });

  // attach data and computations to proxy...
  Object.keys(state).forEach(key => {
    const val = state[key];
    addToStore(key, val, local.proxy);
  });

  Object.keys(actions).forEach(key => {
    local.proxy("action", key, actions[key]);
  });

  // add computed snapshot
  S.root(dispose => {
    local.snapshotDisposer = dispose;
    local.snapshot = S(() => {
      let snap = {};
      let stateKeys = local.observed.concat(local.unobserved); // only interested in state, not computed/actions
      stateKeys.forEach(key => {
        snap[key] = local.proxy[key];
      });
      // also get the snapshots for nested stores...
      local.stores.forEach(store => {
        snap[store] = local.proxy[store]("snapshot");
      });
      return snap;
    });
  });

  let lastSnap;
  autorun(() => {
    if (local.registered().length === 0) {
      lastSnap = local.snapshot(); // if no one is watching for patches don't generate them...
    } else {
      let nextSnap = local.snapshot();
      const patch = fastJsonPatch.compare(lastSnap, nextSnap);
      if (patch.length > 0) {
        local.registered().forEach(notify => notify(patch));
      }
      // update last snap...
      lastSnap = nextSnap;
    }
  });

  return local.proxy;
}
<|endoftext|>


<commit_before>import S from "s-js";
import * as fastJsonPatch from "fast-json-patch";

function isKey(name, keys) {
  // inefficient check...  we are storing array of keys for this now...
  //return fn.toString().startsWith("function data(value)");
  return keys.indexOf(name) > -1;
}

/*
function isArray(arr) {
  return !!arr && arr.constructor === Array;
}

function isObject(obj) {
  return !!obj && obj.constructor === Object;
}
*/

const arrayMutators = [
  "splice",
  "push",
  "unshift",
  "pop",
  "shift",
  "copyWithin",
  "reverse"
];

export function autorun(thunk) {
  S.root(() => S(thunk));
}

function isKeyConflict(key, store) {
  if (key in store) {
    throw new RangeError(
      `actions: ${key} conflicts with a key already present in state`
    );
  }
}

function extendArray(val, theSetter) {
  const arrHandler = {
    get: function(target, name) {
      // wrap mutating functions...
      if (arrayMutators.indexOf(name) > -1) {
        return function() {
          // you need to delay the set of this value just like SArray... save mutation to temp first...
          let tmp = target.slice(0); // get clone of array
          const res = Array.prototype[name].apply(tmp, arguments);
          theSetter(tmp);
          return res;
        };
      }
      return target[name];
    }
  };
  return new Proxy(val, arrHandler);
}

function addData(key, val, opts, store, local) {
  const unobserved = local.unobserved;
  const observed = local.observed;
  if (opts && opts.observed === false) {
    unobserved.push(key);
    store[key] = val;
  } else {
    observed.push(key);
    store[key] = S.data(val);
  }
}

function addAction(key, val, opts, local) {
  const proxy = local.proxy;
  const fn = val;
  local.actions[key] = function() {
    const actionArgs = arguments;
    S.freeze(() => {
      fn.apply(proxy, actionArgs);
    });
  };
}

function addComputed(key, val, opts, store, local) {
  const proxy = local.proxy;
  const computed = local.computed;
  const disposers = local.disposers;
  computed.push(key);
  const comp = val.bind(proxy);
  S.root(dispose => {
    store[key] = S(comp);
    disposers[key] = dispose;
  });
}

function addStore(key, val, store, local) {
  const stores = local.stores;
  const disposers = local.disposers;
  stores.push(key);
  const s = val.state || {};
  const a = val.actions || {};
  store[key] = Store(s, a);
  disposers[key] = () => {
    store[key]("dispose");
  };
}

function dispose(store, local) {
  const disposers = local.disposers;
  Object.keys(disposers).forEach(key => {
    disposers[key]();
  });
  Object.keys(store).forEach(key => {
    delete store[key];
  });
  Object.keys(local.actions).forEach(key => {
    delete local.actions[key];
  });
  const p = local.proxy;
  local = {
    proxy: p,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions: {},
    snapshot: undefined,
    snapshotDisposer: undefined,
    disposers: {}
  };
  return local;
}

function addToStore(name, value, p) {
  if (typeof value === "function") {
    if (value.length === 0) {
      p("computed", name, value);
    } else {
      //p("action", name, value);
      throw new RangeError(
        "Cannot add actions implicitly, please call store api directly"
      );
    }
  } else if (
    Array.isArray(value) ||
    typeof value === "number" ||
    typeof value === "string"
  ) {
    p("data", name, value);
  } else {
    p("store", name, { state: value });
  }
  return true;
}

export function Store(state, actions) {
  state = state || {};
  actions = actions || {};
  let local = {
    proxy: undefined,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions,
    snapshot: undefined,
    snapshotDisposer: undefined,
    registered: S.data([]), // fills with "patch => {}""
    disposers: {}
  };
  /* eslint-disable complexity */
  const store = function(t, key, val, opts) {
    if (key) {
      isKeyConflict(key, store);
    }

    if (t === "data") {
      addData(key, val, opts, store, local);
    } else if (t === "action") {
      addAction(key, val, opts, local);
    } else if (t === "computed") {
      addComputed(key, val, opts, store, local);
    } else if (t === "store") {
      addStore(key, val, store, local);
    } else if (t === "snapshot") {
      return local.snapshot();
    } else if (t === "register") {
      // overloading use of key... not monomorphic for sure lol...
      let reged = local.registered();
      reged.push(key);
      local.registered(reged);
    } else if (t === "unregister") {
      let reged = local.registered();
      let index = reged.indexOf(key);
      if (index > -1) {
        reged.splice(index, 1);
      } else {
        throw new RangeError(
          "function passed to unregister was not previously registered..."
        );
      }
      local.registered(reged);
    } else if (t === "dispose") {
      local = dispose(store, local);
    } else {
      throw new RangeError(
        "type must be one of the following: data, dispose, action, computed, store, snapshot, register, unregister"
      );
    }
  };
  /* eslint-enable complexity */
  local.proxy = new Proxy(store, {
    get: function(target, name) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            let val = target[name]();
            if (Array.isArray(val)) {
              val = extendArray(val, target[name]);
              return val;
            } else {
              return val;
            }
          } else if (isKey(name, local.computed)) {
            return target[name]();
          } else {
            return target[name];
          }
        } else {
          return target[name];
        }
      } else {
        if (name in local.actions) {
          return local.actions[name];
        } else {
          return undefined;
        }
      }
    },
    set: function(target, name, value) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            target[name](value);
          } else if (isKey(name, local.unobserved)) {
            target[name] = value;
          } else {
            local.disposers[name]();
            delete local.disposers[name];
            delete target[name];
            return addToStore(name, value, local.proxy);
          }
        } else {
          target[name] = value;
        }
        return true;
      } else {
        return addToStore(name, value, local.proxy);
      }
    },
    has: function(target, name) {
      // we only want for..in loops to enumerate data/computed, not actions
      if (
        local.computed.indexOf(name) > -1 ||
        local.observed.indexOf(name) > -1 ||
        local.unobserved.indexOf(name) > -1 ||
        local.stores.indexOf(name) > -1
      ) {
        return true;
      } else {
        return false;
      }
    },
    ownKeys: function(target) {
      return Reflect.ownKeys(target).filter(k => {
        return (
          local.computed.indexOf(k) > -1 ||
          local.observed.indexOf(k) > -1 ||
          local.unobserved.indexOf(k) > -1 ||
          local.stores.indexOf(k) > -1 ||
          k === "caller" ||
          k === "prototype" ||
          k === "arguments"
        );
      });
    },
    deleteProperty: function(target, name) {
      if (name in local.actions) {
        return delete local.actions[name];
      } else if (name in target) {
        if (name in local.disposers) {
          local.disposers[name]();
          delete local.disposers[name];
        }
        if (local.observed.indexOf(name) > -1) {
          local.observed = local.observed.filter(key => key !== name);
        }
        if (local.computed.indexOf(name) > -1) {
          local.computed = local.computed.filter(key => key !== name);
        }
        if (local.stores.indexOf(name) > -1) {
          local.stores = local.stores.filter(key => key !== name);
        }
        return delete target[name];
      } else {
        return false;
      }
    }
  });

  // attach data and computations to proxy...
  Object.keys(state).forEach(key => {
    const val = state[key];
    if (typeof val === "function") {
      local.proxy("computed", key, val);
    } else if (typeof val === "object" && !Array.isArray(val)) {
      local.proxy("store", key, { state: val });
    } else {
      local.proxy("data", key, val);
    }
  });

  Object.keys(actions).forEach(key => {
    local.proxy("action", key, actions[key]);
  });

  // add computed snapshot
  S.root(dispose => {
    local.snapshotDisposer = dispose;
    local.snapshot = S(() => {
      let snap = {};
      let stateKeys = local.observed.concat(local.unobserved); // only interested in state, not computed/actions
      stateKeys.forEach(key => {
        snap[key] = local.proxy[key];
      });
      // also get the snapshots for nested stores...
      local.stores.forEach(store => {
        snap[store] = local.proxy[store]("snapshot");
      });
      return snap;
    });
  });

  let lastSnap;
  autorun(() => {
    if (local.registered().length === 0) {
      lastSnap = local.snapshot(); // if no one is watching for patches don't generate them...
    } else {
      let nextSnap = local.snapshot();
      const patch = fastJsonPatch.compare(lastSnap, nextSnap);
      if (patch.length > 0) {
        local.registered().forEach(notify => notify(patch));
      }
      // update last snap...
      lastSnap = nextSnap;
    }
  });

  return local.proxy;
}
<commit_msg>fixed uncovered branch...<commit_after>import S from "s-js";
import * as fastJsonPatch from "fast-json-patch";

function isKey(name, keys) {
  // inefficient check...  we are storing array of keys for this now...
  //return fn.toString().startsWith("function data(value)");
  return keys.indexOf(name) > -1;
}

/*
function isArray(arr) {
  return !!arr && arr.constructor === Array;
}

function isObject(obj) {
  return !!obj && obj.constructor === Object;
}
*/

const arrayMutators = [
  "splice",
  "push",
  "unshift",
  "pop",
  "shift",
  "copyWithin",
  "reverse"
];

export function autorun(thunk) {
  S.root(() => S(thunk));
}

function isKeyConflict(key, store) {
  if (key in store) {
    throw new RangeError(
      `actions: ${key} conflicts with a key already present in state`
    );
  }
}

function extendArray(val, theSetter) {
  const arrHandler = {
    get: function(target, name) {
      // wrap mutating functions...
      if (arrayMutators.indexOf(name) > -1) {
        return function() {
          // you need to delay the set of this value just like SArray... save mutation to temp first...
          let tmp = target.slice(0); // get clone of array
          const res = Array.prototype[name].apply(tmp, arguments);
          theSetter(tmp);
          return res;
        };
      }
      return target[name];
    }
  };
  return new Proxy(val, arrHandler);
}

function addData(key, val, opts, store, local) {
  const unobserved = local.unobserved;
  const observed = local.observed;
  if (opts && opts.observed === false) {
    unobserved.push(key);
    store[key] = val;
  } else {
    observed.push(key);
    store[key] = S.data(val);
  }
}

function addAction(key, val, opts, local) {
  const proxy = local.proxy;
  const fn = val;
  local.actions[key] = function() {
    const actionArgs = arguments;
    S.freeze(() => {
      fn.apply(proxy, actionArgs);
    });
  };
}

function addComputed(key, val, opts, store, local) {
  const proxy = local.proxy;
  const computed = local.computed;
  const disposers = local.disposers;
  computed.push(key);
  const comp = val.bind(proxy);
  S.root(dispose => {
    store[key] = S(comp);
    disposers[key] = dispose;
  });
}

function addStore(key, val, store, local) {
  const stores = local.stores;
  const disposers = local.disposers;
  stores.push(key);
  const s = val.state || {};
  const a = val.actions || {};
  store[key] = Store(s, a);
  disposers[key] = () => {
    store[key]("dispose");
  };
}

function dispose(store, local) {
  const disposers = local.disposers;
  Object.keys(disposers).forEach(key => {
    disposers[key]();
  });
  Object.keys(store).forEach(key => {
    delete store[key];
  });
  Object.keys(local.actions).forEach(key => {
    delete local.actions[key];
  });
  const p = local.proxy;
  local = {
    proxy: p,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions: {},
    snapshot: undefined,
    snapshotDisposer: undefined,
    disposers: {}
  };
  return local;
}

function addToStore(name, value, p) {
  if (typeof value === "function") {
    if (value.length === 0) {
      p("computed", name, value);
    } else {
      //p("action", name, value);
      throw new RangeError(
        "Cannot add actions implicitly, please call store api directly"
      );
    }
  } else if (
    Array.isArray(value) ||
    typeof value === "number" ||
    typeof value === "string"
  ) {
    p("data", name, value);
  } else {
    p("store", name, { state: value });
  }
  return true;
}

export function Store(state, actions) {
  state = state || {};
  actions = actions || {};
  let local = {
    proxy: undefined,
    computed: [],
    observed: [],
    unobserved: [],
    stores: [],
    actions,
    snapshot: undefined,
    snapshotDisposer: undefined,
    registered: S.data([]), // fills with "patch => {}""
    disposers: {}
  };
  /* eslint-disable complexity */
  const store = function(t, key, val, opts) {
    if (key) {
      isKeyConflict(key, store);
    }

    if (t === "data") {
      addData(key, val, opts, store, local);
    } else if (t === "action") {
      addAction(key, val, opts, local);
    } else if (t === "computed") {
      addComputed(key, val, opts, store, local);
    } else if (t === "store") {
      addStore(key, val, store, local);
    } else if (t === "snapshot") {
      return local.snapshot();
    } else if (t === "register") {
      // overloading use of key... not monomorphic for sure lol...
      let reged = local.registered();
      reged.push(key);
      local.registered(reged);
    } else if (t === "unregister") {
      let reged = local.registered();
      let index = reged.indexOf(key);
      if (index > -1) {
        reged.splice(index, 1);
      } else {
        throw new RangeError(
          "function passed to unregister was not previously registered..."
        );
      }
      local.registered(reged);
    } else if (t === "dispose") {
      local = dispose(store, local);
    } else {
      throw new RangeError(
        "type must be one of the following: data, dispose, action, computed, store, snapshot, register, unregister"
      );
    }
  };
  /* eslint-enable complexity */
  local.proxy = new Proxy(store, {
    get: function(target, name) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            let val = target[name]();
            if (Array.isArray(val)) {
              val = extendArray(val, target[name]);
              return val;
            } else {
              return val;
            }
          } else if (isKey(name, local.computed)) {
            return target[name]();
          } else {
            return target[name];
          }
        } else {
          return target[name];
        }
      } else {
        if (name in local.actions) {
          return local.actions[name];
        } else {
          return undefined;
        }
      }
    },
    set: function(target, name, value) {
      if (name in target) {
        if (typeof target[name] === "function") {
          if (isKey(name, local.observed)) {
            target[name](value);
          } else if (isKey(name, local.unobserved)) {
            target[name] = value;
          } else {
            local.disposers[name]();
            delete local.disposers[name];
            delete target[name];
            return addToStore(name, value, local.proxy);
          }
        } else {
          target[name] = value;
        }
        return true;
      } else {
        return addToStore(name, value, local.proxy);
      }
    },
    has: function(target, name) {
      // we only want for..in loops to enumerate data/computed, not actions
      if (
        local.computed.indexOf(name) > -1 ||
        local.observed.indexOf(name) > -1 ||
        local.unobserved.indexOf(name) > -1 ||
        local.stores.indexOf(name) > -1
      ) {
        return true;
      } else {
        return false;
      }
    },
    ownKeys: function(target) {
      return Reflect.ownKeys(target).filter(k => {
        return (
          local.computed.indexOf(k) > -1 ||
          local.observed.indexOf(k) > -1 ||
          local.unobserved.indexOf(k) > -1 ||
          local.stores.indexOf(k) > -1 ||
          k === "caller" ||
          k === "prototype" ||
          k === "arguments"
        );
      });
    },
    deleteProperty: function(target, name) {
      if (name in local.actions) {
        return delete local.actions[name];
      } else if (name in target) {
        if (name in local.disposers) {
          local.disposers[name]();
          delete local.disposers[name];
        }
        if (local.observed.indexOf(name) > -1) {
          local.observed = local.observed.filter(key => key !== name);
        }
        if (local.computed.indexOf(name) > -1) {
          local.computed = local.computed.filter(key => key !== name);
        }
        if (local.stores.indexOf(name) > -1) {
          local.stores = local.stores.filter(key => key !== name);
        }
        return delete target[name];
      } else {
        return false;
      }
    }
  });

  // attach data and computations to proxy...
  Object.keys(state).forEach(key => {
    const val = state[key];
    if (typeof val === "function") {
      local.proxy("computed", key, val);
    } else if (
      Array.isArray(val) ||
      typeof val === "number" ||
      typeof val === "string"
    ) {
      local.proxy("data", key, val);
    } else {
      local.proxy("store", key, { state: val });
    }
  });

  Object.keys(actions).forEach(key => {
    local.proxy("action", key, actions[key]);
  });

  // add computed snapshot
  S.root(dispose => {
    local.snapshotDisposer = dispose;
    local.snapshot = S(() => {
      let snap = {};
      let stateKeys = local.observed.concat(local.unobserved); // only interested in state, not computed/actions
      stateKeys.forEach(key => {
        snap[key] = local.proxy[key];
      });
      // also get the snapshots for nested stores...
      local.stores.forEach(store => {
        snap[store] = local.proxy[store]("snapshot");
      });
      return snap;
    });
  });

  let lastSnap;
  autorun(() => {
    if (local.registered().length === 0) {
      lastSnap = local.snapshot(); // if no one is watching for patches don't generate them...
    } else {
      let nextSnap = local.snapshot();
      const patch = fastJsonPatch.compare(lastSnap, nextSnap);
      if (patch.length > 0) {
        local.registered().forEach(notify => notify(patch));
      }
      // update last snap...
      lastSnap = nextSnap;
    }
  });

  return local.proxy;
}
<|endoftext|>


<commit_before>/* global describe,it,afterEach,beforeEach */
var Hapi = require('hapi')
var assert = require('assert')

describe('Testing Hapi RethinkDB plugin', function () {
  var server = null

  beforeEach(function () {
    server = new Hapi.Server()
  })

  afterEach(function () {
    server = null
  })

  it('should be able to register the plugin with default options', function (done) {
    server.register({
      register: require('../')
    }, function () {
      assert(server.plugins['hapi-rethinkdb'].connection, 'No RethinkDB connection returned')
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should have connected', function (done) {
    server.register({
      register: require('../')
    }, function () {
      assert(server.plugins['hapi-rethinkdb'].connection.open, 'Did not connect')
      done()
    })
  })

  it('should take URLs as parameters', function (done) {
    server.register({
      register: require('../'),
      options: { url: 'rethinkdb://localhost:28015' }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should take URLs as parameters and use 28015 port as default', function (done) {
    server.register({
      register: require('../'),
      options: { url: 'rethinkdb://localhost' }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

})
<commit_msg>add tests<commit_after>/* global describe,it,afterEach,beforeEach */
var Hapi = require('hapi')
var assert = require('assert')

describe('Testing Hapi RethinkDB plugin', function () {
  var server = null

  beforeEach(function () {
    server = new Hapi.Server()
  })

  afterEach(function () {
    server = null
  })

  it('should be able to register the plugin with default options', function (done) {
    server.register({
      register: require('../')
    }, function () {
      assert(server.plugins['hapi-rethinkdb'].connection, 'No RethinkDB connection returned')
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should have connected', function (done) {
    server.register({
      register: require('../')
    }, function () {
      assert(server.plugins['hapi-rethinkdb'].connection.open, 'Did not connect')
      done()
    })
  })

  it('should take URLs as parameters', function (done) {
    server.register({
      register: require('../'),
      options: { url: 'rethinkdb://localhost:28015' }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should take URLs as parameters and use 28015 port as default', function (done) {
    server.register({
      register: require('../'),
      options: { url: 'rethinkdb://localhost' }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should connect taking the port and the host as an option', function (done) {
    server.register({
      register: require('../'),
      options: {
        host: 'localhost',
        port: 28015
      }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should connect to the default port passing only the hostname as an option', function (done) {
    server.register({
      register: require('../'),
      options: { host: 'localhost' }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should connect to the default host passing only the port number as an option', function (done) {
    server.register({
      register: require('../'),
      options: { port: 28015 }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

  it('should connect to the default host and port passing only the database name as an option', function (done) {
    server.register({
      register: require('../'),
      options: { db: 'newtest' }
    }, function () {
      assert(
        server.plugins['hapi-rethinkdb'].connection.host === 'localhost',
        'Connected to incorrect address'
      )
      assert(
        server.plugins['hapi-rethinkdb'].connection.port === 28015,
        'Connected to incorrect port'
      )
      done()
    })
  })

})
<|endoftext|>


<commit_before>var assert = require("assert")
var cookies = require('../index');

var url = 'http://www.example.com';

// these are simple tests
describe('CookieJar', function() {
  describe('add', function() {
    it("using a Cookie object", function(){
      var jar = new cookies.CookieJar();
      var c = new cookies.Cookie('foo=bar');
      jar.add(c, url);

      var header = jar.getCookieHeaderString(url)
      assert(header === 'foo=bar');
    });

    it("using a cookie string", function(){
      var jar = new cookies.CookieJar();
      jar.add('foo=bar', url);

      var header = jar.getCookieHeaderString(url)
      assert(header === 'foo=bar');
    });

    it("using a json object", function(){
      var jar = new cookies.CookieJar();
      jar.add({key:'foo', value:'bar'}, url);

      var header = jar.getCookieHeaderString(url);
      assert(header === 'foo=bar');
    });
  });

  describe('remove', function() {
    it('should not exist in jar', function(){
      var jar = new cookies.CookieJar();
      jar.add('foo=bar', url);

      var header = jar.getCookieHeaderString(url);
      assert(header === 'foo=bar');
      jar.remove(url);

      var header2 = jar.getCookieHeaderString(url);
      assert(header2 === '');
    });
  });

  describe('getCookies', function() {
    it('should find cookies that match the domain', function(){
      var jar = new cookies.CookieJar();
      jar.add('foo=bar', url);

      var instances = jar.getCookies(url);
      assert(instances.length === 1);
      assert(instances[0].getCookieHeaderString() === 'foo=bar');
    });
  });
});<commit_msg>using better variable name<commit_after>var assert = require("assert")
var cookies = require('../index');

var url = 'http://www.example.com';

// these are simple tests
describe('CookieJar', function() {
  describe('add', function() {
    it("using a Cookie object", function(){
      var jar = new cookies.CookieJar();
      var c = new cookies.Cookie('foo=bar');
      jar.add(c, url);

      var header = jar.getCookieHeaderString(url)
      assert(header === 'foo=bar');
    });

    it("using a cookie string", function(){
      var jar = new cookies.CookieJar();
      jar.add('foo=bar', url);

      var header = jar.getCookieHeaderString(url)
      assert(header === 'foo=bar');
    });

    it("using a json object", function(){
      var jar = new cookies.CookieJar();
      jar.add({key:'foo', value:'bar'}, url);

      var header = jar.getCookieHeaderString(url);
      assert(header === 'foo=bar');
    });
  });

  describe('remove', function() {
    it('should not exist in jar', function(){
      var jar = new cookies.CookieJar();
      jar.add('foo=bar', url);

      var header = jar.getCookieHeaderString(url);
      assert(header === 'foo=bar');
      jar.remove(url);

      var header2 = jar.getCookieHeaderString(url);
      assert(header2 === '');
    });
  });

  describe('getCookies', function() {
    it('should find cookies that match the domain', function(){
      var jar = new cookies.CookieJar();
      jar.add('foo=bar', url);

      var matchingCookies = jar.getCookies(url);
      assert(matchingCookies.length === 1);
      assert(matchingCookies[0].getCookieHeaderString() === 'foo=bar');
    });
  });
});<|endoftext|>