Skip to content

Commit

Permalink
Testing higher-performance CT interface, see #88
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanolson committed Apr 15, 2020
1 parent 08c5610 commit 9285a2c
Show file tree
Hide file tree
Showing 4 changed files with 239 additions and 7 deletions.
25 changes: 25 additions & 0 deletions html/local-report.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<!--
Displays a self-updating report of continuous test results based on the continuous-server.js prototype.
See local-report.js
-->
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>

<title>Continuous Testing</title>
</head>

<body>
<script src="../../assert/js/assert.js"></script>
<script src="../../tandem/js/PhetioIDUtils.js"></script>
<script src="../../sherpa/lib/jquery-2.1.0.js"></script>
<script src="../../sherpa/lib/lodash-4.17.4.min.js"></script>
<script src="../../sherpa/lib/himalaya-0.2.7.js"></script>
<script src="../../sherpa/lib/he-1.1.1.js"></script>
<script src="../../query-string-machine/js/QueryStringMachine.js"></script>
<script src="../../scenery/build/scenery.min.js"></script>
<script src="../js/local-report.js"></script>
</body>
</html>
161 changes: 161 additions & 0 deletions js/local-report.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright 2020, University of Colorado Boulder

/**
* Displays a self-updating report of continuous test results
*
* @author Jonathan Olson <[email protected]>
*/

'use strict';

window.assertions.enableAssert();

const options = QueryStringMachine.getAll( {
server: {
type: 'string',

// Origin for our server (ignoring current port), so that we don't require localhost
defaultValue: window.location.protocol + '//' + window.location.hostname
}
} );

const passColor = new scenery.Color( 60, 255, 60 );
const failColor = new scenery.Color( 255, 90, 90 );
const mixedColor = new scenery.Color( 255,210,80 );
const unincludedColor = new scenery.Color( 128, 128, 128 );
const untestedColor = new scenery.Color( 240, 240, 240 );

// Property.<string>
const snapshotStatusProperty = new axon.Property( 'unknown status' );

snapshotStatusProperty.lazyLink( status => console.log( `Status: ${status}` ) );

(function snapshotStatusLoop() {
const req = new XMLHttpRequest();
req.onload = function() {
setTimeout( snapshotStatusLoop, 1000 );
snapshotStatusProperty.value = JSON.parse( req.responseText ).status;
};
req.onerror = function() {
setTimeout( snapshotStatusLoop, 1000 );
snapshotStatusProperty.value = 'Could not contact server';
};
req.open( 'get', options.server + '/aquaserver/snapshot-status', true );
req.send();
})();

// Property.<Object|null>
const reportProperty = new axon.Property( {
snapshots: [],
testNames: []
} );

(function reportLoop() {
const req = new XMLHttpRequest();
req.onload = function() {
setTimeout( reportLoop, 20000 );
reportProperty.value = JSON.parse( req.responseText );
};
req.onerror = function() {
setTimeout( reportLoop, 20000 );
reportProperty.reset();
};
req.open( 'get', options.server + '/aquaserver/report', true );
req.send();
})();

const rootNode = new scenery.Node();
const display = new scenery.Display( rootNode );

document.body.appendChild( display.domElement );

display.initializeEvents();
display.updateOnRequestAnimationFrame( dt => {

} );

const statusNode = new scenery.Text( '', { fontSize: 14 } );
snapshotStatusProperty.link( status => {
statusNode.text = status;
} );

