diff --git a/app/adapters/crate.js b/app/adapters/crate.js index 544514604bf..5dc3b05f122 100644 --- a/app/adapters/crate.js +++ b/app/adapters/crate.js @@ -6,12 +6,23 @@ export default class CrateAdapter extends ApplicationAdapter { coalesceFindRequests = true; findRecord(store, type, id, snapshot) { - let { include } = snapshot; - // This ensures `crate.versions` are always fetched from another request. - if (include === undefined) { - snapshot.include = 'keywords,categories,downloads'; + return super.findRecord(store, type, id, setDefaultInclude(snapshot)); + } + + queryRecord(store, type, query, adapterOptions) { + return super.queryRecord(store, type, setDefaultInclude(query), adapterOptions); + } + + /** Removes the `name` query parameter and turns it into a path parameter instead */ + urlForQueryRecord(query) { + let baseUrl = super.urlForQueryRecord(...arguments); + if (!query.name) { + return baseUrl; } - return super.findRecord(store, type, id, snapshot); + + let crateName = query.name; + delete query.name; + return `${baseUrl}/${crateName}`; } groupRecordsForFindMany(store, snapshots) { @@ -22,3 +33,12 @@ export default class CrateAdapter extends ApplicationAdapter { return result; } } + +function setDefaultInclude(query) { + if (query.include === undefined) { + // This ensures `crate.versions` are always fetched from another request. + query.include = 'keywords,categories,downloads'; + } + + return query; +} diff --git a/app/routes/crate.js b/app/routes/crate.js index f8646db3baa..84a1fe56739 100644 --- a/app/routes/crate.js +++ b/app/routes/crate.js @@ -12,7 +12,7 @@ export default class CrateRoute extends Route { let crateName = params.crate_id; try { - return await this.store.findRecord('crate', crateName); + return this.store.peekRecord('crate', crateName) || (await this.store.queryRecord('crate', { name: crateName })); } catch (error) { if (error instanceof NotFoundError) { let title = `${crateName}: Crate not found`; diff --git a/e2e/acceptance/crate.spec.ts b/e2e/acceptance/crate.spec.ts index 906365cbc45..505545ae678 100644 --- a/e2e/acceptance/crate.spec.ts +++ b/e2e/acceptance/crate.spec.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@/e2e/helper'; +import { expect, test } from '@/e2e/helper'; test.describe('Acceptance | crate page', { tag: '@acceptance' }, () => { test('visiting a crate page from the front page', async ({ page, mirage }) => { @@ -139,6 +139,20 @@ test.describe('Acceptance | crate page', { tag: '@acceptance' }, () => { await expect(page.locator('[data-test-try-again]')).toBeVisible(); }); + test('works for non-canonical names', async ({ page, mirage }) => { + await mirage.addHook(server => { + let crate = server.create('crate', { name: 'foo-bar' }); + server.create('version', { crate }); + }); + + await page.goto('/crates/foo_bar'); + + await expect(page).toHaveURL('/crates/foo_bar'); + await expect(page).toHaveTitle('foo-bar - crates.io: Rust Package Registry'); + + await expect(page.locator('[data-test-heading] [data-test-crate-name]')).toHaveText('foo-bar'); + }); + test('navigating to the all versions page', async ({ page, mirage }) => { await mirage.addHook(server => { server.loadFixtures(); diff --git a/tests/acceptance/crate-test.js b/tests/acceptance/crate-test.js index 0b607c54c22..ab6f22d53fe 100644 --- a/tests/acceptance/crate-test.js +++ b/tests/acceptance/crate-test.js @@ -131,6 +131,19 @@ module('Acceptance | crate page', function (hooks) { assert.dom('[data-test-try-again]').exists(); }); + test('works for non-canonical names', async function (assert) { + let crate = this.server.create('crate', { name: 'foo-bar' }); + this.server.create('version', { crate }); + + await visit('/crates/foo_bar'); + + assert.strictEqual(currentURL(), '/crates/foo_bar'); + assert.strictEqual(currentRouteName(), 'crate.index'); + assert.strictEqual(getPageTitle(), 'foo-bar - crates.io: Rust Package Registry'); + + assert.dom('[data-test-heading] [data-test-crate-name]').hasText('foo-bar'); + }); + test('navigating to the all versions page', async function (assert) { this.server.loadFixtures();