Skip to content

Commit

Permalink
[7.x] Add Login Selector functional tests. (#66709)
Browse files Browse the repository at this point in the history
# Conflicts:
#	x-pack/scripts/functional_tests.js
  • Loading branch information
azasypkin authored May 15, 2020
1 parent 3a4c86b commit aa6785e
Show file tree
Hide file tree
Showing 20 changed files with 552 additions and 131 deletions.
6 changes: 3 additions & 3 deletions test/functional/page_objects/common_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
const find = getService('find');
const globalNav = getService('globalNav');
const testSubjects = getService('testSubjects');
const PageObjects = getPageObjects(['shield']);
const PageObjects = getPageObjects(['login']);

const defaultTryTimeout = config.get('timeouts.try');
const defaultFindTimeout = config.get('timeouts.find');
Expand Down Expand Up @@ -76,12 +76,12 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
if (loginPage && !wantedLoginPage) {
log.debug('Found login page');
if (config.get('security.disableTestUser')) {
await PageObjects.shield.login(
await PageObjects.login.login(
config.get('servers.kibana.username'),
config.get('servers.kibana.password')
);
} else {
await PageObjects.shield.login('test_user', 'changeme');
await PageObjects.login.login('test_user', 'changeme');
}

await find.byCssSelector(
Expand Down
4 changes: 2 additions & 2 deletions test/functional/page_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { HomePageProvider } from './home_page';
import { NewsfeedPageProvider } from './newsfeed_page';
import { SettingsPageProvider } from './settings_page';
import { SharePageProvider } from './share_page';
import { ShieldPageProvider } from './shield_page';
import { LoginPageProvider } from './login_page';
import { TimePickerProvider } from './time_picker';
import { TimelionPageProvider } from './timelion_page';
import { VisualBuilderPageProvider } from './visual_builder_page';
Expand All @@ -51,7 +51,7 @@ export const pageObjects = {
newsfeed: NewsfeedPageProvider,
settings: SettingsPageProvider,
share: SharePageProvider,
shield: ShieldPageProvider,
login: LoginPageProvider,
timelion: TimelionPageProvider,
timePicker: TimePickerProvider,
visualBuilder: VisualBuilderPageProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,16 @@

import { FtrProviderContext } from '../ftr_provider_context';

export function ShieldPageProvider({ getService }: FtrProviderContext) {
export function LoginPageProvider({ getService }: FtrProviderContext) {
const testSubjects = getService('testSubjects');

class ShieldPage {
class LoginPage {
async login(user: string, pwd: string) {
await testSubjects.setValue('loginUsername', user);
await testSubjects.setValue('loginPassword', pwd);
await testSubjects.click('loginSubmit');
}
}

return new ShieldPage();
return new LoginPage();
}
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export class LoginForm extends Component<Props, State> {
{this.props.selector.providers.map(provider => (
<button
key={provider.name}
data-test-subj={`loginCard-${provider.type}/${provider.name}`}
disabled={!this.isLoadingState(LoadingStateType.None)}
onClick={() =>
provider.usesLoginForm
Expand Down
3 changes: 2 additions & 1 deletion x-pack/scripts/functional_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ require('@kbn/test').runTestsCli([
require.resolve('../test/reporting/configs/generate_api'),
require.resolve('../test/functional/config.js'),
require.resolve('../test/functional_with_es_ssl/config.ts'),
require.resolve('../test/functional/config_security_basic.js'),
require.resolve('../test/functional/config_security_basic.ts'),
require.resolve('../test/functional/config_security_trial.ts'),
require.resolve('../test/api_integration/config_security_basic.js'),
require.resolve('../test/api_integration/config.js'),
require.resolve('../test/alerting_api_integration/basic/config.ts'),
Expand Down
2 changes: 1 addition & 1 deletion x-pack/test/functional/apps/security/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
});

it('logging out of a non-default space redirects to the login page at the server root', async () => {
await PageObjects.security.login(null, null, {
await PageObjects.security.login(undefined, undefined, {
expectSpaceSelector: true,
});

Expand Down
15 changes: 15 additions & 0 deletions x-pack/test/functional/apps/security/trial_license/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { FtrProviderContext } from '../../../ftr_provider_context';

export default function({ loadTestFile }: FtrProviderContext) {
describe('security app - trial license', function() {
this.tags('ciGroup4');

loadTestFile(require.resolve('./login_selector'));
});
}
123 changes: 123 additions & 0 deletions x-pack/test/functional/apps/security/trial_license/login_selector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import expect from '@kbn/expect';
import { parse } from 'url';
import { USERS_PATH } from '../../../../../plugins/security/public/management/management_urls';
import { FtrProviderContext } from '../../../ftr_provider_context';

export default function({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const PageObjects = getPageObjects(['security', 'common']);

describe('Login Selector', function() {
this.tags('includeFirefox');

before(async () => {
await getService('esSupertest')
.post('/_security/role_mapping/saml1')
.send({ roles: ['superuser'], enabled: true, rules: { field: { 'realm.name': 'saml1' } } })
.expect(200);

await esArchiver.load('empty_kibana');
await PageObjects.security.forceLogout();
});

after(async () => {
await esArchiver.unload('empty_kibana');
});

beforeEach(async () => {
await browser.get(`${PageObjects.common.getHostPort()}/login`);
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();
});

afterEach(async () => {
await PageObjects.security.forceLogout();
});

it('can login with Login Form preserving original URL', async () => {
await PageObjects.common.navigateToActualUrl('kibana', USERS_PATH, {
ensureCurrentUrl: false,
shouldLoginIfPrompted: false,
});
await PageObjects.common.waitUntilUrlIncludes('next=');

await PageObjects.security.loginSelector.login('basic', 'basic1');

// We need to make sure that both path and hash are respected.
const currentURL = parse(await browser.getCurrentUrl());
expect(currentURL.pathname).to.eql('/app/kibana');
expect(currentURL.hash).to.eql(`#${USERS_PATH}`);
});

it('can login with SSO preserving original URL', async () => {
await PageObjects.common.navigateToActualUrl('kibana', USERS_PATH, {
ensureCurrentUrl: false,
shouldLoginIfPrompted: false,
});
await PageObjects.common.waitUntilUrlIncludes('next=');

await PageObjects.security.loginSelector.login('saml', 'saml1');

// We need to make sure that both path and hash are respected.
const currentURL = parse(await browser.getCurrentUrl());
expect(currentURL.pathname).to.eql('/app/kibana');
expect(currentURL.hash).to.eql(`#${USERS_PATH}`);
});

it('should show toast with error if SSO fails', async () => {
await PageObjects.security.loginSelector.selectLoginMethod('saml', 'unknown_saml');

const toastTitle = await PageObjects.common.closeToast();
expect(toastTitle).to.eql('Could not perform login.');

await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();
});

it('can go to Login Form and return back to Selector', async () => {
await PageObjects.security.loginSelector.selectLoginMethod('basic', 'basic1');
await PageObjects.security.loginSelector.verifyLoginFormIsVisible();

await testSubjects.click('loginBackToSelector');
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();

await PageObjects.security.loginSelector.login('saml', 'saml1');
});

it('can show Login Help from both Login Selector and Login Form', async () => {
// Show Login Help from Login Selector.
await testSubjects.click('loginHelpLink');
await PageObjects.security.loginSelector.verifyLoginHelpIsVisible('Some-login-help.');

// Go back to Login Selector.
await testSubjects.click('loginBackToLoginLink');
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();

// Go to Login Form and show Login Help there.
await PageObjects.security.loginSelector.selectLoginMethod('basic', 'basic1');
await PageObjects.security.loginSelector.verifyLoginFormIsVisible();
await testSubjects.click('loginHelpLink');
await PageObjects.security.loginSelector.verifyLoginHelpIsVisible('Some-login-help.');

// Go back to Login Form.
await testSubjects.click('loginBackToLoginLink');
await PageObjects.security.loginSelector.verifyLoginFormIsVisible();

// Go back to Login Selector and show Login Help there again.
await testSubjects.click('loginBackToSelector');
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();
await testSubjects.click('loginHelpLink');
await PageObjects.security.loginSelector.verifyLoginHelpIsVisible('Some-login-help.');

// Go back to Login Selector.
await testSubjects.click('loginBackToLoginLink');
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();
});
});
}
2 changes: 1 addition & 1 deletion x-pack/test/functional/apps/spaces/copy_saved_objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function spaceSelectorFunctonalTests({
disabledFeatures: [],
});

await PageObjects.security.login(null, null, {
await PageObjects.security.login(undefined, undefined, {
expectSpaceSelector: true,
});

Expand Down
4 changes: 2 additions & 2 deletions x-pack/test/functional/apps/spaces/enter_space.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function enterSpaceFunctonalTests({
it('falls back to the default home page when the configured default route is malformed', async () => {
const spaceId = 'default';

await PageObjects.security.login(null, null, {
await PageObjects.security.login(undefined, undefined, {
expectSpaceSelector: true,
});

Expand All @@ -39,7 +39,7 @@ export default function enterSpaceFunctonalTests({
it('allows user to navigate to different spaces, respecting the configured default route', async () => {
const spaceId = 'another-space';

await PageObjects.security.login(null, null, {
await PageObjects.security.login(undefined, undefined, {
expectSpaceSelector: true,
});

Expand Down
4 changes: 2 additions & 2 deletions x-pack/test/functional/apps/spaces/spaces_selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function spaceSelectorFunctonalTests({
it('allows user to navigate to different spaces', async () => {
const spaceId = 'another-space';

await PageObjects.security.login(null, null, {
await PageObjects.security.login(undefined, undefined, {
expectSpaceSelector: true,
});

Expand Down Expand Up @@ -67,7 +67,7 @@ export default function spaceSelectorFunctonalTests({

before(async () => {
await esArchiver.load('spaces/selector');
await PageObjects.security.login(null, null, {
await PageObjects.security.login(undefined, undefined, {
expectSpaceSelector: true,
});
await PageObjects.spaceSelector.clickSpaceCard('default');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,10 +409,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
await PageObjects.security.login(
'no_visualize_privileges_user',
'no_visualize_privileges_user-password',
{
expectSpaceSelector: false,
shouldLoginIfPrompted: false,
}
{ expectSpaceSelector: false }
);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

import { resolve } from 'path';

import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
import { services } from './services';
import { pageObjects } from './page_objects';

// the default export of config files must be a config provider
// that returns an object with the projects config values
export default async function({ readConfigFile }) {
export default async function({ readConfigFile }: FtrConfigProviderContext) {
const kibanaCommonConfig = await readConfigFile(
require.resolve('../../../test/common/config.js')
);
Expand Down
84 changes: 84 additions & 0 deletions x-pack/test/functional/config_security_trial.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/* eslint-disable import/no-default-export */

import { resolve } from 'path';
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
import { services } from './services';
import { pageObjects } from './page_objects';

// the default export of config files must be a config provider
// that returns an object with the projects config values
export default async function({ readConfigFile }: FtrConfigProviderContext) {
const kibanaCommonConfig = await readConfigFile(
require.resolve('../../../test/common/config.js')
);
const kibanaFunctionalConfig = await readConfigFile(
require.resolve('../../../test/functional/config.js')
);

const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port');
const idpPath = resolve(__dirname, '../saml_api_integration/fixtures/saml_provider/metadata.xml');
const samlIdPPlugin = resolve(__dirname, '../saml_api_integration/fixtures/saml_provider');

return {
testFiles: [resolve(__dirname, './apps/security/trial_license')],

services,
pageObjects,

servers: kibanaFunctionalConfig.get('servers'),

esTestCluster: {
license: 'trial',
from: 'snapshot',
serverArgs: [
'xpack.security.authc.token.enabled=true',
'xpack.security.authc.realms.saml.saml1.order=0',
`xpack.security.authc.realms.saml.saml1.idp.metadata.path=${idpPath}`,
'xpack.security.authc.realms.saml.saml1.idp.entity_id=http://www.elastic.co/saml1',
`xpack.security.authc.realms.saml.saml1.sp.entity_id=http://localhost:${kibanaPort}`,
`xpack.security.authc.realms.saml.saml1.sp.logout=http://localhost:${kibanaPort}/logout`,
`xpack.security.authc.realms.saml.saml1.sp.acs=http://localhost:${kibanaPort}/api/security/saml/callback`,
'xpack.security.authc.realms.saml.saml1.attributes.principal=urn:oid:0.0.7',
],
},

kbnTestServer: {
...kibanaCommonConfig.get('kbnTestServer'),
serverArgs: [
...kibanaCommonConfig.get('kbnTestServer.serverArgs'),
`--plugin-path=${samlIdPPlugin}`,
'--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d',
'--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"',
`--xpack.security.loginHelp="Some-login-help."`,
'--xpack.security.authc.providers.basic.basic1.order=0',
'--xpack.security.authc.providers.saml.saml1.order=1',
'--xpack.security.authc.providers.saml.saml1.realm=saml1',
'--xpack.security.authc.providers.saml.saml1.description="Log-in-with-SAML"',
'--xpack.security.authc.providers.saml.saml1.icon=logoKibana',
'--xpack.security.authc.providers.saml.unknown_saml.order=2',
'--xpack.security.authc.providers.saml.unknown_saml.realm=unknown_realm',
'--xpack.security.authc.providers.saml.unknown_saml.description="Do-not-log-in-with-THIS-SAML"',
'--xpack.security.authc.providers.saml.unknown_saml.icon=logoAWS',
],
},
uiSettings: {
defaults: {
'accessibility:disableAnimations': true,
'dateFormat:tz': 'UTC',
},
},
apps: kibanaFunctionalConfig.get('apps'),
esArchiver: { directory: resolve(__dirname, 'es_archives') },
screenshots: { directory: resolve(__dirname, 'screenshots') },

junit: {
reportName: 'Chrome X-Pack UI Functional Tests',
},
};
}
Loading

0 comments on commit aa6785e

Please sign in to comment.