Comparing version 2.3.2 to 2.4.0
@@ -1,45 +0,41 @@ | ||
const { join } = require('path') | ||
const { date_ago } = require('./util') | ||
const { join } = require("path"); | ||
const { date_ago } = require("./util"); | ||
require('dotenv').config({ | ||
path: join(process.cwd(), '.env') | ||
}) | ||
require("dotenv").config({ | ||
path: join(process.cwd(), ".env") | ||
}); | ||
module.exports = { | ||
alias: { | ||
c: 'csv', | ||
k: 'keys', | ||
t: 'types', | ||
a: 'auto', | ||
d: 'done', | ||
t: 'todo', | ||
s: 'start', | ||
f: 'finish', | ||
u: ['user', 'username'], | ||
p: ['pass', 'password'], | ||
j: ['url', 'jira'], | ||
e: 'endpoint', | ||
q: 'query', | ||
r: 'report', | ||
i: 'interval', | ||
x: 'period', | ||
h: 'help' | ||
c: "csv", | ||
k: "keys", | ||
t: "types", | ||
a: "auto", | ||
d: "done", | ||
t: "todo", | ||
s: "start", | ||
f: "finish", | ||
u: ["user", "username"], | ||
p: ["pass", "password"], | ||
j: ["url", "jira"], | ||
e: "endpoint", | ||
q: "query", | ||
r: "report", | ||
i: "interval", | ||
x: "period", | ||
h: "help" | ||
}, | ||
boolean: [ | ||
'csv', | ||
'help', | ||
'report' | ||
], | ||
boolean: ["csv", "help", "report"], | ||
string: [ | ||
'keys', | ||
'done', | ||
'todo', | ||
'start', | ||
'finish', | ||
'user', | ||
'pass', | ||
'jira', | ||
'query', | ||
'types', | ||
'endpoint' | ||
"keys", | ||
"done", | ||
"todo", | ||
"start", | ||
"finish", | ||
"user", | ||
"pass", | ||
"jira", | ||
"query", | ||
"types", | ||
"endpoint" | ||
], | ||
@@ -56,17 +52,20 @@ default: { | ||
finish: process.env.KBME_FINISH || date_ago(0), | ||
done: process.env.KBME_DONE || 'Done', | ||
todo: process.env.KBME_TODO || 'Pending', | ||
keys: process.env.KBME_KEYS || 'ELEMENTS', | ||
types: process.env.KBME_TYPES || 'NOT IN (Epic)', | ||
query: process.env.KBME_QUERY || 'project IN (%keys) AND status IN (%done) AND resolutiondate > %start AND resolutiondate < %finish AND issuetype %types', | ||
endpoint: process.env.KBME_ENDPOINT || '%jira/search?jql=%jql&expand=changelog' | ||
done: process.env.KBME_DONE || "Done", | ||
todo: process.env.KBME_TODO || "Pending", | ||
keys: process.env.KBME_KEYS || "ELEMENTS", | ||
types: process.env.KBME_TYPES || "NOT IN (Epic)", | ||
query: | ||
process.env.KBME_QUERY || | ||
"project IN (%keys) AND status IN (%done) AND resolutiondate > %start AND resolutiondate < %finish AND issuetype %types", | ||
endpoint: | ||
process.env.KBME_ENDPOINT || "%jira/search?jql=%jql&expand=changelog" | ||
}, | ||
unknown: function(flag) { | ||
console.log(`Unknown option ${flag}`) | ||
process.exit(1) | ||
console.log(`Unknown option ${flag}`); | ||
process.exit(1); | ||
} | ||
} | ||
}; | ||
function to_bool(val) { | ||
return val === 'false' ? false : Boolean(val) | ||
return val === "false" ? false : Boolean(val); | ||
} |
@@ -1,5 +0,5 @@ | ||
const pkg = require('../package.json') | ||
const opt = require('./config') | ||
const pkg = require("../package.json"); | ||
const opt = require("./config"); | ||
const help =` | ||
const help = ` | ||
${pkg.name} v${pkg.version} | ||
@@ -31,3 +31,5 @@ ----------- | ||
- Override JIRA URL | ||
> KBME_JIRA="https://jira.com/jira/rest/api/2" KBME_KEYS="SFC, KRK" ${pkg.name} --csv | ||
> KBME_JIRA="https://jira.com/jira/rest/api/2" KBME_KEYS="SFC, KRK" ${ | ||
pkg.name | ||
} --csv | ||
@@ -48,4 +50,4 @@ Pay special attention to the query and endpoint options, they have special characters (%opt) that | ||
> kbme --auto 15 --csv >> metrics.csv | ||
` | ||
`; | ||
module.exports = help | ||
module.exports = help; |
@@ -1,4 +0,12 @@ | ||
const got = require('got') | ||
const debug = require('debug')('jql'); | ||
const { pad, xtend, date_ago, days_between, num_reducer, replace, generate_dates } = require('./util') | ||
const got = require("got"); | ||
const debug = require("debug")("jql"); | ||
const { | ||
pad, | ||
xtend, | ||
date_ago, | ||
days_between, | ||
num_reducer, | ||
replace, | ||
generate_dates | ||
} = require("./util"); | ||
@@ -13,3 +21,3 @@ module.exports = { | ||
report | ||
} | ||
}; | ||
@@ -20,9 +28,9 @@ /** | ||
*/ | ||
function request({jira, user, pass, endpoint}, req = got) { | ||
return async (jql) => | ||
function request({ jira, user, pass, endpoint }, req = got) { | ||
return async jql => | ||
debug(jql) || | ||
req(replace(endpoint, {jira, jql}), { | ||
req(replace(endpoint, { jira, jql }), { | ||
json: true, | ||
auth: `${user}:${pass}` | ||
}).then(res => res.body.issues) | ||
}).then(res => res.body.issues); | ||
} | ||
@@ -41,7 +49,7 @@ | ||
*/ | ||
function lead({fields, changelog}, status) { | ||
const start = new Date(fields.created) | ||
const finish = new Date(date_to_status(status, changelog)) | ||
function lead({ fields, changelog }, status) { | ||
const start = new Date(fields.created); | ||
const finish = new Date(date_to_status(status, changelog)); | ||
return days_between(finish, start) | ||
return days_between(finish, start); | ||
} | ||
@@ -61,10 +69,10 @@ | ||
*/ | ||
function cycle({fields, changelog}, todo, done) { | ||
function cycle({ fields, changelog }, todo, done) { | ||
// When issues are moved directly to 'done' status, without going | ||
// thru 'todo', date_to_status() returns undefined, in this case | ||
// fields.created will be used instead of 'todo' date | ||
const start = new Date(date_to_status(todo, changelog) || fields.created) | ||
const finish = new Date(date_to_status(done, changelog)) | ||
const start = new Date(date_to_status(todo, changelog) || fields.created); | ||
const finish = new Date(date_to_status(done, changelog)); | ||
return days_between(finish, start) | ||
return days_between(finish, start); | ||
} | ||
@@ -105,12 +113,12 @@ | ||
*/ | ||
function date_to_status(status, {histories}) { | ||
function date_to_status(status, { histories }) { | ||
const date = histories | ||
.filter( | ||
({ items }) => items.filter( | ||
({ field, toString }) => | ||
(field === 'status' && toString === status) | ||
).length > 0 | ||
({ items }) => | ||
items.filter( | ||
({ field, toString }) => field === "status" && toString === status | ||
).length > 0 | ||
) | ||
.map(f => f.created) | ||
.pop() | ||
.pop(); | ||
@@ -126,12 +134,13 @@ return date; | ||
function metrics(opts, issues) { | ||
const leadTimeAvg = issues | ||
.map(issue => lead(issue, opts.done)) | ||
.reduce(num_reducer, 0) / issues.length | ||
const leadTimeAvg = | ||
issues.map(issue => lead(issue, opts.done)).reduce(num_reducer, 0) / | ||
issues.length; | ||
const cycleTimeAvg = issues | ||
.map(issue => cycle(issue, opts.todo, opts.done)) | ||
.reduce(num_reducer, 0) / issues.length | ||
const cycleTimeAvg = | ||
issues | ||
.map(issue => cycle(issue, opts.todo, opts.done)) | ||
.reduce(num_reducer, 0) / issues.length; | ||
const period = days_between(new Date(opts.start), new Date(opts.finish)) | ||
const throughput = (issues.length / period) | ||
const period = days_between(new Date(opts.start), new Date(opts.finish)); | ||
const throughput = issues.length / period; | ||
@@ -145,3 +154,3 @@ return { | ||
finish: opts.finish | ||
} | ||
}; | ||
} | ||
@@ -155,5 +164,5 @@ | ||
const api = request(opt, req); | ||
const jql = replace(opt.query, opt) | ||
const issues = await api(jql) | ||
const res = metrics(opt, issues) | ||
const jql = replace(opt.query, opt); | ||
const issues = await api(jql); | ||
const res = metrics(opt, issues); | ||
@@ -168,7 +177,9 @@ return res; | ||
async function report(opt, req = got) { | ||
const dates = generate_dates(opt.interval, opt.period) | ||
const dates = generate_dates(opt.interval, opt.period); | ||
return Promise.all(dates | ||
.map(date => xtend({}, opt, date)) | ||
.map(opts => query(opts, req).then(data => data))) | ||
return Promise.all( | ||
dates | ||
.map(date => xtend({}, opt, date)) | ||
.map(opts => query(opts, req).then(data => data)) | ||
); | ||
} |
@@ -12,3 +12,3 @@ module.exports = { | ||
generate_dates | ||
} | ||
}; | ||
@@ -20,3 +20,3 @@ /** | ||
function pad(n) { | ||
return ('0' + n).slice(-2) | ||
return ("0" + n).slice(-2); | ||
} | ||
@@ -30,6 +30,6 @@ | ||
if (!Array.isArray(data)) { | ||
return Object.values(data).join(', ') | ||
return Object.values(data).join(", "); | ||
} | ||
return data.map(csv).join('\n') | ||
return data.map(csv).join("\n"); | ||
} | ||
@@ -42,3 +42,3 @@ | ||
function toJSON(data) { | ||
return JSON.stringify(data, null, 2) | ||
return JSON.stringify(data, null, 2); | ||
} | ||
@@ -51,5 +51,7 @@ | ||
function date_ago(days) { | ||
const now = new Date() | ||
const last = new Date(now.getTime() - (days * 24 * 60 * 60 * 1000)) | ||
return `${last.getFullYear()}-${pad(last.getMonth() + 1)}-${pad(last.getDate())}`; | ||
const now = new Date(); | ||
const last = new Date(now.getTime() - days * 24 * 60 * 60 * 1000); | ||
return `${last.getFullYear()}-${pad(last.getMonth() + 1)}-${pad( | ||
last.getDate() | ||
)}`; | ||
} | ||
@@ -63,3 +65,3 @@ | ||
function days_between(a, b) { | ||
const diff = Math.abs(a.getTime() - b.getTime()) | ||
const diff = Math.abs(a.getTime() - b.getTime()); | ||
return Math.ceil(diff / (1000 * 3600 * 24)); | ||
@@ -74,4 +76,4 @@ } | ||
function num_reducer(a, b) { | ||
a += b | ||
return a | ||
a += b; | ||
return a; | ||
} | ||
@@ -98,10 +100,10 @@ | ||
function generate_dates(interval = 15, period = 365) { | ||
let top = 0 | ||
let bottom = 0 | ||
const dates = [] | ||
const limit = Math.ceil(period / interval) | ||
let top = 0; | ||
let bottom = 0; | ||
const dates = []; | ||
const limit = Math.ceil(period / interval); | ||
for (let i = 0; i < limit; i++) { | ||
top += interval | ||
bottom = top - interval | ||
top += interval; | ||
bottom = top - interval; | ||
@@ -111,12 +113,12 @@ dates.push({ | ||
finish: date_ago(bottom) | ||
}) | ||
}); | ||
} | ||
return dates | ||
return dates; | ||
} | ||
function format(opt) { | ||
if (opt.csv) return data => csv(data) | ||
if (opt.csv) return data => csv(data); | ||
return data => toJSON(data) | ||
return data => toJSON(data); | ||
} |
{ | ||
"name": "kbme", | ||
"version": "2.3.2", | ||
"version": "2.4.0", | ||
"description": "Gather kanban metrics from your JIRA instance", | ||
@@ -28,3 +28,6 @@ "main": "lib/index.js", | ||
"devDependencies": { | ||
"jest": "^23.1.0" | ||
"cz-conventional-changelog": "^2.1.0", | ||
"husky": "^1.3.1", | ||
"jest": "^23.1.0", | ||
"lint-staged": "^8.1.0" | ||
}, | ||
@@ -34,3 +37,5 @@ "scripts": { | ||
"test:watch": "jest --watch", | ||
"release": "npx semantic-release@beta" | ||
"release": "npx semantic-release@beta", | ||
"commit": "npx git-cz", | ||
"format": "npx prettier --write **/*.js" | ||
}, | ||
@@ -43,3 +48,19 @@ "release": { | ||
] | ||
}, | ||
"config": { | ||
"commitizen": { | ||
"path": "./node_modules/cz-conventional-changelog" | ||
} | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"npm run format", | ||
"git add" | ||
] | ||
} | ||
} |
@@ -102,2 +102,4 @@ # kbme | ||
**HEADS UP:** If you are not sure how write a commit message, make your changes in your feature branch and run `npm run commit` and follow the assistant. | ||
### Releases | ||
@@ -104,0 +106,0 @@ |
@@ -1,100 +0,120 @@ | ||
const { got } = require('./mocks') | ||
const { date_ago } = require('../lib/util') | ||
const { issues } = require('./mocks/issues.json') | ||
const { request, lead, cycle, metrics, date_to_status, query, report } = require('../lib') | ||
const { got } = require("./mocks"); | ||
const { date_ago } = require("../lib/util"); | ||
const { issues } = require("./mocks/issues.json"); | ||
const { | ||
request, | ||
lead, | ||
cycle, | ||
metrics, | ||
date_to_status, | ||
query, | ||
report | ||
} = require("../lib"); | ||
let options = { | ||
done: 'Done', | ||
todo: 'ToDo', | ||
start: '2017-08-01', | ||
finish: '2017-08-26', | ||
jira: 'jira', | ||
user: 'user', | ||
pass: 'pass', | ||
endpoint: '%jira/%jql', | ||
query: 'test', | ||
done: "Done", | ||
todo: "ToDo", | ||
start: "2017-08-01", | ||
finish: "2017-08-26", | ||
jira: "jira", | ||
user: "user", | ||
pass: "pass", | ||
endpoint: "%jira/%jql", | ||
query: "test", | ||
interval: 2, | ||
period: 4, | ||
report: false | ||
} | ||
}; | ||
const makeOptions = opts => Object.assign({}, options, opts) | ||
const makeOptions = opts => Object.assign({}, options, opts); | ||
describe('lib', () => { | ||
describe('#request', () => { | ||
test('should return a function', () => { | ||
expect(typeof request(options)).toBe('function') | ||
}) | ||
describe("lib", () => { | ||
describe("#request", () => { | ||
test("should return a function", () => { | ||
expect(typeof request(options)).toBe("function"); | ||
}); | ||
test('function returned should return a promise', async () => { | ||
const api = request(options, got) | ||
const res = await api() | ||
expect(api() instanceof Promise).toBe(true) | ||
expect(res.length).toBe(4) | ||
expect(res).toHaveLength(4) | ||
}) | ||
}) | ||
test("function returned should return a promise", async () => { | ||
const api = request(options, got); | ||
const res = await api(); | ||
expect(api() instanceof Promise).toBe(true); | ||
expect(res.length).toBe(4); | ||
expect(res).toHaveLength(4); | ||
}); | ||
}); | ||
describe('#lead', () => { | ||
test('should return return the lead time for given issue', () => { | ||
expect(lead(issues[0], 'ToDo')).toBe(1) | ||
expect(lead(issues[1], 'ToDo')).toBe(1) | ||
expect(lead(issues[2], 'ToDo')).toBe(1) | ||
expect(lead(issues[3], 'ToDo')).toBe(1) | ||
}) | ||
}) | ||
describe("#lead", () => { | ||
test("should return return the lead time for given issue", () => { | ||
expect(lead(issues[0], "ToDo")).toBe(1); | ||
expect(lead(issues[1], "ToDo")).toBe(1); | ||
expect(lead(issues[2], "ToDo")).toBe(1); | ||
expect(lead(issues[3], "ToDo")).toBe(1); | ||
}); | ||
}); | ||
describe('#cycle', () => { | ||
test('should return return the lead time for given issue', () => { | ||
expect(cycle(issues[0], 'In Progress', 'ToDo')).toBe(1) | ||
expect(cycle(issues[1], 'In Progress', 'ToDo')).toBe(2) | ||
expect(cycle(issues[2], 'In Progress', 'ToDo')).toBe(1) | ||
expect(cycle(issues[3], 'In Progress', 'ToDo')).toBe(8) | ||
}) | ||
describe("#cycle", () => { | ||
test("should return return the lead time for given issue", () => { | ||
expect(cycle(issues[0], "In Progress", "ToDo")).toBe(1); | ||
expect(cycle(issues[1], "In Progress", "ToDo")).toBe(2); | ||
expect(cycle(issues[2], "In Progress", "ToDo")).toBe(1); | ||
expect(cycle(issues[3], "In Progress", "ToDo")).toBe(8); | ||
}); | ||
test('should use issue creation date when status transition date not available', () => { | ||
expect(cycle(issues[3], 'NonExistent', 'ToDo')).toBe(1) | ||
}) | ||
}) | ||
test("should use issue creation date when status transition date not available", () => { | ||
expect(cycle(issues[3], "NonExistent", "ToDo")).toBe(1); | ||
}); | ||
}); | ||
describe('#date_to_status', () => { | ||
test('should return the date transition to a given status', () => { | ||
expect(date_to_status('NonExistentSTatus', issues[0].changelog)).toBeUndefined() | ||
expect(date_to_status('ToDo', issues[0].changelog)).toBe('2017-08-07T11:56:53.090+0000') | ||
expect(date_to_status('In Progress', issues[0].changelog)).toBe('2017-08-07T11:56:57.293+0000') | ||
}) | ||
}) | ||
describe("#date_to_status", () => { | ||
test("should return the date transition to a given status", () => { | ||
expect( | ||
date_to_status("NonExistentSTatus", issues[0].changelog) | ||
).toBeUndefined(); | ||
expect(date_to_status("ToDo", issues[0].changelog)).toBe( | ||
"2017-08-07T11:56:53.090+0000" | ||
); | ||
expect(date_to_status("In Progress", issues[0].changelog)).toBe( | ||
"2017-08-07T11:56:57.293+0000" | ||
); | ||
}); | ||
}); | ||
describe('#query', () => { | ||
describe('should collect metrics for specific interval', () => { | ||
it('should return correct output for given options', async () => { | ||
const a = await query(options, got) | ||
describe("#query", () => { | ||
describe("should collect metrics for specific interval", () => { | ||
it("should return correct output for given options", async () => { | ||
const a = await query(options, got); | ||
const b = await query(makeOptions({ | ||
start: '2017-08-01', | ||
finish: '2017-08-03', | ||
}), got) | ||
const b = await query( | ||
makeOptions({ | ||
start: "2017-08-01", | ||
finish: "2017-08-03" | ||
}), | ||
got | ||
); | ||
const c = await query(makeOptions({ | ||
start: '2017-08-01', | ||
finish: '2017-08-05', | ||
}), got) | ||
const c = await query( | ||
makeOptions({ | ||
start: "2017-08-01", | ||
finish: "2017-08-05" | ||
}), | ||
got | ||
); | ||
expect(a).toMatchObject({throughput: 0.16}) | ||
expect(b).toMatchObject({throughput: 2}) | ||
expect(c).toMatchObject({throughput: 1}) | ||
}) | ||
}) | ||
}) | ||
expect(a).toMatchObject({ throughput: 0.16 }); | ||
expect(b).toMatchObject({ throughput: 2 }); | ||
expect(c).toMatchObject({ throughput: 1 }); | ||
}); | ||
}); | ||
}); | ||
describe('#report', () => { | ||
describe('should collect metrics for specific period & interval', () => { | ||
it('should not be used when report set to false', async () => { | ||
const a = await report(options, got) | ||
const b = await report(makeOptions({period: 9, interval: 3}), got) | ||
expect(a).toHaveLength(2) | ||
expect(b).toHaveLength(3) | ||
}) | ||
}) | ||
}) | ||
}) | ||
describe("#report", () => { | ||
describe("should collect metrics for specific period & interval", () => { | ||
it("should not be used when report set to false", async () => { | ||
const a = await report(options, got); | ||
const b = await report(makeOptions({ period: 9, interval: 3 }), got); | ||
expect(a).toHaveLength(2); | ||
expect(b).toHaveLength(3); | ||
}); | ||
}); | ||
}); | ||
}); |
@@ -1,2 +0,12 @@ | ||
const { pad, csv, toJSON, date_ago, days_between, num_reducer, replace, generate_dates, format } = require('../lib/util') | ||
const { | ||
pad, | ||
csv, | ||
toJSON, | ||
date_ago, | ||
days_between, | ||
num_reducer, | ||
replace, | ||
generate_dates, | ||
format | ||
} = require("../lib/util"); | ||
const pretty = `{ | ||
@@ -6,114 +16,118 @@ "a": "x", | ||
"c": "z" | ||
}` | ||
}`; | ||
describe('util', () => { | ||
describe('#pad', () => { | ||
test('should pad with zero when number is 1 digit', () => { | ||
expect(pad(0)).toBe('00') | ||
expect(pad(1)).toBe('01') | ||
}) | ||
describe("util", () => { | ||
describe("#pad", () => { | ||
test("should pad with zero when number is 1 digit", () => { | ||
expect(pad(0)).toBe("00"); | ||
expect(pad(1)).toBe("01"); | ||
}); | ||
test('should not pad with zero when number is 2 digits', () => { | ||
expect(pad(10)).toBe('10') | ||
expect(pad(20)).toBe('20') | ||
}) | ||
}) | ||
test("should not pad with zero when number is 2 digits", () => { | ||
expect(pad(10)).toBe("10"); | ||
expect(pad(20)).toBe("20"); | ||
}); | ||
}); | ||
describe('#csv', () => { | ||
test('should output comma separated list of object values', () => { | ||
expect(csv({})).toBe('') | ||
expect(csv({a:'x', b: 'y', c: 'z'})).toBe('x, y, z') | ||
}) | ||
describe("#csv", () => { | ||
test("should output comma separated list of object values", () => { | ||
expect(csv({})).toBe(""); | ||
expect(csv({ a: "x", b: "y", c: "z" })).toBe("x, y, z"); | ||
}); | ||
test('should handle arrays', () => { | ||
expect(csv([{}])).toBe('') | ||
expect(csv([{a:'x', b: 'y', c: 'z'}])).toBe('x, y, z') | ||
}) | ||
}) | ||
test("should handle arrays", () => { | ||
expect(csv([{}])).toBe(""); | ||
expect(csv([{ a: "x", b: "y", c: "z" }])).toBe("x, y, z"); | ||
}); | ||
}); | ||
describe('#toJSON', () => { | ||
test('should output prettified json', () => { | ||
expect(toJSON({a:'x', b: 'y', c: 'z'})).toBe(pretty) | ||
}) | ||
}) | ||
describe("#toJSON", () => { | ||
test("should output prettified json", () => { | ||
expect(toJSON({ a: "x", b: "y", c: "z" })).toBe(pretty); | ||
}); | ||
}); | ||
describe('#date_ago', () => { | ||
const d = new Date() | ||
const date = `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}` | ||
const year = `${d.getFullYear()-1}-${pad(d.getMonth()+1)}-${pad(d.getDate())}` | ||
describe("#date_ago", () => { | ||
const d = new Date(); | ||
const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad( | ||
d.getDate() | ||
)}`; | ||
const year = `${d.getFullYear() - 1}-${pad(d.getMonth() + 1)}-${pad( | ||
d.getDate() | ||
)}`; | ||
test('should return the date string of n days ago', () => { | ||
expect(date_ago(0)).toBe(date) | ||
expect(date_ago(365)).toBe(year) | ||
}) | ||
test("should return the date string of n days ago", () => { | ||
expect(date_ago(0)).toBe(date); | ||
expect(date_ago(365)).toBe(year); | ||
}); | ||
test('format should be YYYY-MM-DD', () => { | ||
expect(date_ago(10)).toMatch(/^\d{4}-\d{2}-\d{2}$/) | ||
}) | ||
}) | ||
test("format should be YYYY-MM-DD", () => { | ||
expect(date_ago(10)).toMatch(/^\d{4}-\d{2}-\d{2}$/); | ||
}); | ||
}); | ||
describe('#days_between', () => { | ||
const today = new Date(date_ago(0)) | ||
const yesterday = new Date(date_ago(1)) | ||
const week = new Date(date_ago(7)) | ||
describe("#days_between", () => { | ||
const today = new Date(date_ago(0)); | ||
const yesterday = new Date(date_ago(1)); | ||
const week = new Date(date_ago(7)); | ||
test('should return the date string of n days ago', () => { | ||
expect(days_between(today, week)).toBe(7) | ||
expect(days_between(today, today)).toBe(0) | ||
expect(days_between(today, yesterday)).toBe(1) | ||
}) | ||
}) | ||
test("should return the date string of n days ago", () => { | ||
expect(days_between(today, week)).toBe(7); | ||
expect(days_between(today, today)).toBe(0); | ||
expect(days_between(today, yesterday)).toBe(1); | ||
}); | ||
}); | ||
describe('#num_reducer', () => { | ||
test('should return the date string of n days ago', () => { | ||
expect([0].reduce(num_reducer, 0)).toBe(0) | ||
expect([1,2,3].reduce(num_reducer, 0)).toBe(6) | ||
}) | ||
}) | ||
describe("#num_reducer", () => { | ||
test("should return the date string of n days ago", () => { | ||
expect([0].reduce(num_reducer, 0)).toBe(0); | ||
expect([1, 2, 3].reduce(num_reducer, 0)).toBe(6); | ||
}); | ||
}); | ||
describe('#replace', () => { | ||
describe("#replace", () => { | ||
let result; | ||
const string = 'the %name cat is %where %noreplaceme' | ||
const string = "the %name cat is %where %noreplaceme"; | ||
const options = { | ||
name: 'Felix', | ||
where: 'in the kitchen' | ||
} | ||
name: "Felix", | ||
where: "in the kitchen" | ||
}; | ||
beforeEach(() => { | ||
result = replace(string, options) | ||
}) | ||
result = replace(string, options); | ||
}); | ||
test('should replace %strings for object values', () => { | ||
expect(result).toContain('Felix') | ||
expect(result).toContain('in the kitchen') | ||
}) | ||
test("should replace %strings for object values", () => { | ||
expect(result).toContain("Felix"); | ||
expect(result).toContain("in the kitchen"); | ||
}); | ||
test('should replace only matching strings', () => { | ||
expect(result).toContain('%noreplaceme') | ||
}) | ||
}) | ||
test("should replace only matching strings", () => { | ||
expect(result).toContain("%noreplaceme"); | ||
}); | ||
}); | ||
describe('#generate_dates', () => { | ||
test('should create an array of dates for default interval and period', () => { | ||
expect(generate_dates()).toHaveLength(25) | ||
}) | ||
describe("#generate_dates", () => { | ||
test("should create an array of dates for default interval and period", () => { | ||
expect(generate_dates()).toHaveLength(25); | ||
}); | ||
test('should create an array of dates for given interval and period', () => { | ||
expect(generate_dates(30, 30)).toHaveLength(1) | ||
expect(generate_dates(15, 20)).toHaveLength(2) | ||
expect(generate_dates(15, 31)).toHaveLength(3) | ||
expect(generate_dates(15, 365)).toHaveLength(25) | ||
}) | ||
}) | ||
test("should create an array of dates for given interval and period", () => { | ||
expect(generate_dates(30, 30)).toHaveLength(1); | ||
expect(generate_dates(15, 20)).toHaveLength(2); | ||
expect(generate_dates(15, 31)).toHaveLength(3); | ||
expect(generate_dates(15, 365)).toHaveLength(25); | ||
}); | ||
}); | ||
describe('#format', () => { | ||
test('should return correct output based on input', () => { | ||
const json = format({}) | ||
const comma = format({csv: true}) | ||
expect(typeof json).toBe('function') | ||
expect(typeof comma).toBe('function') | ||
expect(json({a:'x', b: 'y', c: 'z'})).toBe(pretty) | ||
expect(comma({a: 1, b: 2})).toBe('1, 2') | ||
}) | ||
}) | ||
}) | ||
describe("#format", () => { | ||
test("should return correct output based on input", () => { | ||
const json = format({}); | ||
const comma = format({ csv: true }); | ||
expect(typeof json).toBe("function"); | ||
expect(typeof comma).toBe("function"); | ||
expect(json({ a: "x", b: "y", c: "z" })).toBe(pretty); | ||
expect(comma({ a: 1, b: 2 })).toBe("1, 2"); | ||
}); | ||
}); | ||
}); |
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
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
154958
1140
119
4