Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group parallel reservations #632

Merged
merged 67 commits into from
Nov 24, 2023
Merged

Conversation

kasperg
Copy link
Contributor

@kasperg kasperg commented Oct 23, 2023

Link to issue

https://reload.atlassian.net/browse/DDFLSBP-79

Description

This change ensures that parallel reservations in FBS are displayed as a single reservation in the UI:

  • The reservationId attribute for ListType has been replaced by a reservationIds attribute
  • A new hook for retrieving reservation groups has been implemented. This supersedes the default useGetReservationsV2(). Instead of returning individual reservations it returns reservation groups which contain an array of reservation ids. Single reservations will have a single entry, parallel reservations will have multiple. The return value is mapped to the current ListType and ReservationType types.
  • In general passing around strings as different forms of identifiers have been replaced by passing around business objects. As a mininum ListType but preferably ReservationType or LoanType where applicable.
  • Components which previously took nullable faust (FBS) and identifier (Publizon) props now take a single ListType item prop
  • Higher-order components fetchDigitalMaterial() and fetchMaterial() now work with item props
  • States which previously used strings for ids, now use business objects

This change has lead to a number of related changes along the way:

  • To have a stable approach for generating string ids for business objects I have created itemId(), loanId() and reservationId() functions. They can be used for key props and potentially id attributes.
  • Test cases and fixtures have been updated with parallel reservations
  • I have removed it.only() from a few test cases to be able to run all tests locally. I have skip'ed or fixed other cases in the same test which is now running.
  • Helpers related to modals have been moved from helpers/general to helpers/modal-helpers
  • Construction of modal id strings are delegated to functions related to the individual modal component which take relevant domain objects as arguments e.g. deleteReservationModalId(ReservationType)
  • A few components have been updated to use the new domain hooks for loans and reservations
  • Equality checks for business objects instead of primitives means that we have to use isEqual() from Lodash and useDeepCompareEffect() from react-use
  • In an attempt to make Cypress tests less flaky I have added aliases and wait() in some tests. This is especially relevant for test cases which rely on other e.g. get the first list of reverations which can either be ready, physical or digital depending on what loads first.
  • I merged in Get rid of node in docker and adjust task cmds #577 to ease my development proces. We should consider if the comments there should be considered before merging this or these changes should be pulled from this PR.

Additional comments or questions

  • I have tried to add comments throughout the PR to explain what is going on
  • I tried to enable Cypress Cloud during this PR (0510d98). I disabled it again to avoid getting to much in. You can see it in action in this PR.
  • Codecov fails even though it should not. Sigh.

@kasperg kasperg force-pushed the group-parallel-reservations branch 2 times, most recently from 3bb7230 to a44a0c5 Compare October 23, 2023 09:10
@cypress
Copy link

cypress bot commented Oct 23, 2023

5 failed tests on run #10 ↗︎

5 138 6 0 Flakiness 0

Details:

Skip a failing loan list test
Project: React components Commit: 838a9c57b2
Status: Failed Duration: 08:47 💡
Started: Nov 6, 2023 1:58 PM Ended: Nov 6, 2023 2:07 PM
Failed  reservation-list/modal/reservation-details/reservation-details.test.ts • 2 failed tests • Integration tests

View Output Video

Test Artifacts
Reservation details modal test > It shows physical reservation details modal Output Screenshots Video
Reservation details modal test > It shows physical reservation details modal (ready for pickup) Output Screenshots Video
Failed  reservation-list/modal/delete-reservation/delete-reservation.test.ts • 1 failed test • Integration tests

View Output Video

Test Artifacts
Delete reservation modal test > It shows delete physical material modal Output Screenshots Video
Failed  dashboard/dashboard.test.tsx • 1 failed test • Integration tests

View Output Video

Test Artifacts
Dashboard > Dashboard general Output Screenshots Video
Failed  loan-list/list/loan-list.test.ts • 1 failed test • Integration tests

View Output Video

Test Artifacts
Loan list > Loan list basics (digital loans) Output Screenshots Video

Review all test suite changes for PR #632 ↗︎

@cypress
Copy link

cypress bot commented Oct 23, 2023

5 failed tests on run #9 ↗︎

5 138 6 0 Flakiness 0

Details:

Merge 838a9c5 into bc09aa9...
Project: React components Commit: c336a6047c ℹ️
Status: Failed Duration: 07:04 💡
Started: Nov 6, 2023 1:58 PM Ended: Nov 6, 2023 2:05 PM
Failed  reservation-list/modal/reservation-details/reservation-details.test.ts • 2 failed tests • Integration tests

View Output Video

Test Artifacts
Reservation details modal test > It shows physical reservation details modal Output Screenshots Video
Reservation details modal test > It shows physical reservation details modal (ready for pickup) Output Screenshots Video
Failed  reservation-list/modal/delete-reservation/delete-reservation.test.ts • 1 failed test • Integration tests

View Output Video

Test Artifacts
Delete reservation modal test > It shows delete physical material modal Output Screenshots Video
Failed  dashboard/dashboard.test.tsx • 1 failed test • Integration tests

View Output Video

Test Artifacts
Dashboard > Dashboard general Output Screenshots Video
Failed  loan-list/list/loan-list.test.ts • 1 failed test • Integration tests

View Output Video

Test Artifacts
Loan list > Loan list basics (digital loans) Output Screenshots Video

Review all test suite changes for PR #632 ↗︎

