Skip to content

Commit 9c70198

Browse files
authored
Meta: Update selector tests to expect an exact match count (refined-github#7165)
1 parent 9cdd6a8 commit 9c70198

8 files changed

Lines changed: 166 additions & 49 deletions

File tree

package-lock.json

Lines changed: 57 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,11 @@
112112
"eslint-plugin-react": "^7.33.2",
113113
"eslint-plugin-react-hooks": "^4.6.0",
114114
"fast-ignore": "^1.1.1",
115+
"filenamify": "^6.0.0",
115116
"highlight.js": "^11.9.0",
116117
"mini-css-extract-plugin": "^2.7.6",
117118
"npm-run-all": "^4.1.5",
119+
"p-memoize": "^7.1.1",
118120
"prettier": "^3.0.3",
119121
"snarkdown": "^2.0.0",
120122
"stylelint": "^15.11.0",

source/features/open-issue-to-latest-comment.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ import {$$} from 'select-dom';
22
import * as pageDetect from 'github-url-detection';
33

44
import features from '../feature-manager.js';
5-
6-
const selector = `
7-
:is(.js-issue-row, .js-pinned-issue-list-item)
8-
.Link--muted:is(a[aria-label$="comment"], a[aria-label$="comments"])
9-
`;
5+
import {openIssueToLastComment} from '../github-helpers/selectors.js';
106

117
function init(): void {
12-
for (const link of $$(selector)) {
8+
for (const link of $$(openIssueToLastComment)) {
139
link.hash = '#issue-comment-box';
1410
}
1511
}
@@ -19,6 +15,13 @@ void features.add(import.meta.url, {
1915
pageDetect.isIssueOrPRList,
2016
],
2117
awaitDomReady: true,
22-
deduplicate: 'has-rgh-inner',
2318
init,
2419
});
20+
21+
/*
22+
23+
Test URLs:
24+
25+
https://github.com/refined-github/sandbox/labels/bug
26+
27+
*/

source/github-helpers/get-current-git-ref.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {assert, test} from 'vitest';
22

33
// @ts-expect-error JS only
4-
import {navigateToCommits} from '../../test/fixtures/globals.js';
4+
import {navigateToCommits} from '../../test/setup-file.js';
55
import getCurrentGitRef, {getGitRef} from './get-current-git-ref.js';
66

77
// The titles supplied here listed here are real, not guessed, except the error tester
Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,47 @@
1-
import mem from 'memoize';
1+
import pMemoize from 'p-memoize';
22
import {test, assert, describe} from 'vitest';
33
import {parseHTML} from 'linkedom';
4+
import filenamify from 'filenamify';
5+
import {writeFile, mkdir, unlink, readFile, access} from 'node:fs/promises';
46

57
import * as exports from './selectors.js';
68

7-
const fetchDocument = mem(async (url: string): Promise<Window> => {
8-
const request = await fetch(url);
9-
const contents = await request.text();
10-
return parseHTML(contents);
9+
const fsCache = {
10+
async get(path: string): Promise<string | undefined> {
11+
try {
12+
const value = await readFile(path, 'utf8');
13+
return value;
14+
} catch {
15+
return undefined;
16+
}
17+
},
18+
async set(path: string, contents: string): Promise<void> {
19+
await mkdir('./test/.cache', {recursive: true});
20+
await writeFile(path, contents);
21+
},
22+
async has(path: string): Promise<boolean> {
23+
try {
24+
await access(path);
25+
return true;
26+
} catch {
27+
return false;
28+
}
29+
},
30+
async delete(path: string): Promise<void> {
31+
await unlink(path);
32+
},
33+
} as const;
34+
35+
const fetchDocument = pMemoize(async (url: string): Promise<string> => {
36+
const request = await fetch(url, {
37+
headers: {
38+
Accept: 'text/html',
39+
},
40+
});
41+
return request.text();
42+
}, {
43+
cacheKey: ([url]) => `./test/.cache/${filenamify(url.replace('https://github.com', ''))}.html`,
44+
cache: fsCache,
1145
});
1246

1347
describe.concurrent('selectors', () => {
@@ -21,13 +55,15 @@ describe.concurrent('selectors', () => {
2155

2256
test.each(selectors)('%s', async (name, selector) => {
2357
// @ts-expect-error Index signature bs
24-
const urls = exports[name + '_'] as string[];
58+
const urls = exports[name + '_'] as exports.UrlMatch[];
2559

2660
assert.isArray(urls, `No URLs defined for "${name}"`);
27-
await Promise.all(urls.map(async url => {
28-
const {window} = await fetchDocument(url);
29-
// It's not equivalent at the moment, but at least the tests don't fail. Let's see how it goes
30-
assert.isDefined(window.document.querySelector(selector));
61+
await Promise.all(urls.map(async ([expectations, url]) => {
62+
const html = await fetchDocument(url);
63+
const {document} = parseHTML(html);
64+
// TODO: ? Use snapshot with outerHTML[]
65+
const matches = document.querySelectorAll(selector);
66+
assert.equal(matches.length, expectations, `Got wrong number of matches on ${url}:\n${selector}`);
3167
}));
3268
}, {timeout: 9999});
3369
});

source/github-helpers/selectors.ts

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import {css} from 'code-tag';
22

3+
export type UrlMatch = [expectations: number, url: string];
4+
35
/** The repo navigation bar */
46
export const repoUnderlineNavUl = '.js-responsive-underlinenav ul.UnderlineNav-body';
57
export const repoUnderlineNavUl_ = [
6-
'https://github.com/refined-github/refined-github',
7-
'https://github.com/refined-github/refined-github/releases',
8-
];
8+
[1, 'https://github.com/refined-github/refined-github'],
9+
[1, 'https://github.com/refined-github/refined-github/releases'],
10+
] satisfies UrlMatch[];
911

1012
export const standaloneGistLinkInMarkdown = css`
1113
.js-comment-body p a:only-child:is(
@@ -14,23 +16,30 @@ export const standaloneGistLinkInMarkdown = css`
1416
)
1517
` as 'a'; // TODO: Drop after https://github.com/fregante/code-tag/issues/12
1618
export const standaloneGistLinkInMarkdown_ = [
17-
'https://github.com/refined-github/sandbox/issues/77',
18-
];
19+
[3, 'https://github.com/refined-github/sandbox/issues/77'],
20+
] satisfies UrlMatch[];
1921

2022
/** The repo navigation bar’s overflow menu */
2123
export const repoUnderlineNavDropdownUl = '.js-responsive-underlinenav .dropdown-menu ul';
22-
export const repoUnderlineNavDropdownUl_ = repoUnderlineNavUl_;
24+
export const repoUnderlineNavDropdownUl_ = [
25+
// Added via JS :(
26+
// TOOD: Use Puppeteer?
27+
[0, 'https://github.com/refined-github/refined-github'],
28+
[0, 'https://github.com/refined-github/refined-github/releases'],
29+
] satisfies UrlMatch[];
2330

2431
export const branchSelector = '[data-hotkey="w"]';
2532
export const branchSelector_ = [
26-
'https://github.com/refined-github/refined-github',
27-
'https://github.com/refined-github/refined-github/blob/main/readme.md',
28-
'https://github.com/refined-github/refined-github/blame/main/readme.md',
29-
'https://github.com/refined-github/refined-github/tree/main/source',
30-
'https://github.com/refined-github/sandbox/tree/branch/with/slashes',
31-
'https://github.com/refined-github/sandbox/commits/branch/with/slashes',
32-
'https://github.com/refined-github/sandbox/commits',
33-
];
33+
[1, 'https://github.com/refined-github/refined-github'],
34+
// Added via JS :(
35+
// TOOD: Use Puppeteer?
36+
[0, 'https://github.com/refined-github/refined-github/blob/main/readme.md'],
37+
[0, 'https://github.com/refined-github/refined-github/blame/main/readme.md'],
38+
[0, 'https://github.com/refined-github/refined-github/tree/main/source'],
39+
[1, 'https://github.com/refined-github/sandbox/tree/branch/with/slashes'],
40+
[1, 'https://github.com/refined-github/sandbox/commits/branch/with/slashes'],
41+
[1, 'https://github.com/refined-github/sandbox/commits'],
42+
] satisfies UrlMatch[];
3443

3544
export const branchSelectorParent = 'details#branch-select-menu';
3645
export const branchSelectorParent_ = branchSelector_;
@@ -41,20 +50,21 @@ export const directoryListingFileIcon = [
4150
'.js-navigation-container .octicon-file',
4251
];
4352
export const directoryListingFileIcon_ = [
44-
'https://github.com/refined-github/refined-github',
45-
'https://github.com/refined-github/refined-github/tree/main/.github',
46-
];
53+
[1, 'https://github.com/refined-github/refined-github'],
54+
[1, 'https://github.com/refined-github/refined-github/tree/main/.github'],
55+
] satisfies UrlMatch[];
4756

4857
export const prCommit = '.TimelineItem--condensed:has(.octicon-git-commit)';
4958
export const prCommit_ = [
50-
'https://github.com/refined-github/sandbox/pull/10',
51-
];
59+
[1, 'https://github.com/refined-github/sandbox/pull/10'],
60+
] satisfies UrlMatch[];
5261

5362
// `summary` is needed because the details dropdown contains the list of check runs, each with its status icon
5463
export const prCommitStatusIcon = `:is(${prCommit}) details.commit-build-statuses summary .octicon`;
5564
export const prCommitStatusIcon_ = [
56-
'https://github.com/refined-github/sandbox/pull/10',
57-
];
65+
// Icon not loaded when logged out :(
66+
[0, 'https://github.com/refined-github/sandbox/pull/10'],
67+
] satisfies UrlMatch[];
5868

5969
// `.color-fg-open` is needed because of the icon added by `highlight-non-default-base-branch`
6070
export const openPrsListLink = css`
@@ -64,13 +74,24 @@ export const openPrsListLink = css`
6474
) a.js-navigation-open
6575
`;
6676
export const openPrsListLink_ = [
67-
'https://github.com/refined-github/sandbox/issues?q=conflict',
68-
];
77+
[4, 'https://github.com/refined-github/sandbox/issues?q=conflict'],
78+
] satisfies UrlMatch[];
79+
80+
export const openIssueToLastComment = `
81+
:is(.js-issue-row, .js-pinned-issue-list-item)
82+
.Link--muted:is(
83+
a[aria-label$="comment"],
84+
a[aria-label$="comments"]
85+
)
86+
`;
87+
export const openIssueToLastComment_ = [
88+
[2, 'https://github.com/refined-github/sandbox/labels/bug'],
89+
] satisfies UrlMatch[];
6990

7091
export const actionsTab = '#actions-tab';
7192
export const actionsTab_ = [
72-
'https://github.com/refined-github/sandbox',
73-
];
93+
[1, 'https://github.com/refined-github/sandbox'],
94+
] satisfies UrlMatch[];
7495

7596
export const codeSearchHeader = css`
7697
div:has(
@@ -79,5 +100,6 @@ export const codeSearchHeader = css`
79100
)
80101
`;
81102
export const codeSearchHeader_ = [
82-
'https://github.com/search?q=repo%3Arefined-github%2Frefined-github&type=code',
83-
];
103+
// Search not available when logged out :(
104+
[0, 'https://github.com/search?q=repo%3Arefined-github%2Frefined-github&type=code'],
105+
] satisfies UrlMatch[];
Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ const globals = [
66
'HTMLAnchorElement',
77
'DocumentFragment',
88
'Node',
9-
10-
// Use JSDOM’s implementation because Node’s uses `pathname`’s accessors while the browser doesn’t
11-
'URL',
129
];
1310

1411
const {window} = parseHTML('...', 'text/html');

vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {defineConfig} from 'vitest/config';
33
export default defineConfig({
44
test: {
55
setupFiles: [
6-
'./test/fixtures/globals.js',
6+
'./test/setup-file.js',
77
],
88
},
99
});

0 commit comments

Comments
 (0)