Bugzilla – Attachment 180318 Details for
Bug 39315
Missing tests for KohaTable search on coded value's description
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 39315: Move holdings Cypress tests to a separate file
Bug-39315-Move-holdings-Cypress-tests-to-a-separat.patch (text/plain), 31.27 KB, created by
David Nind
on 2025-04-02 12:38:28 UTC
(
hide
)
Description:
Bug 39315: Move holdings Cypress tests to a separate file
Filename:
MIME Type:
Creator:
David Nind
Created:
2025-04-02 12:38:28 UTC
Size:
31.27 KB
patch
obsolete
>From 6b2d5ccd6207a9da61cfec86d92993794750a0c4 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@bugs.koha-community.org> >Date: Wed, 12 Mar 2025 10:11:23 +0100 >Subject: [PATCH] Bug 39315: Move holdings Cypress tests to a separate file > >Signed-off-by: David Nind <david@davidnind.com> >--- > .../integration/KohaTable/Holdings_spec.ts | 292 ++++++++++++++ > .../integration/KohaTable/KohaTable_spec.ts | 367 +----------------- > t/cypress/support/e2e.js | 36 ++ > 3 files changed, 335 insertions(+), 360 deletions(-) > create mode 100644 t/cypress/integration/KohaTable/Holdings_spec.ts > >diff --git a/t/cypress/integration/KohaTable/Holdings_spec.ts b/t/cypress/integration/KohaTable/Holdings_spec.ts >new file mode 100644 >index 0000000000..0248ba773e >--- /dev/null >+++ b/t/cypress/integration/KohaTable/Holdings_spec.ts >@@ -0,0 +1,292 @@ >+const RESTdefaultPageSize = "20"; // FIXME Mock this >+const baseTotalCount = "42"; >+ >+describe("catalogue/detail/holdings_table", () => { >+ const table_id = "holdings_table"; >+ beforeEach(() => { >+ cy.login(); >+ cy.title().should("eq", "Koha staff interface"); >+ cy.window().then(win => { >+ win.localStorage.clear(); >+ }); >+ >+ // FIXME All the following code should not be reused as it >+ // It must be moved to a Cypress command or task "buildSampleBiblio" or even "insertSampleBiblio" >+ let generated_objects = {}; >+ const objects = [{ object: "library" }, { object: "item_type" }]; >+ cy.wrap(Promise.resolve()) >+ .then(() => { >+ return objects.reduce((chain, { object }) => { >+ return chain.then(() => { >+ return cy >+ .task("buildSampleObject", { object }) >+ .then(attributes => { >+ generated_objects[object] = attributes; >+ }); >+ }); >+ }, Promise.resolve()); >+ }) >+ .then(() => { >+ const library = generated_objects["library"]; >+ const item_type = generated_objects["item_type"]; >+ const queries = [ >+ { >+ query: "INSERT INTO branches(branchcode, branchname) VALUES (?, ?)", >+ values: [library.library_id, library.name], >+ }, >+ { >+ query: "INSERT INTO itemtypes(itemtype, description) VALUES (?, ?)", >+ values: [item_type.item_type_id, item_type.description], >+ }, >+ ]; >+ cy.wrap(Promise.resolve()) >+ .then(() => { >+ return queries.reduce((chain, { query, values }) => { >+ return chain.then(() => cy.query(query, values)); >+ }, Promise.resolve()); >+ }) >+ .then(() => { >+ let biblio = { >+ leader: " nam a22 7a 4500", >+ fields: [ >+ { "005": "20250120101920.0" }, >+ { >+ "245": { >+ ind1: "", >+ ind2: "", >+ subfields: [{ a: "Some boring read" }], >+ }, >+ }, >+ { >+ "100": { >+ ind1: "", >+ ind2: "", >+ subfields: [ >+ { c: "Some boring author" }, >+ ], >+ }, >+ }, >+ { >+ "942": { >+ ind1: "", >+ ind2: "", >+ subfields: [ >+ { c: item_type.item_type_id }, >+ ], >+ }, >+ }, >+ ], >+ }; >+ cy.request({ >+ method: "POST", >+ url: "/api/v1/biblios", >+ headers: { >+ "Content-Type": "application/marc-in-json", >+ "x-confirm-not-duplicate": 1, >+ }, >+ body: biblio, >+ }).then(response => { >+ const biblio_id = response.body.id; >+ cy.wrap(biblio_id).as("biblio_id"); >+ cy.request({ >+ method: "POST", >+ url: `/api/v1/biblios/${biblio_id}/items`, >+ headers: { >+ "Content-Type": "application/json", >+ }, >+ body: { >+ home_library_id: library.library_id, >+ holding_library_id: library.library_id, >+ }, >+ }); >+ }); >+ }); >+ }); >+ cy.query( >+ "SELECT value FROM systempreferences WHERE variable='AlwaysShowHoldingsTableFilters'" >+ ).then(value => { >+ cy.wrap(value).as("syspref_AlwaysShowHoldingsTableFilters"); >+ }); >+ }); >+ >+ afterEach( >+ () => >+ function () { >+ cleanup(); >+ cy.set_syspref( >+ "AlwaysShowHoldingsTableFilters", >+ this.syspref_AlwaysShowHoldingsTableFilters >+ ); >+ } >+ ); >+ >+ it("Correctly init the table", function () { >+ // Do not use `() => {` or this.biblio_id won't be retrieved >+ const biblio_id = this.biblio_id; >+ cy.task("buildSampleObjects", { >+ object: "item", >+ count: RESTdefaultPageSize, >+ values: { >+ biblio_id, >+ checkout: null, >+ transfer: null, >+ lost_status: 0, >+ withdrawn: 0, >+ damaged_status: 0, >+ not_for_loan_status: 0, >+ course_item: null, >+ cover_image_ids: [], >+ }, >+ }).then(items => { >+ cy.intercept("get", `/api/v1/biblios/${biblio_id}/items*`, { >+ statuscode: 200, >+ body: items, >+ headers: { >+ "X-Base-Total-Count": baseTotalCount, >+ "X-Total-Count": baseTotalCount, >+ }, >+ }); >+ >+ cy.visit( >+ "/cgi-bin/koha/catalogue/detail.pl?biblionumber=" + biblio_id >+ ); >+ >+ cy.window().then(win => { >+ win.libraries_map = items.reduce((map, i) => { >+ map[i.library_id] = i.library_id; >+ return map; >+ }, {}); >+ }); >+ >+ cy.get(`#${table_id}_wrapper tbody tr`).should( >+ "have.length", >+ RESTdefaultPageSize >+ ); >+ >+ cy.get(`#${table_id}_wrapper .dt-info`).contains( >+ `Showing 1 to ${RESTdefaultPageSize} of ${baseTotalCount} entries` >+ ); >+ }); >+ }); >+ >+ it("Show filters", function () { >+ // Do not use `() => {` or this.biblio_id won't be retrieved >+ const biblio_id = this.biblio_id; >+ cy.task("buildSampleObjects", { >+ object: "item", >+ count: RESTdefaultPageSize, >+ values: { >+ biblio_id, >+ checkout: null, >+ transfer: null, >+ lost_status: 0, >+ withdrawn: 0, >+ damaged_status: 0, >+ not_for_loan_status: 0, >+ course_item: null, >+ cover_image_ids: [], >+ }, >+ }).then(items => { >+ cy.intercept("get", `/api/v1/biblios/${biblio_id}/items*`, { >+ statuscode: 200, >+ body: items, >+ headers: { >+ "X-Base-Total-Count": baseTotalCount, >+ "X-Total-Count": baseTotalCount, >+ }, >+ }); >+ >+ cy.set_syspref("AlwaysShowHoldingsTableFilters", 0).then(() => { >+ cy.visit( >+ "/cgi-bin/koha/catalogue/detail.pl?biblionumber=" + >+ biblio_id >+ ); >+ >+ // Hide the 'URL' column >+ cy.mock_table_settings( >+ { >+ columns: { uri: { is_hidden: 1 } }, >+ }, >+ "items_table_settings.holdings" >+ ); >+ >+ cy.window().then(win => { >+ win.libraries_map = items.reduce((map, i) => { >+ map[i.library_id] = i.library_id; >+ return map; >+ }, {}); >+ }); >+ >+ cy.get("@columns").then(columns => { >+ cy.get(`#${table_id}_wrapper tbody tr`).should( >+ "have.length", >+ RESTdefaultPageSize >+ ); >+ >+ // Filters are not displayed >+ cy.get(`#${table_id} thead tr`).should("have.length", 1); >+ >+ cy.get(`#${table_id} th`).contains("Status"); >+ cy.get(`#${table_id} th`) >+ .contains("URL") >+ .should("not.exist"); >+ cy.get(`#${table_id} th`) >+ .contains("Course reserves") >+ .should("not.exist"); >+ >+ cy.get(".show_filters").click(); >+ cy.get(`#${table_id}_wrapper .dt-info`).contains( >+ `Showing 1 to ${RESTdefaultPageSize} of ${baseTotalCount} entries` >+ ); >+ // Filters are displayed >+ cy.get(`#${table_id} thead tr`).should("have.length", 2); >+ >+ cy.get(`#${table_id} th`).contains("Status"); >+ cy.get(`#${table_id} th`) >+ .contains("URL") >+ .should("not.exist"); >+ cy.get(`#${table_id} th`) >+ .contains("Course reserves") >+ .should("not.exist"); >+ }); >+ }); >+ >+ cy.set_syspref("AlwaysShowHoldingsTableFilters", 1).then(() => { >+ cy.visit( >+ "/cgi-bin/koha/catalogue/detail.pl?biblionumber=" + >+ biblio_id >+ ); >+ >+ // Hide the 'URL' column >+ cy.mock_table_settings( >+ { >+ columns: { uri: { is_hidden: 1 } }, >+ }, >+ "items_table_settings.holdings" >+ ); >+ >+ cy.window().then(win => { >+ win.libraries_map = items.reduce((map, i) => { >+ map[i.library_id] = i.library_id; >+ return map; >+ }, {}); >+ }); >+ >+ cy.get("@columns").then(columns => { >+ cy.get(`#${table_id}_wrapper tbody tr`).should( >+ "have.length", >+ RESTdefaultPageSize >+ ); >+ >+ // Filters are displayed >+ cy.get(`#${table_id} thead tr`).should("have.length", 2); >+ >+ cy.get(".hide_filters").click(); >+ >+ // Filters are not displayed >+ cy.get(`#${table_id} thead tr`).should("have.length", 1); >+ }); >+ }); >+ }); >+ }); >+}); >diff --git a/t/cypress/integration/KohaTable/KohaTable_spec.ts b/t/cypress/integration/KohaTable/KohaTable_spec.ts >index efced8e4b6..6e9194967e 100644 >--- a/t/cypress/integration/KohaTable/KohaTable_spec.ts >+++ b/t/cypress/integration/KohaTable/KohaTable_spec.ts >@@ -22,42 +22,6 @@ function build_libraries() { > }); > } > >-function mock_table_settings(settings, table_settings_var) { >- cy.window().then(win => { >- let table_settings = >- typeof table_settings_var === "undefined" >- ? win.table_settings >- : table_settings_var >- .split(".") >- .reduce((acc, key) => acc[key], win); >- >- table_settings.columns = table_settings.columns.map(c => ({ >- ...c, >- is_hidden: 0, >- cannot_be_toggled: 0, >- })); >- if (settings && settings.hasOwnProperty("default_save_state")) { >- table_settings.default_save_state = settings.default_save_state; >- } >- if (settings && settings.hasOwnProperty("default_save_state_search")) { >- table_settings.default_save_state_search = >- settings.default_save_state_search; >- } >- >- if (settings && settings.columns) { >- Object.entries(settings.columns).forEach(([name, values]) => { >- let column = table_settings.columns.find( >- cc => cc.columnname == name >- ); >- Object.entries(values).forEach(([prop, value]) => { >- column[prop] = value; >- }); >- }); >- } >- cy.wrap(table_settings.columns).as("columns"); >- }); >-} >- > describe("kohaTable (using REST API)", () => { > beforeEach(() => { > cy.login(); >@@ -114,7 +78,7 @@ describe("kohaTable (using REST API)", () => { > build_libraries().then(() => { > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings(); >+ cy.mock_table_settings(); > cy.get("@columns").then(columns => { > cy.get(`#${table_id} th`).should( > "have.length", >@@ -128,7 +92,7 @@ describe("kohaTable (using REST API)", () => { > build_libraries().then(() => { > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings({ >+ cy.mock_table_settings({ > columns: { library_code: { is_hidden: 1 } }, > }); > >@@ -148,7 +112,7 @@ describe("kohaTable (using REST API)", () => { > build_libraries().then(() => { > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings({ >+ cy.mock_table_settings({ > default_save_state: 0, > columns: { library_code: { is_hidden: 1 } }, > }); >@@ -176,7 +140,7 @@ describe("kohaTable (using REST API)", () => { > > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings({ >+ cy.mock_table_settings({ > default_save_state: 0, > columns: { library_code: { is_hidden: 1 } }, > }); >@@ -198,7 +162,7 @@ describe("kohaTable (using REST API)", () => { > build_libraries().then(() => { > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings({ >+ cy.mock_table_settings({ > default_save_state: 1, > columns: { library_code: { is_hidden: 1 } }, > }); >@@ -226,7 +190,7 @@ describe("kohaTable (using REST API)", () => { > > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings({ >+ cy.mock_table_settings({ > default_save_state: 1, > columns: { library_code: { is_hidden: 1 } }, > }); >@@ -246,7 +210,7 @@ describe("kohaTable (using REST API)", () => { > build_libraries().then(() => { > cy.visit("/cgi-bin/koha/admin/branches.pl"); > >- mock_table_settings({ >+ cy.mock_table_settings({ > default_save_state: 1, > columns: { library_code: { is_hidden: 1 } }, > }); >@@ -476,320 +440,3 @@ describe("ERM ", () => { > }); > }); > }); >- >-describe("Hit all tables", () => { >- beforeEach(() => { >- cy.login(); >- cy.title().should("eq", "Koha staff interface"); >- cy.window().then(win => { >- win.localStorage.clear(); >- }); >- }); >- >- describe("catalogue/detail/holdings_table", () => { >- const table_id = "holdings_table"; >- beforeEach(() => { >- // FIXME All the following code should not be reused as it >- // It must be moved to a Cypress command or task "buildSampleBiblio" or even "insertSampleBiblio" >- let generated_objects = {}; >- const objects = [{ object: "library" }, { object: "item_type" }]; >- cy.wrap(Promise.resolve()) >- .then(() => { >- return objects.reduce((chain, { object }) => { >- return chain.then(() => { >- return cy >- .task("buildSampleObject", { object }) >- .then(attributes => { >- generated_objects[object] = attributes; >- }); >- }); >- }, Promise.resolve()); >- }) >- .then(() => { >- const library = generated_objects["library"]; >- const item_type = generated_objects["item_type"]; >- const queries = [ >- { >- query: "INSERT INTO branches(branchcode, branchname) VALUES (?, ?)", >- values: [library.library_id, library.name], >- }, >- { >- query: "INSERT INTO itemtypes(itemtype, description) VALUES (?, ?)", >- values: [ >- item_type.item_type_id, >- item_type.description, >- ], >- }, >- ]; >- cy.wrap(Promise.resolve()) >- .then(() => { >- return queries.reduce( >- (chain, { query, values }) => { >- return chain.then(() => >- cy.query(query, values) >- ); >- }, >- Promise.resolve() >- ); >- }) >- .then(() => { >- let biblio = { >- leader: " nam a22 7a 4500", >- fields: [ >- { "005": "20250120101920.0" }, >- { >- "245": { >- ind1: "", >- ind2: "", >- subfields: [ >- { a: "Some boring read" }, >- ], >- }, >- }, >- { >- "100": { >- ind1: "", >- ind2: "", >- subfields: [ >- { c: "Some boring author" }, >- ], >- }, >- }, >- { >- "942": { >- ind1: "", >- ind2: "", >- subfields: [ >- { c: item_type.item_type_id }, >- ], >- }, >- }, >- ], >- }; >- cy.request({ >- method: "POST", >- url: "/api/v1/biblios", >- headers: { >- "Content-Type": "application/marc-in-json", >- "x-confirm-not-duplicate": 1, >- }, >- body: biblio, >- }).then(response => { >- const biblio_id = response.body.id; >- cy.wrap(biblio_id).as("biblio_id"); >- cy.request({ >- method: "POST", >- url: `/api/v1/biblios/${biblio_id}/items`, >- headers: { >- "Content-Type": "application/json", >- }, >- body: { >- home_library_id: library.library_id, >- holding_library_id: library.library_id, >- }, >- }); >- }); >- }); >- }); >- cy.query( >- "SELECT value FROM systempreferences WHERE variable='AlwaysShowHoldingsTableFilters'" >- ).then(value => { >- cy.wrap(value).as("syspref_AlwaysShowHoldingsTableFilters"); >- }); >- }); >- >- afterEach( >- () => >- function () { >- cleanup(); >- cy.set_syspref( >- "AlwaysShowHoldingsTableFilters", >- this.syspref_AlwaysShowHoldingsTableFilters >- ); >- } >- ); >- >- it("Correctly init the table", function () { >- // Do not use `() => {` or this.biblio_id won't be retrieved >- const biblio_id = this.biblio_id; >- cy.task("buildSampleObjects", { >- object: "item", >- count: RESTdefaultPageSize, >- values: { >- biblio_id, >- checkout: null, >- transfer: null, >- lost_status: 0, >- withdrawn: 0, >- damaged_status: 0, >- not_for_loan_status: 0, >- course_item: null, >- cover_image_ids: [], >- }, >- }).then(items => { >- cy.intercept("get", `/api/v1/biblios/${biblio_id}/items*`, { >- statuscode: 200, >- body: items, >- headers: { >- "X-Base-Total-Count": baseTotalCount, >- "X-Total-Count": baseTotalCount, >- }, >- }); >- >- cy.visit( >- "/cgi-bin/koha/catalogue/detail.pl?biblionumber=" + >- biblio_id >- ); >- >- cy.window().then(win => { >- win.libraries_map = items.reduce((map, i) => { >- map[i.library_id] = i.library_id; >- return map; >- }, {}); >- }); >- >- cy.get(`#${table_id}_wrapper tbody tr`).should( >- "have.length", >- RESTdefaultPageSize >- ); >- >- cy.get(`#${table_id}_wrapper .dt-info`).contains( >- `Showing 1 to ${RESTdefaultPageSize} of ${baseTotalCount} entries` >- ); >- }); >- }); >- >- it("Show filters", function () { >- // Do not use `() => {` or this.biblio_id won't be retrieved >- const biblio_id = this.biblio_id; >- cy.task("buildSampleObjects", { >- object: "item", >- count: RESTdefaultPageSize, >- values: { >- biblio_id, >- checkout: null, >- transfer: null, >- lost_status: 0, >- withdrawn: 0, >- damaged_status: 0, >- not_for_loan_status: 0, >- course_item: null, >- cover_image_ids: [], >- }, >- }).then(items => { >- cy.intercept("get", `/api/v1/biblios/${biblio_id}/items*`, { >- statuscode: 200, >- body: items, >- headers: { >- "X-Base-Total-Count": baseTotalCount, >- "X-Total-Count": baseTotalCount, >- }, >- }); >- >- cy.set_syspref("AlwaysShowHoldingsTableFilters", 0).then(() => { >- cy.visit( >- "/cgi-bin/koha/catalogue/detail.pl?biblionumber=" + >- biblio_id >- ); >- >- // Hide the 'URL' column >- mock_table_settings( >- { >- columns: { uri: { is_hidden: 1 } }, >- }, >- "items_table_settings.holdings" >- ); >- >- cy.window().then(win => { >- win.libraries_map = items.reduce((map, i) => { >- map[i.library_id] = i.library_id; >- return map; >- }, {}); >- }); >- >- cy.get("@columns").then(columns => { >- cy.get(`#${table_id}_wrapper tbody tr`).should( >- "have.length", >- RESTdefaultPageSize >- ); >- >- // Filters are not displayed >- cy.get(`#${table_id} thead tr`).should( >- "have.length", >- 1 >- ); >- >- cy.get(`#${table_id} th`).contains("Status"); >- cy.get(`#${table_id} th`) >- .contains("URL") >- .should("not.exist"); >- cy.get(`#${table_id} th`) >- .contains("Course reserves") >- .should("not.exist"); >- >- cy.get(".show_filters").click(); >- cy.get(`#${table_id}_wrapper .dt-info`).contains( >- `Showing 1 to ${RESTdefaultPageSize} of ${baseTotalCount} entries` >- ); >- // Filters are displayed >- cy.get(`#${table_id} thead tr`).should( >- "have.length", >- 2 >- ); >- >- cy.get(`#${table_id} th`).contains("Status"); >- cy.get(`#${table_id} th`) >- .contains("URL") >- .should("not.exist"); >- cy.get(`#${table_id} th`) >- .contains("Course reserves") >- .should("not.exist"); >- }); >- }); >- >- cy.set_syspref("AlwaysShowHoldingsTableFilters", 1).then(() => { >- cy.visit( >- "/cgi-bin/koha/catalogue/detail.pl?biblionumber=" + >- biblio_id >- ); >- >- // Hide the 'URL' column >- mock_table_settings( >- { >- columns: { uri: { is_hidden: 1 } }, >- }, >- "items_table_settings.holdings" >- ); >- >- cy.window().then(win => { >- win.libraries_map = items.reduce((map, i) => { >- map[i.library_id] = i.library_id; >- return map; >- }, {}); >- }); >- >- cy.get("@columns").then(columns => { >- cy.get(`#${table_id}_wrapper tbody tr`).should( >- "have.length", >- RESTdefaultPageSize >- ); >- >- // Filters are displayed >- cy.get(`#${table_id} thead tr`).should( >- "have.length", >- 2 >- ); >- >- cy.get(".hide_filters").click(); >- >- // Filters are not displayed >- cy.get(`#${table_id} thead tr`).should( >- "have.length", >- 1 >- ); >- }); >- }); >- }); >- }); >- }); >-}); >diff --git a/t/cypress/support/e2e.js b/t/cypress/support/e2e.js >index 269f5eabd5..a525438675 100644 >--- a/t/cypress/support/e2e.js >+++ b/t/cypress/support/e2e.js >@@ -1822,3 +1822,39 @@ Cypress.Commands.add("set_syspref", (variable, value) => { > return client.sysprefs.update(variable, value); > }); > }); >+ >+Cypress.Commands.add("mock_table_settings", (settings, table_settings_var) => { >+ cy.window().then(win => { >+ let table_settings = >+ typeof table_settings_var === "undefined" >+ ? win.table_settings >+ : table_settings_var >+ .split(".") >+ .reduce((acc, key) => acc[key], win); >+ >+ table_settings.columns = table_settings.columns.map(c => ({ >+ ...c, >+ is_hidden: 0, >+ cannot_be_toggled: 0, >+ })); >+ if (settings && settings.hasOwnProperty("default_save_state")) { >+ table_settings.default_save_state = settings.default_save_state; >+ } >+ if (settings && settings.hasOwnProperty("default_save_state_search")) { >+ table_settings.default_save_state_search = >+ settings.default_save_state_search; >+ } >+ >+ if (settings && settings.columns) { >+ Object.entries(settings.columns).forEach(([name, values]) => { >+ let column = table_settings.columns.find( >+ cc => cc.columnname == name >+ ); >+ Object.entries(values).forEach(([prop, value]) => { >+ column[prop] = value; >+ }); >+ }); >+ } >+ cy.wrap(table_settings.columns).as("columns"); >+ }); >+}); >-- >2.39.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 39315
:
179201
|
179202
|
179203
|
179204
|
179365
|
179366
|
179367
|
179368
|
180285
|
180317
|
180318
|
180319
|
180320
|
180371
|
180372
|
180373
|
180374
|
180386
|
180387
|
180388
|
180389