From 178d23d2ccb643e46b39724205b006f860a741bc Mon Sep 17 00:00:00 2001 From: JohnAlbin Date: Sun, 14 Apr 2024 18:26:56 +0800 Subject: [PATCH] test(next-drupal): fix "403 forbidden" jest failures Fixes #603 --- .../tests/NextDrupal/resource-methods.test.ts | 5 + .../pages-router-methods.test.ts | 23 - .../next-drupal/tests/utils/mocks/data.ts | 427 +++++++++++++++++- 3 files changed, 430 insertions(+), 25 deletions(-) diff --git a/packages/next-drupal/tests/NextDrupal/resource-methods.test.ts b/packages/next-drupal/tests/NextDrupal/resource-methods.test.ts index 0a2765ca1..e790aa257 100644 --- a/packages/next-drupal/tests/NextDrupal/resource-methods.test.ts +++ b/packages/next-drupal/tests/NextDrupal/resource-methods.test.ts @@ -330,6 +330,7 @@ describe("getResource()", () => { test("throws an error if revision access is forbidden", async () => { const drupal = new NextDrupal(BASE_URL) + spyOnFetch({ responseBody: mocks.resources.node.forbidden, status: 403 }) await expect( drupal.getResource( @@ -501,6 +502,10 @@ describe("getResourceByPath()", () => { test("throws an error if revision access is forbidden", async () => { const drupal = new NextDrupal(BASE_URL) + spyOnFetch({ + responseBody: mocks.resources.subRequests.forbidden, + status: 207, + }) await expect( drupal.getResourceByPath( diff --git a/packages/next-drupal/tests/NextDrupalPages/pages-router-methods.test.ts b/packages/next-drupal/tests/NextDrupalPages/pages-router-methods.test.ts index 1ef3f2c7c..456ee032e 100644 --- a/packages/next-drupal/tests/NextDrupalPages/pages-router-methods.test.ts +++ b/packages/next-drupal/tests/NextDrupalPages/pages-router-methods.test.ts @@ -889,29 +889,6 @@ describe("getResourceFromContext()", () => { ) }) - test("throws an error if revision access is forbidden", async () => { - const drupal = new NextDrupalPages(BASE_URL) - - const context: GetStaticPropsContext = { - previewData: { - resourceVersion: "id:1", - }, - params: { - slug: ["recipes", "deep-mediterranean-quiche"], - }, - } - - await expect( - drupal.getResourceFromContext("node--recipe", context, { - params: { - "fields[node--recipe]": "title", - }, - }) - ).rejects.toThrow( - "403 Forbidden\nThe current user is not allowed to GET the selected resource. The user does not have access to the requested version." - ) - }) - test("makes un-authenticated requests by default", async () => { const drupal = new NextDrupalPages(BASE_URL) const drupalFetchSpy = spyOnDrupalFetch(drupal) diff --git a/packages/next-drupal/tests/utils/mocks/data.ts b/packages/next-drupal/tests/utils/mocks/data.ts index dd5397054..c6be6fa63 100644 --- a/packages/next-drupal/tests/utils/mocks/data.ts +++ b/packages/next-drupal/tests/utils/mocks/data.ts @@ -235,7 +235,330 @@ const resources = { }, }, }, + node: { + ok: { + jsonapi: { + meta: { + links: { + self: { + href: "http://jsonapi.org/format/1.0/", + }, + }, + }, + version: "1.0", + }, + data: { + type: "node--recipe", + id: "71e04ead-4cc7-416c-b9ca-60b635fdc50f", + attributes: { + changed: "2022-03-25T08:02:17+00:00", + content_translation_outdated: false, + content_translation_source: "und", + created: "2022-03-21T10:52:42+00:00", + default_langcode: true, + drupal_internal__nid: 1, + drupal_internal__vid: 37, + field_cooking_time: 30, + field_difficulty: "medium", + field_ingredients: [ + "For the pastry:", + "280g plain flour", + "140g butter", + "Cold water", + "For the filling:", + "1 onion", + "2 garlic cloves", + "Half a courgette", + "450ml soya milk", + "500g grated parmesan", + "2 eggs", + "200g sun dried tomatoes", + "100g feta", + ], + field_number_of_servings: 8, + field_preparation_time: 40, + field_recipe_instruction: { + format: "basic_html", + processed: + "
  1. Preheat the oven to 400°F/200°C. Starting with the pastry; rub the flour and butter together in a bowl until crumbling like breadcrumbs. Add water, a little at a time, until it forms a dough.
  2. \n" + + "
  3. Roll out the pastry on a floured board and gently spread over your tin. Place in the fridge for 20 minutes before blind baking for a further 10.
  4. \n" + + "
  5. Whilst the pastry is cooling, chop and gently cook the onions, garlic and courgette.
  6. \n" + + "
  7. In a large bowl, add the soya milk, half the parmesan, and the eggs. Gently mix.
  8. \n" + + "
  9. Once the pastry is cooked, spread the onions, garlic and sun dried tomatoes over the base and pour the eggs mix over. Sprinkle the remaining parmesan and careful lay the feta over the top. Bake for 30 minutes or until golden brown.
  10. \n" + + "
