Skip to content
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
11 changes: 9 additions & 2 deletions app/routes/crates.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class CratesRoute extends Route {
@service router;
@service store;

queryParams = {
page: { refreshModel: true },
sort: { refreshModel: true },
};

model(params) {
return this.store.query('crate', params);
async model(params, transition) {
try {
return await this.store.query('crate', params);
} catch (error) {
let title = `Failed to load crate list`;
let details = error.errors?.[0]?.detail;
return this.router.replaceWith('catch-all', { transition, error, title, details, tryAgain: true });
}
}
}
4 changes: 4 additions & 0 deletions app/templates/catch-all.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

<h1 local-class="title" data-test-title>{{or @model.title "Page not found"}}</h1>

{{#if @model.details}}
<p local-class="details" data-test-details>{{@model.details}}</p>
{{/if}}

{{#if @model.loginNeeded}}
<button
type="button"
Expand Down
22 changes: 22 additions & 0 deletions e2e/acceptance/crates.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { expect, test } from '@/e2e/helper';
import { loadFixtures } from '@crates-io/msw/fixtures';
import { http, HttpResponse } from 'msw';

test.describe('Acceptance | crates page', { tag: '@acceptance' }, () => {
// should match the default set in the crates controller
Expand Down Expand Up @@ -79,4 +80,25 @@ test.describe('Acceptance | crates page', { tag: '@acceptance' }, () => {
await page.goto('/crates');
await expect(page.locator('[data-test-crate-row="0"] [data-test-recent-downloads]')).toHaveText('Recent: 2,000');
});

test('shows error message screen', async ({ page, msw }) => {
loadFixtures(msw.db);

let detail =
'Page 1 is unavailable for performance reasons. Please take a look at https://crates.io/data-access for alternatives.';
let error = HttpResponse.json({ errors: [{ detail }] }, { status: 400 });
await msw.worker.use(http.get('/api/v1/crates', () => error));

await page.goto('/crates');
await expect(page.locator('[data-test-404-page]')).toBeVisible();
await expect(page.locator('[data-test-title]')).toHaveText('Failed to load crate list');
await expect(page.locator('[data-test-details]')).toHaveText(detail);
await expect(page.locator('[data-test-try-again]')).toBeVisible();
await expect(page.locator('[data-test-go-back]')).not.toBeVisible();

await msw.worker.resetHandlers();
await page.click('[data-test-try-again]');
await expect(page.locator('[data-test-404-page]')).not.toBeVisible();
await expect(page.locator('[data-test-crate-row]')).toHaveCount(23);
});
});
25 changes: 24 additions & 1 deletion tests/acceptance/crates-test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { click, currentURL, visit } from '@ember/test-helpers';
import { click, currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';

import { loadFixtures } from '@crates-io/msw/fixtures.js';
import percySnapshot from '@percy/ember';
import a11yAudit from 'ember-a11y-testing/test-support/audit';
import { getPageTitle } from 'ember-page-title/test-support';
import { http, HttpResponse } from 'msw';

import { setupApplicationTest } from 'crates-io/tests/helpers';

import axeConfig from '../axe-config';
import { visit } from '../helpers/visit-ignoring-abort';

module('Acceptance | crates page', function (hooks) {
setupApplicationTest(hooks, { msw: true });
Expand Down Expand Up @@ -92,4 +94,25 @@ module('Acceptance | crates page', function (hooks) {
let formatted = Number(2000).toLocaleString();
assert.dom('[data-test-crate-row="0"] [data-test-recent-downloads]').hasText(`Recent: ${formatted}`);
});

test('shows error message screen', async function (assert) {
loadFixtures(this.db);

let detail =
'Page 1 is unavailable for performance reasons. Please take a look at https://crates.io/data-access for alternatives.';
let error = HttpResponse.json({ errors: [{ detail }] }, { status: 400 });
this.worker.use(http.get('/api/v1/crates', () => error));

await visit('/crates');
assert.dom('[data-test-404-page]').exists();
assert.dom('[data-test-title]').hasText('Failed to load crate list');
assert.dom('[data-test-details]').hasText(detail);
assert.dom('[data-test-try-again]').exists();
assert.dom('[data-test-go-back]').doesNotExist();

this.worker.resetHandlers();
await click('[data-test-try-again]');
assert.dom('[data-test-404-page]').doesNotExist();
assert.dom('[data-test-crate-row]').exists({ count: 23 });
});
});
Loading