From cb9b6117d4c69d8bd72d1185de2553fce3dd4155 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Thu, 7 Nov 2024 13:19:57 -0500
Subject: [PATCH] Support relative links (#45)
* Support relative links
* Update tests
* dep
* fix
---
.../tests/acceptance/visit-all-links-test.ts | 15 ++++-
test-app/tests/index.html | 1 -
test-support/src/routing/visit-all.ts | 57 +++++++++++++------
3 files changed, 54 insertions(+), 19 deletions(-)
diff --git a/test-app/tests/acceptance/visit-all-links-test.ts b/test-app/tests/acceptance/visit-all-links-test.ts
index 1a01bb7..161803e 100644
--- a/test-app/tests/acceptance/visit-all-links-test.ts
+++ b/test-app/tests/acceptance/visit-all-links-test.ts
@@ -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})`,
+ );
});
});
diff --git a/test-app/tests/index.html b/test-app/tests/index.html
index e4b2e69..0fc6787 100644
--- a/test-app/tests/index.html
+++ b/test-app/tests/index.html
@@ -11,7 +11,6 @@
-
{{content-for "head-footer"}}
{{content-for "test-head-footer"}}
diff --git a/test-support/src/routing/visit-all.ts b/test-support/src/routing/visit-all.ts
index db551c6..6638def 100644
--- a/test-support/src/routing/visit-all.ts
+++ b/test-support/src/routing/visit-all.ts
@@ -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;
@@ -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;
@@ -44,7 +67,7 @@ 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;
}
@@ -52,11 +75,11 @@ export async function visitAllLinks(
// 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 === '/') {
@@ -67,31 +90,31 @@ 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();
@@ -99,4 +122,6 @@ export async function visitAllLinks(
queue.push({ changeReturnTo: currentURL() });
queue.push(...links);
}
+
+ return visited.size;
}