Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support relative links #45

Merged
merged 4 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions test-app/tests/acceptance/visit-all-links-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ import { visitAllLinks } from '@universal-ember/test-support';
module('All Links', function (hooks) {
setupApplicationTest(hooks);

test('are visitable without error', async function () {
await visitAllLinks();
test('are visitable without error', async function (assert) {
const size1 = await visitAllLinks();
const size2 = await visitAllLinks((url) => {
assert.ok(url);
});

assert.ok(size1 > 0, 'The test app has links');
assert.ok(size2 > 0, 'The test app has links');
assert.strictEqual(
size1,
size2,
`multiple usages does not visit different numbers of links (${size1} === ${size2})`,
);
});
});
1 change: 0 additions & 1 deletion test-app/tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

<link rel="stylesheet" href="{{rootURL}}assets/vendor.css">
<link rel="stylesheet" href="{{rootURL}}assets/test-app.css">
<link rel="stylesheet" href="{{rootURL}}assets/test-support.css">

{{content-for "head-footer"}}
{{content-for "test-head-footer"}}
Expand Down
57 changes: 41 additions & 16 deletions test-support/src/routing/visit-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,34 @@ import QUnit from 'qunit';
import type Owner from '@ember/owner';
import type RouterService from '@ember/routing/router-service';

function findInAppLinks(): string[] {
return (findAll('a')
?.map((link) => link.getAttribute('href'))
?.filter((href) => !href?.startsWith('http'))
.filter(Boolean) || []) as string[];
interface InAppLink {
href: string;
original: string;
selector: string;
}

function findInAppLinks(): InAppLink[] {
const results: InAppLink[] = [];

const allAnchorsOnThePage = findAll('a');

for (const a of allAnchorsOnThePage) {
const href = a.getAttribute('href');

if (!href) continue;
if (href.startsWith('http')) continue;

const url = new URL(href, window.location.href);
const withoutDomain = `${url.pathname}${url.search}${url.hash}`;

results.push({
href: withoutDomain,
original: href,
selector: `a[href="${href}"]`,
});
}

return results;
}

const assert = QUnit.assert;
Expand All @@ -32,7 +55,7 @@ export async function visitAllLinks(
await visit(returnTo);

const inAppLinks = findInAppLinks();
const queue: (string | { changeReturnTo: string })[] = [...inAppLinks];
const queue: (InAppLink | { changeReturnTo: string })[] = [...inAppLinks];

const ctx = getContext() as unknown as { owner: Owner };
const router = ctx?.owner?.lookup('service:router') as RouterService;
Expand All @@ -44,19 +67,19 @@ export async function visitAllLinks(

debugAssert(`Queue entries cannot be falsey`, toVisit);

if (typeof toVisit === 'object' && toVisit !== null) {
if ('changeReturnTo' in toVisit) {
returnTo = toVisit.changeReturnTo;
continue;
}

// In-page links are on the page we're already on.
// As long as we haven't already encountered an error,
// this is silly to check.
if (toVisit.startsWith('#')) {
if (toVisit.original.startsWith('#')) {
continue;
}

const [nonHashPart] = toVisit.split('#');
const [nonHashPart] = toVisit.href.split('#');

// This was our first page, we've already been here
if (nonHashPart === '/') {
Expand All @@ -67,36 +90,38 @@ export async function visitAllLinks(

if (visited.has(key)) continue;

const result = router.recognize(toVisit);
const result = router.recognize(toVisit.href);

if (!result) {
assert.ok(
true,
`${toVisit} on page ${returnTo} is not recognized by this app and will be skipped`,
`${toVisit.href} on page ${returnTo} is not recognized by this app and will be skipped`,
);
continue;
}

await visit(returnTo);

const link = find(`a[href="${toVisit}"]`);
const link = find(toVisit.selector);

debugAssert(`link exists with ${toVisit}`, link);
debugAssert(`link exists via selector \`${toVisit.selector}\``, link);

await click(link);
assert.ok(
currentURL().startsWith(toVisit),
`Navigation was successful: to:${toVisit}, from:${returnTo}`,
currentURL().startsWith(toVisit.href),
`Navigation was successful: to:${toVisit.original}, from:${returnTo}`,
);
visited.add(key);

if (callback) {
await callback(toVisit);
await callback(toVisit.href);
}

const links = findInAppLinks();

queue.push({ changeReturnTo: currentURL() });
queue.push(...links);
}

return visited.size;
}
Loading