Skip to content

Commit

Permalink
fix: fix entry not found when launching apex replay debugger from ape…
Browse files Browse the repository at this point in the history
…x class (#5326)

* fix: correct resolution of the test class file URI

@W-12508503@

* chore: post telemtry when file flush renames a file

* chore: add tests

* chore: fix copyright year

* chore: update eslint header template for new year
  • Loading branch information
peternhale authored Jan 9, 2024
1 parent 0ac3c72 commit 1631048
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 16 deletions.
2 changes: 1 addition & 1 deletion config/base-eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"",
{
"pattern": " \\* Copyright \\(c\\) \\d{4}, salesforce\\.com, inc\\.",
"template": " * Copyright (c) 2023, salesforce.com, inc."
"template": " * Copyright (c) 2024, salesforce.com, inc."
},
" * All rights reserved.",
" * Licensed under the BSD 3-Clause license.",
Expand Down
17 changes: 15 additions & 2 deletions packages/salesforcedx-utils-vscode/src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* 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 { realpathSync } from 'fs';
import { basename } from 'path';
import { telemetryService } from '../telemetry';

export const isNullOrUndefined = (object: any): object is null | undefined => {
return object === null || object === undefined;
Expand All @@ -28,7 +30,7 @@ export const flushFilePath = (filePath: string): string => {
return filePath;
}

let nativePath = fs.realpathSync.native(filePath);
let nativePath = realpathSync.native(filePath);
if (/^win32/.test(process.platform)) {
// The file path on Windows is in the form of "c:\Users\User Name\foo.cls".
// When called, fs.realpathSync.native() is returning the file path back as
Expand All @@ -39,6 +41,17 @@ export const flushFilePath = (filePath: string): string => {
nativePath = nativePath.charAt(0).toLowerCase() + nativePath.slice(1);
}

// check if the native path is the same case insensitive and then case sensitive
// so that condition can be reported via telemetry
if (
filePath !== nativePath &&
filePath.toLowerCase() === nativePath.toLowerCase()
) {
telemetryService.sendEventData('FilePathCaseMismatch', {
originalPath: basename(filePath),
nativePath: basename(nativePath)
});
}
return nativePath;
};

Expand Down
13 changes: 3 additions & 10 deletions packages/salesforcedx-utils-vscode/src/telemetry/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

/**
* This file is intentionally left blank. Telemetry Service is exported
* in the root of salesforcedx-utils-vscode.
*
* If your service or util is dependent on telemetry service, please leave the index
* of your service folder empty as well, and export your service in src/index.ts.
* Otherwise, you will have a duplicate copy of telemetry service in your folder,
* for webpack treats the index of each folder as an entry point
* and bundles all of its dependencies.
*/
import { TelemetryService } from './telemetry';

export const telemetryService = TelemetryService.getInstance();
40 changes: 40 additions & 0 deletions packages/salesforcedx-utils-vscode/test/jest/helpers/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2024, 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 { realpathSync } from 'fs';
import { TelemetryService } from '../../../src';
import { flushFilePath } from '../../../src/helpers/utils';

describe('flushFilePath', () => {
let teleSpy: jest.SpyInstance;
beforeEach(() => {
jest.mock('fs');
jest.mock('../../../src/context/workspaceContextUtil');
});
it('should detect changes in character casing', () => {
const originalPath = './test.txt';
const alteredPath = './TEST.txt';

jest.spyOn(realpathSync, 'native').mockReturnValue(alteredPath);
teleSpy = jest.spyOn(TelemetryService.prototype, 'sendEventData');

const r = flushFilePath(originalPath);
expect(r).toEqual(alteredPath);
expect(teleSpy).toHaveBeenCalledTimes(1);
});

it('should not send to telemetry if there are no changes in character casing', () => {
const originalPath = './test.txt';
const alteredPath = './test.txt';

jest.spyOn(realpathSync, 'native').mockReturnValue(alteredPath);
teleSpy = jest.spyOn(TelemetryService.prototype, 'sendEventData');

const r = flushFilePath(originalPath);
expect(r).toEqual(alteredPath);
expect(teleSpy).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,14 @@ const getApexTestClassName = async (

const testOutlineProvider = getTestOutlineProvider();
await testOutlineProvider.refresh();
let testClassName = testOutlineProvider.getTestClassName(sourceUri);
// This is a little bizarre. Intellisense is reporting that getTestClassName() returns a string,
// but it actually it returns string | undefined. Well, regardless, since flushFilePath() takes
// a string (and guards against empty strings) using the Non-null assertion operator
// (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator)
// fixes the issue.
testClassName = fileUtils.flushFilePath(testClassName || '');
const flushedUri = vscode.Uri.file(fileUtils.flushFilePath(sourceUri.fsPath));

return testClassName;
return testOutlineProvider.getTestClassName(flushedUri);
};

const launchAnonymousApexReplayDebugger = async () => {
Expand Down

0 comments on commit 1631048

Please sign in to comment.