Skip to content

Commit 8daeae3

Browse files
committed
refactor(logger): Use util.styleText when possible
In the next major when we drop Node 20 support, we can remove the ansi dependency and refactor CordovaLogger to clean up the exposed API a bit.
1 parent ec5de30 commit 8daeae3

2 files changed

Lines changed: 107 additions & 49 deletions

File tree

spec/CordovaLogger.spec.js

Lines changed: 80 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919

2020
const CordovaError = require('../src/CordovaError');
2121
const CordovaLogger = require('../src/CordovaLogger');
22-
const EventEmitter = require('events').EventEmitter;
22+
const EventEmitter = require('node:events').EventEmitter;
23+
const util = require('node:util');
2324

25+
const hasStyleText = !!util.styleText;
2426
const DEFAULT_LEVELS = ['verbose', 'normal', 'warn', 'info', 'error', 'results'];
2527

2628
describe('CordovaLogger class', function () {
@@ -119,56 +121,96 @@ describe('CordovaLogger class', function () {
119121
});
120122
});
121123

122-
describe('log method', function () {
123-
function CursorSpy (name) {
124-
const cursorMethods = ['reset', 'write', 'bold'];
125-
const spy = jasmine.createSpyObj(name, cursorMethods);
124+
if (hasStyleText) {
125+
describe('log method', function () {
126+
beforeEach(function () {
127+
logger.stdoutCursor = jasmine.createSpyObj('stdout', ['write']);
128+
logger.stderrCursor = jasmine.createSpyObj('stderr', ['write']);
129+
});
126130

127-
// Make spy methods chainable, as original Cursor acts
128-
cursorMethods.forEach(function (method) { spy[method].and.returnValue(spy); });
131+
it('Test 010 : should ignore message if severity is less than logger\'s level', function () {
132+
logger.setLevel('error').log('verbose', 'some_messgge');
133+
expect(logger.stdoutCursor.write).not.toHaveBeenCalled();
134+
expect(logger.stderrCursor.write).not.toHaveBeenCalled();
135+
});
129136

130-
spy.fg = jasmine.createSpyObj('fg', ['grey', 'yellow', 'blue', 'red']);
137+
it('Test 011 : should log everything except error messages to stdout', function () {
138+
logger.setLevel('verbose');
139+
DEFAULT_LEVELS.forEach(function (level) {
140+
logger.log(level, 'message');
141+
});
131142

132-
return spy;
133-
}
143+
expect(logger.stdoutCursor.write.calls.count()).toBe((DEFAULT_LEVELS.length - 1));
144+
expect(logger.stderrCursor.write.calls.count()).toBe(1);
145+
});
134146

135-
beforeEach(function () {
136-
logger.stdoutCursor = new CursorSpy('stdoutCursor');
137-
logger.stderrCursor = new CursorSpy('stderrCursor');
138-
});
147+
it('Test 012 : should log Error objects to stderr despite of loglevel', function () {
148+
logger.setLevel('verbose').log('verbose', new Error());
149+
expect(logger.stdoutCursor.write).not.toHaveBeenCalled();
150+
expect(logger.stderrCursor.write).toHaveBeenCalled();
151+
});
139152

140-
it('Test 010 : should ignore message if severity is less than logger\'s level', function () {
141-
logger.setLevel('error').log('verbose', 'some_messgge');
142-
expect(logger.stdoutCursor.write).not.toHaveBeenCalled();
143-
expect(logger.stderrCursor.write).not.toHaveBeenCalled();
153+
it('Test 013 : should handle CordovaError instances separately from Error ones', function () {
154+
const errorMock = new CordovaError();
155+
spyOn(errorMock, 'toString').and.returnValue('error_message');
156+
157+
logger.setLevel('verbose').log('verbose', errorMock);
158+
expect(errorMock.toString).toHaveBeenCalled();
159+
expect(logger.stderrCursor.write.calls.argsFor(0)).toMatch('Error: error_message');
160+
});
144161
});
162+
} else {
163+
describe('log method (ansi)', function () {
164+
function CursorSpy (name) {
165+
const cursorMethods = ['reset', 'write', 'bold'];
166+
const spy = jasmine.createSpyObj(name, cursorMethods);
167+
168+
// Make spy methods chainable, as original Cursor acts
169+
cursorMethods.forEach(function (method) { spy[method].and.returnValue(spy); });
170+
171+
spy.fg = jasmine.createSpyObj('fg', ['grey', 'yellow', 'blue', 'red']);
172+
173+
return spy;
174+
}
145175

146-
it('Test 011 : should log everything except error messages to stdout', function () {
147-
logger.setLevel('verbose');
148-
DEFAULT_LEVELS.forEach(function (level) {
149-
logger.log(level, 'message');
176+
beforeEach(function () {
177+
logger.stdoutCursor = new CursorSpy('stdoutCursor');
178+
logger.stderrCursor = new CursorSpy('stderrCursor');
150179
});
151180

152-
// Multiply calls number to 2 because 'write' method is get called twice (with message and EOL)
153-
expect(logger.stdoutCursor.write.calls.count()).toBe((DEFAULT_LEVELS.length - 1) * 2);
154-
expect(logger.stderrCursor.write.calls.count()).toBe(1 * 2);
155-
});
181+
it('Test 010 : should ignore message if severity is less than logger\'s level', function () {
182+
logger.setLevel('error').log('verbose', 'some_messgge');
183+
expect(logger.stdoutCursor.write).not.toHaveBeenCalled();
184+
expect(logger.stderrCursor.write).not.toHaveBeenCalled();
185+
});
156186

157-
it('Test 012 : should log Error objects to stderr despite of loglevel', function () {
158-
logger.setLevel('verbose').log('verbose', new Error());
159-
expect(logger.stdoutCursor.write).not.toHaveBeenCalled();
160-
expect(logger.stderrCursor.write).toHaveBeenCalled();
161-
});
187+
it('Test 011 : should log everything except error messages to stdout', function () {
188+
logger.setLevel('verbose');
189+
DEFAULT_LEVELS.forEach(function (level) {
190+
logger.log(level, 'message');
191+
});
192+
193+
// Multiply calls number to 2 because 'write' method is get called twice (with message and EOL)
194+
expect(logger.stdoutCursor.write.calls.count()).toBe((DEFAULT_LEVELS.length - 1) * 2);
195+
expect(logger.stderrCursor.write.calls.count()).toBe(1 * 2);
196+
});
197+
198+
it('Test 012 : should log Error objects to stderr despite of loglevel', function () {
199+
logger.setLevel('verbose').log('verbose', new Error());
200+
expect(logger.stdoutCursor.write).not.toHaveBeenCalled();
201+
expect(logger.stderrCursor.write).toHaveBeenCalled();
202+
});
162203

163-
it('Test 013 : should handle CordovaError instances separately from Error ones', function () {
164-
const errorMock = new CordovaError();
165-
spyOn(errorMock, 'toString').and.returnValue('error_message');
204+
it('Test 013 : should handle CordovaError instances separately from Error ones', function () {
205+
const errorMock = new CordovaError();
206+
spyOn(errorMock, 'toString').and.returnValue('error_message');
166207

167-
logger.setLevel('verbose').log('verbose', errorMock);
168-
expect(errorMock.toString).toHaveBeenCalled();
169-
expect(logger.stderrCursor.write.calls.argsFor(0)).toMatch('Error: error_message');
208+
logger.setLevel('verbose').log('verbose', errorMock);
209+
expect(errorMock.toString).toHaveBeenCalled();
210+
expect(logger.stderrCursor.write.calls.argsFor(0)).toMatch('Error: error_message');
211+
});
170212
});
171-
});
213+
}
172214

173215
describe('adjustLevel method', function () {
174216
it('Test 014 : should properly adjust log level', function () {

src/CordovaLogger.js

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717
under the License.
1818
*/
1919

20-
const ansi = require('ansi');
21-
const EventEmitter = require('events').EventEmitter;
22-
const EOL = require('os').EOL;
20+
const EventEmitter = require('node:events').EventEmitter;
21+
const EOL = require('node:os').EOL;
22+
const util = require('node:util');
2323
const formatError = require('./util/formatError');
2424

25+
const hasStyleText = !!util.styleText;
26+
const ansi = !hasStyleText ? require('ansi') : null;
27+
2528
const INSTANCE_KEY = Symbol.for('org.apache.cordova.common.CordovaLogger');
2629

2730
/**
@@ -74,10 +77,17 @@ class CordovaLogger {
7477
/** @private */
7578
this.stderr = process.stderr;
7679

77-
/** @private */
78-
this.stdoutCursor = ansi(this.stdout);
79-
/** @private */
80-
this.stderrCursor = ansi(this.stderr);
80+
if (hasStyleText) {
81+
/** @private */
82+
this.stdoutCursor = this.stdout;
83+
/** @private */
84+
this.stderrCursor = this.stderr;
85+
} else {
86+
/** @private */
87+
this.stdoutCursor = ansi(this.stdout);
88+
/** @private */
89+
this.stderrCursor = ansi(this.stderr);
90+
}
8191

8292
this.addLevel(CordovaLogger.VERBOSE, 1000, 'grey');
8393
this.addLevel(CordovaLogger.NORMAL, 2000);
@@ -120,11 +130,17 @@ class CordovaLogger {
120130
}
121131

122132
const color = this.colors[logLevel];
123-
if (color) {
124-
cursor.bold().fg[color]();
125-
}
126133

127-
cursor.write(message).reset().write(EOL);
134+
if (!hasStyleText) {
135+
if (color) {
136+
cursor.bold().fg[color]();
137+
}
138+
139+
cursor.write(message).reset().write(EOL);
140+
} else {
141+
const styles = color ? ['bold', color] : [];
142+
cursor.write(util.styleText(styles, message) + EOL);
143+
}
128144

129145
return this;
130146
}

0 commit comments

Comments
 (0)