Skip to content

Commit

Permalink
Style the exception expiry date if it is more than one or five years ago
Browse files Browse the repository at this point in the history
  • Loading branch information
jeemok committed Jul 11, 2021
1 parent 15ae9ad commit 32b8535
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 113 deletions.
Binary file added .DS_Store
Binary file not shown.
Binary file modified .README/exceptions_table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .README/exceptions_table_old.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Updated declaration file extension so it will not be included in final build
- Added multiple date format support for `expiry` field
- Added `dayjs` package
- Style the exception expiry date if it is more than one or five years ago

## 3.0.1 (July 11, 2021)

Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ You may add a file `.nsprc` to your project root directory to manage the excepti
"notes": "Ignored since we don't use xxx method"
},
"980": "Ignored since we don't use xxx method",
"Note": "Any non number key will not be excepted"
"Note": "Any non number key will not be accepted"
}
```

Expand All @@ -118,10 +118,12 @@ You may add a file `.nsprc` to your project root directory to manage the excepti

<br />

When using a `.nsprc` file, you will see this report display when it starts running:
When using a `.nsprc` file, a report will be displayed when it starts running:

<img src="./.README/exceptions_table.png" alt="Demo of table displaying a list of exceptions" />

> Note: the expiry date will be styled in yellow and red color if it is detected more than one or five years ago.
<br />

## Changelog
Expand Down
2 changes: 0 additions & 2 deletions src/types/date.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export type DateAnalysis = {
valid: boolean;
expired?: boolean;
days?: number;
months?: number;
years?: number;
};
2 changes: 0 additions & 2 deletions src/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ export function analyzeExpiry(expiry?: string | number, now: string | number = n
return {
valid: true,
expired: dayjsNow.isAfter(expiry),
days: dayjsNow.diff(expiry, 'days'),
months: dayjsNow.diff(expiry, 'months'),
years: dayjsNow.diff(expiry, 'years'),
};
}
13 changes: 11 additions & 2 deletions src/utils/vulnerability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ export function processExceptions(nsprc: NsprcFile, cmdExceptions: number[] = []
const numberId = Number(id);
const isValidId = !isNaN(numberId);
const isActive = Boolean(get(details, 'active', true)); // default to true
const expiryDate = get(details, 'expiry') ? new Date(get(details, 'expiry')).toUTCString() : '';
const notes = typeof details === 'string' ? details : get(details, 'notes', '');
const { valid, expired } = analyzeExpiry(get(details, 'expiry'));
const { valid, expired, years } = analyzeExpiry(get(details, 'expiry'));

// Color the status accordingly
let status = color('active', 'green');
if (expired) {
status = color('expired', 'red');
Expand All @@ -200,6 +200,15 @@ export function processExceptions(nsprc: NsprcFile, cmdExceptions: number[] = []
status = color('inactive', 'yellow');
}

// Color the date accordingly
let expiryDate = get(details, 'expiry') ? new Date(get(details, 'expiry')).toUTCString() : '';
// If it was expired for more than 5 years ago, warn by coloring the date in red
if (years && years <= -5) {
expiryDate = color(expiryDate, 'red');
} else if (years && years <= -1) {
expiryDate = color(expiryDate, 'yellow');
}

acc.report.push([id, status, expiryDate, notes]);

if (isValidId && isActive && !expired) {
Expand Down
95 changes: 16 additions & 79 deletions test/__mocks__/exception-table-data.json
Original file line number Diff line number Diff line change
@@ -1,80 +1,17 @@
[
[
"1165",
"\u001b[32mactive\u001b[0m",
"",
""
],
[
"1890",
"\u001b[32mactive\u001b[0m",
"",
""
],
[
"975",
"\u001b[31mexpired\u001b[0m",
"Thu, 11 Mar 2021 11:28:54 GMT",
""
],
[
"976",
"\u001b[33minactive\u001b[0m",
"",
""
],
[
"985",
"\u001b[32mactive\u001b[0m",
"",
""
],
[
"1084",
"\u001b[31mexpired\u001b[0m",
"Thu, 11 Mar 2021 11:28:54 GMT",
"Inactive package; consider replacing it."
],
[
"1179",
"\u001b[31mexpired\u001b[0m",
"Thu, 11 Mar 2021 11:28:54 GMT",
""
],
[
"1213",
"\u001b[32mactive\u001b[0m",
"",
"Ignored since we don't use xxx method"
],
[
"1556",
"\u001b[31mexpired\u001b[0m",
"Thu, 11 Mar 2021 11:28:54 GMT",
"Issue: https://github.com/jeemok/better-npm-audit/issues/28"
],
[
"1651",
"\u001b[31mexpired\u001b[0m",
"Thu, 11 Mar 2021 11:28:54 GMT",
"This will be fixed by the maintainers by June 14"
],
[
"1654",
"\u001b[32mactive\u001b[0m",
"Fri, 31 Dec 2021 16:00:00 GMT",
""
],
[
"2100",
"\u001b[32mactive\u001b[0m",
"",
"Unused"
],
[
"Note",
"\u001b[31minvalid\u001b[0m",
"",
"personal note"
]
]
["1165", "\u001b[32mactive\u001b[0m", "", ""],
["1890", "\u001b[32mactive\u001b[0m", "", ""],
["975", "\u001b[31mexpired\u001b[0m", "Thu, 11 Mar 2021 11:28:54 GMT", ""],
["976", "\u001b[33minactive\u001b[0m", "", ""],
["985", "\u001b[32mactive\u001b[0m", "", ""],
["1084", "\u001b[31mexpired\u001b[0m", "Thu, 11 Mar 2021 11:28:54 GMT", "Inactive package; consider replacing it."],
["1179", "\u001b[31mexpired\u001b[0m", "Thu, 11 Mar 2021 11:28:54 GMT", ""],
["1213", "\u001b[32mactive\u001b[0m", "", "Ignored since we don't use xxx method"],
["1556", "\u001b[31mexpired\u001b[0m", "Thu, 11 Mar 2021 11:28:54 GMT", "Issue: https://github.com/jeemok/better-npm-audit/issues/28"],
["1651", "\u001b[31mexpired\u001b[0m", "Thu, 11 Mar 2021 11:28:54 GMT", "This will be fixed by the maintainers by June 14"],
["1654", "\u001b[32mactive\u001b[0m", "Fri, 31 Dec 2021 16:00:00 GMT", ""],
["2000", "\u001b[32mactive\u001b[0m", "\u001b[33mMon, 01 Jan 2024 00:00:00 GMT\u001b[0m", ""],
["2001", "\u001b[32mactive\u001b[0m", "\u001b[31mTue, 01 Jan 2030 00:00:00 GMT\u001b[0m", ""],
["2100", "\u001b[32mactive\u001b[0m", "", "Unused"],
["Note", "\u001b[31minvalid\u001b[0m", "", "personal note"]
]
6 changes: 6 additions & 0 deletions test/__mocks__/nsprc.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
"1654": {
"expiry": 1640966400000
},
"2000": {
"expiry": "2024-01-01"
},
"2001": {
"expiry": "2030-01-01"
},
"2100": "Unused",
"Note": "personal note"
}
30 changes: 12 additions & 18 deletions test/utils/date.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,46 +52,40 @@ describe('Date utils', () => {

it('should be able to analyze the given timestamp correctly', () => {
// Only dates
expect(analyzeExpiry('2020-01-31', '2020-01-01')).to.deep.equal({ valid: true, expired: false, days: -30, months: 0, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-01-31')).to.deep.equal({ valid: true, expired: false, days: 0, months: 0, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-02-02')).to.deep.equal({ valid: true, expired: true, days: 2, months: 0, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-01-01')).to.deep.equal({ valid: true, expired: false, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-01-31')).to.deep.equal({ valid: true, expired: false, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-02-02')).to.deep.equal({ valid: true, expired: true, years: 0 });

// Dates & time
expect(analyzeExpiry('1 March 2020 3:00 pm', '1 March 2020 2:59:00 pm')).to.deep.equal({
valid: true,
expired: false,
days: 0,
months: 0,
years: 0,
});
expect(analyzeExpiry('1 March 2020 3:00 pm', '1 March 2020 3:00:00 pm')).to.deep.equal({
valid: true,
expired: false,
days: 0,
months: 0,
years: 0,
});
expect(analyzeExpiry('1 March 2020 3:00 pm', '1 March 2020 3:00:01 pm')).to.deep.equal({
valid: true,
expired: true,
days: 0,
months: 0,
years: 0,
});

// Milliseconds
expect(analyzeExpiry(1327611110410, 1327611110409)).to.deep.equal({ valid: true, expired: false, days: 0, months: 0, years: 0 });
expect(analyzeExpiry(1327611110410, 1327611110410)).to.deep.equal({ valid: true, expired: false, days: 0, months: 0, years: 0 });
expect(analyzeExpiry(1327611110410, 1327611110411)).to.deep.equal({ valid: true, expired: true, days: 0, months: 0, years: 0 });
expect(analyzeExpiry(1327611110410, 1327611110409)).to.deep.equal({ valid: true, expired: false, years: 0 });
expect(analyzeExpiry(1327611110410, 1327611110410)).to.deep.equal({ valid: true, expired: false, years: 0 });
expect(analyzeExpiry(1327611110410, 1327611110411)).to.deep.equal({ valid: true, expired: true, years: 0 });
});

it('should be able to analyze the time difference correctly', () => {
expect(analyzeExpiry('2020-01-31', '2020-01-01')).to.deep.equal({ valid: true, expired: false, days: -30, months: 0, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-02-02')).to.deep.equal({ valid: true, expired: true, days: 2, months: 0, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-03-01')).to.deep.equal({ valid: true, expired: true, days: 30, months: 1, years: 0 });
expect(analyzeExpiry('2020-01-31', '2021-01-01')).to.deep.equal({ valid: true, expired: true, days: 336, months: 11, years: 0 });
expect(analyzeExpiry('2020-01-31', '2021-01-31')).to.deep.equal({ valid: true, expired: true, days: 366, months: 12, years: 1 });
expect(analyzeExpiry('2020-01-31', '2025-10-10')).to.deep.equal({ valid: true, expired: true, days: 2079, months: 68, years: 5 });
expect(analyzeExpiry('2020-01-31', '2020-01-01')).to.deep.equal({ valid: true, expired: false, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-02-02')).to.deep.equal({ valid: true, expired: true, years: 0 });
expect(analyzeExpiry('2020-01-31', '2020-03-01')).to.deep.equal({ valid: true, expired: true, years: 0 });
expect(analyzeExpiry('2020-01-31', '2021-01-01')).to.deep.equal({ valid: true, expired: true, years: 0 });
expect(analyzeExpiry('2020-01-31', '2021-01-31')).to.deep.equal({ valid: true, expired: true, years: 1 });
expect(analyzeExpiry('2020-01-31', '2025-10-10')).to.deep.equal({ valid: true, expired: true, years: 5 });
});
});
});
16 changes: 8 additions & 8 deletions test/utils/vulnerability.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('Vulnerability utils', () => {
const cmdExceptions = [1165, 1890];
expect(consoleStub.called).to.equal(false);
const result = getExceptionsIds(NSPRC, cmdExceptions);
expect(result).to.have.length(6).and.deep.equal([1165, 1890, 985, 1213, 1654, 2100]);
expect(result).to.have.length(8).and.deep.equal([1165, 1890, 985, 1213, 1654, 2000, 2001, 2100]);
expect(consoleStub.called).to.equal(true); // Print security report
consoleStub.restore();
});
Expand All @@ -51,25 +51,25 @@ describe('Vulnerability utils', () => {
const result = processExceptions(NSPRC, cmdExceptions);

expect(result).to.have.property('exceptionIds');
expect(result.exceptionIds).to.have.length(6).and.to.deep.equal([1165, 1890, 985, 1213, 1654, 2100]);
expect(result.exceptionIds).to.have.length(8).and.to.deep.equal([1165, 1890, 985, 1213, 1654, 2000, 2001, 2100]);
expect(result).to.have.property('report');
expect(result.report).to.have.length(13).and.to.deep.equal(EXCEPTION_TABLE_DATA);
expect(result.report).to.have.length(15).and.to.deep.equal(EXCEPTION_TABLE_DATA);
});

it('should be able to filter active exceptions and label correctly', () => {
const result = processExceptions(NSPRC);
expect(result).to.have.property('exceptionIds').and.to.have.length(4);
expect(result).to.have.property('exceptionIds').and.to.have.length(6);
expect(result).to.have.property('report');

const activeExceptionIds = result.report
.filter((exception: string[]) => exception[1] === '\u001b[32mactive\u001b[0m')
.map((each: (string | number)[]) => Number(each[0]));
expect(activeExceptionIds).to.have.length(4).to.deep.equal([985, 1213, 1654, 2100]);
expect(activeExceptionIds).to.have.length(6).to.deep.equal([985, 1213, 1654, 2000, 2001, 2100]);
});

it('should be able to filter inactive exceptions and label correctly', () => {
const result = processExceptions(NSPRC);
expect(result).to.have.property('exceptionIds').and.to.have.length(4);
expect(result).to.have.property('exceptionIds').and.to.have.length(6);
expect(result).to.have.property('report');

const activeExceptionIds = result.report
Expand All @@ -81,7 +81,7 @@ describe('Vulnerability utils', () => {
it('should be able to filter expired exceptions and label correctly', () => {
const dateStub = sinon.stub(Date, 'now').returns(new Date(Date.UTC(2021, 6, 1)).valueOf());
const result = processExceptions(NSPRC);
expect(result).to.have.property('exceptionIds').and.to.have.length(4);
expect(result).to.have.property('exceptionIds').and.to.have.length(6);
expect(result).to.have.property('report');

const activeExceptionIds = result.report
Expand All @@ -95,7 +95,7 @@ describe('Vulnerability utils', () => {

it('should be able to filter invalid exceptions and label correctly', () => {
const result = processExceptions(NSPRC);
expect(result).to.have.property('exceptionIds').and.to.have.length(4);
expect(result).to.have.property('exceptionIds').and.to.have.length(6);
expect(result).to.have.property('report');

const activeExceptionIds = result.report
Expand Down

0 comments on commit 32b8535

Please sign in to comment.