Skip to content

Commit

Permalink
feat(upsell-products): add upsell products package (#1820)
Browse files Browse the repository at this point in the history
* feat(upsell-products): add upsell products package

* add testing driver

* fix lint
  • Loading branch information
griest024 authored Sep 11, 2021
1 parent 9112bfd commit 63448ad
Show file tree
Hide file tree
Showing 83 changed files with 1,508 additions and 2 deletions.
39 changes: 39 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,45 @@
}
}
},
"upsell-products": {
"root": "libs/upsell-products",
"sourceRoot": "libs/upsell-products/src",
"projectType": "library",
"prefix": "@daffodil",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "libs/upsell-products/tsconfig.lib.json",
"project": "libs/upsell-products/ng-package.json"
},
"configurations": {
"production": {
"project": "libs/upsell-products/ng-package.prod.json",
"tsConfig": "libs/upsell-products/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "libs/upsell-products/test.ts",
"codeCoverage": true,
"tsConfig": "libs/upsell-products/tsconfig.spec.json",
"karmaConfig": "libs/upsell-products/karma.conf.js"
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"libs/upsell-products/**/*.ts",
"libs/upsell-products/**/*.html"
]
}
}
}
},
"product-configurable": {
"root": "libs/product-configurable",
"sourceRoot": "libs/product-configurable/src",
Expand Down
52 changes: 52 additions & 0 deletions libs/upsell-products/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module.exports = {
extends: '../../.eslintrc.js',
ignorePatterns: [
'!**/*'
],
overrides: [
{
files: [
'*.ts'
],
parserOptions: {
project: [
'libs/upsell-products/tsconfig.lib.json',
'libs/upsell-products/tsconfig.spec.json'
],
createDefaultProgram: true
},
rules: {
'@angular-eslint/component-class-suffix': [
'error',
{
suffixes: [
'Component',
'Container'
]
}
],
'@angular-eslint/component-selector': [
'error',
{
type: 'lib',
prefix: 'kebab-case'
}
],
'@angular-eslint/directive-selector': [
'error',
{
type: 'attribute',
prefix: 'lib',
style: 'camelCase'
}
],
}
},
{
files: [
'*.html'
],
rules: {}
}
]
}
10 changes: 10 additions & 0 deletions libs/upsell-products/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# @daffodil/upsell-products

An optional package which adds the upsell products feature onto the `@daffodil/product` package.


## Installation

```
npm install @daffodil/upsell-products
```
8 changes: 8 additions & 0 deletions libs/upsell-products/driver/in-memory/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/upsell-products/driver/in-memory",
"deleteDestPath": false,
"lib": {
"entryFile": "src/index.ts"
}
}
3 changes: 3 additions & 0 deletions libs/upsell-products/driver/in-memory/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "@daffodil/upsell-products/driver/in-memory"
}
31 changes: 31 additions & 0 deletions libs/upsell-products/driver/in-memory/src/in-memory.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { CommonModule } from '@angular/common';
import {
NgModule,
ModuleWithProviders,
} from '@angular/core';

import { DAFF_PRODUCT_EXTRA_FACTORIES } from '@daffodil/product/testing';
import { DaffUpsellProductFactory } from '@daffodil/upsell-products/testing';

/**
* Module for providing the upsell product fields to the product extension factory.
*/
@NgModule({
imports: [
CommonModule,
],
})
export class DaffUpsellProductsInMemoryDriverModule {
static forRoot(): ModuleWithProviders<DaffUpsellProductsInMemoryDriverModule> {
return {
ngModule: DaffUpsellProductsInMemoryDriverModule,
providers: [
{
provide: DAFF_PRODUCT_EXTRA_FACTORIES,
useExisting: DaffUpsellProductFactory,
multi: true,
},
],
};
}
}
1 change: 1 addition & 0 deletions libs/upsell-products/driver/in-memory/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public_api';
1 change: 1 addition & 0 deletions libs/upsell-products/driver/in-memory/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DaffUpsellProductsInMemoryDriverModule } from './in-memory.module';
8 changes: 8 additions & 0 deletions libs/upsell-products/driver/magento/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/upsell-products/driver/magento",
"deleteDestPath": false,
"lib": {
"entryFile": "src/index.ts"
}
}
3 changes: 3 additions & 0 deletions libs/upsell-products/driver/magento/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "@daffodil/upsell-products/driver/magento"
}
1 change: 1 addition & 0 deletions libs/upsell-products/driver/magento/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './public_api';
56 changes: 56 additions & 0 deletions libs/upsell-products/driver/magento/src/magento.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { CommonModule } from '@angular/common';
import {
NgModule,
ModuleWithProviders,
inject,
} from '@angular/core';

