mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 13:31:54 +00:00
misc improvements to tests to prep for vitest switch (#57904)
* stub method to avoid unhandled exception in test from pretendRemote
* less flaky ActionItem test that checks condition before snapshotting
* rename *.{spec => test}.ts
This simplifies the test filename pattern.
* rename top-level tsconfig.all.json to tsconfig.json
* upgrade to pnpm 8.9.2
* avoid usage of jsdom.reconfigure
* more robust linkClickHandler.test.tsx
* make getBundleSizeStats.test.ts not need to use mocks
* extract createBarrier() to @sourcegraph/testing
* more robust fromObservableQuery.test.ts
* avoid jsdom.reconfigure
* do not attempt to request assets from assets.gitlab-static.net
fastmod -F assets.gitlab-static.net example.com client/browser/src/
* avoid "incorrect casing" for mocked React components
* use createBarrier
* fix SurveyToast mock GraphQL query
* fix classNames typo
This commit is contained in:
parent
55fdf1b105
commit
85818110a7
@ -12,4 +12,4 @@ awscli 2.4.7
|
||||
python 3.11.3 system
|
||||
rust 1.68.0
|
||||
ruby 3.1.3
|
||||
pnpm 8.3.0
|
||||
pnpm 8.9.2
|
||||
|
||||
@ -57,7 +57,7 @@ ts_config(
|
||||
|
||||
ts_config(
|
||||
name = "tsconfig-all",
|
||||
src = "tsconfig.all.json",
|
||||
src = "tsconfig.json",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":tsconfig",
|
||||
|
||||
@ -313,6 +313,7 @@ ts_project(
|
||||
":node_modules/@sourcegraph/common",
|
||||
":node_modules/@sourcegraph/http-client",
|
||||
":node_modules/@sourcegraph/shared",
|
||||
":node_modules/@sourcegraph/testing",
|
||||
":node_modules/@sourcegraph/wildcard", #keep
|
||||
":node_modules/sourcegraph",
|
||||
"//:node_modules/@jest/globals",
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
"devDependencies": {
|
||||
"@sourcegraph/build-config": "workspace:*",
|
||||
"@sourcegraph/extension-api-types": "workspace:*",
|
||||
"@sourcegraph/testing": "workspace:*",
|
||||
"sourcegraph": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@ -8,17 +8,22 @@ import {
|
||||
getFileInfoWithoutCommitIDsFromMultiFileDiffCodeView,
|
||||
isCommitsView,
|
||||
isPullRequestView,
|
||||
windowLocation__testingOnly,
|
||||
} from './scrape'
|
||||
|
||||
describe('Bitbucket scrape.ts', () => {
|
||||
afterEach(() => {
|
||||
windowLocation__testingOnly.value = null
|
||||
})
|
||||
|
||||
describe('getFileInfoFromSingleFileSourceCodeView()', () => {
|
||||
afterEach(() => {
|
||||
document.body.innerHTML = ''
|
||||
})
|
||||
it('should get the FileInfo for a single file code view', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOUR/repos/mux/browse/context.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOUR/repos/mux/browse/context.go'
|
||||
)
|
||||
document.body.innerHTML = await readFile(`${__dirname}/__fixtures__/single-file.html`, 'utf-8')
|
||||
const codeView = document.querySelector<HTMLElement>('.file-content')
|
||||
const fileInfo = getFileInfoFromSingleFileSourceCodeView(codeView!)
|
||||
@ -34,9 +39,9 @@ describe('Bitbucket scrape.ts', () => {
|
||||
})
|
||||
describe('getDiffFileInfoFromMultiFileDiffCodeView()', () => {
|
||||
it('should get the FileInfo for an added file', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/new_file.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/new_file.go'
|
||||
)
|
||||
const codeView = await getFixtureBody({
|
||||
htmlFixturePath: `${__dirname}/__fixtures__/code-views/pull-request/split/added.html`,
|
||||
isFullDocument: false,
|
||||
@ -52,9 +57,9 @@ describe('Bitbucket scrape.ts', () => {
|
||||
})
|
||||
})
|
||||
it('should get the FileInfo for a modified file', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/mux.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/mux.go'
|
||||
)
|
||||
const codeView = await getFixtureBody({
|
||||
htmlFixturePath: `${__dirname}/__fixtures__/code-views/pull-request/split/modified.html`,
|
||||
isFullDocument: false,
|
||||
@ -70,9 +75,9 @@ describe('Bitbucket scrape.ts', () => {
|
||||
})
|
||||
})
|
||||
it('should get the FileInfo for a deleted file', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/old_test.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/old_test.go'
|
||||
)
|
||||
const codeView = await getFixtureBody({
|
||||
htmlFixturePath: `${__dirname}/__fixtures__/code-views/pull-request/split/deleted.html`,
|
||||
isFullDocument: false,
|
||||
@ -88,9 +93,9 @@ describe('Bitbucket scrape.ts', () => {
|
||||
})
|
||||
})
|
||||
it('should get the FileInfo for a copied file', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/mux.1.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/mux.1.go'
|
||||
)
|
||||
const codeView = await getFixtureBody({
|
||||
htmlFixturePath: `${__dirname}/__fixtures__/code-views/pull-request/split/copied.html`,
|
||||
isFullDocument: false,
|
||||
@ -106,9 +111,9 @@ describe('Bitbucket scrape.ts', () => {
|
||||
})
|
||||
})
|
||||
it('should get the FileInfo for a renamed file', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/mux_test_moved.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/mux_test_moved.go'
|
||||
)
|
||||
const codeView = await getFixtureBody({
|
||||
htmlFixturePath: `${__dirname}/__fixtures__/code-views/pull-request/split/renamed.html`,
|
||||
isFullDocument: false,
|
||||
@ -124,9 +129,9 @@ describe('Bitbucket scrape.ts', () => {
|
||||
})
|
||||
})
|
||||
it('should get the FileInfo for a moved file', async () => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/test-dir/route.go',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://bitbucket.test/projects/SOURCEGRAPH/repos/mux/pull-requests/1/diff#dir/test-dir/route.go'
|
||||
)
|
||||
const codeView = await getFixtureBody({
|
||||
htmlFixturePath: `${__dirname}/__fixtures__/code-views/pull-request/split/moved.html`,
|
||||
isFullDocument: false,
|
||||
|
||||
@ -10,10 +10,16 @@ export interface BitbucketRepoInfo {
|
||||
project: string
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing only, used to set the window.location value.
|
||||
* @internal
|
||||
*/
|
||||
export const windowLocation__testingOnly: { value: Pick<URL, 'hostname' | 'pathname'> | null } = { value: null }
|
||||
|
||||
const LINK_SELECTORS = ['a.raw-view-link', 'a.source-view-link', 'a.mode-source']
|
||||
|
||||
const bitbucketToSourcegraphRepoName = ({ repoSlug, project }: BitbucketRepoInfo): string =>
|
||||
[window.location.hostname, project, repoSlug].join('/')
|
||||
[(windowLocation__testingOnly.value ?? window.location).hostname, project, repoSlug].join('/')
|
||||
|
||||
/**
|
||||
* Attempts to parse the file info from a link element contained in the given
|
||||
@ -278,7 +284,9 @@ export const getFileInfoWithoutCommitIDsFromMultiFileDiffCodeView = (
|
||||
}
|
||||
|
||||
// Get project and repo from the URL
|
||||
const pathMatch = location.pathname.match(/\/projects\/(.*?)\/repos\/(.*?)\//)
|
||||
const pathMatch = (windowLocation__testingOnly.value ?? window.location).pathname.match(
|
||||
/\/projects\/(.*?)\/repos\/(.*?)\//
|
||||
)
|
||||
if (!pathMatch) {
|
||||
throw new Error('Location did not match regexp')
|
||||
}
|
||||
@ -316,9 +324,13 @@ export const getFileInfoFromCommitDiffCodeView = (codeViewElement: HTMLElement):
|
||||
}
|
||||
|
||||
export function getPRIDFromPathName(): number {
|
||||
const prIDMatch = window.location.pathname.match(/pull-requests\/(\d*?)\/(diff|overview|commits)/)
|
||||
const prIDMatch = (windowLocation__testingOnly.value ?? window.location).pathname.match(
|
||||
/pull-requests\/(\d*?)\/(diff|overview|commits)/
|
||||
)
|
||||
if (!prIDMatch) {
|
||||
throw new Error(`Could not parse PR ID from pathname: ${window.location.pathname}`)
|
||||
throw new Error(
|
||||
`Could not parse PR ID from pathname: ${(windowLocation__testingOnly.value ?? window.location).pathname}`
|
||||
)
|
||||
}
|
||||
return parseInt(prIDMatch[1], 10)
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
isPrivateRepository,
|
||||
parseHash,
|
||||
} from './codeHost'
|
||||
import { windowLocation__testingOnly } from './util'
|
||||
|
||||
const testCodeHost = (fixturePath: string): void => {
|
||||
if (existsSync(fixturePath)) {
|
||||
@ -83,11 +84,15 @@ describe('github/codeHost', () => {
|
||||
const urlToFile = githubCodeHost.urlToFile!
|
||||
const sourcegraphURL = 'https://sourcegraph.my.org'
|
||||
|
||||
afterAll(() => {
|
||||
windowLocation__testingOnly.value = null
|
||||
})
|
||||
|
||||
describe('on blob page', () => {
|
||||
beforeAll(() => {
|
||||
jsdom.reconfigure({
|
||||
url: 'https://github.com/sourcegraph/sourcegraph/blob/main/browser/src/shared/code-hosts/code_intelligence.tsx',
|
||||
})
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://github.com/sourcegraph/sourcegraph/blob/main/browser/src/shared/code-hosts/code_intelligence.tsx'
|
||||
)
|
||||
})
|
||||
it('returns an URL to the Sourcegraph instance if the location has a viewState', () => {
|
||||
expect(
|
||||
@ -154,7 +159,9 @@ describe('github/codeHost', () => {
|
||||
})
|
||||
describe('on pull request page', () => {
|
||||
beforeAll(async () => {
|
||||
jsdom.reconfigure({ url: 'https://github.com/sourcegraph/sourcegraph/pull/3257/files' })
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://github.com/sourcegraph/sourcegraph/pull/3257/files'
|
||||
)
|
||||
document.documentElement.innerHTML = await readFile(
|
||||
__dirname + '/__fixtures__/github.com/pull-request/vanilla/unified/page.html',
|
||||
'utf-8'
|
||||
@ -213,15 +220,8 @@ describe('isPrivateRepository', () => {
|
||||
})
|
||||
|
||||
describe('when on "github.com"', () => {
|
||||
const { location } = window
|
||||
|
||||
beforeAll(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
delete window.location
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
window.location = new URL('https://github.com')
|
||||
windowLocation__testingOnly.value = new URL('https://github.com')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
@ -232,7 +232,7 @@ describe('isPrivateRepository', () => {
|
||||
afterAll(() => {
|
||||
fetch.disableMocks()
|
||||
|
||||
window.location = location
|
||||
windowLocation__testingOnly.value = null
|
||||
})
|
||||
|
||||
it('returns [private=true] on unsuccessful request', async () => {
|
||||
|
||||
@ -31,7 +31,14 @@ import type { ViewResolver } from '../shared/views'
|
||||
|
||||
import { diffDomFunctions, searchCodeSnippetDOMFunctions, singleFileDOMFunctions } from './domFunctions'
|
||||
import { resolveDiffFileInfo, resolveFileInfo, resolveSnippetFileInfo } from './fileInfo'
|
||||
import { getFileContainers, parseURL, getSelectorFor, isNewGitHubUI, getEmbeddedData } from './util'
|
||||
import {
|
||||
getFileContainers,
|
||||
parseURL,
|
||||
getSelectorFor,
|
||||
isNewGitHubUI,
|
||||
getEmbeddedData,
|
||||
windowLocation__testingOnly,
|
||||
} from './util'
|
||||
|
||||
import styles from './codeHost.module.scss'
|
||||
|
||||
@ -286,7 +293,8 @@ export function checkIsGitHubEnterprise(): boolean {
|
||||
/**
|
||||
* Returns true if the current page is github.com.
|
||||
*/
|
||||
export const checkIsGitHubDotCom = (url = window.location.href): boolean => /^https?:\/\/(www\.)?github\.com/.test(url)
|
||||
export const checkIsGitHubDotCom = (url = (windowLocation__testingOnly.value ?? window.location).href): boolean =>
|
||||
/^https?:\/\/(www\.)?github\.com/.test(url)
|
||||
|
||||
/**
|
||||
* Returns true if the current page is either github.com or GitHub Enterprise.
|
||||
@ -383,7 +391,7 @@ export const isPrivateRepository = async (
|
||||
fetchCache = background.fetchCache,
|
||||
fallbackSelector = '#repository-container-header span.Label'
|
||||
): Promise<boolean> => {
|
||||
if (window.location.hostname !== 'github.com') {
|
||||
if ((windowLocation__testingOnly.value ?? window.location).hostname !== 'github.com') {
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
try {
|
||||
@ -418,12 +426,15 @@ export interface GithubCodeHost extends CodeHost {
|
||||
|
||||
export const isGithubCodeHost = (codeHost: CodeHost): codeHost is GithubCodeHost => codeHost.type === 'github'
|
||||
|
||||
const isSimpleSearchPage = (): boolean => window.location.pathname === '/search'
|
||||
const isAdvancedSearchPage = (): boolean => window.location.pathname === '/search/advanced'
|
||||
const isRepoSearchPage = (): boolean => !isSimpleSearchPage() && window.location.pathname.endsWith('/search')
|
||||
const isSimpleSearchPage = (): boolean => (windowLocation__testingOnly.value ?? window.location).pathname === '/search'
|
||||
const isAdvancedSearchPage = (): boolean =>
|
||||
(windowLocation__testingOnly.value ?? window.location).pathname === '/search/advanced'
|
||||
const isRepoSearchPage = (): boolean =>
|
||||
!isSimpleSearchPage() && (windowLocation__testingOnly.value ?? window.location).pathname.endsWith('/search')
|
||||
const isSearchResultsPage = (): boolean =>
|
||||
// TODO(#44327): Do not rely on window.location.search - it may be present not only on search pages (e.g., issues, pulls, etc.).
|
||||
Boolean(new URLSearchParams(window.location.search).get('q')) && !isAdvancedSearchPage()
|
||||
Boolean(new URLSearchParams((windowLocation__testingOnly.value ?? window.location).search).get('q')) &&
|
||||
!isAdvancedSearchPage()
|
||||
const isSearchPage = (): boolean =>
|
||||
isSimpleSearchPage() || isAdvancedSearchPage() || isRepoSearchPage() || isSearchResultsPage()
|
||||
|
||||
@ -440,7 +451,9 @@ type GithubResultType =
|
||||
| 'users'
|
||||
|
||||
const getGithubResultType = (): GithubResultType | '' => {
|
||||
const githubResultType = new URLSearchParams(window.location.search).get('type')
|
||||
const githubResultType = new URLSearchParams((windowLocation__testingOnly.value ?? window.location).search).get(
|
||||
'type'
|
||||
)
|
||||
|
||||
return githubResultType ? (githubResultType.toLowerCase() as GithubResultType) : ''
|
||||
}
|
||||
@ -466,7 +479,8 @@ const getSourcegraphResultType = (): SourcegraphResultType | '' => {
|
||||
}
|
||||
}
|
||||
|
||||
const getSourcegraphResultLanguage = (): string | null => new URLSearchParams(window.location.search).get('l')
|
||||
const getSourcegraphResultLanguage = (): string | null =>
|
||||
new URLSearchParams((windowLocation__testingOnly.value ?? window.location).search).get('l')
|
||||
|
||||
const buildSourcegraphQuery = (searchTerms: string[]): string => {
|
||||
const queryParameters = searchTerms.filter(Boolean).map(parameter => parameter.trim())
|
||||
@ -482,7 +496,7 @@ const buildSourcegraphQuery = (searchTerms: string[]): string => {
|
||||
}
|
||||
|
||||
if (isRepoSearchPage()) {
|
||||
const [user, repo] = window.location.pathname.split('/').filter(Boolean)
|
||||
const [user, repo] = (windowLocation__testingOnly.value ?? window.location).pathname.split('/').filter(Boolean)
|
||||
queryParameters.push(`repo:${user}/${repo}$`)
|
||||
}
|
||||
|
||||
@ -673,7 +687,7 @@ export const githubCodeHost: GithubCodeHost = {
|
||||
routeChange: mutations =>
|
||||
mutations.pipe(
|
||||
map(() => {
|
||||
const { pathname } = window.location
|
||||
const { pathname } = windowLocation__testingOnly.value ?? window.location
|
||||
|
||||
// repository file tree navigation
|
||||
const pageType = pathname.slice(1).split('/')[2]
|
||||
@ -738,7 +752,9 @@ export const githubCodeHost: GithubCodeHost = {
|
||||
}
|
||||
|
||||
// Make sure the location is also on this github instance, return an absolute URL otherwise.
|
||||
const sameCodeHost = target.rawRepoName.startsWith(window.location.hostname)
|
||||
const sameCodeHost = target.rawRepoName.startsWith(
|
||||
(windowLocation__testingOnly.value ?? window.location).hostname
|
||||
)
|
||||
if (!sameCodeHost) {
|
||||
return toAbsoluteBlobURL(sourcegraphURL, target)
|
||||
}
|
||||
@ -763,7 +779,7 @@ export const githubCodeHost: GithubCodeHost = {
|
||||
const anchorPath = header.dataset.path
|
||||
if (anchorPath === target.filePath) {
|
||||
const anchorUrl = header.dataset.anchor
|
||||
const url = new URL(window.location.href)
|
||||
const url = new URL((windowLocation__testingOnly.value ?? window.location).href)
|
||||
url.hash = anchorUrl
|
||||
if (target.position) {
|
||||
// GitHub uses L for the left side, R for both right side and the unchanged/white parts
|
||||
@ -787,7 +803,7 @@ export const githubCodeHost: GithubCodeHost = {
|
||||
},
|
||||
observeLineSelection: fromEvent(window, 'hashchange').pipe(
|
||||
startWith(undefined), // capture initial value
|
||||
map(() => parseHash(window.location.hash))
|
||||
map(() => parseHash((windowLocation__testingOnly.value ?? window.location).hash))
|
||||
),
|
||||
codeViewsRequireTokenization: true,
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { beforeEach, describe, expect, it } from '@jest/globals'
|
||||
import { afterEach, beforeEach, describe, expect, it } from '@jest/globals'
|
||||
import { startCase } from 'lodash'
|
||||
import type { Omit } from 'utility-types'
|
||||
|
||||
import { type DOMFunctionsTest, getFixtureBody, testDOMFunctions } from '../shared/codeHostTestUtils'
|
||||
|
||||
import { diffDomFunctions, isDomSplitDiff, singleFileDOMFunctions } from './domFunctions'
|
||||
import { windowLocation__testingOnly } from './util'
|
||||
|
||||
type GitHubVersion = 'github.com' | 'ghe-2.14.11'
|
||||
|
||||
@ -131,12 +132,14 @@ describe('GitHub DOM functions', () => {
|
||||
]
|
||||
for (const { view, url } of views) {
|
||||
describe(`${startCase(view)} page`, () => {
|
||||
beforeEach(() => {
|
||||
// TODO ideally DOM functions would not look at global state like the URL.
|
||||
jsdom.reconfigure({ url })
|
||||
})
|
||||
for (const extension of ['vanilla', 'refined-github']) {
|
||||
describe(startCase(extension), () => {
|
||||
beforeEach(() => {
|
||||
windowLocation__testingOnly.value = new URL(url)
|
||||
})
|
||||
afterEach(() => {
|
||||
windowLocation__testingOnly.value = null
|
||||
})
|
||||
if (view === 'pull-request-discussion') {
|
||||
it('should return false', async () => {
|
||||
const codeViewElement = await getFixtureBody({
|
||||
|
||||
@ -233,8 +233,7 @@ export const searchCodeSnippetDOMFunctions: DOMFunctions = {
|
||||
|
||||
/**
|
||||
* Returns if the current view shows diffs with split (vs. unified) view.
|
||||
*
|
||||
* @param element, either an element contained in a code view or the code view itself
|
||||
* @param element either an element contained in a code view or the code view itself
|
||||
*/
|
||||
export function isDomSplitDiff(element: HTMLElement): boolean {
|
||||
const { pageType } = parseURL()
|
||||
|
||||
@ -41,8 +41,7 @@ describe('github/fileInfo', () => {
|
||||
|
||||
for (const { url, rev, filePath } of toReturn) {
|
||||
it(`returns "${filePath}" for URL "${url}" and revision "${rev}"`, () => {
|
||||
jsdom.reconfigure({ url })
|
||||
expect(getFilePathFromURL(rev)).toBe(filePath)
|
||||
expect(getFilePathFromURL(rev, new URL(url))).toBe(filePath)
|
||||
})
|
||||
}
|
||||
|
||||
@ -61,9 +60,8 @@ describe('github/fileInfo', () => {
|
||||
|
||||
for (const { url, rev, reason } of toThrow) {
|
||||
it(`throws an error for URL "${url}" and revision "${rev}", reason: "${reason}"`, () => {
|
||||
jsdom.reconfigure({ url })
|
||||
expect(() => {
|
||||
getFilePathFromURL(rev)
|
||||
getFilePathFromURL(rev, new URL(url))
|
||||
}).toThrow()
|
||||
})
|
||||
}
|
||||
|
||||
@ -3,6 +3,12 @@ import type { RawRepoSpec, RepoSpec } from '@sourcegraph/shared/src/util/url'
|
||||
import type { DiffResolvedRevisionSpec } from '../../repo'
|
||||
import { RepoURLParseError } from '../shared/errors'
|
||||
|
||||
/**
|
||||
* For testing only, used to set the window.location value.
|
||||
* @internal
|
||||
*/
|
||||
export const windowLocation__testingOnly: { value: URL | null } = { value: null }
|
||||
|
||||
/**
|
||||
* Returns the elements on the page which should be marked
|
||||
* up with tooltips & links:
|
||||
@ -237,10 +243,10 @@ export function getFilePath(): string {
|
||||
* making the boundary between the branch name and file path ambiguous.
|
||||
* E.g., in URL "https://github.com/sourcegraph/sourcegraph/blob/bext/release/package.json" branch name is "bext/release".
|
||||
*/
|
||||
export function getFilePathFromURL(rev: string): string {
|
||||
export function getFilePathFromURL(rev: string, windowLocation__testingOnly: URL | Location = window.location): string {
|
||||
// <empty>/<user>/<repo>/(blob|tree)/<commitID|rev>/<path/to/file>
|
||||
// eslint-disable-next-line unicorn/no-unreadable-array-destructuring
|
||||
const [, , , pageType, ...revAndPathParts] = window.location.pathname.split('/')
|
||||
const [, , , pageType, ...revAndPathParts] = windowLocation__testingOnly.pathname.split('/')
|
||||
const revAndPath = revAndPathParts.join('/')
|
||||
if (!revAndPath.startsWith(rev) || (pageType !== 'tree' && revAndPath.length === rev.length)) {
|
||||
throw new Error('Failed to extract the file path from the URL.')
|
||||
@ -273,11 +279,11 @@ export function isDiffPageType(pageType: GitHubURL['pageType']): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
export function parseURL(location: Pick<Location, 'host' | 'pathname' | 'href'> = window.location): GitHubURL {
|
||||
const { host, pathname } = location
|
||||
export function parseURL(location?: Pick<Location, 'host' | 'pathname' | 'href'>): GitHubURL {
|
||||
const { pathname, href, host } = location ?? windowLocation__testingOnly.value ?? window.location
|
||||
const [user, ghRepoName, pageType, ...rest] = pathname.slice(1).split('/')
|
||||
if (!user || !ghRepoName) {
|
||||
throw new RepoURLParseError(`Could not parse repoName from GitHub url: ${location.href}`)
|
||||
throw new RepoURLParseError(`Could not parse repoName from GitHub url: ${href}`)
|
||||
}
|
||||
const repoName = `${user}/${ghRepoName}`
|
||||
const rawRepoName = `${host}/${repoName}`
|
||||
|
||||
@ -1,42 +1,42 @@
|
||||
<!-- Created from https://gitlab.com/sourcegraph/jsonrpc2/merge_requests/1/diffs -->
|
||||
<head prefix="og: http://ogp.me/ns#">
|
||||
<meta charset="utf-8">
|
||||
<link href="https://assets.gitlab-static.net" rel="dns-prefetch">
|
||||
<link crossorigin="" href="https://assets.gitlab-static.net" rel="preconnnect">
|
||||
<link href="https://example.com" rel="dns-prefetch">
|
||||
<link crossorigin="" href="https://example.com" rel="preconnnect">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="object" property="og:type">
|
||||
<meta content="GitLab" property="og:site_name">
|
||||
<meta content="Test Merge Request (!1) · Merge Requests · sourcegraph / jsonrpc2" property="og:title">
|
||||
<meta content="A merge request for testing purposes (used in our tests)" property="og:description">
|
||||
<meta content="https://assets.gitlab-static.net/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png" property="og:image">
|
||||
<meta content="https://example.com/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png" property="og:image">
|
||||
<meta content="64" property="og:image:width">
|
||||
<meta content="64" property="og:image:height">
|
||||
<meta content="https://gitlab.com/sourcegraph/jsonrpc2/merge_requests/1" property="og:url">
|
||||
<meta content="summary" property="twitter:card">
|
||||
<meta content="Test Merge Request (!1) · Merge Requests · sourcegraph / jsonrpc2" property="twitter:title">
|
||||
<meta content="A merge request for testing purposes (used in our tests)" property="twitter:description">
|
||||
<meta content="https://assets.gitlab-static.net/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png" property="twitter:image">
|
||||
<meta content="https://example.com/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png" property="twitter:image">
|
||||
<meta property="twitter:label1" content="Author"><meta property="twitter:data1" content="Felix Becker">
|
||||
<title>Test Merge Request (!1) · Merge Requests · sourcegraph / jsonrpc2 · GitLab</title>
|
||||
<meta content="A merge request for testing purposes (used in our tests)" name="description">
|
||||
<link rel="shortcut icon" type="image/png" href="https://gitlab.com/assets/favicon-7901bd695fb93edb07975966062049829afb56cf11511236e61bcf425070e36e.png" id="favicon" data-original-href="https://gitlab.com/assets/favicon-7901bd695fb93edb07975966062049829afb56cf11511236e61bcf425070e36e.png">
|
||||
<link rel="stylesheet" media="all" href="https://assets.gitlab-static.net/assets/application-b5479da436d0a5238c900951dd2549fe6cb7160b1896f39ef3c7aeb1a5863aeb.css">
|
||||
<link rel="stylesheet" media="print" href="https://assets.gitlab-static.net/assets/print-74c3df10dad473d66660c828e3aa54ca3bfeac6d8bb708643331403fe7211e60.css">
|
||||
<link rel="stylesheet" media="all" href="https://example.com/assets/application-b5479da436d0a5238c900951dd2549fe6cb7160b1896f39ef3c7aeb1a5863aeb.css">
|
||||
<link rel="stylesheet" media="print" href="https://example.com/assets/print-74c3df10dad473d66660c828e3aa54ca3bfeac6d8bb708643331403fe7211e60.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" media="all" href="https://assets.gitlab-static.net/assets/highlight/themes/dark-b079013cfc8e90eab11e6bf2ae08c9f7df18bb77602a480ced3ef903912a9476.css">
|
||||
<script async="" src="https://assets.gitlab-static.net/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js"></script><script nonce="">
|
||||
<link rel="stylesheet" media="all" href="https://example.com/assets/highlight/themes/dark-b079013cfc8e90eab11e6bf2ae08c9f7df18bb77602a480ced3ef903912a9476.css">
|
||||
<script async="" src="https://example.com/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js"></script><script nonce="">
|
||||
//<![CDATA[
|
||||
window.gon={};gon.api_version="v4";gon.default_avatar_url="https://assets.gitlab-static.net/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png";gon.max_file_size=10;gon.asset_host="https://assets.gitlab-static.net";gon.webpack_public_path="https://assets.gitlab-static.net/assets/webpack/";gon.relative_url_root="";gon.shortcuts_path="/help/shortcuts";gon.user_color_scheme="dark";gon.sentry_dsn="https://526a2f38a53d44e3a8e69bfa001d1e8b@sentry.gitlab.net/15";gon.sentry_environment=null;gon.gitlab_url="https://gitlab.com";gon.revision="0bf60009bec";gon.gitlab_logo="https://assets.gitlab-static.net/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png";gon.sprite_icons="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg";gon.sprite_file_icons="https://gitlab.com/assets/file_icons-7262fc6897e02f1ceaf8de43dc33afa5e4f9a2067f4f68ef77dcc87946575e9e.svg";gon.emoji_sprites_css_path="https://assets.gitlab-static.net/assets/emoji_sprites-289eccffb1183c188b630297431be837765d9ff4aed6130cf738586fb307c170.css";gon.test_env=false;gon.suggested_label_colors={"#0033CC":"UA blue","#428BCA":"Moderate blue","#44AD8E":"Lime green","#A8D695":"Feijoa","#5CB85C":"Slightly desaturated green","#69D100":"Bright green","#004E00":"Very dark lime green","#34495E":"Very dark desaturated blue","#7F8C8D":"Dark grayish cyan","#A295D6":"Slightly desaturated blue","#5843AD":"Dark moderate blue","#8E44AD":"Dark moderate violet","#FFECDB":"Very pale orange","#AD4363":"Dark moderate pink","#D10069":"Strong pink","#CC0033":"Strong red","#FF0000":"Pure red","#D9534F":"Soft red","#D1D100":"Strong yellow","#F0AD4E":"Soft orange","#AD8D43":"Dark moderate orange"};gon.first_day_of_week=0;gon.ee=true;gon.current_user_id=2479048;gon.current_username="felixfbecker";gon.current_user_fullname="Felix Becker";gon.current_user_avatar_url="https://secure.gravatar.com/avatar/136cfa95366534bfa42f55becb1be434?s=80\u0026d=identicon";gon.features={"suppressAjaxNavigationErrors":true,"scopedLabels":true,"diffsBatchLoad":false,"vueIssuableSidebar":false,"releaseSearchFilter":true,"sastMergeRequestReportApi":true,"dastMergeRequestReportApi":true,"containerScanningMergeRequestReportApi":true,"dependencyScanningMergeRequestReportApi":true,"parsedLicenseReport":true,"anonymousVisualReviewFeedback":false};gon.sourcegraph={"url":"https://sourcegraph.com"};
|
||||
window.gon={};gon.api_version="v4";gon.default_avatar_url="https://example.com/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png";gon.max_file_size=10;gon.asset_host="https://example.com";gon.webpack_public_path="https://example.com/assets/webpack/";gon.relative_url_root="";gon.shortcuts_path="/help/shortcuts";gon.user_color_scheme="dark";gon.sentry_dsn="https://526a2f38a53d44e3a8e69bfa001d1e8b@sentry.gitlab.net/15";gon.sentry_environment=null;gon.gitlab_url="https://gitlab.com";gon.revision="0bf60009bec";gon.gitlab_logo="https://example.com/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png";gon.sprite_icons="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg";gon.sprite_file_icons="https://gitlab.com/assets/file_icons-7262fc6897e02f1ceaf8de43dc33afa5e4f9a2067f4f68ef77dcc87946575e9e.svg";gon.emoji_sprites_css_path="https://example.com/assets/emoji_sprites-289eccffb1183c188b630297431be837765d9ff4aed6130cf738586fb307c170.css";gon.test_env=false;gon.suggested_label_colors={"#0033CC":"UA blue","#428BCA":"Moderate blue","#44AD8E":"Lime green","#A8D695":"Feijoa","#5CB85C":"Slightly desaturated green","#69D100":"Bright green","#004E00":"Very dark lime green","#34495E":"Very dark desaturated blue","#7F8C8D":"Dark grayish cyan","#A295D6":"Slightly desaturated blue","#5843AD":"Dark moderate blue","#8E44AD":"Dark moderate violet","#FFECDB":"Very pale orange","#AD4363":"Dark moderate pink","#D10069":"Strong pink","#CC0033":"Strong red","#FF0000":"Pure red","#D9534F":"Soft red","#D1D100":"Strong yellow","#F0AD4E":"Soft orange","#AD8D43":"Dark moderate orange"};gon.first_day_of_week=0;gon.ee=true;gon.current_user_id=2479048;gon.current_username="felixfbecker";gon.current_user_fullname="Felix Becker";gon.current_user_avatar_url="https://secure.gravatar.com/avatar/136cfa95366534bfa42f55becb1be434?s=80\u0026d=identicon";gon.features={"suppressAjaxNavigationErrors":true,"scopedLabels":true,"diffsBatchLoad":false,"vueIssuableSidebar":false,"releaseSearchFilter":true,"sastMergeRequestReportApi":true,"dastMergeRequestReportApi":true,"containerScanningMergeRequestReportApi":true,"dependencyScanningMergeRequestReportApi":true,"parsedLicenseReport":true,"anonymousVisualReviewFeedback":false};gon.sourcegraph={"url":"https://sourcegraph.com"};
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/runtime.b78871eb.bundle.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/main.45ce0eff.chunk.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/sentry.fb899e74.chunk.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/commons~pages.admin.clusters~pages.admin.clusters.destroy~pages.admin.clusters.edit~pages.admin.clus~adc06f2a.0e3f651c.chunk.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/commons~pages.groups.epics.index~pages.groups.epics.show~pages.groups.milestones.edit~pages.groups.m~b7d7bc7f.28bceb28.chunk.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/pages.projects.merge_requests.show.70ff16c6.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/runtime.b78871eb.bundle.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/main.45ce0eff.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/sentry.fb899e74.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/commons~pages.admin.clusters~pages.admin.clusters.destroy~pages.admin.clusters.edit~pages.admin.clus~adc06f2a.0e3f651c.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/commons~pages.groups.epics.index~pages.groups.epics.show~pages.groups.milestones.edit~pages.groups.m~b7d7bc7f.28bceb28.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/pages.projects.merge_requests.show.70ff16c6.chunk.js" defer="defer"></script>
|
||||
<script nonce="">
|
||||
//<![CDATA[
|
||||
window.uploads_path = "/sourcegraph/jsonrpc2/uploads";
|
||||
@ -51,12 +51,12 @@ window.uploads_path = "/sourcegraph/jsonrpc2/uploads";
|
||||
<meta content="origin-when-cross-origin" name="referrer">
|
||||
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport">
|
||||
<meta content="#474D57" name="theme-color">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://assets.gitlab-static.net/assets/touch-icon-iphone-5a9cee0e8a51212e70b90c87c12f382c428870c0ff67d1eb034d884b78d2dae7.png">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://assets.gitlab-static.net/assets/touch-icon-ipad-a6eec6aeb9da138e507593b464fdac213047e49d3093fc30e90d9a995df83ba3.png" sizes="76x76">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://assets.gitlab-static.net/assets/touch-icon-iphone-retina-72e2aadf86513a56e050e7f0f2355deaa19cc17ed97bbe5147847f2748e5a3e3.png" sizes="120x120">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://assets.gitlab-static.net/assets/touch-icon-ipad-retina-8ebe416f5313483d9c1bc772b5bbe03ecad52a54eba443e5215a22caed2a16a2.png" sizes="152x152">
|
||||
<link color="rgb(226, 67, 41)" href="https://assets.gitlab-static.net/assets/logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg" rel="mask-icon">
|
||||
<meta content="https://assets.gitlab-static.net/assets/msapplication-tile-1196ec67452f618d39cdd85e2e3a542f76574c071051ae7effbfde01710eb17d.png" name="msapplication-TileImage">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://example.com/assets/touch-icon-iphone-5a9cee0e8a51212e70b90c87c12f382c428870c0ff67d1eb034d884b78d2dae7.png">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://example.com/assets/touch-icon-ipad-a6eec6aeb9da138e507593b464fdac213047e49d3093fc30e90d9a995df83ba3.png" sizes="76x76">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://example.com/assets/touch-icon-iphone-retina-72e2aadf86513a56e050e7f0f2355deaa19cc17ed97bbe5147847f2748e5a3e3.png" sizes="120x120">
|
||||
<link rel="apple-touch-icon" type="image/x-icon" href="https://example.com/assets/touch-icon-ipad-retina-8ebe416f5313483d9c1bc772b5bbe03ecad52a54eba443e5215a22caed2a16a2.png" sizes="152x152">
|
||||
<link color="rgb(226, 67, 41)" href="https://example.com/assets/logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg" rel="mask-icon">
|
||||
<meta content="https://example.com/assets/msapplication-tile-1196ec67452f618d39cdd85e2e3a542f76574c071051ae7effbfde01710eb17d.png" name="msapplication-TileImage">
|
||||
<meta content="#30353E" name="msapplication-TileColor">
|
||||
|
||||
|
||||
@ -66,7 +66,7 @@ window.uploads_path = "/sourcegraph/jsonrpc2/uploads";
|
||||
;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[];
|
||||
p.GlobalSnowplowNamespace.push(i);p[i]=function(){(p[i].q=p[i].q||[]).push(arguments)
|
||||
};p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1;
|
||||
n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","https://assets.gitlab-static.net/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js","snowplow"));
|
||||
n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","https://example.com/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js","snowplow"));
|
||||
|
||||
window.snowplowOptions = {"namespace":"gl","hostname":"snowplow.trx.gitlab.net","cookieDomain":".gitlab.com","appId":"gitlab","formTracking":true,"linkClickTracking":true,"igluRegistryUrl":null}
|
||||
|
||||
@ -221,7 +221,7 @@ to {
|
||||
border: 1px solid;
|
||||
color: #707070;
|
||||
}
|
||||
</style><script charset="utf-8" src="https://assets.gitlab-static.net/assets/webpack/vendors~select2.445b4f0c.chunk.js"></script><script type="application/javascript" src="https://gitlab.com/assets/webpack/sourcegraph/scripts/integration.bundle.js" defer=""></script><link rel="stylesheet" type="text/css" href="https://gitlab.com/assets/webpack/sourcegraph/css/style.bundle.css" id="sourcegraph-styles"></head>
|
||||
</style><script charset="utf-8" src="https://example.com/assets/webpack/vendors~select2.445b4f0c.chunk.js"></script><script type="application/javascript" src="https://gitlab.com/assets/webpack/sourcegraph/scripts/integration.bundle.js" defer=""></script><link rel="stylesheet" type="text/css" href="https://gitlab.com/assets/webpack/sourcegraph/css/style.bundle.css" id="sourcegraph-styles"></head>
|
||||
|
||||
<body class="ui-indigo gl-browser-chrome gl-platform-mac" data-find-file="/sourcegraph/jsonrpc2/find_file/master" data-group="" data-page="projects:merge_requests:show" data-project="jsonrpc2">
|
||||
<script nonce="">
|
||||
@ -678,7 +678,7 @@ Activity
|
||||
<i aria-hidden="true" data-hidden="true" class="fa fa-bars"></i>
|
||||
</button><div class="breadcrumbs-links js-title-container">
|
||||
<ul class="list-unstyled breadcrumbs-list js-breadcrumbs-list">
|
||||
<li><a class="group-path breadcrumb-item-text js-breadcrumb-item-text " href="/sourcegraph"><img class="avatar-tile js-lazy-loaded qa-js-lazy-loaded" width="15" height="15" src="https://assets.gitlab-static.net/uploads/-/system/group/avatar/2582152/3979584.png?width=15">sourcegraph</a><svg class="s8 breadcrumbs-list-angle"><use xlink:href="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg#angle-right"></use></svg></li> <li><a href="/sourcegraph/jsonrpc2"><span class="breadcrumb-item-text js-breadcrumb-item-text">jsonrpc2</span></a><svg class="s8 breadcrumbs-list-angle"><use xlink:href="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg#angle-right"></use></svg></li>
|
||||
<li><a class="group-path breadcrumb-item-text js-breadcrumb-item-text " href="/sourcegraph"><img class="avatar-tile js-lazy-loaded qa-js-lazy-loaded" width="15" height="15" src="https://example.com/uploads/-/system/group/avatar/2582152/3979584.png?width=15">sourcegraph</a><svg class="s8 breadcrumbs-list-angle"><use xlink:href="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg#angle-right"></use></svg></li> <li><a href="/sourcegraph/jsonrpc2"><span class="breadcrumb-item-text js-breadcrumb-item-text">jsonrpc2</span></a><svg class="s8 breadcrumbs-list-angle"><use xlink:href="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg#angle-right"></use></svg></li>
|
||||
<li><a href="/sourcegraph/jsonrpc2/merge_requests">Merge Requests</a><svg class="s8 breadcrumbs-list-angle"><use xlink:href="https://gitlab.com/assets/icons-312c16d38220d2412b554d43f05ac0ffa8a701e91fb02cd4332740f6b87ebb5b.svg#angle-right"></use></svg></li>
|
||||
|
||||
<li>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
<html class="" lang="en">
|
||||
<head prefix="og: http://ogp.me/ns#">
|
||||
<meta charset="utf-8" />
|
||||
<link href="https://assets.gitlab-static.net" rel="dns-prefetch" />
|
||||
<link crossorigin="" href="https://assets.gitlab-static.net" rel="preconnnect" />
|
||||
<link href="https://example.com" rel="dns-prefetch" />
|
||||
<link crossorigin="" href="https://example.com" rel="preconnnect" />
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
|
||||
<meta content="object" property="og:type" />
|
||||
<meta content="GitLab" property="og:site_name" />
|
||||
@ -29,32 +29,32 @@
|
||||
<link
|
||||
rel="stylesheet"
|
||||
media="all"
|
||||
href="https://assets.gitlab-static.net/assets/application-f7d1309f3caef67cb63bd114c85e73b323a97d145ceca7d6ef3c1c010078c649.css"
|
||||
href="https://example.com/assets/application-f7d1309f3caef67cb63bd114c85e73b323a97d145ceca7d6ef3c1c010078c649.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
media="print"
|
||||
href="https://assets.gitlab-static.net/assets/print-c8ff536271f8974b8a9a5f75c0ca25d2b8c1dceb4cff3c01d1603862a0bdcbfc.css"
|
||||
href="https://example.com/assets/print-c8ff536271f8974b8a9a5f75c0ca25d2b8c1dceb4cff3c01d1603862a0bdcbfc.css"
|
||||
/>
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
media="all"
|
||||
href="https://assets.gitlab-static.net/assets/highlight/themes/white-a165d47ce52cf24c29686366976ae691bd9addb9641a6abeb3ba6d1823b89aa8.css"
|
||||
href="https://example.com/assets/highlight/themes/white-a165d47ce52cf24c29686366976ae691bd9addb9641a6abeb3ba6d1823b89aa8.css"
|
||||
/>
|
||||
<script
|
||||
async=""
|
||||
src="https://assets.gitlab-static.net/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js"
|
||||
src="https://example.com/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js"
|
||||
></script>
|
||||
<script>
|
||||
//<![CDATA[
|
||||
window.gon = {}
|
||||
gon.api_version = 'v4'
|
||||
gon.default_avatar_url =
|
||||
'https://assets.gitlab-static.net/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png'
|
||||
'https://example.com/assets/no_avatar-849f9c04a3a0d0cea2424ae97b27447dc64a7dbfae83c036c45b403392f0e8ba.png'
|
||||
gon.max_file_size = 10
|
||||
gon.asset_host = 'https://assets.gitlab-static.net'
|
||||
gon.webpack_public_path = 'https://assets.gitlab-static.net/assets/webpack/'
|
||||
gon.asset_host = 'https://example.com'
|
||||
gon.webpack_public_path = 'https://example.com/assets/webpack/'
|
||||
gon.relative_url_root = ''
|
||||
gon.shortcuts_path = '/help/shortcuts'
|
||||
gon.user_color_scheme = 'white'
|
||||
@ -62,13 +62,13 @@
|
||||
gon.gitlab_url = 'https://gitlab.com'
|
||||
gon.revision = '5c22049'
|
||||
gon.gitlab_logo =
|
||||
'https://assets.gitlab-static.net/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png'
|
||||
'https://example.com/assets/gitlab_logo-7ae504fe4f68fdebb3c2034e36621930cd36ea87924c11ff65dbcb8ed50dca58.png'
|
||||
gon.sprite_icons =
|
||||
'https://gitlab.com/assets/icons-24aaa921aa9e411162e6913688816c79861d0de4bee876cf6fc4c794be34ee91.svg'
|
||||
gon.sprite_file_icons =
|
||||
'https://gitlab.com/assets/file_icons-7262fc6897e02f1ceaf8de43dc33afa5e4f9a2067f4f68ef77dcc87946575e9e.svg'
|
||||
gon.emoji_sprites_css_path =
|
||||
'https://assets.gitlab-static.net/assets/emoji_sprites-289eccffb1183c188b630297431be837765d9ff4aed6130cf738586fb307c170.css'
|
||||
'https://example.com/assets/emoji_sprites-289eccffb1183c188b630297431be837765d9ff4aed6130cf738586fb307c170.css'
|
||||
gon.test_env = false
|
||||
gon.suggested_label_colors = [
|
||||
'#0033CC',
|
||||
@ -98,19 +98,19 @@
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/runtime.70f00925.bundle.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/main.593a83e9.chunk.js" defer="defer"></script>
|
||||
<script src="https://assets.gitlab-static.net/assets/webpack/raven.25e661a4.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/runtime.70f00925.bundle.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/main.593a83e9.chunk.js" defer="defer"></script>
|
||||
<script src="https://example.com/assets/webpack/raven.25e661a4.chunk.js" defer="defer"></script>
|
||||
<script
|
||||
src="https://assets.gitlab-static.net/assets/webpack/commons~pages.groups~pages.groups.activity~pages.groups.analytics.show~pages.groups.billings~pages.g~f1af234d.d92789b8.chunk.js"
|
||||
src="https://example.com/assets/webpack/commons~pages.groups~pages.groups.activity~pages.groups.analytics.show~pages.groups.billings~pages.g~f1af234d.d92789b8.chunk.js"
|
||||
defer="defer"
|
||||
></script>
|
||||
<script
|
||||
src="https://assets.gitlab-static.net/assets/webpack/commons~pages.groups.epics.index~pages.groups.epics.show~pages.groups.milestones.edit~pages.groups.m~14875979.557c2633.chunk.js"
|
||||
src="https://example.com/assets/webpack/commons~pages.groups.epics.index~pages.groups.epics.show~pages.groups.milestones.edit~pages.groups.m~14875979.557c2633.chunk.js"
|
||||
defer="defer"
|
||||
></script>
|
||||
<script
|
||||
src="https://assets.gitlab-static.net/assets/webpack/pages.projects.tree.show.b71a592d.chunk.js"
|
||||
src="https://example.com/assets/webpack/pages.projects.tree.show.b71a592d.chunk.js"
|
||||
defer="defer"
|
||||
></script>
|
||||
|
||||
@ -125,33 +125,33 @@
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
type="image/x-icon"
|
||||
href="https://assets.gitlab-static.net/assets/touch-icon-iphone-5a9cee0e8a51212e70b90c87c12f382c428870c0ff67d1eb034d884b78d2dae7.png"
|
||||
href="https://example.com/assets/touch-icon-iphone-5a9cee0e8a51212e70b90c87c12f382c428870c0ff67d1eb034d884b78d2dae7.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
type="image/x-icon"
|
||||
href="https://assets.gitlab-static.net/assets/touch-icon-ipad-a6eec6aeb9da138e507593b464fdac213047e49d3093fc30e90d9a995df83ba3.png"
|
||||
href="https://example.com/assets/touch-icon-ipad-a6eec6aeb9da138e507593b464fdac213047e49d3093fc30e90d9a995df83ba3.png"
|
||||
sizes="76x76"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
type="image/x-icon"
|
||||
href="https://assets.gitlab-static.net/assets/touch-icon-iphone-retina-72e2aadf86513a56e050e7f0f2355deaa19cc17ed97bbe5147847f2748e5a3e3.png"
|
||||
href="https://example.com/assets/touch-icon-iphone-retina-72e2aadf86513a56e050e7f0f2355deaa19cc17ed97bbe5147847f2748e5a3e3.png"
|
||||
sizes="120x120"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
type="image/x-icon"
|
||||
href="https://assets.gitlab-static.net/assets/touch-icon-ipad-retina-8ebe416f5313483d9c1bc772b5bbe03ecad52a54eba443e5215a22caed2a16a2.png"
|
||||
href="https://example.com/assets/touch-icon-ipad-retina-8ebe416f5313483d9c1bc772b5bbe03ecad52a54eba443e5215a22caed2a16a2.png"
|
||||
sizes="152x152"
|
||||
/>
|
||||
<link
|
||||
color="rgb(226, 67, 41)"
|
||||
href="https://assets.gitlab-static.net/assets/logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg"
|
||||
href="https://example.com/assets/logo-d36b5212042cebc89b96df4bf6ac24e43db316143e89926c0db839ff694d2de4.svg"
|
||||
rel="mask-icon"
|
||||
/>
|
||||
<meta
|
||||
content="https://assets.gitlab-static.net/assets/msapplication-tile-1196ec67452f618d39cdd85e2e3a542f76574c071051ae7effbfde01710eb17d.png"
|
||||
content="https://example.com/assets/msapplication-tile-1196ec67452f618d39cdd85e2e3a542f76574c071051ae7effbfde01710eb17d.png"
|
||||
name="msapplication-TileImage"
|
||||
/>
|
||||
<meta content="#30353E" name="msapplication-TileColor" />
|
||||
@ -181,7 +181,7 @@
|
||||
window,
|
||||
document,
|
||||
'script',
|
||||
'https://assets.gitlab-static.net/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js',
|
||||
'https://example.com/assets/snowplow/sp-e10fd598642f1a4dd3e9e0e026f6a1ffa3c31b8a40efd92db3f92d32873baed6.js',
|
||||
'snowplow'
|
||||
)
|
||||
|
||||
@ -204,7 +204,7 @@
|
||||
|
||||
<script
|
||||
charset="utf-8"
|
||||
src="https://assets.gitlab-static.net/assets/webpack/vendors~select2.910dc55c.chunk.js"
|
||||
src="https://example.com/assets/webpack/vendors~select2.910dc55c.chunk.js"
|
||||
></script>
|
||||
</head>
|
||||
|
||||
@ -468,7 +468,7 @@
|
||||
class="avatar s40 avatar-tile js-lazy-loaded qa-js-lazy-loaded"
|
||||
width="40"
|
||||
height="40"
|
||||
src="https://assets.gitlab-static.net/uploads/-/system/project/avatar/250833/runner_logo.png?width=40"
|
||||
src="https://example.com/uploads/-/system/project/avatar/250833/runner_logo.png?width=40"
|
||||
/>
|
||||
</div>
|
||||
<div class="sidebar-context-title">
|
||||
@ -869,7 +869,7 @@
|
||||
class="avatar-tile js-lazy-loaded qa-js-lazy-loaded"
|
||||
width="15"
|
||||
height="15"
|
||||
src="https://assets.gitlab-static.net/uploads/-/system/group/avatar/9970/logo-extra-whitespace.png?width=15"
|
||||
src="https://example.com/uploads/-/system/group/avatar/9970/logo-extra-whitespace.png?width=15"
|
||||
/>GitLab.org</a
|
||||
><svg class="s8 breadcrumbs-list-angle">
|
||||
<use
|
||||
@ -884,7 +884,7 @@
|
||||
class="avatar-tile js-lazy-loaded qa-js-lazy-loaded"
|
||||
width="15"
|
||||
height="15"
|
||||
src="https://assets.gitlab-static.net/uploads/-/system/project/avatar/250833/runner_logo.png?width=15"
|
||||
src="https://example.com/uploads/-/system/project/avatar/250833/runner_logo.png?width=15"
|
||||
/><span class="breadcrumb-item-text js-breadcrumb-item-text"
|
||||
>gitlab-runner</span
|
||||
></a
|
||||
|
||||
@ -6,7 +6,13 @@ import { disableFetchCache, enableFetchCache, fetchCache, type LineOrPositionOrR
|
||||
|
||||
import { testCodeHostMountGetters as testMountGetters, testToolbarMountGetter } from '../shared/codeHostTestUtils'
|
||||
|
||||
import { getToolbarMount, gitlabCodeHost, isPrivateRepository, parseHash } from './codeHost'
|
||||
import {
|
||||
getToolbarMount,
|
||||
gitlabCodeHost,
|
||||
isPrivateRepository,
|
||||
parseHash,
|
||||
windowLocation__testingOnly,
|
||||
} from './codeHost'
|
||||
import { repoNameOnSourcegraph } from './scrape'
|
||||
|
||||
describe('gitlab/codeHost', () => {
|
||||
@ -23,11 +29,14 @@ describe('gitlab/codeHost', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
document.documentElement.innerHTML = await readFile(__dirname + '/__fixtures__/merge-request.html', 'utf-8')
|
||||
jsdom.reconfigure({ url: 'https://gitlab.com/SourcegraphCody/jsonrpc2/merge_requests/1/diffs' })
|
||||
windowLocation__testingOnly.value = new URL(
|
||||
'https://gitlab.com/SourcegraphCody/jsonrpc2/merge_requests/1/diffs'
|
||||
)
|
||||
globalThis.gon = { gitlab_url: 'https://gitlab.com' }
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
windowLocation__testingOnly.value = null
|
||||
// Reset resolved Sourcegraph repo name value
|
||||
repoNameOnSourcegraph.next('')
|
||||
})
|
||||
|
||||
@ -186,6 +186,14 @@ export const parseHash = (hash: string): LineOrPositionOrRange => {
|
||||
return lpr
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing only, used to set the window.location value.
|
||||
* @internal
|
||||
*/
|
||||
export const windowLocation__testingOnly: { value: URL | null } = {
|
||||
value: null,
|
||||
}
|
||||
|
||||
export const gitlabCodeHost = subtypeOf<CodeHost>()({
|
||||
type: 'gitlab',
|
||||
name: 'GitLab',
|
||||
@ -202,7 +210,10 @@ export const gitlabCodeHost = subtypeOf<CodeHost>()({
|
||||
// A view state means that a panel must be shown, and panels are currently only supported on
|
||||
// Sourcegraph (not code hosts).
|
||||
// Make sure the location is also on this Gitlab instance, return an absolute URL otherwise.
|
||||
if (target.viewState || !target.rawRepoName.startsWith(window.location.hostname)) {
|
||||
if (
|
||||
target.viewState ||
|
||||
!target.rawRepoName.startsWith((windowLocation__testingOnly.value ?? window.location).hostname)
|
||||
) {
|
||||
return toAbsoluteBlobURL(sourcegraphURL, target)
|
||||
}
|
||||
|
||||
@ -217,7 +228,7 @@ export const gitlabCodeHost = subtypeOf<CodeHost>()({
|
||||
continue
|
||||
}
|
||||
if (!target.position) {
|
||||
const url = new URL(window.location.href)
|
||||
const url = new URL((windowLocation__testingOnly.value ?? window.location).href)
|
||||
url.hash = codeView.id
|
||||
return url.href
|
||||
}
|
||||
@ -225,10 +236,14 @@ export const gitlabCodeHost = subtypeOf<CodeHost>()({
|
||||
const link = codeView.querySelector<HTMLAnchorElement>(
|
||||
`${partSelector} a[data-linenumber="${target.position.line}"]`
|
||||
)
|
||||
if (!link) {
|
||||
|
||||
// Use link.getAttribute('href') because link.href silently resolves against the the
|
||||
// jsdom current URL (https://localhost:3000) in testing.
|
||||
const href = link?.getAttribute('href')
|
||||
if (!href) {
|
||||
break
|
||||
}
|
||||
return new URL(link.href).href
|
||||
return new URL(href, windowLocation__testingOnly.value ?? window.location.href).href
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +282,7 @@ export const gitlabCodeHost = subtypeOf<CodeHost>()({
|
||||
// despite the URL hash is updated.
|
||||
observeLineSelection: fromEvent(document, 'click').pipe(
|
||||
filter(event => (event.target as HTMLElement).matches('a[data-line-number]')),
|
||||
map(() => parseHash(window.location.hash))
|
||||
map(() => parseHash((windowLocation__testingOnly.value ?? window.location).hash))
|
||||
),
|
||||
|
||||
prepareCodeHost: async requestGraphQL =>
|
||||
|
||||
@ -123,7 +123,8 @@ function mockQueryConduit(responseMap?: ConduitResponseMap): QueryConduitHelper<
|
||||
type Resolver = (
|
||||
codeView: HTMLElement,
|
||||
requestGraphQL: PlatformContext['requestGraphQL'],
|
||||
queryConduit: QueryConduitHelper<any>
|
||||
queryConduit: QueryConduitHelper<any>,
|
||||
windowLocation__testingOnly: Location | URL
|
||||
) => Observable<DiffOrBlobInfo>
|
||||
|
||||
interface Fixture {
|
||||
@ -140,7 +141,6 @@ const resolveFileInfoFromFixture = async (
|
||||
): Promise<DiffOrBlobInfo> => {
|
||||
const fixtureContent = await readFile(`${__dirname}/__fixtures__/pages/${htmlFixture}`, 'utf-8')
|
||||
document.body.innerHTML = fixtureContent
|
||||
jsdom.reconfigure({ url })
|
||||
const codeView = document.querySelector(codeViewSelector)
|
||||
if (!codeView) {
|
||||
throw new Error(`Code view matching selector ${codeViewSelector} not found`)
|
||||
@ -151,7 +151,8 @@ const resolveFileInfoFromFixture = async (
|
||||
...DEFAULT_GRAPHQL_RESPONSES,
|
||||
...graphQLResponseMap,
|
||||
}),
|
||||
mockQueryConduit(conduitResponseMap)
|
||||
mockQueryConduit(conduitResponseMap),
|
||||
new URL(url)
|
||||
).toPromise()
|
||||
}
|
||||
|
||||
|
||||
@ -13,9 +13,10 @@ import { getPhabricatorState } from './util'
|
||||
export const resolveRevisionFileInfo = (
|
||||
codeView: HTMLElement,
|
||||
requestGraphQL: PlatformContext['requestGraphQL'],
|
||||
queryConduit = queryConduitHelper
|
||||
queryConduit = queryConduitHelper,
|
||||
windowLocation__testingOnly: Location | URL = window.location
|
||||
): Observable<DiffInfo> =>
|
||||
getPhabricatorState(window.location, requestGraphQL, queryConduit).pipe(
|
||||
getPhabricatorState(windowLocation__testingOnly, requestGraphQL, queryConduit).pipe(
|
||||
map((state): DiffInfo => {
|
||||
if (state.mode !== PhabricatorMode.Revision) {
|
||||
throw new Error(
|
||||
@ -42,9 +43,10 @@ export const resolveRevisionFileInfo = (
|
||||
export const resolveDiffFileInfo = (
|
||||
codeView: HTMLElement,
|
||||
requestGraphQL: PlatformContext['requestGraphQL'],
|
||||
queryConduit = queryConduitHelper
|
||||
queryConduit = queryConduitHelper,
|
||||
windowLocation__testingOnly: Location | URL = window.location
|
||||
): Observable<DiffInfo> =>
|
||||
getPhabricatorState(window.location, requestGraphQL, queryConduit).pipe(
|
||||
getPhabricatorState(windowLocation__testingOnly, requestGraphQL, queryConduit).pipe(
|
||||
switchMap(state => {
|
||||
if (state.mode !== PhabricatorMode.Differential) {
|
||||
throw new Error(`Unexpected PhabricatorState for resolveDiffFileInfo, PhabricatorMode: ${state.mode}`)
|
||||
@ -116,9 +118,10 @@ export const resolveDiffFileInfo = (
|
||||
export const resolveDiffusionFileInfo = (
|
||||
codeView: HTMLElement,
|
||||
requestGraphQL: PlatformContext['requestGraphQL'],
|
||||
queryConduit = queryConduitHelper
|
||||
queryConduit = queryConduitHelper,
|
||||
windowLocation__testingOnly: Location | URL = window.location
|
||||
): Observable<BlobInfo> =>
|
||||
getPhabricatorState(window.location, requestGraphQL, queryConduit).pipe(
|
||||
getPhabricatorState(windowLocation__testingOnly, requestGraphQL, queryConduit).pipe(
|
||||
map((state): BlobInfo => {
|
||||
if (state.mode !== PhabricatorMode.Diffusion) {
|
||||
throw new Error(
|
||||
|
||||
@ -79,7 +79,7 @@ function getBaseCommitIDFromRevisionPage(): string {
|
||||
}
|
||||
|
||||
export function getPhabricatorState(
|
||||
location: Location,
|
||||
location: URL | Location,
|
||||
requestGraphQL: PlatformContext['requestGraphQL'],
|
||||
queryConduit: QueryConduitHelper<any>
|
||||
): Observable<DiffusionState | DifferentialState | RevisionState | ChangeState> {
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import assert from 'assert'
|
||||
|
||||
import { beforeEach, describe, expect, it } from '@jest/globals'
|
||||
import { afterEach, beforeEach, describe, expect, it } from '@jest/globals'
|
||||
import { readFile } from 'mz/fs'
|
||||
import Simmer, { type Options as SimmerOptions } from 'simmerjs'
|
||||
import type { SetIntersection } from 'utility-types'
|
||||
|
||||
import type { DiffPart } from '@sourcegraph/codeintellify'
|
||||
|
||||
import { windowLocation__testingOnly as windowLocation__testingOnly__github } from '../github/util'
|
||||
|
||||
import type { CodeHost, MountGetter } from './codeHost'
|
||||
import type { CodeView, DOMFunctions } from './codeViews'
|
||||
|
||||
@ -154,10 +156,13 @@ export function testDOMFunctions(
|
||||
let codeViewElement: HTMLElement
|
||||
beforeEach(async () => {
|
||||
if (url) {
|
||||
jsdom.reconfigure({ url })
|
||||
windowLocation__testingOnly__github.value = new URL(url)
|
||||
}
|
||||
codeViewElement = await getFixtureBody({ htmlFixturePath, isFullDocument: false })
|
||||
})
|
||||
afterEach(() => {
|
||||
windowLocation__testingOnly__github.value = null
|
||||
})
|
||||
for (const { diffPart, lineNumber, firstCharacterIsDiffIndicator } of codeElements) {
|
||||
describe(
|
||||
`line number ${lineNumber}` + (diffPart !== undefined ? ` in ${String(diffPart)} diff part` : ''),
|
||||
|
||||
@ -4,7 +4,7 @@ import { from, type Observable, of, Subject, Subscription, NEVER } from 'rxjs'
|
||||
import { bufferCount, map, switchMap, toArray } from 'rxjs/operators'
|
||||
import * as sinon from 'sinon'
|
||||
|
||||
import { createBarrier } from '@sourcegraph/shared/src/testing/testHelpers'
|
||||
import { createBarrier } from '@sourcegraph/testing'
|
||||
|
||||
import type { MutationRecordLike } from '../../util/dom'
|
||||
|
||||
|
||||
@ -51,5 +51,8 @@
|
||||
{
|
||||
"path": "../wildcard",
|
||||
},
|
||||
{
|
||||
"path": "../testing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@ -25,10 +25,5 @@
|
||||
"sass": "^1.32.4",
|
||||
"signale": "^1.4.0",
|
||||
"typed-scss-modules": "^4.1.1"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
"ignoreMissing": ["webpack"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,8 +122,11 @@ export const encodeURIPathComponent = (component: string): string =>
|
||||
/**
|
||||
* Returns true if the given URL points outside the current site.
|
||||
*/
|
||||
export const isExternalLink = (url: string): boolean =>
|
||||
!!tryCatch(() => new URL(url, window.location.href).origin !== window.location.origin)
|
||||
export const isExternalLink = (
|
||||
url: string,
|
||||
windowLocation__testingOnly: Pick<URL, 'origin' | 'href'> = window.location
|
||||
): boolean =>
|
||||
!!tryCatch(() => new URL(url, windowLocation__testingOnly.href).origin !== windowLocation__testingOnly.origin)
|
||||
|
||||
/**
|
||||
* Stringifies the provided search parameters, replaces encoded `/` and `:` characters,
|
||||
|
||||
@ -12,6 +12,7 @@ ts_config(
|
||||
deps = [
|
||||
"//:tsconfig",
|
||||
"//client/common:tsconfig",
|
||||
"//client/testing:tsconfig",
|
||||
],
|
||||
)
|
||||
|
||||
@ -57,6 +58,7 @@ ts_project(
|
||||
tsconfig = ":tsconfig",
|
||||
deps = [
|
||||
":http-client_lib",
|
||||
":node_modules/@sourcegraph/testing",
|
||||
"//:node_modules/@apollo/client",
|
||||
"//:node_modules/@jest/globals",
|
||||
"//:node_modules/@types/sinon",
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sourcegraph/common": "workspace:*"
|
||||
"@sourcegraph/common": "workspace:*",
|
||||
"@sourcegraph/testing": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,8 @@ import delay from 'delay'
|
||||
import { isObservable } from 'rxjs'
|
||||
import sinon from 'sinon'
|
||||
|
||||
import { createBarrier } from '@sourcegraph/testing'
|
||||
|
||||
import { fromObservableQuery, fromObservableQueryPromise } from './fromObservableQuery'
|
||||
|
||||
const QUERY_RESULT = { data: {}, loading: false, networkStatus: 1 }
|
||||
@ -25,13 +27,16 @@ describe('fromObservableQuery', () => {
|
||||
expect(isObservable(observable)).toBe(true)
|
||||
})
|
||||
|
||||
it('subscribes to `ObservableQuery` data', done => {
|
||||
it('subscribes to `ObservableQuery` data', async () => {
|
||||
const { wait, done } = createBarrier()
|
||||
const observable = fromObservableQuery(createObservableQuery())
|
||||
|
||||
// eslint-disable-next-line rxjs/no-ignored-subscription
|
||||
observable.subscribe(data => {
|
||||
expect(data).toEqual(QUERY_RESULT)
|
||||
done()
|
||||
})
|
||||
await wait
|
||||
})
|
||||
|
||||
it('exposes `ObservableQuery` unsubscribe method', () => {
|
||||
@ -49,13 +54,17 @@ describe('fromObservableQueryPromise', () => {
|
||||
expect(isObservable(observable)).toBe(true)
|
||||
})
|
||||
|
||||
it('subscribes to `ObservableQuery` data', done => {
|
||||
it('subscribes to `ObservableQuery` data', async () => {
|
||||
const { wait, done } = createBarrier()
|
||||
|
||||
const observable = fromObservableQueryPromise(Promise.resolve(createObservableQuery()))
|
||||
|
||||
// eslint-disable-next-line rxjs/no-ignored-subscription
|
||||
observable.subscribe(data => {
|
||||
expect(data).toEqual(QUERY_RESULT)
|
||||
done()
|
||||
})
|
||||
await wait
|
||||
})
|
||||
|
||||
it('exposes `ObservableQuery` unsubscribe method', () => {
|
||||
|
||||
@ -13,5 +13,8 @@
|
||||
{
|
||||
"path": "../common",
|
||||
},
|
||||
{
|
||||
"path": "../testing",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
const MOCK_ASSETS_PATH = __dirname + '/assets'
|
||||
|
||||
module.exports = {
|
||||
files: [
|
||||
{
|
||||
path: MOCK_ASSETS_PATH + '/scripts/*.js',
|
||||
maxSize: '10kb',
|
||||
},
|
||||
{
|
||||
path: MOCK_ASSETS_PATH + '/styles/*.css',
|
||||
maxSize: '10kb',
|
||||
},
|
||||
],
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
{
|
||||
"main.js": "/.assets/scripts/main.js",
|
||||
"main.css": "/.assets/styles/main.css"
|
||||
}
|
||||
@ -1,43 +1,17 @@
|
||||
import path from 'path'
|
||||
|
||||
import { describe, expect, it, jest } from '@jest/globals'
|
||||
import { describe, expect, it } from '@jest/globals'
|
||||
|
||||
import { getBundleSizeStats } from './getBundleSizeStats'
|
||||
|
||||
const MOCK_ASSETS_PATH = path.join(__dirname, './__mocks__/assets')
|
||||
|
||||
jest.mock(
|
||||
'bundlesize.config.js',
|
||||
() => ({
|
||||
files: [
|
||||
{
|
||||
path: MOCK_ASSETS_PATH + '/scripts/*.js',
|
||||
maxSize: '10kb',
|
||||
},
|
||||
{
|
||||
path: MOCK_ASSETS_PATH + '/styles/*.css',
|
||||
maxSize: '10kb',
|
||||
},
|
||||
],
|
||||
}),
|
||||
{ virtual: true }
|
||||
)
|
||||
|
||||
jest.mock(
|
||||
'web.manifest.json',
|
||||
() => ({
|
||||
'main.js': '/.assets/scripts/main.js',
|
||||
'main.css': '/.assets/styles/main.css',
|
||||
}),
|
||||
{ virtual: true }
|
||||
)
|
||||
|
||||
describe('getBundleSizeStats', () => {
|
||||
it('collects bundle stats based on bundlesize config', () => {
|
||||
const stats = getBundleSizeStats({
|
||||
staticAssetsPath: MOCK_ASSETS_PATH,
|
||||
bundlesizeConfigPath: 'bundlesize.config.js',
|
||||
webBuildManifestPath: 'web.manifest.json',
|
||||
bundlesizeConfigPath: __dirname + '/__mocks__/bundlesize.config.js',
|
||||
webBuildManifestPath: __dirname + '/__mocks__/web.manifest.json',
|
||||
})
|
||||
|
||||
expect(stats).toEqual({
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
import { describe, expect, it, test, jest } from '@jest/globals'
|
||||
import { afterEach, describe, expect, it, test, jest } from '@jest/globals'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import * as H from 'history'
|
||||
import { NEVER } from 'rxjs'
|
||||
|
||||
import { assertAriaEnabled } from '@sourcegraph/testing'
|
||||
import { assertAriaEnabled, createBarrier } from '@sourcegraph/testing'
|
||||
import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
|
||||
|
||||
import { NOOP_TELEMETRY_SERVICE } from '../telemetry/telemetryService'
|
||||
import { createBarrier } from '../testing/testHelpers'
|
||||
|
||||
import { ActionItem } from './ActionItem'
|
||||
import { ActionItem, windowLocation__testingOnly } from './ActionItem'
|
||||
|
||||
jest.mock('mdi-react/OpenInNewIcon', () => 'OpenInNewIcon')
|
||||
|
||||
@ -163,7 +162,9 @@ describe('ActionItem', () => {
|
||||
// Finish execution. (Use setTimeout to wait for the executeCommand resolution to result in the setState
|
||||
// call.)
|
||||
done()
|
||||
await new Promise<void>(resolve => setTimeout(resolve))
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId('action-item-spinner')).not.toBeInTheDocument()
|
||||
})
|
||||
expect(asFragment()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@ -195,8 +196,12 @@ describe('ActionItem', () => {
|
||||
})
|
||||
|
||||
describe('"open" command', () => {
|
||||
afterEach(() => {
|
||||
windowLocation__testingOnly.value = null
|
||||
})
|
||||
|
||||
it('renders as link', () => {
|
||||
jsdom.reconfigure({ url: 'https://example.com/foo' })
|
||||
windowLocation__testingOnly.value = new URL('https://example.com/foo')
|
||||
|
||||
const { asFragment } = renderWithBrandedContext(
|
||||
<ActionItem
|
||||
@ -212,7 +217,7 @@ describe('ActionItem', () => {
|
||||
})
|
||||
|
||||
it('renders as link with icon and opens a new tab for a different origin', () => {
|
||||
jsdom.reconfigure({ url: 'https://example.com/foo' })
|
||||
windowLocation__testingOnly.value = new URL('https://example.com/foo')
|
||||
|
||||
const { asFragment } = renderWithBrandedContext(
|
||||
<ActionItem
|
||||
@ -228,7 +233,7 @@ describe('ActionItem', () => {
|
||||
})
|
||||
|
||||
it('renders as link that opens in a new tab, but without icon for a different origin as the alt action and a primary action defined', () => {
|
||||
jsdom.reconfigure({ url: 'https://example.com/foo' })
|
||||
windowLocation__testingOnly.value = new URL('https://example.com/foo')
|
||||
|
||||
const { asFragment } = renderWithBrandedContext(
|
||||
<ActionItem
|
||||
|
||||
@ -116,6 +116,12 @@ interface State {
|
||||
actionOrError: typeof LOADING | null | ErrorLike
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing only, used to set the window.location value for {@link isExternalLink}.
|
||||
* @internal
|
||||
*/
|
||||
export const windowLocation__testingOnly: { value: Pick<URL, 'origin' | 'href'> | null } = { value: null }
|
||||
|
||||
export class ActionItem extends React.PureComponent<ActionItemProps, State, typeof WildcardThemeContext> {
|
||||
public static contextType = WildcardThemeContext
|
||||
public context!: React.ContextType<typeof WildcardThemeContext>
|
||||
@ -237,7 +243,7 @@ export class ActionItem extends React.PureComponent<ActionItemProps, State, type
|
||||
const to = primaryTo || altTo
|
||||
// Open in new tab if an external link
|
||||
const newTabProps =
|
||||
to && isExternalLink(to)
|
||||
to && isExternalLink(to, windowLocation__testingOnly.value ?? window.location)
|
||||
? {
|
||||
target: '_blank',
|
||||
rel: 'noopener noreferrer',
|
||||
|
||||
@ -9,6 +9,19 @@ exports[`ActionItem "open" command renders as link 1`] = `
|
||||
tabindex="0"
|
||||
>
|
||||
t
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="mdi-icon"
|
||||
fill="currentColor"
|
||||
height="24"
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
>
|
||||
<path
|
||||
d="M14,3V5H17.59L7.76,14.83L9.17,16.24L19,6.41V10H21V3M19,19H5V5H12V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V12H19V19Z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</span>
|
||||
</DocumentFragment>
|
||||
|
||||
@ -118,7 +118,10 @@ describe('MainThreadAPI', () => {
|
||||
clientApplication: 'other',
|
||||
}
|
||||
|
||||
const { api } = initMainThreadAPI(pretendRemote({}), platformContext)
|
||||
const { api } = initMainThreadAPI(
|
||||
pretendRemote<FlatExtensionHostAPI>({ syncSettingsData: () => {} }),
|
||||
platformContext
|
||||
)
|
||||
|
||||
const edit: SettingsEdit = { path: ['a'], value: 'newVal' }
|
||||
await api.applySettingsEdit(edit)
|
||||
|
||||
@ -7,8 +7,9 @@ import type * as sourcegraph from 'sourcegraph'
|
||||
import type { MaybeLoadingResult } from '@sourcegraph/codeintellify'
|
||||
import { MarkupKind } from '@sourcegraph/extension-api-classes'
|
||||
import type { Location } from '@sourcegraph/extension-api-types'
|
||||
import { createBarrier } from '@sourcegraph/testing'
|
||||
|
||||
import { assertToJSON, createBarrier, integrationTestContext } from '../../testing/testHelpers'
|
||||
import { assertToJSON, integrationTestContext } from '../../testing/testHelpers'
|
||||
import { wrapRemoteObservable } from '../client/api/common'
|
||||
import type { FlatExtensionHostAPI } from '../contract'
|
||||
|
||||
|
||||
@ -107,17 +107,6 @@ export async function integrationTestContext(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Promise} and a function. The {@link Promise} blocks until the returned function is called.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function createBarrier(): { wait: Promise<void>; done: () => void } {
|
||||
let done!: () => void
|
||||
const wait = new Promise<void>(resolve => (done = resolve))
|
||||
return { wait, done }
|
||||
}
|
||||
|
||||
export function collectSubscribableValues<T>(subscribable: Subscribable<T>): T[] {
|
||||
const values: T[] = []
|
||||
subscribable.subscribe(value => values.push(value))
|
||||
|
||||
@ -426,21 +426,20 @@ describe('buildSearchURLQuery', () => {
|
||||
|
||||
describe('isExternalLink', () => {
|
||||
it('returns false for the same site', () => {
|
||||
jsdom.reconfigure({ url: 'https://github.com/here' })
|
||||
expect(isExternalLink('https://github.com/there')).toBe(false)
|
||||
const windowLocation = new URL('https://github.com/here')
|
||||
expect(isExternalLink('https://github.com/there', windowLocation)).toBe(false)
|
||||
})
|
||||
it('returns false for relative links', () => {
|
||||
jsdom.reconfigure({ url: 'https://github.com/here' })
|
||||
expect(isExternalLink('/there')).toBe(false)
|
||||
const windowLocation = new URL('https://github.com/here')
|
||||
expect(isExternalLink('/there', windowLocation)).toBe(false)
|
||||
})
|
||||
it('returns false for invalid URLs', () => {
|
||||
jsdom.reconfigure({ url: 'https://github.com/here' })
|
||||
|
||||
expect(isExternalLink(' ')).toBe(false)
|
||||
const windowLocation = new URL('https://github.com/here')
|
||||
expect(isExternalLink(' ', windowLocation)).toBe(false)
|
||||
})
|
||||
it('returns true for a different site', () => {
|
||||
jsdom.reconfigure({ url: 'https://github.com/here' })
|
||||
expect(isExternalLink('https://sourcegraph.com/here')).toBe(true)
|
||||
const windowLocation = new URL('https://github.com/here')
|
||||
expect(isExternalLink('https://sourcegraph.com/here', windowLocation)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -1 +1,10 @@
|
||||
export * from './aria-asserts'
|
||||
|
||||
/**
|
||||
* Returns a {@link Promise} and a function. The {@link Promise} blocks until the returned function is called.
|
||||
*/
|
||||
export function createBarrier(): { wait: Promise<void>; done: () => void } {
|
||||
let done!: () => void
|
||||
const wait = new Promise<void>(resolve => (done = resolve))
|
||||
return { wait, done }
|
||||
}
|
||||
|
||||
@ -6,8 +6,8 @@ import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
|
||||
|
||||
import { ErrorBoundary } from './ErrorBoundary'
|
||||
|
||||
jest.mock('mdi-react/AlertCircleIcon', () => 'AlertCircleIcon')
|
||||
jest.mock('mdi-react/ReloadIcon', () => 'ReloadIcon')
|
||||
jest.mock('mdi-react/AlertCircleIcon', () => () => 'AlertCircleIcon')
|
||||
jest.mock('mdi-react/ReloadIcon', () => () => 'ReloadIcon')
|
||||
|
||||
const ThrowError: React.FunctionComponent<React.PropsWithChildren<unknown>> = () => {
|
||||
throw new Error('x')
|
||||
|
||||
@ -8,11 +8,7 @@ exports[`ErrorBoundary passes through if non-error 1`] = `
|
||||
<div
|
||||
class="iconWrapper"
|
||||
>
|
||||
<alertcircleicon
|
||||
aria-hidden="true"
|
||||
class="mdi-icon iconInline icon"
|
||||
role="img"
|
||||
/>
|
||||
AlertCircleIcon
|
||||
</div>
|
||||
<h1
|
||||
class="h1 title"
|
||||
@ -62,11 +58,7 @@ exports[`ErrorBoundary renders reload page if dynamic import error 1`] = `
|
||||
<div
|
||||
class="iconWrapper"
|
||||
>
|
||||
<reloadicon
|
||||
aria-hidden="true"
|
||||
class="mdi-icon iconInline icon"
|
||||
role="img"
|
||||
/>
|
||||
ReloadIcon
|
||||
</div>
|
||||
<h1
|
||||
class="h1 title"
|
||||
|
||||
@ -23,7 +23,7 @@ export const SuggestionsPanel: React.FunctionComponent<React.PropsWithChildren<S
|
||||
|
||||
if (suggestions === undefined) {
|
||||
return (
|
||||
<div className={classNames(styles.loadingPanel, classNames)}>
|
||||
<div className={classNames(styles.loadingPanel, className)}>
|
||||
<LoadingSpinner inline={false} />
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -6,7 +6,7 @@ import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
|
||||
import { SiteAdminProductLicenseNode } from './SiteAdminProductLicenseNode'
|
||||
import { mockLicenseContext } from './testUtils'
|
||||
|
||||
jest.mock('../../../dotcom/productSubscriptions/AccountName', () => ({ AccountName: 'AccountName' }))
|
||||
jest.mock('../../../dotcom/productSubscriptions/AccountName', () => ({ AccountName: () => 'AccountName' }))
|
||||
|
||||
describe('SiteAdminProductLicenseNode', () => {
|
||||
const origContext = window.context
|
||||
|
||||
@ -49,7 +49,7 @@ exports[`SiteAdminProductLicenseNode active 1`] = `
|
||||
<span
|
||||
class="mr-3"
|
||||
>
|
||||
<accountname />
|
||||
AccountName
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
@ -262,7 +262,7 @@ exports[`SiteAdminProductLicenseNode inactive 1`] = `
|
||||
<span
|
||||
class="mr-3"
|
||||
>
|
||||
<accountname />
|
||||
AccountName
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@ -6,9 +6,9 @@ import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
|
||||
|
||||
import { UserProductSubscriptionStatus } from './UserProductSubscriptionStatus'
|
||||
|
||||
jest.mock('mdi-react/KeyIcon', () => 'KeyIcon')
|
||||
jest.mock('mdi-react/InformationIcon', () => 'InformationIcon')
|
||||
jest.mock('../../../components/CopyableText', () => ({ CopyableText: 'CopyableText' }))
|
||||
jest.mock('mdi-react/KeyIcon', () => () => 'KeyIcon')
|
||||
jest.mock('mdi-react/InformationIcon', () => () => 'InformationIcon')
|
||||
jest.mock('../../../components/CopyableText', () => ({ CopyableText: () => 'CopyableText' }))
|
||||
|
||||
describe('UserProductSubscriptionStatus', () => {
|
||||
test('toggle', () => {
|
||||
|
||||
@ -155,10 +155,7 @@ exports[`UserProductSubscriptionStatus toggle: license key revealed 1`] = `
|
||||
>
|
||||
License key
|
||||
</h3>
|
||||
<copyabletext
|
||||
class="d-block"
|
||||
text="lk"
|
||||
/>
|
||||
CopyableText
|
||||
<small
|
||||
class="mt-2 d-flex align-items-center"
|
||||
>
|
||||
|
||||
@ -33,9 +33,9 @@ describe('SurveyToast', () => {
|
||||
})
|
||||
|
||||
const mockClient = createMockClient(
|
||||
{ contents: JSON.stringify({}) },
|
||||
{ temporarySettings: { contents: JSON.stringify({}) } },
|
||||
gql`
|
||||
query TemporarySettings {
|
||||
query GetTemporarySettings {
|
||||
temporarySettings {
|
||||
contents
|
||||
}
|
||||
|
||||
@ -12,8 +12,8 @@ import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
|
||||
|
||||
import { GlobalNavbar } from './GlobalNavbar'
|
||||
|
||||
jest.mock('../search/input/SearchNavbarItem', () => ({ SearchNavbarItem: 'SearchNavbarItem' }))
|
||||
jest.mock('../components/branding/BrandLogo', () => ({ BrandLogo: 'BrandLogo' }))
|
||||
jest.mock('../search/input/SearchNavbarItem', () => ({ SearchNavbarItem: () => 'SearchNavbarItem' }))
|
||||
jest.mock('../components/branding/BrandLogo', () => ({ BrandLogo: () => 'BrandLogo' }))
|
||||
|
||||
const PROPS: React.ComponentProps<typeof GlobalNavbar> = {
|
||||
authenticatedUser: null,
|
||||
|
||||
@ -13,10 +13,7 @@ exports[`GlobalNavbar default 1`] = `
|
||||
class="d-flex align-items-center"
|
||||
href="/search"
|
||||
>
|
||||
<brandlogo
|
||||
class="logo"
|
||||
variant="symbol"
|
||||
/>
|
||||
BrandLogo
|
||||
</a>
|
||||
</h1>
|
||||
<hr
|
||||
@ -212,13 +209,7 @@ exports[`GlobalNavbar default 1`] = `
|
||||
<div
|
||||
class="searchNavBar"
|
||||
>
|
||||
<searchnavbaritem
|
||||
platformcontext="[object Object]"
|
||||
routes=""
|
||||
selectedsearchcontextspec=""
|
||||
settingscascade="[object Object]"
|
||||
telemetryservice="[object Object]"
|
||||
/>
|
||||
SearchNavbarItem
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
||||
|
||||
@ -5,6 +5,7 @@ import { tap, last } from 'rxjs/operators'
|
||||
|
||||
import { logger, resetAllMemoizationCaches } from '@sourcegraph/common'
|
||||
import { SearchMode } from '@sourcegraph/shared/src/search'
|
||||
import { createBarrier } from '@sourcegraph/testing'
|
||||
import { renderWithBrandedContext } from '@sourcegraph/wildcard/src/testing'
|
||||
|
||||
import { SearchPatternType } from '../graphql-operations'
|
||||
@ -193,7 +194,8 @@ describe('updateQueryStateFromURL', () => {
|
||||
const isSearchContextAvailable = () => Promise.resolve(true)
|
||||
|
||||
describe('search context', () => {
|
||||
it('should extract the search context from the query', done => {
|
||||
it('should extract the search context from the query', async () => {
|
||||
const { wait, done } = createBarrier()
|
||||
const [locationSubject, location] = createHistoryObservable('q=context:me+test')
|
||||
|
||||
getQueryStateFromLocation({
|
||||
@ -213,6 +215,7 @@ describe('updateQueryStateFromURL', () => {
|
||||
|
||||
locationSubject.next(location)
|
||||
locationSubject.complete()
|
||||
await wait
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -525,8 +525,8 @@ ts_project(
|
||||
"src/components/PageSelector/PageSelector.test.tsx",
|
||||
"src/components/PageSwitcher/PageSwitcher.test.tsx",
|
||||
"src/components/Panel/Panel.test.tsx",
|
||||
"src/components/Popover/tether/models/geometry/rectangle.spec.ts",
|
||||
"src/components/Popover/tether/services/geometry/actions/get-constrained-element.spec.ts",
|
||||
"src/components/Popover/tether/models/geometry/rectangle.test.ts",
|
||||
"src/components/Popover/tether/services/geometry/actions/get-constrained-element.test.ts",
|
||||
"src/components/Tabs/Tabs.test.tsx",
|
||||
"src/components/Tooltip/Tooltip.test.tsx",
|
||||
"src/components/Tree/Tree.test.tsx",
|
||||
|
||||
@ -9,9 +9,17 @@ import { Link } from '../components/Link/Link'
|
||||
|
||||
import { createLinkClickHandler } from './linkClickHandler'
|
||||
|
||||
if (!global.SVGAElement) {
|
||||
// jsdom does not define SVGAElement, which is currently used in createLinkClickHandler. See
|
||||
// https://github.com/jsdom/jsdom/issues/2128.
|
||||
;(global as any).SVGAElement = HTMLAnchorElement
|
||||
}
|
||||
|
||||
describe('createLinkClickHandler', () => {
|
||||
it('handles clicks on links that stay inside the app', () => {
|
||||
jsdom.reconfigure({ url: 'https://sourcegraph.test/some/where' })
|
||||
// Create a URL that refers to the same host as `window.location.href`.
|
||||
const urlInsideApp = new URL('/else/where', window.location.href)
|
||||
expect(urlInsideApp.toString()).toBe(window.location.href + 'else/where')
|
||||
|
||||
const history = createMemoryHistory({ initialEntries: [] })
|
||||
expect(history).toHaveLength(0)
|
||||
@ -19,7 +27,7 @@ describe('createLinkClickHandler', () => {
|
||||
const { container } = render(
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
||||
<div onClick={createLinkClickHandler(history)}>
|
||||
<Link to="https://sourcegraph.test/else/where">Test</Link>
|
||||
<Link to={urlInsideApp.toString()}>Test</Link>
|
||||
</div>
|
||||
)
|
||||
|
||||
@ -39,14 +47,17 @@ describe('createLinkClickHandler', () => {
|
||||
})
|
||||
|
||||
it('ignores clicks on links that go outside the app', () => {
|
||||
jsdom.reconfigure({ url: 'https://sourcegraph.test/some/where' })
|
||||
// Create a URL that refers to a different host than `window.location.href`.
|
||||
const urlOutsideApp = new URL('https://other.example.com/some/where')
|
||||
expect(urlOutsideApp.origin).not.toBe(window.location.origin)
|
||||
|
||||
const history = createMemoryHistory({ initialEntries: [] })
|
||||
expect(history).toHaveLength(0)
|
||||
|
||||
const { container } = render(
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
||||
<div onClick={createLinkClickHandler(history)}>
|
||||
<Link to="https://github.com/some/where">Test</Link>
|
||||
<Link to={urlOutsideApp.toString()}>Test</Link>
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ var clientRootFiles = []string{
|
||||
"jest.config.base.js",
|
||||
"jest.config.js",
|
||||
"postcss.config.js",
|
||||
"tsconfig.all.json",
|
||||
"tsconfig.base.json",
|
||||
"tsconfig.json",
|
||||
".percy.yml",
|
||||
".eslintrc.js",
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^v18.17.1",
|
||||
"pnpm": "^8.3.0"
|
||||
"pnpm": "^8.9.2"
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier '**/{*.{js?(on),ts?(x),graphql,md,scss},.*.js?(on)}' --list-different --config prettier.config.js --write",
|
||||
@ -23,7 +23,7 @@
|
||||
"lint:css:changed": "pnpm _lint:css --allow-empty-input \"*.none\" $(git diff --diff-filter=d --name-only origin/main... | grep -E '.s?css$' | xargs)",
|
||||
"lint:css:all": "pnpm _lint:css 'client/*/src/**/*.scss'",
|
||||
"lint:graphql": "graphql-schema-linter",
|
||||
"build-ts": "tsc --build tsconfig.all.json --emitDeclarationOnly",
|
||||
"build-ts": "tsc --build tsconfig.json --emitDeclarationOnly",
|
||||
"build-web": "pnpm --filter @sourcegraph/web run build",
|
||||
"build-app-shell": "pnpm --filter @sourcegraph/app-shell run build",
|
||||
"watch-web": "pnpm --filter @sourcegraph/web run watch",
|
||||
@ -436,7 +436,7 @@
|
||||
"yaml-ast-parser": "^0.0.43",
|
||||
"zustand": "^3.6.9"
|
||||
},
|
||||
"packageManager": "pnpm@8.3.0",
|
||||
"packageManager": "pnpm@8.9.2",
|
||||
"pnpm": {
|
||||
"packageExtensions": {
|
||||
"hnswlib-node": {
|
||||
|
||||
2080
pnpm-lock.yaml
2080
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user