CrOS Settings: Convert apn detail dialog browser test to TS
Bug: b/270728282 Test: browser_tests --gtest_filter="*ApnDetailDialog*" Change-Id: I1ae97454cfb1fe7212aae8fe26ffb17ecd92293e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4908401 Commit-Queue: Ruma Kesh <rkesh@google.com> Reviewed-by: Wes Okuhara <wesokuhara@google.com> Cr-Commit-Position: refs/heads/main@{#1207351}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
80516eb1c8
commit
adb7d16865
ash/webui/common/resources/network
chrome
browser
resources
ash
settings
test
data
@ -2,4 +2,26 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
export {};
|
import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js';
|
||||||
|
import {ApnProperties} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
|
||||||
|
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
|
||||||
|
|
||||||
|
import {ApnDetailDialogMode} from './cellular_utils.js';
|
||||||
|
|
||||||
|
export class ApnDetailDialog extends I18nMixin
|
||||||
|
(PolymerElement) {
|
||||||
|
guid:
|
||||||
|
string;
|
||||||
|
apnProperties:
|
||||||
|
ApnProperties|undefined;
|
||||||
|
mode:
|
||||||
|
ApnDetailDialogMode;
|
||||||
|
apnList:
|
||||||
|
ApnProperties[];
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
'apn-detail-dialog': ApnDetailDialog;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -91,6 +91,7 @@ export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '/shared/settings/l
|
|||||||
export {ProfileInfo, ProfileInfoBrowserProxy, ProfileInfoBrowserProxyImpl} from '/shared/settings/people_page/profile_info_browser_proxy.js';
|
export {ProfileInfo, ProfileInfoBrowserProxy, ProfileInfoBrowserProxyImpl} from '/shared/settings/people_page/profile_info_browser_proxy.js';
|
||||||
export {PageStatus, StatusAction, StoredAccount, SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '/shared/settings/people_page/sync_browser_proxy.js';
|
export {PageStatus, StatusAction, StoredAccount, SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from '/shared/settings/people_page/sync_browser_proxy.js';
|
||||||
export {PrivacyPageBrowserProxyImpl, SecureDnsMode, SecureDnsUiManagementMode} from '/shared/settings/privacy_page/privacy_page_browser_proxy.js';
|
export {PrivacyPageBrowserProxyImpl, SecureDnsMode, SecureDnsUiManagementMode} from '/shared/settings/privacy_page/privacy_page_browser_proxy.js';
|
||||||
|
export {ApnDetailDialog} from 'chrome://resources/ash/common/network/apn_detail_dialog.js';
|
||||||
export {AppManagementFileHandlingItemElement} from 'chrome://resources/cr_components/app_management/file_handling_item.js';
|
export {AppManagementFileHandlingItemElement} from 'chrome://resources/cr_components/app_management/file_handling_item.js';
|
||||||
export {AppManagementSupportedLinksItemElement} from 'chrome://resources/cr_components/app_management/supported_links_item.js';
|
export {AppManagementSupportedLinksItemElement} from 'chrome://resources/cr_components/app_management/supported_links_item.js';
|
||||||
export {AppManagementToggleRowElement} from 'chrome://resources/cr_components/app_management/toggle_row.js';
|
export {AppManagementToggleRowElement} from 'chrome://resources/cr_components/app_management/toggle_row.js';
|
||||||
|
@ -22,7 +22,7 @@ build_webui_tests("build") {
|
|||||||
|
|
||||||
files = [
|
files = [
|
||||||
"apn_subpage_tests.js",
|
"apn_subpage_tests.js",
|
||||||
"apn_detail_dialog_tests.js",
|
"apn_detail_dialog_test.ts",
|
||||||
"cellular_networks_list_test.js",
|
"cellular_networks_list_test.js",
|
||||||
"cellular_roaming_toggle_button_test.js",
|
"cellular_roaming_toggle_button_test.js",
|
||||||
"crostini_extra_containers_subpage_test.js",
|
"crostini_extra_containers_subpage_test.js",
|
||||||
|
@ -0,0 +1,520 @@
|
|||||||
|
// Copyright 2022 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'chrome://os-settings/os_settings.js';
|
||||||
|
|
||||||
|
import {ApnDetailDialog, CrCheckboxElement, CrDialogElement, CrInputElement} from 'chrome://os-settings/os_settings.js';
|
||||||
|
import {ApnDetailDialogMode} from 'chrome://resources/ash/common/network/cellular_utils.js';
|
||||||
|
import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js';
|
||||||
|
import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js';
|
||||||
|
import {ApnAuthenticationType, ApnIpType, ApnProperties, ApnState, ApnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
|
||||||
|
import {NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
|
||||||
|
import {assertEquals, assertFalse, assertNull, assertStringContains, assertTrue} from 'chrome://webui-test/chai_assert.js';
|
||||||
|
import {FakeNetworkConfig} from 'chrome://webui-test/chromeos/fake_network_config_mojom.js';
|
||||||
|
import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
|
||||||
|
import {disableAnimationsAndTransitions} from 'chrome://webui-test/test_api.js';
|
||||||
|
import {eventToPromise} from 'chrome://webui-test/test_util.js';
|
||||||
|
|
||||||
|
const TEST_APN: ApnProperties = {
|
||||||
|
accessPointName: 'apn',
|
||||||
|
username: 'username',
|
||||||
|
password: 'password',
|
||||||
|
authentication: ApnAuthenticationType.kAutomatic,
|
||||||
|
ipType: ApnIpType.kAutomatic,
|
||||||
|
apnTypes: [ApnType.kDefault],
|
||||||
|
state: ApnState.kEnabled,
|
||||||
|
id: undefined,
|
||||||
|
language: undefined,
|
||||||
|
localizedName: undefined,
|
||||||
|
name: undefined,
|
||||||
|
attach: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
suite('<apn-detail-dialog>', () => {
|
||||||
|
let apnDetailDialog: ApnDetailDialog;
|
||||||
|
let mojoApi: FakeNetworkConfig;
|
||||||
|
|
||||||
|
function toggleAdvancedSettings(): void {
|
||||||
|
const advancedSettingsBtn =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#advancedSettingsBtn');
|
||||||
|
assertTrue(!!advancedSettingsBtn);
|
||||||
|
advancedSettingsBtn.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertElementEnabled(selector: string): void {
|
||||||
|
const element = apnDetailDialog.shadowRoot!.querySelector<
|
||||||
|
HTMLInputElement|HTMLSelectElement|HTMLButtonElement|CrCheckboxElement>(
|
||||||
|
selector);
|
||||||
|
assertTrue(!!element);
|
||||||
|
assertFalse(element.disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertAllInputsEnabled(): void {
|
||||||
|
assertElementEnabled('#apnInput');
|
||||||
|
assertElementEnabled('#usernameInput');
|
||||||
|
assertElementEnabled('#passwordInput');
|
||||||
|
assertElementEnabled('#authTypeDropDown');
|
||||||
|
assertElementEnabled('#apnDefaultTypeCheckbox');
|
||||||
|
assertElementEnabled('#apnAttachTypeCheckbox');
|
||||||
|
assertElementEnabled('#ipTypeDropDown');
|
||||||
|
}
|
||||||
|
|
||||||
|
suiteSetup(() => {
|
||||||
|
disableAnimationsAndTransitions();
|
||||||
|
mojoApi = new FakeNetworkConfig();
|
||||||
|
MojoInterfaceProviderImpl.getInstance().setMojoServiceRemoteForTest(
|
||||||
|
mojoApi);
|
||||||
|
});
|
||||||
|
|
||||||
|
teardown(() => {
|
||||||
|
apnDetailDialog.remove();
|
||||||
|
mojoApi.resetForTest();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function init(
|
||||||
|
mode?: ApnDetailDialogMode,
|
||||||
|
apnProperties?: ApnProperties): Promise<void> {
|
||||||
|
apnDetailDialog = document.createElement('apn-detail-dialog');
|
||||||
|
apnDetailDialog.guid = 'fake-guid';
|
||||||
|
apnDetailDialog.apnList = [TEST_APN];
|
||||||
|
apnDetailDialog.mode = mode || ApnDetailDialogMode.CREATE;
|
||||||
|
apnDetailDialog.apnProperties = apnProperties;
|
||||||
|
document.body.appendChild(apnDetailDialog);
|
||||||
|
await waitAfterNextRender(apnDetailDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
test('Element contains dialog', async () => {
|
||||||
|
await init();
|
||||||
|
const dialog = apnDetailDialog.shadowRoot!.querySelector('cr-dialog');
|
||||||
|
assertTrue(!!dialog);
|
||||||
|
assertTrue(dialog.open);
|
||||||
|
// Confirm that the dialog has the add apn title.
|
||||||
|
const apnDetailDialogTitle =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLElement>(
|
||||||
|
'#apnDetailDialogTitle');
|
||||||
|
assertTrue(!!apnDetailDialogTitle);
|
||||||
|
assertEquals(
|
||||||
|
apnDetailDialog.i18n('apnDetailAddApnDialogTitle'),
|
||||||
|
apnDetailDialogTitle.innerText);
|
||||||
|
assertTrue(!!apnDetailDialog.shadowRoot!.querySelector('#apnInput'));
|
||||||
|
assertTrue(!!apnDetailDialog.shadowRoot!.querySelector('#usernameInput'));
|
||||||
|
assertTrue(!!apnDetailDialog.shadowRoot!.querySelector('#passwordInput'));
|
||||||
|
|
||||||
|
assertTrue(
|
||||||
|
!!apnDetailDialog.shadowRoot!.querySelector('#authTypeDropDown'));
|
||||||
|
const defaultTypeCheckbox =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<CrCheckboxElement>(
|
||||||
|
'#apnDefaultTypeCheckbox');
|
||||||
|
assertTrue(!!defaultTypeCheckbox);
|
||||||
|
assertTrue(defaultTypeCheckbox.checked);
|
||||||
|
assertTrue(
|
||||||
|
!!apnDetailDialog.shadowRoot!.querySelector('#apnAttachTypeCheckbox'));
|
||||||
|
assertTrue(!!apnDetailDialog.shadowRoot!.querySelector('#ipTypeDropDown'));
|
||||||
|
assertTrue(
|
||||||
|
!!apnDetailDialog.shadowRoot!.querySelector('#apnDetailCancelBtn'));
|
||||||
|
assertTrue(
|
||||||
|
!!apnDetailDialog.shadowRoot!.querySelector('#apnDetailActionBtn'));
|
||||||
|
assertNull(apnDetailDialog.shadowRoot!.querySelector('#apnDoneBtn'));
|
||||||
|
assertEquals(
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#apnInput'),
|
||||||
|
apnDetailDialog.shadowRoot!.activeElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Clicking the cancel button fires the close event', async () => {
|
||||||
|
await init();
|
||||||
|
const closeEventPromise = eventToPromise('close', window);
|
||||||
|
const cancelBtn =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailCancelBtn');
|
||||||
|
assertTrue(!!cancelBtn);
|
||||||
|
|
||||||
|
cancelBtn.click();
|
||||||
|
await closeEventPromise;
|
||||||
|
const crDialogElement =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<CrDialogElement>(
|
||||||
|
'#apnDetailDialog');
|
||||||
|
assertTrue(!!crDialogElement);
|
||||||
|
assertFalse(crDialogElement.open);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Clicking on the advanced settings button expands/collapses section',
|
||||||
|
async () => {
|
||||||
|
await init();
|
||||||
|
const isAdvancedSettingShowing = () => {
|
||||||
|
const ironCollapseElement =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('iron-collapse');
|
||||||
|
assertTrue(!!ironCollapseElement);
|
||||||
|
return ironCollapseElement.opened;
|
||||||
|
};
|
||||||
|
assertFalse(isAdvancedSettingShowing());
|
||||||
|
toggleAdvancedSettings();
|
||||||
|
assertTrue(!!isAdvancedSettingShowing());
|
||||||
|
toggleAdvancedSettings();
|
||||||
|
assertFalse(isAdvancedSettingShowing());
|
||||||
|
toggleAdvancedSettings();
|
||||||
|
const assertOptions =
|
||||||
|
(expectedTextArray: string[],
|
||||||
|
optionNodes: NodeListOf<HTMLOptionElement>) => {
|
||||||
|
for (const [idx, expectedText] of expectedTextArray.entries()) {
|
||||||
|
assertTrue(!!optionNodes[idx]);
|
||||||
|
assertTrue(!!optionNodes[idx]!.text);
|
||||||
|
assertEquals(expectedText, optionNodes[idx]!.text);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const authTypeDropDown =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#authTypeDropDown');
|
||||||
|
assertTrue(!!authTypeDropDown);
|
||||||
|
const authTypeOptionNodes = authTypeDropDown.querySelectorAll('option');
|
||||||
|
assertEquals(3, authTypeOptionNodes.length);
|
||||||
|
// Note: We are also checking that the items appear in a certain order.
|
||||||
|
assertOptions(
|
||||||
|
[
|
||||||
|
apnDetailDialog.i18n('apnDetailTypeAuto'),
|
||||||
|
apnDetailDialog.i18n('apnDetailAuthTypePAP'),
|
||||||
|
apnDetailDialog.i18n('apnDetailAuthTypeCHAP'),
|
||||||
|
],
|
||||||
|
authTypeOptionNodes);
|
||||||
|
|
||||||
|
const ipTypeDropDown =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#ipTypeDropDown');
|
||||||
|
assertTrue(!!ipTypeDropDown);
|
||||||
|
const ipTypeOptionNodes =
|
||||||
|
ipTypeDropDown.querySelectorAll<HTMLOptionElement>('option');
|
||||||
|
assertEquals(4, ipTypeOptionNodes.length);
|
||||||
|
|
||||||
|
assertOptions(
|
||||||
|
[
|
||||||
|
apnDetailDialog.i18n('apnDetailTypeAuto'),
|
||||||
|
apnDetailDialog.i18n('apnDetailIpTypeIpv4'),
|
||||||
|
apnDetailDialog.i18n('apnDetailIpTypeIpv6'),
|
||||||
|
apnDetailDialog.i18n('apnDetailIpTypeIpv4_Ipv6'),
|
||||||
|
],
|
||||||
|
ipTypeOptionNodes);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Clicking on the add button calls createCustomApn', async () => {
|
||||||
|
await init();
|
||||||
|
const apnInput =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLInputElement>(
|
||||||
|
'#apnInput');
|
||||||
|
assertTrue(!!apnInput);
|
||||||
|
apnInput.value = TEST_APN.accessPointName;
|
||||||
|
const usernameInput =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLInputElement>(
|
||||||
|
'#usernameInput');
|
||||||
|
assertTrue(!!usernameInput);
|
||||||
|
usernameInput.value = TEST_APN.username!;
|
||||||
|
const passwordInput =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLInputElement>(
|
||||||
|
'#passwordInput');
|
||||||
|
assertTrue(!!passwordInput);
|
||||||
|
passwordInput.value = TEST_APN.password!;
|
||||||
|
|
||||||
|
assertAllInputsEnabled();
|
||||||
|
assertElementEnabled('#apnDetailCancelBtn');
|
||||||
|
let actionBtn =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailActionBtn');
|
||||||
|
assertTrue(!!actionBtn);
|
||||||
|
assertEquals(apnDetailDialog.i18n('add'), actionBtn.innerText);
|
||||||
|
|
||||||
|
// Add a network.
|
||||||
|
const network = OncMojo.getDefaultManagedProperties(
|
||||||
|
NetworkType.kCellular, apnDetailDialog.guid, apnDetailDialog.guid);
|
||||||
|
mojoApi.setManagedPropertiesForTest(network);
|
||||||
|
await flushTasks();
|
||||||
|
|
||||||
|
const properties = await mojoApi.getManagedProperties(apnDetailDialog.guid);
|
||||||
|
assertTrue(!!properties);
|
||||||
|
assertEquals(
|
||||||
|
undefined, properties.result.typeProperties.cellular!.customApnList);
|
||||||
|
|
||||||
|
actionBtn = apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailActionBtn');
|
||||||
|
assertTrue(!!actionBtn);
|
||||||
|
actionBtn.click();
|
||||||
|
await flushTasks();
|
||||||
|
await mojoApi.whenCalled('createCustomApn');
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
1, properties.result.typeProperties.cellular!.customApnList!.length);
|
||||||
|
|
||||||
|
const apn = properties.result.typeProperties.cellular!.customApnList![0];
|
||||||
|
assertTrue(!!apn);
|
||||||
|
assertEquals(TEST_APN.accessPointName, apn.accessPointName);
|
||||||
|
assertEquals(TEST_APN.username, apn.username);
|
||||||
|
assertEquals(TEST_APN.password, apn.password);
|
||||||
|
assertEquals(TEST_APN.authentication, apn.authentication);
|
||||||
|
assertEquals(TEST_APN.ipType, apn.ipType);
|
||||||
|
assertEquals(TEST_APN.apnTypes.length, apn.apnTypes.length);
|
||||||
|
assertEquals(TEST_APN.apnTypes[0], apn.apnTypes[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Setting mode to view changes buttons and fields', async () => {
|
||||||
|
const assertFieldDisabled = (selector: string) => {
|
||||||
|
const element = apnDetailDialog.shadowRoot!.querySelector<
|
||||||
|
HTMLInputElement|HTMLSelectElement|CrCheckboxElement>(selector);
|
||||||
|
assertTrue(!!element);
|
||||||
|
assertTrue(element.disabled);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set the dialog mode before opening the dialog so that the default focus
|
||||||
|
// can be tested.
|
||||||
|
await init(
|
||||||
|
/* mode= */ ApnDetailDialogMode.VIEW, /* apnProperties= */ TEST_APN);
|
||||||
|
|
||||||
|
const apnDetailDialogTitle =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLElement>(
|
||||||
|
'#apnDetailDialogTitle');
|
||||||
|
assertTrue(!!apnDetailDialogTitle);
|
||||||
|
assertEquals(
|
||||||
|
apnDetailDialog.i18n('apnDetailViewApnDialogTitle'),
|
||||||
|
apnDetailDialogTitle.innerText);
|
||||||
|
assertNull(
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#apnDetailCancelBtn'));
|
||||||
|
assertNull(
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#apnDetailActionBtn'));
|
||||||
|
const doneBtn =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDoneBtn');
|
||||||
|
assertTrue(!!doneBtn);
|
||||||
|
assertFalse(doneBtn.disabled);
|
||||||
|
assertFieldDisabled('#apnInput');
|
||||||
|
assertFieldDisabled('#usernameInput');
|
||||||
|
assertFieldDisabled('#passwordInput');
|
||||||
|
assertFieldDisabled('#authTypeDropDown');
|
||||||
|
assertFieldDisabled('#apnDefaultTypeCheckbox');
|
||||||
|
assertFieldDisabled('#apnAttachTypeCheckbox');
|
||||||
|
assertFieldDisabled('#ipTypeDropDown');
|
||||||
|
assertEquals(doneBtn, apnDetailDialog.shadowRoot!.activeElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Dialog input fields are validated', async () => {
|
||||||
|
await init();
|
||||||
|
const apnInputField =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<CrInputElement>('#apnInput');
|
||||||
|
assertTrue(!!apnInputField);
|
||||||
|
const actionButton =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailActionBtn');
|
||||||
|
assertTrue(!!actionButton);
|
||||||
|
// Case: After opening dialog before user input
|
||||||
|
assertFalse(apnInputField.invalid);
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
|
||||||
|
// Case : After valid user input
|
||||||
|
apnInputField.value = 'test';
|
||||||
|
assertFalse(apnInputField.invalid);
|
||||||
|
assertFalse(actionButton.disabled);
|
||||||
|
|
||||||
|
// Case : After Removing all user input no error state but button disabled
|
||||||
|
apnInputField.value = '';
|
||||||
|
assertFalse(apnInputField.invalid);
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
|
||||||
|
// Case : Non ascii user input
|
||||||
|
apnInputField.value = 'testμ';
|
||||||
|
assertTrue(apnInputField.invalid);
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertStringContains(apnInputField.value, 'μ');
|
||||||
|
|
||||||
|
// Case : longer than 63 characters then removing one character
|
||||||
|
apnInputField.value = 'a'.repeat(64);
|
||||||
|
assertTrue(apnInputField.invalid);
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertEquals(63, apnInputField.value.length);
|
||||||
|
apnInputField.value = apnInputField.value.slice(0, -1);
|
||||||
|
assertFalse(apnInputField.invalid);
|
||||||
|
assertFalse(actionButton.disabled);
|
||||||
|
|
||||||
|
// Case : longer than 63 non-ASCII characters
|
||||||
|
apnInputField.value = 'μ'.repeat(64);
|
||||||
|
assertTrue(apnInputField.invalid);
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Apn types are correctly validated in all modes', async () => {
|
||||||
|
await init();
|
||||||
|
const updateApnTypeCheckboxes =
|
||||||
|
(defaultType: boolean, attachType: boolean) => {
|
||||||
|
const apnDefaultTypeCheckbox =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<CrCheckboxElement>(
|
||||||
|
'#apnDefaultTypeCheckbox');
|
||||||
|
assertTrue(!!apnDefaultTypeCheckbox);
|
||||||
|
apnDefaultTypeCheckbox.checked = defaultType;
|
||||||
|
|
||||||
|
const apnAttachTypeCheckbox =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<CrCheckboxElement>(
|
||||||
|
'#apnAttachTypeCheckbox');
|
||||||
|
assertTrue(!!apnAttachTypeCheckbox);
|
||||||
|
apnAttachTypeCheckbox.checked = attachType;
|
||||||
|
};
|
||||||
|
|
||||||
|
toggleAdvancedSettings();
|
||||||
|
const getDefaultApnInfo = () =>
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#defaultApnRequiredInfo');
|
||||||
|
|
||||||
|
TEST_APN.id = '1';
|
||||||
|
const currentApn = {...TEST_APN};
|
||||||
|
currentApn.id = '2';
|
||||||
|
apnDetailDialog.set('apnList', [TEST_APN, currentApn]);
|
||||||
|
apnDetailDialog.set('apnProperties', currentApn);
|
||||||
|
|
||||||
|
const actionButton =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailActionBtn');
|
||||||
|
assertTrue(!!actionButton);
|
||||||
|
const apnInputField =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLInputElement>(
|
||||||
|
'#apnInput');
|
||||||
|
assertTrue(!!apnInputField);
|
||||||
|
apnInputField.value = 'valid_name';
|
||||||
|
|
||||||
|
// CREATE mode tests
|
||||||
|
apnDetailDialog.mode = ApnDetailDialogMode.CREATE;
|
||||||
|
TEST_APN.state = ApnState.kDisabled;
|
||||||
|
apnDetailDialog.set('apnList', [TEST_APN]);
|
||||||
|
|
||||||
|
// Case: Default APN type is checked
|
||||||
|
updateApnTypeCheckboxes(/* default= */ true, /* attach= */ false);
|
||||||
|
await flushTasks();
|
||||||
|
assertFalse(actionButton.disabled);
|
||||||
|
assertNull(getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: No enabled default APNs, default unchecked and attach is checked.
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertTrue(!!getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: No enabled default APNs and both unchecked.
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertNull(getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: Enabled default APNs, default unchecked and attach is checked.
|
||||||
|
TEST_APN.state = ApnState.kEnabled;
|
||||||
|
apnDetailDialog.set('apnList', [TEST_APN]);
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
||||||
|
await flushTasks();
|
||||||
|
assertFalse(actionButton.disabled);
|
||||||
|
assertNull(getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: Enabled default APNs and both unchecked.
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertNull(getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Edit mode tests
|
||||||
|
apnDetailDialog.set('mode', ApnDetailDialogMode.EDIT);
|
||||||
|
TEST_APN.apnTypes = [ApnType.kAttach];
|
||||||
|
currentApn.apnTypes = [ApnType.kDefault, ApnType.kAttach];
|
||||||
|
apnDetailDialog.set('apnList', [TEST_APN, currentApn]);
|
||||||
|
|
||||||
|
// Case: Default APN type is checked
|
||||||
|
updateApnTypeCheckboxes(/* default= */ true, /* attach= */ false);
|
||||||
|
await flushTasks();
|
||||||
|
assertFalse(actionButton.disabled);
|
||||||
|
assertNull(getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: User unchecks the default checkbox, APN being modified is the
|
||||||
|
// only default APN
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertTrue(!!getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: User unchecks both checkboxes, APN being modified is the
|
||||||
|
// only enabled default APN but there are other enabled attach APNs.
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertTrue(!!getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: User unchecks both checkboxes, APN being modified is the
|
||||||
|
// only enabled default APN and is the only enabled attachApn.
|
||||||
|
currentApn.apnTypes = [ApnType.kDefault, ApnType.kAttach];
|
||||||
|
apnDetailDialog.set('apnList', [currentApn]);
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertNull(getDefaultApnInfo());
|
||||||
|
|
||||||
|
// Case: User unchecks default APN type checkbox and checks the attach
|
||||||
|
// APN type checkbox, APN being modified is the only enabled default APN
|
||||||
|
// and there are no other enabled attach type APNs.
|
||||||
|
currentApn.apnTypes = [ApnType.kDefault];
|
||||||
|
apnDetailDialog.set('apnList', [currentApn]);
|
||||||
|
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
||||||
|
await flushTasks();
|
||||||
|
assertTrue(actionButton.disabled);
|
||||||
|
assertTrue(!!getDefaultApnInfo());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Setting mode to edit changes buttons and fields', async () => {
|
||||||
|
const apnWithId = TEST_APN;
|
||||||
|
apnWithId.id = '1';
|
||||||
|
apnWithId.apnTypes = [ApnType.kDefault];
|
||||||
|
|
||||||
|
// Set the dialog mode before opening the dialog so that the default focus
|
||||||
|
// can be tested.
|
||||||
|
await init(
|
||||||
|
/* mode= */ ApnDetailDialogMode.EDIT, /* apnProperties= */ apnWithId);
|
||||||
|
|
||||||
|
const apnDetailDialogTitle =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLElement>(
|
||||||
|
'#apnDetailDialogTitle');
|
||||||
|
assertTrue(!!apnDetailDialogTitle);
|
||||||
|
assertEquals(
|
||||||
|
apnDetailDialog.i18n('apnDetailEditApnDialogTitle'),
|
||||||
|
apnDetailDialogTitle.innerText);
|
||||||
|
assertElementEnabled('#apnDetailCancelBtn');
|
||||||
|
let button = apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailActionBtn');
|
||||||
|
assertTrue(!!button);
|
||||||
|
assertEquals(apnDetailDialog.i18n('save'), button.innerText);
|
||||||
|
assertNull(apnDetailDialog.shadowRoot!.querySelector('#apnDoneBtn'));
|
||||||
|
assertAllInputsEnabled();
|
||||||
|
|
||||||
|
// Case: clicking on the action button calls the correct method
|
||||||
|
const network = OncMojo.getDefaultManagedProperties(
|
||||||
|
NetworkType.kCellular, apnDetailDialog.guid, apnDetailDialog.guid);
|
||||||
|
mojoApi.setManagedPropertiesForTest(network);
|
||||||
|
await flushTasks();
|
||||||
|
const managedProperties =
|
||||||
|
await mojoApi.getManagedProperties(apnDetailDialog.guid);
|
||||||
|
assertTrue(!!managedProperties);
|
||||||
|
mojoApi.createCustomApn(apnDetailDialog.guid, apnWithId);
|
||||||
|
const newExpectedApn = 'modified';
|
||||||
|
const apnInputField =
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector<HTMLInputElement>(
|
||||||
|
'#apnInput');
|
||||||
|
assertTrue(!!apnInputField);
|
||||||
|
apnInputField.value = newExpectedApn;
|
||||||
|
button = apnDetailDialog.shadowRoot!.querySelector<HTMLButtonElement>(
|
||||||
|
'#apnDetailActionBtn');
|
||||||
|
assertTrue(!!button);
|
||||||
|
button.click();
|
||||||
|
await mojoApi.whenCalled('modifyCustomApn');
|
||||||
|
|
||||||
|
const apn =
|
||||||
|
managedProperties.result.typeProperties.cellular!.customApnList![0];
|
||||||
|
assertTrue(!!apn);
|
||||||
|
assertEquals(newExpectedApn, apn.accessPointName);
|
||||||
|
assertEquals(apnWithId.id, apn.id);
|
||||||
|
assertEquals(apnWithId.username, apn.username);
|
||||||
|
assertEquals(apnWithId.password, apn.password);
|
||||||
|
assertEquals(apnWithId.authentication, apn.authentication);
|
||||||
|
assertEquals(apnWithId.ipType, apn.ipType);
|
||||||
|
assertEquals(apnWithId.apnTypes.length, apn.apnTypes.length);
|
||||||
|
assertEquals(apnWithId.apnTypes[0], apn.apnTypes[0]);
|
||||||
|
assertEquals(
|
||||||
|
apnDetailDialog.shadowRoot!.querySelector('#apnInput'),
|
||||||
|
apnDetailDialog.shadowRoot!.activeElement);
|
||||||
|
});
|
||||||
|
});
|
@ -1,461 +0,0 @@
|
|||||||
// Copyright 2022 The Chromium Authors
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
import 'chrome://os-settings/strings.m.js';
|
|
||||||
import 'chrome://resources/ash/common/network/apn_detail_dialog.js';
|
|
||||||
|
|
||||||
import {ApnDetailDialog} from 'chrome://resources/ash/common/network/apn_detail_dialog.js';
|
|
||||||
import {ApnDetailDialogMode} from 'chrome://resources/ash/common/network/cellular_utils.js';
|
|
||||||
import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js';
|
|
||||||
import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js';
|
|
||||||
import {ApnAuthenticationType, ApnIpType, ApnProperties, ApnState, ApnType, ManagedProperties} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js';
|
|
||||||
import {NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js';
|
|
||||||
import {FakeNetworkConfig} from 'chrome://test/chromeos/fake_network_config_mojom.js';
|
|
||||||
import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
|
|
||||||
import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js';
|
|
||||||
import {eventToPromise} from 'chrome://webui-test/test_util.js';
|
|
||||||
|
|
||||||
/** @type {!ApnProperties} */
|
|
||||||
const TEST_APN = {
|
|
||||||
accessPointName: 'apn',
|
|
||||||
username: 'username',
|
|
||||||
password: 'password',
|
|
||||||
authentication: ApnAuthenticationType.kAutomatic,
|
|
||||||
ipType: ApnIpType.kAutomatic,
|
|
||||||
apnTypes: [ApnType.kDefault],
|
|
||||||
state: ApnState.kEnabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
suite('ApnDetailDialog', function() {
|
|
||||||
/** @type {ApnDetailDialog} */
|
|
||||||
let apnDetailDialog = null;
|
|
||||||
|
|
||||||
let mojoApi_ = null;
|
|
||||||
|
|
||||||
async function toggleAdvancedSettings() {
|
|
||||||
const advancedSettingsBtn =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#advancedSettingsBtn');
|
|
||||||
assertTrue(!!advancedSettingsBtn);
|
|
||||||
advancedSettingsBtn.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} selector
|
|
||||||
*/
|
|
||||||
function assertElementEnabled(selector) {
|
|
||||||
const element = apnDetailDialog.shadowRoot.querySelector(selector);
|
|
||||||
assertTrue(!!element);
|
|
||||||
assertFalse(element.disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertAllInputsEnabled() {
|
|
||||||
assertElementEnabled('#apnInput');
|
|
||||||
assertElementEnabled('#usernameInput');
|
|
||||||
assertElementEnabled('#passwordInput');
|
|
||||||
assertElementEnabled('#authTypeDropDown');
|
|
||||||
assertElementEnabled('#apnDefaultTypeCheckbox');
|
|
||||||
assertElementEnabled('#apnAttachTypeCheckbox');
|
|
||||||
assertElementEnabled('#ipTypeDropDown');
|
|
||||||
}
|
|
||||||
|
|
||||||
setup(async function() {
|
|
||||||
testing.Test.disableAnimationsAndTransitions();
|
|
||||||
PolymerTest.clearBody();
|
|
||||||
mojoApi_ = new FakeNetworkConfig();
|
|
||||||
MojoInterfaceProviderImpl.getInstance().remote_ = mojoApi_;
|
|
||||||
apnDetailDialog = document.createElement('apn-detail-dialog');
|
|
||||||
apnDetailDialog.guid = 'fake-guid';
|
|
||||||
apnDetailDialog.apnList = [TEST_APN];
|
|
||||||
});
|
|
||||||
|
|
||||||
teardown(function() {
|
|
||||||
return flushTasks().then(() => {
|
|
||||||
apnDetailDialog.remove();
|
|
||||||
apnDetailDialog = null;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function init() {
|
|
||||||
document.body.appendChild(apnDetailDialog);
|
|
||||||
return waitAfterNextRender(apnDetailDialog);
|
|
||||||
}
|
|
||||||
|
|
||||||
test('Element contains dialog', async function() {
|
|
||||||
await init();
|
|
||||||
const dialog = apnDetailDialog.shadowRoot.querySelector('cr-dialog');
|
|
||||||
assertTrue(!!dialog);
|
|
||||||
assertTrue(dialog.open);
|
|
||||||
// Confirm that the dialog has the add apn title.
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.i18n('apnDetailAddApnDialogTitle'),
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailDialogTitle')
|
|
||||||
.innerText);
|
|
||||||
assertTrue(!!apnDetailDialog.shadowRoot.querySelector('#apnInput'));
|
|
||||||
assertTrue(!!apnDetailDialog.shadowRoot.querySelector('#usernameInput'));
|
|
||||||
assertTrue(!!apnDetailDialog.shadowRoot.querySelector('#passwordInput'));
|
|
||||||
|
|
||||||
assertTrue(!!apnDetailDialog.shadowRoot.querySelector('#authTypeDropDown'));
|
|
||||||
const defaultTypeCheckbox =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDefaultTypeCheckbox');
|
|
||||||
assertTrue(!!defaultTypeCheckbox);
|
|
||||||
assertTrue(defaultTypeCheckbox.checked);
|
|
||||||
assertTrue(
|
|
||||||
!!apnDetailDialog.shadowRoot.querySelector('#apnAttachTypeCheckbox'));
|
|
||||||
assertTrue(!!apnDetailDialog.shadowRoot.querySelector('#ipTypeDropDown'));
|
|
||||||
assertTrue(
|
|
||||||
!!apnDetailDialog.shadowRoot.querySelector('#apnDetailCancelBtn'));
|
|
||||||
assertTrue(
|
|
||||||
!!apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn'));
|
|
||||||
assertFalse(!!apnDetailDialog.shadowRoot.querySelector('#apnDoneBtn'));
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnInput'),
|
|
||||||
apnDetailDialog.shadowRoot.activeElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Clicking the cancel button fires the close event', async function() {
|
|
||||||
await init();
|
|
||||||
const closeEventPromise = eventToPromise('close', window);
|
|
||||||
const cancelBtn =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailCancelBtn');
|
|
||||||
assertTrue(!!cancelBtn);
|
|
||||||
|
|
||||||
cancelBtn.click();
|
|
||||||
await closeEventPromise;
|
|
||||||
assertFalse(!!apnDetailDialog.$.apnDetailDialog.open);
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
|
||||||
'Clicking on the advanced settings button expands/collapses section',
|
|
||||||
async function() {
|
|
||||||
await init();
|
|
||||||
const isAdvancedSettingShowing = () =>
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('iron-collapse').opened;
|
|
||||||
assertFalse(!!isAdvancedSettingShowing());
|
|
||||||
toggleAdvancedSettings();
|
|
||||||
assertTrue(!!isAdvancedSettingShowing());
|
|
||||||
toggleAdvancedSettings();
|
|
||||||
assertFalse(!!isAdvancedSettingShowing());
|
|
||||||
toggleAdvancedSettings();
|
|
||||||
const assertOptions = (expectedTextArray, optionNodes) => {
|
|
||||||
for (const [idx, expectedText] of expectedTextArray.entries()) {
|
|
||||||
assertTrue(!!optionNodes[idx]);
|
|
||||||
assertTrue(!!optionNodes[idx].text);
|
|
||||||
assertEquals(expectedText, optionNodes[idx].text);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const authTypeDropDown =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#authTypeDropDown');
|
|
||||||
assertTrue(!!authTypeDropDown);
|
|
||||||
const authTypeOptionNodes = authTypeDropDown.querySelectorAll('option');
|
|
||||||
assertEquals(3, authTypeOptionNodes.length);
|
|
||||||
// Note: We are also checking that the items appear in a certain order.
|
|
||||||
assertOptions(
|
|
||||||
[
|
|
||||||
apnDetailDialog.i18n('apnDetailTypeAuto'),
|
|
||||||
apnDetailDialog.i18n('apnDetailAuthTypePAP'),
|
|
||||||
apnDetailDialog.i18n('apnDetailAuthTypeCHAP'),
|
|
||||||
],
|
|
||||||
authTypeOptionNodes);
|
|
||||||
|
|
||||||
const ipTypeDropDown =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#ipTypeDropDown');
|
|
||||||
assertTrue(!!ipTypeDropDown);
|
|
||||||
const ipTypeOptionNodes = ipTypeDropDown.querySelectorAll('option');
|
|
||||||
assertEquals(4, ipTypeOptionNodes.length);
|
|
||||||
|
|
||||||
assertOptions(
|
|
||||||
[
|
|
||||||
apnDetailDialog.i18n('apnDetailTypeAuto'),
|
|
||||||
apnDetailDialog.i18n('apnDetailIpTypeIpv4'),
|
|
||||||
apnDetailDialog.i18n('apnDetailIpTypeIpv6'),
|
|
||||||
apnDetailDialog.i18n('apnDetailIpTypeIpv4_Ipv6'),
|
|
||||||
],
|
|
||||||
ipTypeOptionNodes);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Clicking on the add button calls createCustomApn', async () => {
|
|
||||||
await init();
|
|
||||||
apnDetailDialog.$.apnInput.value = TEST_APN.accessPointName;
|
|
||||||
apnDetailDialog.$.usernameInput.value = TEST_APN.username;
|
|
||||||
apnDetailDialog.$.passwordInput.value = TEST_APN.password;
|
|
||||||
|
|
||||||
assertAllInputsEnabled();
|
|
||||||
assertElementEnabled('#apnDetailCancelBtn');
|
|
||||||
assertElementEnabled('#apnDetailActionBtn');
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.i18n('add'),
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn')
|
|
||||||
.innerText);
|
|
||||||
|
|
||||||
// Add a network.
|
|
||||||
const network = OncMojo.getDefaultManagedProperties(
|
|
||||||
NetworkType.kCellular, apnDetailDialog.guid);
|
|
||||||
mojoApi_.setManagedPropertiesForTest(network);
|
|
||||||
await flushTasks();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {!ManagedProperties}
|
|
||||||
*/
|
|
||||||
const properties =
|
|
||||||
await mojoApi_.getManagedProperties(apnDetailDialog.guid);
|
|
||||||
assertTrue(!!properties);
|
|
||||||
assertFalse(!!properties.result.typeProperties.cellular.customApnList);
|
|
||||||
|
|
||||||
const actionBtn =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn');
|
|
||||||
assertTrue(!!actionBtn);
|
|
||||||
actionBtn.click();
|
|
||||||
await flushTasks();
|
|
||||||
await mojoApi_.whenCalled('createCustomApn');
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
1, properties.result.typeProperties.cellular.customApnList.length);
|
|
||||||
|
|
||||||
const apn = properties.result.typeProperties.cellular.customApnList[0];
|
|
||||||
assertEquals(TEST_APN.accessPointName, apn.accessPointName);
|
|
||||||
assertEquals(TEST_APN.username, apn.username);
|
|
||||||
assertEquals(TEST_APN.password, apn.password);
|
|
||||||
assertEquals(TEST_APN.authentication, apn.authentication);
|
|
||||||
assertEquals(TEST_APN.ipType, apn.ipType);
|
|
||||||
assertEquals(TEST_APN.apnTypes.length, apn.apnTypes.length);
|
|
||||||
assertEquals(TEST_APN.apnTypes[0], apn.apnTypes[0]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Setting mode to view changes buttons and fields', async () => {
|
|
||||||
const assertFieldDisabled = (selector) => {
|
|
||||||
const element = apnDetailDialog.shadowRoot.querySelector(selector);
|
|
||||||
assertTrue(!!element);
|
|
||||||
assertTrue(element.disabled);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Set the dialog mode before opening the dialog so that the default focus
|
|
||||||
// can be tested.
|
|
||||||
apnDetailDialog.mode = ApnDetailDialogMode.VIEW;
|
|
||||||
apnDetailDialog.apnProperties = TEST_APN;
|
|
||||||
|
|
||||||
await init();
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.i18n('apnDetailViewApnDialogTitle'),
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailDialogTitle')
|
|
||||||
.innerText);
|
|
||||||
assertFalse(
|
|
||||||
!!apnDetailDialog.shadowRoot.querySelector('#apnDetailCancelBtn'));
|
|
||||||
assertFalse(
|
|
||||||
!!apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn'));
|
|
||||||
const doneBtn = apnDetailDialog.shadowRoot.querySelector('#apnDoneBtn');
|
|
||||||
assertTrue(!!doneBtn);
|
|
||||||
assertFalse(doneBtn.disabled);
|
|
||||||
assertFieldDisabled('#apnInput');
|
|
||||||
assertFieldDisabled('#usernameInput');
|
|
||||||
assertFieldDisabled('#passwordInput');
|
|
||||||
assertFieldDisabled('#authTypeDropDown');
|
|
||||||
assertFieldDisabled('#apnDefaultTypeCheckbox');
|
|
||||||
assertFieldDisabled('#apnAttachTypeCheckbox');
|
|
||||||
assertFieldDisabled('#ipTypeDropDown');
|
|
||||||
assertEquals(doneBtn, apnDetailDialog.shadowRoot.activeElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Dialog input fields are validated', async () => {
|
|
||||||
await init();
|
|
||||||
const apnInputField = apnDetailDialog.$.apnInput;
|
|
||||||
const actionButton =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn');
|
|
||||||
assertTrue(!!actionButton);
|
|
||||||
// Case: After opening dialog before user input
|
|
||||||
assertFalse(!!apnInputField.invalid);
|
|
||||||
assertTrue(!!actionButton.disabled);
|
|
||||||
|
|
||||||
// Case : After valid user input
|
|
||||||
apnInputField.value = 'test';
|
|
||||||
assertFalse(!!apnInputField.invalid);
|
|
||||||
assertFalse(!!actionButton.disabled);
|
|
||||||
|
|
||||||
// Case : After Removing all user input no error state but button disabled
|
|
||||||
apnInputField.value = '';
|
|
||||||
assertFalse(!!apnInputField.invalid);
|
|
||||||
assertTrue(!!actionButton.disabled);
|
|
||||||
|
|
||||||
// Case : Non ascii user input
|
|
||||||
apnInputField.value = 'testμ';
|
|
||||||
assertTrue(!!apnInputField.invalid);
|
|
||||||
assertTrue(!!actionButton.disabled);
|
|
||||||
assertTrue(apnInputField.value.includes('μ'));
|
|
||||||
|
|
||||||
// Case : longer than 63 characters then removing one character
|
|
||||||
apnInputField.value = 'a'.repeat(64);
|
|
||||||
assertTrue(!!apnInputField.invalid);
|
|
||||||
assertTrue(!!actionButton.disabled);
|
|
||||||
assertFalse(apnInputField.value.length > 63);
|
|
||||||
apnInputField.value = apnInputField.value.slice(0, -1);
|
|
||||||
assertFalse(!!apnInputField.invalid);
|
|
||||||
assertFalse(!!actionButton.disabled);
|
|
||||||
|
|
||||||
// Case : longer than 63 non-ASCII characters
|
|
||||||
apnInputField.value = 'μ'.repeat(64);
|
|
||||||
assertTrue(!!apnInputField.invalid);
|
|
||||||
assertTrue(!!actionButton.disabled);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Apn types are correctly validated in all modes', async () => {
|
|
||||||
await init();
|
|
||||||
const updateApnTypeCheckboxes = (defaultType, attachType) => {
|
|
||||||
apnDetailDialog.$.apnDefaultTypeCheckbox.checked = defaultType;
|
|
||||||
apnDetailDialog.$.apnAttachTypeCheckbox.checked = attachType;
|
|
||||||
};
|
|
||||||
await toggleAdvancedSettings();
|
|
||||||
const getDefaultApnInfo = () => {
|
|
||||||
return apnDetailDialog.shadowRoot.querySelector(
|
|
||||||
'#defaultApnRequiredInfo');
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_APN.id = '1';
|
|
||||||
const currentApn = /** @type {ApnProperties} */ ({});
|
|
||||||
Object.assign(currentApn, TEST_APN);
|
|
||||||
currentApn.id = '2';
|
|
||||||
apnDetailDialog.apnList = [TEST_APN, currentApn];
|
|
||||||
apnDetailDialog.apnProperties = currentApn;
|
|
||||||
|
|
||||||
const actionButton =
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn');
|
|
||||||
apnDetailDialog.$.apnInput.value = 'valid_name';
|
|
||||||
|
|
||||||
// CREATE mode tests
|
|
||||||
apnDetailDialog.mode = ApnDetailDialogMode.CREATE;
|
|
||||||
TEST_APN.state = ApnState.kDisabled;
|
|
||||||
apnDetailDialog.apnList = [TEST_APN];
|
|
||||||
|
|
||||||
// Case: Default APN type is checked
|
|
||||||
updateApnTypeCheckboxes(/* default= */ true, /* attach= */ false);
|
|
||||||
await flushTasks();
|
|
||||||
assertFalse(actionButton.disabled);
|
|
||||||
assertFalse(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: No enabled default APNs, default unchecked and attach is checked.
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertTrue(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: No enabled default APNs and both unchecked.
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertFalse(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: Enabled default APNs, default unchecked and attach is checked.
|
|
||||||
TEST_APN.state = ApnState.kEnabled;
|
|
||||||
apnDetailDialog.apnList = [TEST_APN];
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
|
||||||
await flushTasks();
|
|
||||||
assertFalse(actionButton.disabled);
|
|
||||||
assertFalse(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: Enabled default APNs and both unchecked.
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertFalse(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Edit mode tests
|
|
||||||
apnDetailDialog.mode = ApnDetailDialogMode.EDIT;
|
|
||||||
TEST_APN.apnTypes = [ApnType.kAttach];
|
|
||||||
currentApn.apnTypes = [ApnType.kDefault, ApnType.kAttach];
|
|
||||||
apnDetailDialog.apnList = [TEST_APN, currentApn];
|
|
||||||
|
|
||||||
// Case: Default APN type is checked
|
|
||||||
updateApnTypeCheckboxes(/* default= */ true, /* attach= */ false);
|
|
||||||
await flushTasks();
|
|
||||||
assertFalse(actionButton.disabled);
|
|
||||||
assertFalse(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: User unchecks the default checkbox, APN being modified is the
|
|
||||||
// only default APN
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertTrue(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: User unchecks both checkboxes, APN being modified is the
|
|
||||||
// only enabled default APN but there are other enabled attach APNs.
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertTrue(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: User unchecks both checkboxes, APN being modified is the
|
|
||||||
// only enabled default APN and is the only enabled attachApn.
|
|
||||||
currentApn.apnTypes = [ApnType.kDefault, ApnType.kAttach];
|
|
||||||
apnDetailDialog.apnList = [currentApn];
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ false);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertFalse(!!getDefaultApnInfo());
|
|
||||||
|
|
||||||
// Case: User unchecks default APN type checkbox and checks the attach
|
|
||||||
// APN type checkbox, APN being modified is the only enabled default APN
|
|
||||||
// and there are no other enabled attach type APNs.
|
|
||||||
currentApn.apnTypes = [ApnType.kDefault];
|
|
||||||
apnDetailDialog.apnList = [currentApn];
|
|
||||||
updateApnTypeCheckboxes(/* default= */ false, /* attach= */ true);
|
|
||||||
await flushTasks();
|
|
||||||
assertTrue(actionButton.disabled);
|
|
||||||
assertTrue(!!getDefaultApnInfo());
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Setting mode to edit changes buttons and fields', async () => {
|
|
||||||
const apnWithId = TEST_APN;
|
|
||||||
apnWithId.id = '1';
|
|
||||||
apnWithId.apnTypes = [ApnType.kDefault];
|
|
||||||
|
|
||||||
// Set the dialog mode before opening the dialog so that the default focus
|
|
||||||
// can be tested.
|
|
||||||
apnDetailDialog.mode = ApnDetailDialogMode.EDIT;
|
|
||||||
apnDetailDialog.apnProperties = apnWithId;
|
|
||||||
|
|
||||||
await init();
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.i18n('apnDetailEditApnDialogTitle'),
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailDialogTitle')
|
|
||||||
.innerText);
|
|
||||||
assertElementEnabled('#apnDetailCancelBtn');
|
|
||||||
assertElementEnabled('#apnDetailActionBtn');
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.i18n('save'),
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn')
|
|
||||||
.innerText);
|
|
||||||
assertFalse(!!apnDetailDialog.shadowRoot.querySelector('#apnDoneBtn'));
|
|
||||||
assertAllInputsEnabled();
|
|
||||||
|
|
||||||
// Case: clicking on the action button calls the correct method
|
|
||||||
const network = OncMojo.getDefaultManagedProperties(
|
|
||||||
NetworkType.kCellular, apnDetailDialog.guid);
|
|
||||||
mojoApi_.setManagedPropertiesForTest(network);
|
|
||||||
await flushTasks();
|
|
||||||
const managedProperties =
|
|
||||||
await mojoApi_.getManagedProperties(apnDetailDialog.guid);
|
|
||||||
assertTrue(!!managedProperties);
|
|
||||||
managedProperties.result.typeProperties.cellular = {
|
|
||||||
customApnList: [apnWithId],
|
|
||||||
};
|
|
||||||
const newExpectedApn = 'modified';
|
|
||||||
apnDetailDialog.$.apnInput.value = newExpectedApn;
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnDetailActionBtn').click();
|
|
||||||
await mojoApi_.whenCalled('modifyCustomApn');
|
|
||||||
|
|
||||||
const apn =
|
|
||||||
managedProperties.result.typeProperties.cellular.customApnList[0];
|
|
||||||
assertEquals(newExpectedApn, apn.accessPointName);
|
|
||||||
assertEquals(apnWithId.id, apn.id);
|
|
||||||
assertEquals(apnWithId.username, apn.username);
|
|
||||||
assertEquals(apnWithId.password, apn.password);
|
|
||||||
assertEquals(apnWithId.authentication, apn.authentication);
|
|
||||||
assertEquals(apnWithId.ipType, apn.ipType);
|
|
||||||
assertEquals(apnWithId.apnTypes.length, apn.apnTypes.length);
|
|
||||||
assertEquals(apnWithId.apnTypes[0], apn.apnTypes[0]);
|
|
||||||
assertEquals(
|
|
||||||
apnDetailDialog.shadowRoot.querySelector('#apnInput'),
|
|
||||||
apnDetailDialog.shadowRoot.activeElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -205,7 +205,7 @@ TEST_F('OSSettingsCrostiniExtraContainerPageTest', 'AllJsTests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
[['AboutPage', 'os_about_page_tests.js'],
|
[['AboutPage', 'os_about_page_tests.js'],
|
||||||
['ApnDetailDialog', 'apn_detail_dialog_tests.js'],
|
['ApnDetailDialog', 'apn_detail_dialog_test.js'],
|
||||||
// TODO(crbug.com/1455866): Enable the ApnSubpage test.
|
// TODO(crbug.com/1455866): Enable the ApnSubpage test.
|
||||||
// [
|
// [
|
||||||
// 'ApnSubpage', 'apn_subpage_tests.js',
|
// 'ApnSubpage', 'apn_subpage_tests.js',
|
||||||
|
Reference in New Issue
Block a user