Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix .log format for apex log get command -> W-7858918 #20

Merged
merged 5 commits into from
Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 7 additions & 16 deletions packages/apex-node/src/logs/logService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { Connection } from '@salesforce/core';
import { ApexLogGetOptions } from '../types';
import { QueryResult } from '../types/common';
import { nls } from '../i18n';
import * as fs from 'fs';
import * as path from 'path';
import { createFiles } from '../utils';

const MAX_NUM_LOGS = 25;

Expand All @@ -29,30 +29,21 @@ export class LogService {
logIdList.push(options.logId);
}

const saveLogsMap = new Map();

const connectionRequests = logIdList.map(async id => {
const url = `${this.connection.tooling._baseUrl()}/sobjects/ApexLog/${id}/Body`;
const logRecord = await this.toolingRequest(url);
if (options.outputDir) {
this.writeLog(options.outputDir, logRecord, id);
saveLogsMap.set(path.join(options.outputDir, `${id}.log`), logRecord);
smitshah2531 marked this conversation as resolved.
Show resolved Hide resolved
}
return logRecord;
});

const result = await Promise.all(connectionRequests);
return result;
}
createFiles(saveLogsMap);

public async writeLog(
outputDir: string,
logRecord: string,
id: string
): Promise<void> {
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
const filePath = path.join(`${outputDir}`, `${id}.txt`);
const stream = fs.createWriteStream(filePath);
stream.write(logRecord);
stream.end();
return result;
}

