Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix flaky integration tests and error handling for invalid team config #3322

Merged
merged 18 commits into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .github/workflows/zowe-explorer-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ jobs:
# install pnpm
- run: npm install -g pnpm@8

- run: pnpm config set network-timeout 60000 && pnpm install && pnpm build
- run: pnpm config set network-timeout 60000 && pnpm install

- run: pnpm build
id: build

- run: pnpm test
env:
Expand All @@ -55,22 +58,24 @@ jobs:
id: unlock-keyring
if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x'
uses: t1m0thyj/unlock-keyring@v1

- name: Integration tests
if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x'
run: xvfb-run pnpm test:integration --exclude "Activation.feature"
working-directory: packages/zowe-explorer

- name: Upload test results
uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x'
if: always() && steps.build.outcome == 'success' && matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x'
with:
name: zowe-explorer-results
path: packages/zowe-explorer/results/
path: |
packages/zowe-explorer/results/
packages/zowe-explorer/__tests__/__integration__/bdd/results/

- name: Upload API test results
uses: actions/upload-artifact@v4
if: matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x'
if: always() && steps.build.outcome == 'success' && matrix.os == 'ubuntu-22.04' && matrix.node-version == '20.x'
with:
name: zowe-explorer-api-results
path: packages/zowe-explorer-api/results/
Expand Down
2 changes: 1 addition & 1 deletion packages/zowe-explorer-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ All notable changes to the "zowe-explorer-api" extension will be documented in t

### New features and enhancements

- Update Zowe SDKs to `8.8.2` to get the latest enhancements from Imperative.
- Update Zowe SDKs to `8.8.2` to get the latest enhancements from Imperative. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)

### Bug fixes

Expand Down
3 changes: 2 additions & 1 deletion packages/zowe-explorer/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ results
scripts
src/webviews/dist
l10n/bundle.l10n.json
__tests__/__common__/.wdio-vscode-service
__tests__/__common__/.wdio-vscode-service
zFernand0 marked this conversation as resolved.
Show resolved Hide resolved
__tests__/__integration__/bdd/resources
12 changes: 10 additions & 2 deletions packages/zowe-explorer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen

### New features and enhancements

### Bug fixes

