Skip to content

Commit

Permalink
test for ability to create same clouds using same random seed
Browse files Browse the repository at this point in the history
  • Loading branch information
cesine committed Jun 24, 2015
1 parent f812a9e commit aa92441
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 28 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"canvas": "^1.2.1"
},
"devDependencies": {
"jsdom": "^3.0.0"
"jsdom": "^3.0.0",
"mersenne-twister": "^1.0.1"
}
}
}
2 changes: 2 additions & 0 deletions test/SpecRunner.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<script type="text/javascript" src="bower_components/jasmine/lib/jasmine-core/jasmine-html.js"></script>
<script type="text/javascript" src="bower_components/jasmine/lib/jasmine-core/boot.js"></script>

<script type="text/javascript" src="../node_modules/mersenne-twister/src/mersenne-twister.js"></script>

<script type="text/javascript" src="bower_components/d3/d3.js"></script>
<script type="text/javascript" src="../src/d3.layout.cloud.js"></script>

Expand Down
100 changes: 74 additions & 26 deletions test/replicable-layout-spec.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,42 @@
(function() {

/* globals require, describe, it, expect, console, d3, document */
/* globals require, describe, it, expect, console, d3, document, MersenneTwister */
'use strict';

try {

var localdocument;
var locald3;
var d3CloudLayout;
var LocalMersenneTwister;
try {
localdocument = document;
locald3 = d3;
d3CloudLayout = d3.layout.cloud;
LocalMersenneTwister = MersenneTwister;
} catch (e) {
localdocument = require("jsdom").jsdom("<body></body>");
locald3 = require("d3");
d3CloudLayout = require("../");
LocalMersenneTwister = require("mersenne-twister");
}

describe('Replicable layout', function() {
var myFewWordsFactory,
myColorFunction,
myReproduceableDrawFunction,
WIDTH = 400,
HEIGHT = 400;
HEIGHT = 400,
SEED = 2;

// Short hand to build an array of word objects with random importance (as a function to ensure no shared state between the clouds)
myFewWordsFactory = function() {
var randomImportanceGenerator = new LocalMersenneTwister(SEED);
return "As a user I want to be able to remove words and see roughly the same cloud".split(" ")
.map(function(word) {
return {
text: word,
importance: 10 + Math.random() * 90
importance: 10 + randomImportanceGenerator.random() * 90
};
});
};
Expand Down Expand Up @@ -75,7 +80,24 @@
};


xdescribe('Redraw a new cloud', function() {
describe('generate same text data', function() {

it('should have equivalent data', function() {
var firstPageLoad = myFewWordsFactory();
var secondPageLoad = myFewWordsFactory();
expect(secondPageLoad[0].importance).not.toEqual(firstPageLoad[firstPageLoad.length - 1].importance);
for (var wordIndex = 0; wordIndex < secondPageLoad.length; wordIndex++) {
expect(secondPageLoad[wordIndex].importance).toEqual(firstPageLoad[wordIndex].importance);
}
});

it('should use the same code but not leak state ', function() {
expect(myFewWordsFactory()).not.toBe(myFewWordsFactory());
});

});

describe('Redraw a new random cloud', function() {

// Hoist all vars
var myRerenderableCloud,
Expand Down Expand Up @@ -122,6 +144,8 @@
myRerenderableCloud.start();

var representativeWord = myRerenderableCloud.words()[15];
expect(representativeWord.color).toBeDefined();
expect(representativeWord.transform).toBeDefined();
expect(representativeWord.rotate).toBeDefined();
expect(representativeWord.size).toBeDefined();
expect(representativeWord.padding).toBeDefined();
Expand Down Expand Up @@ -153,11 +177,18 @@

expect(wordBeforeRerender.text).toEqual(wordAfterRender.text);
expect(wordBeforeRerender.value).toEqual(wordAfterRender.value);
expect(wordBeforeRerender.color).toEqual(wordAfterRender.color);
expect(wordBeforeRerender.transform).toEqual(wordAfterRender.transform);

expect(wordBeforeRerender.rotate).toEqual(wordAfterRender.rotate);
expect(wordBeforeRerender.size).toEqual(wordAfterRender.size);
expect(wordBeforeRerender.padding).toEqual(wordAfterRender.padding);
expect(wordBeforeRerender.width).toEqual(wordAfterRender.width);
expect(wordBeforeRerender.height).toEqual(wordAfterRender.height);

// If this version of d3.layout.cloud has recursive fit for all words, they might not be the exact same size and therefore width and height
if (wordBeforeRerender.size === wordAfterRender.size) {
expect(wordBeforeRerender.size).toEqual(wordAfterRender.size);
expect(wordBeforeRerender.width).toEqual(wordAfterRender.width);
expect(wordBeforeRerender.height).toEqual(wordAfterRender.height);
}

// These attributes might change but dont seem to affect the render being identical
// expect(wordBeforeRerender.xoff).toEqual(wordAfterRender.xoff);
Expand All @@ -177,14 +208,19 @@
* https://github.com/jasondavies/d3-cloud/pull/8
* https://github.com/jasondavies/d3-cloud/pull/14
* https://github.com/jasondavies/d3-cloud/pull/35
* https://github.com/jasondavies/d3-cloud/pull/45
* https://github.com/WheatonCS/Lexos/issues/149
*/
describe('Redraw the same pseudorandom cloud from the same text', function() {
// Hoist all vars
var myPseudorandomCloud,
myPseudorandomCloudsElement,
myRandomGenerator = new LocalMersenneTwister(SEED),
myRotateRandomGenerator = new LocalMersenneTwister(SEED),
mySecondPseudorandomCloud,
mySecondPseudorandomCloudsElement;
mySecondPseudorandomCloudsElement,
mySecondRandomGenerator = new LocalMersenneTwister(SEED),
mySecondRotateRandomGenerator = new LocalMersenneTwister(SEED);

myPseudorandomCloudsElement = localdocument.createElement("span");
myPseudorandomCloudsElement.setAttribute("id", "pseudo-random-cloud");
Expand All @@ -194,17 +230,21 @@
mySecondPseudorandomCloudsElement.setAttribute("id", "second-pseudo-random-cloud");
localdocument.body.appendChild(mySecondPseudorandomCloudsElement);


// Ask d3-cloud to make an cloud object for us
myPseudorandomCloud = d3CloudLayout();

// Configure our cloud with d3 chaining
myPseudorandomCloud
.random(function() {
return myRandomGenerator.random();
})
.size([WIDTH, HEIGHT])
.words(myFewWordsFactory())
.padding(5)
.rotate(function(word) {
if (word.rotate === null || word.rotate === undefined) {
word.rotate = ~~(Math.random() * 2) * 90;
word.rotate = ~~(myRotateRandomGenerator.random() * 2) * 90;
}
return word.rotate;
})
Expand Down Expand Up @@ -236,12 +276,15 @@

// Configure our cloud with d3 chaining
mySecondPseudorandomCloud
.random(function() {
return mySecondRandomGenerator.random();
})
.size([WIDTH, HEIGHT])
.words(myFewWordsFactory())
.padding(5)
.rotate(function(word) {
if (word.rotate === null || word.rotate === undefined) {
word.rotate = ~~(Math.random() * 2) * 90;
word.rotate = ~~(mySecondRotateRandomGenerator.random() * 2) * 90;
}
return word.rotate;
})
Expand All @@ -263,27 +306,32 @@
var representativeWordInSecondCloud = mySecondPseudorandomCloud.words()[15];
expect(representativeWordInSecondCloud).toBeDefined();
expect(representativeWordInSecondCloud).toBe(mySecondPseudorandomCloud.words()[15]);
// expect(representativeWordInSecondCloud.rotate).toBeDefined();
// expect(representativeWordInSecondCloud.size).toBeDefined();
// expect(representativeWordInSecondCloud.padding).toBeDefined();
// expect(representativeWordInSecondCloud.width).toBeDefined();
// expect(representativeWordInSecondCloud.height).toBeDefined();

// expect(representativeWordInSecondCloud).not.toBe(representativeWord);
// expect(representativeWordInSecondCloud.text).toEqual(wordAfterRender.text);
// expect(representativeWordInSecondCloud.value).toEqual(wordAfterRender.value);
// expect(representativeWordInSecondCloud.rotate).toEqual(wordAfterRender.rotate);
// expect(representativeWordInSecondCloud.size).toEqual(wordAfterRender.size);
// expect(representativeWordInSecondCloud.padding).toEqual(wordAfterRender.padding);
// expect(representativeWordInSecondCloud.width).toEqual(wordAfterRender.width);
// expect(representativeWordInSecondCloud.height).toEqual(wordAfterRender.height);

expect(representativeWordInSecondCloud.rotate).toBeDefined();
expect(representativeWordInSecondCloud.size).toBeDefined();
expect(representativeWordInSecondCloud.padding).toBeDefined();
expect(representativeWordInSecondCloud.width).toBeDefined();
expect(representativeWordInSecondCloud.height).toBeDefined();

// Make sure that there is NO shared state between clouds, otherwise this proves nothing.
expect(representativeWordInSecondCloud).not.toBe(representativeWord);

expect(representativeWordInSecondCloud.text).toEqual(representativeWord.text);
expect(representativeWordInSecondCloud.value).toEqual(representativeWord.value);
expect(representativeWordInSecondCloud.rotate).toEqual(representativeWord.rotate);
expect(representativeWordInSecondCloud.color).toEqual(representativeWord.color);
expect(representativeWordInSecondCloud.transform).toEqual(representativeWord.transform);
expect(representativeWordInSecondCloud.size).toEqual(representativeWord.size);
expect(representativeWordInSecondCloud.padding).toEqual(representativeWord.padding);
expect(representativeWordInSecondCloud.width).toEqual(representativeWord.width);
expect(representativeWordInSecondCloud.height).toEqual(representativeWord.height);
expect(representativeWordInSecondCloud.x).toEqual(representativeWord.x);
expect(representativeWordInSecondCloud.y).toEqual(representativeWord.y);

});

});

describe('Redraw an existing cloud', function() {
xdescribe('Redraw an existing cloud', function() {

it('should not change word objects render attributes', function() {
expect(true).toBeTruthy();
Expand Down

0 comments on commit aa92441

Please sign in to comment.