public async getLogIds(numberOfLogs: number): Promise<string[]> {
Expand Down
37 changes: 37 additions & 0 deletions packages/apex-node/src/utils/fileSystemHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import * as fs from 'fs';
import * as path from 'path';

export function ensureDirectoryExists(filePath: string): void {
smitshah2531 marked this conversation as resolved.
Show resolved Hide resolved
if (fs.existsSync(filePath)) {
return;
}
ensureDirectoryExists(path.dirname(filePath));
fs.mkdirSync(filePath);
}

export function ensureFileExists(filePath: string): void {
ensureDirectoryExists(path.dirname(filePath));
fs.closeSync(fs.openSync(filePath, 'w'));
}

/**
* Method to save multiple files on disk.
*
* @param fileMap key = filePath, value = file contents
*/
export function createFiles(fileMap: Map<string, string>): void {
for (const filePath of fileMap.keys()) {
ensureFileExists(filePath);

const writeStream = fs.createWriteStream(filePath);
smitshah2531 marked this conversation as resolved.
Show resolved Hide resolved
writeStream.write(fileMap.get(filePath));
writeStream.end();
}
}
8 changes: 8 additions & 0 deletions packages/apex-node/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

export { createFiles } from './fileSystemHandler';
40 changes: 24 additions & 16 deletions packages/apex-node/test/logs/logService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import * as fs from 'fs';
import { createSandbox, SinonSandbox, SinonStub } from 'sinon';
import { LogService } from '../../src/logs/logService';
import * as path from 'path';
import * as stream from 'stream';

const $$ = testSetup();

describe('Apex Log Service Tests', () => {
const testData = new MockTestOrgData();
let mockConnection: Connection;
let sandboxStub: SinonSandbox;
let mkdirStub: SinonStub;
let toolingRequestStub: SinonStub;

beforeEach(async () => {
Expand All @@ -32,7 +32,6 @@ describe('Apex Log Service Tests', () => {
username: testData.username
})
});
mkdirStub = sandboxStub.stub(fs, 'mkdirSync');
toolingRequestStub = sandboxStub.stub(
LogService.prototype,
'toolingRequest'
Expand Down Expand Up @@ -132,7 +131,15 @@ describe('Apex Log Service Tests', () => {
const filePath = path.join('file', 'path', 'logs');
const logIds = ['07WgsWfad', '9SiomgS'];
sandboxStub.stub(LogService.prototype, 'getLogIds').resolves(logIds);

const createStreamStub = sandboxStub.stub(fs, 'createWriteStream');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createStreamStub.onCall(0).returns(new stream.PassThrough() as any);
smitshah2531 marked this conversation as resolved.
Show resolved Hide resolved
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createStreamStub.onCall(1).returns(new stream.PassThrough() as any);
sandboxStub.stub(fs, 'closeSync');
sandboxStub.stub(fs, 'openSync');

const logs = ['48jnskd', '57fskjf'];
toolingRequestStub.onFirstCall().resolves(logs[0]);
toolingRequestStub.onSecondCall().resolves(logs[1]);
Expand All @@ -144,25 +151,26 @@ describe('Apex Log Service Tests', () => {
expect(createStreamStub.callCount).to.eql(2);
});

it('should create directory if it does not exist', async () => {
it('should successfully create a .log file', async () => {
const apexLogGet = new LogService(mockConnection);
const filePath = path.join('Users', 'smit.shah', 'Desktop', 'mod');
const logIds = ['07WgsWfad', '9SiomgS'];
const logs = ['48jnskd', '57fskjf'];
sandboxStub.stub(LogService.prototype, 'getLogIds').resolves(logIds);
const existsStub = sandboxStub.stub(fs, 'existsSync');
existsStub.onFirstCall().returns(false);
existsStub.onSecondCall().returns(true);
const filePath = path.join('path', 'to', 'logs');
const logIds = ['07WgsWfad'];
const logs = ['log content'];
const logsPath = path.join(filePath, `${logIds[0]}.log`);
sandboxStub.stub(fs, 'existsSync').returns(true);
const createStreamStub = sandboxStub.stub(fs, 'createWriteStream');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createStreamStub.onCall(0).returns(new stream.PassThrough() as any);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
createStreamStub.onCall(1).returns(new stream.PassThrough() as any);
sandboxStub.stub(fs, 'closeSync');
sandboxStub.stub(fs, 'openSync');
toolingRequestStub.onFirstCall().resolves(logs[0]);
toolingRequestStub.onSecondCall().resolves(logs[1]);
const response = await apexLogGet.getLogs({
numberOfLogs: 2,
await apexLogGet.getLogs({
logId: '07WgsWfad',
outputDir: filePath
});
expect(response.length).to.eql(2);
expect(createStreamStub.callCount).to.eql(2);
expect(existsStub.callCount).to.eql(2);
expect(mkdirStub.callCount).to.eql(1);
expect(createStreamStub.calledWith(logsPath)).to.be.true;
});
});
70 changes: 70 additions & 0 deletions packages/apex-node/test/utils/fileSystemHandler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2020, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import * as fsUtil from '../../src/utils/fileSystemHandler';
import { createSandbox, SinonStub } from 'sinon';
import { expect } from 'chai';
import { join } from 'path';
import * as fs from 'fs';

const sb = createSandbox();

describe('File System Utils', () => {
describe('ensureDirectoryExists', () => {
let mkdirStub: SinonStub;
let existsStub: SinonStub;

beforeEach(() => {
mkdirStub = sb.stub(fs, 'mkdirSync');
existsStub = sb.stub(fs, 'existsSync');
});

afterEach(() => {
sb.restore();
});

it('should return immediately if file or directory already exists', () => {
const path = join('path', 'to', 'dir');
existsStub.withArgs(path).returns(true);

fsUtil.ensureDirectoryExists(path);

expect(mkdirStub.notCalled).to.be.true;
});

it('should create nested directories as needed', () => {
const path = join('path', 'to');
const path2 = join(path, 'dir');
const path3 = join(path2, 'dir2');
existsStub.returns(false);
existsStub.withArgs(path).returns(true);

fsUtil.ensureDirectoryExists(path3);

expect(mkdirStub.firstCall.args[0]).to.equal(path2);
expect(mkdirStub.secondCall.args[0]).to.equal(path3);
});
});

describe('ensureFileExists', () => {
afterEach(() => {
sb.restore();
});

it('should ensure file exists', () => {
const path = join('path', 'to', 'a', 'file.x');
const closeStub = sb.stub(fs, 'closeSync');
const openStub = sb.stub(fs, 'openSync');
openStub.returns(123);
const existsSyncStub = sb.stub(fs, 'existsSync').returns(true);

fsUtil.ensureFileExists(path);

expect(existsSyncStub.calledBefore(openStub)).to.be.true;
expect(closeStub.firstCall.args[0]).to.equal(123);
});
});
});