This is an automated email from the ASF dual-hosted git repository.
tbonelee pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/master by this push:
new 33ebb738d4 [ZEPPELIN-6520] Bind repository proxy password input to
proxyPassword control
33ebb738d4 is described below
commit 33ebb738d4d8ae43b8ffc14ca9fcbc642fb46160
Author: 김예나 <[email protected]>
AuthorDate: Mon Jul 13 00:37:21 2026 +0900
[ZEPPELIN-6520] Bind repository proxy password input to proxyPassword
control
### What is this PR for?
In the interpreter "add repository" dialog, the proxy **Password** input
was bound to the wrong reactive-form control (`proxyLogin`) — the same control
the **Login** field already uses. As a result a proxy password could never be
saved, and typing a proxy password overwrote the proxy login.
This PR binds the Password input to the `proxyPassword` control so that
both proxy credentials are submitted independently.
`create-repository-modal.component.html`:
```diff
- <input nz-input type="password" formControlName="proxyLogin"
placeholder="proxy password" />
+ <input nz-input type="password" formControlName="proxyPassword"
placeholder="proxy password" />
```
### What type of PR is it?
Bug Fix
### Todos
* [x] - Fix the form-control binding
* [x] - Add an e2e regression test
### What is the ticket?
https://issues.apache.org/jira/browse/ZEPPELIN-6520
### How should this be tested?
* `cd zeppelin-web-angular && npm run lint`
* A Playwright e2e test is added:
`e2e/tests/workspace/interpreter/create-repository-proxy-credentials.spec.ts`.
It fills the proxy login and proxy password in the add-repository modal and
asserts the `POST /api/interpreter/repository` payload carries each value in
its own field (`proxyLogin` / `proxyPassword`). The test fails on the current
binding and passes with this fix.
* Manually: add a repository with a proxy login and password in the
interpreter UI and confirm both are sent.
### Screenshots (if appropriate)
N/A — the form renders identically; the defect is only visible in the
submitted payload.
### Questions:
* Does the license files need to update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No
Closes #5291 from kimyenac/ZEPPELIN-6520.
Signed-off-by: ChanHo Lee <[email protected]>
---
.../e2e/models/interpreter-repository-modal.ts | 65 +++++++++++++++++++++
.../create-repository-proxy-credentials.spec.ts | 66 ++++++++++++++++++++++
.../create-repository-modal.component.html | 2 +-
3 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/zeppelin-web-angular/e2e/models/interpreter-repository-modal.ts
b/zeppelin-web-angular/e2e/models/interpreter-repository-modal.ts
new file mode 100644
index 0000000000..c4fc0d1782
--- /dev/null
+++ b/zeppelin-web-angular/e2e/models/interpreter-repository-modal.ts
@@ -0,0 +1,65 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Locator, Page } from '@playwright/test';
+import { BasePage } from './base-page';
+
+export interface RepositoryProxyCredentials {
+ id: string;
+ url: string;
+ proxyLogin: string;
+ proxyPassword: string;
+}
+
+export class InterpreterRepositoryModal extends BasePage {
+ readonly repositoryTrigger: Locator;
+ readonly createRepositoryTag: Locator;
+ readonly idInput: Locator;
+ readonly urlInput: Locator;
+ readonly proxyLoginInput: Locator;
+ readonly proxyPasswordInput: Locator;
+ readonly addButton: Locator;
+
+ constructor(page: Page) {
+ super(page);
+ this.repositoryTrigger = page.locator('button.repository-trigger');
+ this.createRepositoryTag = page.locator('nz-tag.editable-tag');
+ this.idInput = page.locator('input[placeholder="Repository id"]');
+ this.urlInput = page.locator('input[placeholder="Repository url"]');
+ // Locate the proxy inputs by placeholder, not formControlName: the
binding is
+ // what the regression test exercises, so the locator must not depend on
it.
+ this.proxyLoginInput = page.locator('input[placeholder="proxy login"]');
+ this.proxyPasswordInput = page.locator('input[placeholder="proxy
password"]');
+ this.addButton = page.getByRole('button', { name: 'Add', exact: true });
+ }
+
+ async navigate(): Promise<void> {
+ await this.navigateToRoute('/interpreter');
+ }
+
+ async openCreateModal(): Promise<void> {
+ await this.repositoryTrigger.click();
+ await this.createRepositoryTag.click();
+ await this.idInput.waitFor({ state: 'visible' });
+ }
+
+ async fillProxyRepository(form: RepositoryProxyCredentials): Promise<void> {
+ await this.fillAndVerifyInput(this.idInput, form.id);
+ await this.fillAndVerifyInput(this.urlInput, form.url);
+ await this.fillAndVerifyInput(this.proxyLoginInput, form.proxyLogin);
+ await this.fillAndVerifyInput(this.proxyPasswordInput, form.proxyPassword);
+ }
+
+ async submit(): Promise<void> {
+ await this.addButton.click();
+ }
+}
diff --git
a/zeppelin-web-angular/e2e/tests/workspace/interpreter/create-repository-proxy-credentials.spec.ts
b/zeppelin-web-angular/e2e/tests/workspace/interpreter/create-repository-proxy-credentials.spec.ts
new file mode 100644
index 0000000000..ec156dac60
--- /dev/null
+++
b/zeppelin-web-angular/e2e/tests/workspace/interpreter/create-repository-proxy-credentials.spec.ts
@@ -0,0 +1,66 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { expect, test } from '@playwright/test';
+import { InterpreterRepositoryModal } from
'../../../models/interpreter-repository-modal';
+import { addPageAnnotationBeforeEach, waitForZeppelinReady, PAGES } from
'../../../utils';
+
+interface AddRepositoryRequestBody {
+ id: string;
+ proxyLogin?: string;
+ proxyPassword?: string;
+}
+
+test.describe('Interpreter Repository - Proxy Credentials', () => {
+ addPageAnnotationBeforeEach(PAGES.WORKSPACE.INTERPRETER_CREATE_REPO);
+
+ test('submits the proxy login and proxy password to their own fields', async
({ page }) => {
+ const proxyLogin = 'proxy-user';
+ const proxyPassword = 'proxy-secret';
+ const repoId = `e2e-proxy-repo-${Date.now()}`;
+
+ await page.goto('/#/interpreter');
+ await waitForZeppelinReady(page);
+
+ // Intercept the POST so the payload can be checked without persisting a
repo.
+ let requestBody: AddRepositoryRequestBody | null = null;
+ await page.route('**/api/interpreter/repository', async route => {
+ if (route.request().method() === 'POST') {
+ requestBody = route.request().postDataJSON() as
AddRepositoryRequestBody;
+ await route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({ status: 'OK', message: '', body: '' })
+ });
+ return;
+ }
+ await route.continue();
+ });
+
+ const modal = new InterpreterRepositoryModal(page);
+ await modal.openCreateModal();
+ await modal.fillProxyRepository({
+ id: repoId,
+ url: 'repo1.maven.org/maven2/',
+ proxyLogin,
+ proxyPassword
+ });
+ await modal.submit();
+
+ await expect.poll(() => requestBody, { timeout: 15000 }).not.toBeNull();
+
+ // Regression guard for ZEPPELIN-6520: Password was bound to proxyLogin,
so the
+ // password overwrote the login and proxyPassword was always empty.
+ expect(requestBody!.proxyLogin).toBe(proxyLogin);
+ expect(requestBody!.proxyPassword).toBe(proxyPassword);
+ });
+});
diff --git
a/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html
b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html
index 072be772b2..607e4987f8 100644
---
a/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html
+++
b/zeppelin-web-angular/src/app/pages/workspace/interpreter/create-repository-modal/create-repository-modal.component.html
@@ -84,7 +84,7 @@
<nz-form-item>
<nz-form-label [nzSpan]="6">Password</nz-form-label>
<nz-form-control nz-col [nzSpan]="16">
- <input nz-input type="password" formControlName="proxyLogin"
placeholder="proxy password" />
+ <input nz-input type="password" formControlName="proxyPassword"
placeholder="proxy password" />
</nz-form-control>
</nz-form-item>
</form>