import { DaffProductDriverResponse } from '@daffodil/product/driver';
import {
DAFF_PRODUCT_MAGENTO_EXTRA_PRODUCT_FRAGMENTS,
DAFF_PRODUCT_MAGENTO_EXTRA_PRODUCT_PREVIEW_FRAGMENTS,
DAFF_PRODUCT_MAGENTO_EXTRA_PRODUCT_RESPONSE_TRANSFORMS,
} from '@daffodil/product/driver/magento';

import { MagentoProductWithUpsell } from './models/product-with-upsell.interface';
import { magentoUpsellProductsFragment } from './queries/fragments/upsell-products';
import { DaffMagentoUpsellProductsTransformers } from './transforms/product-response.service';

/**
* A module that provides the {@link magentoUpsellProductsFragment} and {@link DaffMagentoUpsellProductsTransformers}.
*/
@NgModule({
imports: [
CommonModule,
],
})
export class DaffUpsellProductsMagentoDriverModule {
static forRoot(): ModuleWithProviders<DaffUpsellProductsMagentoDriverModule> {
return {
ngModule: DaffUpsellProductsMagentoDriverModule,
providers: [
{
provide: DAFF_PRODUCT_MAGENTO_EXTRA_PRODUCT_FRAGMENTS,
multi: true,
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
useFactory() {
return magentoUpsellProductsFragment(inject(DAFF_PRODUCT_MAGENTO_EXTRA_PRODUCT_PREVIEW_FRAGMENTS));
},
},
{
provide: DAFF_PRODUCT_MAGENTO_EXTRA_PRODUCT_RESPONSE_TRANSFORMS,
multi: true,
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
useFactory() {
const transformerService = inject(DaffMagentoUpsellProductsTransformers);
return (
daffProductResponse: DaffProductDriverResponse,
magentoProduct: MagentoProductWithUpsell,
mediaUrl: string,
) => transformerService.transformMagentoUpsellProducts(daffProductResponse, magentoProduct, mediaUrl);
},
},
],
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {
MagentoProduct,
MagentoProductPreview,
} from '@daffodil/product/driver/magento';

/**
* A product that includes a list of upsell products.
*/
export interface MagentoProductWithUpsell extends MagentoProduct {
upsell_products: MagentoProductPreview[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { MagentoProductWithUpsell } from './product-with-upsell.interface';
6 changes: 6 additions & 0 deletions libs/upsell-products/driver/magento/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export { magentoUpsellProductsFragment } from './queries/fragments/upsell-products';
export { DaffMagentoUpsellProductsTransformers } from './transforms/product-response.service';

export * from './models/public_api';

export { DaffUpsellProductsMagentoDriverModule } from './magento.module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { gql } from 'apollo-angular';
import { DocumentNode } from 'graphql';

import {
daffBuildFragmentDefinition,
daffBuildFragmentNameSpread,
} from '@daffodil/core/graphql';
import { magentoProductPreviewFragment } from '@daffodil/product/driver/magento';

export const magentoUpsellProductsFragment = (extraProductFragments: DocumentNode[] = []) => gql`
fragment upsellProducts on ProductInterface {
upsell_products {
...magentoProductPreview
${daffBuildFragmentNameSpread(...extraProductFragments)}
}
}
${magentoProductPreviewFragment}
${daffBuildFragmentDefinition(...extraProductFragments)}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { TestBed } from '@angular/core/testing';
import { DaffUpsellProduct } from 'libs/upsell-products/src/models/upsell-product.interface';

import { DaffProduct } from '@daffodil/product';
import { DaffProductDriverResponse } from '@daffodil/product/driver';
import { daffProvideProductMagentoExtraProductPreviewTransforms } from '@daffodil/product/driver/magento';
import { MagentoCoreProductFactory } from '@daffodil/product/driver/magento/testing';
import { DaffProductFactory } from '@daffodil/product/testing';
import { MagentoProductWithUpsellFactory } from '@daffodil/upsell-products/driver/magento/testing';
import { DaffUpsellProductFactory } from '@daffodil/upsell-products/testing';

import { MagentoProductWithUpsell } from '../models/product-with-upsell.interface';
import { DaffMagentoUpsellProductsTransformers } from './product-response.service';

describe('@daffodil/upsell-products/driver/magento | DaffMagentoUpsellProductsTransformers', () => {
let service: DaffMagentoUpsellProductsTransformers;
let stubMagentoProduct: MagentoProductWithUpsell;
let productFactory: DaffProductFactory;
let magentoProductFactory: MagentoCoreProductFactory;
let magentoUpsellProductFactory: MagentoProductWithUpsellFactory;
const mediaUrl = 'media url';
let mockProduct: DaffProduct;
let mockResponse: DaffProductDriverResponse;
let previewTransformerSpy: jasmine.Spy;

beforeEach(() => {
previewTransformerSpy = jasmine.createSpy();
previewTransformerSpy.and.callFake(product => product);

TestBed.configureTestingModule({
providers: [
daffProvideProductMagentoExtraProductPreviewTransforms(
previewTransformerSpy,
),
],
});

service = TestBed.inject(DaffMagentoUpsellProductsTransformers);
productFactory = TestBed.inject(DaffProductFactory);
magentoProductFactory = TestBed.inject(MagentoCoreProductFactory);
magentoUpsellProductFactory = TestBed.inject(MagentoProductWithUpsellFactory);

stubMagentoProduct = magentoUpsellProductFactory.create({
upsell_products: magentoProductFactory.createMany(1),
});
mockProduct = productFactory.create();
mockResponse = {
id: mockProduct.id,
products: [mockProduct],
};
});

describe('transformMagentoUpsellProducts', () => {
let result: DaffProductDriverResponse;

beforeEach(() => {
result = service.transformMagentoUpsellProducts(mockResponse, stubMagentoProduct, mediaUrl);
});

it('should call the preview transformer', () => {
expect(previewTransformerSpy).toHaveBeenCalled();
});

it('should add upsell products to the main daff product', () => {
expect((<DaffUpsellProduct>result.products[0]).upsell[0].id).toEqual(stubMagentoProduct.upsell_products[0].sku);
});

it('should add upsell products to the response product list', () => {
expect(result.products[1].id).toEqual(stubMagentoProduct.upsell_products[0].sku);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Inject,
Injectable,
} from '@angular/core';

import { DaffProductDriverResponse } from '@daffodil/product/driver';
import {
DaffMagentoProductPreviewTransform,
DAFF_PRODUCT_MAGENTO_PRODUCT_PREVIEW_TRANSFORM,
} from '@daffodil/product/driver/magento';

import { MagentoProductWithUpsell } from '../models/product-with-upsell.interface';

/**
* Adds upsell product info to the product driver response.
*/
@Injectable({
providedIn: 'root',
})
export class DaffMagentoUpsellProductsTransformers {
constructor(
@Inject(DAFF_PRODUCT_MAGENTO_PRODUCT_PREVIEW_TRANSFORM) private productPreviewTransform: DaffMagentoProductPreviewTransform,
) {}

/**
* Transforms magento upsell products with the product preview transform and
* stores those upsell products in the products array and nested in the main product.
*/
transformMagentoUpsellProducts(
daffProductResponse: DaffProductDriverResponse,
magentoProduct: MagentoProductWithUpsell,
mediaUrl: string,
): DaffProductDriverResponse {
const upsell = magentoProduct.upsell_products.map(p => this.productPreviewTransform(p, mediaUrl));

return {
...daffProductResponse,

products: [
...daffProductResponse.products.map(product =>
product.id === daffProductResponse.id
? ({
...product,
upsell,
})
: product,
),
...upsell,
],
};
}
}
Loading

0 comments on commit 63448ad

Please sign in to comment.