", + value: + "
    \n" + + "\t
  1. Preheat the oven to 400°F/200°C. Starting with the pastry; rub the flour and butter together in a bowl until crumbling like breadcrumbs. Add water, a little at a time, until it forms a dough.
  2. \n" + + "\t
  3. Roll out the pastry on a floured board and gently spread over your tin. Place in the fridge for 20 minutes before blind baking for a further 10.
  4. \n" + + "\t
  5. Whilst the pastry is cooling, chop and gently cook the onions, garlic and courgette.
  6. \n" + + "\t
  7. In a large bowl, add the soya milk, half the parmesan, and the eggs. Gently mix.
  8. \n" + + "\t
  9. Once the pastry is cooked, spread the onions, garlic and sun dried tomatoes over the base and pour the eggs mix over. Sprinkle the remaining parmesan and careful lay the feta over the top. Bake for 30 minutes or until golden brown.
  10. \n" + + "
", + }, + field_summary: { + format: "basic_html", + processed: + "

An Italian inspired quiche with sun dried tomatoes and courgette. A perfect light meal for a summer's day.

", + value: + "

An Italian inspired quiche with sun dried tomatoes and courgette. A perfect light meal for a summer's day.

", + }, + langcode: "en", + moderation_state: "published", + path: { + alias: "/recipes/deep-mediterranean-quiche", + langcode: "en", + pid: 67, + }, + promote: true, + revision_log: null, + revision_timestamp: "2022-03-25T08:02:17+00:00", + revision_translation_affected: true, + status: true, + sticky: false, + title: "Deep mediterranean quiche - edited", + }, + relationships: { + field_media_image: { + data: { + id: "bbfe9d97-2da2-432b-a22c-0396c08e06ca", + meta: { + drupal_internal__target_id: 1, + }, + type: "media--image", + }, + links: { + related: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/field_media_image?resourceVersion=id%3A37", + }, + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/relationships/field_media_image?resourceVersion=id%3A37", + }, + }, + }, + field_recipe_category: { + data: [ + { + id: "a6c02fe4-67bf-462c-90cb-32281a07efe4", + meta: { + drupal_internal__target_id: 31, + }, + type: "taxonomy_term--recipe_category", + }, + ], + links: { + related: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/field_recipe_category?resourceVersion=id%3A37", + }, + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/relationships/field_recipe_category?resourceVersion=id%3A37", + }, + }, + }, + field_tags: { + data: [ + { + id: "46258827-cfad-4813-99dc-287c4cb41117", + meta: { + drupal_internal__target_id: 22, + }, + type: "taxonomy_term--tags", + }, + { + id: "f32a4d84-0568-4bfd-8be3-8217d36efb6d", + meta: { + drupal_internal__target_id: 13, + }, + type: "taxonomy_term--tags", + }, + ], + links: { + related: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/field_tags?resourceVersion=id%3A37", + }, + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/relationships/field_tags?resourceVersion=id%3A37", + }, + }, + }, + node_type: { + data: { + id: "9b70a287-cade-454f-be8b-dea7b9a37c7a", + meta: { + drupal_internal__target_id: "recipe", + }, + type: "node_type--node_type", + }, + links: { + related: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/node_type?resourceVersion=id%3A37", + }, + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/relationships/node_type?resourceVersion=id%3A37", + }, + }, + }, + revision_uid: { + data: { + id: "365cc7b5-ddc4-4b3b-939e-1494400aab4a", + meta: { + drupal_internal__target_id: 1, + }, + type: "user--user", + }, + links: { + related: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/revision_uid?resourceVersion=id%3A37", + }, + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/relationships/revision_uid?resourceVersion=id%3A37", + }, + }, + }, + uid: { + data: { + id: "9e4944e8-dd77-407a-8610-83e823b48b56", + meta: { + drupal_internal__target_id: 4, + }, + type: "user--user", + }, + links: { + related: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/uid?resourceVersion=id%3A37", + }, + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f/relationships/uid?resourceVersion=id%3A37", + }, + }, + }, + }, + links: { + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f?resourceVersion=id%3A37", + }, + }, + }, + links: { + self: { + href: "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f", + }, + }, + }, + forbidden: { + jsonapi: { + version: "1.0", + meta: { links: { self: { href: "http://jsonapi.org/format/1.0/" } } }, + }, + errors: [ + { + title: "Forbidden", + status: "403", + detail: + "The current user is not allowed to GET the selected resource. The user does not have access to the requested version.", + source: { pointer: "/data" }, + }, + ], + }, + }, + translatePath: { + jsonapi: { + basePath: "/en/jsonapi", + entryPoint: "https://example.com/en/jsonapi", + individual: + "https://example.com/en/jsonapi/node/recipe/71e04ead-4cc7-416c-b9ca-60b635fdc50f", + resourceName: "node--recipe", + }, + entity: { + bundle: "recipe", + canonical: "https://example.com/en/recipes/deep-mediterranean-quiche", + id: "1", + langcode: "en", + path: "/en/recipes/deep-mediterranean-quiche", + type: "node", + uuid: "71e04ead-4cc7-416c-b9ca-60b635fdc50f", + }, + isHomePath: false, + label: "Deep mediterranean quiche - edited", + resolved: "https://example.com/en/recipes/deep-mediterranean-quiche", + }, + subRequests: { + ok: { + router: { + body: "SEE REPLACEMENT BELOW", + headers: { + "cache-control": ["no-cache, private"], + "content-id": [""], + "content-type": ["application/json"], + date: ["Fri, 12 Apr 2024 16:44:53 GMT"], + status: [200], + "x-drupal-dynamic-cache": ["HIT"], + }, + }, + "resolvedResource#uri{0}": { + body: "SEE REPLACEMENT BELOW", + headers: { + "cache-control": ["no-cache, private"], + "content-id": [""], + "content-type": ["application/vnd.api+json"], + date: ["Fri, 12 Apr 2024 16:44:54 GMT"], + status: [200], + "x-drupal-dynamic-cache": ["HIT"], + }, + }, + }, + forbidden: { + router: { + body: "SEE REPLACEMENT BELOW", + headers: { + "cache-control": ["no-cache, private"], + "content-id": [""], + "content-type": ["application/json"], + date: ["Fri, 12 Apr 2024 16:44:53 GMT"], + status: [200], + "x-drupal-dynamic-cache": ["HIT"], + }, + }, + "resolvedResource#uri{0}": { + body: "SEE REPLACEMENT BELOW", + headers: { + "cache-control": ["no-cache, private"], + "content-id": [""], + "content-type": ["application/vnd.api+json"], + date: ["Fri, 12 Apr 2024 16:44:54 GMT"], + status: [403], + "x-drupal-dynamic-cache": ["MISS"], + }, + }, + }, + pathNotFound: { + router: { + body: JSON.stringify({ + message: "Unable to resolve path /path-does-not-exist.", + details: + "None of the available methods were able to find a match for this path.", + }), + headers: { + "cache-control": ["no-cache, private"], + "content-id": [""], + "content-type": ["application/json"], + date: ["Fri, 12 Apr 2024 16:44:54 GMT"], + status: [404], + "x-drupal-dynamic-cache": ["MISS"], + }, + }, + }, + }, } +// JSON-encode the subrequest body fields. +resources.subRequests.ok.router.body = JSON.stringify(resources.translatePath) +resources.subRequests.ok["resolvedResource#uri{0}"].body = JSON.stringify( + resources.node.ok +) +resources.subRequests.forbidden.router.body = JSON.stringify( + resources.translatePath +) +resources.subRequests.forbidden["resolvedResource#uri{0}"].body = + JSON.stringify(resources.node.forbidden) const menus = { menuItems: { @@ -319,10 +642,110 @@ const menus = { weight: "30", }, }, + { + type: "menu_link_content--menu_link_content", + id: "menu_link_content:c116329b-dd21-445d-ab44-9f89f940339c", + attributes: { + description: null, + enabled: true, + expanded: false, + menu_name: "main", + meta: { + entity_id: "1", + }, + options: [], + parent: "", + provider: "menu_link_content", + route: { + name: "entity.node.canonical", + parameters: { + node: "1", + }, + }, + title: "About", + url: "/en/about", + weight: 40, + }, + }, + { + type: "menu_link_content--menu_link_content", + id: "menu_link_content:87d2132d-a55c-4743-aebc-87c050c58ba3", + attributes: { + description: null, + enabled: true, + expanded: false, + menu_name: "main", + meta: { + entity_id: "3", + }, + options: [], + parent: "menu_link_content:c116329b-dd21-445d-ab44-9f89f940339c", + provider: "menu_link_content", + route: { + name: "entity.node.canonical", + parameters: { + node: "2", + }, + }, + title: "Locations", + url: "/en/about/locations", + weight: -10, + }, + }, + { + type: "menu_link_content--menu_link_content", + id: "menu_link_content:7b1de73b-2497-4634-854c-6ef6142b790b", + attributes: { + description: null, + enabled: true, + expanded: false, + menu_name: "main", + meta: { + entity_id: "2", + }, + options: [], + parent: "menu_link_content:c116329b-dd21-445d-ab44-9f89f940339c", + provider: "menu_link_content", + route: { + name: "entity.node.canonical", + parameters: { + node: "3", + }, + }, + title: "Team", + url: "/en/about/team", + weight: 0, + }, + }, + { + type: "menu_link_content--menu_link_content", + id: "menu_link_content:80b574f3-5271-4769-93c5-8ae406864b0c", + attributes: { + description: null, + enabled: true, + expanded: false, + menu_name: "main", + meta: { + entity_id: "4", + }, + options: [], + parent: "menu_link_content:7b1de73b-2497-4634-854c-6ef6142b790b", + provider: "menu_link_content", + route: { + name: "entity.node.canonical", + parameters: { + node: "4", + }, + }, + title: "Management", + url: "/en/about/team/management", + weight: 0, + }, + }, ], links: { self: { - href: "https://next-drupal-test.ddev.site/jsonapi/menu_items/main", + href: "https://example.com/jsonapi/menu_items/main", }, }, }, @@ -345,7 +768,7 @@ const menus = { 'The "menu" parameter was not converted for the path "/jsonapi/menu_items/{menu}" (route name: "jsonapi_menu_items.menu")', links: { via: { - href: "https://next-drupal-test.ddev.site/jsonapi/menu_items/INVALID", + href: "https://example.com/jsonapi/menu_items/INVALID", }, info: { href: "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5",