diff --git a/.github/release.config.js b/.github/release.config.js index 371f160a16..3c24ff0ea1 100644 --- a/.github/release.config.js +++ b/.github/release.config.js @@ -6,20 +6,24 @@ module.exports = { level: "minor" }, { - name: "v2-lts", - channel: "zowe-v2-lts", + name: "v1-lts", + channel: "zowe-v1-lts", level: "patch" }, { - name: "v1-lts", - channel: "zowe-v1-lts", + name: "v2-lts", + channel: "zowe-v2-lts", level: "patch" }, { name: "release/3.*", - channel: "next", - prerelease: true, + channel: "latest", + level: "patch" } + // { + // name: "next", + // prerelease: true + // } ], plugins: [ [ @@ -45,7 +49,7 @@ module.exports = { { $cwd: "packages/zowe-explorer-api", aliasTags: { - "latest": ["zowe-v2-lts"], + "latest": ["zowe-v3-lts"], }, npmPublish: true, tarballDir: "dist", diff --git a/.github/workflows/zowe-explorer-samples.yml b/.github/workflows/zowe-explorer-samples.yml deleted file mode 100644 index 1c03446776..0000000000 --- a/.github/workflows/zowe-explorer-samples.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Zowe Explorer Samples CI - -on: - push: - paths: - - .github/workflows/zowe-explorer-samples.yml - - packages/zowe-explorer-api/** - - samples/** - pull_request: - paths: - - .github/workflows/zowe-explorer-samples.yml - - packages/zowe-explorer-api/** - - samples/** - -jobs: - samples-build: - runs-on: ubuntu-latest - timeout-minutes: 30 - - concurrency: - group: node-${{ matrix.node-version }}-ze-samples-ci-${{ github.ref }} - cancel-in-progress: true - - strategy: - # Continue to run tests on the other systems if one fails - fail-fast: false - matrix: - node-version: [18.x, 20.x] - - if: (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) && !contains(github.event.head_commit.message, '[ci skip]') - - steps: - - name: Check out code - uses: actions/checkout@v4 - - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - # install pnpm - - run: npm install -g pnpm@8 - - - run: pnpm config set network-timeout 60000 && pnpm i - - run: pnpm --filter "zowe-explorer-api" build - - run: for dir in samples/*; do pushd $dir && pnpm --ignore-workspace i && pnpm run compile && popd; done - - shell: bash diff --git a/.gitignore b/.gitignore index d66ecd848f..a158a3e2b6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ out lib !packages/eslint-plugin-zowe-explorer/**/lib logs -testProfileData.ts results *.log npm-shrinkwrap.json @@ -24,7 +23,6 @@ coverage/ v8-compile-cache-0/ dist/ prebuilds/ -samples/**/pnpm-lock.yaml packages/zowe-explorer/**/.wdio-vscode-service packages/zowe-explorer/__tests__/**/.zowe packages/zowe-explorer/__tests__/**/.env diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 0000000000..9f9f23abf2 --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1,4 @@ +sonar.sources=packages/**/src +sonar.tests=packages/**/__tests__ +sonar.test.inclusions=**/*.test.ts,**/*.steps.ts +sonar.cpd.exclusions=packages/**/__tests__ diff --git a/lerna.json b/lerna.json index 8bf8a93ddb..b7b93b092e 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.1.0-SNAPSHOT", + "version": "3.0.1", "command": { "version": { "forcePublish": true, diff --git a/package.json b/package.json index 62e382e2ef..3a7deeb52c 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,6 @@ "test:parallel": "pnpm -r --parallel --color test", "package": "pnpm -r --sequential package", "preinstall": "npx only-allow pnpm", - "update-sdks": "pnpm -r update \"@zowe/*@next\" \"!@zowe/zowe-explorer-api\" \"!@zowe/zos-ftp-for-zowe-cli\"" + "update-sdks": "pnpm -r update \"@zowe/*@zowe-v3-lts\" \"!@zowe/zowe-explorer-api\" \"!@zowe/zos-ftp-for-zowe-cli\"" } } diff --git a/packages/eslint-plugin-zowe-explorer/CHANGELOG.md b/packages/eslint-plugin-zowe-explorer/CHANGELOG.md index 52b496f5f7..032a4a6c76 100644 --- a/packages/eslint-plugin-zowe-explorer/CHANGELOG.md +++ b/packages/eslint-plugin-zowe-explorer/CHANGELOG.md @@ -2,10 +2,6 @@ All notable changes to the "eslint-plugin-zowe-explorer" package will be documen ## TBD Release -### New features and enhancements - -### Bug fixes - ## `3.0.0` ### New features and enhancements diff --git a/packages/zowe-explorer-api/CHANGELOG.md b/packages/zowe-explorer-api/CHANGELOG.md index 199c8c475f..82122efd4e 100644 --- a/packages/zowe-explorer-api/CHANGELOG.md +++ b/packages/zowe-explorer-api/CHANGELOG.md @@ -4,10 +4,10 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t ## TBD Release -### New features and enhancements - ### Bug fixes +- Updated the `ZoweTreeNode.setProfileToChoice` function so that it propagates profile changes to its child nodes. [#3150](https://github.com/zowe/zowe-explorer-vscode/issues/3150) + ## `3.0.0` ### New features and enhancements diff --git a/packages/zowe-explorer-api/__tests__/__unit__/tree/ZoweTreeNode.unit.test.ts b/packages/zowe-explorer-api/__tests__/__unit__/tree/ZoweTreeNode.unit.test.ts index fe3ca62227..c8a0ae5618 100644 --- a/packages/zowe-explorer-api/__tests__/__unit__/tree/ZoweTreeNode.unit.test.ts +++ b/packages/zowe-explorer-api/__tests__/__unit__/tree/ZoweTreeNode.unit.test.ts @@ -94,6 +94,7 @@ describe("ZoweTreeNode", () => { it("setProfileToChoice should update profile for associated FSProvider entry", () => { const node = makeNode("test", vscode.TreeItemCollapsibleState.None, undefined); + node.resourceUri = vscode.Uri.file(__dirname); const fsEntry = { metadata: { profile: { name: "oldProfile" }, @@ -108,4 +109,23 @@ describe("ZoweTreeNode", () => { expect(node.getProfileName()).toBe("newProfile"); expect(fsEntry.metadata.profile.name).toBe("newProfile"); }); + + it("setProfileToChoice should update child nodes with the new profile", () => { + const node = makeNode("test", vscode.TreeItemCollapsibleState.Expanded, undefined); + const nodeChild = makeNode("child", vscode.TreeItemCollapsibleState.None, undefined); + node.children = [nodeChild as any]; + const setProfileToChoiceChildMock = jest.spyOn(nodeChild, "setProfileToChoice").mockImplementation(); + const fsEntry = { + metadata: { + profile: { name: "oldProfile" }, + }, + }; + const mockNewProfile = { name: "newProfile" } as unknown as imperative.IProfileLoaded; + const mockProvider = { + lookup: jest.fn().mockReturnValue(fsEntry), + } as unknown as BaseProvider; + node.setProfileToChoice(mockNewProfile, mockProvider); + expect(node.getProfileName()).toBe("newProfile"); + expect(setProfileToChoiceChildMock).toHaveBeenCalledWith(mockNewProfile, mockProvider); + }); }); diff --git a/packages/zowe-explorer-api/package.json b/packages/zowe-explorer-api/package.json index 07b3229781..7704ac56c9 100644 --- a/packages/zowe-explorer-api/package.json +++ b/packages/zowe-explorer-api/package.json @@ -28,15 +28,15 @@ }, "dependencies": { "@types/vscode": "^1.53.2", - "@zowe/core-for-zowe-sdk": "8.0.0", - "@zowe/imperative": "8.0.0", - "@zowe/secrets-for-zowe-sdk": "8.0.0", - "@zowe/zos-console-for-zowe-sdk": "8.0.0", - "@zowe/zos-files-for-zowe-sdk": "8.0.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.0.0", - "@zowe/zos-tso-for-zowe-sdk": "8.0.0", - "@zowe/zos-uss-for-zowe-sdk": "8.0.0", - "@zowe/zosmf-for-zowe-sdk": "8.0.0", + "@zowe/core-for-zowe-sdk": "^8.1.1", + "@zowe/imperative": "^8.1.0", + "@zowe/secrets-for-zowe-sdk": "^8.1.0", + "@zowe/zos-console-for-zowe-sdk": "^8.1.1", + "@zowe/zos-files-for-zowe-sdk": "^8.1.1", + "@zowe/zos-jobs-for-zowe-sdk": "^8.1.1", + "@zowe/zos-tso-for-zowe-sdk": "^8.1.1", + "@zowe/zos-uss-for-zowe-sdk": "^8.1.1", + "@zowe/zosmf-for-zowe-sdk": "^8.1.1", "deep-object-diff": "^1.1.9", "mustache": "^4.2.0", "semver": "^7.6.0" diff --git a/packages/zowe-explorer-api/src/fs/types/abstract.ts b/packages/zowe-explorer-api/src/fs/types/abstract.ts index f29305bc6b..b26c64ba59 100644 --- a/packages/zowe-explorer-api/src/fs/types/abstract.ts +++ b/packages/zowe-explorer-api/src/fs/types/abstract.ts @@ -68,7 +68,6 @@ export type ConflictData = { export interface IFileSystemEntry extends vscode.FileStat { name: string; metadata: EntryMetadata; - type: vscode.FileType; wasAccessed: boolean; data?: Uint8Array; } diff --git a/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts b/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts index b6892f23a2..c2fad23677 100644 --- a/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts +++ b/packages/zowe-explorer-api/src/profiles/ZoweExplorerZosmfApi.ts @@ -382,6 +382,7 @@ export namespace ZoweExplorerZosmf { */ export class CommandApi extends CommonApi implements MainframeInteraction.ICommand { public issueTsoCommandWithParms(command: string, parms: zostso.IStartTsoParms): Promise { + // eslint-disable-next-line deprecation/deprecation return zostso.IssueTso.issueTsoCommand(this.getSession(), parms.account, command, parms); } diff --git a/packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts b/packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts index d65612211e..392ad02020 100644 --- a/packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts +++ b/packages/zowe-explorer-api/src/tree/IZoweTreeNode.ts @@ -181,6 +181,11 @@ export interface IZoweDatasetTreeNode extends IZoweTreeNode { */ encoding?: string; + /** + * Use Dataset-specific tree node for children. + */ + children?: IZoweDatasetTreeNode[]; + /** * Retrieves child nodes of this IZoweDatasetTreeNode * @@ -296,6 +301,11 @@ export interface IZoweUSSTreeNode extends IZoweTreeNode { */ onUpdateEmitter?: vscode.EventEmitter; + /** + * Use USS-specific tree node for children. + */ + children?: IZoweUSSTreeNode[]; + /** * Event that fires whenever an existing node is updated. */ diff --git a/packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts b/packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts index 7c03c4c2c2..bdcc061f99 100644 --- a/packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts +++ b/packages/zowe-explorer-api/src/tree/ZoweTreeNode.ts @@ -107,9 +107,14 @@ export class ZoweTreeNode extends vscode.TreeItem { // Don't reassign profile, we want to keep object reference shared across nodes this.profile.profile = aProfile.profile; } - const fsEntry = fsProvider?.lookup(this.resourceUri, true); - if (fsEntry != null) { - fsEntry.metadata.profile = aProfile; + if (this.resourceUri != null) { + const fsEntry = fsProvider?.lookup(this.resourceUri, true); + if (fsEntry != null) { + fsEntry.metadata.profile = aProfile; + } + } + for (const child of this.children) { + (child as unknown as ZoweTreeNode).setProfileToChoice(aProfile, fsProvider); } } /** diff --git a/packages/zowe-explorer-ftp-extension/CHANGELOG.md b/packages/zowe-explorer-ftp-extension/CHANGELOG.md index ea613f1e86..a671e8540b 100644 --- a/packages/zowe-explorer-ftp-extension/CHANGELOG.md +++ b/packages/zowe-explorer-ftp-extension/CHANGELOG.md @@ -2,10 +2,10 @@ All notable changes to the "zowe-explorer-ftp-extension" extension will be docum ## TBD Release -### New features and enhancements - ### Bug fixes +- Fixed bug where the `getContents` MVS and USS APIs failed to return whenever a local file path was provided. [#3199](https://github.com/zowe/zowe-explorer-vscode/issues/3199) + ## `3.0.0` ### New features and enhancements diff --git a/packages/zowe-explorer-ftp-extension/__mocks__/mockUtils.ts b/packages/zowe-explorer-ftp-extension/__mocks__/mockUtils.ts new file mode 100644 index 0000000000..06a03e3e0a --- /dev/null +++ b/packages/zowe-explorer-ftp-extension/__mocks__/mockUtils.ts @@ -0,0 +1,13 @@ +/** + * This program and the accompanying materials are made available under the terms of the + * Eclipse Public License v2.0 which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-v20.html + * + * SPDX-License-Identifier: EPL-2.0 + * + * Copyright Contributors to the Zowe Project. + * + */ + +// Idea is borrowed from: https://github.com/kulshekhar/ts-jest/blob/master/src/util/testing.ts +export const mocked = any>(fn: T): jest.Mock> => fn as any; diff --git a/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Mvs/ZoweExplorerFtpMvsApi.unit.test.ts b/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Mvs/ZoweExplorerFtpMvsApi.unit.test.ts index 3d90f828e8..cca7a1954f 100644 --- a/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Mvs/ZoweExplorerFtpMvsApi.unit.test.ts +++ b/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Mvs/ZoweExplorerFtpMvsApi.unit.test.ts @@ -20,6 +20,7 @@ import * as tmp from "tmp"; import { Gui, imperative } from "@zowe/zowe-explorer-api"; import * as globals from "../../../src/globals"; import { ZoweFtpExtensionError } from "../../../src/ZoweFtpExtensionError"; +import { mocked } from "../../../__mocks__/mockUtils"; // two methods to mock modules: create a __mocks__ file for zowe-explorer-api.ts and direct mock for extension.ts jest.mock("../../../__mocks__/@zowe/zowe-explorer-api.ts"); @@ -93,6 +94,7 @@ describe("FtpMvsApi", () => { expect(result.apiResponse.etag).toHaveLength(64); expect(DataSetUtils.downloadDataSet).toHaveBeenCalledTimes(1); + expect(mocked(DataSetUtils.downloadDataSet).mock.calls[0][2].localFile).toBe(localFile); expect(MvsApi.releaseConnection).toHaveBeenCalled(); expect((response._readableState.buffer.head?.data ?? response._readableState.buffer).toString()).toContain("Hello world"); diff --git a/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Uss/ZoweExplorerFtpUssApi.unit.test.ts b/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Uss/ZoweExplorerFtpUssApi.unit.test.ts index d2e5718670..e2a60713c0 100644 --- a/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Uss/ZoweExplorerFtpUssApi.unit.test.ts +++ b/packages/zowe-explorer-ftp-extension/__tests__/__unit__/Uss/ZoweExplorerFtpUssApi.unit.test.ts @@ -21,6 +21,7 @@ import * as globals from "../../../src/globals"; import { ZoweFtpExtensionError } from "../../../src/ZoweFtpExtensionError"; import * as tmp from "tmp"; import { imperative } from "@zowe/zowe-explorer-api"; +import { mocked } from "../../../__mocks__/mockUtils"; // two methods to mock modules: create a __mocks__ file for zowe-explorer-api.ts and direct mock for extension.ts jest.mock("../../../__mocks__/@zowe/zowe-explorer-api.ts"); @@ -78,6 +79,7 @@ describe("FtpUssApi", () => { expect(result.apiResponse.etag).toHaveLength(64); expect(UssUtils.downloadFile).toHaveBeenCalledTimes(1); + expect(mocked(UssUtils.downloadFile).mock.calls[0][2].localFile).toBe(localFile); expect(UssApi.releaseConnection).toHaveBeenCalled(); expect((response._readableState.buffer.head?.data ?? response._readableState.buffer).toString()).toContain("Hello world"); diff --git a/packages/zowe-explorer-ftp-extension/package.json b/packages/zowe-explorer-ftp-extension/package.json index 7ca96cbe59..b6eaa89dcd 100644 --- a/packages/zowe-explorer-ftp-extension/package.json +++ b/packages/zowe-explorer-ftp-extension/package.json @@ -52,9 +52,9 @@ "vscode": "^1.79.0" }, "dependencies": { - "@zowe/zos-files-for-zowe-sdk": "8.0.0", - "@zowe/zos-ftp-for-zowe-cli": "3.0.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.0.0", + "@zowe/zos-files-for-zowe-sdk": "^8.1.1", + "@zowe/zos-ftp-for-zowe-cli": "^3.0.0", + "@zowe/zos-jobs-for-zowe-sdk": "^8.1.1", "@zowe/zowe-explorer-api": "3.1.0-SNAPSHOT", "tmp": "0.2.3" }, diff --git a/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpMvsApi.ts b/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpMvsApi.ts index 7ae41a5810..a8f39a0f51 100644 --- a/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpMvsApi.ts +++ b/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpMvsApi.ts @@ -84,7 +84,7 @@ export class FtpMvsApi extends AbstractFtpApi implements MainframeInteraction.IM const result = this.getDefaultResponse(); const transferOptions = { encoding: options.encoding, - localFile: undefined, + localFile: options.file, transferType: CoreUtils.getBinaryTransferModeOrDefault(options.binary), }; const fileOrStreamSpecified = options.file != null || options.stream != null; diff --git a/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpUssApi.ts b/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpUssApi.ts index e536cefdb1..4ad999d339 100644 --- a/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpUssApi.ts +++ b/packages/zowe-explorer-ftp-extension/src/ZoweExplorerFtpUssApi.ts @@ -64,7 +64,7 @@ export class FtpUssApi extends AbstractFtpApi implements MainframeInteraction.IU const result = this.getDefaultResponse(); const transferOptions = { transferType: CoreUtils.getBinaryTransferModeOrDefault(options.binary), - localFile: undefined, + localFile: options.file, size: 1, }; const fileOrStreamSpecified = options.file != null || options.stream != null; diff --git a/packages/zowe-explorer/CHANGELOG.md b/packages/zowe-explorer/CHANGELOG.md index de704ac041..d356543b2a 100644 --- a/packages/zowe-explorer/CHANGELOG.md +++ b/packages/zowe-explorer/CHANGELOG.md @@ -4,10 +4,19 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen ## TBD Release -### New features and enhancements - ### Bug fixes +- Fixed an issue where opening sequential data sets within favorited searches resulted in an error. [#3163](https://github.com/zowe/zowe-explorer-vscode/pull/3163) +- Fixed an issue where automatic file extension detection identified file types incorrectly. [#3181](https://github.com/zowe/zowe-explorer-vscode/pull/3181) +- Fixed an issue where Zowe Explorer displayed a "No Zowe client configurations" prompt when a project user configuration existed but no global configuration was present. [#3168](https://github.com/zowe/zowe-explorer-vscode/issues/3168) +- Fixed an issue where the `ProfilesUtils.getProfileInfo` function returned a new `ProfileInfo` instance that ignored the `ZOWE_CLI_HOME` environment variable and workspace paths. [#3168](https://github.com/zowe/zowe-explorer-vscode/issues/3168) +- Fixed an issue where the location prompt for the `Create Directory` and `Create File` USS features would appear even when a path is already set for the profile or parent folder. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183) +- Fixed an issue where the `Create Directory` and `Create File` features would continue processing when the first prompt was dismissed, causing an incorrect URI to be generated. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183) +- Fixed an issue where the `Create Directory` and `Create File` features would incorrectly handle user-specified locations with trailing slashes. [#3183](https://github.com/zowe/zowe-explorer-vscode/pull/3183) +- Fixed an issue where a 401 error could occur when opening PDS members after updating credentials within the same user session. [#3150](https://github.com/zowe/zowe-explorer-vscode/issues/3150) +- Fixed issue where switching from token-based authentication to user/password would cause an error for nested profiles. [#3142](https://github.com/zowe/zowe-explorer-vscode/issues/3142) +- Fixed the "Edit Profile" operation to open the correct files when both global and project team configs are present. [#3125](https://github.com/zowe/zowe-explorer-vscode/issues/3125) + ## `3.0.0` ### New features and enhancements diff --git a/packages/zowe-explorer/__tests__/__mocks__/@zowe/imperative.ts b/packages/zowe-explorer/__tests__/__mocks__/@zowe/imperative.ts index f53b84a82c..3e3a844d4e 100644 --- a/packages/zowe-explorer/__tests__/__mocks__/@zowe/imperative.ts +++ b/packages/zowe-explorer/__tests__/__mocks__/@zowe/imperative.ts @@ -17,6 +17,10 @@ import * as os from "os"; import * as path from "path"; const log4js = require("log4js"); +export class EventProcessor { + public emitZoweEvent(eventName: string): void {} +} + export enum ProfLocType { OLD_PROFILE = 0, // an old-school profile TEAM_CONFIG = 1, // a team configuration diff --git a/packages/zowe-explorer/__tests__/__mocks__/mockCreators/jobs.ts b/packages/zowe-explorer/__tests__/__mocks__/mockCreators/jobs.ts index 5ff05ac1ba..5c787e51a1 100644 --- a/packages/zowe-explorer/__tests__/__mocks__/mockCreators/jobs.ts +++ b/packages/zowe-explorer/__tests__/__mocks__/mockCreators/jobs.ts @@ -160,8 +160,8 @@ export function createJobInfoNode(session: any, profile: imperative.IProfileLoad collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: session.getSessionNode(), profile, + contextOverride: Constants.INFORMATION_CONTEXT, }); - jobNode.contextValue = Constants.INFORMATION_CONTEXT; return jobNode; } diff --git a/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts index 93cafe06af..813d265b74 100644 --- a/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/configuration/Profiles.unit.test.ts @@ -28,7 +28,7 @@ import { } from "../../__mocks__/mockCreators/shared"; import { createDatasetSessionNode, createDatasetTree } from "../../__mocks__/mockCreators/datasets"; import { createProfileManager } from "../../__mocks__/mockCreators/profiles"; -import { imperative, Gui, ZoweTreeNode, ZoweVsCodeExtension, IZoweTree, IZoweTreeNode, Validation } from "@zowe/zowe-explorer-api"; +import { imperative, Gui, ZoweTreeNode, ZoweVsCodeExtension, IZoweTree, IZoweTreeNode, Validation, FileManagement } from "@zowe/zowe-explorer-api"; import { Profiles } from "../../../src/configuration/Profiles"; import { ZoweExplorerExtender } from "../../../src/extending/ZoweExplorerExtender"; import { ZoweExplorerApiRegister } from "../../../src/extending/ZoweExplorerApiRegister"; @@ -403,6 +403,7 @@ describe("Profiles Unit Tests - Function editZoweConfigFile", () => { const spyQuickPick = jest.spyOn(Gui, "showQuickPick"); spyQuickPick.mockResolvedValueOnce("Global: in the Zowe home directory" as any); + jest.spyOn(FileManagement, "getZoweDir").mockReturnValue("file://globalPath/.zowe"); const spyOpenFile = jest.spyOn(globalMocks.mockProfileInstance, "openConfigFile"); await Profiles.getInstance().editZoweConfigFile(); expect(spyQuickPick).toHaveBeenCalled(); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts index cd838c7550..c7bbf3c1a1 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/ZoweTreeProvider.unit.test.ts @@ -276,7 +276,7 @@ describe("Tree Provider unit tests, function getTreeItem", () => { }); }); -describe("Tree Provider unit tests, function getTreeItem", () => { +describe("Tree Provider unit tests, function flipState", () => { it("Testing that expand tree is executed successfully", async () => { const globalMocks = await createGlobalMocks(); const spy = jest.spyOn(ZoweLogger, "trace"); @@ -287,14 +287,17 @@ describe("Tree Provider unit tests, function getTreeItem", () => { session: globalMocks.testSession, }); folder.contextValue = Constants.USS_DIR_CONTEXT; + folder.dirty = false; // Testing flipState to open await globalMocks.testUSSTree.flipState(folder, true); expect(JSON.stringify(folder.iconPath)).toContain("folder-open.svg"); + expect(folder.dirty).toBe(false); // Testing flipState to closed await globalMocks.testUSSTree.flipState(folder, false); expect(JSON.stringify(folder.iconPath)).toContain("folder-closed.svg"); + expect(folder.dirty).toBe(true); expect(spy).toHaveBeenCalled(); spy.mockClear(); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts index c8d1301585..dcfa23e152 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetActions.unit.test.ts @@ -871,57 +871,6 @@ describe("Dataset Actions Unit Tests - Function deleteDataset", () => { }); }); -describe("Dataset Actions Unit Tests - Function enterPattern", () => { - afterAll(() => jest.restoreAllMocks()); - - it("Checking common dataset filter action", async () => { - createGlobalMocks(); - const blockMocks = createBlockMocksShared(); - const node = new ZoweDatasetNode({ - label: "node", - collapsibleState: vscode.TreeItemCollapsibleState.None, - parentNode: blockMocks.datasetSessionNode, - }); - node.pattern = "TEST"; - node.contextValue = Constants.DS_SESSION_CONTEXT; - - const mySpy = mocked(vscode.window.showInputBox).mockResolvedValue("test"); - await DatasetActions.enterPattern(node, blockMocks.testDatasetTree); - - expect(mySpy).toHaveBeenCalledWith( - expect.objectContaining({ - prompt: "Search Data Sets: use a comma to separate multiple patterns", - value: node.pattern, - }) - ); - expect(mocked(Gui.showMessage)).not.toHaveBeenCalled(); - }); - it("Checking common dataset filter failed attempt", async () => { - createGlobalMocks(); - const blockMocks = createBlockMocksShared(); - const node = new ZoweDatasetNode({ - label: "node", - collapsibleState: vscode.TreeItemCollapsibleState.None, - parentNode: blockMocks.datasetSessionNode, - }); - node.pattern = "TEST"; - node.contextValue = Constants.DS_SESSION_CONTEXT; - - mocked(vscode.window.showInputBox).mockResolvedValueOnce(""); - await DatasetActions.enterPattern(node, blockMocks.testDatasetTree); - - expect(mocked(Gui.showMessage)).toHaveBeenCalledWith("You must enter a pattern."); - }); - it("Checking favorite dataset filter action", async () => { - createGlobalMocks(); - const blockMocks = createBlockMocksShared(); - const favoriteSample = new ZoweDatasetNode({ label: "[sestest]: HLQ.TEST", collapsibleState: vscode.TreeItemCollapsibleState.None }); - - await DatasetActions.enterPattern(favoriteSample, blockMocks.testDatasetTree); - expect(blockMocks.testDatasetTree.addSession).toHaveBeenCalledWith({ sessionName: "sestest" }); - }); -}); - describe("Dataset Actions Unit Tests - Function showAttributes", () => { function createBlockMocks() { const session = createISession(); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts index f08c3e802e..1cb7e8149f 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetTree.unit.test.ts @@ -549,30 +549,6 @@ describe("Dataset Tree Unit Tests - Function getChildren", () => { expect(loadProfilesForFavoritesSpy).toHaveBeenCalledWith(log, favProfileNode); }); - - it("returns 'No data sets found' if there are no children", async () => { - createGlobalMocks(); - const blockMocks = createBlockMocks(); - - mocked(Profiles.getInstance).mockReturnValue(blockMocks.profile); - mocked(vscode.window.createTreeView).mockReturnValueOnce(blockMocks.treeView); - const testTree = new DatasetTree(); - testTree.mSessionNodes.push(blockMocks.datasetSessionNode); - const parent = new ZoweDatasetNode({ - label: "BRTVS99.PUBLIC", - collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, - parentNode: testTree.mSessionNodes[1], - }); - parent.dirty = true; - jest.spyOn(parent, "getChildren").mockResolvedValueOnce([]); - - const children = await testTree.getChildren(parent); - - // This function should never return undefined. - expect(children).toBeDefined(); - expect(children).toHaveLength(1); - expect(children[0].label).toBe("No data sets found"); - }); }); describe("Dataset Tree Unit Tests - Function loadProfilesForFavorites", () => { function createBlockMocks() { @@ -3338,7 +3314,6 @@ describe("Dataset Tree Unit Tests - Function applyPatternsToChildren", () => { const withProfileMock = jest.spyOn(SharedContext, "withProfile").mockImplementation((child) => String(child.contextValue)); testTree.applyPatternsToChildren(fakeChildren as any[], [{ dsn: "HLQ.PROD.PDS", member: "A*" }], fakeSessionNode as any); expect(SharedContext.isFilterFolder(fakeChildren[0])).toBe(true); - expect(fakeSessionNode.dirty).toBe(true); withProfileMock.mockRestore(); }); it("applies a closed filter folder icon to the PDS if collapsed", () => { diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetUtils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetUtils.unit.test.ts index 7f79ff5e82..8fe99b0354 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/DatasetUtils.unit.test.ts @@ -34,6 +34,6 @@ describe("Dataset utils unit tests - function getExtension", () => { } }); it("returns null if no language was detected", () => { - expect(DatasetUtils.getExtension("TEST.DS")).toBe(null); + expect(DatasetUtils.getExtension("TEST.DS.X")).toBe(null); }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/ZoweDatasetNode.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/ZoweDatasetNode.unit.test.ts index 05b31159f4..51a17ff69a 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/dataset/ZoweDatasetNode.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/dataset/ZoweDatasetNode.unit.test.ts @@ -125,7 +125,7 @@ describe("ZoweDatasetNode Unit Tests", () => { /************************************************************************************************************* * Checks that returning an unsuccessful response results in an error being thrown and caught *************************************************************************************************************/ - it("Checks that when List.dataSet/allMembers() returns an unsuccessful response, " + "it returns a label of 'No data sets found'", async () => { + it("Checks that when List.dataSet/allMembers() throws an error, it returns an empty list", async () => { Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => { return { @@ -139,8 +139,41 @@ describe("ZoweDatasetNode Unit Tests", () => { collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, session, profile: profileOne, + contextOverride: Constants.DS_SESSION_CONTEXT, + }); + rootNode.dirty = true; + const subNode = new ZoweDatasetNode({ + label: "Response Fail", + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + parentNode: rootNode, + profile: profileOne, + }); + jest.spyOn(zosfiles.List, "allMembers").mockRejectedValueOnce(new Error(subNode.label as string)); + // Populate node with children from previous search to ensure they are removed + subNode.children = [ + new ZoweDatasetNode({ label: "old", collapsibleState: vscode.TreeItemCollapsibleState.None, session, profile: profileOne }), + ]; + subNode.dirty = true; + const response = await subNode.getChildren(); + expect(response).toEqual([]); + }); + + it("Checks that when List.dataSet/allMembers() returns an empty response, it returns a label of 'No data sets found'", async () => { + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn(() => { + return { + loadNamedProfile: jest.fn().mockReturnValue(profileOne), + }; + }), + }); + // Creating a rootNode + const rootNode = new ZoweDatasetNode({ + label: "root", + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + session, + profile: profileOne, + contextOverride: Constants.DS_SESSION_CONTEXT, }); - rootNode.contextValue = Constants.DS_SESSION_CONTEXT; rootNode.dirty = true; const subNode = new ZoweDatasetNode({ label: "Response Fail", @@ -148,7 +181,7 @@ describe("ZoweDatasetNode Unit Tests", () => { parentNode: rootNode, profile: profileOne, }); - jest.spyOn(subNode as any, "getDatasets").mockReturnValueOnce([ + jest.spyOn(subNode as any, "getDatasets").mockResolvedValueOnce([ { success: true, apiResponse: { @@ -171,19 +204,14 @@ describe("ZoweDatasetNode Unit Tests", () => { collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, session, profile: profileOne, + contextOverride: Constants.DS_SESSION_CONTEXT, }); const infoChild = new ZoweDatasetNode({ label: "Use the search button to display data sets", collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: rootNode, - profile: profileOne, contextOverride: Constants.INFORMATION_CONTEXT, }); - infoChild.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; - rootNode.contextValue = Constants.DS_SESSION_CONTEXT; rootNode.dirty = false; expect(await rootNode.getChildren()).toEqual([infoChild]); }); @@ -198,19 +226,14 @@ describe("ZoweDatasetNode Unit Tests", () => { collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, session, profile: profileOne, + contextOverride: Constants.DS_SESSION_CONTEXT, }); const infoChild = new ZoweDatasetNode({ label: "Use the search button to display data sets", collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: rootNode, - profile: profileOne, contextOverride: Constants.INFORMATION_CONTEXT, }); - infoChild.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; - rootNode.contextValue = Constants.DS_SESSION_CONTEXT; expect(await rootNode.getChildren()).toEqual([infoChild]); }); @@ -301,9 +324,9 @@ describe("ZoweDatasetNode Unit Tests", () => { parentNode: sessionNode, session, profile: profileOne, + contextOverride: Constants.DS_PDS_CONTEXT, }); pds.dirty = true; - pds.contextValue = Constants.DS_PDS_CONTEXT; const allMembers = jest.fn().mockReturnValueOnce({ success: true, apiResponse: { @@ -323,6 +346,48 @@ describe("ZoweDatasetNode Unit Tests", () => { getSessionNodeSpy.mockRestore(); getStatsMock.mockRestore(); }); + it("Testing what happens when response has multiple members and member pattern is set", async () => { + Object.defineProperty(Profiles, "getInstance", { + value: jest.fn(() => { + return { + loadNamedProfile: jest.fn().mockReturnValue(profileOne), + }; + }), + }); + + const getStatsMock = jest.spyOn(ZoweDatasetNode.prototype, "getStats").mockImplementation(); + + const sessionNode = createDatasetSessionNode(session, profileOne); + const getSessionNodeSpy = jest.spyOn(ZoweDatasetNode.prototype, "getSessionNode").mockReturnValue(sessionNode); + // Creating a rootNode + const pds = new ZoweDatasetNode({ + label: "[root]: something", + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + parentNode: sessionNode, + session, + profile: profileOne, + contextOverride: Constants.DS_PDS_CONTEXT, + }); + pds.dirty = true; + pds.memberPattern = "MEM*"; + const allMembers = jest.fn().mockReturnValueOnce({ + success: true, + apiResponse: { + items: [{ member: "MEMBER1" }], + returnedRows: 1, + }, + }); + jest.spyOn(DatasetFSProvider.instance, "exists").mockReturnValue(false); + jest.spyOn(DatasetFSProvider.instance, "writeFile").mockImplementation(); + jest.spyOn(DatasetFSProvider.instance, "createDirectory").mockImplementation(); + Object.defineProperty(zosfiles.List, "allMembers", { value: allMembers }); + const pdsChildren = await pds.getChildren(); + expect(pdsChildren[0].label).toEqual("MEMBER1"); + expect(pdsChildren[0].contextValue).toEqual(Constants.DS_MEMBER_CONTEXT); + expect(allMembers).toHaveBeenCalledWith(expect.any(imperative.Session), pds.label, expect.objectContaining({ pattern: pds.memberPattern })); + getSessionNodeSpy.mockRestore(); + getStatsMock.mockRestore(); + }); /************************************************************************************************************* * Profile properties have changed diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/job/JobTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/job/JobTree.unit.test.ts index 0fa961cfc4..5e573cdbec 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/job/JobTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/job/JobTree.unit.test.ts @@ -96,7 +96,6 @@ async function createGlobalMocks() { mockDeleteJobs: jest.fn(), mockShowInputBox: jest.fn(), mockDeleteJob: jest.fn(), - mockGetJobsByOwnerAndPrefix: jest.fn(), mockShowInformationMessage: jest.fn(), mockShowWarningMessage: jest.fn(), mockLoadNamedProfile: jest.fn(), @@ -110,7 +109,6 @@ async function createGlobalMocks() { testSessionNoCred: createISessionWithoutCredentials(), testProfile: createIProfile(), testIJob: createIJobObject(), - testIJobComplete: createIJobObject(), testJobNode: null, testSessionNode: null, mockIJobFile: createIJobFile(), @@ -237,7 +235,6 @@ async function createGlobalMocks() { Object.defineProperty(ZoweLogger, "trace", { value: jest.fn(), configurable: true }); globalMocks.testSessionNode = createJobSessionNode(globalMocks.testSession, globalMocks.testProfile); globalMocks.mockGetJob.mockReturnValue(globalMocks.testIJob); - globalMocks.mockGetJobsByOwnerAndPrefix.mockReturnValue([globalMocks.testIJob, globalMocks.testIJobComplete]); globalMocks.mockProfileInstance.editSession = jest.fn(() => globalMocks.testProfile); globalMocks.mockGetConfiguration.mockReturnValue({ persistence: true, diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/job/ZoweJobNode.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/job/ZoweJobNode.unit.test.ts index fa5309ff4d..54f98b38d3 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/job/ZoweJobNode.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/job/ZoweJobNode.unit.test.ts @@ -30,7 +30,7 @@ import { Profiles } from "../../../../src/configuration/Profiles"; import { ZoweExplorerApiRegister } from "../../../../src/extending/ZoweExplorerApiRegister"; import { ZoweLocalStorage } from "../../../../src/tools/ZoweLocalStorage"; import { JobFSProvider } from "../../../../src/trees/job/JobFSProvider"; -import { ZoweJobNode } from "../../../../src/trees/job/ZoweJobNode"; +import { ZoweJobNode, ZoweSpoolNode } from "../../../../src/trees/job/ZoweJobNode"; import { SharedContext } from "../../../../src/trees/shared/SharedContext"; import { SharedTreeProviders } from "../../../../src/trees/shared/SharedTreeProviders"; import { JobInit } from "../../../../src/trees/job/JobInit"; @@ -52,7 +52,7 @@ async function createGlobalMocks() { mockDeleteJobs: jest.fn(), mockShowInputBox: jest.fn(), mockDeleteJob: jest.fn(), - mockGetJobsByOwnerAndPrefix: jest.fn(), + mockGetJobsByParameters: jest.fn(), mockShowInformationMessage: jest.fn(), mockLoadNamedProfile: jest.fn(), mockCreateQuickPick: jest.fn(), @@ -114,6 +114,10 @@ async function createGlobalMocks() { configurable: true, }); Object.defineProperty(globalMocks.mockGetJobs, "getJob", { value: globalMocks.mockGetJob, configurable: true }); + Object.defineProperty(globalMocks.mockGetJobs, "getJobsByParameters", { + value: globalMocks.mockGetJobsByParameters, + configurable: true, + }); Object.defineProperty(zosmf.ZosmfSession, "createSessCfgFromArgs", { value: globalMocks.mockCreateSessCfgFromArgs, configurable: true, @@ -174,7 +178,7 @@ async function createGlobalMocks() { globalMocks.mockCreateSessCfgFromArgs.mockReturnValue(globalMocks.testSession); globalMocks.testSessionNode = createJobSessionNode(globalMocks.testSession, globalMocks.testProfile); globalMocks.mockGetJob.mockReturnValue(globalMocks.testIJob); - globalMocks.mockGetJobsByOwnerAndPrefix.mockReturnValue([globalMocks.testIJob, globalMocks.testIJobComplete]); + globalMocks.mockGetJobsByParameters.mockReturnValue([globalMocks.testIJob, globalMocks.testIJobComplete]); globalMocks.mockProfileInstance.editSession = jest.fn(() => globalMocks.testProfile); globalMocks.testJobNode = new ZoweJobNode({ label: "jobtest", @@ -298,17 +302,18 @@ describe("ZoweJobNode unit tests - Function onDidConfiguration", () => { }); describe("ZoweJobNode unit tests - Function getChildren", () => { - xit("Tests that getChildren returns the jobs of the session, when called on the session", async () => { + it("Tests that getChildren returns the jobs of the session, when called on the session", async () => { const globalMocks = await createGlobalMocks(); await globalMocks.testJobsProvider.addSession("fake"); + globalMocks.testJobsProvider.mSessionNodes[1].filtered = true; const jobs = await globalMocks.testJobsProvider.mSessionNodes[1].getChildren(); expect(jobs.length).toBe(2); expect(jobs[0].job.jobid).toEqual(globalMocks.testIJob.jobid); - expect(jobs[0].tooltip).toEqual("TESTJOB(JOB1234)"); + expect(jobs[0].tooltip).toEqual("TESTJOB(JOB1234) - ACTIVE"); expect(jobs[1].job.jobid).toEqual(globalMocks.testIJobComplete.jobid); - expect(jobs[1].tooltip).toEqual("TESTJOB(JOB1235) - 0"); + expect(jobs[1].tooltip).toEqual("TESTJOB(JOB1235) - sampleMember - 0"); }); it("Tests that getChildren updates existing job nodes with new statuses", async () => { @@ -379,7 +384,26 @@ describe("ZoweJobNode unit tests - Function getChildren", () => { globalMocks.testJobNode.dirty = true; const spoolFilesAfter = await globalMocks.testJobNode.getChildren(); expect(spoolFilesAfter.length).toBe(1); - expect(spoolFilesAfter[0].label).toEqual("There are no JES spool messages to display"); + expect(spoolFilesAfter[0].label).toEqual("No spool files found"); + }); + + it("Tests that getChildren returns empty list if there is error retrieving spool files", async () => { + const globalMocks = await createGlobalMocks(); + jest.spyOn(ZoweExplorerApiRegister, "getJesApi").mockReturnValueOnce({ + getSpoolFiles: jest.fn().mockResolvedValue(new Error("Response Fail")), + } as any); + // Populate node with children from previous search to ensure they are removed + globalMocks.testJobNode.children = [ + new ZoweSpoolNode({ + label: "old", + collapsibleState: vscode.TreeItemCollapsibleState.None, + session: globalMocks.testSession, + profile: globalMocks.testProfile, + }), + ]; + globalMocks.testJobNode.dirty = true; + const spools = await globalMocks.testJobNode.getChildren(); + expect(spools).toEqual([]); }); it("Tests that getChildren returns the spool files if user/owner is not defined", async () => { @@ -395,19 +419,14 @@ describe("ZoweJobNode unit tests - Function getChildren", () => { expect(spoolFiles[0].owner).toEqual("*"); }); - it("should return a new job if not owner and is a session", async () => { + it("should return placeholder node if session node expanded without search params", async () => { const globalMocks = await createGlobalMocks(); const expectedJob = new ZoweJobNode({ label: "Use the search button to display jobs", collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: globalMocks.testJobNode, - profile: globalMocks.testProfile, contextOverride: Constants.INFORMATION_CONTEXT, }); - expectedJob.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; globalMocks.testJobNode._owner = null; jest.spyOn(SharedContext, "isSession").mockReturnValueOnce(true); @@ -420,13 +439,8 @@ describe("ZoweJobNode unit tests - Function getChildren", () => { label: "No jobs found", collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: globalMocks.testJobsProvider.mSessionNodes[1], + contextOverride: Constants.INFORMATION_CONTEXT, }); - job.iconPath = undefined; - job.contextValue = "information"; - job.command = { - title: "Placeholder", - command: "zowe.placeholderCommand", - }; await globalMocks.testJobsProvider.addSession("fake"); globalMocks.testJobsProvider.mSessionNodes[1].filtered = true; jest.spyOn(globalMocks.testJobsProvider.mSessionNodes[1], "getJobs").mockResolvedValue([]); @@ -434,6 +448,27 @@ describe("ZoweJobNode unit tests - Function getChildren", () => { expect(jobs[0]).toEqual(job); }); + it("should return empty list if there is error retrieving jobs", async () => { + const globalMocks = await createGlobalMocks(); + await globalMocks.testJobsProvider.addSession("fake"); + // Populate node with children from previous search to ensure they are removed + globalMocks.testJobsProvider.mSessionNodes[1].children = [ + new ZoweJobNode({ + label: "old", + collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, + session: globalMocks.testSession, + profile: globalMocks.testProfile, + }), + ]; + globalMocks.testJobsProvider.mSessionNodes[1].filtered = true; + globalMocks.mockGetJobsByParameters.mockRejectedValue(new Error("Response Fail")); + jest.spyOn(ZoweExplorerApiRegister, "getJesApi").mockReturnValueOnce({ + getSession: jest.fn().mockReturnValue(globalMocks.testSession), + } as any); + const jobs = await globalMocks.testJobsProvider.mSessionNodes[1].getChildren(); + expect(jobs).toEqual([]); + }); + it("To check smfid field in Jobs Tree View", async () => { const globalMocks = await createGlobalMocks(); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedInit.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedInit.unit.test.ts index 7a54f6aaa8..600c3a11d9 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedInit.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedInit.unit.test.ts @@ -30,6 +30,7 @@ import { Gui, imperative, ZoweScheme } from "@zowe/zowe-explorer-api"; import { MockedProperty } from "../../../__mocks__/mockUtils"; import { DatasetFSProvider } from "../../../../src/trees/dataset/DatasetFSProvider"; import { UssFSProvider } from "../../../../src/trees/uss/UssFSProvider"; +import { ZoweLogger } from "../../../../src/tools/ZoweLogger"; jest.mock("../../../../src/utils/LoggerUtils"); jest.mock("../../../../src/tools/ZoweLogger"); @@ -322,7 +323,8 @@ describe("Test src/shared/extension", () => { describe("watchConfigProfile", () => { let context: any; let watcherPromise: any; - const spyReadFile = jest.fn().mockReturnValue("test"); + const fakeUri = { fsPath: "fsPath" }; + const spyReadFile = jest.fn().mockReturnValue(Buffer.from("test")); const mockEmitter = jest.fn(); const watcher: any = { onDidCreate: jest.fn(), @@ -332,9 +334,12 @@ describe("Test src/shared/extension", () => { beforeEach(() => { context = { subscriptions: [] }; jest.clearAllMocks(); - Object.defineProperty(vscode.workspace, "workspaceFolders", { value: [{ uri: { fsPath: "fsPath" } }], configurable: true }); + Object.defineProperty(vscode.workspace, "workspaceFolders", { value: [{ uri: fakeUri }], configurable: true }); Object.defineProperty(vscode.workspace, "fs", { value: { readFile: spyReadFile }, configurable: true }); - Object.defineProperty(Constants, "SAVED_PROFILE_CONTENTS", { value: "test", configurable: true }); + Object.defineProperty(Constants, "SAVED_PROFILE_CONTENTS", { + value: new Map(Object.entries({ [fakeUri.fsPath]: Buffer.from("test") })), + configurable: true, + }); jest.spyOn(vscode.workspace, "createFileSystemWatcher").mockReturnValue(watcher); jest.spyOn(ZoweExplorerApiRegister.getInstance().onProfilesUpdateEmitter, "fire").mockImplementation(mockEmitter); }); @@ -365,23 +370,23 @@ describe("Test src/shared/extension", () => { it("should be able to trigger onDidChange listener", async () => { const spyRefreshAll = jest.spyOn(SharedActions, "refreshAll").mockImplementation(); - watcher.onDidChange.mockImplementationOnce((fun) => (watcherPromise = fun("uri"))); + watcher.onDidChange.mockImplementationOnce((fun) => (watcherPromise = fun(fakeUri))); SharedInit.watchConfigProfile(context); await watcherPromise; expect(context.subscriptions).toContain(watcher); - expect(spyReadFile).toHaveBeenCalledWith("uri"); + expect(spyReadFile).toHaveBeenCalledWith(fakeUri); expect(spyRefreshAll).not.toHaveBeenCalled(); expect(mockEmitter).not.toHaveBeenCalled(); }); it("should be able to trigger onDidChange listener with changes", async () => { const spyRefreshAll = jest.spyOn(SharedActions, "refreshAll").mockImplementation(); - spyReadFile.mockReturnValueOnce("other"); - watcher.onDidChange.mockImplementationOnce((fun) => (watcherPromise = fun("uri"))); + spyReadFile.mockReturnValueOnce(Buffer.from("other")); + watcher.onDidChange.mockImplementationOnce((fun) => (watcherPromise = fun(fakeUri))); SharedInit.watchConfigProfile(context); await watcherPromise; expect(context.subscriptions).toContain(watcher); - expect(spyReadFile).toHaveBeenCalledWith("uri"); + expect(spyReadFile).toHaveBeenCalledWith(fakeUri); expect(spyRefreshAll).toHaveBeenCalledTimes(1); expect(mockEmitter).toHaveBeenCalledTimes(1); }); @@ -408,7 +413,7 @@ describe("Test src/shared/extension", () => { const spyRefreshAll = jest.spyOn(SharedActions, "refreshAll").mockImplementation(jest.fn()); // Setup watchers - await SharedInit.watchConfigProfile(context); + SharedInit.watchConfigProfile(context); expect(spyWatcher).toHaveBeenCalled(); expect(spyGuiError).not.toHaveBeenCalled(); @@ -435,7 +440,7 @@ describe("Test src/shared/extension", () => { }); const spyGuiError = jest.spyOn(Gui, "errorMessage"); - await SharedInit.watchConfigProfile(context); + SharedInit.watchConfigProfile(context); expect(spyWatcher).toHaveBeenCalled(); expect(spyGuiError.mock.calls[0][0]).toContain("vault changes"); @@ -443,6 +448,39 @@ describe("Test src/shared/extension", () => { expect(spyGuiError.mock.calls[1][0]).toContain("credential manager changes"); expect(spyGuiError.mock.calls[1][0]).toContain(testError); }); + + it("should replace the function signature for EventProcessor.emitZoweEvent to set Constant.IGNORE_VAULT_CHANGE", async () => { + const emitZoweEventOverride = jest.fn(); + const emitZoweEventMock = new MockedProperty(imperative.EventProcessor.prototype, "emitZoweEvent", { + set: emitZoweEventOverride, + configurable: true, + }); + SharedInit.watchConfigProfile(context); + expect(emitZoweEventOverride).toHaveBeenCalled(); + emitZoweEventMock[Symbol.dispose](); + }); + + it("should replace the function signature for EventProcessor.emitZoweEvent to set Constant.IGNORE_VAULT_CHANGE", async () => { + const emitZoweEventOverride = jest.fn(); + const emitZoweEventMock = new MockedProperty(imperative.EventProcessor.prototype, "emitZoweEvent", { + set: emitZoweEventOverride, + configurable: true, + }); + SharedInit.watchConfigProfile(context); + expect(emitZoweEventOverride).toHaveBeenCalled(); + emitZoweEventMock[Symbol.dispose](); + }); + + it("should subscribe to the ON_VAULT_CHANGED event using EventProcessor.subscribeUser", async () => { + const subscribeUser = jest.fn(); + const getWatcherMock = jest.spyOn(imperative.EventOperator, "getWatcher").mockReturnValue({ + subscribeUser, + } as any); + + SharedInit.watchConfigProfile(context); + expect(getWatcherMock).toHaveBeenCalled(); + expect(subscribeUser).toHaveBeenCalledWith(imperative.ZoweUserEvents.ON_VAULT_CHANGED, SharedInit.onVaultChanged); + }); }); describe("initSubscribers", () => { @@ -518,4 +556,33 @@ describe("Test src/shared/extension", () => { expect(remoteLookupUssSpy).not.toHaveBeenCalled(); }); }); + + describe("emitZoweEventHook", () => { + it("sets Constants.IGNORE_VAULT_CHANGE to true if emitZoweEvent is called and calls the original function", () => { + const originalEmitZoweEvent = new MockedProperty(SharedInit, "originalEmitZoweEvent", undefined, jest.fn()); + SharedInit.emitZoweEventHook({} as any, imperative.ZoweUserEvents.ON_VAULT_CHANGED); + expect(Constants.IGNORE_VAULT_CHANGE).toBe(true); + expect(originalEmitZoweEvent.mock).toHaveBeenCalled(); + originalEmitZoweEvent[Symbol.dispose](); + }); + }); + describe("onVaultChanged", () => { + it("resets Constants.IGNORE_VAULT_CHANGE if it is true and returns early", async () => { + const infoSpy = jest.spyOn(ZoweLogger, "info"); + Constants.IGNORE_VAULT_CHANGE = true; + await SharedInit.onVaultChanged(); + expect(Constants.IGNORE_VAULT_CHANGE).toBe(false); + expect(infoSpy).not.toHaveBeenCalled(); + }); + + it("calls SharedActions.refreshAll and ProfilesUtils.readConfigFromDisk on vault change", async () => { + const loggerInfo = jest.spyOn(ZoweLogger, "info").mockImplementation(); + const readCfgFromDisk = jest.spyOn(profUtils.ProfilesUtils, "readConfigFromDisk").mockImplementation(); + const refreshAll = jest.spyOn(SharedActions, "refreshAll").mockImplementation(); + await SharedInit.onVaultChanged(); + expect(loggerInfo).toHaveBeenCalledWith("Changes in the credential vault detected, refreshing Zowe Explorer."); + expect(readCfgFromDisk).toHaveBeenCalled(); + expect(refreshAll).toHaveBeenCalled(); + }); + }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts index 3fda35525a..645f8de4d8 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/shared/SharedUtils.unit.test.ts @@ -24,6 +24,7 @@ import { ZoweJobNode } from "../../../../src/trees/job/ZoweJobNode"; import { SharedUtils } from "../../../../src/trees/shared/SharedUtils"; import { ZoweUSSNode } from "../../../../src/trees/uss/ZoweUSSNode"; import { AuthUtils } from "../../../../src/utils/AuthUtils"; +import { SharedTreeProviders } from "../../../../src/trees/shared/SharedTreeProviders"; function createGlobalMocks() { const newMocks = { @@ -110,6 +111,30 @@ describe("syncSessionNode shared util function", () => { expect(sessionNode.getSession()).toEqual(expectedSession); expect(sessionNode.getProfile()).toEqual(createIProfile()); }); + it("should update session node and refresh tree node if provided", async () => { + const globalMocks = createGlobalMocks(); + // given + Object.defineProperty(globalMocks.mockProfilesCache, "loadNamedProfile", { + value: jest.fn().mockReturnValue(createIProfile()), + }); + const getChildrenSpy = jest.spyOn(sessionNode, "getChildren").mockResolvedValueOnce([]); + const refreshElementMock = jest.fn(); + jest.spyOn(SharedTreeProviders, "getProviderForNode").mockReturnValueOnce({ + refreshElement: refreshElementMock, + } as any); + const getSessionMock = jest.fn().mockReturnValue(new imperative.Session({})); + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + const sessionForProfile = (_profile) => + ({ + getSession: getSessionMock, + } as any); + // when + AuthUtils.syncSessionNode(sessionForProfile, sessionNode, sessionNode); + expect(getSessionMock).toHaveBeenCalled(); + expect(sessionNode.dirty).toBe(true); + expect(await getChildrenSpy).toHaveBeenCalled(); + expect(refreshElementMock).toHaveBeenCalledWith(sessionNode); + }); it("should do nothing, if there is no profile from provided node in the file system", () => { const profiles = createInstanceOfProfile(serviceProfile); profiles.loadNamedProfile = jest.fn(() => diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSActions.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSActions.unit.test.ts index ad3b05e951..3cd04ee5c5 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSActions.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSActions.unit.test.ts @@ -174,7 +174,7 @@ function createGlobalMocks() { return globalMocks; } -describe("USS Action Unit Tests - Function createUSSNodeDialog", () => { +describe("USS Action Unit Tests - Function createUSSNode", () => { function createBlockMocks(globalMocks) { const newMocks = { testUSSTree: null, @@ -193,18 +193,50 @@ describe("USS Action Unit Tests - Function createUSSNodeDialog", () => { return newMocks; } - it("Tests that only the child node is refreshed when createUSSNode() is called on a child node", async () => { + it("should prompt the user for a location if one is not set on the node", async () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); - globalMocks.mockShowInputBox.mockReturnValue("USSFolder"); - jest.spyOn(blockMocks.ussNode, "getChildren").mockResolvedValueOnce([]); - const isTopLevel = false; - jest.spyOn(SharedActions, "refreshAll"); + globalMocks.mockShowInputBox.mockResolvedValueOnce("/u/myuser/"); + globalMocks.mockShowInputBox.mockResolvedValueOnce("folderName"); + const refreshAllMock = jest.spyOn(SharedActions, "refreshAll").mockImplementation(); + const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation(); + blockMocks.ussNode.getParent().fullPath = ""; - await USSActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder", isTopLevel); - expect(blockMocks.testUSSTree.refreshElement).toHaveBeenCalled(); - expect(SharedActions.refreshAll).not.toHaveBeenCalled(); + await USSActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "directory"); + expect(createApiMock).toHaveBeenCalledWith("/u/myuser/folderName", "directory"); + expect(refreshAllMock).toHaveBeenCalled(); + createApiMock.mockRestore(); + }); + + it("returns early if a location was never provided", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + + globalMocks.mockShowInputBox.mockResolvedValueOnce(undefined); + const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation(); + blockMocks.ussNode.getParent().fullPath = ""; + + await USSActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "directory"); + expect(createApiMock).not.toHaveBeenCalled(); + createApiMock.mockRestore(); + }); + + it("handles trailing slashes in the location", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + + globalMocks.mockShowInputBox.mockResolvedValueOnce("/u/myuser/aDir/"); + globalMocks.mockShowInputBox.mockResolvedValueOnce("testFile.txt"); + const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation(); + const refreshAllMock = jest.spyOn(SharedActions, "refreshAll").mockImplementation(); + blockMocks.ussNode.getParent().fullPath = ""; + + await USSActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "file"); + expect(createApiMock).toHaveBeenCalledWith("/u/myuser/aDir/testFile.txt", "file"); + expect(refreshAllMock).toHaveBeenCalled(); + createApiMock.mockRestore(); + refreshAllMock.mockRestore(); }); it("Tests if createUSSNode is executed successfully with Unverified profile", async () => { @@ -214,20 +246,24 @@ describe("USS Action Unit Tests - Function createUSSNodeDialog", () => { Object.defineProperty(Profiles, "getInstance", { value: jest.fn(() => { return { - checkCurrentProfile: blockMocks.mockCheckCurrentProfile.mockReturnValueOnce({ + checkCurrentProfile: blockMocks.mockCheckCurrentProfile.mockResolvedValueOnce({ name: globalMocks.testProfile.name, status: "unverified", }), + loadNamedProfile: globalMocks.mockLoadNamedProfile, validProfile: Validation.ValidationType.UNVERIFIED, }; }), }); - globalMocks.showQuickPick.mockResolvedValueOnce("File"); globalMocks.mockShowInputBox.mockReturnValueOnce("USSFolder"); + const refreshAllMock = jest.spyOn(SharedActions, "refreshAll").mockImplementation(); + const createApiMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementation(); - await USSActions.createUSSNodeDialog(blockMocks.ussNode.getParent(), blockMocks.testUSSTree); + await USSActions.createUSSNode(blockMocks.ussNode.getParent(), blockMocks.testUSSTree, "directory"); + expect(refreshAllMock).toHaveBeenCalled(); + expect(createApiMock).toHaveBeenCalled(); expect(blockMocks.testUSSTree.refreshElement).not.toHaveBeenCalled(); - expect(globalMocks.showErrorMessage.mock.calls.length).toBe(0); + createApiMock.mockRestore(); }); it("Tests that createUSSNode does not execute if node name was not entered", async () => { @@ -292,7 +328,7 @@ describe("USS Action Unit Tests - Function createUSSNodeDialog", () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); - jest.spyOn(ZoweExplorerApiRegister, "getUssApi").mockImplementationOnce(() => { + const ussApi = jest.spyOn(ZoweExplorerApiRegister, "getUssApi").mockImplementationOnce(() => { throw Error("Test error"); }); globalMocks.mockShowInputBox.mockReturnValueOnce("USSFolder"); @@ -305,6 +341,7 @@ describe("USS Action Unit Tests - Function createUSSNodeDialog", () => { } expect(testError?.message).toEqual("Test error"); + ussApi.mockRestore(); }); it("Tests that only the child node is refreshed when createUSSNode() is called on a child node", async () => { @@ -312,31 +349,28 @@ describe("USS Action Unit Tests - Function createUSSNodeDialog", () => { const blockMocks = createBlockMocks(globalMocks); globalMocks.mockShowInputBox.mockReturnValueOnce("USSFolder"); - jest.spyOn(blockMocks.ussNode, "getChildren").mockResolvedValueOnce([]); - const isTopLevel = false; - jest.spyOn(SharedActions, "refreshAll"); + const refreshAllSpy = jest.spyOn(SharedActions, "refreshAll"); + refreshAllSpy.mockRestore(); - await USSActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder", isTopLevel); + await USSActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder"); expect(blockMocks.testUSSTree.refreshElement).toHaveBeenCalled(); - expect(SharedActions.refreshAll).not.toHaveBeenCalled(); + expect(refreshAllSpy).not.toHaveBeenCalled(); }); it("Tests that the error is handled if createUSSNode is unsuccessful", async () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); globalMocks.mockShowInputBox.mockReturnValueOnce("USSFolder"); - const isTopLevel = false; const errorHandlingSpy = jest.spyOn(AuthUtils, "errorHandling"); // Simulate unsuccessful api call - Object.defineProperty(blockMocks.ussApi, "create", { - value: jest.fn(() => { - throw new Error(); - }), + const createMock = jest.spyOn(blockMocks.ussApi, "create").mockImplementationOnce(async (ussPath, type, mode) => { + throw new Error(); }); - await expect(USSActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder", isTopLevel)).rejects.toThrow(); + await expect(USSActions.createUSSNode(blockMocks.ussNode, blockMocks.testUSSTree, "folder")).rejects.toThrow(); expect(errorHandlingSpy).toHaveBeenCalledTimes(1); + createMock.mockRestore(); }); }); @@ -398,8 +432,10 @@ describe("USS Action Unit Tests - Function deleteFromDisk", () => { jest.spyOn(fs, "unlinkSync").mockImplementation(() => { throw new Error(); }); + const warnSpy = jest.spyOn(ZoweLogger, "warn"); + warnSpy.mockRestore(); USSActions.deleteFromDisk(null, "some/where/that/does/not/exist"); - expect(ZoweLogger.warn).toHaveBeenCalledTimes(1); + expect(warnSpy).toHaveBeenCalledTimes(1); }); }); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts index a22d8f21c8..17cfac602d 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/USSTree.unit.test.ts @@ -1685,6 +1685,7 @@ describe("USSTree Unit Tests - Function crossLparMove", () => { profile: ussDirNode.getProfile(), }), ]; + ussDirNode.dirty = false; const deleteMock = jest.spyOn(UssFSProvider.instance, "delete").mockResolvedValue(undefined); const readFileMock = jest.spyOn(UssFSProvider.instance, "readFile").mockResolvedValue(new Uint8Array([1, 2, 3])); diff --git a/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts index f2ea39ae06..5d00e1ac6e 100644 --- a/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/trees/uss/ZoweUSSNode.unit.test.ts @@ -25,7 +25,7 @@ import { createInstanceOfProfile, createValidIProfile, } from "../../../__mocks__/mockCreators/shared"; -import { createUSSTree } from "../../../__mocks__/mockCreators/uss"; +import { createUSSNode, createUSSTree } from "../../../__mocks__/mockCreators/uss"; import { Constants } from "../../../../src/configuration/Constants"; import { ZoweLocalStorage } from "../../../../src/tools/ZoweLocalStorage"; import { UssFSProvider } from "../../../../src/trees/uss/UssFSProvider"; @@ -831,7 +831,7 @@ describe("ZoweUSSNode Unit Tests - Function node.getChildren()", () => { setAttrsMock.mockRestore(); }); - it("Tests that error is thrown when node label is blank", async () => { + it("Tests that error is thrown when node label is blank", () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); @@ -842,29 +842,29 @@ describe("ZoweUSSNode Unit Tests - Function node.getChildren()", () => { expect(blockMocks.rootNode.getChildren()).rejects.toEqual(Error("Invalid node")); }); - it( - "Tests that when zowe.List. causes an error on the zowe call, " + "node.getChildren() throws an error and the catch block is reached", - async () => { - const globalMocks = createGlobalMocks(); - const blockMocks = createBlockMocks(globalMocks); - - blockMocks.childNode.contextValue = Constants.USS_SESSION_CONTEXT; - blockMocks.childNode.fullPath = "Throw Error"; - blockMocks.childNode.dirty = true; - blockMocks.childNode.profile = globalMocks.profileOne; - jest.spyOn(UssFSProvider.instance, "listFiles").mockImplementation(() => { - throw new Error("Throwing an error to check error handling for unit tests!"); - }); - - await blockMocks.childNode.getChildren(); - expect(globalMocks.showErrorMessage.mock.calls.length).toEqual(1); - expect(globalMocks.showErrorMessage.mock.calls[0][0]).toEqual( - "Retrieving response from uss-file-list Error: Throwing an error to check error handling for unit tests!" - ); - } - ); + it("Tests that when List.fileList throws an error, node.getChildren() throws an error and the catch block is reached", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + + // Populate node with children from previous search to ensure they are removed + blockMocks.childNode.children = [createUSSNode(globalMocks.session, globalMocks.profileOne)]; + blockMocks.childNode.contextValue = Constants.USS_SESSION_CONTEXT; + blockMocks.childNode.fullPath = "Throw Error"; + blockMocks.childNode.dirty = true; + blockMocks.childNode.profile = globalMocks.profileOne; + jest.spyOn(UssFSProvider.instance, "listFiles").mockImplementation(() => { + throw new Error("Throwing an error to check error handling for unit tests!"); + }); - it("Tests that when passing a globalMocks.session node that is not dirty the node.getChildren() method is exited early", async () => { + const response = await blockMocks.childNode.getChildren(); + expect(response).toEqual([]); + expect(globalMocks.showErrorMessage.mock.calls.length).toEqual(1); + expect(globalMocks.showErrorMessage.mock.calls[0][0]).toEqual( + "Retrieving response from USS list API Error: Throwing an error to check error handling for unit tests!" + ); + }); + + it("Tests that when passing a session node that is not dirty the node.getChildren() method is exited early", async () => { const globalMocks = createGlobalMocks(); const blockMocks = createBlockMocks(globalMocks); @@ -874,6 +874,21 @@ describe("ZoweUSSNode Unit Tests - Function node.getChildren()", () => { expect(await blockMocks.rootNode.getChildren()).toEqual([]); }); + + it("Tests that when passing a session node without path the node.getChildren() method is exited early", async () => { + const globalMocks = createGlobalMocks(); + const blockMocks = createBlockMocks(globalMocks); + + blockMocks.rootNode.contextValue = Constants.USS_SESSION_CONTEXT; + const expectedNode = new ZoweUSSNode({ + label: "Use the search button to list USS files", + collapsibleState: vscode.TreeItemCollapsibleState.None, + parentNode: blockMocks.rootNode, + contextOverride: Constants.INFORMATION_CONTEXT, + }); + + expect(await blockMocks.rootNode.getChildren()).toEqual([expectedNode]); + }); }); describe("ZoweUSSNode Unit Tests - Function node.openUSS()", () => { diff --git a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts index 520639e15b..c276a01e3e 100644 --- a/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts +++ b/packages/zowe-explorer/__tests__/__unit__/utils/ProfilesUtils.unit.test.ts @@ -13,7 +13,7 @@ import * as fs from "fs"; import * as path from "path"; import * as util from "util"; import * as vscode from "vscode"; -import { Gui, imperative, ProfilesCache, ZoweVsCodeExtension } from "@zowe/zowe-explorer-api"; +import { FileManagement, Gui, imperative, ProfilesCache, ZoweVsCodeExtension } from "@zowe/zowe-explorer-api"; import { createAltTypeIProfile, createInstanceOfProfile, createValidIProfile } from "../../__mocks__/mockCreators/shared"; import { MockedProperty } from "../../__mocks__/mockUtils"; import { Constants } from "../../../src/configuration/Constants"; @@ -248,6 +248,7 @@ describe("ProfilesUtils unit tests", () => { value: [ { uri: { + scheme: "file", fsPath: "./test", }, }, @@ -285,7 +286,7 @@ describe("ProfilesUtils unit tests", () => { const mockReadProfilesFromDisk = jest.fn(); const profInfoSpy = jest.spyOn(ProfilesUtils, "getProfileInfo").mockReturnValue({ readProfilesFromDisk: mockReadProfilesFromDisk, - getTeamConfig: () => ({ exists: true }), + getTeamConfig: () => ({ exists: true, layers: [] }), } as never); await expect(ProfilesUtils.readConfigFromDisk()).resolves.not.toThrow(); expect(mockReadProfilesFromDisk).toHaveBeenCalledTimes(1); @@ -1314,4 +1315,15 @@ describe("ProfilesUtils unit tests", () => { onlyV1ProfsExistMock[Symbol.dispose](); }); }); + + describe("setupDefaultCredentialManager", () => { + it("calls readProfilesFromDisk with homeDir and projectDir", async () => { + const readProfilesFromDiskMock = jest.spyOn(imperative.ProfileInfo.prototype, "readProfilesFromDisk").mockImplementation(); + await ProfilesUtils.setupDefaultCredentialManager(); + expect(readProfilesFromDiskMock).toHaveBeenCalledWith({ + homeDir: FileManagement.getZoweDir(), + projectDir: vscode.workspace.workspaceFolders?.[0].uri.fsPath, + }); + }); + }); }); diff --git a/packages/zowe-explorer/l10n/bundle.l10n.json b/packages/zowe-explorer/l10n/bundle.l10n.json index d680aadbae..69f6380b85 100644 --- a/packages/zowe-explorer/l10n/bundle.l10n.json +++ b/packages/zowe-explorer/l10n/bundle.l10n.json @@ -143,9 +143,6 @@ "Favorites": "Favorites", "Use the search button to list USS files": "Use the search button to list USS files", "Invalid node": "Invalid node", - "Profile auth error": "Profile auth error", - "Profile is not authenticated, please log in to continue": "Profile is not authenticated, please log in to continue", - "Retrieving response from uss-file-list": "Retrieving response from uss-file-list", "Delete action was cancelled.": "Delete action was cancelled.", "Unable to delete node: {0}/Error message": { "message": "Unable to delete node: {0}", @@ -171,6 +168,9 @@ "Required API functions for pasting (fileList and copy/uploadFromBuffer) were not found.": "Required API functions for pasting (fileList and copy/uploadFromBuffer) were not found.", "Uploading USS files...": "Uploading USS files...", "Error uploading files": "Error uploading files", + "Profile auth error": "Profile auth error", + "Profile is not authenticated, please log in to continue": "Profile is not authenticated, please log in to continue", + "Retrieving response from USS list API": "Retrieving response from USS list API", "The 'move' function is not implemented for this USS API.": "The 'move' function is not implemented for this USS API.", "Could not list USS files: Empty path provided in URI": "Could not list USS files: Empty path provided in URI", "Profile does not exist for this file.": "Profile does not exist for this file.", @@ -334,10 +334,10 @@ ] }, "Enter a codepage (e.g., 1047, IBM-1047)": "Enter a codepage (e.g., 1047, IBM-1047)", + "Changes in the credential vault detected, refreshing Zowe Explorer.": "Changes in the credential vault detected, refreshing Zowe Explorer.", "Team config file created, refreshing Zowe Explorer.": "Team config file created, refreshing Zowe Explorer.", "Team config file deleted, refreshing Zowe Explorer.": "Team config file deleted, refreshing Zowe Explorer.", "Team config file updated.": "Team config file updated.", - "Changes in the credential vault detected, refreshing Zowe Explorer.": "Changes in the credential vault detected, refreshing Zowe Explorer.", "Changes in credential management detected, refreshing Zowe Explorer.": "Changes in credential management detected, refreshing Zowe Explorer.", "Zowe Explorer has activated successfully.": "Zowe Explorer has activated successfully.", "Type the new pattern to add to history": "Type the new pattern to add to history", @@ -350,9 +350,9 @@ "Select a recent member to open": "Select a recent member to open", "No recent members found.": "No recent members found.", "Use the search button to display jobs": "Use the search button to display jobs", - "There are no JES spool messages to display": "There are no JES spool messages to display", + "No spool files found": "No spool files found", "No jobs found": "No jobs found", - "Retrieving response from zowe.GetJobs": "Retrieving response from zowe.GetJobs", + "Retrieving response from JES list API": "Retrieving response from JES list API", "$(list-ordered) Job ID (default)": "$(list-ordered) Job ID (default)", "$(calendar) Date Submitted": "$(calendar) Date Submitted", "$(calendar) Date Completed": "$(calendar) Date Completed", @@ -538,6 +538,7 @@ "The response from Zowe CLI was not successful": "The response from Zowe CLI was not successful", "{0} members failed to load due to invalid name errors for {1}": "{0} members failed to load due to invalid name errors for {1}", "No data sets found": "No data sets found", + "Retrieving response from MVS list API": "Retrieving response from MVS list API", "Cannot download, item invalid.": "Cannot download, item invalid.", "$(case-sensitive) Name (default)": "$(case-sensitive) Name (default)", "$(calendar) Date Created": "$(calendar) Date Created", @@ -801,12 +802,6 @@ "Stringified JSON error" ] }, - "Prompted for a data set pattern, recieved {0}./Data Set pattern": { - "message": "Prompted for a data set pattern, recieved {0}.", - "comment": [ - "Data Set pattern" - ] - }, "Cannot perform the copy operation as the data sets selected have different types": "Cannot perform the copy operation as the data sets selected have different types", "Migration of data set {0} requested./Data Set name": { "message": "Migration of data set {0} requested.", diff --git a/packages/zowe-explorer/l10n/poeditor.json b/packages/zowe-explorer/l10n/poeditor.json index 5aa4422076..6e38e9d54b 100644 --- a/packages/zowe-explorer/l10n/poeditor.json +++ b/packages/zowe-explorer/l10n/poeditor.json @@ -478,9 +478,6 @@ "Favorites": "", "Use the search button to list USS files": "", "Invalid node": "", - "Profile auth error": "", - "Profile is not authenticated, please log in to continue": "", - "Retrieving response from uss-file-list": "", "Delete action was cancelled.": "", "Unable to delete node: {0}": "", "The item {0} has been deleted.": "", @@ -491,6 +488,9 @@ "Required API functions for pasting (fileList and copy/uploadFromBuffer) were not found.": "", "Uploading USS files...": "", "Error uploading files": "", + "Profile auth error": "", + "Profile is not authenticated, please log in to continue": "", + "Retrieving response from USS list API": "", "The 'move' function is not implemented for this USS API.": "", "Could not list USS files: Empty path provided in URI": "", "Profile does not exist for this file.": "", @@ -554,10 +554,10 @@ "Choose encoding for {0}": "", "Current encoding is {0}": "", "Enter a codepage (e.g., 1047, IBM-1047)": "", + "Changes in the credential vault detected, refreshing Zowe Explorer.": "", "Team config file created, refreshing Zowe Explorer.": "", "Team config file deleted, refreshing Zowe Explorer.": "", "Team config file updated.": "", - "Changes in the credential vault detected, refreshing Zowe Explorer.": "", "Changes in credential management detected, refreshing Zowe Explorer.": "", "Zowe Explorer has activated successfully.": "", "Type the new pattern to add to history": "", @@ -570,9 +570,9 @@ "Select a recent member to open": "", "No recent members found.": "", "Use the search button to display jobs": "", - "There are no JES spool messages to display": "", + "No spool files found": "", "No jobs found": "", - "Retrieving response from zowe.GetJobs": "", + "Retrieving response from JES list API": "", "$(list-ordered) Job ID (default)": "", "$(calendar) Date Submitted": "", "$(calendar) Date Completed": "", @@ -648,6 +648,7 @@ "The response from Zowe CLI was not successful": "", "{0} members failed to load due to invalid name errors for {1}": "", "No data sets found": "", + "Retrieving response from MVS list API": "", "Cannot download, item invalid.": "", "$(case-sensitive) Name (default)": "", "$(calendar) Date Created": "", @@ -740,7 +741,6 @@ "Item invalid.": "", "$(sync~spin) Fetching data set...": "", "Error encountered when refreshing data set view. {0}": "", - "Prompted for a data set pattern, recieved {0}.": "", "Cannot perform the copy operation as the data sets selected have different types": "", "Migration of data set {0} requested.": "", "Recall of data set {0} requested.": "", diff --git a/packages/zowe-explorer/package.json b/packages/zowe-explorer/package.json index 73cc11559d..1d4a5b16d9 100644 --- a/packages/zowe-explorer/package.json +++ b/packages/zowe-explorer/package.json @@ -1793,10 +1793,8 @@ "fresh-clone": "pnpm clean:bundle && pnpm clean:dependencies", "madge": "madge -c --no-color --no-spinner --exclude __mocks__ --extensions js,ts src/", "pretty": "prettier --write .", - "createTestProfileData": "tsx ./scripts/createTestProfileData.ts", - "createDemoNodes": "tsx ./scripts/createDemoNodes.ts", "generateLocalization": "pnpm dlx @vscode/l10n-dev export --o ./l10n ./src && node ./scripts/generatePoeditorJson.js", - "copy-secrets": "tsx ./scripts/getSecretsPrebuilds.ts", + "copy-secrets": "node ./scripts/getSecretsPrebuilds.js", "strip-l10n": "node ./scripts/stripL10nComments.js" }, "engines": { @@ -1830,11 +1828,11 @@ }, "dependencies": { "@vscode/codicons": "^0.0.35", - "@zowe/core-for-zowe-sdk": "8.0.0", - "@zowe/secrets-for-zowe-sdk": "8.0.0", - "@zowe/zos-files-for-zowe-sdk": "8.0.0", - "@zowe/zos-jobs-for-zowe-sdk": "8.0.0", - "@zowe/zosmf-for-zowe-sdk": "8.0.0", + "@zowe/core-for-zowe-sdk": "^8.1.1", + "@zowe/secrets-for-zowe-sdk": "^8.1.0", + "@zowe/zos-files-for-zowe-sdk": "^8.1.1", + "@zowe/zos-jobs-for-zowe-sdk": "^8.1.1", + "@zowe/zosmf-for-zowe-sdk": "^8.1.1", "@zowe/zowe-explorer-api": "3.1.0-SNAPSHOT", "dayjs": "^1.11.10", "fs-extra": "8.0.1", diff --git a/packages/zowe-explorer/scripts/createDemoNodes.ts b/packages/zowe-explorer/scripts/createDemoNodes.ts deleted file mode 100644 index d7b5052c14..0000000000 --- a/packages/zowe-explorer/scripts/createDemoNodes.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createDemoNodes } from "../../../scripts/systemTestEnv"; - -(async () => { - await createDemoNodes(); -})(); diff --git a/packages/zowe-explorer/scripts/createTestProfileData.ts b/packages/zowe-explorer/scripts/createTestProfileData.ts deleted file mode 100644 index b73836e1cf..0000000000 --- a/packages/zowe-explorer/scripts/createTestProfileData.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This program and the accompanying materials are made available under the terms of the * - * Eclipse Public License v2.0 which accompanies this distribution, and is available at * - * https://www.eclipse.org/legal/epl-v20.html * - * * - * SPDX-License-Identifier: EPL-2.0 * - * * - * Copyright Contributors to the Zowe Project. * - * * - */ - -const fs = require("fs"); -const util = require("util"); - -const testProfileData = "./resources/testProfileData.ts"; -const testProfileDataExample = "./resources/testProfileData.example.ts"; - -(async () => { - try { - await util.promisify(fs.access)(testProfileData); - console.log(testProfileData, "- File already exists"); - } catch (err) { - await util.promisify(fs.copyFile)(testProfileDataExample, testProfileData); - console.log(testProfileData, "- File created"); - } -})(); diff --git a/packages/zowe-explorer/scripts/getSecretsPrebuilds.ts b/packages/zowe-explorer/scripts/getSecretsPrebuilds.js similarity index 59% rename from packages/zowe-explorer/scripts/getSecretsPrebuilds.ts rename to packages/zowe-explorer/scripts/getSecretsPrebuilds.js index 65625e4396..dceadd83e2 100644 --- a/packages/zowe-explorer/scripts/getSecretsPrebuilds.ts +++ b/packages/zowe-explorer/scripts/getSecretsPrebuilds.js @@ -1,4 +1,4 @@ -import { copySync } from "fs-extra"; -import { join, resolve } from "path"; +const { copySync } = require("fs-extra"); +const { join, resolve } = require("path"); const secretsPkgDir = resolve(require.resolve("@zowe/secrets-for-zowe-sdk"), "..", ".."); -copySync(join(secretsPkgDir, "prebuilds"), resolve(__dirname, "..", "prebuilds")); \ No newline at end of file +copySync(join(secretsPkgDir, "prebuilds"), resolve(__dirname, "..", "prebuilds")); diff --git a/packages/zowe-explorer/src/configuration/Constants.ts b/packages/zowe-explorer/src/configuration/Constants.ts index f2643a3504..24a965867f 100644 --- a/packages/zowe-explorer/src/configuration/Constants.ts +++ b/packages/zowe-explorer/src/configuration/Constants.ts @@ -16,7 +16,6 @@ import { imperative, PersistenceSchemaEnum } from "@zowe/zowe-explorer-api"; import type { Profiles } from "./Profiles"; export class Constants { - public static CONFIG_PATH: string; public static readonly COMMAND_COUNT = 99; public static readonly MAX_SEARCH_HISTORY = 5; public static readonly MAX_FILE_HISTORY = 10; @@ -82,7 +81,8 @@ export class Constants { public static DS_NAME_REGEX_CHECK = /^[a-zA-Z#@$][a-zA-Z0-9#@$-]{0,7}(\.[a-zA-Z#@$][a-zA-Z0-9#@$-]{0,7})*$/; public static MEMBER_NAME_REGEX_CHECK = /^[a-zA-Z#@$][a-zA-Z0-9#@$]{0,7}$/; public static ACTIVATED = false; - public static SAVED_PROFILE_CONTENTS = new Uint8Array(); + public static SAVED_PROFILE_CONTENTS = new Map(); + public static IGNORE_VAULT_CHANGE = false; public static readonly JOBS_MAX_PREFIX = 8; public static PROFILES_CACHE: Profiles; public static readonly WORKSPACE_UTIL_TAB_SWITCH_DELAY = 200; diff --git a/packages/zowe-explorer/src/configuration/Profiles.ts b/packages/zowe-explorer/src/configuration/Profiles.ts index 8622b3a4f9..de3fd1b590 100644 --- a/packages/zowe-explorer/src/configuration/Profiles.ts +++ b/packages/zowe-explorer/src/configuration/Profiles.ts @@ -520,7 +520,16 @@ export class Profiles extends ProfilesCache { public async editZoweConfigFile(): Promise { ZoweLogger.trace("Profiles.editZoweConfigFile called."); - const existingLayers = await this.getConfigLayers(); + const configLayers = await this.getConfigLayers(); + const uniquePaths = new Set(); + const existingLayers = configLayers.filter((layer) => { + const normalized = path.normalize(layer.path); + if (!uniquePaths.has(normalized)) { + uniquePaths.add(normalized); + return true; + } + return false; + }); if (existingLayers.length === 1) { await this.openConfigFile(existingLayers[0].path); Gui.showMessage(this.manualEditMsg); @@ -530,7 +539,7 @@ export class Profiles extends ProfilesCache { switch (choice) { case "project": for (const file of existingLayers) { - if (file.user) { + if (!file.global) { await this.openConfigFile(file.path); } } @@ -751,7 +760,7 @@ export class Profiles extends ProfilesCache { return filteredProfile; } - public async ssoLogin(node?: Types.IZoweNodeType, label?: string): Promise { + public async ssoLogin(node?: Types.IZoweNodeType, label?: string): Promise { ZoweLogger.trace("Profiles.ssoLogin called."); let loginTokenType: string; let serviceProfile: imperative.IProfileLoaded; @@ -763,7 +772,7 @@ export class Profiles extends ProfilesCache { // This check will handle service profiles that have username and password if (AuthUtils.isProfileUsingBasicAuth(serviceProfile)) { Gui.showMessage(vscode.l10n.t(`This profile is using basic authentication and does not support token authentication.`)); - return; + return false; } const zeInstance = ZoweExplorerApiRegister.getInstance(); @@ -778,7 +787,7 @@ export class Profiles extends ProfilesCache { comment: [`Service profile name`], }) ); - return; + return false; } try { let loginOk = false; @@ -805,6 +814,7 @@ export class Profiles extends ProfilesCache { } else { Gui.showMessage(this.profilesOpCancelled); } + return loginOk; } catch (err) { const message = vscode.l10n.t({ message: `Unable to log in with {0}. {1}`, @@ -813,7 +823,7 @@ export class Profiles extends ProfilesCache { }); ZoweLogger.error(message); Gui.errorMessage(message); - return; + return false; } } @@ -822,10 +832,7 @@ export class Profiles extends ProfilesCache { const configApi = profInfo.getTeamConfig(); const profAttrs = await this.getProfileFromConfig(profileName); if (profAttrs.profLoc.jsonLoc) { - configApi.set( - `${profAttrs.profLoc.jsonLoc}.secure`, - loginTokenType?.startsWith("apimlAuthenticationToken") ? [] : ["tokenValue"] - ); + configApi.set(`${profAttrs.profLoc.jsonLoc}.secure`, loginTokenType?.startsWith("apimlAuthenticationToken") ? [] : ["tokenValue"]); } configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "user")?.argLoc.jsonLoc); configApi.delete(profInfo.mergeArgsForProfile(profAttrs).knownArgs.find((arg) => arg.argName === "password")?.argLoc.jsonLoc); @@ -1059,7 +1066,7 @@ export class Profiles extends ProfilesCache { public async openConfigFile(filePath: string): Promise { ZoweLogger.trace("Profiles.openConfigFile called."); const document = await vscode.workspace.openTextDocument(filePath); - await Gui.showTextDocument(document); + await Gui.showTextDocument(document, { preview: false }); } /** diff --git a/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts b/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts index ecf8139bab..5a2a99a44b 100644 --- a/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts +++ b/packages/zowe-explorer/src/trees/ZoweTreeProvider.ts @@ -128,9 +128,11 @@ export class ZoweTreeProvider { if (icon) { element.iconPath = icon.path; } - element.dirty = true; if (isOpen) { this.mOnDidChangeTreeData.fire(element); + } else { + // Don't mark as dirty when expanded to avoid duplicate refresh + element.dirty = true; } } diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts b/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts index a5e0b8cf3f..ab8919fdd8 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetActions.ts @@ -1297,58 +1297,6 @@ export class DatasetActions { } } - /** - * Prompts the user for a pattern, and populates the [TreeView]{@link vscode.TreeView} based on the pattern - * - * @param {IZoweDatasetTreeNode} node - The session node - * @param datasetProvider - Current DatasetTree used to populate the TreeView - * @returns {Promise} - */ - // This function does not appear to be called by anything except unit and integration tests. - public static async enterPattern(node: IZoweDatasetTreeNode, datasetProvider: Types.IZoweDatasetTreeType): Promise { - ZoweLogger.trace("dataset.actions.enterPattern called."); - let pattern: string; - if (SharedContext.isSessionNotFav(node)) { - // manually entering a search - const options: vscode.InputBoxOptions = { - prompt: vscode.l10n.t("Search Data Sets: use a comma to separate multiple patterns"), - value: node.pattern, - }; - // get user input - pattern = await Gui.showInputBox(options); - if (!pattern) { - Gui.showMessage(vscode.l10n.t("You must enter a pattern.")); - return; - } - ZoweLogger.debug( - vscode.l10n.t({ - message: "Prompted for a data set pattern, recieved {0}.", - args: [pattern], - comment: ["Data Set pattern"], - }) - ); - } else { - // executing search from saved search in favorites - pattern = node.label.toString().substring(node.label.toString().indexOf(":") + 2); - const sessionName = node.label.toString().substring(node.label.toString().indexOf("[") + 1, node.label.toString().indexOf("]")); - await datasetProvider.addSession({ sessionName: sessionName.trim() }); - node = datasetProvider.mSessionNodes.find((tempNode) => tempNode.label.toString().trim() === sessionName.trim()) as IZoweDatasetTreeNode; - } - - // update the treeview with the new pattern - // TODO figure out why a label change is needed to refresh the treeview, - // instead of changing the collapsible state - // change label so the treeview updates - node.tooltip = node.pattern = pattern.toUpperCase(); - node.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; - node.dirty = true; - const icon = IconGenerator.getIconByNode(node); - if (icon) { - node.iconPath = icon.path; - } - datasetProvider.addSearchHistory(node.pattern); - } - /** * Copy data sets * diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts b/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts index 3575bf2404..8a7a60d428 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetInit.ts @@ -23,6 +23,7 @@ import { SharedUtils } from "../shared/SharedUtils"; export class DatasetInit { public static async createDatasetTree(log: imperative.Logger): Promise { + ZoweLogger.trace("DatasetInit.createDatasetTree called."); const tree = new DatasetTree(); await tree.initializeFavorites(log); await tree.addSession(); @@ -30,7 +31,7 @@ export class DatasetInit { } public static async initDatasetProvider(context: vscode.ExtensionContext): Promise { - ZoweLogger.trace("dataset.init.initDatasetProvider called."); + ZoweLogger.trace("DatasetInit.initDatasetProvider called."); context.subscriptions.push(vscode.workspace.registerFileSystemProvider(ZoweScheme.DS, DatasetFSProvider.instance, { isCaseSensitive: true })); const datasetProvider = await DatasetInit.createDatasetTree(ZoweLogger.log); if (datasetProvider == null) { diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts b/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts index e6cbf56516..b99db6fd30 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetTree.ts @@ -147,13 +147,7 @@ export class DatasetTree extends ZoweTreeProvider implemen if (element.contextValue && element.contextValue === Constants.FAV_PROFILE_CONTEXT) { return this.loadProfilesForFavorites(this.log, element); } - let response: IZoweDatasetTreeNode[] = []; - try { - response = await element.getChildren(); - } catch (error) { - await AuthUtils.errorHandling(error, String(element.label)); - return []; - } + const response = await element.getChildren(); const finalResponse: IZoweDatasetTreeNode[] = []; for (const item of response) { @@ -169,16 +163,6 @@ export class DatasetTree extends ZoweTreeProvider implemen item.contextValue = SharedContext.withProfile(item); } - if (finalResponse.length === 0) { - return (element.children = [ - new ZoweDatasetNode({ - label: vscode.l10n.t("No data sets found"), - collapsibleState: vscode.TreeItemCollapsibleState.None, - parentNode: element, - contextOverride: Constants.INFORMATION_CONTEXT, - }), - ]); - } return finalResponse; } return this.mSessionNodes; @@ -407,13 +391,13 @@ export class DatasetTree extends ZoweTreeProvider implemen for (const favorite of favsForProfile) { // If profile and session already exists for favorite node, add to updatedFavsForProfile and go to next array item if (favorite.getProfile() && favorite.getSession()) { - updatedFavsForProfile.push(favorite as IZoweDatasetTreeNode); + updatedFavsForProfile.push(favorite); continue; } // If no profile/session for favorite node yet, then add session and profile to favorite node: favorite.setProfileToChoice(profile); favorite.setSessionToChoice(session); - updatedFavsForProfile.push(favorite as IZoweDatasetTreeNode); + updatedFavsForProfile.push(favorite); } // This updates the profile node's children in the this.mFavorites array, as well. return updatedFavsForProfile; @@ -457,8 +441,12 @@ export class DatasetTree extends ZoweTreeProvider implemen collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, session, profile, + contextOverride: Constants.DS_SESSION_CONTEXT, }); - node.contextValue = Constants.DS_SESSION_CONTEXT + (profile.type !== "zosmf" ? `.profile=${profile.type}.` : ""); + if (profile.type !== "zosmf") { + // TODO: Why do we inject profiles in context value only for DS tree? + node.contextValue += `.profile=${profile.type}.`; + } await this.refreshHomeProfileContext(node); const icon = IconGenerator.getIconByNode(node); if (icon) { @@ -571,7 +559,7 @@ export class DatasetTree extends ZoweTreeProvider implemen if (matchingNode) { matchingNode.label = afterLabel; matchingNode.tooltip = afterLabel; - this.refreshElement(matchingNode as IZoweDatasetTreeNode); + this.refreshElement(matchingNode); } } } @@ -892,10 +880,10 @@ export class DatasetTree extends ZoweTreeProvider implemen if (session.children) { for (const node of session.children) { if (node.contextValue !== Constants.INFORMATION_CONTEXT) { - loadedItems.push(node as IZoweDatasetTreeNode); + loadedItems.push(node); for (const member of node.children) { if (member.contextValue !== Constants.INFORMATION_CONTEXT) { - loadedItems.push(member as IZoweDatasetTreeNode); + loadedItems.push(member); } } } @@ -983,8 +971,7 @@ export class DatasetTree extends ZoweTreeProvider implemen let setIcon: IconUtils.IIconItem; if (child.collapsibleState === vscode.TreeItemCollapsibleState.Collapsed) { setIcon = IconGenerator.getIconById(IconUtils.IconId.filterFolder); - } - if (child.collapsibleState === vscode.TreeItemCollapsibleState.Expanded) { + } else if (child.collapsibleState === vscode.TreeItemCollapsibleState.Expanded) { setIcon = IconGenerator.getIconById(IconUtils.IconId.filterFolderOpen); } if (setIcon) { @@ -992,7 +979,6 @@ export class DatasetTree extends ZoweTreeProvider implemen } } } - sessionNode.dirty = true; const icon = IconGenerator.getIconByNode(sessionNode); if (icon) { sessionNode.iconPath = icon.path; @@ -1003,13 +989,13 @@ export class DatasetTree extends ZoweTreeProvider implemen public async datasetFilterPrompt(node: IZoweDatasetTreeNode): Promise { ZoweLogger.trace("DatasetTree.datasetFilterPrompt called."); - ZoweLogger.debug(vscode.l10n.t("Prompting the user for a data set pattern")); let pattern: string; await this.checkCurrentProfile(node); const sessionNode = node; if (Profiles.getInstance().validProfile !== Validation.ValidationType.INVALID) { if (SharedContext.isSessionNotFav(node)) { + ZoweLogger.debug(vscode.l10n.t("Prompting the user for a data set pattern")); if (this.mHistory.getSearchHistory().length > 0) { const createPick = new FilterDescriptor(DatasetTree.defaultDialogText); const items: vscode.QuickPickItem[] = this.mHistory.getSearchHistory().map((element) => new FilterItem({ text: element })); @@ -1032,12 +1018,12 @@ export class DatasetTree extends ZoweTreeProvider implemen pattern = choice.label; } } - const options2: vscode.InputBoxOptions = { + const options: vscode.InputBoxOptions = { prompt: vscode.l10n.t("Search Data Sets: use a comma to separate multiple patterns"), value: pattern, }; // get user input - pattern = await Gui.showInputBox(options2); + pattern = await Gui.showInputBox(options); if (!pattern) { Gui.showMessage(vscode.l10n.t("You must enter a pattern.")); return; @@ -1055,7 +1041,6 @@ export class DatasetTree extends ZoweTreeProvider implemen } } // looking for members in pattern - node.children = []; node.dirty = true; AuthUtils.syncSessionNode((profile) => ZoweExplorerApiRegister.getMvsApi(profile), sessionNode); @@ -1088,6 +1073,7 @@ export class DatasetTree extends ZoweTreeProvider implemen sessionNode.resourceUri = sessionNode.resourceUri.with({ query: `pattern=${pattern}` }); } await TreeViewUtils.expandNode(sessionNode, this); + this.refresh(); } public checkFilterPattern(dsName: string, itemName: string): boolean { @@ -1276,7 +1262,7 @@ export class DatasetTree extends ZoweTreeProvider implemen } c.children.sort(ZoweDatasetNode.sortBy(node.sort)); - this.nodeDataChanged(c as IZoweDatasetTreeNode); + this.nodeDataChanged(c); } } } @@ -1389,7 +1375,7 @@ export class DatasetTree extends ZoweTreeProvider implemen if (node.children?.length > 0) { // children nodes already exist, sort and repaint to avoid extra refresh for (const c of node.children) { - const asDs = c as IZoweDatasetTreeNode; + const asDs = c; // PDS-level filters should have precedence over a session-level filter if (asDs.filter != null) { @@ -1400,15 +1386,15 @@ export class DatasetTree extends ZoweTreeProvider implemen // If there was an old session-wide filter set: refresh to get any // missing nodes - new filter will be applied if (oldFilter != null) { - this.refreshElement(c as IZoweDatasetTreeNode); + this.refreshElement(c); continue; } if (newFilter != null && c.children?.length > 0) { c.children = c.children.filter(ZoweDatasetNode.filterBy(newFilter)); - this.nodeDataChanged(c as IZoweDatasetTreeNode); + this.nodeDataChanged(c); } else { - this.refreshElement(c as IZoweDatasetTreeNode); + this.refreshElement(c); } } } diff --git a/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts b/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts index 1483cf89a0..73444e3628 100644 --- a/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts +++ b/packages/zowe-explorer/src/trees/dataset/DatasetUtils.ts @@ -75,14 +75,8 @@ export class DatasetUtils { const split = bracket > -1 ? label.substring(0, bracket).split(".", limit) : label.split(".", limit); for (let i = split.length - 1; i > 0; i--) { for (const [ext, matches] of DS_EXTENSION_MAP.entries()) { - for (const match of matches) { - if (match instanceof RegExp) { - if (match.test(split[i])) { - return ext; - } - } else if (match.includes(split[i])) { - return ext; - } + if (matches.some((match) => (match instanceof RegExp ? match.test(split[i]) : match === split[i]))) { + return ext; } } } diff --git a/packages/zowe-explorer/src/trees/dataset/ZoweDatasetNode.ts b/packages/zowe-explorer/src/trees/dataset/ZoweDatasetNode.ts index f2b273dee4..355c9a5397 100644 --- a/packages/zowe-explorer/src/trees/dataset/ZoweDatasetNode.ts +++ b/packages/zowe-explorer/src/trees/dataset/ZoweDatasetNode.ts @@ -102,13 +102,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod if (this.label !== vscode.l10n.t("Favorites")) { const sessionLabel = opts.profile?.name ?? SharedUtils.getSessionLabel(this); - if (this.getParent() == null || this.getParent().label === vscode.l10n.t("Favorites")) { - this.resourceUri = vscode.Uri.from({ - scheme: ZoweScheme.DS, - path: `/${sessionLabel}/`, - }); - DatasetFSProvider.instance.createDirectory(this.resourceUri); - } else if ( + if ( this.contextValue === Constants.DS_DS_CONTEXT || this.contextValue === Constants.DS_PDS_CONTEXT || this.contextValue === Constants.DS_MIGRATED_FILE_CONTEXT @@ -130,7 +124,15 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod }); this.command = { command: "vscode.open", title: "", arguments: [this.resourceUri] }; } else { - this.resourceUri = null; + this.resourceUri = vscode.Uri.from({ + scheme: ZoweScheme.DS, + path: `/${sessionLabel}/`, + }); + if (this.getParent() == null || this.getParent().label === vscode.l10n.t("Favorites")) { + DatasetFSProvider.instance.createDirectory(this.resourceUri); + } else if (this.contextValue === Constants.INFORMATION_CONTEXT) { + this.command = { command: "zowe.placeholderCommand", title: "Placeholder" }; + } } if (opts.encoding != null) { @@ -201,20 +203,15 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod * @returns {Promise} */ public async getChildren(): Promise { - ZoweLogger.trace("ZoweDatasetNode.getChildren called."); + ZoweLogger.trace(`ZoweDatasetNode.getChildren called for ${this.label as string}.`); if (!this.pattern && SharedContext.isSessionNotFav(this)) { const placeholder = new ZoweDatasetNode({ label: vscode.l10n.t("Use the search button to display data sets"), collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: this, contextOverride: Constants.INFORMATION_CONTEXT, - profile: null, }); - placeholder.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; - return [placeholder]; + return (this.children = [placeholder]); } if (SharedContext.isDocument(this) || SharedContext.isInformation(this)) { return []; @@ -232,8 +229,8 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod // Gets the datasets from the pattern or members of the dataset and displays any thrown errors const cachedProfile = Profiles.getInstance().loadNamedProfile(this.getProfileName()); const responses = await this.getDatasets(cachedProfile); - if (responses.length === 0) { - return; + if (responses == null) { + return []; } // push nodes to an object with property names to avoid duplicates @@ -243,7 +240,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod // The dataSetsMatchingPattern API may return success=false and apiResponse=[] when no data sets found if (!response.success && !(Array.isArray(response.apiResponse) && response.apiResponse.length === 0)) { await AuthUtils.errorHandling(vscode.l10n.t("The response from Zowe CLI was not successful")); - return; + return []; } // Loops through all the returned dataset members and creates nodes for them @@ -314,6 +311,7 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod parentNode: this, encoding: cachedEncoding, profile: cachedProfile, + contextOverride: cachedEncoding?.kind === "binary" ? Constants.DS_DS_BINARY_CONTEXT : Constants.DS_DS_CONTEXT, }); elementChildren[dsNode.label.toString()] = dsNode; } else if (item.member) { @@ -376,10 +374,6 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod parentNode: this, contextOverride: Constants.INFORMATION_CONTEXT, }); - placeholder.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; this.children = [placeholder]; } else { const newChildren = Object.keys(elementChildren) @@ -538,14 +532,15 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod return fileEntry?.etag; } - private async getDatasets(profile: imperative.IProfileLoaded): Promise { + private async getDatasets(profile: imperative.IProfileLoaded): Promise { ZoweLogger.trace("ZoweDatasetNode.getDatasets called."); const responses: zosfiles.IZosFilesResponse[] = []; const options: zosfiles.IListOptions = { attributes: true, responseTimeout: profile.profile.responseTimeout, }; - if (SharedContext.isSession(this) || SharedContext.isFavoriteSearch(this)) { + const isSession = SharedContext.isSession(this) || SharedContext.isFavoriteSearch(this); + if (isSession) { const fullPattern = SharedContext.isFavoriteSearch(this) ? (this.label as string) : this.pattern; const dsTree = SharedTreeProviders.ds as DatasetTree; this.patternMatches = dsTree.extractPatterns(fullPattern); @@ -557,38 +552,46 @@ export class ZoweDatasetNode extends ZoweTreeNode implements IZoweDatasetTreeNod } this.tooltip = this.pattern = dsPattern.toUpperCase(); } + } - const dsPatterns = [ - ...new Set( - this.pattern - .toUpperCase() - .split(",") - .map((p) => p.trim()) - ), - ]; - const mvsApi = ZoweExplorerApiRegister.getMvsApi(profile); - if (!mvsApi.getSession(profile)) { - throw new imperative.ImperativeError({ - msg: vscode.l10n.t("Profile auth error"), - additionalDetails: vscode.l10n.t("Profile is not authenticated, please log in to continue"), - errorCode: `${imperative.RestConstants.HTTP_STATUS_401}`, - }); - } - if (mvsApi.dataSetsMatchingPattern) { - responses.push(await mvsApi.dataSetsMatchingPattern(dsPatterns)); - } else { - for (const dsp of dsPatterns) { - responses.push(await mvsApi.dataSet(dsp)); + try { + if (isSession) { + const dsPatterns = [ + ...new Set( + this.pattern + .toUpperCase() + .split(",") + .map((p) => p.trim()) + ), + ]; + const mvsApi = ZoweExplorerApiRegister.getMvsApi(profile); + if (!mvsApi.getSession(profile)) { + throw new imperative.ImperativeError({ + msg: vscode.l10n.t("Profile auth error"), + additionalDetails: vscode.l10n.t("Profile is not authenticated, please log in to continue"), + errorCode: `${imperative.RestConstants.HTTP_STATUS_401}`, + }); } - } - } else if (this.memberPattern) { - this.memberPattern = this.memberPattern.toUpperCase(); - for (const memPattern of this.memberPattern.split(",")) { - options.pattern = memPattern; + if (mvsApi.dataSetsMatchingPattern) { + responses.push(await mvsApi.dataSetsMatchingPattern(dsPatterns)); + } else { + for (const dsp of dsPatterns) { + responses.push(await mvsApi.dataSet(dsp)); + } + } + } else if (this.memberPattern) { + this.memberPattern = this.memberPattern.toUpperCase(); + for (const memPattern of this.memberPattern.split(",")) { + options.pattern = memPattern; + responses.push(await ZoweExplorerApiRegister.getMvsApi(profile).allMembers(this.label as string, options)); + } + } else { responses.push(await ZoweExplorerApiRegister.getMvsApi(profile).allMembers(this.label as string, options)); } - } else { - responses.push(await ZoweExplorerApiRegister.getMvsApi(profile).allMembers(this.label as string, options)); + } catch (error) { + const updated = await AuthUtils.errorHandling(error, this.getProfileName(), vscode.l10n.t("Retrieving response from MVS list API")); + AuthUtils.syncSessionNode((prof) => ZoweExplorerApiRegister.getMvsApi(prof), this.getSessionNode(), updated && this); + return; } return responses; } diff --git a/packages/zowe-explorer/src/trees/job/JobInit.ts b/packages/zowe-explorer/src/trees/job/JobInit.ts index 7367955e39..2f4516ba08 100644 --- a/packages/zowe-explorer/src/trees/job/JobInit.ts +++ b/packages/zowe-explorer/src/trees/job/JobInit.ts @@ -32,7 +32,7 @@ export class JobInit { * @implements {vscode.TreeDataProvider} */ public static async createJobsTree(log: imperative.Logger): Promise { - ZoweLogger.trace("ZosJobsProvider.createJobsTree called."); + ZoweLogger.trace("JobInit.createJobsTree called."); const tree = new JobTree(); await tree.initializeJobsTree(log); await tree.addSession(); @@ -40,7 +40,7 @@ export class JobInit { } public static async initJobsProvider(context: vscode.ExtensionContext): Promise { - ZoweLogger.trace("job.init.initJobsProvider called."); + ZoweLogger.trace("JobInit.initJobsProvider called."); context.subscriptions.push(vscode.workspace.registerFileSystemProvider(ZoweScheme.Jobs, JobFSProvider.instance, { isCaseSensitive: false })); const jobsProvider = await JobInit.createJobsTree(ZoweLogger.log); if (jobsProvider == null) { diff --git a/packages/zowe-explorer/src/trees/job/JobTree.ts b/packages/zowe-explorer/src/trees/job/JobTree.ts index 176447cb89..0262ab49ec 100644 --- a/packages/zowe-explorer/src/trees/job/JobTree.ts +++ b/packages/zowe-explorer/src/trees/job/JobTree.ts @@ -32,21 +32,6 @@ import { AuthUtils } from "../../utils/AuthUtils"; import { PollProvider } from "./JobPollProvider"; import { Definitions } from "../../configuration/Definitions"; -/** - * Creates the Job tree that contains nodes of sessions, jobs and spool items - * - * @export - * @class ZosJobsProvider - * @implements {vscode.TreeDataProvider} - */ -export async function createJobsTree(log: imperative.Logger): Promise { - ZoweLogger.trace("ZosJobsProvider.createJobsTree called."); - const tree = new JobTree(); - await tree.initializeJobsTree(log); - await tree.addSession(); - return tree; -} - export class JobTree extends ZoweTreeProvider implements Types.IZoweJobTreeType { public static readonly JobId = "JobId: "; public static readonly Owner = "Owner: "; @@ -139,7 +124,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param {IZoweJobTreeNode} node */ public saveSearch(node: IZoweJobTreeNode): void { - ZoweLogger.trace("ZosJobsProvider.saveSearch called."); + ZoweLogger.trace("JobTree.saveSearch called."); node.contextValue = SharedContext.asFavorite(node); } public saveFile(_document: vscode.TextDocument): void { @@ -162,7 +147,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @returns {IZoweJobTreeNode[] | Promise} */ public async getChildren(element?: IZoweJobTreeNode | undefined): Promise { - ZoweLogger.trace("ZosJobsProvider.getChildren called."); + ZoweLogger.trace("JobTree.getChildren called."); if (element) { // solution for optional credentials. Owner is having error on initialization. if (element.owner === "") { @@ -185,7 +170,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @returns {vscode.TreeView} */ public getTreeView(): vscode.TreeView { - ZoweLogger.trace("ZosJobsProvider.getTreeView called."); + ZoweLogger.trace("JobTree.getTreeView called."); return this.treeView; } @@ -194,7 +179,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param profile the profile to add to the tree */ public async addSingleSession(profile: imperative.IProfileLoaded): Promise { - ZoweLogger.trace("ZosJobsProvider.addSingleSession called."); + ZoweLogger.trace("JobTree.addSingleSession called."); if (profile) { // If session is already added, do nothing if (this.mSessionNodes.find((tNode) => tNode.label.toString() === profile.name)) { @@ -217,8 +202,8 @@ export class JobTree extends ZoweTreeProvider implements Types collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, session, profile, + contextOverride: Constants.JOBS_SESSION_CONTEXT, }); - node.contextValue = Constants.JOBS_SESSION_CONTEXT; await this.refreshHomeProfileContext(node); const icon = IconGenerator.getIconByNode(node); if (icon) { @@ -231,7 +216,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async delete(node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.delete called."); + ZoweLogger.trace("JobTree.delete called."); await JobFSProvider.instance.delete(node.resourceUri, { recursive: false, deleteRemote: true }); const favNode = this.relabelFavoritedJob(node); @@ -248,7 +233,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @returns {IZoweJobTreeNode | undefined} Returns matching profile node if found. Otherwise, returns undefined. */ public findMatchingProfileInArray(jobsProvider: IZoweJobTreeNode[], profileName: string): IZoweJobTreeNode | undefined { - ZoweLogger.trace("ZosJobsProvider.findMatchingProfileInArray called."); + ZoweLogger.trace("JobTree.findMatchingProfileInArray called."); return jobsProvider.find((treeNode) => treeNode.label === profileName); } @@ -257,7 +242,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param node */ public findFavoritedNode(node: IZoweJobTreeNode): IZoweJobTreeNode { - ZoweLogger.trace("ZosJobsProvider.findFavoritedNode called."); + ZoweLogger.trace("JobTree.findFavoritedNode called."); const profileNodeInFavorites = this.findMatchingProfileInArray(this.mFavorites, node.getProfileName()); return profileNodeInFavorites?.children.find( (temp) => temp.label === node.getLabel().toString() && temp.contextValue.includes(node.contextValue) @@ -269,7 +254,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param node */ public findNonFavoritedNode(node: IZoweJobTreeNode): IZoweJobTreeNode { - ZoweLogger.trace("ZosJobsProvider.findNonFavoritedNode called."); + ZoweLogger.trace("JobTree.findNonFavoritedNode called."); const profileName = node.getProfileName(); const sessionNode = this.mSessionNodes.find((session) => session.label.toString().trim() === profileName); return sessionNode?.children.find((temp) => temp.label === node.label); @@ -280,7 +265,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param node */ public findEquivalentNode(node: IZoweJobTreeNode, isFavorite: boolean): IZoweJobTreeNode { - ZoweLogger.trace("ZosJobsProvider.findEquivalentNode called."); + ZoweLogger.trace("JobTree.findEquivalentNode called."); return isFavorite ? this.findNonFavoritedNode(node) : this.findFavoritedNode(node); } @@ -290,7 +275,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @returns {ZoweJobNode} */ public async createProfileNodeForFavs(profileName: string): Promise { - ZoweLogger.trace("ZosJobsProvider.createProfileNodeForFavs called."); + ZoweLogger.trace("JobTree.createProfileNodeForFavs called."); let favProfileNode: ZoweJobNode; try { const profile = Profiles.getInstance().loadNamedProfile(profileName); @@ -334,7 +319,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param log - Logger */ public async initializeJobsTree(log: imperative.Logger): Promise { - ZoweLogger.trace("ZosJobsProvider.initializeJobsTree called."); + ZoweLogger.trace("JobTree.initializeJobsTree called."); this.log = log; ZoweLogger.debug(vscode.l10n.t("Initializing profiles with jobs favorites.")); const lines: string[] = this.mHistory.readFavorites(); @@ -369,7 +354,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @returns IZoweJobTreeNode */ public initializeFavChildNodeForProfile(label: string, contextValue: string, parentNode: IZoweJobTreeNode): ZoweJobNode { - ZoweLogger.trace("ZosJobsProvider.initializeFavChildNodeForProfile called."); + ZoweLogger.trace("JobTree.initializeFavChildNodeForProfile called."); let favJob: ZoweJobNode; if (contextValue.startsWith(Constants.JOBS_JOB_CONTEXT)) { favJob = new ZoweJobNode({ @@ -406,7 +391,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param parentNode */ public async loadProfilesForFavorites(log: imperative.Logger, parentNode: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.loadProfilesForFavorites called."); + ZoweLogger.trace("JobTree.loadProfilesForFavorites called."); const profileName = parentNode.label as string; const updatedFavsForProfile: IZoweJobTreeNode[] = []; let profile: imperative.IProfileLoaded; @@ -490,7 +475,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param {IZoweJobTreeNode} node */ public async addFavorite(node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.addFavorite called."); + ZoweLogger.trace("JobTree.addFavorite called."); let favJob: ZoweJobNode; // Get node's profile node in favorites const profileName = node.getProfileName(); @@ -544,7 +529,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param {IZoweJobTreeNode} node */ public async removeFavorite(node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.removeFavorite called."); + ZoweLogger.trace("JobTree.removeFavorite called."); // Get node's profile node in favorites const profileName = node.getProfileName(); const profileNodeInFavorites = this.findMatchingProfileInArray(this.mFavorites, profileName); @@ -565,7 +550,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public updateFavorites(): void { - ZoweLogger.trace("ZosJobsProvider.updateFavorites called."); + ZoweLogger.trace("JobTree.updateFavorites called."); const favoritesArray = []; this.mFavorites.forEach((profileNode) => { profileNode.children.forEach((fav) => { @@ -589,7 +574,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param userSelected True if the function is being called directly because the user selected to remove the profile from Favorites */ public async removeFavProfile(profileName: string, userSelected: boolean): Promise { - ZoweLogger.trace("ZosJobsProvider.removeFavProfile called."); + ZoweLogger.trace("JobTree.removeFavProfile called."); // If user selected the "Remove profile from Favorites option", confirm they are okay with deleting all favorited items for that profile. let cancelled = false; if (userSelected) { @@ -626,17 +611,17 @@ export class JobTree extends ZoweTreeProvider implements Types } public removeSearchHistory(name: string): void { - ZoweLogger.trace("ZosJobsProvider.removeSearchHistory called."); + ZoweLogger.trace("JobTree.removeSearchHistory called."); this.mHistory.removeSearchHistory(name); } public removeSession(name: string): void { - ZoweLogger.trace("ZosJobsProvider.removeSession called."); + ZoweLogger.trace("JobTree.removeSession called."); this.mHistory.removeSession(name); } public resetSearchHistory(): void { - ZoweLogger.trace("ZosJobsProvider.resetSearchHistory called."); + ZoweLogger.trace("JobTree.resetSearchHistory called."); this.mHistory.resetSearchHistory(); } @@ -656,7 +641,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async getUserJobsMenuChoice(): Promise { - ZoweLogger.trace("ZosJobsProvider.getUserJobsMenuChoice called."); + ZoweLogger.trace("JobTree.getUserJobsMenuChoice called."); const items: FilterItem[] = this.mHistory .getSearchHistory() .map((element) => new FilterItem({ text: element, menuType: Definitions.JobPickerTypes.History })); @@ -677,7 +662,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async getUserSearchQueryInput(choice: FilterItem, node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.getUserSearchQueryInput called."); + ZoweLogger.trace("JobTree.getUserSearchQueryInput called."); if (!choice) { return undefined; } @@ -703,7 +688,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async applyRegularSessionSearchLabel(node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.applyRegularSessionsSearchLabel called."); + ZoweLogger.trace("JobTree.applyRegularSessionsSearchLabel called."); const choice = await this.getUserJobsMenuChoice(); const searchCriteriaObj = await this.getUserSearchQueryInput(choice, node); @@ -721,7 +706,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async handleSearchByJobId(jobId?: string): Promise { - ZoweLogger.trace("ZosJobsProvider.handleSearchByJobId called."); + ZoweLogger.trace("JobTree.handleSearchByJobId called."); const options = { prompt: vscode.l10n.t("Enter a job ID"), value: jobId, @@ -740,7 +725,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public parseJobSearchQuery(searchCriteria: string): Definitions.IJobSearchCriteria { - ZoweLogger.trace("ZosJobsProvider.parseJobSearchQuery called."); + ZoweLogger.trace("JobTree.parseJobSearchQuery called."); const searchCriteriaObj: Definitions.IJobSearchCriteria = { Owner: undefined, Prefix: undefined, @@ -769,7 +754,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public getPopulatedPickerValues(searchObj: Definitions.IJobSearchCriteria): Definitions.IJobPickerOption[] { - ZoweLogger.trace("ZosJobsProvider.getPopulatedPickerValues called."); + ZoweLogger.trace("JobTree.getPopulatedPickerValues called."); const historyPopulatedItems = this.JOB_PROPERTIES; historyPopulatedItems.forEach((prop) => { if (prop.key === "owner") { @@ -786,7 +771,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async applySavedFavoritesSearchLabel(node): Promise { - ZoweLogger.trace("ZosJobsProvider.applySavedFavoritesSearchLabel called."); + ZoweLogger.trace("JobTree.applySavedFavoritesSearchLabel called."); // executing search from saved search in favorites const searchCriteria = node.label as string; const session = node.getProfileName(); @@ -808,7 +793,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @returns {Promise} */ public async searchPrompt(node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.searchPrompt called."); + ZoweLogger.trace("JobTree.searchPrompt called."); await this.checkCurrentProfile(node); let searchCriteria: string = ""; if (Profiles.getInstance().validProfile !== Validation.ValidationType.INVALID) { @@ -847,7 +832,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public async onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent): Promise { - ZoweLogger.trace("ZosJobsProvider.onDidChangeConfiguration called."); + ZoweLogger.trace("JobTree.onDidChangeConfiguration called."); if (e.affectsConfiguration(JobTree.persistenceSchema)) { const setting: any = { ...SettingsConfig.getDirectValue(JobTree.persistenceSchema), @@ -861,7 +846,7 @@ export class JobTree extends ZoweTreeProvider implements Types } public deleteSession(node: IZoweJobTreeNode, hideFromAllTrees?: boolean): void { - ZoweLogger.trace("ZosJobsProvider.deleteSession called."); + ZoweLogger.trace("JobTree.deleteSession called."); super.deleteSession(node, hideFromAllTrees); } @@ -872,7 +857,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param jobid - A specific jobid search item */ public createSearchLabel(owner: string, prefix: string, jobid: string, status: string): string { - ZoweLogger.trace("ZosJobsProvider.createSearchLabel called."); + ZoweLogger.trace("JobTree.createSearchLabel called."); const alphaNumeric = new RegExp("^w+$"); if (jobid && !alphaNumeric.exec(jobid.trim())) { return JobTree.JobId + jobid.toUpperCase().trim(); @@ -892,12 +877,12 @@ export class JobTree extends ZoweTreeProvider implements Types } public addFileHistory(_criteria: string): void { - ZoweLogger.trace("ZosJobsProvider.addFileHistory called."); + ZoweLogger.trace("JobTree.addFileHistory called."); throw new Error("Method not implemented."); } private async setJobStatus(node: IZoweJobTreeNode): Promise { - ZoweLogger.trace("ZosJobsProvider.setJobStatus called."); + ZoweLogger.trace("JobTree.setJobStatus called."); const jobStatusSelection = ZoweExplorerApiRegister.getJesApi(node.getProfile()).getJobsByParameters ? Constants.JOB_STATUS : Constants.JOB_STATUS_UNSUPPORTED; @@ -912,7 +897,7 @@ export class JobTree extends ZoweTreeProvider implements Types jobProperties: Definitions.IJobPickerOption[], node: IZoweJobTreeNode ): Promise { - ZoweLogger.trace("ZosJobsProvider.handleEditingMultiJobParameters called."); + ZoweLogger.trace("JobTree.handleEditingMultiJobParameters called."); const editableItems: vscode.QuickPickItem[] = [new FilterItem({ text: JobTree.submitJobQueryLabel, show: true }), Constants.SEPARATORS.BLANK]; jobProperties.forEach((prop) => { if (prop.key === "owner" && !prop.value) { @@ -949,7 +934,6 @@ export class JobTree extends ZoweTreeProvider implements Types }; this.resetJobProperties(jobProperties); - await TreeViewUtils.expandNode(node, this); return searchCriteriaObj; } default: { @@ -967,7 +951,7 @@ export class JobTree extends ZoweTreeProvider implements Types return this.handleEditingMultiJobParameters(jobProperties, node); } private resetJobProperties(jobProperties: Definitions.IJobPickerOption[]): Definitions.IJobPickerOption[] { - ZoweLogger.trace("ZosJobsProvider.resetJobProperties called."); + ZoweLogger.trace("JobTree.resetJobProperties called."); jobProperties.forEach((prop) => { if (prop.key === "owner") { prop.value = ""; @@ -988,7 +972,7 @@ export class JobTree extends ZoweTreeProvider implements Types * @param storedSearch - The original search string */ private applySearchLabelToNode(node: IZoweJobTreeNode, storedSearchObj: Definitions.IJobSearchCriteria): void { - ZoweLogger.trace("ZosJobsProvider.applySearchLabelToNode called."); + ZoweLogger.trace("JobTree.applySearchLabelToNode called."); if (storedSearchObj) { node.searchId = storedSearchObj.JobId || ""; node.owner = storedSearchObj.Owner || "*"; @@ -998,7 +982,7 @@ export class JobTree extends ZoweTreeProvider implements Types } private relabelFavoritedJob(node: IZoweJobTreeNode): IZoweJobTreeNode { - ZoweLogger.trace("ZosJobsProvider.relabelFavoritedJob called."); + ZoweLogger.trace("JobTree.relabelFavoritedJob called."); node.label = node.label.toString().substring(0, node.label.toString().lastIndexOf(")") + 1); return node; } diff --git a/packages/zowe-explorer/src/trees/job/ZoweJobNode.ts b/packages/zowe-explorer/src/trees/job/ZoweJobNode.ts index 46edc1c6a9..4d4f7dfc86 100644 --- a/packages/zowe-explorer/src/trees/job/ZoweJobNode.ts +++ b/packages/zowe-explorer/src/trees/job/ZoweJobNode.ts @@ -103,6 +103,8 @@ export class ZoweJobNode extends ZoweTreeNode implements IZoweJobTreeNode { if (this.getParent()?.label !== vscode.l10n.t("Favorites") && !SharedContext.isFavorite(this)) { this.id = this.label as string; } + } else if (this.contextValue === Constants.INFORMATION_CONTEXT) { + this.command = { command: "zowe.placeholderCommand", title: "Placeholder" }; } else if (this.job != null) { this.resourceUri = vscode.Uri.from({ scheme: ZoweScheme.Jobs, @@ -117,49 +119,36 @@ export class ZoweJobNode extends ZoweTreeNode implements IZoweJobTreeNode { * @returns {Promise} */ public async getChildren(): Promise { - const thisSessionNode = this.getSessionNode(); - ZoweLogger.trace(`ZoweJobNode.getChildren called for ${String(thisSessionNode.label)}.`); - if (this?.filter !== undefined) { - return this.children; - } + ZoweLogger.trace(`ZoweJobNode.getChildren called for ${this.label as string}.`); if (SharedContext.isSession(this) && !this.filtered && !SharedContext.isFavorite(this)) { const placeholder = new ZoweJobNode({ label: vscode.l10n.t("Use the search button to display jobs"), collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: this, - profile: thisSessionNode.getProfile(), contextOverride: Constants.INFORMATION_CONTEXT, }); - placeholder.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; return [placeholder]; } - if (!this.dirty) { + if (!this.dirty || this.filter !== undefined) { return this.children; } const elementChildren: Record = {}; if (SharedContext.isJob(this)) { // Fetch spool files under job node - const cachedProfile = Profiles.getInstance().loadNamedProfile(this.getProfileName()); - const spools: zosjobs.IJobFile[] = ( - (await ZoweExplorerApiRegister.getJesApi(cachedProfile).getSpoolFiles(this.job.jobname, this.job.jobid)) ?? [] - ) - // filter out all the objects which do not seem to be correct Job File Document types - // see an issue #845 for the details - .filter((item) => !(item.id === undefined && item.ddname === undefined && item.stepname === undefined)); - if (!spools.length) { + const spools = await this.getSpoolFiles(this.job); + if (spools == null) { + return []; + } else if (!spools.length) { const noSpoolNode = new ZoweSpoolNode({ - label: vscode.l10n.t("There are no JES spool messages to display"), + label: vscode.l10n.t("No spool files found"), collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: this, profile: this.getProfile(), + contextOverride: Constants.INFORMATION_CONTEXT, }); - noSpoolNode.iconPath = undefined; - return [noSpoolNode]; + return (this.children = [noSpoolNode]); } spools.forEach((spool) => { const procstep = spool.procstep ? spool.procstep : undefined; @@ -202,20 +191,17 @@ export class ZoweJobNode extends ZoweTreeNode implements IZoweJobTreeNode { } else { // Fetch jobs under session node const jobs = await this.getJobs(this._owner, this._prefix, this._searchId, this._jobStatus); - if (jobs.length === 0) { + if (jobs == null) { + return []; + } else if (jobs.length === 0) { const noJobsNode = new ZoweJobNode({ label: vscode.l10n.t("No jobs found"), collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode: this, profile: this.getProfile(), + contextOverride: Constants.INFORMATION_CONTEXT, }); - noJobsNode.contextValue = Constants.INFORMATION_CONTEXT; - noJobsNode.iconPath = undefined; - noJobsNode.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; - return [noJobsNode]; + return (this.children = [noJobsNode]); } jobs.forEach((job) => { let nodeTitle: string; @@ -371,10 +357,10 @@ export class ZoweJobNode extends ZoweTreeNode implements IZoweJobTreeNode { return this._searchId; } - private async getJobs(owner: string, prefix: string, searchId: string, status: string): Promise { + private async getJobs(owner: string, prefix: string, searchId: string, status: string): Promise { ZoweLogger.trace("ZoweJobNode.getJobs called."); - let jobsInternal: zosjobs.IJob[] = []; const cachedProfile = Profiles.getInstance().loadNamedProfile(this.getProfileName()); + let jobsInternal: zosjobs.IJob[] = []; try { if (this.searchId.length > 0) { jobsInternal.push(await ZoweExplorerApiRegister.getJesApi(cachedProfile).getJob(searchId)); @@ -410,12 +396,29 @@ export class ZoweJobNode extends ZoweTreeNode implements IZoweJobTreeNode { }, []); } } catch (error) { - ZoweLogger.trace("Error getting jobs from Rest API."); - await AuthUtils.errorHandling(error, cachedProfile.name, vscode.l10n.t("Retrieving response from zowe.GetJobs")); - AuthUtils.syncSessionNode((profile) => ZoweExplorerApiRegister.getJesApi(profile), this.getSessionNode()); + const updated = await AuthUtils.errorHandling(error, this.getProfileName(), vscode.l10n.t("Retrieving response from JES list API")); + AuthUtils.syncSessionNode((profile) => ZoweExplorerApiRegister.getJesApi(profile), this.getSessionNode(), updated && this); + return; } return jobsInternal; } + + private async getSpoolFiles(job: zosjobs.IJob = this.job): Promise { + ZoweLogger.trace("ZoweJobNode.getSpoolFiles called."); + const cachedProfile = Profiles.getInstance().loadNamedProfile(this.getProfileName()); + let spools: zosjobs.IJobFile[] = []; + try { + spools = (await ZoweExplorerApiRegister.getJesApi(cachedProfile).getSpoolFiles(job.jobname, job.jobid)) ?? []; + // filter out all the objects which do not seem to be correct Job File Document types + // see an issue #845 for the details + spools = spools.filter((item) => !(item.id === undefined && item.ddname === undefined && item.stepname === undefined)); + } catch (error) { + const updated = await AuthUtils.errorHandling(error, this.getProfileName(), vscode.l10n.t("Retrieving response from JES list API")); + AuthUtils.syncSessionNode((profile) => ZoweExplorerApiRegister.getJesApi(profile), this.getSessionNode(), updated && this); + return; + } + return spools; + } } export class ZoweSpoolNode extends ZoweJobNode { diff --git a/packages/zowe-explorer/src/trees/shared/SharedInit.ts b/packages/zowe-explorer/src/trees/shared/SharedInit.ts index b45dd82a61..daefdba139 100644 --- a/packages/zowe-explorer/src/trees/shared/SharedInit.ts +++ b/packages/zowe-explorer/src/trees/shared/SharedInit.ts @@ -48,6 +48,8 @@ import { CertificateWizard } from "../../utils/CertificateWizard"; import { ZosConsoleViewProvider } from "../../zosconsole/ZosConsolePanel"; export class SharedInit { + private static originalEmitZoweEvent: typeof imperative.EventProcessor.prototype.emitEvent; + public static registerCommonCommands(context: vscode.ExtensionContext, providers: Definitions.IZoweProviders): void { ZoweLogger.trace("shared.init.registerCommonCommands called."); @@ -284,6 +286,24 @@ export class SharedInit { } } + public static emitZoweEventHook(this: void, processor: imperative.EventProcessor, eventName: string): void { + if (eventName === imperative.ZoweUserEvents.ON_VAULT_CHANGED) { + Constants.IGNORE_VAULT_CHANGE = true; + } + SharedInit.originalEmitZoweEvent.call(processor, eventName); + } + + public static async onVaultChanged(this: void): Promise { + if (Constants.IGNORE_VAULT_CHANGE) { + Constants.IGNORE_VAULT_CHANGE = false; + return; + } + ZoweLogger.info(vscode.l10n.t("Changes in the credential vault detected, refreshing Zowe Explorer.")); + await ProfilesUtils.readConfigFromDisk(); + await SharedActions.refreshAll(); + ZoweExplorerApiRegister.getInstance().onVaultUpdateEmitter.fire(Validation.EventType.UPDATE); + } + public static watchConfigProfile(context: vscode.ExtensionContext): void { ZoweLogger.trace("shared.init.watchConfigProfile called."); const watchers: vscode.FileSystemWatcher[] = []; @@ -311,23 +331,28 @@ export class SharedInit { }); watcher.onDidChange(async (uri: vscode.Uri) => { ZoweLogger.info(vscode.l10n.t("Team config file updated.")); - const newProfileContents = await vscode.workspace.fs.readFile(uri); - if (newProfileContents.toString() === Constants.SAVED_PROFILE_CONTENTS.toString()) { + const newProfileContents = Buffer.from(await vscode.workspace.fs.readFile(uri)); + if (Constants.SAVED_PROFILE_CONTENTS.get(uri.fsPath)?.equals(newProfileContents)) { return; } - Constants.SAVED_PROFILE_CONTENTS = newProfileContents; + Constants.SAVED_PROFILE_CONTENTS.set(uri.fsPath, newProfileContents); void SharedActions.refreshAll(); ZoweExplorerApiRegister.getInstance().onProfilesUpdateEmitter.fire(Validation.EventType.UPDATE); }); }); try { - const zoweWatcher = imperative.EventOperator.getWatcher().subscribeUser(imperative.ZoweUserEvents.ON_VAULT_CHANGED, async () => { - ZoweLogger.info(vscode.l10n.t("Changes in the credential vault detected, refreshing Zowe Explorer.")); - await ProfilesUtils.readConfigFromDisk(); - await SharedActions.refreshAll(); - ZoweExplorerApiRegister.getInstance().onVaultUpdateEmitter.fire(Validation.EventType.UPDATE); - }); + // Workaround to skip ON_VAULT_CHANGED events triggered by ZE and not by external app + // TODO: Remove this hack once https://github.com/zowe/zowe-cli/issues/2279 is implemented + SharedInit.originalEmitZoweEvent = (imperative.EventProcessor.prototype as any).emitZoweEvent; + (imperative.EventProcessor.prototype as any).emitZoweEvent = function (eventName: string): void { + SharedInit.emitZoweEventHook(this, eventName); + }; + + const zoweWatcher = imperative.EventOperator.getWatcher().subscribeUser( + imperative.ZoweUserEvents.ON_VAULT_CHANGED, + SharedInit.onVaultChanged + ); context.subscriptions.push(new vscode.Disposable(zoweWatcher.close.bind(zoweWatcher))); } catch (err) { Gui.errorMessage("Unable to watch for vault changes. " + JSON.stringify(err)); @@ -354,11 +379,11 @@ export class SharedInit { const theTreeView = theProvider.getTreeView(); context.subscriptions.push(theTreeView); context.subscriptions.push(vscode.workspace.onDidChangeWorkspaceFolders(async (e) => SharedInit.setupRemoteWorkspaceFolders(e))); - theTreeView.onDidCollapseElement(async (e) => { - await theProvider.flipState(e.element, false); + theTreeView.onDidCollapseElement((e) => { + theProvider.flipState(e.element, false); }); - theTreeView.onDidExpandElement(async (e) => { - await theProvider.flipState(e.element, true); + theTreeView.onDidExpandElement((e) => { + theProvider.flipState(e.element, true); }); } diff --git a/packages/zowe-explorer/src/trees/uss/USSActions.ts b/packages/zowe-explorer/src/trees/uss/USSActions.ts index ef365dac02..0f89d1be0c 100644 --- a/packages/zowe-explorer/src/trees/uss/USSActions.ts +++ b/packages/zowe-explorer/src/trees/uss/USSActions.ts @@ -13,13 +13,12 @@ import * as vscode from "vscode"; import * as fs from "fs"; import * as path from "path"; import * as zosfiles from "@zowe/zos-files-for-zowe-sdk"; -import { Gui, imperative, Validation, IZoweUSSTreeNode, Types } from "@zowe/zowe-explorer-api"; +import { Gui, imperative, IZoweUSSTreeNode, Types } from "@zowe/zowe-explorer-api"; import { isBinaryFileSync } from "isbinaryfile"; import { USSAttributeView } from "./USSAttributeView"; import { USSFileStructure } from "./USSFileStructure"; import { ZoweUSSNode } from "./ZoweUSSNode"; import { Constants } from "../../configuration/Constants"; -import { Profiles } from "../../configuration/Profiles"; import { ZoweExplorerApiRegister } from "../../extending/ZoweExplorerApiRegister"; import { LocalFileManagement } from "../../management/LocalFileManagement"; import { ZoweLogger } from "../../tools/ZoweLogger"; @@ -36,16 +35,12 @@ export class USSActions { * @param {ussTree} ussFileProvider - Current ussTree used to populate the TreeView * @returns {Promise} */ - public static async createUSSNode( - node: IZoweUSSTreeNode, - ussFileProvider: Types.IZoweUSSTreeType, - nodeType: string, - isTopLevel?: boolean - ): Promise { + public static async createUSSNode(node: IZoweUSSTreeNode, ussFileProvider: Types.IZoweUSSTreeType, nodeType: string): Promise { ZoweLogger.trace("uss.actions.createUSSNode called."); await ussFileProvider.checkCurrentProfile(node); let filePath = ""; - if (SharedContext.isSession(node)) { + const isTopLevel = SharedContext.isSession(node); + if (isTopLevel && node.fullPath?.length === 0) { const filePathOptions: vscode.InputBoxOptions = { placeHolder: vscode.l10n.t({ message: "{0} location", @@ -60,17 +55,25 @@ export class USSActions { value: node.tooltip as string, }; filePath = await Gui.showInputBox(filePathOptions); + node.fullPath = filePath; } else { filePath = node.fullPath; } + + if (filePath == null || filePath.length === 0) { + return; + } + const nameOptions: vscode.InputBoxOptions = { placeHolder: vscode.l10n.t("Name of file or directory"), }; const name = await Gui.showInputBox(nameOptions); if (name && filePath) { try { - filePath = `${filePath}/${name}`; - const uri = node.resourceUri.with({ path: path.posix.join(node.resourceUri.path, name) }); + filePath = path.posix.join(filePath, name); + const uri = node.resourceUri.with({ + path: isTopLevel ? path.posix.join(node.resourceUri.path, filePath) : path.posix.join(node.resourceUri.path, name), + }); await ZoweExplorerApiRegister.getUssApi(node.getProfile()).create(filePath, nodeType); if (nodeType === "file") { await vscode.workspace.fs.writeFile(uri, new Uint8Array()); @@ -82,6 +85,7 @@ export class USSActions { } else { ussFileProvider.refreshElement(node); } + const newNode = await node.getChildren().then((children) => children.find((child) => child.label === name) as ZoweUSSNode); await ussFileProvider.getTreeView().reveal(node, { select: true, focus: true }); ussFileProvider.getTreeView().reveal(newNode, { select: true, focus: true }); @@ -117,24 +121,6 @@ export class USSActions { } } - public static async createUSSNodeDialog(node: IZoweUSSTreeNode, ussFileProvider: Types.IZoweUSSTreeType): Promise { - ZoweLogger.trace("uss.actions.createUSSNodeDialog called."); - await ussFileProvider.checkCurrentProfile(node); - if ( - Profiles.getInstance().validProfile === Validation.ValidationType.VALID || - Profiles.getInstance().validProfile === Validation.ValidationType.UNVERIFIED - ) { - const quickPickOptions: vscode.QuickPickOptions = { - placeHolder: `What would you like to create at ${node.fullPath}?`, - ignoreFocusOut: true, - canPickMany: false, - }; - const type = await Gui.showQuickPick([Constants.USS_DIR_CONTEXT, "File"], quickPickOptions); - const isTopLevel = true; - return USSActions.createUSSNode(node, ussFileProvider, type, isTopLevel); - } - } - /** * Marks file as deleted from disk * diff --git a/packages/zowe-explorer/src/trees/uss/USSInit.ts b/packages/zowe-explorer/src/trees/uss/USSInit.ts index 638c98a1b9..91bba48005 100644 --- a/packages/zowe-explorer/src/trees/uss/USSInit.ts +++ b/packages/zowe-explorer/src/trees/uss/USSInit.ts @@ -27,7 +27,7 @@ export class USSInit { * @export */ public static async createUSSTree(log: imperative.Logger): Promise { - ZoweLogger.trace("uss.USSTree.createUSSTree called."); + ZoweLogger.trace("USSInit.createUSSTree called."); const tree = new USSTree(); await tree.initializeFavorites(log); await tree.addSession(); @@ -35,7 +35,7 @@ export class USSInit { } public static async initUSSProvider(context: vscode.ExtensionContext): Promise { - ZoweLogger.trace("init.initUSSProvider called."); + ZoweLogger.trace("USSInit.initUSSProvider called."); context.subscriptions.push(vscode.workspace.registerFileSystemProvider(ZoweScheme.USS, UssFSProvider.instance, { isCaseSensitive: true })); const ussFileProvider: USSTree = await USSInit.createUSSTree(ZoweLogger.log); diff --git a/packages/zowe-explorer/src/trees/uss/USSTree.ts b/packages/zowe-explorer/src/trees/uss/USSTree.ts index 3cae74470b..f0098ac766 100644 --- a/packages/zowe-explorer/src/trees/uss/USSTree.ts +++ b/packages/zowe-explorer/src/trees/uss/USSTree.ts @@ -495,8 +495,8 @@ export class USSTree extends ZoweTreeProvider implements Types collapsibleState: vscode.TreeItemCollapsibleState.Collapsed, session, profile, + contextOverride: Constants.USS_SESSION_CONTEXT, }); - node.contextValue = Constants.USS_SESSION_CONTEXT; await this.refreshHomeProfileContext(node); const icon = IconGenerator.getIconByNode(node); if (icon) { @@ -676,9 +676,7 @@ export class USSTree extends ZoweTreeProvider implements Types */ public async getAllLoadedItems(): Promise { ZoweLogger.trace("USSTree.getAllLoadedItems called."); - if (this.log) { - ZoweLogger.debug(vscode.l10n.t("Prompting the user to choose a member from the filtered list")); - } + ZoweLogger.debug(vscode.l10n.t("Prompting the user to choose a member from the filtered list")); const loadedNodes: IZoweUSSTreeNode[] = []; const sessions = await this.getChildren(); @@ -691,7 +689,7 @@ export class USSTree extends ZoweTreeProvider implements Types const children = nodeToCheck.children; if (children.length !== 0) { for (const child of children) { - await checkForChildren(child as IZoweUSSTreeNode); + await checkForChildren(child); } } loadedNodes.push(nodeToCheck); @@ -715,13 +713,11 @@ export class USSTree extends ZoweTreeProvider implements Types */ public async filterPrompt(node: IZoweUSSTreeNode): Promise { ZoweLogger.trace("USSTree.filterPrompt called."); - if (this.log) { - ZoweLogger.debug(vscode.l10n.t("Prompting the user for a USS path")); - } await this.checkCurrentProfile(node); if (Profiles.getInstance().validProfile !== Validation.ValidationType.INVALID) { let remotepath: string; if (SharedContext.isSessionNotFav(node)) { + ZoweLogger.debug(vscode.l10n.t("Prompting the user for a USS path")); if (this.mHistory.getSearchHistory().length > 0) { const createPick = new FilterDescriptor(USSTree.defaultDialogText); const items: vscode.QuickPickItem[] = this.mHistory.getSearchHistory().map((element) => new FilterItem({ text: element })); @@ -982,9 +978,8 @@ export class USSTree extends ZoweTreeProvider implements Types collapsibleState: vscode.TreeItemCollapsibleState.None, parentNode, parentPath: parentNode.fullPath, + contextOverride: Constants.INFORMATION_CONTEXT, }); - infoNode.contextValue = Constants.INFORMATION_CONTEXT; - infoNode.iconPath = undefined; return [infoNode]; } } catch (error) { @@ -1016,13 +1011,13 @@ export class USSTree extends ZoweTreeProvider implements Types for (const favorite of favsForProfile) { // If profile and session already exists for favorite node, add to updatedFavsForProfile and go to next array item if (favorite.getProfile() && favorite.getSession()) { - updatedFavsForProfile.push(favorite as IZoweUSSTreeNode); + updatedFavsForProfile.push(favorite); continue; } // If no profile/session for favorite node yet, then add session and profile to favorite node: favorite.setProfileToChoice(profile); favorite.setSessionToChoice(session); - updatedFavsForProfile.push(favorite as IZoweUSSTreeNode); + updatedFavsForProfile.push(favorite); } // This updates the profile node's children in the this.mFavorites array, as well. return updatedFavsForProfile; @@ -1123,11 +1118,11 @@ export class USSTree extends ZoweTreeProvider implements Types } const isFullPathChild: boolean = SharedUtils.checkIfChildPath(node.fullPath, fullPath); if (isFullPathChild) { - return this.findMatchInLoadedChildren(node as IZoweUSSTreeNode, fullPath); + return this.findMatchInLoadedChildren(node, fullPath); } } } - return match as IZoweUSSTreeNode; + return match; } public async openWithEncoding(node: IZoweUSSTreeNode, encoding?: ZosEncoding): Promise { diff --git a/packages/zowe-explorer/src/trees/uss/ZoweUSSNode.ts b/packages/zowe-explorer/src/trees/uss/ZoweUSSNode.ts index 5931fc94cc..f7f7951131 100644 --- a/packages/zowe-explorer/src/trees/uss/ZoweUSSNode.ts +++ b/packages/zowe-explorer/src/trees/uss/ZoweUSSNode.ts @@ -112,6 +112,8 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { }); if (isSession) { UssFSProvider.instance.createDirectory(this.resourceUri); + } else if (this.contextValue === Constants.INFORMATION_CONTEXT) { + this.command = { command: "zowe.placeholderCommand", title: "Placeholder" }; } else if (this.collapsibleState === vscode.TreeItemCollapsibleState.None) { this.command = { command: "vscode.open", title: "", arguments: [this.resourceUri] }; } @@ -177,7 +179,7 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { * @returns {Promise} */ public async getChildren(): Promise { - ZoweLogger.trace("ZoweUSSNode.getChildren called."); + ZoweLogger.trace(`ZoweUSSNode.getChildren called for ${this.label as string}.`); if ((!this.fullPath && SharedContext.isSession(this)) || SharedContext.isDocument(this)) { const placeholder = new ZoweUSSNode({ label: vscode.l10n.t("Use the search button to list USS files"), @@ -185,11 +187,7 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { parentNode: this, contextOverride: Constants.INFORMATION_CONTEXT, }); - placeholder.command = { - command: "zowe.placeholderCommand", - title: "Placeholder", - }; - return [placeholder]; + return (this.children = [placeholder]); } if (!this.dirty) { @@ -205,35 +203,10 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { } // Get the list of files/folders at the given USS path and handle any errors - let response: zosfiles.IZosFilesResponse; - const sessNode = this.getSessionNode(); - let nodeProfile; - try { - const cachedProfile = Profiles.getInstance().loadNamedProfile(this.getProfileName()); - if (!ZoweExplorerApiRegister.getUssApi(cachedProfile).getSession(cachedProfile)) { - throw new imperative.ImperativeError({ - msg: vscode.l10n.t("Profile auth error"), - additionalDetails: vscode.l10n.t("Profile is not authenticated, please log in to continue"), - errorCode: `${imperative.RestConstants.HTTP_STATUS_401 as number}`, - }); - } - nodeProfile = cachedProfile; - if (SharedContext.isSession(this)) { - response = await UssFSProvider.instance.listFiles( - nodeProfile, - SharedContext.isFavorite(this) - ? this.resourceUri - : this.resourceUri.with({ - path: path.posix.join(this.resourceUri.path, this.fullPath), - }) - ); - } else { - response = await UssFSProvider.instance.listFiles(nodeProfile, this.resourceUri); - } - } catch (err) { - await AuthUtils.errorHandling(err, this.label.toString(), vscode.l10n.t("Retrieving response from uss-file-list")); - AuthUtils.syncSessionNode((profile) => ZoweExplorerApiRegister.getUssApi(profile), sessNode); - return this.children; + const cachedProfile = Profiles.getInstance().loadNamedProfile(this.getProfileName()); + const response = await this.getUssFiles(cachedProfile); + if (!response.success) { + return []; } // If search path has changed, invalidate all children @@ -271,8 +244,8 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { collapsibleState: collapseState, parentNode: this, parentPath: this.fullPath, - profile: nodeProfile, - encoding: isDir ? undefined : await this.getEncodingInMap(`${this.fullPath}/${item.name as string}`), + profile: cachedProfile, + encoding: isDir ? undefined : this.getEncodingInMap(`${this.fullPath}/${item.name as string}`), }); if (isDir) { // Create an entry for the USS folder if it doesn't exist. @@ -684,4 +657,32 @@ export class ZoweUSSNode extends ZoweTreeNode implements IZoweUSSTreeNode { await AuthUtils.errorHandling(error, this.label.toString(), vscode.l10n.t("Error uploading files")); } } + + private async getUssFiles(profile: imperative.IProfileLoaded): Promise { + try { + if (!ZoweExplorerApiRegister.getUssApi(profile).getSession(profile)) { + throw new imperative.ImperativeError({ + msg: vscode.l10n.t("Profile auth error"), + additionalDetails: vscode.l10n.t("Profile is not authenticated, please log in to continue"), + errorCode: `${imperative.RestConstants.HTTP_STATUS_401 as number}`, + }); + } + if (SharedContext.isSession(this)) { + return await UssFSProvider.instance.listFiles( + profile, + SharedContext.isFavorite(this) + ? this.resourceUri + : this.resourceUri.with({ + path: path.posix.join(this.resourceUri.path, this.fullPath), + }) + ); + } else { + return await UssFSProvider.instance.listFiles(profile, this.resourceUri); + } + } catch (error) { + const updated = await AuthUtils.errorHandling(error, this.getProfileName(), vscode.l10n.t("Retrieving response from USS list API")); + AuthUtils.syncSessionNode((prof) => ZoweExplorerApiRegister.getUssApi(prof), this.getSessionNode(), updated && this); + return { success: false, commandResponse: null }; + } + } } diff --git a/packages/zowe-explorer/src/utils/AuthUtils.ts b/packages/zowe-explorer/src/utils/AuthUtils.ts index cbfcabbeb3..0f6fa561c4 100644 --- a/packages/zowe-explorer/src/utils/AuthUtils.ts +++ b/packages/zowe-explorer/src/utils/AuthUtils.ts @@ -14,6 +14,7 @@ import * as vscode from "vscode"; import { imperative, Gui, MainframeInteraction, IZoweTreeNode } from "@zowe/zowe-explorer-api"; import { Constants } from "../configuration/Constants"; import { ZoweLogger } from "../tools/ZoweLogger"; +import { SharedTreeProviders } from "../trees/shared/SharedTreeProviders"; export class AuthUtils { /************************************************************************************************************* @@ -22,7 +23,7 @@ export class AuthUtils { * @param {label} - additional information such as profile name, credentials, messageID etc * @param {moreInfo} - additional/customized error messages *************************************************************************************************************/ - public static async errorHandling(errorDetails: Error | string, label?: string, moreInfo?: string): Promise { + public static async errorHandling(errorDetails: Error | string, label?: string, moreInfo?: string): Promise { // Use util.inspect instead of JSON.stringify to handle circular references // eslint-disable-next-line @typescript-eslint/restrict-template-expressions ZoweLogger.error(`${errorDetails.toString()}\n` + util.inspect({ errorDetails, label, moreInfo }, { depth: null })); @@ -38,7 +39,7 @@ export class AuthUtils { if (prof.profName === label.trim()) { const filePath = prof.profLoc.osLoc[0]; await Constants.PROFILES_CACHE.openConfigFile(filePath); - return; + return false; } } } else if ( @@ -68,16 +69,16 @@ export class AuthUtils { if (tokenError.includes("Token is not valid or expired.") || isTokenAuth) { const message = vscode.l10n.t("Log in to Authentication Service"); - Gui.showMessage(errToken, { items: [message] }).then(async (selection) => { + const success = Gui.showMessage(errToken, { items: [message] }).then(async (selection) => { if (selection) { - await Constants.PROFILES_CACHE.ssoLogin(null, label); + return Constants.PROFILES_CACHE.ssoLogin(null, label); } }); - return; + return success; } } const checkCredsButton = vscode.l10n.t("Update Credentials"); - await Gui.errorMessage(errMsg, { + const creds = await Gui.errorMessage(errMsg, { items: [checkCredsButton], vsCodeOpts: { modal: true }, }).then(async (selection) => { @@ -85,13 +86,13 @@ export class AuthUtils { Gui.showMessage(vscode.l10n.t("Operation Cancelled")); return; } - await Constants.PROFILES_CACHE.promptCredentials(label.trim(), true); + return Constants.PROFILES_CACHE.promptCredentials(label.trim(), true); }); - return; + return creds != null ? true : false; } } if (errorDetails.toString().includes("Could not find profile")) { - return; + return false; } if (moreInfo === undefined) { moreInfo = errorDetails.toString().includes("Error") ? "" : "Error: "; @@ -100,6 +101,7 @@ export class AuthUtils { } // Try to keep message readable since VS Code doesn't support newlines in error messages Gui.errorMessage(moreInfo + errorDetails.toString().replace(/\n/g, " | ")); + return false; } /** @@ -110,7 +112,8 @@ export class AuthUtils { */ public static syncSessionNode( getCommonApi: (profile: imperative.IProfileLoaded) => MainframeInteraction.ICommon, - sessionNode: IZoweTreeNode + sessionNode: IZoweTreeNode, + nodeToRefresh?: IZoweTreeNode ): void { ZoweLogger.trace("ProfilesUtils.syncSessionNode called."); @@ -127,6 +130,10 @@ export class AuthUtils { sessionNode.setProfileToChoice(profile); const session = getCommonApi(profile).getSession(); sessionNode.setSessionToChoice(session); + if (nodeToRefresh) { + nodeToRefresh.dirty = true; + void nodeToRefresh.getChildren().then(() => SharedTreeProviders.getProviderForNode(nodeToRefresh).refreshElement(nodeToRefresh)); + } } /** diff --git a/packages/zowe-explorer/src/utils/ProfilesUtils.ts b/packages/zowe-explorer/src/utils/ProfilesUtils.ts index 857cedd08a..9e1a87b569 100644 --- a/packages/zowe-explorer/src/utils/ProfilesUtils.ts +++ b/packages/zowe-explorer/src/utils/ProfilesUtils.ts @@ -187,8 +187,13 @@ export class ProfilesUtils { const profileInfo = new imperative.ProfileInfo("zowe", { credMgrOverride: defaultCredentialManager, }); + + const workspacePath = ZoweVsCodeExtension.workspaceRoot?.uri.fsPath; // Trigger initialize() function of credential manager to throw an error early if failed to load - await profileInfo.readProfilesFromDisk(); + await profileInfo.readProfilesFromDisk({ + homeDir: FileManagement.getZoweDir(), + projectDir: workspacePath ? FileManagement.getFullPath(workspacePath) : undefined, + }); return profileInfo; } catch (err) { if (err instanceof imperative.ProfInfoErr && err.errorCode === imperative.ProfInfoErr.LOAD_CRED_MGR_FAILED) { @@ -332,7 +337,12 @@ export class ProfilesUtils { Gui.warningMessage(schemaWarning); ZoweLogger.warn(schemaWarning); } - Constants.CONFIG_PATH = rootPath ? rootPath : FileManagement.getZoweDir(); + Constants.SAVED_PROFILE_CONTENTS.clear(); + for (const layer of mProfileInfo.getTeamConfig().layers) { + if (layer.exists) { + Constants.SAVED_PROFILE_CONTENTS.set(vscode.Uri.file(layer.path).fsPath, fs.readFileSync(layer.path)); + } + } ZoweLogger.info(`Zowe Explorer is using the team configuration file "${mProfileInfo.getTeamConfig().configName}"`); const layers = mProfileInfo.getTeamConfig().layers || []; const layerSummary = layers.map( diff --git a/packages/zowe-explorer/tsconfig-tests.json b/packages/zowe-explorer/tsconfig-tests.json index 07603d6a68..2107c48345 100644 --- a/packages/zowe-explorer/tsconfig-tests.json +++ b/packages/zowe-explorer/tsconfig-tests.json @@ -10,8 +10,6 @@ "__tests__/__unit__", "__tests__/__integration__/bdd/step_definitions/**/*.ts", // Needed for integration tests to work: - "__tests__/__integration__/tdd", - "resources/testProfileData.example.ts", - "resources/testProfileData.ts" + "__tests__/__integration__/tdd" ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 14088b4779..c2ff641447 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -142,20 +142,20 @@ importers: specifier: ^0.0.35 version: 0.0.35 '@zowe/core-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/imperative@8.1.0) '@zowe/secrets-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0 + specifier: ^8.1.0 + version: 8.1.0 '@zowe/zos-files-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zos-jobs-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zosmf-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zowe-explorer-api': specifier: 3.1.0-SNAPSHOT version: link:../zowe-explorer-api @@ -251,32 +251,32 @@ importers: specifier: ^1.53.2 version: 1.89.0 '@zowe/core-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/imperative@8.1.0) '@zowe/imperative': - specifier: 8.0.0 - version: 8.0.0 + specifier: ^8.1.0 + version: 8.1.0 '@zowe/secrets-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0 + specifier: ^8.1.0 + version: 8.1.0 '@zowe/zos-console-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zos-files-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zos-jobs-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zos-tso-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zos-uss-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/imperative@8.1.0) '@zowe/zosmf-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) deep-object-diff: specifier: ^1.1.9 version: 1.1.9 @@ -300,14 +300,14 @@ importers: packages/zowe-explorer-ftp-extension: dependencies: '@zowe/zos-files-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zos-ftp-for-zowe-cli': - specifier: 3.0.0 - version: 3.0.0(@zowe/imperative@8.0.0) + specifier: ^3.0.0 + version: 3.0.0(@zowe/imperative@8.1.0) '@zowe/zos-jobs-for-zowe-sdk': - specifier: 8.0.0 - version: 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + specifier: ^8.1.1 + version: 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) '@zowe/zowe-explorer-api': specifier: 3.1.0-SNAPSHOT version: link:../zowe-explorer-api @@ -3569,19 +3569,19 @@ packages: requiresBuild: true dev: true - /@zowe/core-for-zowe-sdk@8.0.0(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-+e7INyHuucrQj/y02kDvOhhvtv6eGWnyWJgXhPxeNOyiCwTB6B1Fk6E6Go/s5/ql1dlaQSVjegrJpXwmXTepRA==} + /@zowe/core-for-zowe-sdk@8.1.1(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-O3lbFiCWe8tsf7eAWdbmDqyEIhHniPD7AOr0IixRcnyPVu5aNLSX91Xt11PA7Ka+nbEN1mdo/BYZcpQiIcUiDQ==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/imperative': ^8.0.0-next + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/imperative': 8.0.0 + '@zowe/imperative': 8.1.0 comment-json: 4.2.5 string-width: 4.2.3 dev: false - /@zowe/imperative@8.0.0: - resolution: {integrity: sha512-ek0OtcrNWDaVeP5kauQ5uY53fiLbEoqu3z9gzrVwRLZ+c62RE3OkRDOE+27nHndj+VYpg3Wx2LLp33DvQ3AA1Q==} + /@zowe/imperative@8.1.0: + resolution: {integrity: sha512-laKAPM5YWGD3s2Gc2y9BV/6QiENfg3hRbOBi+zEX8cDshAaZQ0Nd2Q1vN++6u211QvD50e/VVPwFusnJpqdczg==} engines: {node: '>=18.12.0'} dependencies: '@types/yargs': 17.0.33 @@ -3625,87 +3625,87 @@ packages: - supports-color dev: false - /@zowe/secrets-for-zowe-sdk@8.0.0: - resolution: {integrity: sha512-tqd9lK8aWSLypJC6fjob5uF4mwEn1hn9nmQ/OSnya4yL+2jYe/qV53tJUtoGDZEQMySlMM4VGqtMDMEaJ+azxw==} + /@zowe/secrets-for-zowe-sdk@8.1.0: + resolution: {integrity: sha512-XhwuLo+e3sMIUETHLmVpKvU0ydnYouWHDOHTVvaWfexlwzcuZy23D0EOOjWw/LsQ65rABXaOHOfATuyT0FvFww==} engines: {node: '>=14'} requiresBuild: true dev: false - /@zowe/zos-console-for-zowe-sdk@8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-rXfTOBEvvKdT2yVYO2NOEBOpRVif1pVH6NAPD6lZCzPdCxYD0izOeTWPOQbCxcJHC0/XYysoMV44ARnNz92r7A==} + /@zowe/zos-console-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-8rH3madm917KoBEMzyS2XLkzU7axQg5kvrQltjuF248pFEpPX4WkplHljaNOJ1RraZFdjp+6KdyEODWgeZpSmw==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/core-for-zowe-sdk': ^8.0.0-next - '@zowe/imperative': ^8.0.0-next + '@zowe/core-for-zowe-sdk': ^8.0.0 + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.0.0(@zowe/imperative@8.0.0) - '@zowe/imperative': 8.0.0 + '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) + '@zowe/imperative': 8.1.0 dev: false - /@zowe/zos-files-for-zowe-sdk@8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-brra18QQErOqdQ3JfFp6/sdk87kBRS36pESfW18HcG4VijWt3RI0cdcEiraqVJAEyLz27lpAsxcWfJfNwWYqdQ==} + /@zowe/zos-files-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-zna2Dj8u1jL20YzkIq2FVHoiJFFFTKnurjfRfGHcy9WErLOKdM97AXVpCEVjMboWbIbBDomjXvsa0gYw3soqdg==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/core-for-zowe-sdk': ^8.0.0-next - '@zowe/imperative': ^8.0.0-next + '@zowe/core-for-zowe-sdk': ^8.0.0 + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.0.0(@zowe/imperative@8.0.0) - '@zowe/imperative': 8.0.0 + '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) + '@zowe/imperative': 8.1.0 minimatch: 9.0.5 dev: false - /@zowe/zos-ftp-for-zowe-cli@3.0.0(@zowe/imperative@8.0.0): + /@zowe/zos-ftp-for-zowe-cli@3.0.0(@zowe/imperative@8.1.0): resolution: {integrity: sha512-lNt4t4VJMvnnjQXXusw5N5w5nVysbKZVSD+c7wvj/RJt6ceSV2aMH7QPeiyvTE0FEFErCkjCRl2AxeVtBkn82Q==} peerDependencies: '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/imperative': 8.0.0 + '@zowe/imperative': 8.1.0 zos-node-accessor: 2.0.11 dev: false - /@zowe/zos-jobs-for-zowe-sdk@8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-/1qnGZYIb544LkAjrYbfIrBZiHqcsCwJjLZX962B90rq2EZnbqiT5zy45nKtZvPeMp1oY0ZJ1HNEOexkXOIaOw==} + /@zowe/zos-jobs-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-ozdupvtmcuzq7P2CYueLGAfRUuxjL/vXAH9h11bLxiSO62LoqW87vDWJXwHQq0Fkey0TuU5Vi3Ayf8G0pNtuSQ==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/core-for-zowe-sdk': ^8.0.0-next - '@zowe/imperative': ^8.0.0-next + '@zowe/core-for-zowe-sdk': ^8.0.0 + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.0.0(@zowe/imperative@8.0.0) - '@zowe/imperative': 8.0.0 - '@zowe/zos-files-for-zowe-sdk': 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) + '@zowe/imperative': 8.1.0 + '@zowe/zos-files-for-zowe-sdk': 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) dev: false - /@zowe/zos-tso-for-zowe-sdk@8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-zwtWDCbe4oPGO84xRaGBVWR5JC0KW5bWGJmz9z5574NyetcDdnKg5JgJ8CyWkdc6bLwMpevcRU2o34FVefksMg==} + /@zowe/zos-tso-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-JVK/AkzdZfxaLsVpNm0x2CsTBJ6OaeFQEwJzMUtENM53t6IauDBKq2FfWe4ivxP2Hd/dyieRiSIS+Hw+KEN4Og==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/core-for-zowe-sdk': ^8.0.0-next - '@zowe/imperative': ^8.0.0-next + '@zowe/core-for-zowe-sdk': ^8.0.0 + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.0.0(@zowe/imperative@8.0.0) - '@zowe/imperative': 8.0.0 - '@zowe/zosmf-for-zowe-sdk': 8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0) + '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) + '@zowe/imperative': 8.1.0 + '@zowe/zosmf-for-zowe-sdk': 8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0) dev: false - /@zowe/zos-uss-for-zowe-sdk@8.0.0(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-D5wbYVLVINRGAd1Q88udHJy0GxAiQETH2V/jHmQ6YAs7dXbI97CZ8ZNOtXimktEp0t+IS5mw+4tFr4nnae2H5Q==} + /@zowe/zos-uss-for-zowe-sdk@8.1.1(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-AvL7DNR/zdEI+K5kwWynnN20E7No+UzZMMvkpTEPjC6gWqlF7w9hq0kZ6EIeyml+QtwAEcsoWglhlQWQBMvr3g==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/imperative': ^8.0.0-next + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/imperative': 8.0.0 + '@zowe/imperative': 8.1.0 ssh2: 1.15.0 dev: false - /@zowe/zosmf-for-zowe-sdk@8.0.0(@zowe/core-for-zowe-sdk@8.0.0)(@zowe/imperative@8.0.0): - resolution: {integrity: sha512-Io3EtGepe5CXnmB0gNXeS3+E/rv6b4CtrA1Mq9EUAvvTwl8nrlE2Vig3dW1HHHD3fScgBh7+XIOVDMWd+bn3rw==} + /@zowe/zosmf-for-zowe-sdk@8.1.1(@zowe/core-for-zowe-sdk@8.1.1)(@zowe/imperative@8.1.0): + resolution: {integrity: sha512-bSY2RKo3aAjpm7Ec//gayjGv0pGiB4wfi/SztXa5gjB2sIgJcJDTxgResCWBhM8nDVqXw+rpvdaSMOptyAmlgQ==} engines: {node: '>=18.12.0'} peerDependencies: - '@zowe/core-for-zowe-sdk': ^8.0.0-next - '@zowe/imperative': ^8.0.0-next + '@zowe/core-for-zowe-sdk': ^8.0.0 + '@zowe/imperative': ^8.0.0 dependencies: - '@zowe/core-for-zowe-sdk': 8.0.0(@zowe/imperative@8.0.0) - '@zowe/imperative': 8.0.0 + '@zowe/core-for-zowe-sdk': 8.1.1(@zowe/imperative@8.1.0) + '@zowe/imperative': 8.1.0 dev: false /abbrev@1.1.1: @@ -4836,8 +4836,8 @@ packages: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} dev: true - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + /cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} engines: {node: '>= 0.6'} dev: true @@ -6204,7 +6204,7 @@ packages: fast-content-type-parse: 1.1.0 fast-json-stringify: 5.16.0 find-my-way: 8.2.2 - light-my-request: 5.13.0 + light-my-request: 5.14.0 pino: 9.2.0 process-warning: 3.0.0 proxy-addr: 2.0.7 @@ -8357,10 +8357,10 @@ packages: immediate: 3.0.6 dev: true - /light-my-request@5.13.0: - resolution: {integrity: sha512-9IjUN9ZyCS9pTG+KqTDEQo68Sui2lHsYBrfMyVUTTZ3XhH8PMZq7xO94Kr+eP9dhi/kcKsx4N41p2IXEBil1pQ==} + /light-my-request@5.14.0: + resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} dependencies: - cookie: 0.6.0 + cookie: 0.7.2 process-warning: 3.0.0 set-cookie-parser: 2.6.0 dev: true diff --git a/samples/README.md b/samples/README.md deleted file mode 100644 index 19ec209af2..0000000000 --- a/samples/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Zowe Explorer Sample Packages - -This folder contains sample packages for reference during development, for both Zowe Explorer contributors and extender developers. - ---- - -## menu-item-sample - -Demonstrates adding a new command to the context menu shown when a tree item is right-clicked in Zowe Explorer. - ---- - -## tree-view-sample - -Demonstrates adding a new tree view to Zowe Explorer alongside data sets, USS, and jobs. - ---- - -## uss-profile-sample - -Demonstrates adding support for a new profile type to the USS tree in Zowe Explorer. - ---- - -## vue-webview-sample - -Demonstrates the use of the `WebView` class from Zowe Explorer API to create a webview panel, powered by the Vite bundler and Vue JavaScript framework. diff --git a/samples/menu-item-sample/.eslintrc.js b/samples/menu-item-sample/.eslintrc.js deleted file mode 100644 index 5e0416f422..0000000000 --- a/samples/menu-item-sample/.eslintrc.js +++ /dev/null @@ -1,15 +0,0 @@ -/**@type {import('eslint').Linter.Config} */ -// eslint-disable-next-line no-undef -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - plugins: ["@typescript-eslint"], - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - rules: { - semi: [2, "always"], - "@typescript-eslint/no-unused-vars": 0, - "@typescript-eslint/no-explicit-any": 0, - "@typescript-eslint/explicit-module-boundary-types": 0, - "@typescript-eslint/no-non-null-assertion": 0, - }, -}; diff --git a/samples/menu-item-sample/.gitignore b/samples/menu-item-sample/.gitignore deleted file mode 100644 index 5fe00fea85..0000000000 --- a/samples/menu-item-sample/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -out -node_modules -.vscode-test/ -*.vsix diff --git a/samples/menu-item-sample/.vscode/launch.json b/samples/menu-item-sample/.vscode/launch.json deleted file mode 100644 index e3dea5af1e..0000000000 --- a/samples/menu-item-sample/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// Use IntelliSense to learn about possible attributes. -// Hover to view descriptions of existing attributes. -// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceFolder}"], - "outFiles": ["${workspaceFolder}/out/**/*.js"], - "preLaunchTask": "npm: watch" - } - ] -} diff --git a/samples/menu-item-sample/.vscode/tasks.json b/samples/menu-item-sample/.vscode/tasks.json deleted file mode 100644 index 078ff7e01e..0000000000 --- a/samples/menu-item-sample/.vscode/tasks.json +++ /dev/null @@ -1,20 +0,0 @@ -// See https://go.microsoft.com/fwlink/?LinkId=733558 -// for the documentation about the tasks.json format -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} diff --git a/samples/menu-item-sample/README.md b/samples/menu-item-sample/README.md deleted file mode 100644 index dc7d8c4153..0000000000 --- a/samples/menu-item-sample/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Menu Item Sample - -Demonstrates adding a new command to the context menu shown when a tree item is right-clicked in Zowe Explorer. - -The `contributes` section of "package.json" defines a menu item named "Show Node Context" for all tree views that have an ID starting with `zowe.`. - -In "extension.ts" a command is registered which runs when the menu item is clicked and displays the associated [`TreeItem.contextValue`](https://code.visualstudio.com/api/references/vscode-api#TreeItem). - -## Running the sample - -- Open this sample in VS Code -- `pnpm i` -- `pnpm run compile` -- `F5` to start debugging diff --git a/samples/menu-item-sample/package.json b/samples/menu-item-sample/package.json deleted file mode 100644 index f4c733b453..0000000000 --- a/samples/menu-item-sample/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "menu-item-sample", - "displayName": "menu-item-sample", - "description": "Menu item sample for Zowe Explorer", - "version": "0.0.1", - "publisher": "Zowe", - "repository": "https://github.com/zowe/zowe-explorer-vscode/samples/menu-item-sample", - "engines": { - "vscode": "^1.79.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "menu-item-sample.showNodeContext", - "title": "Show Node Context" - } - ], - "menus": { - "commandPalette": [ - { - "command": "menu-item-sample.showNodeContext", - "when": "never" - } - ], - "view/item/context": [ - { - "when": "view =~ /^zowe\\./", - "command": "menu-item-sample.showNodeContext", - "group": "100_zowe_menuItemSample@0" - } - ] - } - }, - "extensionDependencies": [ - "Zowe.vscode-extension-for-zowe" - ], - "scripts": { - "vscode:prepublish": "pnpm run compile", - "compile": "tsc -p ./", - "lint": "eslint \"src/**/*.ts\"", - "watch": "tsc -watch -p ./" - }, - "dependencies": { - "@zowe/zowe-explorer-api": "file:../../packages/zowe-explorer-api" - }, - "devDependencies": { - "@types/node": "^18.19.14", - "@types/vscode": "^1.53.2", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", - "eslint": "^8.26.0", - "typescript": "^5.1.3" - } -} diff --git a/samples/menu-item-sample/src/extension.ts b/samples/menu-item-sample/src/extension.ts deleted file mode 100644 index 795622fd1e..0000000000 --- a/samples/menu-item-sample/src/extension.ts +++ /dev/null @@ -1,23 +0,0 @@ -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -import * as vscode from "vscode"; -import { IZoweTreeNode } from "@zowe/zowe-explorer-api"; - -// This method is called when your extension is activated -// Your extension is activated the very first time the command is executed -export function activate(context: vscode.ExtensionContext) { - // Use the console to output diagnostic information (console.log) and errors (console.error) - // This line of code will only be executed once when your extension is activated - console.log('Congratulations, your extension "menu-item-sample" is now active!'); - - // The command has been defined in the package.json file - // Now provide the implementation of the command with registerCommand - // The commandId parameter must match the command field in package.json - const disposable = vscode.commands.registerCommand("menu-item-sample.showNodeContext", (node: IZoweTreeNode) => { - // The code you place here will be executed every time your command is executed - // Display a message box to the user - vscode.window.showInformationMessage(node.contextValue as string); - }); - - context.subscriptions.push(disposable); -} diff --git a/samples/menu-item-sample/tsconfig.json b/samples/menu-item-sample/tsconfig.json deleted file mode 100644 index 52cbd382ae..0000000000 --- a/samples/menu-item-sample/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es2020", - "lib": ["es2020"], - "outDir": "out", - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "rootDir": "src" - }, - "exclude": ["node_modules", ".vscode-test"] -} diff --git a/samples/tree-view-sample/.eslintrc.js b/samples/tree-view-sample/.eslintrc.js deleted file mode 100644 index 5e0416f422..0000000000 --- a/samples/tree-view-sample/.eslintrc.js +++ /dev/null @@ -1,15 +0,0 @@ -/**@type {import('eslint').Linter.Config} */ -// eslint-disable-next-line no-undef -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - plugins: ["@typescript-eslint"], - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - rules: { - semi: [2, "always"], - "@typescript-eslint/no-unused-vars": 0, - "@typescript-eslint/no-explicit-any": 0, - "@typescript-eslint/explicit-module-boundary-types": 0, - "@typescript-eslint/no-non-null-assertion": 0, - }, -}; diff --git a/samples/tree-view-sample/.gitignore b/samples/tree-view-sample/.gitignore deleted file mode 100644 index 5fe00fea85..0000000000 --- a/samples/tree-view-sample/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -out -node_modules -.vscode-test/ -*.vsix diff --git a/samples/tree-view-sample/.vscode/launch.json b/samples/tree-view-sample/.vscode/launch.json deleted file mode 100644 index e3dea5af1e..0000000000 --- a/samples/tree-view-sample/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// Use IntelliSense to learn about possible attributes. -// Hover to view descriptions of existing attributes. -// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceFolder}"], - "outFiles": ["${workspaceFolder}/out/**/*.js"], - "preLaunchTask": "npm: watch" - } - ] -} diff --git a/samples/tree-view-sample/.vscode/tasks.json b/samples/tree-view-sample/.vscode/tasks.json deleted file mode 100644 index 078ff7e01e..0000000000 --- a/samples/tree-view-sample/.vscode/tasks.json +++ /dev/null @@ -1,20 +0,0 @@ -// See https://go.microsoft.com/fwlink/?LinkId=733558 -// for the documentation about the tasks.json format -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} diff --git a/samples/tree-view-sample/README.md b/samples/tree-view-sample/README.md deleted file mode 100644 index a40beba01a..0000000000 --- a/samples/tree-view-sample/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Tree View Sample - -Demonstrates adding a new tree view to Zowe Explorer alongside data sets, USS, and jobs. - -The `contributes` section of "package.json" defines a tree view named "Profiles" that will show inside the Zowe Explorer sidebar panel. - -In "extension.ts" the tree view is configured to use [`ProfilesTreeProvider`](/samples/tree-view-sample/src/ProfilesTreeProvider.ts) as a data provider which retrieves a list of available Zowe profiles. - -## Running the sample - -- Open this sample in VS Code -- `pnpm i` -- `pnpm run compile` -- `F5` to start debugging diff --git a/samples/tree-view-sample/package.json b/samples/tree-view-sample/package.json deleted file mode 100644 index 70e094fdbf..0000000000 --- a/samples/tree-view-sample/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "tree-view-sample", - "displayName": "tree-view-sample", - "description": "Tree view sample for Zowe Explorer", - "version": "0.0.1", - "publisher": "Zowe", - "repository": "https://github.com/zowe/zowe-explorer-vscode/samples/tree-view-sample", - "engines": { - "vscode": "^1.79.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "tree-view-sample.refresh", - "title": "Refresh View", - "icon": "$(refresh)" - } - ], - "menus": { - "view/title": [ - { - "command": "tree-view-sample.refresh", - "when": "view == tree-view-sample.profiles", - "group": "navigation" - } - ] - }, - "views": { - "zowe": [ - { - "id": "tree-view-sample.profiles", - "name": "profiles" - } - ] - } - }, - "extensionDependencies": [ - "Zowe.vscode-extension-for-zowe" - ], - "scripts": { - "vscode:prepublish": "pnpm run compile", - "compile": "tsc -p ./", - "lint": "eslint \"src/**/*.ts\"", - "watch": "tsc -watch -p ./" - }, - "dependencies": { - "@zowe/zowe-explorer-api": "file:../../packages/zowe-explorer-api" - }, - "devDependencies": { - "@types/node": "^18.19.14", - "@types/vscode": "^1.53.2", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", - "eslint": "^8.26.0", - "typescript": "^5.1.3" - } -} diff --git a/samples/tree-view-sample/src/ProfilesTreeProvider.ts b/samples/tree-view-sample/src/ProfilesTreeProvider.ts deleted file mode 100644 index b1241fb3f0..0000000000 --- a/samples/tree-view-sample/src/ProfilesTreeProvider.ts +++ /dev/null @@ -1,60 +0,0 @@ -import * as vscode from "vscode"; -import { ProfilesCache, imperative } from "@zowe/zowe-explorer-api"; - -class ProfilesNode extends vscode.TreeItem { - constructor( - public readonly label: string, - public readonly collapsibleState: vscode.TreeItemCollapsibleState, - public readonly command?: vscode.Command - ) { - super(label, collapsibleState); - this.iconPath = collapsibleState === vscode.TreeItemCollapsibleState.None ? vscode.ThemeIcon.File : vscode.ThemeIcon.Folder; - } -} - -export class ProfilesTreeProvider implements vscode.TreeDataProvider { - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter(); - public readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; - private _dirty = true; - private _profileData: imperative.IProfAttrs[] = []; - - public constructor() { - vscode.workspace.onDidChangeWorkspaceFolders(this.refresh.bind(this)); - } - - public refresh(): void { - this._dirty = false; - this._onDidChangeTreeData.fire(); - } - - public getTreeItem(node: ProfilesNode): ProfilesNode { - return node; - } - - public async getChildren(node?: ProfilesNode): Promise { - if (this._dirty) { - const profiles = new ProfilesCache(imperative.Logger.getAppLogger(), vscode.workspace.workspaceFolders?.[0]?.uri.fsPath); - this._profileData = (await profiles.getProfileInfo()).getAllProfiles(); - this._dirty = false; - } - - const children: ProfilesNode[] = []; - if (node == null) { - for (const profType of new Set(this._profileData.map((profAttrs) => profAttrs.profType))) { - children.push(new ProfilesNode(profType, vscode.TreeItemCollapsibleState.Collapsed)); - } - } else { - const profType = node.label as string; - for (const profAttrs of new Set(this._profileData.filter((profAttrs) => profAttrs.profType === profType))) { - children.push( - new ProfilesNode(profAttrs.profName, vscode.TreeItemCollapsibleState.None, { - title: "Open Profile in Editor", - command: "vscode.open", - arguments: profAttrs.profLoc.osLoc, - }) - ); - } - } - return Promise.resolve(children); - } -} diff --git a/samples/tree-view-sample/src/extension.ts b/samples/tree-view-sample/src/extension.ts deleted file mode 100644 index 2f086d060d..0000000000 --- a/samples/tree-view-sample/src/extension.ts +++ /dev/null @@ -1,16 +0,0 @@ -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -import * as vscode from "vscode"; -import { ProfilesTreeProvider } from "./ProfilesTreeProvider"; - -// This method is called when your extension is activated -// Your extension is activated the very first time the command is executed -export function activate(context: vscode.ExtensionContext) { - const treeDataProvider = new ProfilesTreeProvider(); - vscode.window.createTreeView("tree-view-sample.profiles", { treeDataProvider, showCollapseAll: true }); - - const disposable = vscode.commands.registerCommand("tree-view-sample.refresh", () => { - treeDataProvider.refresh(); - }); - context.subscriptions.push(disposable); -} diff --git a/samples/tree-view-sample/tsconfig.json b/samples/tree-view-sample/tsconfig.json deleted file mode 100644 index 52cbd382ae..0000000000 --- a/samples/tree-view-sample/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es2020", - "lib": ["es2020"], - "outDir": "out", - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "rootDir": "src" - }, - "exclude": ["node_modules", ".vscode-test"] -} diff --git a/samples/uss-profile-sample/.eslintrc.js b/samples/uss-profile-sample/.eslintrc.js deleted file mode 100644 index 5e0416f422..0000000000 --- a/samples/uss-profile-sample/.eslintrc.js +++ /dev/null @@ -1,15 +0,0 @@ -/**@type {import('eslint').Linter.Config} */ -// eslint-disable-next-line no-undef -module.exports = { - root: true, - parser: "@typescript-eslint/parser", - plugins: ["@typescript-eslint"], - extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - rules: { - semi: [2, "always"], - "@typescript-eslint/no-unused-vars": 0, - "@typescript-eslint/no-explicit-any": 0, - "@typescript-eslint/explicit-module-boundary-types": 0, - "@typescript-eslint/no-non-null-assertion": 0, - }, -}; diff --git a/samples/uss-profile-sample/.gitignore b/samples/uss-profile-sample/.gitignore deleted file mode 100644 index 5fe00fea85..0000000000 --- a/samples/uss-profile-sample/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -out -node_modules -.vscode-test/ -*.vsix diff --git a/samples/uss-profile-sample/.npmrc b/samples/uss-profile-sample/.npmrc deleted file mode 100644 index f301fedf98..0000000000 --- a/samples/uss-profile-sample/.npmrc +++ /dev/null @@ -1 +0,0 @@ -auto-install-peers=false diff --git a/samples/uss-profile-sample/.vscode/launch.json b/samples/uss-profile-sample/.vscode/launch.json deleted file mode 100644 index e3dea5af1e..0000000000 --- a/samples/uss-profile-sample/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// Use IntelliSense to learn about possible attributes. -// Hover to view descriptions of existing attributes. -// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceFolder}"], - "outFiles": ["${workspaceFolder}/out/**/*.js"], - "preLaunchTask": "npm: watch" - } - ] -} diff --git a/samples/uss-profile-sample/.vscode/tasks.json b/samples/uss-profile-sample/.vscode/tasks.json deleted file mode 100644 index 078ff7e01e..0000000000 --- a/samples/uss-profile-sample/.vscode/tasks.json +++ /dev/null @@ -1,20 +0,0 @@ -// See https://go.microsoft.com/fwlink/?LinkId=733558 -// for the documentation about the tasks.json format -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} diff --git a/samples/uss-profile-sample/README.md b/samples/uss-profile-sample/README.md deleted file mode 100644 index fd88effae0..0000000000 --- a/samples/uss-profile-sample/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# USS Profile Sample - -Demonstrates adding support for a new profile type to the USS tree in Zowe Explorer. - -This samples adds SSH profiles to the Zowe Explorer USS tree, so that files can be managed on a mainframe or any Unix server that supports SFTP (FTP over SSH). - -In "extension.ts" the Zowe Explorer API is used to load SSH profiles, and [`SshUssApi`](/samples/uss-profile-sample/src/SshUssApi.ts) is registered to enable USS file operations such as listing, downloading, and uploading. - -**Warning:** This extension performs remote file operations and has not been thoroughly tested. Use at your own risk for testing purposes only. - -## Running the sample - -- Open this sample in VS Code -- `pnpm` -- `pnpm run compile` -- `F5` to start debugging diff --git a/samples/uss-profile-sample/package.json b/samples/uss-profile-sample/package.json deleted file mode 100644 index e4a56104eb..0000000000 --- a/samples/uss-profile-sample/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "uss-profile-sample", - "displayName": "uss-profile-sample", - "description": "USS profile sample for Zowe Explorer", - "version": "0.0.1", - "publisher": "Zowe", - "repository": "https://github.com/zowe/zowe-explorer-vscode/samples/uss-profile-sample", - "engines": { - "vscode": "^1.79.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [ - "onStartupFinished" - ], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "uss-profile-sample.helloWorld", - "title": "Hello World" - } - ] - }, - "extensionDependencies": [ - "Zowe.vscode-extension-for-zowe" - ], - "scripts": { - "vscode:prepublish": "pnpm run compile", - "compile": "tsc -p ./", - "lint": "eslint \"src/**/*.ts\"", - "watch": "tsc -watch -p ./" - }, - "dependencies": { - "@zowe/zowe-explorer-api": "file:../../packages/zowe-explorer-api", - "ssh2-sftp-client": "^9.1.0" - }, - "devDependencies": { - "@types/node": "^18.19.14", - "@types/ssh2-sftp-client": "^9.0.0", - "@types/vscode": "^1.53.2", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", - "eslint": "^8.26.0", - "typescript": "^5.1.3" - }, - "peerDependencies": { - "@zowe/zos-files-for-zowe-sdk": "^8.0.0", - "@zowe/zos-uss-for-zowe-sdk": "^8.0.0" - } -} diff --git a/samples/uss-profile-sample/src/SshUssApi.ts b/samples/uss-profile-sample/src/SshUssApi.ts deleted file mode 100644 index 87ffea0e82..0000000000 --- a/samples/uss-profile-sample/src/SshUssApi.ts +++ /dev/null @@ -1,126 +0,0 @@ -import * as Client from "ssh2-sftp-client"; -import * as vscode from "vscode"; -import * as zosfiles from "@zowe/zos-files-for-zowe-sdk"; -import { ZosUssProfile } from "@zowe/zos-uss-for-zowe-sdk"; -import { imperative, MainframeInteraction } from "@zowe/zowe-explorer-api"; - -export class SshUssApi implements MainframeInteraction.IUss { - public constructor(public profile?: imperative.IProfileLoaded) {} - - public getProfileTypeName(): string { - return ZosUssProfile.type; - } - - public getSession(profile?: imperative.IProfileLoaded): imperative.Session { - const sessCfg: imperative.ISession = {}; - imperative.ConnectionPropsForSessCfg.resolveSessCfgProps(sessCfg, (profile || this.profile)?.profile as any); - return new imperative.Session(sessCfg); - } - - public async getStatus(profile: imperative.IProfileLoaded, profileType?: string): Promise { - if (profileType === ZosUssProfile.type) { - try { - return await this.withClient(this.getSession(profile), () => Promise.resolve("active")); - } catch (err) { - vscode.window.showErrorMessage((err as Error).toString()); - return Promise.resolve("inactive"); - } - } - return Promise.resolve("unverified"); - } - - public async fileList(ussFilePath: string): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = []; - for (const fileInfo of await client.list(ussFilePath)) { - response.push({ - name: fileInfo.name, - mode: fileInfo.type + fileInfo.owner + fileInfo.group + fileInfo.rights.other, - size: fileInfo.size, - uid: fileInfo.owner, - gid: fileInfo.group, - mtime: fileInfo.modifyTime.toString(), - }); - } - return this.buildZosFilesResponse({ items: response }); - }); - } - - public isFileTagBinOrAscii(ussFilePath: string): Promise { - return Promise.resolve(false); - } - - public async getContents(ussFilePath: string, options: zosfiles.IDownloadOptions): Promise { - return this.withClient(this.getSession(), async (client) => { - const localPath = options.file as string; - imperative.IO.createDirsSyncFromFilePath(localPath); - const response = await client.fastGet(ussFilePath, localPath); - return this.buildZosFilesResponse(response); - }); - } - - public uploadFromBuffer(buffer: Buffer, filePath: string, _options?: zosfiles.IUploadOptions): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = await client.put(buffer, filePath); - return this.buildZosFilesResponse(response); - }); - } - - public async putContent(inputFilePath: string, ussFilePath: string): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = await client.fastPut(inputFilePath, ussFilePath); - return this.buildZosFilesResponse(response); - }); - } - - public async uploadDirectory( - inputDirectoryPath: string, - ussDirectoryPath: string, - options: zosfiles.IUploadOptions - ): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = await client.uploadDir(inputDirectoryPath, ussDirectoryPath); - return this.buildZosFilesResponse(response); - }); - } - - public async create(ussPath: string, type: string, mode?: string | undefined): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = type === "directory" ? await client.mkdir(ussPath) : await client.append(Buffer.from(""), ussPath, { mode }); - return this.buildZosFilesResponse(response); - }); - } - - public async delete(ussPath: string, recursive?: boolean | undefined): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = recursive ? await client.rmdir(ussPath, true) : await client.delete(ussPath); - return this.buildZosFilesResponse(response); - }); - } - - public async rename(currentUssPath: string, newUssPath: string): Promise { - return this.withClient(this.getSession(), async (client) => { - const response = await client.rename(currentUssPath, newUssPath); - return this.buildZosFilesResponse(response); - }); - } - - private buildZosFilesResponse(apiResponse: any, success = true): zosfiles.IZosFilesResponse { - return { apiResponse, commandResponse: "", success }; - } - - private async withClient(session: imperative.Session, callback: (client: Client) => Promise): Promise { - const client = new Client(); - try { - await client.connect({ - host: session.ISession.hostname, - port: session.ISession.port, - username: session.ISession.user, - password: session.ISession.password, - }); - return await callback(client); - } finally { - await client.end(); - } - } -} diff --git a/samples/uss-profile-sample/src/extension.ts b/samples/uss-profile-sample/src/extension.ts deleted file mode 100644 index 4c3aa0bea7..0000000000 --- a/samples/uss-profile-sample/src/extension.ts +++ /dev/null @@ -1,19 +0,0 @@ -// The module 'vscode' contains the VS Code extensibility API -// Import the module and reference it with the alias vscode in your code below -import * as vscode from "vscode"; -import { ZosUssProfile } from "@zowe/zos-uss-for-zowe-sdk"; -import { ZoweVsCodeExtension } from "@zowe/zowe-explorer-api"; -import { SshUssApi } from "./SshUssApi"; - -// This method is called when your extension is activated -// Your extension is activated the very first time the command is executed -export async function activate(context: vscode.ExtensionContext) { - const zoweExplorerApi = ZoweVsCodeExtension.getZoweExplorerApi(); - if (zoweExplorerApi != null) { - zoweExplorerApi.registerUssApi(new SshUssApi()); - await zoweExplorerApi.getExplorerExtenderApi().initForZowe("ssh", [ZosUssProfile]); - await zoweExplorerApi.getExplorerExtenderApi().reloadProfiles("ssh"); - } else { - vscode.window.showErrorMessage("Could not access Zowe Explorer API. Please check that the latest version of Zowe Explorer is installed."); - } -} diff --git a/samples/uss-profile-sample/tsconfig.json b/samples/uss-profile-sample/tsconfig.json deleted file mode 100644 index 52cbd382ae..0000000000 --- a/samples/uss-profile-sample/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es2020", - "lib": ["es2020"], - "outDir": "out", - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "rootDir": "src" - }, - "exclude": ["node_modules", ".vscode-test"] -} diff --git a/samples/vue-webview-sample/.vscode/launch.json b/samples/vue-webview-sample/.vscode/launch.json deleted file mode 100644 index e3dea5af1e..0000000000 --- a/samples/vue-webview-sample/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -// A launch configuration that compiles the extension and then opens it inside a new window -// Use IntelliSense to learn about possible attributes. -// Hover to view descriptions of existing attributes. -// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Run Extension", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": ["--extensionDevelopmentPath=${workspaceFolder}"], - "outFiles": ["${workspaceFolder}/out/**/*.js"], - "preLaunchTask": "npm: watch" - } - ] -} diff --git a/samples/vue-webview-sample/.vscode/tasks.json b/samples/vue-webview-sample/.vscode/tasks.json deleted file mode 100644 index 078ff7e01e..0000000000 --- a/samples/vue-webview-sample/.vscode/tasks.json +++ /dev/null @@ -1,20 +0,0 @@ -// See https://go.microsoft.com/fwlink/?LinkId=733558 -// for the documentation about the tasks.json format -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "watch", - "problemMatcher": "$tsc-watch", - "isBackground": true, - "presentation": { - "reveal": "never" - }, - "group": { - "kind": "build", - "isDefault": true - } - } - ] -} diff --git a/samples/vue-webview-sample/package.json b/samples/vue-webview-sample/package.json deleted file mode 100644 index 3e09721f33..0000000000 --- a/samples/vue-webview-sample/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "vue-webview-sample", - "displayName": "vue-webview-sample", - "description": "Sample VSCode extension leveraging ZE API WebView class and a Vite-powered Vue demo", - "private": true, - "version": "0.0.1", - "engines": { - "vscode": "^1.79.0" - }, - "categories": [ - "Other" - ], - "activationEvents": [], - "main": "./out/extension.js", - "contributes": { - "commands": [ - { - "command": "extension.helloWorld", - "title": "Hello World" - } - ] - }, - "scripts": { - "vscode:prepublish": "pnpm run compile", - "compile": "pnpm --package=typescript dlx tsc -p ./ && cd webviews/vue-sample && pnpm --ignore-workspace i && pnpm build", - "lint": "eslint \"src/**/*.ts\"", - "watch": "pnpm --package=typescript dlx tsc -watch -p ./" - }, - "dependencies": { - "@zowe/zowe-explorer-api": "file:../../packages/zowe-explorer-api" - }, - "devDependencies": { - "@types/node": "^18.19.14", - "@types/vscode": "^1.53.2", - "@typescript-eslint/eslint-plugin": "^5.42.0", - "@typescript-eslint/parser": "^5.42.0", - "eslint": "^8.26.0", - "typescript": "^5.0.2", - "vue-tsc": "^1.8.8" - } -} diff --git a/samples/vue-webview-sample/src/extension.ts b/samples/vue-webview-sample/src/extension.ts deleted file mode 100644 index a2c546db56..0000000000 --- a/samples/vue-webview-sample/src/extension.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as vscode from "vscode"; -import { WebView } from "@zowe/zowe-explorer-api"; - -export function activate(context: vscode.ExtensionContext) { - console.log('Congratulations, your extension "helloworld-sample" is now active!'); - - const disposable = vscode.commands.registerCommand("extension.helloWorld", () => { - const webview = new WebView("Sample Webview", "vue-sample", context, { - onDidReceiveMessage: (message: Record) => { - vscode.window.showInformationMessage(message.text); - }, - }); - }); - - context.subscriptions.push(disposable); -} diff --git a/samples/vue-webview-sample/tsconfig.json b/samples/vue-webview-sample/tsconfig.json deleted file mode 100644 index 786b1f2167..0000000000 --- a/samples/vue-webview-sample/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "module": "commonjs", - "target": "es2020", - "lib": ["es2020"], - "outDir": "out", - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "rootDir": "src" - }, - "exclude": ["node_modules", ".vscode-test", "webviews"] -} diff --git a/samples/vue-webview-sample/webviews/vue-sample/index.html b/samples/vue-webview-sample/webviews/vue-sample/index.html deleted file mode 100644 index a5649bbf97..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Vite + Vue + TS - - -
- - - diff --git a/samples/vue-webview-sample/webviews/vue-sample/package.json b/samples/vue-webview-sample/webviews/vue-sample/package.json deleted file mode 100644 index cabcfb13ef..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "vue-sample", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vue-tsc && vite build", - "preview": "vite preview" - }, - "dependencies": { - "@types/vscode-webview": "^1.57.1", - "vue": "^3.3.4" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^4.2.3", - "typescript": "~5.4.0", - "vite": "^4.5.5", - "vue-tsc": "^1.8.8" - } -} diff --git a/samples/vue-webview-sample/webviews/vue-sample/src/App.vue b/samples/vue-webview-sample/webviews/vue-sample/src/App.vue deleted file mode 100644 index 03d681a33e..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/src/App.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/samples/vue-webview-sample/webviews/vue-sample/src/components/HelloWorld.vue b/samples/vue-webview-sample/webviews/vue-sample/src/components/HelloWorld.vue deleted file mode 100644 index 9bba458a19..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/src/components/HelloWorld.vue +++ /dev/null @@ -1,23 +0,0 @@ - - - diff --git a/samples/vue-webview-sample/webviews/vue-sample/src/main.ts b/samples/vue-webview-sample/webviews/vue-sample/src/main.ts deleted file mode 100644 index ade91c937d..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createApp } from "vue"; -import "./style.css"; -import App from "./App.vue"; - -createApp(App).mount("#webviewRoot"); diff --git a/samples/vue-webview-sample/webviews/vue-sample/src/style.css b/samples/vue-webview-sample/webviews/vue-sample/src/style.css deleted file mode 100644 index 8a645c53a6..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/src/style.css +++ /dev/null @@ -1,80 +0,0 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -.card { - padding: 2em; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/samples/vue-webview-sample/webviews/vue-sample/src/vite-env.d.ts b/samples/vue-webview-sample/webviews/vue-sample/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a0..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/samples/vue-webview-sample/webviews/vue-sample/tsconfig.json b/samples/vue-webview-sample/webviews/vue-sample/tsconfig.json deleted file mode 100644 index fd693e5ab6..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "node", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], - "references": [{ "path": "./tsconfig.node.json" }] -} diff --git a/samples/vue-webview-sample/webviews/vue-sample/tsconfig.node.json b/samples/vue-webview-sample/webviews/vue-sample/tsconfig.node.json deleted file mode 100644 index 42872c59f5..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/tsconfig.node.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "skipLibCheck": true, - "module": "ESNext", - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/samples/vue-webview-sample/webviews/vue-sample/vite.config.ts b/samples/vue-webview-sample/webviews/vue-sample/vite.config.ts deleted file mode 100644 index 0c7e40e453..0000000000 --- a/samples/vue-webview-sample/webviews/vue-sample/vite.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from "vite"; -import vue from "@vitejs/plugin-vue"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue()], - build: { - rollupOptions: { - output: { - entryFileNames: `assets/[name].js`, - chunkFileNames: `assets/[name].js`, - assetFileNames: `assets/[name].[ext]`, - }, - }, - }, -}); diff --git a/scripts/systemTestEnv.ts b/scripts/systemTestEnv.ts deleted file mode 100755 index 9f57abef41..0000000000 --- a/scripts/systemTestEnv.ts +++ /dev/null @@ -1,162 +0,0 @@ -/** - * This program and the accompanying materials are made available under the terms of the - * Eclipse Public License v2.0 which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Copyright Contributors to the Zowe Project. - * - */ - -import { profile, normalPattern, ussPattern } from "../packages/zowe-explorer/resources/testProfileData"; -import * as imperative from "@zowe/imperative"; -import * as zosfiles from "@zowe/zos-files-for-zowe-sdk"; - -const session: imperative.Session = new imperative.Session({ - hostname: profile.host, - user: profile.user, - password: profile.password, - port: profile.port, - rejectUnauthorized: profile.rejectUnauthorized, - type: "basic", -}); - -/** - * Creates the system test environment - */ -export async function createSystemTestEnvironment() { - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_PARTITIONED, `${normalPattern}.EXT.PDS`); - await createMember(`${normalPattern}.EXT.PDS(MEMBER)`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, `${normalPattern}.EXT.PS`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_PARTITIONED, `${normalPattern}.EXT.SAMPLE.PDS`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_PARTITIONED, `${normalPattern}.DELETE.TEST`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, `${normalPattern}.PUBLIC.BIN`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_CLASSIC, `${normalPattern}.PUBLIC.TCLASSIC`); - await createMember(`${normalPattern}.PUBLIC.TCLASSIC(NEW)`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_PARTITIONED, `${normalPattern}.PUBLIC.TPDS`); - await createMember(`${normalPattern}.PUBLIC.TPDS(TCHILD1)`); - await createMember(`${normalPattern}.PUBLIC.TPDS(TCHILD2)`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, `${normalPattern}.PUBLIC.TPS`); - - await createUSSDirectory(`${ussPattern}`); - await createUSSDirectory(`${ussPattern}/aDir1`); - await createUSSFile(`${ussPattern}/aDir1/aFile1.txt`); - await createUSSFile(`${ussPattern}/aFile2.txt`); - await createUSSDirectory(`${ussPattern}/aDir2`); - await createUSSDirectory(`${ussPattern}/group`); - await createUSSDirectory(`${ussPattern}/group/aDir3`); - await createUSSDirectory(`${ussPattern}/group/aDir4`); - await createUSSFile(`${ussPattern}/group/aDir4/aFile3.txt`); - await createUSSDirectory(`${ussPattern}/group/aDir5`); - await createUSSFile(`${ussPattern}/group/aDir5/aFile4.txt`); - await createUSSFile(`${ussPattern}/group/aDir5/aFile5.txt`); - await createUSSDirectory(`${ussPattern}/group/aDir6`); -} - -/** - * Creates data sets, members, and USS nodes which can be used in our demos - */ -export async function createDemoNodes() { - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_BINARY, `${normalPattern}.DEMO.BINARY`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_C, `${normalPattern}.DEMO.BINARY`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_CLASSIC, `${normalPattern}.DEMO.CLASSIC1`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_CLASSIC, `${normalPattern}.DEMO.CLASSIC2`); - await createMember(`${normalPattern}.DEMO.CLASSIC2(MEMBER1)`); - await createMember(`${normalPattern}.DEMO.CLASSIC2(MEMBER2)`); - await createMember(`${normalPattern}.DEMO.CLASSIC2(MEMBER3)`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_SEQUENTIAL, `${normalPattern}.DEMO.SDS`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_PARTITIONED, `${normalPattern}.DEMO.PDS1`); - await createDataset(zosfiles.CreateDataSetTypeEnum.DATA_SET_PARTITIONED, `${normalPattern}.DEMO.PDS2`); - await createMember(`${normalPattern}.DEMO.PDS2(MEMBER1)`); - await createMember(`${normalPattern}.DEMO.PDS2(MEMBER2)`); - await createMember(`${normalPattern}.DEMO.PDS2(MEMBER3)`); - - await createUSSDirectory(`${ussPattern}`); - await createUSSFile(`${ussPattern}/demoFile1.txt`); - await createUSSFile(`${ussPattern}/demoFile2.txt`); - await createUSSFile(`${ussPattern}/demoFile3.txt`); - await createUSSDirectory(`${ussPattern}/demoDir1`); - await createUSSFile(`${ussPattern}/demoDir1/demoFile1.txt`); - await createUSSFile(`${ussPattern}/demoDir1/demoFile2.txt`); - await createUSSFile(`${ussPattern}/demoDir1/demoFile3.txt`); - await createUSSDirectory(`${ussPattern}/demoDir1/demoDir2`); - await createUSSFile(`${ussPattern}/demoDir1/demoDir2/demoFile1.txt`); - await createUSSFile(`${ussPattern}/demoDir1/demoDir2/demoFile2.txt`); - await createUSSFile(`${ussPattern}/demoDir1/demoDir2/demoFile3.txt`); -} - -/** - * Clean's up the system test environment - */ -export async function cleanupSystemTestEnvironment() { - await deleteDataset(`${normalPattern}.EXT.PDS`); - await deleteDataset(`${normalPattern}.EXT.PS`); - await deleteDataset(`${normalPattern}.EXT.SAMPLE.PDS`); - await deleteDataset(`${normalPattern}.DELETE.TEST`); - await deleteDataset(`${normalPattern}.PUBLIC.BIN`); - await deleteDataset(`${normalPattern}.PUBLIC.TCLASSIC`); - await deleteDataset(`${normalPattern}.PUBLIC.TPDS`); - await deleteDataset(`${normalPattern}.PUBLIC.TPS`); - - await deleteAllFiles(`${ussPattern}`); -} - -async function createDataset(type: CreateDataSetTypeEnum, name: string) { - imperative.Logger.getConsoleLogger().info(`Creating Dataset: ${name}`); - try { - return await zosfiles.Create.dataSet(session, type, name); - } catch (err) { - imperative.Logger.getConsoleLogger().error(`Creating Dataset ${name} failed: ${err}`); - return null; - } -} - -async function createMember(name: string) { - imperative.Logger.getConsoleLogger().info(`Creating DS member: ${name}`); - try { - return await zosfiles.Upload.bufferToDataSet(session, Buffer.from(""), name); - } catch (err) { - imperative.Logger.getConsoleLogger().error(`Creating DS member ${name} failed: ${err}`); - return null; - } -} - -async function deleteDataset(name: string) { - imperative.Logger.getConsoleLogger().info(`Deleting Dataset: ${name}`); - try { - return await zosfiles.Delete.dataSet(session, name); - } catch (err) { - imperative.Logger.getConsoleLogger().error(`Deleting Dataset ${name} failed: ${err}`); - return null; - } -} -async function deleteAllFiles(name: string) { - imperative.Logger.getConsoleLogger().info(`Deleting files: ${name}`); - try { - return await zosfiles.Delete.ussFile(session, name, true); - } catch (err) { - imperative.Logger.getConsoleLogger().error(`Deleting files ${name} failed: ${err}`); - return null; - } -} - -async function createUSSFile(name: string) { - imperative.Logger.getConsoleLogger().info(`Creating USS File: ${name}`); - try { - return await zosfiles.Create.uss(session, name, "file"); - } catch (err) { - imperative.Logger.getConsoleLogger().error(`Creating USS File ${name} failed: ${err}`); - return null; - } -} - -async function createUSSDirectory(name: string) { - imperative.Logger.getConsoleLogger().info(`Creating USS Directory: ${name}`); - try { - return await zosfiles.Create.uss(session, name, "directory"); - } catch (err) { - imperative.Logger.getConsoleLogger().error(`Creating USS Directory ${name} failed: ${err}`); - return null; - } -}