diff --git a/x-pack/plugins/code/public/components/admin_page/project_item.tsx b/x-pack/plugins/code/public/components/admin_page/project_item.tsx index afffa4151152d..740cc8765b046 100644 --- a/x-pack/plugins/code/public/components/admin_page/project_item.tsx +++ b/x-pack/plugins/code/public/components/admin_page/project_item.tsx @@ -187,7 +187,13 @@ class CodeProjectItem extends React.PureComponent<{ {this.renderProgress()} - {disableRepoLink ? repoTitle : {repoTitle}} + {disableRepoLink ? ( + repoTitle + ) : ( + + {repoTitle} + + )} {showStatus ? repoStatus : null} diff --git a/x-pack/plugins/code/public/monaco/monaco.scss b/x-pack/plugins/code/public/monaco/monaco.scss index 2d8be4cb56bef..89cba38a0264b 100644 --- a/x-pack/plugins/code/public/monaco/monaco.scss +++ b/x-pack/plugins/code/public/monaco/monaco.scss @@ -1,11 +1,10 @@ .code-monaco-highlight-line { background: $euiCodeBlockBuiltInColor; - } .code-mark-line-number { background: $euiCodeBlockBuiltInColor; - width: $euiSizeXS; + width: $euiSizeXS; } .monaco-editor .margin-view-overlays .line-numbers { @@ -13,8 +12,6 @@ border-right: $euiBorderThin; } - - .monaco-editor-hover { min-width: 350px; border: $euiBorderThin; @@ -29,7 +26,7 @@ -o-user-select: text; user-select: text; box-sizing: initial; - animation: fadein .1s linear; + animation: fadein 0.1s linear; line-height: 1.5em; background: $euiColorLightestShade; border-radius: 4px 4px 4px 4px; @@ -51,7 +48,7 @@ border-left: 1px solid $euiBorderColor; } -.monaco-editor-hover .button-group button{ +.monaco-editor-hover .button-group button { font-size: 13px; font-weight: normal; border: 0; @@ -63,7 +60,8 @@ display: none; } -.code-mark-line-number, .code-monaco-highlight-line { +.code-mark-line-number, +.code-monaco-highlight-line { background-color: $euiColorLightShade; } @@ -80,18 +78,22 @@ animation-name: placeHolderShimmer; animation-timing-function: linear; background: $euiColorLightestShade; - background: linear-gradient(to right, $euiColorLightShade 8%, $euiColorLightestShade 38%, $euiColorLightShade 54%); + background: linear-gradient( + to right, + $euiColorLightShade 8%, + $euiColorLightestShade 38%, + $euiColorLightShade 54% + ); background-size: 1000px 640px; position: relative; - } -@keyframes placeHolderShimmer{ - 0%{ - background-position: -468px 0 +@keyframes placeHolderShimmer { + 0% { + background-position: -468px 0; } - 100%{ - background-position: 468px 0 + 100% { + background-position: 468px 0; } } diff --git a/x-pack/plugins/code/public/monaco/monaco_helper.ts b/x-pack/plugins/code/public/monaco/monaco_helper.ts index 9d56388cf6215..f1b6e3871cd58 100644 --- a/x-pack/plugins/code/public/monaco/monaco_helper.ts +++ b/x-pack/plugins/code/public/monaco/monaco_helper.ts @@ -138,7 +138,7 @@ export class MonacoHelper { range: new this.monaco!.Range(line, 0, line, 0), options: { isWholeLine: true, - className: 'code-monaco-highlight-line', + className: `code-monaco-highlight-line code-line-number-${line}`, linesDecorationsClassName: 'code-mark-line-number', }, }, diff --git a/x-pack/test/functional/apps/code/code_intelligence.ts b/x-pack/test/functional/apps/code/code_intelligence.ts index ebce5afeb5cf7..f03618b157e0d 100644 --- a/x-pack/test/functional/apps/code/code_intelligence.ts +++ b/x-pack/test/functional/apps/code/code_intelligence.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { TestInvoker } from './lib/types'; // eslint-disable-next-line import/no-default-export -export default function codeIntelligenceFunctonalTests({ +export default function codeIntelligenceFunctionalTests({ getService, getPageObjects, }: TestInvoker) { @@ -117,7 +117,7 @@ export default function codeIntelligenceFunctonalTests({ const userModelSpan = spans[1]; expect(await userModelSpan.getVisibleText()).to.equal('UserModel'); await browser.moveMouseTo(userModelSpan); - // Expect the go to defintion button show up eventually. + // Expect the go to definition button show up eventually. expect(await testSubjects.exists('codeGoToDefinitionButton')).to.be(true); await testSubjects.click('codeGoToDefinitionButton'); @@ -127,6 +127,16 @@ export default function codeIntelligenceFunctonalTests({ // Expect to jump to src/models/User.ts file on line 5. expect(currentUrl.indexOf('src/models/User.ts!L5:13')).to.greaterThan(0); }); + + // it should goes back to controllers/user.ts + await browser.goBack(); + + await retry.try(async () => { + const $spans = await find.allByCssSelector('.mtk31', FIND_TIME); + expect($spans.length).to.greaterThan(1); + const $userModelSpan = $spans[1]; + expect(await $userModelSpan.getVisibleText()).to.equal('UserModel'); + }); }); }); @@ -163,7 +173,7 @@ export default function codeIntelligenceFunctonalTests({ const userModelSpan = spans[0]; expect(await userModelSpan.getVisibleText()).to.equal('UserModel'); await browser.moveMouseTo(userModelSpan); - // Expect the go to defintion button show up eventually. + // Expect the go to definition button show up eventually. expect(await testSubjects.exists('codeFindReferenceButton')).to.be(true); await testSubjects.click('codeFindReferenceButton'); @@ -218,7 +228,7 @@ export default function codeIntelligenceFunctonalTests({ const asyncSpan = spans[1]; expect(await asyncSpan.getVisibleText()).to.equal('async'); await browser.moveMouseTo(asyncSpan); - // Expect the go to defintion button show up eventually. + // Expect the go to definition button show up eventually. expect(await testSubjects.exists('codeGoToDefinitionButton')).to.be(true); await testSubjects.click('codeGoToDefinitionButton'); @@ -232,6 +242,16 @@ export default function codeIntelligenceFunctonalTests({ // 0 // ); // }); + + // it should goes back to controllers/user.ts + await browser.goBack(); + + await retry.try(async () => { + const $spans = await find.allByCssSelector('.mtk31', FIND_TIME); + expect($spans.length).to.greaterThan(1); + const $userModelSpan = $spans[1]; + expect(await $userModelSpan.getVisibleText()).to.equal('UserModel'); + }); }); }); }); diff --git a/x-pack/test/functional/apps/code/history.ts b/x-pack/test/functional/apps/code/history.ts new file mode 100644 index 0000000000000..96beacb0d6f94 --- /dev/null +++ b/x-pack/test/functional/apps/code/history.ts @@ -0,0 +1,145 @@ +/* + * 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 { TestInvoker } from './lib/types'; + +// eslint-disable-next-line import/no-default-export +export default function manageRepositoriesFunctionalTests({ + getService, + getPageObjects, +}: TestInvoker) { + // const esArchiver = getService('esArchiver'); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const log = getService('log'); + const browser = getService('browser'); + const queryBar = getService('queryBar'); + const config = getService('config'); + const FIND_TIME = config.get('timeouts.find'); + const find = getService('find'); + const PageObjects = getPageObjects(['common', 'header', 'security', 'code', 'home']); + + describe('Code', () => { + const repositoryListSelector = 'codeRepositoryList codeRepositoryItem'; + + describe('browser history can go back while exploring code app', () => { + let driver: any; + before(async () => { + // Navigate to the code app. + await PageObjects.common.navigateToApp('code'); + await PageObjects.header.waitUntilLoadingHasFinished(); + + 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' + ); + // Click the import repository button. + await PageObjects.code.clickImportRepositoryButton(); + + const webDriver = await getService('__webdriver__').init(); + driver = webDriver.driver; + }); + // after(async () => await esArchiver.unload('code')); + + after(async () => { + await PageObjects.security.logout(); + }); + + it('from admin page to source view page can go back and forward', async () => { + await retry.tryForTime(300000, async () => { + const repositoryItems = await testSubjects.findAll(repositoryListSelector); + expect(repositoryItems).to.have.length(1); + expect(await repositoryItems[0].getVisibleText()).to.equal( + 'Microsoft/TypeScript-Node-Starter' + ); + }); + + await retry.try(async () => { + expect(await testSubjects.exists('repositoryIndexDone')).to.be(true); + + log.debug('it goes to Microsoft/TypeScript-Node-Starter project page'); + await testSubjects.click('adminLinkToTypeScript-Node-Starter'); + await retry.try(async () => { + expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true); + }); + + // can go back to admin page + await browser.goBack(); + + await retry.tryForTime(300000, async () => { + const repositoryItems = await testSubjects.findAll(repositoryListSelector); + expect(repositoryItems).to.have.length(1); + expect(await repositoryItems[0].getVisibleText()).to.equal( + 'Microsoft/TypeScript-Node-Starter' + ); + }); + + // can go forward to source view page + await driver.navigate().forward(); + + await retry.try(async () => { + expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true); + }); + }); + }); + + it('from source view page to search page can go back and forward', async () => { + log.debug('it search a symbol'); + await queryBar.setQuery('user'); + await queryBar.submitQuery(); + await retry.try(async () => { + const searchResultListSelector = 'codeSearchResultList codeSearchResultFileItem'; + const results = await testSubjects.findAll(searchResultListSelector); + expect(results).to.be.ok(); + }); + log.debug('it goes back to project page'); + await browser.goBack(); + retry.try(async () => { + expect(await testSubjects.exists('codeStructureTreeTab')).to.be(true); + }); + + await driver.navigate().forward(); + + await retry.try(async () => { + const searchResultListSelector = 'codeSearchResultList codeSearchResultFileItem'; + const results = await testSubjects.findAll(searchResultListSelector); + expect(results).to.be.ok(); + }); + }); + + it('in source view page file line number changed can go back and forward', async () => { + log.debug('it goes back after line number changed'); + const url = `${PageObjects.common.getHostPort()}/app/code#/github.com/Microsoft/TypeScript-Node-Starter`; + await browser.get(url); + const lineNumber = 20; + await testSubjects.click('codeFileTreeNode-File-package.json'); + const lineNumberElements = await find.allByCssSelector('.line-numbers'); + + await lineNumberElements[lineNumber].click(); + await retry.try(async () => { + const existence = await find.existsByCssSelector('.code-line-number-21', FIND_TIME); + expect(existence).to.be(true); + }); + + await browser.goBack(); + + await retry.try(async () => { + const existence = await find.existsByCssSelector('.code-line-number-21', FIND_TIME); + expect(existence).to.be(false); + }); + + await driver.navigate().forward(); + + await retry.try(async () => { + const existence = await find.existsByCssSelector('.code-line-number-21', FIND_TIME); + expect(existence).to.be(true); + }); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/code/index.ts b/x-pack/test/functional/apps/code/index.ts index b0d7b20075a47..76f07cce3efab 100644 --- a/x-pack/test/functional/apps/code/index.ts +++ b/x-pack/test/functional/apps/code/index.ts @@ -14,5 +14,6 @@ export default function codeApp({ loadTestFile }: TestInvoker) { loadTestFile(require.resolve('./explore_repository')); loadTestFile(require.resolve('./code_intelligence')); loadTestFile(require.resolve('./with_security')); + loadTestFile(require.resolve('./history')); }); } diff --git a/x-pack/test/functional/apps/code/manage_repositories.ts b/x-pack/test/functional/apps/code/manage_repositories.ts index b79c57ee2a971..6917deede90da 100644 --- a/x-pack/test/functional/apps/code/manage_repositories.ts +++ b/x-pack/test/functional/apps/code/manage_repositories.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { TestInvoker } from './lib/types'; // eslint-disable-next-line import/no-default-export -export default function manageRepositoriesFunctonalTests({ +export default function manageRepositoriesFunctionalTests({ getService, getPageObjects, }: TestInvoker) {