/** * Test for LoginAutoComplete.isProbablyANewPasswordField. */ "use strict"; const LoginAutoComplete = Cc[ "@mozilla.org/login-manager/autocompletesearch;1" ].getService(Ci.nsILoginAutoCompleteSearch).wrappedJSObject; // TODO: create a fake window for the test document to pass fathom.isVisible check. // We should consider moving these tests to mochitest because many fathom // signals rely on visibility, position, etc., of the test element (See Bug 1712699), // which is not supported in xpcshell-test. function makeDocumentVisibleToFathom(doc) { let win = { getComputedStyle() { return { overflow: "visible", visibility: "visible", }; }, }; Object.defineProperty(doc, "defaultView", { value: win, }); return doc; } function labelledByDocument() { let doc = MockDocument.createTestDocument( "http://localhost:8080/test/", `
` ); let div = doc.querySelector("div"); // Put the div contents inside shadow DOM. div.attachShadow({ mode: "open" }).append(...div.children); return doc; } const LABELLEDBY_SHADOW_TESTCASE = labelledByDocument(); const TESTCASES = [ // Note there is no test case for `` // since isProbablyANewPasswordField explicitly does not run in that case. { description: "Basic login form", document: `

Sign in

`, expectedResult: [false], }, { description: "Basic registration form", document: `

Create account

`, expectedResult: [true], }, { // TODO: Add to "confirm-passowrd" password field so fathom can recognize it // as a new password field. Currently, the fathom rules don't really work well in xpcshell-test // because signals rely on visibility, position doesn't work. If we move this test to mochitest, we should // be able to remove the interim solution (See Bug 1712699). description: "Basic password change form", document: `

Change password

`, expectedResult: [false, true, true], }, { description: "Basic login 'form' without a form element", document: `

Sign in

`, expectedResult: [false], }, { description: "Basic registration 'form' without a form element", document: `

Create account

`, expectedResult: [true], }, { description: "Basic password change 'form' without a form element", document: `

Change password

`, expectedResult: [false, true, true], }, { description: "Password field with aria-labelledby inside shadow DOM", document: LABELLEDBY_SHADOW_TESTCASE, inputs: LABELLEDBY_SHADOW_TESTCASE.querySelector( "div" ).shadowRoot.querySelectorAll("input[type='password']"), expectedResult: [false], }, ]; add_task(async function test_returns_false_when_pref_disabled() { const threshold = Services.prefs.getStringPref( NEW_PASSWORD_HEURISTIC_ENABLED_PREF ); info("Temporarily disabling new-password heuristic pref"); Services.prefs.setStringPref(NEW_PASSWORD_HEURISTIC_ENABLED_PREF, "-1"); // Use registration form test case, where we know it should return true if enabled const testcase = TESTCASES[1]; info("Starting testcase: " + testcase.description); const document = Document.isInstance(testcase.document) ? testcase.document : MockDocument.createTestDocument( "http://localhost:8080/test/", testcase.document ); for (let [i, input] of testcase.inputs || document.querySelectorAll(`input[type="password"]`).entries()) { const result = LoginAutoComplete.isProbablyANewPasswordField(input); Assert.strictEqual( result, false, `When the pref is set to disable, the result is always false, e.g. for the testcase, ${testcase.description} ${i}` ); } info("Re-enabling new-password heuristic pref"); Services.prefs.setStringPref(NEW_PASSWORD_HEURISTIC_ENABLED_PREF, threshold); }); for (let testcase of TESTCASES) { info("Sanity checking the testcase: " + testcase.description); (function () { add_task(async function () { info("Starting testcase: " + testcase.description); let document = Document.isInstance(testcase.document) ? testcase.document : MockDocument.createTestDocument( "http://localhost:8080/test/", testcase.document ); document = makeDocumentVisibleToFathom(document); const results = []; for (let input of testcase.inputs || document.querySelectorAll(`input[type="password"]`)) { const result = LoginAutoComplete.isProbablyANewPasswordField(input); results.push(result); } for (let i = 0; i < testcase.expectedResult.length; i++) { let expectedResult = testcase.expectedResult[i]; Assert.strictEqual( results[i], expectedResult, `In the test case, ${testcase.description}, check if password field #${i} is a new password field.` ); } }); })(); }