file-timestamp-stream
Advanced tools
Comparing version 0.0.2 to 0.0.3
# Changelog | ||
## v0.0.3 2017-02-19 | ||
* Upgraded tap-given | ||
## v0.0.2 2017-02-17 | ||
* Minor optimizations and better error handling | ||
* BDD tests | ||
* Relicensed to MIT | ||
@@ -7,0 +12,0 @@ |
{ | ||
"name": "file-timestamp-stream", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "Writing stream with file rotating based on timestamp", | ||
@@ -21,2 +21,5 @@ "main": "lib/file-timestamp-stream.js", | ||
"homepage": "http://github.com/dex4er/js-file-timestamp-stream", | ||
"engines": { | ||
"node": ">=4.0.0" | ||
}, | ||
"dependencies": { | ||
@@ -26,6 +29,8 @@ "ultra-strftime": "^1.0.2" | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"nyc": "^10.1.2", | ||
"sleep-promise": "^2.0.0", | ||
"standard": "^8.6.0", | ||
"tap": "^10.1.1" | ||
"tap": "^10.2.0", | ||
"tap-given": "^0.2.0" | ||
}, | ||
@@ -39,7 +44,4 @@ "scripts": { | ||
"nyc": { | ||
"exclude": [ | ||
"mock", | ||
"test" | ||
] | ||
"exclude": [] | ||
} | ||
} |
@@ -6,3 +6,2 @@ 'use strict' | ||
const sleep = require('sleep-promise') | ||
const t = require('tap') | ||
@@ -12,196 +11,296 @@ const FileTimestampStream = require('../lib/file-timestamp-stream') | ||
const TIMEOUT = 2000 | ||
/* global Feature, Scenario, Given, When, Then */ | ||
const t = require('tap') | ||
require('tap-given')(t) | ||
require('chai').should() | ||
t.plan(8) | ||
Feature('Test file-timestamp-stream module', () => { | ||
Scenario('Write lines to different files', function () { | ||
Given('stream created with %S specifier', () => { | ||
this.wstream = new FileTimestampStream({ | ||
path: '%Y-%m-%dT%H:%M:%S.log', | ||
flags: 'x', | ||
fs: mockFs | ||
}) | ||
t.test('Write lines to different files', {timeout: TIMEOUT}, t => { | ||
let filename1, filename2 | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
t.plan(6) | ||
When('I write first part of content to stream', () => { | ||
this.wstream.write(Buffer.from('content1\r\n')) | ||
}) | ||
const wstream = new FileTimestampStream({ | ||
path: '%Y-%m-%dT%H:%M:%S.log', | ||
flags: 'x', | ||
fs: mockFs | ||
}) | ||
Then('file contains first part of content', () => { | ||
this.wstream.wstream.content.toString().should.equal('content1\r\n') | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
Then('stream has defined filename', () => { | ||
this.filename1 = this.wstream.wstream.filename | ||
this.filename1.should.be.ok | ||
}) | ||
wstream.write(Buffer.from('content1\r\n')) | ||
t.equals(wstream.wstream.content.toString(), 'content1\r\n', 'content is correct') | ||
Then('stream has correct flags', () => { | ||
this.wstream.wstream.options.flags.should.equal('x') | ||
}) | ||
filename1 = wstream.wstream.filename | ||
t.equals(wstream.wstream.options.flags, 'x', 'flags for new file are correct') | ||
When('I wait more than one second', () => { | ||
return sleep(1100) | ||
}) | ||
sleep(1100) | ||
.then(() => { | ||
wstream.write(Buffer.from('content2\r\n')) | ||
t.equals(wstream.wstream.content.toString(), 'content2\r\n', 'content is correct') | ||
When('I write second part of content to the same stream', () => { | ||
this.wstream.write(Buffer.from('content2\r\n')) | ||
}) | ||
filename2 = wstream.wstream.filename | ||
t.equals(wstream.wstream.options.flags, 'x', 'flags for new file are correct') | ||
t.notEqual(filename2, filename1, 'filenames are different') | ||
Then('file contains second part of content', () => { | ||
this.wstream.wstream.content.toString().should.equal('content2\r\n') | ||
}) | ||
t.end() | ||
Then('stream has defined another filename', () => { | ||
this.filename2 = this.wstream.wstream.filename | ||
this.filename2.should.be.ok | ||
}) | ||
Then('stream has correct flags', () => { | ||
this.wstream.wstream.options.flags.should.equal('x') | ||
}) | ||
Then('stream has new filename different than previous', () => { | ||
this.filename2.should.not.equal(this.filename1) | ||
}) | ||
}) | ||
.catch(err => { | ||
t.threw(err) | ||
t.end() | ||
}) | ||
}) | ||
t.test('Custom filename generator', {timeout: TIMEOUT}, t => { | ||
t.plan(8) | ||
Scenario('Custom filename generator', function () { | ||
Given('counter', () => { | ||
this.n = 0 | ||
}) | ||
let n = 0 | ||
Given('stream created with custom filename generator which uses counter', () => { | ||
this.wstream = new FileTimestampStream({ | ||
newFilename: () => { | ||
return Math.floor(this.n++ / 2) + '.log' | ||
}, | ||
fs: mockFs | ||
}) | ||
const wstream = new FileTimestampStream({ | ||
newFilename: () => { | ||
return Math.floor(n++ / 2) + '.log' | ||
}, | ||
fs: mockFs | ||
}) | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
When('I write fist part of content to stream', () => { | ||
this.wstream.write(Buffer.from('content1\r\n')) | ||
}) | ||
wstream.write(Buffer.from('content1\r\n')) | ||
t.equals(wstream.wstream.content.toString(), 'content1\r\n', 'content is correct') | ||
t.equals(wstream.wstream.filename, '0.log', 'filename is correct') | ||
Then('file contains first part of content', () => { | ||
this.wstream.wstream.content.toString().should.equal('content1\r\n') | ||
}) | ||
wstream.write(Buffer.from('content2\r\n')) | ||
t.equals(wstream.wstream.content.toString(), 'content1\r\ncontent2\r\n', 'content is correct') | ||
t.equals(wstream.wstream.filename, '0.log', 'filename is correct') | ||
Then('stream has correct filename', () => { | ||
this.wstream.wstream.filename.should.equal('0.log') | ||
}) | ||
wstream.write(Buffer.from('content3\r\n'), () => { | ||
t.pass('callback was called') | ||
t.equals(wstream.wstream.content.toString(), 'content3\r\n', 'content is correct') | ||
t.equals(wstream.wstream.filename, '1.log', 'filename is correct') | ||
When('I write second part of content to stream', () => { | ||
this.wstream.write(Buffer.from('content2\r\n')) | ||
}) | ||
t.end() | ||
}) | ||
}) | ||
Then('file contains both parts of content', () => { | ||
this.wstream.wstream.content.toString().should.equal('content1\r\ncontent2\r\n') | ||
}) | ||
t.test('_writev', {timeout: TIMEOUT}, t => { | ||
t.plan(8) | ||
Then('stream has unchanged filename', () => { | ||
this.wstream.wstream.filename.should.equal('0.log') | ||
}) | ||
let n = 0 | ||
When('I write third part of content to stream (this time with callback)', done => { | ||
this.wstream.write(Buffer.from('content3\r\n'), done) | ||
}) | ||
const wstream = new FileTimestampStream({ | ||
newFilename: () => { | ||
return Math.floor(n++ / 2) + '.log' | ||
}, | ||
fs: mockFs | ||
Then('file contains only third part of content', () => { | ||
this.wstream.wstream.content.toString().should.equal('content3\r\n') | ||
}) | ||
Then('stream has new filename', () => { | ||
this.wstream.wstream.filename.should.equal('1.log') | ||
}) | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
Scenario('Use _writev method directly', function () { | ||
Given('counter', () => { | ||
this.n = 0 | ||
}) | ||
wstream._writev([Buffer.from('A'), Buffer.from('B'), Buffer.from('C')]) | ||
t.equals(wstream.wstream.content.toString(), 'ABC', 'content is correct') | ||
t.equals(wstream.wstream.filename, '0.log', 'filename is correct') | ||
Given('stream created with custom filename generator which uses counter', () => { | ||
this.wstream = new FileTimestampStream({ | ||
newFilename: () => { | ||
return Math.floor(this.n++ / 2) + '.log' | ||
}, | ||
fs: mockFs | ||
}) | ||
wstream._writev([Buffer.from('D'), Buffer.from('E'), Buffer.from('F')]) | ||
t.equals(wstream.wstream.content.toString(), 'ABCDEF', 'content is correct') | ||
t.equals(wstream.wstream.filename, '0.log', 'filename is correct') | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
wstream._writev([Buffer.from('G'), Buffer.from('H'), Buffer.from('I')], () => { | ||
t.pass('callback was called') | ||
When('I write first 3 bytes to stream', () => { | ||
this.wstream._writev([Buffer.from('A'), Buffer.from('B'), Buffer.from('C')]) | ||
}) | ||
t.equals(wstream.wstream.content.toString(), 'GHI', 'content is correct') | ||
t.equals(wstream.wstream.filename, '1.log', 'filename is correct') | ||
Then('file contains first 3 bytes', () => { | ||
this.wstream.wstream.content.toString().should.equal('ABC') | ||
}) | ||
t.end() | ||
}) | ||
}) | ||
Then('stream has unchanged filename', () => { | ||
this.wstream.wstream.filename.should.equal('0.log') | ||
}) | ||
t.test('Default options', {timeout: TIMEOUT}, t => { | ||
t.plan(4) | ||
When('I write next 3 bytes to stream', () => { | ||
this.wstream._writev([Buffer.from('D'), Buffer.from('E'), Buffer.from('F')]) | ||
}) | ||
const wstream = new FileTimestampStream() | ||
wstream.fs = mockFs | ||
Then('file contains first 6 bytes', () => { | ||
this.wstream.wstream.content.toString().should.equal('ABCDEF') | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
Then('stream has unchanged name', () => { | ||
this.wstream.wstream.filename.should.equal('0.log') | ||
}) | ||
wstream.write(Buffer.from('content1\r\n')) | ||
When('I write last 3 bytes to stream (this time with callback)', done => { | ||
this.wstream._writev([Buffer.from('G'), Buffer.from('H'), Buffer.from('I')], done) | ||
}) | ||
t.equals(wstream.wstream.content.toString(), 'content1\r\n', 'content is correct') | ||
t.equals(wstream.wstream.filename, 'out.log', 'filename is correct') | ||
t.equals(wstream.wstream.options.flags, 'a', 'flags for new file are correct') | ||
Then('file contains last 3 bytes', () => { | ||
this.wstream.wstream.content.toString().should.equal('GHI') | ||
}) | ||
t.end() | ||
}) | ||
Then('stream has new filename', () => { | ||
this.wstream.wstream.filename.should.equal('1.log') | ||
}) | ||
}) | ||
t.test('Open error for _write', {timeout: TIMEOUT}, t => { | ||
t.plan(3) | ||
Scenario('Default options', function () { | ||
Given('stream created with no options but overriden fs property', () => { | ||
this.wstream = new FileTimestampStream() | ||
this.wstream.fs = mockFs | ||
const wstream = new FileTimestampStream({ | ||
path: 'badopen', | ||
fs: mockFs | ||
}) | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
When('I write fist part of content to stream', () => { | ||
this.wstream.write(Buffer.from('content1\r\n')) | ||
}) | ||
wstream.on('error', e => { | ||
t.pass('error signal was received') | ||
t.equal(e.message, 'badopen', 'error is correct') | ||
t.end() | ||
}) | ||
wstream.write(Buffer.from('nevermind')) | ||
}) | ||
Then('file contains first part of content', () => { | ||
this.wstream.wstream.content.toString().should.equal('content1\r\n') | ||
}) | ||
t.test('Write error for _write', {timeout: TIMEOUT}, t => { | ||
t.plan(3) | ||
Then('stream has the default filename', () => { | ||
this.wstream.wstream.filename.should.equal('out.log') | ||
}) | ||
const wstream = new FileTimestampStream({ | ||
path: 'badwrite', | ||
fs: mockFs | ||
Then('stream has the default flags', () => { | ||
this.wstream.wstream.options.flags.should.equal('a') | ||
}) | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
Scenario('Open error for _write', function () { | ||
Given('stream with an error on open file', () => { | ||
this.wstream = new FileTimestampStream({ | ||
path: 'badopen', | ||
fs: mockFs | ||
}) | ||
wstream.on('error', e => { | ||
t.pass('callback was called') | ||
t.equal(e.message, 'badwrite', 'error is correct') | ||
t.end() | ||
}) | ||
wstream.write(Buffer.from('nevermind')) | ||
}) | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
t.test('Open error for _writev', {timeout: TIMEOUT}, t => { | ||
t.plan(3) | ||
Given('subscription on error event', () => { | ||
this.wstream.on('error', e => { | ||
this.error = e | ||
}) | ||
}) | ||
const wstream = new FileTimestampStream({ | ||
path: 'badopen', | ||
fs: mockFs | ||
When('I write something to stream', () => { | ||
this.wstream.write(Buffer.from('something')) | ||
}) | ||
Then("an error was because can't open file", () => { | ||
this.error.should.have.property('message').that.equals('badopen') | ||
}) | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
Scenario('Write error for _write', function () { | ||
Given('stream with an error on write to file', () => { | ||
this.wstream = new FileTimestampStream({ | ||
path: 'badwrite', | ||
fs: mockFs | ||
}) | ||
wstream._writev([Buffer.from('nevermind')], e => { | ||
if (e) { | ||
t.pass('callback was received') | ||
t.equal(e.message, 'badopen', 'error is correct') | ||
t.end() | ||
} | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
Given('subscription on error event', () => { | ||
this.wstream.on('error', e => { | ||
this.error = e | ||
}) | ||
}) | ||
When('I write something to stream', () => { | ||
this.wstream.write(Buffer.from('something')) | ||
}) | ||
Then("an error was because can't write to file", () => { | ||
this.error.should.have.property('message').that.equals('badwrite') | ||
}) | ||
}) | ||
}) | ||
t.test('Write error for _writev', {timeout: TIMEOUT}, t => { | ||
t.plan(3) | ||
Scenario('Open error for _writev', function () { | ||
Given('stream with an error on open file', () => { | ||
this.wstream = new FileTimestampStream({ | ||
path: 'badopen', | ||
fs: mockFs | ||
}) | ||
const wstream = new FileTimestampStream({ | ||
path: 'badwrite', | ||
fs: mockFs | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
Given('callback for _writev', () => { | ||
this.callback = e => { | ||
if (e) { | ||
this.error = e | ||
} | ||
} | ||
}) | ||
When('I write some bytes to stream', () => { | ||
this.wstream._writev([Buffer.from('A'), Buffer.from('B'), Buffer.from('C')], this.callback) | ||
}) | ||
Then("an error was because can't open file", () => { | ||
this.error.should.have.property('message').that.equals('badopen') | ||
}) | ||
}) | ||
t.type(wstream.pipe, 'function', 'wstream is stream') | ||
Scenario('Write error for _writev', function () { | ||
Given('stream with an error on write to file', () => { | ||
this.wstream = new FileTimestampStream({ | ||
path: 'badwrite', | ||
fs: mockFs | ||
}) | ||
wstream._writev([Buffer.from('')], e => { | ||
if (e) { | ||
t.pass('callback was called') | ||
t.equal(e.message, 'badwrite', 'error is correct') | ||
t.end() | ||
} | ||
this.wstream.should.have.property('pipe').that.is.a('function') | ||
}) | ||
Given('callback for _writev', () => { | ||
this.callback = e => { | ||
if (e) { | ||
this.error = e | ||
} | ||
} | ||
}) | ||
When('I write some bytes to stream', () => { | ||
this.wstream._writev([Buffer.from('A'), Buffer.from('B'), Buffer.from('C')], this.callback) | ||
}) | ||
Then("an error was because can't write to file", () => { | ||
this.error.should.have.property('message').that.equals('badwrite') | ||
}) | ||
}) | ||
}) | ||
t.end() |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15975
336
6
1