[7.x] Improve the functional test of code (#35869) (#36922)

* Improve the functional test of code (#35869)

* [Code] enable integration test

* [Code] Improve functional test

* disable flaky test #36495 (#36497)

* [Code] skip explore-repository functional test for code (#36926)

* skip failing tests
This commit is contained in:
Mengwei Ding 2019-05-23 12:47:30 -07:00 committed by GitHub
parent 12697d8a3b
commit fd797f3665
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 215 additions and 192 deletions

View file

@ -258,6 +258,9 @@ const handleRepoDeleteStatusPolling = createRepoStatusPollingHandler(
})
);
return isInProgress(status.deleteStatus.progress);
} else {
// Keep polling if the deleteStatus has not been persisted yet.
return true;
}
},
pollRepoDeleteStatus

View file

@ -117,7 +117,7 @@ export default function codeIntelligenceFunctionalTests({
// Clean up the imported repository
await PageObjects.code.clickDeleteRepositoryButton();
await retry.try(async () => {
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(0);
});

View file

@ -23,7 +23,8 @@ export default function exploreRepositoryFunctonalTests({
const FIND_TIME = config.get('timeouts.find');
describe('Code', () => {
// FLAKY https://github.com/elastic/kibana/issues/35944
describe.skip('Explore Repository', () => {
describe('Explore a repository', () => {
const repositoryListSelector = 'codeRepositoryList codeRepositoryItem';
@ -64,7 +65,7 @@ export default function exploreRepositoryFunctonalTests({
// Clean up the imported repository
await PageObjects.code.clickDeleteRepositoryButton();
await retry.try(async () => {
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(0);
});
@ -140,9 +141,10 @@ export default function exploreRepositoryFunctonalTests({
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-src-open')).ok();
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-src-doc-open')).ok();
});
log.info('src-doc folder opened');
// click src again to close this folder
// click src again to focus on this folder
await testSubjects.click('codeFileTreeNode-Directory-src');
// then click again to close this folder.
await testSubjects.click('codeFileTreeNode-Directory-src');
await retry.tryForTime(5000, async () => {
@ -161,23 +163,23 @@ export default function exploreRepositoryFunctonalTests({
});
await testSubjects.click('codeFileTreeNode-Directory-src');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileTreeNode-Directory-src/config')).ok();
expect(await testSubjects.exists('codeFileTreeNode-Directory-src/controllers')).ok();
});
await testSubjects.click('codeFileTreeNode-Directory-src/config');
await testSubjects.click('codeFileTreeNode-Directory-src/controllers');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileTreeNode-File-src/config/passport.ts')).ok();
expect(await testSubjects.exists('codeFileTreeNode-File-src/controllers/user.ts')).ok();
});
await testSubjects.click('codeFileTreeNode-File-src/config/passport.ts');
await testSubjects.click('codeFileTreeNode-File-src/controllers/user.ts');
await retry.try(async () => {
expect(await testSubjects.exists('codeStructureTreeTab')).ok();
});
await testSubjects.click('codeStructureTreeTab');
await retry.try(async () => {
expect(
await testSubjects.exists('"codeStructureTreeNode-User.findById() callback"')
).ok();
// Retry click the structure tab in case it's not ready yet
await testSubjects.click('codeStructureTreeTab');
expect(await testSubjects.exists('codeStructureTreeNode-errors')).ok();
});
await testSubjects.click('"codeStructureTreeNode-User.findById() callback"');
await testSubjects.click('codeStructureTreeNode-errors');
await retry.try(async () => {
const highlightSymbols = await find.allByCssSelector('.code-full-width-node', FIND_TIME);
@ -187,7 +189,7 @@ export default function exploreRepositoryFunctonalTests({
it('click a breadcrumb should not affect the file tree', async () => {
log.debug('it goes to a deep node of file tree');
const url = `${PageObjects.common.getHostPort()}/app/code#/github.com/Microsoft/TypeScript-Node-Starter/blob/master/src/models/User.ts`;
const url = `${PageObjects.common.getHostPort()}/app/code#/github.com/elastic/TypeScript-Node-Starter/blob/master/src/models/User.ts`;
await browser.get(url);
// Click breadcrumb does not affect file tree
await retry.try(async () => {
@ -196,76 +198,78 @@ export default function exploreRepositoryFunctonalTests({
await testSubjects.click('codeFileBreadcrumb-src');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-src-open')).ok();
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-src-doc-open')).ok();
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-src-doc-closed')).ok();
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-test-closed')).ok();
expect(await testSubjects.exists('codeFileTreeNode-Directory-Icon-views-closed')).ok();
});
});
it('Click file/directory on the right panel', async () => {
log.debug('Click file/directory on the right panel');
// TODO(qianliang): blocked by https://github.com/elastic/code/issues/1163
// it('Click file/directory on the right panel', async () => {
// log.debug('Click file/directory on the right panel');
// Wait the file tree to be rendered and click the 'src' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
});
// // Wait the file tree to be rendered and click the 'src' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-src');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-src');
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-models');
// Then the 'models' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-models');
// // Then the 'models' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-User.ts');
// Then the 'User.ts' file on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
});
});
// await testSubjects.click('codeFileExplorerNode-User.ts');
// // Then the 'User.ts' file on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
// });
// });
it('Navigate source file via structure tree', async () => {
log.debug('Navigate source file via structure tree');
// Wait the file tree to be rendered and click the 'src' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
});
// TODO(qianliang): blocked by https://github.com/elastic/code/issues/1163
// it('Navigate source file via structure tree', async () => {
// log.debug('Navigate source file via structure tree');
// // Wait the file tree to be rendered and click the 'src' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-src')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-src');
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-src');
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-models')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-models');
// Then the 'models' folder on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-models');
// // Then the 'models' folder on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeFileExplorerNode-User.ts')).to.be(true);
// });
await testSubjects.click('codeFileExplorerNode-User.ts');
// Then the 'User.ts' file on the file tree.
await retry.try(async () => {
expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true);
});
// await testSubjects.click('codeFileExplorerNode-User.ts');
// // Then the 'User.ts' file on the file tree.
// await retry.try(async () => {
// expect(await testSubjects.exists('codeSourceViewer')).to.be(true);
// expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true);
// });
// Click the structure tree tab
await testSubjects.click('codeStructureTreeTab');
await retry.tryForTime(300000, async () => {
expect(await testSubjects.exists('codeStructureTreeNode-User')).to.be(true);
// // Click the structure tree tab
// await testSubjects.click('codeStructureTreeTab');
// await retry.tryForTime(300000, async () => {
// expect(await testSubjects.exists('codeStructureTreeNode-User')).to.be(true);
await testSubjects.click('codeStructureTreeNode-User');
await retry.tryForTime(5000, async () => {
const currentUrl: string = await browser.getCurrentUrl();
log.info(`Jump to url: ${currentUrl}`);
expect(currentUrl.indexOf('src/models/User.ts!L92:6') > 0).to.be(true);
});
});
});
// await testSubjects.click('codeStructureTreeNode-User');
// await retry.tryForTime(120000, async () => {
// const currentUrl: string = await browser.getCurrentUrl();
// log.info(`Jump to url: ${currentUrl}`);
// expect(currentUrl.indexOf('src/models/User.ts!L92:6') > 0).to.be(true);
// });
// });
// });
});
});
}

View file

@ -23,7 +23,8 @@ export default function manageRepositoriesFunctionalTests({
const find = getService('find');
const PageObjects = getPageObjects(['common', 'header', 'security', 'code', 'home']);
describe('Code', () => {
// FLAKY: https://github.com/elastic/kibana/issues/36495
describe.skip('History', () => {
const repositoryListSelector = 'codeRepositoryList codeRepositoryItem';
describe('browser history can go back while exploring code app', () => {
@ -47,6 +48,17 @@ export default function manageRepositoriesFunctionalTests({
// after(async () => await esArchiver.unload('code'));
after(async () => {
// Navigate to the code app.
await PageObjects.common.navigateToApp('code');
await PageObjects.header.waitUntilLoadingHasFinished();
// Clean up the imported repository
await PageObjects.code.clickDeleteRepositoryButton();
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(0);
});
await PageObjects.security.logout();
});

View file

@ -7,7 +7,7 @@ import { TestInvoker } from './lib/types';
// eslint-disable-next-line import/no-default-export
export default function codeApp({ loadTestFile }: TestInvoker) {
describe('Code app', function codeAppTestSuite() {
describe('Code', function codeAppTestSuite() {
this.tags('ciGroup2');
loadTestFile(require.resolve('./manage_repositories'));
loadTestFile(require.resolve('./search'));

View file

@ -18,7 +18,7 @@ export default function manageRepositoriesFunctionalTests({
const log = getService('log');
const PageObjects = getPageObjects(['common', 'header', 'security', 'code', 'home']);
describe('Code', () => {
describe('Manage Repositories', () => {
const repositoryListSelector = 'codeRepositoryList codeRepositoryItem';
describe('Manage Repositories', () => {
@ -37,7 +37,7 @@ export default function manageRepositoriesFunctionalTests({
log.debug('Code test import repository');
// Fill in the import repository input box with a valid git repository url.
await PageObjects.code.fillImportRepositoryUrlInputBox(
'https://github.com/Microsoft/TypeScript-Node-Starter'
'https://github.com/elastic/code-examples_empty-file'
);
// Click the import repository button.
await PageObjects.code.clickImportRepositoryButton();
@ -46,7 +46,7 @@ export default function manageRepositoriesFunctionalTests({
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(1);
expect(await repositoryItems[0].getVisibleText()).to.equal(
'Microsoft/TypeScript-Node-Starter'
'elastic/code-examples_empty-file'
);
});
@ -65,7 +65,7 @@ export default function manageRepositoriesFunctionalTests({
// Click the delete repository button.
await PageObjects.code.clickDeleteRepositoryButton();
await retry.try(async () => {
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(0);
});
@ -75,8 +75,9 @@ export default function manageRepositoriesFunctionalTests({
log.debug('Code test import repository');
// Fill in the import repository input box with a valid git repository url.
await PageObjects.code.fillImportRepositoryUrlInputBox(
'git://github.com/Microsoft/TypeScript-Node-Starter'
'git://github.com/elastic/code-examples_empty-file'
);
// Click the import repository button.
await PageObjects.code.clickImportRepositoryButton();
@ -84,7 +85,7 @@ export default function manageRepositoriesFunctionalTests({
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(1);
expect(await repositoryItems[0].getVisibleText()).to.equal(
'Microsoft/TypeScript-Node-Starter'
'elastic/code-examples_empty-file'
);
});
@ -100,7 +101,7 @@ export default function manageRepositoriesFunctionalTests({
// Delete the repository
await PageObjects.code.clickDeleteRepositoryButton();
await retry.try(async () => {
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(0);
});

View file

@ -15,7 +15,7 @@ export default function searchFunctonalTests({ getService, getPageObjects }: Tes
const log = getService('log');
const PageObjects = getPageObjects(['common', 'header', 'security', 'code', 'home']);
describe('Code', () => {
describe('Search', () => {
const symbolTypeaheadListSelector = 'codeTypeaheadList-symbol codeTypeaheadItem';
const searchResultListSelector = 'codeSearchResultList codeSearchResultFileItem';
const languageFilterListSelector = 'codeSearchLanguageFilterList codeSearchLanguageFilterItem';

View file

@ -21,128 +21,131 @@ export default function testWithSecurity({ getService, getPageObjects }: TestInv
const log = getService('log');
const security = getService('security');
describe('with security enabled:', () => {
before(async () => {
await esArchiver.load('empty_kibana');
await security.role.create('global_code_all_role', {
elasticsearch: {
indices: [],
},
kibana: [
{
feature: {
code: ['all'],
},
spaces: ['*'],
describe('Security', () => {
describe('with security enabled:', () => {
before(async () => {
await esArchiver.load('empty_kibana');
await security.role.create('global_code_all_role', {
elasticsearch: {
indices: [],
},
],
});
await security.user.create(codeAdmin, {
password: dummyPassword,
roles: ['global_code_all_role'],
full_name: 'code admin',
});
await security.role.create('global_code_read_role', {
elasticsearch: {
indices: [],
},
kibana: [
{
feature: {
code: ['read'],
kibana: [
{
feature: {
code: ['all'],
},
spaces: ['*'],
},
spaces: ['*'],
],
});
await security.user.create(codeAdmin, {
password: dummyPassword,
roles: ['global_code_all_role'],
full_name: 'code admin',
});
await security.role.create('global_code_read_role', {
elasticsearch: {
indices: [],
},
],
kibana: [
{
feature: {
code: ['read'],
},
spaces: ['*'],
},
],
});
await security.user.create(codeUser, {
password: dummyPassword,
roles: ['global_code_read_role'],
full_name: 'code user',
});
});
await security.user.create(codeUser, {
password: dummyPassword,
roles: ['global_code_read_role'],
full_name: 'code user',
});
});
async function login(user: string) {
await PageObjects.security.logout();
await PageObjects.security.login(user, dummyPassword);
await PageObjects.common.navigateToApp('code');
await PageObjects.header.waitUntilLoadingHasFinished();
}
async function login(user: string) {
await PageObjects.security.logout();
await PageObjects.security.login(user, dummyPassword);
await PageObjects.common.navigateToApp('code');
await PageObjects.header.waitUntilLoadingHasFinished();
}
it('codeAdmin should have an import button', async () => {
await login(codeAdmin);
await retry.tryForTime(5000, async () => {
const buttons = await testSubjects.findAll('importRepositoryButton');
expect(buttons).to.have.length(1);
});
});
it('codeUser should not have that import button', async () => {
await login(codeUser);
await retry.tryForTime(5000, async () => {
const buttons = await testSubjects.findAll('importRepositoryButton');
expect(buttons).to.have.length(0);
});
});
it('only codeAdmin can manage repositories', async () => {
await login(codeAdmin);
await retry.tryForTime(5000, async () => {
const buttons = await testSubjects.findAll('importRepositoryButton');
expect(buttons).to.have.length(1);
});
await PageObjects.code.fillImportRepositoryUrlInputBox(
'https://github.com/Microsoft/TypeScript-Node-Starter'
);
// Click the import repository button.
await PageObjects.code.clickImportRepositoryButton();
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(1);
for (const buttonSelector of manageButtonSelectors) {
const buttons = await testSubjects.findAll(buttonSelector);
it('codeAdmin should have an import button', async () => {
await login(codeAdmin);
await retry.tryForTime(5000, async () => {
const buttons = await testSubjects.findAll('importRepositoryButton');
expect(buttons).to.have.length(1);
log.debug(`button ${buttonSelector} found.`);
}
const importButton = await testSubjects.findAll('newProjectButton');
expect(importButton).to.have.length(1);
log.debug(`button newProjectButton found.`);
});
});
await login(codeUser);
await retry.tryForTime(5000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(1);
for (const buttonSelector of manageButtonSelectors) {
const buttons = await testSubjects.findAll(buttonSelector);
it('codeUser should not have that import button', async () => {
await login(codeUser);
await retry.tryForTime(5000, async () => {
const buttons = await testSubjects.findAll('importRepositoryButton');
expect(buttons).to.have.length(0);
}
const importButton = await testSubjects.findAll('newProjectButton');
expect(importButton).to.have.length(0);
});
});
});
async function cleanProjects() {
// remove imported project
await login(codeAdmin);
await retry.tryForTime(30000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
if (repositoryItems.length > 0) {
const deleteButton = await testSubjects.findAll('deleteRepositoryButton');
if (deleteButton.length > 0) {
await PageObjects.code.clickDeleteRepositoryButton();
}
}
expect(repositoryItems).to.have.length(0);
});
}
after(async () => {
await cleanProjects();
await PageObjects.security.logout();
await esArchiver.unload('code');
it('only codeAdmin can manage repositories', async () => {
await login(codeAdmin);
await retry.tryForTime(5000, async () => {
const buttons = await testSubjects.findAll('importRepositoryButton');
expect(buttons).to.have.length(1);
});
await PageObjects.code.fillImportRepositoryUrlInputBox(
'https://github.com/Microsoft/TypeScript-Node-Starter'
);
// Click the import repository button.
await PageObjects.code.clickImportRepositoryButton();
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(1);
for (const buttonSelector of manageButtonSelectors) {
const buttons = await testSubjects.findAll(buttonSelector);
expect(buttons).to.have.length(1);
log.debug(`button ${buttonSelector} found.`);
}
const importButton = await testSubjects.findAll('newProjectButton');
expect(importButton).to.have.length(1);
log.debug(`button newProjectButton found.`);
});
await login(codeUser);
await retry.tryForTime(5000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
expect(repositoryItems).to.have.length(1);
for (const buttonSelector of manageButtonSelectors) {
const buttons = await testSubjects.findAll(buttonSelector);
expect(buttons).to.have.length(0);
}
const importButton = await testSubjects.findAll('newProjectButton');
expect(importButton).to.have.length(0);
});
});
async function cleanProjects() {
// remove imported project
await login(codeAdmin);
await retry.tryForTime(300000, async () => {
const repositoryItems = await testSubjects.findAll(repositoryListSelector);
if (repositoryItems.length > 0) {
const deleteButton = await testSubjects.findAll('deleteRepositoryButton');
if (deleteButton.length > 0) {
await PageObjects.code.clickDeleteRepositoryButton();
}
}
expect(repositoryItems).to.have.length(0);
});
}
after(async () => {
await cleanProjects();
await PageObjects.security.logout();
await esArchiver.unload('code');
});
});
});
}

View file

@ -102,7 +102,7 @@ export default async function ({ readConfigFile }) {
resolve(__dirname, './apps/status_page'),
resolve(__dirname, './apps/timelion'),
resolve(__dirname, './apps/upgrade_assistant'),
// resolve(__dirname, './apps/code'),
resolve(__dirname, './apps/code'),
resolve(__dirname, './apps/visualize'),
resolve(__dirname, './apps/uptime'),
resolve(__dirname, './apps/saved_objects_management'),