diff --git a/.vscode/launch.json b/.vscode/launch.json index 0bb56eeebb7..78289cba0f9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -42,6 +42,22 @@ "args": ["add", "@spartacus/schematics@latest"], "console": "integratedTerminal", "outFiles": ["${workspaceFolder}/**/*.js"] + }, + + // to debug a schematics Jest test, make sure that a spec.ts file is currently opened. + { + "type": "node", + "request": "launch", + "name": "Debug project/schematics Jest test", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": [ + "${fileBasenameNoExtension}", + "--config", + "projects/schematics/jest.schematics.config.js" + ], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true } ] } diff --git a/docs/migration/4_0.md b/docs/migration/4_0.md index 88d4a277619..fe4cd53fabc 100644 --- a/docs/migration/4_0.md +++ b/docs/migration/4_0.md @@ -289,14 +289,40 @@ Lib: @spartacus/core Class: UserAddressService Change: Two new required constructor parameters `userAddressConnector: UserAddressConnector` and `command: CommandService` + +## New Checkout Library + +Spartacus 4.0 introduces the checkout library. The checkout related code is moved out of `@spartacus/core` and `@spartacus/storefrontlib` into one of the checkout lib's entry points. The checkout library is split into these entry points: + +``` +@spartacus/checkout/assets +( checkout related i18n keys are moved here ) + +@spartacus/checkout/components +( checkout related UI codee is moved here. This includes components, guards and ui services ) + +@spartacus/checkout/core +The checkout facade API implementation are moved here, as well as connectors, event builder, event listener, models, other services, and state management. + +@spartacus/checkout/occ +The checkout related OCC code is moved here. This includes the checkout related adapters and converters. + +@spartacus/checkout/root +The root entry point is, by convention, meant to always be eager loaded. It contains the config, events, facades, http interceptors and models. + +@spartacus/checkout/styles +The checkout related scss styles are moved here. + +``` + +Most of the code is moved unchanged, but some classes required changes after they were moved. See the section below for the list: + ## (start) Changes in the classes carried over to the @spartacus/checkout lib ### CheckoutEventModule -Class: CheckoutEventModule Change: One new required constructor parameters `_checkoutEventListener: CheckoutEventListener` ### PaymentFormComponent -Class: PaymentFormComponent Changes: - PaymentFormComponent does not implement `OnDestroy` anymore - method `ngOnDestroy()` removed. @@ -619,6 +645,10 @@ The display of the guest checkout button relies on the presence of the `forced` - `platformId` is now required constructor dependency. +### ProductListComponentService +- `ProductListComponentService` now also requires `ViewConfig`. +- The `defaultPageSize` property was removed. To modify default page size use `provideConfig({ view: { defaultPageSize: /tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/cart/jest.schematics.config.js b/feature-libs/cart/jest.schematics.config.js index e4cec47b293..f6ed6317ee7 100644 --- a/feature-libs/cart/jest.schematics.config.js +++ b/feature-libs/cart/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/cart/saved-cart/components/add-to-saved-cart/add-to-saved-cart.component.spec.ts b/feature-libs/cart/saved-cart/components/add-to-saved-cart/add-to-saved-cart.component.spec.ts index bc214b6d502..2715b6c8afd 100644 --- a/feature-libs/cart/saved-cart/components/add-to-saved-cart/add-to-saved-cart.component.spec.ts +++ b/feature-libs/cart/saved-cart/components/add-to-saved-cart/add-to-saved-cart.component.spec.ts @@ -35,7 +35,7 @@ class MockAuthService implements Partial { } class MockRoutingService implements Partial { - go(): void {} + go = () => Promise.resolve(true); } class MockLaunchDialogService implements Partial { diff --git a/feature-libs/cart/saved-cart/components/details/saved-cart-details-action/saved-cart-details-action.component.spec.ts b/feature-libs/cart/saved-cart/components/details/saved-cart-details-action/saved-cart-details-action.component.spec.ts index aa95c7c7913..3dd432d522e 100644 --- a/feature-libs/cart/saved-cart/components/details/saved-cart-details-action/saved-cart-details-action.component.spec.ts +++ b/feature-libs/cart/saved-cart/components/details/saved-cart-details-action/saved-cart-details-action.component.spec.ts @@ -37,7 +37,7 @@ class MockSavedCartFacade implements Partial { } class MockRoutingService implements Partial { - go(): void {} + go = () => Promise.resolve(true); } class MockGlobalMessageService implements Partial { diff --git a/feature-libs/cart/saved-cart/components/details/saved-cart-details-items/saved-cart-details-items.component.spec.ts b/feature-libs/cart/saved-cart/components/details/saved-cart-details-items/saved-cart-details-items.component.spec.ts index e754dd7792d..b38939dff0d 100644 --- a/feature-libs/cart/saved-cart/components/details/saved-cart-details-items/saved-cart-details-items.component.spec.ts +++ b/feature-libs/cart/saved-cart/components/details/saved-cart-details-items/saved-cart-details-items.component.spec.ts @@ -78,7 +78,7 @@ class MockSavedCartFacade implements Partial { } class MockRoutingService implements Partial { - go(): void {} + go = () => Promise.resolve(true); } class MockGlobalMessageService implements Partial { add( diff --git a/feature-libs/cart/saved-cart/components/list/saved-cart-list.component.spec.ts b/feature-libs/cart/saved-cart/components/list/saved-cart-list.component.spec.ts index 762c04b0693..b5247c87136 100644 --- a/feature-libs/cart/saved-cart/components/list/saved-cart-list.component.spec.ts +++ b/feature-libs/cart/saved-cart/components/list/saved-cart-list.component.spec.ts @@ -65,7 +65,7 @@ class MockTranslationService { } class MockRoutingService implements Partial { - go(): void {} + go = () => Promise.resolve(true); } describe('SavedCartListComponent', () => { diff --git a/feature-libs/cart/saved-cart/components/saved-cart-form-dialog/saved-cart-form-dialog.component.spec.ts b/feature-libs/cart/saved-cart/components/saved-cart-form-dialog/saved-cart-form-dialog.component.spec.ts index b73a724f559..a28fba31a3d 100644 --- a/feature-libs/cart/saved-cart/components/saved-cart-form-dialog/saved-cart-form-dialog.component.spec.ts +++ b/feature-libs/cart/saved-cart/components/saved-cart-form-dialog/saved-cart-form-dialog.component.spec.ts @@ -55,7 +55,7 @@ class MockLaunchDialogService implements Partial { } class MockRoutingService implements Partial { - go(): void {} + go = () => Promise.resolve(true); } class MockSavedCartFacade implements Partial { diff --git a/feature-libs/checkout/jest.schematics.config.js b/feature-libs/checkout/jest.schematics.config.js index 6ecf12eb4ee..62c26003698 100644 --- a/feature-libs/checkout/jest.schematics.config.js +++ b/feature-libs/checkout/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/organization/jest.schematics.config.js b/feature-libs/organization/jest.schematics.config.js index 1b9bfe60402..40870df9788 100644 --- a/feature-libs/organization/jest.schematics.config.js +++ b/feature-libs/organization/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/product-configurator/common/components/configure-product/configure-product.component.spec.ts b/feature-libs/product-configurator/common/components/configure-product/configure-product.component.spec.ts index 9fdef776590..c67ffad9da9 100644 --- a/feature-libs/product-configurator/common/components/configure-product/configure-product.component.spec.ts +++ b/feature-libs/product-configurator/common/components/configure-product/configure-product.component.spec.ts @@ -50,7 +50,7 @@ class MockUrlPipe implements PipeTransform { } class MockRoutingService implements Partial { - go() {} + go = () => Promise.resolve(true); } let component: ConfigureProductComponent; diff --git a/feature-libs/product-configurator/jest.schematics.config.js b/feature-libs/product-configurator/jest.schematics.config.js index 70eb66361ac..140bf303f5f 100644 --- a/feature-libs/product-configurator/jest.schematics.config.js +++ b/feature-libs/product-configurator/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, diff --git a/feature-libs/product/jest.schematics.config.js b/feature-libs/product/jest.schematics.config.js index a8a9d509367..5b7cfed10d6 100644 --- a/feature-libs/product/jest.schematics.config.js +++ b/feature-libs/product/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/qualtrics/jest.schematics.config.js b/feature-libs/qualtrics/jest.schematics.config.js index 8dfb81211e4..99e7408ebbb 100644 --- a/feature-libs/qualtrics/jest.schematics.config.js +++ b/feature-libs/qualtrics/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/smartedit/jest.schematics.config.js b/feature-libs/smartedit/jest.schematics.config.js index 40fa65ffde2..aab1d5f08d6 100644 --- a/feature-libs/smartedit/jest.schematics.config.js +++ b/feature-libs/smartedit/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/storefinder/core/facade/store-finder.service.spec.ts b/feature-libs/storefinder/core/facade/store-finder.service.spec.ts index aaf068f727b..39f3c82f755 100644 --- a/feature-libs/storefinder/core/facade/store-finder.service.spec.ts +++ b/feature-libs/storefinder/core/facade/store-finder.service.spec.ts @@ -1,38 +1,32 @@ import { inject, TestBed } from '@angular/core/testing'; import * as NgrxStore from '@ngrx/store'; import { MemoizedSelector, Store, StoreModule } from '@ngrx/store'; -import { StoreFinderActions } from '../store/actions/index'; -import * as fromStoreReducers from '../store/reducers/index'; -import { - FindStoresState, - StoresState, - StateWithStoreFinder, - STORE_FINDER_FEATURE, -} from '../store/store-finder-state'; -import { StoreFinderService } from './store-finder.service'; -import { NavigationExtras } from '@angular/router'; -import { StoreFinderConfig } from '../config/store-finder-config'; import { GeoPoint, GlobalMessageService, PointOfService, RoutingService, - UrlCommands, WindowRef, } from '@spartacus/core'; import { BehaviorSubject, EMPTY, of } from 'rxjs'; +import { StoreFinderConfig } from '../config/store-finder-config'; import { StoreFinderSelectors } from '../store'; +import { StoreFinderActions } from '../store/actions/index'; +import * as fromStoreReducers from '../store/reducers/index'; +import { + FindStoresState, + StateWithStoreFinder, + StoresState, + STORE_FINDER_FEATURE, +} from '../store/store-finder-state'; +import { StoreFinderService } from './store-finder.service'; const routerParam$: BehaviorSubject<{ [key: string]: string; }> = new BehaviorSubject({}); class MockRoutingService implements Partial { - go( - _commands: any[] | UrlCommands, - _query?: object, - _extras?: NavigationExtras - ): void {} + go = () => Promise.resolve(true); getParams = () => routerParam$.asObservable(); } diff --git a/feature-libs/storefinder/jest.schematics.config.js b/feature-libs/storefinder/jest.schematics.config.js index 439fecaff2e..17324d2cb7f 100644 --- a/feature-libs/storefinder/jest.schematics.config.js +++ b/feature-libs/storefinder/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/tracking/jest.schematics.config.js b/feature-libs/tracking/jest.schematics.config.js index fb3f9cf64c7..4b650302753 100644 --- a/feature-libs/tracking/jest.schematics.config.js +++ b/feature-libs/tracking/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/user/jest.schematics.config.js b/feature-libs/user/jest.schematics.config.js index 2488913eb07..cc40efcf29c 100644 --- a/feature-libs/user/jest.schematics.config.js +++ b/feature-libs/user/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/feature-libs/user/profile/components/close-account/components/close-account-modal/close-account-modal.component.spec.ts b/feature-libs/user/profile/components/close-account/components/close-account-modal/close-account-modal.component.spec.ts index 6e17958608b..a4449d0f700 100644 --- a/feature-libs/user/profile/components/close-account/components/close-account-modal/close-account-modal.component.spec.ts +++ b/feature-libs/user/profile/components/close-account/components/close-account-modal/close-account-modal.component.spec.ts @@ -7,9 +7,9 @@ import { RoutingService, } from '@spartacus/core'; import { ICON_TYPE, ModalService } from '@spartacus/storefront'; +import { UserProfileFacade } from '@spartacus/user/profile/root'; import { Observable, of, throwError } from 'rxjs'; import { CloseAccountModalComponent } from './close-account-modal.component'; -import { UserProfileFacade } from '@spartacus/user/profile/root'; import createSpy = jasmine.createSpy; class MockGlobalMessageService implements Partial { @@ -31,7 +31,7 @@ class MockAuthService implements Partial { } class MockRoutingService implements Partial { - go() {} + go = () => Promise.resolve(true); } @Component({ diff --git a/integration-libs/cdc/jest.schematics.config.js b/integration-libs/cdc/jest.schematics.config.js index 0083f087dc0..7b70cd160ff 100644 --- a/integration-libs/cdc/jest.schematics.config.js +++ b/integration-libs/cdc/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/integration-libs/cds/jest.schematics.config.js b/integration-libs/cds/jest.schematics.config.js index aadcafc79a6..117dcbaaa1f 100644 --- a/integration-libs/cds/jest.schematics.config.js +++ b/integration-libs/cds/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', }, }, collectCoverage: false, diff --git a/projects/schematics/jest.schematics.config.js b/projects/schematics/jest.schematics.config.js index 9d9a2eb53c4..30fa116bc32 100644 --- a/projects/schematics/jest.schematics.config.js +++ b/projects/schematics/jest.schematics.config.js @@ -8,7 +8,7 @@ module.exports = { }, globals: { 'ts-jest': { - tsconfig: './tsconfig.schematics.json', + tsconfig: '/tsconfig.schematics.json', } }, collectCoverage: false, diff --git a/projects/schematics/src/migrations/4_0/constructor-deprecations/constructor-deprecations.ts b/projects/schematics/src/migrations/4_0/constructor-deprecations/constructor-deprecations.ts index 9f36cb88b04..4a63a3779c2 100644 --- a/projects/schematics/src/migrations/4_0/constructor-deprecations/constructor-deprecations.ts +++ b/projects/schematics/src/migrations/4_0/constructor-deprecations/constructor-deprecations.ts @@ -115,6 +115,7 @@ import { UNIT_USER_LIST_COMPONENT_MIGRATION } from './data/unit-user-list.compon import { USER_ADDRESS_SERVICE_MIGRATION } from './data/user-address-service.migration'; import { USER_GROUP_USER_LIST_COMPONENT_MIGRATION } from './data/user-group-user-list.component.migration'; import { WINDOW_REF_MIGRATION } from './data/window-ref.migration'; +import { PRODUCT_LIST_COMPONENT_SERVICE_MIGRATION } from './data/product-list-component.service.migration'; export const CONSTRUCTOR_DEPRECATION_DATA: ConstructorDeprecation[] = [ UNIT_CHILDREN_COMPONENT_MIGRATION, @@ -195,6 +196,7 @@ export const CONSTRUCTOR_DEPRECATION_DATA: ConstructorDeprecation[] = [ AUTH_REDIRECT_SERVICE_MIGRATION, PROTECTED_ROUTES_SERVICE_MIGRATION, PRODUCT_LIST_ITEM_COMPONENT_MIGRATION, + PRODUCT_LIST_COMPONENT_SERVICE_MIGRATION, PRODUCT_GRID_ITEM_COMPONENT_MIGRATION, CART_ITEM_COMPONENT_MIGRATION, CONFIGURATOR_CART_ENTRY_INFO_COMPONENT_MIGRATION, diff --git a/projects/schematics/src/migrations/4_0/constructor-deprecations/data/product-list-component.service.migration.ts b/projects/schematics/src/migrations/4_0/constructor-deprecations/data/product-list-component.service.migration.ts new file mode 100644 index 00000000000..cb808671aba --- /dev/null +++ b/projects/schematics/src/migrations/4_0/constructor-deprecations/data/product-list-component.service.migration.ts @@ -0,0 +1,52 @@ +import { + ACTIVATED_ROUTE, + ANGULAR_ROUTER, + CURRENCY_SERVICE, + LANGUAGE_SERVICE, + PRODUCT_LIST_COMPONENT_SERVICE, + PRODUCT_SEARCH_SERVICE, + ROUTER, + ROUTING_SERVICE, + SPARTACUS_CORE, + SPARTACUS_STOREFRONTLIB, + VIEW_CONFIG, +} from '../../../../shared/constants'; +import { ConstructorDeprecation } from '../../../../shared/utils/file-utils'; + +export const PRODUCT_LIST_COMPONENT_SERVICE_MIGRATION: ConstructorDeprecation = { + // projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.ts + class: PRODUCT_LIST_COMPONENT_SERVICE, + importPath: SPARTACUS_STOREFRONTLIB, + deprecatedParams: [ + { + className: PRODUCT_SEARCH_SERVICE, + importPath: SPARTACUS_CORE, + }, + { + className: ROUTING_SERVICE, + importPath: SPARTACUS_CORE, + }, + { + className: ACTIVATED_ROUTE, + importPath: ANGULAR_ROUTER, + }, + { + className: CURRENCY_SERVICE, + importPath: SPARTACUS_CORE, + }, + { + className: LANGUAGE_SERVICE, + importPath: SPARTACUS_CORE, + }, + { + className: ROUTER, + importPath: ANGULAR_ROUTER, + }, + ], + addParams: [ + { + className: VIEW_CONFIG, + importPath: SPARTACUS_STOREFRONTLIB, + }, + ], +}; diff --git a/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/data/product-list-component.service.migration.ts b/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/data/product-list-component.service.migration.ts new file mode 100644 index 00000000000..0abccbdb40d --- /dev/null +++ b/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/data/product-list-component.service.migration.ts @@ -0,0 +1,17 @@ +import { + DEFAULT_PAGE_SIZE, + PRODUCT_LIST_COMPONENT_SERVICE, + SPARTACUS_STOREFRONTLIB, +} from '../../../../shared/constants'; +import { MethodPropertyDeprecation } from '../../../../shared/utils/file-utils'; + +// projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.ts + +export const PRODUCT_LIST_COMPONENT_SERVICE_MIGRATION: MethodPropertyDeprecation[] = [ + { + class: PRODUCT_LIST_COMPONENT_SERVICE, + importPath: SPARTACUS_STOREFRONTLIB, + deprecatedNode: DEFAULT_PAGE_SIZE, + comment: `Property '${DEFAULT_PAGE_SIZE}' was removed, to modify default page size use 'view.defaultPageSize' configuration property.`, + }, +]; diff --git a/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/methods-and-properties-deprecations.ts b/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/methods-and-properties-deprecations.ts index c4a19e3678e..6579617815c 100644 --- a/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/methods-and-properties-deprecations.ts +++ b/projects/schematics/src/migrations/4_0/methods-and-properties-deprecations/methods-and-properties-deprecations.ts @@ -21,6 +21,7 @@ import { } from './data/occ-endpoints.service.migration'; import { ORDER_DETAIL_ITEMS_COMPONENT_MIGRATION } from './data/order-detail-items.component.migration'; import { PAGE_EVENT_BUILDER_MIGRATION } from './data/page-event.builder.ts.migration'; +import { PRODUCT_LIST_COMPONENT_SERVICE_MIGRATION } from './data/product-list-component.service.migration'; import { ROUTING_SERVICE_MIGRATION } from './data/routing.service.ts.migration'; import { SELECTIVE_CART_SERVICE_MIGRATION } from './data/selective-cart.service.migration'; @@ -43,6 +44,7 @@ export const METHOD_PROPERTY_DATA: MethodPropertyDeprecation[] = [ ...ORDER_DETAIL_ITEMS_COMPONENT_MIGRATION, ...ROUTING_SERVICE_MIGRATION, ...CONFIGURATOR_GROUP_MENU_COMPONENT_MIGRATION, + ...PRODUCT_LIST_COMPONENT_SERVICE_MIGRATION, ]; export function migrate(): Rule { diff --git a/projects/schematics/src/migrations/4_0/rename-symbol/rename-symbol.ts b/projects/schematics/src/migrations/4_0/rename-symbol/rename-symbol.ts index ae7dedc738d..f9045ffdaeb 100644 --- a/projects/schematics/src/migrations/4_0/rename-symbol/rename-symbol.ts +++ b/projects/schematics/src/migrations/4_0/rename-symbol/rename-symbol.ts @@ -2,7 +2,14 @@ import { Rule, Tree } from '@angular-devkit/schematics'; import { RenamedSymbol } from '../../../shared/utils/file-utils'; import { migrateRenamedSymbols } from '../../mechanism/rename-symbol/rename-symbol'; -export const RENAMED_SYMBOLS_DATA: RenamedSymbol[] = []; +export const RENAMED_SYMBOLS_DATA: RenamedSymbol[] = [ + // projects/storefrontlib/src/cms-components/product/config/default-view-config.ts + { + previousNode: 'defaultScrollConfig', + previousImportPath: '@spartacus/storefront', + newNode: 'defaultViewConfig', + }, +]; export function migrate(): Rule { return (tree: Tree) => { diff --git a/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management.ts b/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management.ts index 27133fa7cb0..96c51f16bd3 100644 --- a/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management.ts +++ b/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management.ts @@ -13,8 +13,8 @@ import { installPackageJsonDependencies, } from '../../../shared/utils/lib-utils'; import { + CORE_SPARTACUS_SCOPES, createDependencies, - FEATURES_LIBS_SKIP_SCOPES, readPackageJson, } from '../../../shared/utils/package-utils'; @@ -24,16 +24,20 @@ export function migrateDependencies( removedDependencies: string[] ): Rule { const packageJson = readPackageJson(tree); - const installedSpartacusLibs = collectSpartacusLibraryDependencies( - packageJson - ); + const { + spartacusPeerDeps, + installedLibs, + } = collectSpartacusLibraryDependencies(packageJson); + const allSpartacusDeps = installedLibs.concat(spartacusPeerDeps); + const dependencies = createSpartacusLibraryDependencies( - installedSpartacusLibs + allSpartacusDeps, + installedLibs ); checkAndLogRemovedDependencies( packageJson, - installedSpartacusLibs, + allSpartacusDeps, removedDependencies, context.logger ); @@ -44,18 +48,62 @@ export function migrateDependencies( ]); } -function collectSpartacusLibraryDependencies(packageJson: any): string[] { +function collectSpartacusLibraryDependencies( + packageJson: any +): { installedLibs: string[]; spartacusPeerDeps: string[] } { const dependencies = (packageJson.dependencies as Record) ?? {}; - return Object.keys(dependencies).filter((d) => d.startsWith(SPARTACUS_SCOPE)); + const installedLibs = Object.keys(dependencies).filter((dep) => + dep.startsWith(SPARTACUS_SCOPE) + ); + const nonCoreLibs = installedLibs.filter( + (lib) => !CORE_SPARTACUS_SCOPES.includes(lib) + ); + + let spartacusPeerDeps: string[] = []; + for (const spartacusLib of nonCoreLibs) { + spartacusPeerDeps = collectSpartacusPeerDeps( + spartacusPeerDeps, + spartacusLib + ); + } + + // remove the duplicates + spartacusPeerDeps = Array.from(new Set(spartacusPeerDeps)); + return { + installedLibs, + spartacusPeerDeps, + }; +} + +function collectSpartacusPeerDeps( + collectedDeps: string[], + name: string +): string[] { + const peerDepsWithVersions = (collectedDependencies as Record< + string, + Record + >)[name]; + const peerDeps = Object.keys(peerDepsWithVersions) + .filter((d) => d.startsWith(SPARTACUS_SCOPE)) + .filter((d) => !CORE_SPARTACUS_SCOPES.includes(d)) + .filter((d) => !collectedDeps.includes(d)); + + collectedDeps = collectedDeps.concat(peerDeps); + for (const peerDep of peerDeps) { + collectedDeps = collectSpartacusPeerDeps(collectedDeps, peerDep); + } + + return collectedDeps; } function createSpartacusLibraryDependencies( - installedSpartacusLibs: string[] + allSpartacusLibraries: string[], + skipScopes: string[] ): NodeDependency[] { const dependenciesToAdd: NodeDependency[] = []; - for (const libraryName of installedSpartacusLibs) { + for (const libraryName of allSpartacusLibraries) { const spartacusLibrary = (collectedDependencies as Record< string, Record @@ -63,7 +111,7 @@ function createSpartacusLibraryDependencies( dependenciesToAdd.push( ...createDependencies(spartacusLibrary, { - skipScopes: FEATURES_LIBS_SKIP_SCOPES, + skipScopes, overwrite: true, }) ); diff --git a/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management_spec.ts b/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management_spec.ts index 78395458826..832c58ae2f0 100644 --- a/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management_spec.ts +++ b/projects/schematics/src/migrations/mechanism/dependency-management/dependency-management_spec.ts @@ -116,4 +116,36 @@ describe('dependency management migrations', () => { ); }); }); + + describe('cross dependencies', () => { + beforeEach(() => { + writeFile( + host, + '/package.json', + JSON.stringify({ + name: 'xxx', + version: '3.0.0', + dependencies: { + '@spartacus/core': '3.0.0', + '@spartacus/storefront': '3.0.0', + '@spartacus/cds': '3.0.0', + '@spartacus/qualtrics': '3.0.0', + }, + }) + ); + }); + it('should install cross spartacus peer deps', async () => { + await runMigration(appTree, schematicRunner, MIGRATION_SCRIPT_NAME); + + const packageJson = JSON.parse(appTree.readContent('/package.json')); + + expect(packageJson.dependencies['@spartacus/core']).toBeTruthy(); + expect(packageJson.dependencies['@spartacus/storefront']).toBeTruthy(); + expect(packageJson.dependencies['@spartacus/cds']).toBeTruthy(); + expect(packageJson.dependencies['@spartacus/tracking']).toBeTruthy(); + expect(packageJson.dependencies['@spartacus/cart']).toBeTruthy(); + expect(packageJson.dependencies['@spartacus/checkout']).toBeTruthy(); + expect(packageJson.dependencies['@spartacus/qualtrics']).toBeTruthy(); + }); + }); }); diff --git a/projects/schematics/src/migrations/mechanism/rename-symbol/__snapshots__/rename-symbol_spec.ts.snap b/projects/schematics/src/migrations/mechanism/rename-symbol/__snapshots__/rename-symbol_spec.ts.snap index 54c7dbcdd79..6abb0d9df4f 100644 --- a/projects/schematics/src/migrations/mechanism/rename-symbol/__snapshots__/rename-symbol_spec.ts.snap +++ b/projects/schematics/src/migrations/mechanism/rename-symbol/__snapshots__/rename-symbol_spec.ts.snap @@ -26,3 +26,11 @@ import { Test1Component } from \\"@spartacus/storefront\\"; const array = [OtherComponentTest3, Test1Component, Test2Component]; " `; + +exports[`renamed symbols Should only rename node 1`] = ` +"import { Test2Component } from \\"@spartacus/core\\"; +import { OtherComponentTest4, Test1Component } from \\"@spartacus/storefront\\"; + +const array = [OtherComponentTest4, Test1Component, Test2Component]; +" +`; diff --git a/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol.ts b/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol.ts index 8131377edb5..3ace3055756 100644 --- a/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol.ts +++ b/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol.ts @@ -36,6 +36,11 @@ export function migrateRenamedSymbols( : importName; const oldAlias = namedImport.getAliasNode()?.getText(); + let importPath = renamedSymbol.previousImportPath; + + if (renamedSymbol.newImportPath) { + importPath = renamedSymbol.newImportPath; + } if (!oldAlias && renamedSymbol.newNode) { namedImport.renameAlias(newNodeName); @@ -48,7 +53,7 @@ export function migrateRenamedSymbols( alias: oldAlias, }, ], - moduleSpecifier: renamedSymbol.newImportPath, + moduleSpecifier: importPath, } as ImportDeclarationStructure); if ((id.getImportClause()?.getNamedImports()?.length || 0) > 1) { diff --git a/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol_spec.ts b/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol_spec.ts index 60d8772c10e..e21116781bb 100644 --- a/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol_spec.ts +++ b/projects/schematics/src/migrations/mechanism/rename-symbol/rename-symbol_spec.ts @@ -32,6 +32,12 @@ import { Test2Component } from "@spartacus/core"; const array = [OtherComponent3, Test1Component, Test2Component];`; // ----------------------------------------------------------------------- +const fileWithRename = `import { OtherComponent4, Test1Component } from "@spartacus/storefront"; +import { Test2Component } from "@spartacus/core"; + +const array = [OtherComponent4, Test1Component, Test2Component];`; +// ----------------------------------------------------------------------- + describe('renamed symbols', () => { let host: TempScopedNodeJsSyncHost; let appTree = Tree.empty() as UnitTestTree; @@ -113,4 +119,13 @@ describe('renamed symbols', () => { expect(content).toMatchSnapshot(); }); }); + + it('Should only rename node', async () => { + writeFile(host, '/src/index.ts', fileWithRename); + + await runMigration(appTree, schematicRunner, MIGRATION_SCRIPT_NAME); + + const content = appTree.readContent('/src/index.ts'); + expect(content).toMatchSnapshot(); + }); }); diff --git a/projects/schematics/src/migrations/test/rename-symbol/rename-symbol.ts b/projects/schematics/src/migrations/test/rename-symbol/rename-symbol.ts index 325a791dff8..ff1c917e172 100644 --- a/projects/schematics/src/migrations/test/rename-symbol/rename-symbol.ts +++ b/projects/schematics/src/migrations/test/rename-symbol/rename-symbol.ts @@ -23,6 +23,12 @@ export const RENAMED_SYMBOLS_DATA: RenamedSymbol[] = [ newNode: 'OtherComponentTest3', newImportPath: '@spartacus/storefinder/components', }, + { + // 4) For name change + previousNode: 'OtherComponent4', + previousImportPath: '@spartacus/storefront', + newNode: 'OtherComponentTest4', + }, ]; export function migrate(): Rule { diff --git a/projects/schematics/src/shared/constants.ts b/projects/schematics/src/shared/constants.ts index 1e3efa7663d..d3358d45b87 100644 --- a/projects/schematics/src/shared/constants.ts +++ b/projects/schematics/src/shared/constants.ts @@ -812,6 +812,8 @@ export const ITEM = 'Item'; export const ORDER_ENTRY = 'OrderEntry'; export const ORDER_PROMOTIONS$ = 'orderPromotions$'; +export const DEFAULT_PAGE_SIZE = 'defaultPageSize'; + /***** Properties end *****/ /***** APIs start *****/ diff --git a/projects/schematics/src/shared/utils/file-utils.ts b/projects/schematics/src/shared/utils/file-utils.ts index 2b97e712be3..caf16b6b3c7 100644 --- a/projects/schematics/src/shared/utils/file-utils.ts +++ b/projects/schematics/src/shared/utils/file-utils.ts @@ -106,7 +106,7 @@ export interface RenamedSymbol { previousNode: string; previousImportPath: string; newNode?: string; - newImportPath: string; + newImportPath?: string; } export function getTsSourceFile(tree: Tree, path: string): ts.SourceFile { diff --git a/projects/storefrontapp-e2e-cypress/cypress/helpers/coupons/my-coupons.ts b/projects/storefrontapp-e2e-cypress/cypress/helpers/coupons/my-coupons.ts index 7a6364cc473..8e4923e3820 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/helpers/coupons/my-coupons.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/helpers/coupons/my-coupons.ts @@ -81,7 +81,7 @@ export function verifyMyCoupons() { verifyCouponsClaiming(); verifyEnableDisableNotification(); verifyReadMore(); - verifyFindProduct(CouponWithOpenCatalog, 10); + verifyFindProduct(CouponWithOpenCatalog, 12); goMyCoupon(); verifyFindProduct(CouponWithProductCategory, 4); goMyCoupon(); diff --git a/projects/storefrontapp-e2e-cypress/cypress/helpers/data-configuration.ts b/projects/storefrontapp-e2e-cypress/cypress/helpers/data-configuration.ts index a7ea4831141..6efb06295d3 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/helpers/data-configuration.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/helpers/data-configuration.ts @@ -1,5 +1,5 @@ export const PRODUCT_LISTING = { - PRODUCTS_PER_PAGE: 10, + PRODUCTS_PER_PAGE: 12, SORTING_TYPES: { BY_TOP_RATED: 'Top Rated', BY_RELEVANCE: 'Relevance', diff --git a/projects/storefrontapp-e2e-cypress/cypress/helpers/infinite-scroll.ts b/projects/storefrontapp-e2e-cypress/cypress/helpers/infinite-scroll.ts index 5718fe4d360..67cbcb4f8f4 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/helpers/infinite-scroll.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/helpers/infinite-scroll.ts @@ -2,8 +2,8 @@ import { PRODUCT_LISTING } from './data-configuration'; import { clickFacet, searchUrlPrefix } from './product-search'; const scrollDuration = 5000; -const defaultNumberOfProducts = 10; -let defaultProductLimit = 10; +const defaultNumberOfProducts = 12; +let defaultProductLimit = 12; const defaultQueryName = `query_relevance`; const defaultQueryAlias = `@${defaultQueryName}`; diff --git a/projects/storefrontapp-e2e-cypress/cypress/integration/regression/infinite-scroll.e2e-spec.ts b/projects/storefrontapp-e2e-cypress/cypress/integration/regression/infinite-scroll.e2e-spec.ts index 0f73a8e3e46..ede7568d7fe 100644 --- a/projects/storefrontapp-e2e-cypress/cypress/integration/regression/infinite-scroll.e2e-spec.ts +++ b/projects/storefrontapp-e2e-cypress/cypress/integration/regression/infinite-scroll.e2e-spec.ts @@ -65,20 +65,19 @@ describe('Infinite scroll', () => { isPaginationNotVisible(); scrollToFooter(totalResults, true); - backToTopIsVisible(); + backToTopIsVisible(true); }); }); - it("should enable infinite scroll and display 'Show more' button after 15th product", () => { - configScroll(true, 15, false); + it("should enable infinite scroll and display 'Show more' button after 12th product", () => { + configScroll(true, 12, false); cy.visit(testUrl); cy.wait(defaultQueryAlias).then((waitXHR) => { const totalResults = waitXHR.response.body.pagination.totalResults; isPaginationNotVisible(); - - backtoTopIsNotVisible(); - scrollToFooter(totalResults, false, 15); + backToTopIsVisible(); + scrollToFooter(totalResults, true, 12); backToTopIsVisible(true); }); }); diff --git a/projects/storefrontlib/src/cms-components/product/config/default-scroll-config.ts b/projects/storefrontlib/src/cms-components/product/config/default-view-config.ts similarity index 72% rename from projects/storefrontlib/src/cms-components/product/config/default-scroll-config.ts rename to projects/storefrontlib/src/cms-components/product/config/default-view-config.ts index 6318372de3c..388a7851749 100644 --- a/projects/storefrontlib/src/cms-components/product/config/default-scroll-config.ts +++ b/projects/storefrontlib/src/cms-components/product/config/default-view-config.ts @@ -1,7 +1,8 @@ import { ViewConfig } from '../../../shared/config/view-config'; -export const defaultScrollConfig: ViewConfig = { +export const defaultViewConfig: ViewConfig = { view: { + defaultPageSize: 12, infiniteScroll: { active: false, productLimit: 0, diff --git a/projects/storefrontlib/src/cms-components/product/index.ts b/projects/storefrontlib/src/cms-components/product/index.ts index 9640e093ced..f94371322bb 100644 --- a/projects/storefrontlib/src/cms-components/product/index.ts +++ b/projects/storefrontlib/src/cms-components/product/index.ts @@ -1,5 +1,5 @@ export * from './carousel/index'; -export * from './config/default-scroll-config'; +export * from './config/default-view-config'; export * from './current-product.service'; export * from './product-images/product-images.component'; export * from './product-images/product-images.module'; diff --git a/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.spec.ts b/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.spec.ts index 03f73e66f0c..a8679cbf29d 100644 --- a/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.spec.ts +++ b/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.spec.ts @@ -6,8 +6,10 @@ import { LanguageService, ProductSearchPage, ProductSearchService, + provideDefaultConfig, RoutingService, } from '@spartacus/core'; +import { defaultViewConfig, ViewConfig } from '@spartacus/storefront'; import { BehaviorSubject, of, Subscription } from 'rxjs'; import { ProductListComponentService } from './product-list-component.service'; @@ -80,6 +82,7 @@ describe('ProductListComponentService', () => { { provide: ProductSearchService, useClass: MockProductSearchService }, { provide: CurrencyService, useClass: MockCurrencyService }, { provide: LanguageService, useClass: MockLanguageService }, + provideDefaultConfig(defaultViewConfig), ], }); @@ -135,7 +138,7 @@ describe('ProductListComponentService', () => { })); describe('should perform search on change of routing', () => { - it('with default "pageSize" 10', fakeAsync(() => { + it('with default "pageSize" 12', fakeAsync(() => { const subscription: Subscription = service.model$.subscribe(); tick(); @@ -143,7 +146,7 @@ describe('ProductListComponentService', () => { subscription.unsubscribe(); expect(productSearchService.search).toHaveBeenCalledWith(undefined, { - pageSize: 10, + pageSize: 12, }); })); diff --git a/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.ts b/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.ts index d99424b17ec..0cd69a452ba 100644 --- a/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.ts +++ b/projects/storefrontlib/src/cms-components/product/product-list/container/product-list-component.service.ts @@ -19,6 +19,7 @@ import { tap, } from 'rxjs/operators'; import { ProductListRouteParams, SearchCriteria } from './product-list.model'; +import { ViewConfig } from '../../../../shared/config/view-config'; /** * The `ProductListComponentService` is used to search products. The service is used @@ -30,9 +31,6 @@ import { ProductListRouteParams, SearchCriteria } from './product-list.model'; */ @Injectable({ providedIn: 'root' }) export class ProductListComponentService { - // TODO: make it configurable - protected defaultPageSize = 10; - protected readonly RELEVANCE_ALLCATEGORIES = ':relevance:allCategories:'; constructor( @@ -41,7 +39,8 @@ export class ProductListComponentService { protected activatedRoute: ActivatedRoute, protected currencyService: CurrencyService, protected languageService: LanguageService, - protected router: Router + protected router: Router, + protected config: ViewConfig ) {} /** @@ -109,7 +108,7 @@ export class ProductListComponentService { ): SearchCriteria { return { query: queryParams.query || this.getQueryFromRouteParams(routeParams), - pageSize: queryParams.pageSize || this.defaultPageSize, + pageSize: queryParams.pageSize || this.config.view?.defaultPageSize, currentPage: queryParams.currentPage, sortCode: queryParams.sortCode, }; diff --git a/projects/storefrontlib/src/cms-components/product/product-list/product-list.module.ts b/projects/storefrontlib/src/cms-components/product/product-list/product-list.module.ts index d01044ee21d..1c2198ce892 100644 --- a/projects/storefrontlib/src/cms-components/product/product-list/product-list.module.ts +++ b/projects/storefrontlib/src/cms-components/product/product-list/product-list.module.ts @@ -20,7 +20,7 @@ import { } from '../../../shared/index'; import { AddToCartModule } from '../../cart/index'; import { IconModule } from '../../misc/icon/index'; -import { defaultScrollConfig } from '../config/default-scroll-config'; +import { defaultViewConfig } from '../config/default-view-config'; import { ProductListComponent } from './container/product-list.component'; import { ProductScrollComponent } from './container/product-scroll/product-scroll.component'; import { ProductGridItemComponent } from './product-grid-item/product-grid-item.component'; @@ -45,7 +45,7 @@ import { ProductViewComponent } from './product-view/product-view.component'; OutletModule, ], providers: [ - provideDefaultConfig(defaultScrollConfig), + provideDefaultConfig(defaultViewConfig), provideDefaultConfig({ cmsComponents: { CMSProductListComponent: { diff --git a/projects/storefrontlib/src/shared/config/view-config.ts b/projects/storefrontlib/src/shared/config/view-config.ts index 60c240eac27..919fd570f3e 100644 --- a/projects/storefrontlib/src/shared/config/view-config.ts +++ b/projects/storefrontlib/src/shared/config/view-config.ts @@ -10,6 +10,7 @@ export abstract class ViewConfig { /** * Configurations related to the view of the application */ + defaultPageSize?: number; infiniteScroll?: { active?: boolean; productLimit?: number;