const reportNode = new scenery.Node();
reportProperty.link( report => {
const testLabels = report.testNames.map( names => new scenery.Text( names.join( ' : ' ), { fontSize: 12 } ) );

const snapshotLabels = report.snapshots.map( snapshot => new scenery.VBox( {
spacing: 2,
children: [
...new Date( 1586988043041 ).toLocaleString().replace( ',', '' ).replace( ' AM', 'am' ).replace( ' PM', 'pm' ).split( ' ' ).map( str => new scenery.Text( str, { fontSize: 10 } ) )
]
} ) );

const maxTestLabelWidth = _.max( testLabels.map( node => node.width ) );
const maxTestLabelHeight = _.max( testLabels.map( node => node.height ) );
const maxSnapshotLabelWidth = _.max( snapshotLabels.map( node => node.width ) );
const maxSnapshotLabelHeight = _.max( snapshotLabels.map( node => node.height ) );

const snapshotsTestNodes = _.flatten( report.snapshots.map( ( snapshot, i ) => {
return report.testNames.map( ( names, j ) => {
const test = _.find( snapshot.tests, test => _.isEqual( names, test.names ) );

const background = new scenery.Rectangle( 0, 0, maxSnapshotLabelWidth, maxTestLabelHeight, {
x: maxTestLabelWidth + i * maxSnapshotLabelWidth,
y: maxSnapshotLabelHeight + j * maxTestLabelHeight
} );

if ( test ) {
if ( test.passCount > 0 && test.failCount === 0 ) {
background.fill = passColor;
}
else if ( test.passCount === 0 && test.failCount > 0 ) {
background.fill = failColor;
}
else if ( test.passCount === 0 && test.failCount === 0 ) {
background.fill = untestedColor;
}
else {
background.fill = mixedColor;
}
}
else {
background.fill = unincludedColor;
}

return background;
} );
} ) );

testLabels.forEach( ( label, i ) => {
label.left = 0;
label.top = i * maxTestLabelHeight + maxSnapshotLabelHeight;
} );
snapshotLabels.forEach( ( label, i ) => {
label.top = 0;
label.left = maxTestLabelWidth + i * maxSnapshotLabelWidth;
} );

reportNode.children = [
...testLabels,
...snapshotLabels,
...snapshotsTestNodes
];
display.width = Math.ceil( rootNode.width );
display.height = Math.ceil( rootNode.height );
} );




rootNode.addChild( new scenery.VBox( {
spacing: 10,
align: 'left',
children: [ statusNode, reportNode ]
} ) );







53 changes: 47 additions & 6 deletions js/local-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const jsonHeaders = {
// {Array.<Snapshot>} All of our snapshots
const snapshots = [];

let reportJSON = '{}';

// root of your GitHub working copy, relative to the name of the directory that the currently-executing script resides in
const rootDir = path.normalize( __dirname + '/../../' ); // eslint-disable-line no-undef

Expand Down Expand Up @@ -77,7 +79,7 @@ const deliverTest = ( res, test ) => {
const object = test.getObjectForBrowser();
test.count++;

winston.info( `Delivering test: ${object.snapshotName} ${object.url}` );
winston.info( `[SEND] ${object.snapshotName} ${test.names.join( ',' )} ${object.url}` );
res.writeHead( 200, jsonHeaders );
res.end( JSON.stringify( object ) );
};
Expand Down Expand Up @@ -188,11 +190,9 @@ const startServer = () => {
status: snapshotStatus
} ) );
}
if ( requestInfo.pathname === '/aquaserver/test-status' ) {
if ( requestInfo.pathname === '/aquaserver/report' ) {
res.writeHead( 200, jsonHeaders );
res.end( JSON.stringify( {
zeroCounts: snapshots[ 0 ] ? snapshots[ 0 ].browserTests.filter( test => test.count === 0 ).length : 0
} ) );
res.end( reportJSON );
}
}
catch ( e ) {
Expand Down Expand Up @@ -333,6 +333,47 @@ const localTaskCycle = async () => {
}
};

const reportTaskCycle = async () => {
while ( true ) { // eslint-disable-line
try {
const report = {
snapshots: snapshots.map( snapshot => {
return {
timestamp: snapshot.timestamp,
shas: snapshot.shas,
tests: snapshot.tests.map( test => {
const passedTestResults = test.results.filter( testResult => testResult.passed );
const failedTestResults = test.results.filter( testResult => !testResult.passed );
return {
names: test.names,
passCount: passedTestResults.length,
failCount: failedTestResults.length,
passMessages: _.uniq( passedTestResults.map( testResult => testResult.message ).filter( _.identity ) ),
failMessages: _.uniq( failedTestResults.map( testResult => testResult.message ).filter( _.identity ) )
};
} )
};
} ),
testNames: _.sortBy( _.uniqWith( _.flatten( snapshots.map( snapshot => snapshot.tests.map( test => test.names ) ) ), _.isEqual ), names => names.toString() )
};

reportJSON = JSON.stringify( report );
}
catch ( e ) {
winston.error( e );
}

await sleep( 5000 );
}
};

const numberLocal = Number.parseInt( process.argv[ 2 ], 10 ) || 1;

startServer();
cycleSnapshots();
localTaskCycle(); // TODO: how many to run?
reportTaskCycle();

winston.info( `Launching ${numberLocal} local tasks` );
_.range( 0, numberLocal ).forEach( () => {
localTaskCycle();
} );
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
"globals": {
"aqua": false,
"XMLHttpRequest": false,
"Hashes": false
"Hashes": false,
"phetCore": false,
"axon": false,
"dot": false,
"kite": false,
"scenery": false
}
}
}

0 comments on commit 9285a2c

Please sign in to comment.