@kasperg kasperg force-pushed the group-parallel-reservations branch from 96654d7 to 92b4ab0 Compare October 23, 2023 11:50
@kasperg kasperg force-pushed the group-parallel-reservations branch from 92b4ab0 to 838a9c5 Compare November 6, 2023 13:55
@kasperg kasperg force-pushed the group-parallel-reservations branch 5 times, most recently from e7ac1cc to 7dda49e Compare November 15, 2023 08:41
Taskfile.yml Outdated Show resolved Hide resolved
Comment on lines -62 to -69
isSuccess: isSuccessPublizon,
data: publizonData,
isLoading: isLoadingPublizon
} = useGetV1UserReservations();

// State
const [readyForPickupReservationsFBS, setReadyForPickupReservationsFBS] =
useState<ReservationType[] | ReservationDetailsV2[] | null>(null);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this deletion is a result of using useReservations() and business objects leading to much fewer states and effects.

Comment on lines +486 to +497
cy.wait("@put-library-branch-and-expiry-date").should(({ request }) => {
expect(JSON.stringify(request.body)).to.equal(
JSON.stringify({
reservations: [
{
expiryDate: "2022-09-21",
// TODO: This should be DK-775120 as this is what the user
// selected in previous steps but that does not seem to work
// right now.
pickupBranch: "DK-775160",
reservationId: 4698559133
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see it i have identified a bug here. The reservation sent to FBS does not actually use the updated value. That should be handled in a separate issue though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. Did you already create a task for it?

Comment on lines +29 to +57
function groupReservations(data: ReservationDetailsV2[]) {
const reservationGroups = groupBy(
data,
(reservation) => reservation.transactionId
);

const processedReserations = map(
reservationGroups,
(reservationGroup: ReservationDetailsV2[]): ReservationGroupDetails => {
return {
// Use the first reservation in the group as the base.
...reservationGroup[0],
// The queue number for the group is the lowest individual queue number
numberInQueue: min(map(reservationGroup, "numberInQueue")),
records: reduce(
reservationGroup,
(result, reservation) => {
return {
...result,
[reservation.recordId]: reservation.reservationId
};
},
{}
)
};
}
);
return processedReserations;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also another key point of the PR: Reservations are grouped by transaction id to identify and create parallel reservations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Did you create a type for the id?

@kasperg kasperg marked this pull request as ready for review November 15, 2023 09:59
There is no need for the extra states and we get the expected return 
type by default.
This is necessary for handling parallel reservations
This ensures that it matches the reservation id used in the the
reservation list with physical detail modal story.

If not then no modal will be opened by default. This kind of defeats
the purpose of the story.
Now that we are moving to using business objects as dependencies they
fail the standard equality check of useEffect.

We have decided to use useDeepEffect() to address this so lets do so.
There is no reason to include test in the test name. It is implicit.
Even though this test does not test digital reservations having a stub
which returns an empty list means that requests should resolve and
hopefully make our tests less flaky.
Add aliases to intercepted requests and wait for these to finish before
proceeding. This should make our tests less flaky.
This should allow us to to verify that requests with the expected
payloads are sent.
It does work in that multiple reservation updates are sent but not with
the expected payload. That will have to be fixed separately.
With the added support for parallel reservations the singular value
should not be used anymore. Remove all references to it:

- Where it is used for modal ids: Replace it with modal specific helpers
- Where it is no longer needed: Remove it
This helps with testing.

The current mock will always succeed.
For whatever reason the test hangs when trying to open the modal for
a digital loan. This occurs locally and in CI when running in Cypress.

Opening up the same modal seems to work fine normally. 

Disable the test so we can move on.
Apparently this is rendered now so lets update the test accordingly.
Use isEqual() for deep object equality. The instances might not be the
same even if the values are equal.
MaterialIds is not a telling name when it is actually materials (or
reservations) we are passing around.
This makes it easier to map to other places where we also list facets
We need to use this for parallel reservations. As these reservations
consist of multiple materials we do not have a single manifestation to
show data from.

Instead we take one of the reservations and look up the best 
representation of the owner work corresponding to the faust id for the
reservation.

To make things consistent we introduce a fragment which has the same
signature for direct manifestation lookups used for normal reservations
and best representation lookups used for parallel reservations.
Support for DK5 and year facets have been added. We do not use them at
the moment but we add support for texts for them for good measure.
Use our new query to retrieve data from the best representation of the
owner work of one of the faust ids in our parallel reservation.

In general our parallel reservation data structure only contain a single
faust id (from the first reservation in the group). This may seem liked
a problem but based on the assumption that any faust id in the group 
should return the same owner work which should return the same best 
representation this should actually be OK.

Since parallel reservations may appear in different locations throughout
the app handling is added to the fetchMaterial() higher order component.

We can the utilize the fact that both hooks for retrieving material data
use the same fragment.

Expand the reservation list Cypress test to show that data fetching for
parallel reservations works.
Our current graphQL mocking does not seem to support varying responses 
by operation. This means we cannot provide different responses when 
looking upmaterial data for singular and parallel reservations.

Update with singular use cases to use best representation work fixture
where possibe.

When tests mix parallel and normal reservations we revert to only using
normal reservations.
@kasperg kasperg force-pushed the group-parallel-reservations branch from acf5d70 to 3841a75 Compare November 24, 2023 13:42
@kasperg kasperg merged commit f972bac into demo_2023-48-0 Nov 24, 2023
16 of 17 checks passed
@kasperg kasperg deleted the group-parallel-reservations branch November 24, 2023 15:36
@JacobArrow JacobArrow mentioned this pull request Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants