Skip to content
Open
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
65 changes: 65 additions & 0 deletions zeppelin-web-angular/e2e/models/interpreter-repository-modal.ts
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Loading