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

Issue #969: Jobs with a hash in the name can't be opened #1253

Merged
merged 7 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,30 @@ describe("SpoolProvider Unit Tests", () => {
it("Tests that the URI is encoded", () => {
const uriMock = jest.fn();
Object.defineProperty(vscode, "Uri", { value: uriMock });
const parse = jest.fn();
const mockUri = {
scheme: "testScheme",
authority: "testAuthority",
path: "testPath",
query: "testQuery",
fragment: "testFragment",
fsPath: "testFsPath",
with: jest.fn().mockReturnValue(uriString),
toJSON: jest.fn(),
};

const parse = jest.fn().mockReturnValue(mockUri);
Object.defineProperty(uriMock, "parse", { value: parse });
const query = jest.fn();
Object.defineProperty(uriMock, "query", { value: query });

const uri = spoolprovider.encodeJobFile("sessionName", iJobFile);
expect(parse.mock.calls.length).toEqual(1);
expect(parse.mock.calls[0][0]).toEqual(uriString);
expect(mockUri.with.mock.calls.length).toEqual(1);
expect(mockUri.with.mock.calls[0][0]).toEqual({
path: "TESTJOB.100.STDOUT",
query:
'["sessionName",{"byte-count":128,"job-correlator":"","record-count":1,"records-url":"fake/records","class":"A","ddname":"STDOUT","id":100,"jobid":"100","jobname":"TESTJOB","lrecl":80,"procstep":"","recfm":"FB","stepname":"","subsystem":""}]',
scheme: "zosspool",
});
});

it("Tests that the URI is decoded", () => {
Expand Down
30 changes: 22 additions & 8 deletions packages/zowe-explorer/__tests__/__unit__/job/actions.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import * as dsActions from "../../../src/dataset/actions";
import * as globals from "../../../src/globals";
import { createDatasetSessionNode, createDatasetTree } from "../../../__mocks__/mockCreators/datasets";
import { Profiles } from "../../../src/Profiles";
import * as SpoolProvider from "../../../src/SpoolProvider";

const activeTextEditorDocument = jest.fn();

Expand Down Expand Up @@ -57,8 +58,10 @@ function createGlobalMocks() {
Object.defineProperty(Profiles, "getInstance", { value: jest.fn(), configurable: true });
Object.defineProperty(vscode, "Uri", { value: jest.fn(), configurable: true });
Object.defineProperty(vscode.Uri, "parse", { value: jest.fn(), configurable: true });
Object.defineProperty(vscode.Uri.parse, "with", { value: jest.fn(), configurable: true });
const executeCommand = jest.fn();
Object.defineProperty(vscode.commands, "executeCommand", { value: executeCommand, configurable: true });
Object.defineProperty(SpoolProvider, "encodeJobFile", { value: jest.fn(), configurable: true });
}

// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts
Expand Down Expand Up @@ -660,6 +663,16 @@ describe("Jobs Actions Unit Tests - Function getSpoolContent", () => {
const testJobTree = createJobsTree(session, iJob, imperativeProfile, treeView);
const jesApi = createJesApi(imperativeProfile);
const mockCheckCurrentProfile = jest.fn();
const mockUri: vscode.Uri = {
scheme: "testScheme",
authority: "testAuthority",
path: "testPath",
query: "testQuery",
fragment: "testFragment",
fsPath: "testFsPath",
with: jest.fn(),
toJSON: jest.fn(),
};
bindJesApi(jesApi);

return {
Expand All @@ -672,18 +685,19 @@ describe("Jobs Actions Unit Tests - Function getSpoolContent", () => {
jesApi,
testJobTree,
mockCheckCurrentProfile,
mockUri,
};
}

it("Checking opening of Spool Content", async () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.Uri.parse).mockReturnValueOnce("test" as any);
mocked(SpoolProvider.encodeJobFile).mockReturnValueOnce(blockMocks.mockUri);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
await jobActions.getSpoolContent(blockMocks.testJobTree, "sessionName", blockMocks.iJobFile);

expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith("test");
expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith(blockMocks.mockUri);
expect(mocked(vscode.window.showTextDocument)).toBeCalled();
});
it("Checking opening of Spool Content with Unverified profile", async () => {
Expand All @@ -702,18 +716,18 @@ describe("Jobs Actions Unit Tests - Function getSpoolContent", () => {
}),
});

mocked(vscode.Uri.parse).mockReturnValueOnce("test" as any);
mocked(SpoolProvider.encodeJobFile).mockReturnValueOnce(blockMocks.mockUri);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
await jobActions.getSpoolContent(blockMocks.testJobTree, "sessionName", blockMocks.iJobFile);

expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith("test");
expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith(blockMocks.mockUri);
expect(mocked(vscode.window.showTextDocument)).toBeCalled();
});
it("Checking failed attempt to open Spool Content", async () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

mocked(vscode.Uri.parse).mockImplementationOnce(() => {
mocked(SpoolProvider.encodeJobFile).mockImplementationOnce(() => {
throw new Error("Test");
});
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
Expand All @@ -728,19 +742,19 @@ describe("Jobs Actions Unit Tests - Function getSpoolContent", () => {
const blockMocks = createBlockMocks();

blockMocks.profileInstance.promptCredentials.mockReturnValue(["fake", "fake", "fake"]);
mocked(vscode.Uri.parse).mockReturnValueOnce("test" as any);
mocked(SpoolProvider.encodeJobFile).mockReturnValueOnce(blockMocks.mockUri);
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
await jobActions.getSpoolContent(blockMocks.testJobTree, "sessionName", blockMocks.iJobFile);

expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith("test");
expect(mocked(vscode.workspace.openTextDocument)).toBeCalledWith(blockMocks.mockUri);
expect(mocked(vscode.window.showTextDocument)).toBeCalled();
});
it("Checking failed attempt to open Spool Content with credentials prompt", async () => {
createGlobalMocks();
const blockMocks = createBlockMocks();

blockMocks.profileInstance.promptCredentials.mockReturnValue(["fake", "fake", "fake"]);
mocked(vscode.Uri.parse).mockImplementationOnce(() => {
mocked(SpoolProvider.encodeJobFile).mockImplementationOnce(() => {
throw new Error("Test");
});
mocked(Profiles.getInstance).mockReturnValue(blockMocks.profileInstance);
Expand Down
6 changes: 5 additions & 1 deletion packages/zowe-explorer/src/SpoolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ export default class SpoolProvider implements vscode.TextDocumentContentProvider
*/
export function encodeJobFile(session: string, spool: zowe.IJobFile): vscode.Uri {
const query = JSON.stringify([session, spool]);
return vscode.Uri.parse(`${SpoolProvider.scheme}:${spool.jobname}.${spool.jobid}.${spool.ddname}?${query}`);
return vscode.Uri.parse("").with({
scheme: SpoolProvider.scheme,
path: `${spool.jobname}.${spool.jobid}.${spool.ddname}`,
query,
});
}

/**
Expand Down