Skip to content

Commit 1df179c

Browse files
authored
serializers/crate: Prevent categories and keywords from being cleared (#10721)
Previously, if `categories` and `keywords` of `crate` had existing values, they would be cleared from query results if those value returned null. This caused issues when `crate` was peeked from the store. This commit detects null values and ignores the fields instead of updating them.
1 parent d93a064 commit 1df179c

File tree

3 files changed

+77
-1
lines changed

3 files changed

+77
-1
lines changed

app/serializers/crate.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import ApplicationSerializer from './application';
22

3+
const SKIP_NULL_FIELDS = new Set(['categories', 'keywords']);
4+
35
export default class CrateSerializer extends ApplicationSerializer {
46
isNewSerializerAPI = true;
57

@@ -10,4 +12,20 @@ export default class CrateSerializer extends ApplicationSerializer {
1012

1113
return super.extractRelationships(...arguments);
1214
}
15+
16+
normalizeQueryResponse(_store, _modelClass, payload) {
17+
// We don't want existing relationships overwritten by results with null values.
18+
// See: https://github.com/rust-lang/crates.io/issues/10711
19+
if (payload.crates) {
20+
payload.crates = payload.crates.map(crate => {
21+
for (const rel of SKIP_NULL_FIELDS) {
22+
if (crate[rel] === null) {
23+
delete crate[rel];
24+
}
25+
}
26+
return crate;
27+
});
28+
}
29+
return super.normalizeQueryResponse(...arguments);
30+
}
1331
}

e2e/acceptance/crate.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,33 @@ test.describe('Acceptance | crate page', { tag: '@acceptance' }, () => {
270270
await expect(page).toHaveURL('/crates/nanomsg');
271271
await expect(page.locator('[data-test-keyword]')).toBeVisible();
272272
});
273+
274+
test('keywords are shown when navigating from crate to keywords, and then back to crate', async ({ page, msw }) => {
275+
loadFixtures(msw.db);
276+
277+
await page.goto('/crates/nanomsg');
278+
await expect(page.locator('[data-test-keyword]')).toBeVisible();
279+
280+
await page.getByRole('link', { name: '#network', exact: true }).click();
281+
await expect(page).toHaveURL('/keywords/network');
282+
await page.getByRole('link', { name: 'nanomsg', exact: true }).click();
283+
284+
await expect(page).toHaveURL('/crates/nanomsg');
285+
await expect(page.locator('[data-test-keyword]')).toBeVisible();
286+
});
287+
288+
test('keywords are shown when navigating from crate to searchs, and then back to crate', async ({ page, msw }) => {
289+
loadFixtures(msw.db);
290+
291+
await page.goto('/crates/nanomsg');
292+
await expect(page.locator('[data-test-keyword]')).toBeVisible();
293+
294+
await page.fill('[data-test-search-input]', 'nanomsg');
295+
await page.locator('[data-test-search-form]').getByRole('button', { name: 'Submit' }).click();
296+
await expect(page).toHaveURL('/search?q=nanomsg');
297+
await page.getByRole('link', { name: 'nanomsg', exact: true }).click();
298+
299+
await expect(page).toHaveURL('/crates/nanomsg');
300+
await expect(page.locator('[data-test-keyword]')).toBeVisible();
301+
});
273302
});

tests/acceptance/crate-test.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { click, currentRouteName, currentURL, waitFor } from '@ember/test-helpers';
1+
import { click, currentRouteName, currentURL, fillIn, triggerEvent, waitFor } from '@ember/test-helpers';
22
import { module, skip, test } from 'qunit';
33

44
import { loadFixtures } from '@crates-io/msw/fixtures.js';
@@ -271,4 +271,33 @@ module('Acceptance | crate page', function (hooks) {
271271
assert.strictEqual(currentURL(), '/crates/nanomsg');
272272
assert.dom('[data-test-keyword]').exists();
273273
});
274+
275+
test('keywords are shown when navigating from crate to keywords, and then back to crate', async function (assert) {
276+
loadFixtures(this.db);
277+
278+
await visit('/crates/nanomsg');
279+
assert.dom('[data-test-keyword]').exists();
280+
281+
await click('[data-test-keyword="network"]');
282+
assert.strictEqual(currentURL(), '/keywords/network');
283+
await click('[href="/crates/nanomsg"]');
284+
285+
assert.strictEqual(currentURL(), '/crates/nanomsg');
286+
assert.dom('[data-test-keyword]').exists();
287+
});
288+
289+
test('keywords are shown when navigating from crate to searchs, and then back to crate', async function (assert) {
290+
loadFixtures(this.db);
291+
292+
await visit('/crates/nanomsg');
293+
assert.dom('[data-test-keyword]').exists();
294+
295+
await fillIn('[data-test-search-input]', 'nanomsg');
296+
await triggerEvent('[data-test-search-form]', 'submit');
297+
assert.strictEqual(currentURL(), '/search?q=nanomsg');
298+
await click('[href="/crates/nanomsg"]');
299+
300+
assert.strictEqual(currentURL(), '/crates/nanomsg');
301+
assert.dom('[data-test-keyword]').exists();
302+
});
274303
});

0 commit comments

Comments
 (0)