Skip to content

Commit 20d368e

Browse files
committed
Fix non-canonical crate name pages
Before the Ember Data 5 update it was possible to visit `/crates/foo-bar` when the crate was actually called `foo_bar` and vice-versa. The Ember Data 5 update broke this behavior, and this commit is restoring it, by registering a custom identifier generation method.
1 parent 3f361f1 commit 20d368e

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

app/app.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { setIdentifierGenerationMethod } from '@ember-data/store';
12
import Application from '@ember/application';
23

34
import loadInitializers from 'ember-load-initializers';
@@ -23,3 +24,26 @@ export default class App extends Application {
2324
}
2425

2526
loadInitializers(App, config.modulePrefix);
27+
28+
function toCanonicalName(name) {
29+
return name.toLowerCase().replace(/_/g, '-');
30+
}
31+
32+
function generateIdentifier(resource) {
33+
let { id, lid, type } = resource;
34+
if (lid) {
35+
return lid;
36+
}
37+
38+
if (id) {
39+
if (type === 'crate') {
40+
id = toCanonicalName(id);
41+
}
42+
43+
return `@lid:${type}-${id}`;
44+
}
45+
46+
return crypto.randomUUID();
47+
}
48+
49+
setIdentifierGenerationMethod(generateIdentifier);

e2e/acceptance/crate.spec.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { test, expect } from '@/e2e/helper';
1+
import { expect, test } from '@/e2e/helper';
22

33
test.describe('Acceptance | crate page', { tag: '@acceptance' }, () => {
44
test('visiting a crate page from the front page', async ({ page, mirage }) => {
@@ -139,6 +139,20 @@ test.describe('Acceptance | crate page', { tag: '@acceptance' }, () => {
139139
await expect(page.locator('[data-test-try-again]')).toBeVisible();
140140
});
141141

142+
test('works for non-canonical names', async ({ page, mirage }) => {
143+
await mirage.addHook(server => {
144+
let crate = server.create('crate', { name: 'foo-bar' });
145+
server.create('version', { crate });
146+
});
147+
148+
await page.goto('/crates/foo_bar');
149+
150+
await expect(page).toHaveURL('/crates/foo_bar');
151+
await expect(page).toHaveTitle('foo-bar - crates.io: Rust Package Registry');
152+
153+
await expect(page.locator('[data-test-heading] [data-test-crate-name]')).toHaveText('foo-bar');
154+
});
155+
142156
test('navigating to the all versions page', async ({ page, mirage }) => {
143157
await mirage.addHook(server => {
144158
server.loadFixtures();

tests/acceptance/crate-test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,19 @@ module('Acceptance | crate page', function (hooks) {
131131
assert.dom('[data-test-try-again]').exists();
132132
});
133133

134+
test('works for non-canonical names', async function (assert) {
135+
let crate = this.server.create('crate', { name: 'foo-bar' });
136+
this.server.create('version', { crate });
137+
138+
await visit('/crates/foo_bar');
139+
140+
assert.strictEqual(currentURL(), '/crates/foo_bar');
141+
assert.strictEqual(currentRouteName(), 'crate.index');
142+
assert.strictEqual(getPageTitle(), 'foo-bar - crates.io: Rust Package Registry');
143+
144+
assert.dom('[data-test-heading] [data-test-crate-name]').hasText('foo-bar');
145+
});
146+
134147
test('navigating to the all versions page', async function (assert) {
135148
this.server.loadFixtures();
136149

0 commit comments

Comments
 (0)