diff --git a/my-app/app/controllers/error.ts b/my-app/app/controllers/error.ts
new file mode 100644
index 00000000..fdb77ab7
--- /dev/null
+++ b/my-app/app/controllers/error.ts
@@ -0,0 +1,5 @@
+import Controller from '@ember/controller';
+
+export default class ErrorController extends Controller {
+ declare model: any;
+}
diff --git a/my-app/app/controllers/products/error.ts b/my-app/app/controllers/products/error.ts
index 9c88f4f9..d1290251 100644
--- a/my-app/app/controllers/products/error.ts
+++ b/my-app/app/controllers/products/error.ts
@@ -3,5 +3,7 @@ import Controller from '@ember/controller';
import styles from './error.css';
export default class ProductsErrorController extends Controller {
+ declare model: any;
+
styles = styles;
}
diff --git a/my-app/app/templates/error.hbs b/my-app/app/templates/error.hbs
new file mode 100644
index 00000000..57bd5724
--- /dev/null
+++ b/my-app/app/templates/error.hbs
@@ -0,0 +1,5 @@
+
+
+ {{or this.model (t "routes.error.default-message")}}
+
+
\ No newline at end of file
diff --git a/my-app/app/templates/loading.hbs b/my-app/app/templates/loading.hbs
new file mode 100644
index 00000000..627537ee
--- /dev/null
+++ b/my-app/app/templates/loading.hbs
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/my-app/app/templates/products/error.hbs b/my-app/app/templates/products/error.hbs
new file mode 100644
index 00000000..99fd4701
--- /dev/null
+++ b/my-app/app/templates/products/error.hbs
@@ -0,0 +1,5 @@
+
+
+ {{or this.model (t "routes.error.default-message")}}
+
+
\ No newline at end of file
diff --git a/my-app/app/templates/products/loading.hbs b/my-app/app/templates/products/loading.hbs
new file mode 100644
index 00000000..38c61fbf
--- /dev/null
+++ b/my-app/app/templates/products/loading.hbs
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/my-app/tests/acceptance/products/error-test.ts b/my-app/tests/acceptance/products/error-test.ts
new file mode 100644
index 00000000..49530217
--- /dev/null
+++ b/my-app/tests/acceptance/products/error-test.ts
@@ -0,0 +1,43 @@
+import { visit } from '@ember/test-helpers';
+import { Response } from 'miragejs';
+import {
+ type ApplicationTestContext,
+ setupApplicationTest,
+ setupExperiments,
+} from 'my-app/tests/helpers';
+import { module, test } from 'qunit';
+
+interface TestContext extends ApplicationTestContext {}
+
+module('Acceptance | products/error', function (hooks) {
+ setupApplicationTest(hooks);
+ setupExperiments(hooks, {
+ 'nest-product-details': 'v1',
+ });
+
+ hooks.beforeEach(function (this: TestContext) {
+ this.server.get('/products/:id', () => {
+ return new Response(500, {}, { errors: ['Some server error'] });
+ });
+
+ this.server.create('product', {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore: Assume that Mirage works
+ categoryId: 'cake',
+ description: 'Made with organic herbs',
+ name: 'Vanilla Ice Cream Cake',
+ price: 40,
+ rating: 4.5,
+ seller: "Amy's",
+ shortDescription: 'Made with organic herbs',
+ });
+ });
+
+ test('A user can see the error message', async function (assert) {
+ await visit('/products/1');
+
+ assert
+ .dom('[data-test-error-message]')
+ .exists({ count: 1 }, 'The user sees the error message.');
+ });
+});
diff --git a/my-app/tests/acceptance/products/loading-test.ts b/my-app/tests/acceptance/products/loading-test.ts
new file mode 100644
index 00000000..8cdbb494
--- /dev/null
+++ b/my-app/tests/acceptance/products/loading-test.ts
@@ -0,0 +1,42 @@
+import { settled, visit, waitFor } from '@ember/test-helpers';
+import {
+ type ApplicationTestContext,
+ setupApplicationTest,
+ setupExperiments,
+} from 'my-app/tests/helpers';
+import { module, test } from 'qunit';
+
+interface TestContext extends ApplicationTestContext {}
+
+module('Acceptance | products/loading', function (hooks) {
+ setupApplicationTest(hooks);
+ setupExperiments(hooks, {
+ 'nest-product-details': 'v1',
+ });
+
+ hooks.beforeEach(function (this: TestContext) {
+ this.server.create('product', {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore: Assume that Mirage works
+ categoryId: 'cake',
+ description: 'Made with organic herbs',
+ name: 'Vanilla Ice Cream Cake',
+ price: 40,
+ rating: 4.5,
+ seller: "Amy's",
+ shortDescription: 'Made with organic herbs',
+ });
+ });
+
+ test('A user can see the loading icon', async function (assert) {
+ visit('/products/1');
+
+ await waitFor('[data-test-loading-icon]');
+
+ assert
+ .dom('[data-test-loading-icon]')
+ .exists({ count: 1 }, 'The user can see the loading icon.');
+
+ await settled();
+ });
+});