- Fixed an issue during initialization where the error dialog shown for a broken team configuration file was missing the "Show Config" action. [#3322](https://github.com/zowe/zowe-explorer-vscode/pull/3322)

## `3.0.3`

### New features and enhancements

- Update Zowe SDKs to `8.2.0` to get the latest enhancements from Imperative.
- Added expired JSON web token detection for profiles in each tree view (Data Sets, USS, Jobs). When a user performs a search on a profile, they are prompted to log in if their token expired. [#3175](https://github.com/zowe/zowe-explorer-vscode/issues/3175)
- Add a data set or USS resource to a virtual workspace with the new "Add to Workspace" context menu option. [#3265](https://github.com/zowe/zowe-explorer-vscode/issues/3265)
Expand All @@ -29,9 +37,9 @@ All notable changes to the "vscode-extension-for-zowe" extension will be documen
- Fixed issue where users were not prompted to enter credentials if a 401 error was encountered when opening files, data sets or spools in the editor. [#3197](https://github.com/zowe/zowe-explorer-vscode/issues/3197)
- Fixed issue where profile credential updates or token changes were not reflected within the filesystem. [#3289](https://github.com/zowe/zowe-explorer-vscode/issues/3289)
- Fixed issue to update the success message when changing authentication from token to basic through the 'Change Authentication' option. [#3316](https://github.com/zowe/zowe-explorer-vscode/pull/3316)
- Fixed an issue where editing a team config file or updating credentials in OS vault could trigger multiple events for a single action. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- Fixed an issue where fetching a USS file using `UssFSProvider.stat()` with a `fetch=true` query would cause Zowe Explorer to get stuck in an infinite loop. [#3321](https://github.com/zowe/zowe-explorer-vscode/pull/3321)
- Fixed an issue where editing a team config file or updating secrets in the OS credential vault could trigger multiple events for a single action. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- Updated Zowe SDKs to `8.8.2` for technical currency. [#3296](https://github.com/zowe/zowe-explorer-vscode/pull/3296)
- Fixed an issue where fetching a USS file using `UssFSProvider.stat()` with a `fetch=true` query would cause Zowe Explorer to get stuck in an infinite loop.

## `3.0.2`

Expand Down
4 changes: 4 additions & 0 deletions packages/zowe-explorer/__tests__/__common__/base.wdio.conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/

import type { Options } from "@wdio/types";
import { tmpdir } from "os";
import { join as joinPath } from "path";

export const baseConfig: Partial<Options.Testrunner> = {
//
Expand Down Expand Up @@ -207,3 +209,5 @@ export const baseConfig: Partial<Options.Testrunner> = {
// afterAssertion: function(params) {
// }
};

export const dataDir = joinPath(process.platform === "darwin" ? tmpdir() : __dirname, ".wdio-vscode-service", "data");
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ async function setFilterForProfile(world: IWorld, profileNode: TreeItem, tree: s

if (isJobs) {
// Jobs
const createFilterSelector = await quickPick.findItem("plus Create job search filter");
const createFilterSelector = await quickPick.findItem("$(plus) Create job search filter");
await expect(createFilterSelector).toBeClickable();
await createFilterSelector.click();
const submitSelector = await quickPick.findItem("check Submit this query");
const submitSelector = await quickPick.findItem("$(check) Submit this query");
await expect(submitSelector).toBeClickable();
await submitSelector.click();
} else {
// Data sets or USS
if (await quickPick.hasOptions()) {
// Only click the "Create a new filter" button if there are existing filters and the option is presented
const filterLabel = isUss
? "plus Create a new filter"
: "plus Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)";
? "$(plus) Create a new filter"
: "$(plus) Create a new filter. For example: HLQ.*, HLQ.aaa.bbb, HLQ.ccc.ddd(member)";

const createFilterSelector = await quickPick.findItem(filterLabel);
await expect(createFilterSelector).toBeClickable();
Expand Down
3 changes: 2 additions & 1 deletion packages/zowe-explorer/__tests__/__e2e__/wdio.conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type { Options } from "@wdio/types";
import { existsSync } from "fs";
import { emptyDirSync, mkdirpSync } from "fs-extra";
import { join as joinPath, relative as relativePath } from "path";
import { baseConfig } from "../__common__/base.wdio.conf";
import { baseConfig, dataDir } from "../__common__/base.wdio.conf";

if (process.env.ZOWE_TEST_DIR) {
const homeDir = (process.env["ZOWE_CLI_HOME"] = joinPath(__dirname, relativePath(__dirname, process.env.ZOWE_TEST_DIR)));
Expand Down Expand Up @@ -99,6 +99,7 @@ export const config: Options.Testrunner = {
"wdio:vscodeOptions": {
// points to directory where extension package.json is located
extensionPath: joinPath(__dirname, "..", ".."),
storagePath: dataDir,
// optional VS Code settings
userSettings: {
"editor.fontSize": 14,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ Scenario: User opens and dismisses the Team Configuration quick pick

# Scenario: User creates a global Team Configuration file
# Given a user who is looking at the Add Config quick pick
# When a user selects "Create a new Team Configuration file"
# When a user selects 'Create a new Team Configuration file'
# Then a new configuration file will be created and opened in the editor
# Then it will ask the user for the desired config location
# When the user selects the global option
# Then it will open the config in the editor

Scenario: User edits Team Configuration file
Given a user who is looking at the Add Config quick pick
When a user selects "Edit Team Configuration File"
When a user selects 'Edit Team Configuration File'
Then it will open the config in the editor

Scenario Outline: User wants to add a profile to the tree views
Expand All @@ -23,7 +23,7 @@ Scenario Outline: User wants to add a profile to the tree views
Then it will prompt the user to add the profile to one or all trees
When a user selects <opt> to apply to all trees
Then it will add a tree item for the profile to the correct trees

Examples:
| opt |
| No |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
Feature: Update credentials for z/OSMF profile

Scenario: Prompt for missing <authType> credentials
Given a user who has profile with <authType> auth in team config
And a user who is looking at the Zowe Explorer tree views
And the user has a profile in their Data Sets tree
Given a user who is looking at the Zowe Explorer tree views
And the user has a <authType> profile in their Data Sets tree
When a user clicks search button for the profile
Then the user will be prompted for <authType> credentials
And the profile node icon will be marked as inactive
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
invalidJson
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"$schema": "./zowe.schema.json",
"profiles": {
"zosmf_basic": {
"type": "zosmf",
"properties": {},
"secure": ["user", "password"]
},
"zosmf_token": {
"type": "zosmf",
"properties": {},
"secure": ["tokenValue"]
},
"base": {
"type": "base",
"properties": {
"host": "localhost",
"rejectUnauthorized": false
},
"secure": []
}
},
"defaults": {
"base": "base"
},
"autoStore": true
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Given("a user who is looking at the Add Config quick pick", async function () {
//
// Scenario: User wants to create a new Team Configuration file
//
When('a user selects "Create a new Team Configuration file"', async function () {
When("a user selects 'Create a new Team Configuration file'", async function () {
const createTeamConfigEntry = await quickPick.findItem("+ Create a New Team Configuration File");
await expect(createTeamConfigEntry).toBeClickable();
await createTeamConfigEntry.click();
Expand Down Expand Up @@ -70,7 +70,7 @@ Then("it will open the config in the editor", async function () {
//
// Scenario: User wants to edit existing Team Configuration file
//
When('a user selects "Edit Team Configuration File"', async function () {
When("a user selects 'Edit Team Configuration File'", async function () {
const editTeamConfigEntry = await quickPick.findItem("✏ Edit Team Configuration File");
await expect(editTeamConfigEntry).toBeClickable();
await editTeamConfigEntry.click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,61 +9,28 @@
*
*/

import * as fs from "fs";
import * as path from "path";
import { AfterAll, Then, When } from "@cucumber/cucumber";
import { Then, When } from "@cucumber/cucumber";
import { paneDivForTree } from "../../../../__common__/shared.wdio";
import quickPick from "../../../../__pageobjects__/QuickPick";
import { Key } from "webdriverio";
import { TreeItem } from "wdio-vscode-service";

const USER_CONFIG_FILE = path.join(process.env.ZOWE_CLI_HOME, "zowe.config.user.json");

AfterAll(() => {
fs.rmSync(USER_CONFIG_FILE, { force: true });
});
When(/a user who has profile with (.*) auth in team config/, function (authType: string) {
// TODO: We need to copy from Global Config until Imperative API is fixed
// See https://github.com/zowe/zowe-cli/issues/2273
When(/the user has a (.*) profile in their Data Sets tree/, async function (authType: string) {
this.authType = authType;
const tempCfg = JSON.parse(fs.readFileSync(USER_CONFIG_FILE.replace(".user", ""), "utf-8"));
const testConfig = {
$schema: "./zowe.schema.json",
profiles: {
...tempCfg.profiles,
zosmf1: {
type: null, // Disable default global zosmf profile
},
[`zosmf_${authType}`]: {
type: "zosmf",
properties: {},
secure: [],
},
},
defaults: {
...tempCfg.defaults,
zosmf: `zosmf_${authType}`,
},
};
if (authType === "basic") {
testConfig.profiles.zosmf_basic.secure.push("user", "password");
} else if (authType === "token") {
testConfig.profiles.zosmf_token.secure.push("tokenValue");
}
fs.writeFileSync(USER_CONFIG_FILE, JSON.stringify(testConfig, null, 2));
});
When("the user has a profile in their Data Sets tree", async function () {
// add profile via quick pick
this.treePane = await paneDivForTree("Data Sets");
await browser.waitUntil(async () => {
const visibleItems = await this.treePane.getVisibleItems();
for (const item of visibleItems) {
if ((await item.getLabel()) === `zosmf_${this.authType as string}`) {
this.profileNode = item;
return true;
}
}

return false;
});
await this.treePane.elem.moveTo();
const plusIcon = await this.treePane.getAction(`Add Profile to Data Sets View`);
await expect(plusIcon).toBeDefined();
await plusIcon.elem.click();
await browser.waitUntil((): Promise<boolean> => quickPick.isClickable());
const testProfileEntry = await quickPick.findItem(`$(home) zosmf_${this.authType as string}`);
await expect(testProfileEntry).toBeClickable();
await testProfileEntry.click();
this.yesOpt = await quickPick.findItem("Yes, Apply to all trees");
await expect(this.yesOpt).toBeClickable();
await this.yesOpt.click();
this.profileNode = (await this.treePane.findItem(`zosmf_${this.authType as string}`)) as TreeItem;
});
When("a user clicks search button for the profile", async function () {
await this.profileNode.elem.moveTo();
Expand Down
44 changes: 25 additions & 19 deletions packages/zowe-explorer/__tests__/__integration__/bdd/wdio.conf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@
*/

import type { Options } from "@wdio/types";
import { join as joinPath, resolve as resolvePath } from "path";
import { join as joinPath, parse as parsePath, resolve as resolvePath } from "path";
import { emptyDirSync } from "fs-extra";
import { baseConfig } from "../../__common__/base.wdio.conf";
import { renameSync, rmSync, writeFileSync } from "fs";
import { baseConfig, dataDir } from "../../__common__/base.wdio.conf";
import { cpSync, existsSync, readdirSync, renameSync } from "fs";

const dataDir = joinPath(__dirname, "..", "..", "__common__", ".wdio-vscode-service", "data");
const screenshotDir = joinPath(__dirname, "results", "screenshots");

process.env["ZOWE_CLI_HOME"] = resolvePath("../ci");
process.env.ZOWE_CLI_HOME = resolvePath("../ci");

export const config: Options.Testrunner = {
...baseConfig,
Expand Down Expand Up @@ -81,7 +79,8 @@ export const config: Options.Testrunner = {
capabilities: [
{
browserName: "vscode",
browserVersion: "stable", // also possible: "insiders" or a specific version e.g. "1.80.0"
// version can be "stable", "insiders", or a specific version e.g. "1.80.0"
browserVersion: process.env.ZE_TEST_VSCODE_VER || "stable",
"wdio:vscodeOptions": {
// points to directory where extension package.json is located
extensionPath: joinPath(__dirname, "..", "..", ".."),
Expand Down Expand Up @@ -153,21 +152,28 @@ export const config: Options.Testrunner = {
emptyDirSync(screenshotDir);
},

beforeFeature: async function (uri, feature) {
if (feature.name === "Show Config Error Dialog") {
const configPath = joinPath(process.env["ZOWE_CLI_HOME"], "zowe.config.json");
const backupConfigPath = joinPath(process.env["ZOWE_CLI_HOME"], "zowe.config.bkp");
renameSync(configPath, backupConfigPath);
writeFileSync(configPath, "invalidjson");
before: function (caps, specs) {
const resourceDir = joinPath(__dirname, "resources", parsePath(specs[0]).name);
if (existsSync(resourceDir)) {
for (const resourceFile of readdirSync(resourceDir)) {
const resourcePath = joinPath(process.env.ZOWE_CLI_HOME, resourceFile);
if (!existsSync(resourcePath + ".bak")) {
cpSync(resourcePath, resourcePath + ".bak");
}
cpSync(joinPath(resourceDir, resourceFile), resourcePath);
}
}
},

afterFeature: async function (uri, feature) {
if (feature.name === "Show Config Error Dialog") {
const backupConfigPath = joinPath(process.env["ZOWE_CLI_HOME"], "zowe.config.bkp");
const configPath = joinPath(process.env["ZOWE_CLI_HOME"], "zowe.config.json");
rmSync(configPath);
renameSync(backupConfigPath, configPath);
after: function (result, caps, specs) {
const resourceDir = joinPath(__dirname, "resources", parsePath(specs[0]).name);
if (existsSync(resourceDir)) {
for (const resourceFile of readdirSync(resourceDir)) {
const resourcePath = joinPath(process.env.ZOWE_CLI_HOME, resourceFile);
if (existsSync(resourcePath + ".bak")) {
renameSync(resourcePath + ".bak", resourcePath);
}
}
}
},

Expand Down
2 changes: 2 additions & 0 deletions packages/zowe-explorer/__tests__/__pageobjects__/QuickPick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class QuickPick {
}

public async findItem(label: string): Promise<ChainablePromiseElement> {
// Handle labels that start with a codicon
label = label.replace(/^\$\(([^)]+)\)\s/, "$1 ");
return this.elem.$(`.monaco-list-row[role="option"][aria-label="${label}"]`);
}

Expand Down
Loading
Loading