Skip to content

Commit

Permalink
add some test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
striezel committed Nov 30, 2023
1 parent 423632f commit e24fd0d
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 2 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ jobs:
node-version: ${{ matrix.node-version }}
- name: Display version information
run: node --version && npm --version
- run: cd "$GITHUB_WORKSPACE"/export-server && npm install
- name: Install NPM packages
run: cd "$GITHUB_WORKSPACE"/export-server && npm install
- name: Tests
run: cd "$GITHUB_WORKSPACE"/export-server && ./test.sh
3 changes: 2 additions & 1 deletion export-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
},
"main": "server.js",
"scripts": {
"start": "node server.js"
"start": "node server.js",
"test": "./test.sh"
},
"keywords": [
"Plotly.js",
Expand Down
30 changes: 30 additions & 0 deletions export-server/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh

# Start the server.
npm run start &
# Give server some time to start completely.
sleep 3
SERVER_PID=$(pgrep node)
echo "Server process id is $SERVER_PID."

# Run actual tests.
node --test
EXIT_CODE=$?

# Stop / kill server process.
kill $SERVER_PID
if [ $? -ne 0 ]
then
kill -9 $SERVER_PID
fi

sleep 1

if [ $EXIT_CODE -eq 0 ]
then
echo Tests were successful.
exit 0
else
echo Tests have failed.
exit 1
fi
307 changes: 307 additions & 0 deletions export-server/tests/server.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
const assert = require('node:assert');
const { spawn, spawnSync } = require('node:child_process');
const http = require('node:http');
const { after, before, describe, it } = require('node:test');

describe('server', () => {
describe('request to non-root URL is not acceptable', () => {
it('HTTP status code 404 when another URL is requested', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST',
path: '/foo.svg'
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(404, response.statusCode);
});
});
});

describe('only POST method is allowed', () => {
it('HTTP status code 405 when DELETE is used', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'DELETE',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(405, response.statusCode);
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});

it('HTTP status code 405 when GET is used', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'GET',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(405, response.statusCode);
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});

it('HTTP status code 405 when HEAD is used', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'HEAD',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(405, response.statusCode);
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});

it('HTTP status code 405 when PATCH is used', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'PATCH',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(405, response.statusCode);
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});

it('HTTP status code 405 when PUT is used', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'PUT',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(405, response.statusCode);
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});

it('HTTP status code 405 when TRACE is used', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'TRACE',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
assert.strictEqual(405, response.statusCode);
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});
});

describe('query available methods via OPTIONS', () => {
it('HTTP status code 204 and Allow header for OPTIONS', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'OPTIONS',
};

const req = http.request(options);
req.end();

req.on('response', (response) => {
// 204: no content
assert.strictEqual(204, response.statusCode);
// Response shall contain header "Allow: POST".
assert.ok(response.headers['allow']);
assert.strictEqual(response.headers['allow'], 'POST');
});
});
});

describe('large payload is rejected', () => {
it('HTTP status code 413 when request is too large', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST',
};

const req = http.request(options);
const payload = { long: 'abcdefghij'.repeat(500000) };
req.write(JSON.stringify(payload));
req.end();

req.on('response', (response) => {
assert.strictEqual(413, response.statusCode);
});
});
});

describe('malformed JSON is rejected', () => {
it('HTTP status code 400 when request contains invalid JSON', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST',
};

const req = http.request(options);
const payload = '{ "foo": "bar", "baz": ';
req.write(payload);
req.end();

req.on('response', (response) => {
assert.strictEqual(400, response.statusCode);
});
});
});

describe('image generation requests', () => {
it('request with example data is successful', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST'
};

const req = http.request(options);
const payload = '{ "x": ["2013-10-04 22:23:00", "2013-11-04 22:23:00", "2013-12-04 22:23:00"], "y": [1, 3, 6], "type": "scatter" }';
req.write(payload);
req.end();

req.on('response', (response) => {
assert.strictEqual(200, response.statusCode);
let body = '';
response.on('data', (chunk) => {
body += chunk;
});
response.on('end', () => {
assert.ok(body.startsWith('<svg'));
assert.ok(body.endsWith('</svg>'));
assert.ok(body.indexOf('width="700"') > 0);
assert.ok(body.indexOf('height="400"') > 0);
});
});
});

it('request with different image width', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST',
headers: {
'X-Image-Width': '751'
}
};

const req = http.request(options);
const payload = '{ "x": ["2013-10-04 22:23:00", "2013-11-04 22:23:00", "2013-12-04 22:23:00"], "y": [1, 3, 6], "type": "scatter" }';
req.write(payload);
req.end();

req.on('response', (response) => {
assert.strictEqual(200, response.statusCode);
let body = '';
response.on('data', (chunk) => {
body += chunk;
});
response.on('end', () => {
assert.ok(body.startsWith('<svg'));
assert.ok(body.endsWith('</svg>'));
assert.ok(body.indexOf('width="751"') > 0);
assert.ok(body.indexOf('height="400"') > 0);
});
});
});

it('request with different image height', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST',
headers: {
'X-Image-Height': '432'
}
};

const req = http.request(options);
const payload = '{ "x": ["2013-10-04 22:23:00", "2013-11-04 22:23:00", "2013-12-04 22:23:00"], "y": [1, 3, 6], "type": "scatter" }';
req.write(payload);
req.end();

req.on('response', (response) => {
assert.strictEqual(200, response.statusCode);
let body = '';
response.on('data', (chunk) => {
body += chunk;
});
response.on('end', () => {
assert.ok(body.startsWith('<svg'));
assert.ok(body.endsWith('</svg>'));
assert.ok(body.indexOf('width="700"') > 0);
assert.ok(body.indexOf('height="432"') > 0);
});
});
});

it('request with different image width and height', () => {
const options = {
port: 3000,
host: 'localhost',
method: 'POST',
headers: {
'X-Image-Width': '765',
'X-Image-Height': '456'
}
};

const req = http.request(options);
const payload = '{ "x": ["2013-10-04 22:23:00", "2013-11-04 22:23:00", "2013-12-04 22:23:00"], "y": [1, 3, 6], "type": "scatter" }';
req.write(payload);
req.end();

req.on('response', (response) => {
assert.strictEqual(200, response.statusCode);
let body = '';
response.on('data', (chunk) => {
body += chunk;
});
response.on('end', () => {
assert.ok(body.startsWith('<svg'));
assert.ok(body.endsWith('</svg>'));
assert.ok(body.indexOf('width="765"') > 0);
assert.ok(body.indexOf('height="456"') > 0);
});
});
});
});
});

0 comments on commit e24fd0d

Please sign in to comment.