Skip to content

Commit 9195392

Browse files
authored
Introduce StrippedLocation for mocking browser location and domain (#53)
2 parents e226890 + 97929e5 commit 9195392

File tree

10 files changed

+117
-100
lines changed

10 files changed

+117
-100
lines changed

browser-extension/src/entrypoints/content.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CONFIG } from '../lib/config'
2-
import type { CommentEvent, CommentSpot } from '../lib/enhancer'
2+
import type { CommentEvent, CommentSpot, StrippedLocation } from '../lib/enhancer'
33
import { logger } from '../lib/logger'
44
import { EnhancerRegistry, TextareaRegistry } from '../lib/registries'
55

@@ -9,6 +9,18 @@ const enhancedTextareas = new TextareaRegistry()
99
// Expose for debugging in har:view
1010
;(window as any).gitcassoTextareaRegistry = enhancedTextareas
1111

12+
function detectLocation(): StrippedLocation {
13+
if ((window as any).gitcassoMockLocation) {
14+
return (window as any).gitcassoMockLocation
15+
}
16+
const result = {
17+
host: window.location.host,
18+
pathname: window.location.pathname,
19+
}
20+
logger.debug('[gitcasso] detectLocation called, returning:', result)
21+
return result
22+
}
23+
1224
function sendEventToBackground(type: 'ENHANCED' | 'DESTROYED', spot: CommentSpot): void {
1325
const message: CommentEvent = {
1426
spot,
@@ -26,6 +38,7 @@ enhancedTextareas.setEventHandlers(
2638

2739
export default defineContentScript({
2840
main() {
41+
logger.debug('Main was called')
2942
const textAreasOnPageLoad = document.querySelectorAll<HTMLTextAreaElement>(`textarea`)
3043
for (const textarea of textAreasOnPageLoad) {
3144
enhanceMaybe(textarea)
@@ -35,7 +48,7 @@ export default defineContentScript({
3548
childList: true,
3649
subtree: true,
3750
})
38-
logger.debug('Extension loaded with', enhancers.getEnhancerCount, 'handlers')
51+
logger.debug('Extension loaded with', enhancers.getEnhancerCount(), 'handlers')
3952
},
4053
matches: ['<all_urls>'],
4154
runAt: 'document_end',
@@ -80,6 +93,7 @@ function handleMutations(mutations: MutationRecord[]): void {
8093
}
8194

8295
function enhanceMaybe(textarea: HTMLTextAreaElement) {
96+
logger.debug('[gitcasso] enhanceMaybe called for textarea:', textarea.id, textarea.className)
8397
if (enhancedTextareas.get(textarea)) {
8498
logger.debug('textarea already registered {}', textarea)
8599
return
@@ -89,7 +103,9 @@ function enhanceMaybe(textarea: HTMLTextAreaElement) {
89103
injectStyles()
90104

91105
try {
92-
const enhancedTextarea = enhancers.tryToEnhance(textarea)
106+
const location = detectLocation()
107+
logger.debug('[gitcasso] Calling tryToEnhance with location:', location)
108+
const enhancedTextarea = enhancers.tryToEnhance(textarea, location)
93109
if (enhancedTextarea) {
94110
logger.debug(
95111
'Identified textarea:',

browser-extension/src/lib/enhancer.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ export interface CommentEvent {
1919
draft?: string
2020
}
2121

22+
/**
23+
* Minimal location information that enhancers need for routing decisions.
24+
* Avoids dependency on global window/location objects for better testability.
25+
*/
26+
export interface StrippedLocation {
27+
host: string
28+
pathname: string
29+
}
30+
2231
/** Wraps the textareas of a given platform with Gitcasso's enhancements. */
2332
export interface CommentEnhancer<Spot extends CommentSpot = CommentSpot> {
2433
/** Guarantees to only return a type within this list. */
@@ -27,7 +36,7 @@ export interface CommentEnhancer<Spot extends CommentSpot = CommentSpot> {
2736
* Whenever a new `textarea` is added to any webpage, this method is called.
2837
* If we return non-null, then we become the handler for that text area.
2938
*/
30-
tryToEnhance(textarea: HTMLTextAreaElement): Spot | null
39+
tryToEnhance(textarea: HTMLTextAreaElement, location: StrippedLocation): Spot | null
3140
/** This gets called the first time that `tryToEnhance` returns non-null. */
3241
prepareForFirstEnhancement(): void
3342
/**

browser-extension/src/lib/enhancers/CommentEnhancerMissing.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OverTypeInstance } from 'overtype'
22
import type { ReactNode } from 'react'
3-
import type { CommentEnhancer, CommentSpot } from '../enhancer'
3+
import type { CommentEnhancer, CommentSpot, StrippedLocation } from '../enhancer'
44

55
/** Used when an entry is in the table which we don't recognize. */
66
export class CommentEnhancerMissing implements CommentEnhancer {
@@ -40,7 +40,7 @@ export class CommentEnhancerMissing implements CommentEnhancer {
4040
forSpotTypes(): string[] {
4141
throw new Error('Method not implemented.')
4242
}
43-
tryToEnhance(_textarea: HTMLTextAreaElement): CommentSpot | null {
43+
tryToEnhance(_textarea: HTMLTextAreaElement, _location: StrippedLocation): CommentSpot | null {
4444
throw new Error('Method not implemented.')
4545
}
4646
prepareForFirstEnhancement(): void {

browser-extension/src/lib/enhancers/github/githubIssueAddComment.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { IssueOpenedIcon } from '@primer/octicons-react'
22
import OverType, { type OverTypeInstance } from 'overtype'
33
import type React from 'react'
4-
import type { CommentEnhancer, CommentSpot } from '@/lib/enhancer'
4+
import type { CommentEnhancer, CommentSpot, StrippedLocation } from '@/lib/enhancer'
55
import { logger } from '@/lib/logger'
66
import { modifyDOM } from '../modifyDOM'
77
import { commonGithubOptions } from './ghOptions'
@@ -20,19 +20,22 @@ export class GitHubIssueAddCommentEnhancer implements CommentEnhancer<GitHubIssu
2020
return ['GH_ISSUE_ADD_COMMENT']
2121
}
2222

23-
tryToEnhance(textarea: HTMLTextAreaElement): GitHubIssueAddCommentSpot | null {
23+
tryToEnhance(
24+
textarea: HTMLTextAreaElement,
25+
location: StrippedLocation,
26+
): GitHubIssueAddCommentSpot | null {
2427
if (textarea.id === 'feedback') {
2528
return null
2629
}
27-
if (document.querySelector('meta[name="hostname"]')?.getAttribute('content') !== 'github.com') {
30+
if (location.host !== 'github.com') {
2831
return null
2932
}
3033

3134
// Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456
32-
logger.debug(`${this.constructor.name} examing url`, window.location.pathname)
35+
logger.debug(`${this.constructor.name} examing url`, location.pathname)
3336

34-
const match = window.location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/issues\/(\d+))/)
35-
logger.debug(`${this.constructor.name} found match`, window.location.pathname)
37+
const match = location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/issues\/(\d+))/)
38+
logger.debug(`${this.constructor.name} found match`, location.pathname)
3639
if (!match) return null
3740

3841
const [, owner, repo, numberStr] = match
@@ -41,7 +44,7 @@ export class GitHubIssueAddCommentEnhancer implements CommentEnhancer<GitHubIssu
4144
const unique_key = `github.com:${slug}:${number}`
4245
const title = 'TODO_TITLE'
4346
return {
44-
domain: 'github.com',
47+
domain: location.host,
4548
number,
4649
slug,
4750
title,

browser-extension/src/lib/enhancers/github/githubIssueNewComment.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OverType, { type OverTypeInstance } from 'overtype'
2-
import type { CommentEnhancer, CommentSpot } from '../../enhancer'
2+
import type { CommentEnhancer, CommentSpot, StrippedLocation } from '../../enhancer'
33
import { logger } from '../../logger'
44
import { modifyDOM } from '../modifyDOM'
55
import { commonGithubOptions } from './ghOptions'
@@ -16,23 +16,26 @@ export class GitHubIssueNewCommentEnhancer implements CommentEnhancer<GitHubIssu
1616
return ['GH_ISSUE_NEW_COMMENT']
1717
}
1818

19-
tryToEnhance(_textarea: HTMLTextAreaElement): GitHubIssueNewCommentSpot | null {
20-
if (document.querySelector('meta[name="hostname"]')?.getAttribute('content') !== 'github.com') {
19+
tryToEnhance(
20+
_textarea: HTMLTextAreaElement,
21+
location: StrippedLocation,
22+
): GitHubIssueNewCommentSpot | null {
23+
if (location.host !== 'github.com') {
2124
return null
2225
}
2326

2427
// Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456
25-
logger.debug(`${this.constructor.name} examing url`, window.location.pathname)
28+
logger.debug(`${this.constructor.name} examing url`, location.pathname)
2629

27-
const match = window.location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/issues\/new)/)
28-
logger.debug(`${this.constructor.name} found match`, window.location.pathname)
30+
const match = location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/issues\/new)/)
31+
logger.debug(`${this.constructor.name} found match`, location.pathname)
2932

3033
if (!match) return null
3134
const [, owner, repo] = match
3235
const slug = `${owner}/${repo}`
3336
const unique_key = `github.com:${slug}:new`
3437
return {
35-
domain: 'github.com',
38+
domain: location.host,
3639
slug,
3740
type: 'GH_ISSUE_NEW_COMMENT',
3841
unique_key,

browser-extension/src/lib/enhancers/github/githubPRAddComment.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import OverType, { type OverTypeInstance } from 'overtype'
22
import type React from 'react'
3-
import type { CommentEnhancer, CommentSpot } from '@/lib/enhancer'
3+
import type { CommentEnhancer, CommentSpot, StrippedLocation } from '@/lib/enhancer'
44
import { logger } from '@/lib/logger'
55
import { modifyDOM } from '../modifyDOM'
66
import { commonGithubOptions } from './ghOptions'
@@ -19,28 +19,28 @@ export class GitHubPRAddCommentEnhancer implements CommentEnhancer<GitHubPRAddCo
1919
return ['GH_PR_ADD_COMMENT']
2020
}
2121

22-
tryToEnhance(_textarea: HTMLTextAreaElement): GitHubPRAddCommentSpot | null {
22+
tryToEnhance(
23+
_textarea: HTMLTextAreaElement,
24+
location: StrippedLocation,
25+
): GitHubPRAddCommentSpot | null {
2326
// Only handle github.com domains TODO: identify GitHub Enterprise somehow
24-
if (
25-
document.querySelector('meta[name="hostname"]')?.getAttribute('content') !== 'github.com' ||
26-
_textarea.id !== 'new_comment_field'
27-
) {
27+
if (location.host !== 'github.com' || _textarea.id !== 'new_comment_field') {
2828
return null
2929
}
3030

3131
// Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456
32-
logger.debug(`${this.constructor.name} examing url`, window.location.pathname)
32+
logger.debug(`${this.constructor.name} examing url`, location.pathname)
3333

34-
const match = window.location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/pull\/(\d+))/)
35-
logger.debug(`${this.constructor.name} found match`, window.location.pathname)
34+
const match = location.pathname.match(/^\/([^/]+)\/([^/]+)(?:\/pull\/(\d+))/)
35+
logger.debug(`${this.constructor.name} found match`, location.pathname)
3636
if (!match) return null
3737
const [, owner, repo, numberStr] = match
3838
const slug = `${owner}/${repo}`
3939
const number = parseInt(numberStr!, 10)
4040
const unique_key = `github.com:${slug}:${number}`
4141
const title = 'TODO_TITLE'
4242
return {
43-
domain: 'github.com',
43+
domain: location.host,
4444
number,
4545
slug,
4646
title,

browser-extension/src/lib/enhancers/github/githubPRNewComment.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import OverType, { type OverTypeInstance } from 'overtype'
2-
import type { CommentEnhancer, CommentSpot } from '../../enhancer'
2+
import type { CommentEnhancer, CommentSpot, StrippedLocation } from '../../enhancer'
33
import { logger } from '../../logger'
44
import { modifyDOM } from '../modifyDOM'
55
import { commonGithubOptions } from './ghOptions'
@@ -16,22 +16,25 @@ export class GitHubPRNewCommentEnhancer implements CommentEnhancer<GitHubPRNewCo
1616
return ['GH_PR_NEW_COMMENT']
1717
}
1818

19-
tryToEnhance(textarea: HTMLTextAreaElement): GitHubPRNewCommentSpot | null {
19+
tryToEnhance(
20+
textarea: HTMLTextAreaElement,
21+
location: StrippedLocation,
22+
): GitHubPRNewCommentSpot | null {
2023
if (textarea.id === 'feedback') {
2124
return null
2225
}
23-
if (document.querySelector('meta[name="hostname"]')?.getAttribute('content') !== 'github.com') {
26+
if (location.host !== 'github.com') {
2427
return null
2528
}
2629

2730
// /owner/repo/compare/feature/more-enhancers?expand=1
2831
// or /owner/repo/compare/feat/issue-static-and-dynamic...feature/more-enhancers?expand=1
29-
logger.info(`${this.constructor.name} examing url`, window.location.pathname)
32+
logger.info(`${this.constructor.name} examing url`, location.pathname)
3033

31-
const match = window.location.pathname.match(
34+
const match = location.pathname.match(
3235
/^\/([^/]+)\/([^/]+)\/compare\/(?:([^.?]+)\.\.\.)?([^?]+)/,
3336
)
34-
logger.info(`${this.constructor.name} found match`, window.location.pathname, match)
37+
logger.info(`${this.constructor.name} found match`, location.pathname, match)
3538

3639
if (!match) return null
3740
const [, owner, repo, baseBranch, compareBranch] = match
@@ -40,7 +43,7 @@ export class GitHubPRNewCommentEnhancer implements CommentEnhancer<GitHubPRNewCo
4043
: `${owner}/${repo}/${compareBranch}`
4144
const unique_key = `github.com:${slug}`
4245
return {
43-
domain: 'github.com',
46+
domain: location.host,
4447
slug,
4548
type: 'GH_PR_NEW_COMMENT',
4649
unique_key,

browser-extension/src/lib/registries.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { OverTypeInstance } from 'overtype'
22
import OverType from 'overtype'
3-
import type { CommentEnhancer, CommentSpot } from './enhancer'
3+
import type { CommentEnhancer, CommentSpot, StrippedLocation } from './enhancer'
44
import { CommentEnhancerMissing } from './enhancers/CommentEnhancerMissing'
55
import { GitHubIssueAddCommentEnhancer } from './enhancers/github/githubIssueAddComment'
66
import { GitHubIssueNewCommentEnhancer } from './enhancers/github/githubIssueNewComment'
@@ -59,10 +59,10 @@ export class EnhancerRegistry {
5959
return (this.byType.get(spot.type) || new CommentEnhancerMissing()) as CommentEnhancer<T>
6060
}
6161

62-
tryToEnhance(textarea: HTMLTextAreaElement): EnhancedTextarea | null {
62+
tryToEnhance(textarea: HTMLTextAreaElement, location: StrippedLocation): EnhancedTextarea | null {
6363
for (const enhancer of this.enhancers) {
6464
try {
65-
const spot = enhancer.tryToEnhance(textarea)
65+
const spot = enhancer.tryToEnhance(textarea, location)
6666
if (spot) {
6767
// Prepare enhancer on first use
6868
if (!this.preparedEnhancers.has(enhancer)) {

0 commit comments

Comments
 (0)