diff --git a/.release b/.release
index aeba3f7..f18c599 160000
--- a/.release
+++ b/.release
@@ -1 +1 @@
-Subproject commit aeba3f7c18d0d1e2a54d647b03a0e3c4378c10ae
+Subproject commit f18c599497f7cb1c3b68e9555fb14e8075c4866b
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f16b42a..e7fa28d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
### Unreleased
-### [1.3.6] - 2024-04-09
+### [1.3.6] - 2024-04-14
+- transaction: sync with haraka/Haraka
+- connection: import more from haraka/Haraka/connection
+- test(conn): expect more connection properties
- doc(CONTRIBUTING): added
+- doc(README): added example setup
### [1.3.5] - 2024-04-07
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 9b85317..887121b 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,9 +1,8 @@
-
# Contributors
This handcrafted artisinal software is brought to you by:
-|
msimerson (60)|
kcberg (1)|
baudehlo (1)|
smfreegard (1)|
lnedry (1)|
-| :---: | :---: | :---: | :---: | :---: |
+|
msimerson (61) |
kcberg (1) |
baudehlo (1) |
smfreegard (1) |
lnedry (1) |
+| :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
this file is maintained by [.release](https://github.com/msimerson/.release)
diff --git a/README.md b/README.md
index 1201365..e52bf93 100644
--- a/README.md
+++ b/README.md
@@ -8,11 +8,30 @@
Fixtures for testing Haraka and plugins
-# Usage
+## Usage
-`const fixtures = require('haraka-test-fixtures');`
+```js
+const fixtures = require('haraka-test-fixtures')
+```
-# Exports the following fixture types:
+### A common pattern
+
+```js
+beforeEach(() => {
+ this.plugin = new fixtures.plugin('pluginName')
+
+ this.connection = fixtures.connection.createConnection()
+ this.connection.init_transaction()
+})
+
+describe('pluginName', () => {
+ it('registers', () => {
+ this.plugin.register()
+ })
+})
+```
+
+## Exports the following fixture types:
- connection
- line_socket
diff --git a/lib/connection.js b/lib/connection.js
index fc26c0b..2e2ecac 100644
--- a/lib/connection.js
+++ b/lib/connection.js
@@ -1,76 +1,256 @@
const config = require('haraka-config')
+const constants = require('haraka-constants')
const Notes = require('haraka-notes')
const ResultStore = require('haraka-results')
+const utils = require('haraka-utils')
const logger = require('./logger')
const transaction = require('./transaction')
-const cfg = config.get('smtp.ini', {
- booleans: [
- '+main.smtputf8',
- '+headers.add_received',
- '+headers.clean_auth_results',
- ],
-})
+const states = constants.connection.state
class Connection {
- constructor(client, server) {
+ constructor(client, server, cfg) {
this.client = client
this.server = server
- this.relaying = false
- this.local = {}
+ this.cfg = cfg
+
+ this.local = {
+ ip: null,
+ port: null,
+ host: 'haraka-test.example.com',
+ info: 'Haraka',
+ }
this.remote = {
ip: '127.0.0.1',
+ port: null,
+ host: null,
+ info: null,
+ closed: false,
+ is_private: false,
+ is_local: false,
+ }
+ this.hello = {
+ host: null,
+ verb: null,
+ }
+ this.tls = {
+ enabled: false,
+ advertised: false,
+ verified: false,
+ cipher: {},
}
- this.tls = {}
- this.hello = {}
+ this.proxy = {
+ allowed: false,
+ ip: null,
+ type: null,
+ timer: null,
+ }
+ this.set('tls', 'enabled', !!server.has_tls)
+
+ this.current_data = null
+ this.current_line = null
+ this.state = states.PAUSE
+ this.encoding = 'utf8'
+ this.prev_state = null
+ this.loop_code = null
+ this.loop_msg = null
+ this.uuid = utils.uuid()
this.notes = new Notes()
+ this.transaction = null
+ this.tran_count = 0
+ this.capabilities = null
+ this.ehlo_hello_message = 'Haraka Test is at your service.'
+ this.connection_close_message = 'closing test connection.'
+ this.banner_includes_uuid = true
+ this.deny_includes_uuid = true
+ this.early_talker = false
+ this.pipelining = false
+ this._relaying = false
+ this.esmtp = false
+ this.last_response = null
+ this.hooks_to_run = []
+ this.start_time = Date.now()
+ this.last_reject = ''
+ this.max_bytes = 0
+ this.max_mime_parts = 1000
+ this.totalbytes = 0
+ this.rcpt_count = {
+ accept: 0,
+ tempfail: 0,
+ reject: 0,
+ }
+ this.msg_count = {
+ accept: 0,
+ tempfail: 0,
+ reject: 0,
+ }
+ this.max_line_length = 512
+ this.max_data_line_length = 992
this.results = new ResultStore(this)
+ this.errors = 0
+ this.last_rcpt_msg = null
+ this.hook = null
+
logger.add_log_methods(this, 'mock-connection')
+ Connection.setupClient(this)
}
- auth_results(message) {}
- respond(code, msg, func) {
- return func()
- }
- init_transaction(done) {
- this.transaction = new transaction.createTransaction(null, cfg)
- this.transaction.results = new ResultStore(this)
- if (done) done()
+
+ static setupClient(self) {
+ if (Object.keys(self.client).length === 0) return
+ const ip = self.client.remoteAddress
+ if (!ip) {
+ self.logdebug('setupClient got no IP address for this connection!')
+ self.client.destroy()
+ return
+ }
+
+ const local_addr = self.server.address()
+ self.set(
+ 'local',
+ 'ip',
+ ipaddr.process(self.client.localAddress || local_addr.address).toString(),
+ )
+ self.set('local', 'port', self.client.localPort || local_addr.port)
+ self.results.add({ name: 'local' }, self.local)
+
+ self.set('remote', 'ip', ipaddr.process(ip).toString())
+ self.set('remote', 'port', self.client.remotePort)
+ self.results.add({ name: 'remote' }, self.remote)
+
+ self.lognotice('connect', {
+ ip: self.remote.ip,
+ port: self.remote.port,
+ local_ip: self.local.ip,
+ local_port: self.local.port,
+ })
+
+ if (!self.client.on) return
+
+ const log_data = { ip: self.remote.ip }
+ if (self.remote.host) log_data.host = self.remote.host
+
+ self.client.on('end', () => {
+ if (self.state >= states.DISCONNECTING) return
+ self.remote.closed = true
+ self.loginfo('client half closed connection', log_data)
+ self.fail()
+ })
+
+ self.client.on('close', (has_error) => {
+ if (self.state >= states.DISCONNECTING) return
+ self.remote.closed = true
+ self.loginfo('client dropped connection', log_data)
+ self.fail()
+ })
+
+ self.client.on('error', (err) => {
+ if (self.state >= states.DISCONNECTING) return
+ self.loginfo(`client connection error: ${err}`, log_data)
+ self.fail()
+ })
+
+ self.client.on('timeout', () => {
+ // FIN has sent, when timeout just destroy socket
+ if (self.state >= states.DISCONNECTED) {
+ self.client.destroy()
+ self.loginfo(`timeout, destroy socket (state:${self.state})`)
+ return
+ }
+ if (self.state >= states.DISCONNECTING) return
+ self.respond(421, 'timeout', () => {
+ self.fail('client connection timed out', log_data)
+ })
+ })
+
+ self.client.on('data', (data) => {
+ self.process_data(data)
+ })
+
+ plugins.run_hooks('connect_init', self)
}
- reset_transaction(done) {
- if (this.transaction && this.transaction.resetting === false) {
- this.transaction.resetting = true
- } else {
- this.transaction = null
+
+ setTLS(obj) {
+ this.set('hello', 'host', undefined)
+ this.set('tls', 'enabled', true)
+ for (const t of ['cipher', 'verified', 'verifyError', 'peerCertificate']) {
+ if (obj[t] === undefined) return
+ this.set('tls', t, obj[t])
}
- if (done) done()
}
+
set(prop_str, val) {
if (arguments.length === 3) {
prop_str = `${arguments[0]}.${arguments[1]}`
val = arguments[2]
}
- const segments = prop_str.split('.')
- let dest = this
- while (segments.length > 1) {
- if (!dest[segments[0]]) dest[segments[0]] = {}
- dest = dest[segments.shift()]
+ const path_parts = prop_str.split('.')
+ let loc = this
+ for (let i = 0; i < path_parts.length; i++) {
+ const part = path_parts[i]
+ if (part === '__proto__' || part === 'constructor') continue
+
+ // while another part remains
+ if (i < path_parts.length - 1) {
+ if (loc[part] === undefined) loc[part] = {} // initialize
+ loc = loc[part] // descend
+ continue
+ }
+
+ // last part, so assign the value
+ loc[part] = val
}
- dest[segments[0]] = val
}
+
get(prop_str) {
return prop_str.split('.').reduce((prev, curr) => {
return prev ? prev[curr] : undefined
}, this)
}
+
+ set relaying(val) {
+ if (this.transaction) {
+ this.transaction._relaying = val
+ } else {
+ this._relaying = val
+ }
+ }
+ get relaying() {
+ if (this.transaction && '_relaying' in this.transaction)
+ return this.transaction._relaying
+ return this._relaying
+ }
+ auth_results(message) {}
+ respond(code, msg, func) {
+ return func()
+ }
+ init_transaction(done) {
+ this.transaction = new transaction.createTransaction(null, this.cfg)
+ this.transaction.results = new ResultStore(this)
+ if (done) done()
+ }
+ reset_transaction(done) {
+ if (this.transaction && this.transaction.resetting === false) {
+ this.transaction.resetting = true
+ } else {
+ this.transaction = null
+ }
+ if (done) done()
+ }
}
exports.Connection = Connection
-exports.createConnection = function (client, server) {
- if (typeof client === 'undefined') client = {}
- if (typeof server === 'undefined') server = {}
-
- return new Connection(client, server)
+exports.createConnection = function (client = {}, server = {}, cfg = {}) {
+ if (!cfg || Object.keys(cfg).length === 0) {
+ cfg = config.get('smtp.ini', {
+ booleans: [
+ '+main.smtputf8',
+ '+headers.add_received',
+ '+headers.clean_auth_results',
+ ],
+ })
+ }
+ return new Connection(client, server, cfg)
}
diff --git a/lib/transaction.js b/lib/transaction.js
index b702afc..fdc3aeb 100644
--- a/lib/transaction.js
+++ b/lib/transaction.js
@@ -1,7 +1,9 @@
// A mock SMTP Transaction
+const util = require('util')
+
const Notes = require('haraka-notes')
-const ResultStore = require('haraka-results')
+const utils = require('haraka-utils')
const message = require('haraka-email-message')
const logger = require('./logger')
@@ -42,37 +44,107 @@ class Transaction {
this.data_post_delay = 0
this.encoding = 'utf8'
this.mime_part_count = 0
- this.results = new ResultStore(this)
- logger.add_log_methods(this, 'mock-connection')
}
ensure_body() {
if (this.body) return
this.body = new message.Body(this.header)
- this.attachment_start_hooks.forEach((h) => {
- this.body.on('attachment_start', h)
- })
+ for (const hook of this.attachment_start_hooks) {
+ this.body.on('attachment_start', hook)
+ }
+
if (this.banner) this.body.set_banner(this.banner)
- this.body_filters.forEach((o) => {
+ for (const o of this.body_filters) {
this.body.add_filter((ct, enc, buf) => {
- if (
- (o.ct_match instanceof RegExp && o.ct_match.test(ct.toLowerCase())) ||
+ const re_match =
+ util.types.isRegExp(o.ct_match) && o.ct_match.test(ct.toLowerCase())
+ const ct_begins =
ct.toLowerCase().indexOf(String(o.ct_match).toLowerCase()) === 0
- ) {
- return o.filter(ct, enc, buf)
- }
+ if (re_match || ct_begins) return o.filter(ct, enc, buf)
})
- })
+ }
+ }
+
+ // Removes the CR of a CRLF newline at the end of the buffer.
+ remove_final_cr(data) {
+ if (data.length < 2) return data
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data)
+
+ if (data[data.length - 2] === 0x0d && data[data.length - 1] === 0x0a) {
+ data[data.length - 2] = 0x0a
+ return data.slice(0, data.length - 1)
+ }
+ return data
+ }
+
+ // Duplicates any '.' chars at the beginning of a line (dot-stuffing) and
+ // ensures all newlines are CRLF.
+ add_dot_stuffing_and_ensure_crlf_newlines(data) {
+ if (!data.length) return data
+ if (!Buffer.isBuffer(data)) data = Buffer.from(data)
+
+ // Make a new buffer big enough to hold two bytes for every one input
+ // byte. At most, we add one extra character per input byte, so this
+ // is always big enough. We allocate it "unsafe" (i.e. no memset) for
+ // speed because we're about to fill it with data, and the remainder of
+ // the space we don't fill will be sliced away before we return this.
+ const output = Buffer.allocUnsafe(data.length * 2)
+ let output_pos = 0
+
+ let input_pos = 0
+ let next_dot = data.indexOf(0x2e)
+ let next_lf = data.indexOf(0x0a)
+ while (next_dot !== -1 || next_lf !== -1) {
+ const run_end =
+ next_dot !== -1 && (next_lf === -1 || next_dot < next_lf)
+ ? next_dot
+ : next_lf
+
+ // Copy up till whichever comes first, '.' or '\n' (but don't
+ // copy the '.' or '\n' itself).
+ data.copy(output, output_pos, input_pos, run_end)
+ output_pos += run_end - input_pos
+
+ if (
+ data[run_end] === 0x2e &&
+ (run_end === 0 || data[run_end - 1] === 0x0a)
+ ) {
+ // Replace /^\./ with '..'
+ output[output_pos++] = 0x2e
+ } else if (
+ data[run_end] === 0x0a &&
+ (run_end === 0 || data[run_end - 1] !== 0x0d)
+ ) {
+ // Replace /\r?\n/ with '\r\n'
+ output[output_pos++] = 0x0d
+ }
+ output[output_pos++] = data[run_end]
+
+ input_pos = run_end + 1
+
+ if (run_end === next_dot) {
+ next_dot = data.indexOf(0x2e, input_pos)
+ } else {
+ next_lf = data.indexOf(0x0a, input_pos)
+ }
+ }
+
+ if (input_pos < data.length) {
+ data.copy(output, output_pos, input_pos)
+ output_pos += data.length - input_pos
+ }
+
+ return output.slice(0, output_pos)
}
add_data(line) {
if (typeof line === 'string') {
// This shouldn't ever happen...
- line = Buffer.from(line, 'binary')
+ line = Buffer.from(line, this.encoding)
}
- // check if this is the end of headers line
+ // is this the end of headers line?
if (
this.header_pos === 0 &&
(line[0] === 0x0a || (line[0] === 0x0d && line[1] === 0x0a))
@@ -87,23 +159,18 @@ class Transaction {
// Build up headers
if (this.header_lines.length < this.cfg.headers.max_lines) {
if (line[0] === 0x2e) line = line.slice(1) // Strip leading "."
- this.header_lines.push(line.toString('binary').replace(/\r\n$/, '\n'))
+ this.header_lines.push(
+ line.toString(this.encoding).replace(/\r\n$/, '\n'),
+ )
}
} else if (this.parse_body) {
- if (line[0] === 0x2e) line = line.slice(1) // Strip leading "."
- let new_line = this.body.parse_more(
- line.toString('binary').replace(/\r\n$/, '\n'),
- )
+ let new_line = line
+ if (new_line[0] === 0x2e) new_line = new_line.slice(1) // Strip leading "."
- if (!new_line.length) {
- return // buffering for banners
- }
-
- new_line = new_line
- .toString('binary')
- .replace(/^\./gm, '..')
- .replace(/\r?\n/gm, '\r\n')
- line = Buffer.from(new_line, 'binary')
+ line = this.add_dot_stuffing_and_ensure_crlf_newlines(
+ this.body.parse_more(this.remove_final_cr(new_line)),
+ )
+ if (!line.length) return // buffering for banners
}
if (!this.discard_data) this.message_stream.add_line(line)
@@ -127,28 +194,26 @@ class Transaction {
this.header_pos = header_pos
if (this.parse_body) {
this.ensure_body()
- for (let j = 0; j < body_lines.length; j++) {
- this.body.parse_more(body_lines[j])
+ for (const bodyLine of body_lines) {
+ this.body.parse_more(bodyLine)
}
}
}
if (this.header_pos && this.parse_body) {
- let data = this.body.parse_end()
- if (data.length) {
- data = data
- .toString('binary')
- .replace(/^\./gm, '..')
- .replace(/\r?\n/gm, '\r\n')
- const line = Buffer.from(data, 'binary')
+ const line = this.add_dot_stuffing_and_ensure_crlf_newlines(
+ this.body.parse_end(),
+ )
+ if (line.length) {
+ this.body.force_end()
if (!this.discard_data) this.message_stream.add_line(line)
}
}
- if (!this.discard_data) {
- this.message_stream.add_line_end(cb)
- } else {
+ if (this.discard_data) {
cb()
+ } else {
+ this.message_stream.add_line_end(cb)
}
}
@@ -194,7 +259,8 @@ class Transaction {
exports.Transaction = Transaction
-exports.createTransaction = function (uuid, cfg = {}) {
- if (!cfg.main) cfg.main = {}
- return new Transaction(uuid, cfg)
+exports.createTransaction = function (uuid, cfg) {
+ const t = new Transaction(uuid, cfg)
+ logger.add_log_methods(t, 'mock-connection')
+ return t
}
diff --git a/lib/vm_harness.js b/lib/vm_harness.js
index e8f050b..eac1078 100644
--- a/lib/vm_harness.js
+++ b/lib/vm_harness.js
@@ -49,9 +49,9 @@ function make_test(module_path, test_path, additional_sandbox) {
exports: {},
test,
}
- Object.keys(additional_sandbox).forEach(function (k) {
+ for (const k of Object.keys(additional_sandbox)) {
sandbox[k] = additional_sandbox[k]
- })
+ }
vm.runInNewContext(code, sandbox)
}
}
diff --git a/package.json b/package.json
index e8720b3..87b8b1c 100644
--- a/package.json
+++ b/package.json
@@ -12,8 +12,7 @@
"files": [
"CHANGELOG.md",
"lib",
- "config",
- "CONTRIBUTORS.md"
+ "config"
],
"engines": {
"node": ">=12"
@@ -24,7 +23,8 @@
"haraka-constants": "^1.0.6",
"haraka-email-message": "^1.2.1",
"haraka-notes": "^1.0.6",
- "haraka-results": "^2.2.3"
+ "haraka-results": "^2.2.3",
+ "haraka-utils": "^1.1.2"
},
"devDependencies": {
"@haraka/eslint-config": "^1.1.2"
@@ -39,7 +39,7 @@
"prettier": "npx prettier . --check",
"prettier:fix": "npx prettier . --write --log-level=warn",
"test": "npx mocha@^10",
- "versions": "npx @msimerson/dependency-version-checker check",
- "versions:fix": "npx @msimerson/dependency-version-checker update"
+ "versions": "npx dependency-version-checker check",
+ "versions:fix": "npx dependency-version-checker update"
}
}
diff --git a/test/connection.js b/test/connection.js
index 0f4ed9a..705bb37 100644
--- a/test/connection.js
+++ b/test/connection.js
@@ -4,13 +4,12 @@ const connection = require('../lib/connection')
// console.log(connection);
describe('basic', function () {
- it('is a function', (done) => {
+ it('is a function', () => {
assert.equal(typeof connection.Connection, 'function')
- done()
})
- it('createConnection', (done) => {
+
+ it('createConnection', () => {
assert.equal(typeof connection.createConnection, 'function')
- done()
})
})
@@ -19,38 +18,64 @@ describe('connection', function () {
this.connection = connection.createConnection()
done()
})
- it('creates a new connection', (done) => {
+
+ it('creates a new connection', () => {
assert.ok(this.connection)
- done()
})
- it('creates a new transaction', (done) => {
+
+ it('creates a new transaction', () => {
this.connection.init_transaction()
assert.ok(this.connection.transaction)
- done()
})
- it('remote.ip', (done) => {
- assert.equal(this.connection.remote.ip, '127.0.0.1')
- done()
+
+ it('remote', () => {
+ assert.deepEqual(this.connection.remote, {
+ ip: '127.0.0.1',
+ port: null,
+ closed: false,
+ host: null,
+ info: null,
+ is_local: false,
+ is_private: false,
+ })
})
- it('local', (done) => {
- assert.deepEqual(this.connection.local, {})
- done()
+
+ it('local', () => {
+ assert.deepEqual(this.connection.local, {
+ host: 'haraka-test.example.com',
+ info: 'Haraka',
+ ip: null,
+ port: null,
+ })
})
- it('hello', (done) => {
- assert.deepEqual(this.connection.hello, {})
- done()
+
+ it('hello', () => {
+ assert.deepEqual(this.connection.hello, {
+ host: null,
+ verb: null,
+ })
})
- it('tls', (done) => {
- assert.deepEqual(this.connection.tls, {})
- done()
+
+ it('tls', () => {
+ assert.deepEqual(this.connection.tls, {
+ advertised: false,
+ cipher: {},
+ enabled: false,
+ verified: false,
+ })
})
- it('notes', (done) => {
+
+ it('notes', () => {
assert.deepEqual(this.connection.notes, {})
- done()
})
- it('set', (done) => {
+
+ it('set', () => {
this.connection.set('remote', 'ip', '192.168.1.1')
assert.deepEqual(this.connection.remote.ip, '192.168.1.1')
- done()
+ })
+
+ it('get', () => {
+ this.connection.set('remote', 'ip', '192.168.1.1')
+ assert.equal(this.connection.get('remote.ip'), '192.168.1.1')
})
})
diff --git a/test/index.js b/test/index.js
index 53d9df6..56e3bd0 100644
--- a/test/index.js
+++ b/test/index.js
@@ -4,43 +4,42 @@ const path = require('path')
const fixtures = require('../index')
describe('test-fixtures', function () {
- it('stub', (done) => {
+ it('stub', () => {
assert.equal('function', typeof fixtures.stub.stub)
- done()
})
- it('logger', (done) => {
+
+ it('logger', () => {
assert.equal('function', typeof fixtures.logger.loginfo)
- done()
})
- it('connection', (done) => {
+
+ it('connection', () => {
assert.equal('function', typeof fixtures.connection.createConnection)
- done()
})
- it('transaction', (done) => {
+
+ it('transaction', () => {
assert.equal('function', typeof fixtures.transaction.createTransaction)
- done()
})
- it('line_socket', (done) => {
+
+ it('line_socket', () => {
assert.equal('function', typeof fixtures.line_socket.connect)
- done()
})
- it('plugin', (done) => {
+
+ it('plugin', () => {
const p = new fixtures.plugin(path.join('test', 'fixtures', 'mock-plugin'))
assert.equal('function', typeof p.load_plugin)
- done()
})
- it('result_store', (done) => {
+
+ it('result_store', () => {
const rs = new fixtures.result_store()
// console.log(rs);
assert.equal('function', typeof rs.add)
- done()
})
- it('util_hmailitem', (done) => {
+
+ it('util_hmailitem', () => {
assert.equal('function', typeof fixtures.util_hmailitem.newMockHMailItem)
- done()
})
- it('vm_harness', (done) => {
+
+ it('vm_harness', () => {
assert.equal('function', typeof fixtures.vm_harness.sandbox_require)
- done()
})
})
diff --git a/test/logger.js b/test/logger.js
index 9721f23..110c45d 100644
--- a/test/logger.js
+++ b/test/logger.js
@@ -4,23 +4,19 @@ const logger = require('../lib/logger')
const plugin = { name: 'mock_plugin' }
-// console.log(logger);
describe('logger', function () {
- it('exports logging functions', (done) => {
+ it('exports logging functions', () => {
assert.equal(typeof logger.loginfo, 'function')
assert.equal(typeof logger.logwarn, 'function')
assert.equal(typeof logger.logerror, 'function')
assert.equal(typeof logger.log, 'function')
- done()
})
- it('log', (done) => {
+ it('log', () => {
assert.ok(logger.log('info', '_test log()_'))
- done()
})
- it('loginfo', (done) => {
+ it('loginfo', () => {
assert.ok(logger.loginfo(plugin, '_test loginfo()_'))
- done()
})
})
diff --git a/test/plugin.js b/test/plugin.js
index f39840f..8926964 100644
--- a/test/plugin.js
+++ b/test/plugin.js
@@ -5,60 +5,49 @@ const path = require('path')
const Plugin = require('../lib/plugin')
describe('plugin', function () {
- it('exports a Plugin function', (done) => {
+ it('exports a Plugin function', () => {
assert.equal(typeof Plugin, 'function')
- done()
})
- it('creates a new Plugin from .js', (done) => {
+ it('creates a new Plugin from .js', () => {
const newPlugin = new Plugin(path.join('test', 'fixtures', 'mock-plugin'))
- // console.log(newPlugin);
assert.ok(newPlugin)
- done()
})
- it('creates a new Plugin from dir', (done) => {
+ it('creates a new Plugin from dir', () => {
const newPlugin = new Plugin(
path.join('test', 'fixtures', 'mock-plugin-dir'),
)
- // console.log(newPlugin);
assert.ok(newPlugin)
- done()
})
describe('register', function () {
beforeEach((done) => {
- // console.log(Plugin);
this.plugin = new Plugin(path.join('test', 'fixtures', 'mock-plugin-dir'))
done()
})
- it('register exists', (done) => {
- // console.log(this.plugin);
+ it('register exists', () => {
assert.equal(typeof this.plugin.register, 'function')
- done()
})
- it('register runs', (done) => {
+ it('register runs', () => {
this.plugin.register()
assert.ok(true) // register() didn't throw
- done()
})
})
- it('can register plugin with ineritance', (done) => {
+ it('can register plugin with ineritance', () => {
const pi = new Plugin(path.join('test', 'fixtures', 'mock-plugin'))
assert.equal(typeof pi.register, 'function')
pi.register()
assert.ok(Object.keys(pi.base))
- done()
})
- it('plugin name remains the same after a plugin inherits', (done) => {
+ it('plugin name remains the same after a plugin inherits', () => {
const pi = new Plugin(path.join('test', 'fixtures', 'mock-plugin'))
assert.equal(typeof pi.register, 'function')
pi.register()
assert.equal(pi.name, path.join('test', 'fixtures', 'mock-plugin'))
- done()
})
})