diff --git a/.github/workflows/reference-implementation.yml b/.github/workflows/reference-implementation.yml index b59bc537c9..230fde8402 100644 --- a/.github/workflows/reference-implementation.yml +++ b/.github/workflows/reference-implementation.yml @@ -8,7 +8,7 @@ on: jobs: tests: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: @@ -98,7 +98,7 @@ jobs: # Master branch only if: ${{ github.ref == 'refs/heads/master' }} - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: # Checkout the repo to seed the contents of ./tests/publish/ diff --git a/config/default.json b/config/default.json index 514120bf6a..b487b8baee 100644 --- a/config/default.json +++ b/config/default.json @@ -61,6 +61,7 @@ "dataset-site": true, "availability-check": true, "common-error-conditions": true, + "past-opportunities": true, "amending-order-quote": true, "order-deletion": true, "agent-broker": true, diff --git a/packages/openactive-broker-microservice/package-lock.json b/packages/openactive-broker-microservice/package-lock.json index 8b35913088..f53168f7d7 100644 --- a/packages/openactive-broker-microservice/package-lock.json +++ b/packages/openactive-broker-microservice/package-lock.json @@ -12,7 +12,7 @@ "@openactive/data-model-validator": "^2.0.83", "@openactive/data-models": "^2.0.318", "@openactive/dataset-utils": "^1.0.1", - "@openactive/harvesting-utils": "github:openactive/harvesting-utils#1b2877834055549572fa059a491ac17d306942fd", + "@openactive/harvesting-utils": "^0.1.2", "@openactive/openactive-openid-browser-automation": "file:../openactive-openid-browser-automation", "@openactive/openactive-openid-client": "file:../openactive-openid-client", "@openactive/rpde-validator": "^2.0.20", @@ -14724,10 +14724,9 @@ } }, "node_modules/@openactive/harvesting-utils": { - "version": "0.1.0", - "resolved": "git+ssh://git@github.com/openactive/harvesting-utils.git#1b2877834055549572fa059a491ac17d306942fd", - "integrity": "sha512-jjT4kad88PKp/JXDBOjkD47KCradEu6KmvNIfWKsHh2q6mfQHP5NIrWZreeeWkVlOO1t++lZESGpbmPfnopXmg==", - "license": "MIT", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@openactive/harvesting-utils/-/harvesting-utils-0.1.2.tgz", + "integrity": "sha512-IiuR+xeKihV0HFci857pea36btPIFo+QZj/EEouhwpUWmgt+dhRvpM4/OAhAa9aguChOHwXQ43HzInjfD2HoGw==", "dependencies": { "@openactive/rpde-validator": "^2.0.19", "axios": "^1.6.7", diff --git a/packages/openactive-integration-tests/test/features/README.md b/packages/openactive-integration-tests/test/features/README.md index e77d79c14e..2d60821e66 100644 --- a/packages/openactive-integration-tests/test/features/README.md +++ b/packages/openactive-integration-tests/test/features/README.md @@ -14,7 +14,7 @@ The tests for these features cover all known edge cases, including both happy an | core | AgentBroker mode ([agent-broker](./core/agent-broker/README.md)) | Required
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#agentbroker) | Support for AgentBroker mode | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x8 | | | core | Amending the OrderQuote before B ([amending-order-quote](./core/amending-order-quote/README.md)) | Required
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#amending-the-orderquote-before-b) | Allows the basket to be updated for a particular order | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x32 | | | core | Availability Checking ([availability-check](./core/availability-check/README.md)) | Required
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#step-by-step-process-description-0) | Runs only C1 and C2, to confirm availability checks work as expected | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x5, [TestOpportunityBookableNoSpaces](https://openactive.io/test-interface#TestOpportunityBookableNoSpaces) x3 | | -| core | Common error conditions ([common-error-conditions](./core/common-error-conditions/README.md)) | Required
[View Spec](https://openactive.io/open-booking-api/EditorsDraft/#error-model) | Tests C1, C2 and B for common error conditions applicable to all implementations | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x29, [TestOpportunityBookableInPast](https://openactive.io/test-interface#TestOpportunityBookableInPast) x3 | | +| core | Common error conditions ([common-error-conditions](./core/common-error-conditions/README.md)) | Required
[View Spec](https://openactive.io/open-booking-api/EditorsDraft/#error-model) | Tests C1, C2 and B for common error conditions applicable to all implementations | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x28 | | | core | Dataset Site ([dataset-site](./core/dataset-site/README.md)) | Required
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#endpoints) | Discoverable open data | | | | core | Order Deletion Endpoint ([order-deletion](./core/order-deletion/README.md)) | Required
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#order-deletion) | Check that Order Deletion correctly soft-deletes an Order that has already been emitted in the Orders feed | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x12 | [SellerRequestedCancellationSimulateAction](https://openactive.io/test-interface#SellerRequestedCancellationSimulateAction) | | access | accessChannel - Seller provided remote access ([access-channel](./access/access-channel/README.md)) | Optional
[View Spec](https://github.com/openactive/open-booking-api/issues/176) | For online opportunities, an accessChannel (or a customerNotice indicating that an accessChannel will be sent soon) is provided upon booking with B | [TestOpportunityOnlineBookable](https://openactive.io/test-interface#TestOpportunityOnlineBookable) x3, [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x1 | | @@ -37,6 +37,7 @@ The tests for these features cover all known edge cases, including both happy an | cancellation | cancellationMessage for Seller Requested Cancellation ([seller-requested-cancellation-message](./cancellation/seller-requested-cancellation-message/README.md)) | Optional
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#seller-requested-cancellation) | A message associated with a Cancellation triggered by the Seller through the Booking System | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x4 | [SellerRequestedCancellationWithMessageSimulateAction](https://openactive.io/test-interface#SellerRequestedCancellationWithMessageSimulateAction) | | cancellation | Seller Requested Replacement ([seller-requested-replacement](./cancellation/seller-requested-replacement/README.md)) | Optional
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#cancellation-replacement-refund-calculation-and-notification) | Replacement triggered by the Seller through the Booking System | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x4 | [ReplacementSimulateAction](https://openactive.io/test-interface#ReplacementSimulateAction) | | core | Multiple Sellers ([multiple-sellers](./core/multiple-sellers/README.md)) | Optional
[View Spec](https://openactive.io/open-booking-api/EditorsDraft/#booking-pre-conditions) | The booking system is multi-tenanted and provides services to multiple sellers. | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x6 | | +| core | Past opportunities ([past-opportunities](./core/past-opportunities/README.md)) | Optional
[View Spec](https://openactive.io/open-booking-api/EditorsDraft/#error-model) | For booking systems that support opportunities in the past, ensure that these are not bookable | [TestOpportunityBookableInPast](https://openactive.io/test-interface#TestOpportunityBookableInPast) x3, [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x1 | | | core | Single Seller ([single-seller](./core/single-seller/README.md)) | Optional
[View Spec](https://openactive.io/open-booking-api/EditorsDraft/#booking-pre-conditions) | The booking system only supports providing services to one seller. | | | | core | Test interface ([test-interface](./core/test-interface/README.md)) | Optional
[View Spec](https://openactive.io/test-interface/) | Open Booking API Test Interface implementation | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x1 | | | details-capture | Additional Details capture ([additional-details-capture](./details-capture/additional-details-capture/README.md)) | Optional
[View Spec](https://www.openactive.io/open-booking-api/EditorsDraft/#additional-details-capture) | Support for capturing additional details with required set to true | [TestOpportunityBookableAdditionalDetails](https://openactive.io/test-interface#TestOpportunityBookableAdditionalDetails) x9, [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x3 | | diff --git a/packages/openactive-integration-tests/test/features/categories.json b/packages/openactive-integration-tests/test/features/categories.json index b91bf324b5..8f884c6b90 100644 --- a/packages/openactive-integration-tests/test/features/categories.json +++ b/packages/openactive-integration-tests/test/features/categories.json @@ -10,6 +10,7 @@ "order-deletion": true, "multiple-sellers": true, "opportunity-feed": true, + "past-opportunities": true, "single-seller": true, "test-interface": true }, diff --git a/packages/openactive-integration-tests/test/features/core/common-error-conditions/README.md b/packages/openactive-integration-tests/test/features/core/common-error-conditions/README.md index dbaa7fc926..0cbd7907b9 100644 --- a/packages/openactive-integration-tests/test/features/core/common-error-conditions/README.md +++ b/packages/openactive-integration-tests/test/features/core/common-error-conditions/README.md @@ -10,7 +10,7 @@ Coverage Status: **complete** ### Test prerequisites - Opportunities Opportunities that match the following criteria must exist in the booking system (for each configured `bookableOpportunityTypesInScope`) for the configured primary Seller in order to use `useRandomOpportunities: true`. Alternatively the following `testOpportunityCriteria` values must be supported by the [test interface](https://openactive.io/test-interface/) of the booking system for `useRandomOpportunities: false`. -[TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x29, [TestOpportunityBookableInPast](https://openactive.io/test-interface#TestOpportunityBookableInPast) x3 +[TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x28 @@ -40,7 +40,6 @@ This feature is **required** by the Open Booking API specification, and so must | [incomplete-customer-details](./implemented/incomplete-customer-details-test.js) | Expect an IncompleteCustomerDetailsError when customer details are missing the required email property | Run each of C2 and B for a valid opportunity, with customer details missing the required email property, expecting an IncompleteCustomerDetailsError to be returned (C1 is ignored because customer details are not accepted for C1) | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x8 | | | [incomplete-order-item-no-offer](./implemented/incomplete-order-item-no-offer-test.js) | Test for IncompleteOrderItemError with missing `acceptedOffer` | Test for IncompleteOrderItemError (at C1, C2 and B). If there is a missing `acceptedOffer` property on the OrderItem. | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x4 | | | [incomplete-order-item-no-opportunity](./implemented/incomplete-order-item-no-opportunity-test.js) | Test for IncompleteOrderItemError with missing `orderedItem` | Test for IncompleteOrderItemError (at C1, C2 and B). If there is a missing `orderedItem` property on the OrderItem. | [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x4 | | -| [opportunity-in-past](./implemented/opportunity-in-past-test.js) | Expect an OpportunityOfferPairNotBookableError when opportunity is in the past | Runs C1, C2 and B for an opportunity in the past, expecting an OpportunityOfferPairNotBookableError to be returned at C1, C2, and B | [TestOpportunityBookableInPast](https://openactive.io/test-interface#TestOpportunityBookableInPast) x3, [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x1 | | | [unknown-endpoint](./implemented/unknown-endpoint-test.js) | Expect an UnknownOrIncorrectEndpointError for requests to unknown endpoints | Send a request to an endpoint that does not exist, and expect an UnknownOrIncorrectEndpointError to be returned | | | diff --git a/packages/openactive-integration-tests/test/features/core/past-opportunities/README.md b/packages/openactive-integration-tests/test/features/core/past-opportunities/README.md new file mode 100644 index 0000000000..bdf6af5caa --- /dev/null +++ b/packages/openactive-integration-tests/test/features/core/past-opportunities/README.md @@ -0,0 +1,58 @@ +[< Return to Overview](../../README.md) +# Past opportunities (past-opportunities) + +For booking systems that support opportunities in the past, ensure that these are not bookable + + +https://openactive.io/open-booking-api/EditorsDraft/#error-model + +Coverage Status: **complete** +### Test prerequisites - Opportunities +Opportunities that match the following criteria must exist in the booking system (for each configured `bookableOpportunityTypesInScope`) for the configured primary Seller in order to use `useRandomOpportunities: true`. Alternatively the following `testOpportunityCriteria` values must be supported by the [test interface](https://openactive.io/test-interface/) of the booking system for `useRandomOpportunities: false`. + +[TestOpportunityBookableInPast](https://openactive.io/test-interface#TestOpportunityBookableInPast) x3, [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x1 + + + +### Running tests for only this feature + +```bash +npm start -- --runInBand test/features/core/past-opportunities/ +``` + + + +## 'Implemented' tests + +Update `default.json` within `packages/openactive-integration-tests/config/` as follows to enable 'Implemented' testing for this feature: + +```json +"implementedFeatures": { + ... + "past-opportunities": true, + ... +} +``` + +| Identifier | Name | Description | Prerequisites per Opportunity Type | Required Test Interface Actions | +|------------|------|-------------|---------------|-------------------| +| [opportunity-in-past](./implemented/opportunity-in-past-test.js) | Expect an OpportunityOfferPairNotBookableError when opportunity is in the past | Runs C1, C2 and B for an opportunity in the past, expecting an OpportunityOfferPairNotBookableError to be returned at C1, C2, and B | [TestOpportunityBookableInPast](https://openactive.io/test-interface#TestOpportunityBookableInPast) x3, [TestOpportunityBookable](https://openactive.io/test-interface#TestOpportunityBookable) x1 | | + + + +## 'Not Implemented' tests + + +Update `default.json` within `packages/openactive-integration-tests/config/` as follows to enable 'Not Implemented' testing for this feature: + +```json +"implementedFeatures": { + ... + "past-opportunities": false, + ... +} +``` + +| Identifier | Name | Description | Prerequisites per Opportunity Type | Required Test Interface Actions | +|------------|------|-------------|---------------|-------------------| +| [no-past-opportunities](./not-implemented/no-past-opportunities-test.js) | The open data feeds must not contain any opportunities with `startDate` in the past | Assert that no opportunities that match criteria 'TestOpportunityBookableInPast' are available in the opportunity feeds. | | | diff --git a/packages/openactive-integration-tests/test/features/core/past-opportunities/feature.json b/packages/openactive-integration-tests/test/features/core/past-opportunities/feature.json new file mode 100644 index 0000000000..080831f507 --- /dev/null +++ b/packages/openactive-integration-tests/test/features/core/past-opportunities/feature.json @@ -0,0 +1,10 @@ +{ + "category": "core", + "identifier": "past-opportunities", + "name": "Past opportunities", + "description": "For booking systems that support opportunities in the past, ensure that these are not bookable", + "explainer": "", + "specificationReference": "https://openactive.io/open-booking-api/EditorsDraft/#error-model", + "required": false, + "coverageStatus": "complete" +} \ No newline at end of file diff --git a/packages/openactive-integration-tests/test/features/core/common-error-conditions/implemented/opportunity-in-past-test.js b/packages/openactive-integration-tests/test/features/core/past-opportunities/implemented/opportunity-in-past-test.js similarity index 98% rename from packages/openactive-integration-tests/test/features/core/common-error-conditions/implemented/opportunity-in-past-test.js rename to packages/openactive-integration-tests/test/features/core/past-opportunities/implemented/opportunity-in-past-test.js index c0648ae205..638985eb77 100644 --- a/packages/openactive-integration-tests/test/features/core/common-error-conditions/implemented/opportunity-in-past-test.js +++ b/packages/openactive-integration-tests/test/features/core/past-opportunities/implemented/opportunity-in-past-test.js @@ -9,7 +9,7 @@ const { itShouldIncludeErrorForOnlyPrimaryOrderItems } = require('../../../../sh FeatureHelper.describeFeature(module, { testCategory: 'core', - testFeature: 'common-error-conditions', + testFeature: 'past-opportunities', testFeatureImplemented: true, testIdentifier: 'opportunity-in-past', testName: 'Expect an OpportunityOfferPairNotBookableError when opportunity is in the past', diff --git a/packages/openactive-integration-tests/test/features/core/past-opportunities/not-implemented/no-past-opportunities-test.js b/packages/openactive-integration-tests/test/features/core/past-opportunities/not-implemented/no-past-opportunities-test.js new file mode 100644 index 0000000000..595cfaadfd --- /dev/null +++ b/packages/openactive-integration-tests/test/features/core/past-opportunities/not-implemented/no-past-opportunities-test.js @@ -0,0 +1,12 @@ +const { FeatureHelper } = require('../../../../helpers/feature-helper'); + +FeatureHelper.describeUnmatchedCriteriaFeature(module, { + testCategory: 'core', + testFeature: 'past-opportunities', + testFeatureImplemented: false, + testIdentifier: 'no-past-opportunities', + testName: 'The open data feeds must not contain any opportunities with `startDate` in the past', + unmatchedOpportunityCriteria: [ + 'TestOpportunityBookableInPast', + ], +}); diff --git a/packages/openactive-integration-tests/test/features/feature-requirements.json b/packages/openactive-integration-tests/test/features/feature-requirements.json index d5d53eaa83..5f0d27c317 100644 --- a/packages/openactive-integration-tests/test/features/feature-requirements.json +++ b/packages/openactive-integration-tests/test/features/feature-requirements.json @@ -29,8 +29,7 @@ "common-error-conditions": { "criteriaRequirements": { "primary": { - "TestOpportunityBookable": 29, - "TestOpportunityBookableInPast": 3 + "TestOpportunityBookable": 28 } }, "testInterfaceActionImplementationRequirements": [] @@ -245,6 +244,15 @@ "criteriaRequirements": {}, "testInterfaceActionImplementationRequirements": [] }, + "past-opportunities": { + "criteriaRequirements": { + "primary": { + "TestOpportunityBookableInPast": 3, + "TestOpportunityBookable": 1 + } + }, + "testInterfaceActionImplementationRequirements": [] + }, "single-seller": { "criteriaRequirements": {}, "testInterfaceActionImplementationRequirements": [] diff --git a/packages/openactive-integration-tests/test/features/tests-implemented.json b/packages/openactive-integration-tests/test/features/tests-implemented.json index e976c6929f..4c2cb3b4c0 100644 --- a/packages/openactive-integration-tests/test/features/tests-implemented.json +++ b/packages/openactive-integration-tests/test/features/tests-implemented.json @@ -14,7 +14,7 @@ "notImplementedTestFiles": 1 }, "common-error-conditions": { - "implementedTestFiles": 6, + "implementedTestFiles": 5, "notImplementedTestFiles": 1 }, "dataset-site": { @@ -121,6 +121,10 @@ "implementedTestFiles": 0, "notImplementedTestFiles": 0 }, + "past-opportunities": { + "implementedTestFiles": 1, + "notImplementedTestFiles": 1 + }, "single-seller": { "implementedTestFiles": 1, "notImplementedTestFiles": 1