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

feat(snap-platforms) #1022

Merged
merged 40 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3fbd797
feat(snap-platforms): snap-platforms added for shopify, bigc, & magento2
chrisFrazier77 Apr 4, 2024
b371dd8
chore(package-lock): updating lock file
chrisFrazier77 Apr 4, 2024
b474ca6
refactor(snap-platforms): general clean up
chrisFrazier77 Apr 4, 2024
a356903
refactor(snap-platforms): moving some files around
chrisFrazier77 Apr 5, 2024
fdd1203
chore(cleanup): clean up comments and logs
chrisFrazier77 Apr 5, 2024
f4a4001
feat(preact-components-variantselection): variantSelection & supporti…
chrisFrazier77 Apr 25, 2024
1a226b4
refactor(variantselection.stories): clean up
chrisFrazier77 Apr 25, 2024
9539b44
chore(merge develop): merge develop
chrisFrazier77 Apr 25, 2024
175b9fb
refactor(preact-components-variantselection): some clean up and refac…
chrisFrazier77 May 2, 2024
767a490
refactor(preact-components-variantselection): tweaks,docs,tests,& sto…
chrisFrazier77 May 9, 2024
27c42e7
chore(merge develop): merge develop
chrisFrazier77 May 10, 2024
ae4e8e0
refactor: undo
chrisFrazier77 May 10, 2024
429dca4
refactor(searchresultstore): fix variant availabilty
chrisFrazier77 May 10, 2024
6e928f9
refactor(variants): merging both variant branches together. and gener…
chrisFrazier77 May 14, 2024
48872c8
refactor(merge develop): merge develop
chrisFrazier77 May 14, 2024
5dea0d8
refactor(preact-components): clean up
chrisFrazier77 May 15, 2024
78e238b
build(package-lock): update package-lock
chrisFrazier77 May 15, 2024
4f62981
refactor(variants): merge in variants updates & components
chrisFrazier77 May 15, 2024
4b0ecc9
refactor(platforms-magento-addtocart): finalize magento variants addt…
chrisFrazier77 May 15, 2024
701f9ae
refactor(platforms-bigcommerce-addtocart): general clean up in bigC a…
chrisFrazier77 May 15, 2024
15ae21d
chore(package-lock): update package-lock file and dependency versions…
chrisFrazier77 May 15, 2024
54bf178
refactor(preact-components-variantselection): clean up variantSelecti…
chrisFrazier77 May 16, 2024
d8d04d6
refactor(preact-components): handleize classnames for grid list and s…
chrisFrazier77 May 16, 2024
339d445
chore(mergedevelop): merge in develop
chrisFrazier77 May 16, 2024
b3910e0
chore(lock file): update lock file
chrisFrazier77 May 16, 2024
9cb1674
chore(lock file): update lock file from develop
chrisFrazier77 May 16, 2024
1dff9cd
test(addtocart.test): small refactors after merging develop
chrisFrazier77 May 17, 2024
1627d90
fix(store-mobx/cart): typecasting price and MSRP in cart for edge cas…
korgon May 20, 2024
af1fade
refactor(platforms/bigcommerce): renaming directory
korgon May 21, 2024
193e277
refactor(preact-components/swatches): refactored and polished some of…
korgon May 21, 2024
ec8b17f
refactor(variant-options-abstraction): variant-options-abstraction
chrisFrazier77 May 21, 2024
d71ba0c
feat(variant-options-abstraction): variant-options-abstraction
chrisFrazier77 May 21, 2024
e243707
refactor(platforms/addtocart): removed callback in favor of 'redirect…
korgon May 22, 2024
713fd4b
Merge branch 'develop' into platform
korgon May 22, 2024
2bda50b
fix(preact/createrecommendationcontroller): fixing test after typing …
korgon May 22, 2024
ac920ea
refactor(preact-components/variants): variant component polish and ch…
korgon May 22, 2024
13afc02
docs(docs): adding snap-platforms to the snap docs and adjusting some…
korgon May 22, 2024
13c1dae
refactor(variant-options-abstraction): moving from plugin to SearchRe…
korgon May 22, 2024
2c98067
Merge pull request #1045 from searchspring/cartstore-string-price-fix
korgon May 22, 2024
b847c18
fix(store-mobx/searchresultstore): adding an optional chain for cases…
korgon May 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84,674 changes: 46,317 additions & 38,357 deletions package-lock.json

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions packages/snap-platforms/bigCommerce/README.md
korgon marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# BigCommerce Platform
This platform library gives you helper functions to use with the BigCommerce platform.


## Usage
To use the platform library, simply import what you wish to use from `@searchspring/snap-platforms/bigCommerce`.

```jsx
import { addToCart } from '@searchspring/snap-platforms/bigCommerce';

export const Result = withController(observer((props) => {
const { controller, result } = props;

const config = {
idFieldName: `display.mappings.core.sku`,
callback: () => console.log('added to cart')
}

return (
<div onClick={() => addToCart([result], config)}>Add To Cart</div>
)
}))
```

## AddToCart
The `addToCart` function will automatically add products to the cart and then navigate to the cart page. The function takes an array of products (Result Store References) to add, and an optional config. The optional config can take two optional fields, a `callback` and `idFieldName`.

The `callback` setting takes a function to call after the products are added to the cart, this will get called rather than the automatic redirect to the cart page.

The `idFieldName` setting takes a stringified path in the result reference, to look for the product id to add. `display.mappings.core.sku` for example. By default it will use `display.mappings.core.uid`.
8 changes: 8 additions & 0 deletions packages/snap-platforms/bigCommerce/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "snap-platforms-bigcommerce",
"private": true,
"description": "Snap BigCommerce Platform Library",
"main": "../dist/cjs/bigCommerce/src/index.js",
"module": "../dist/esm/bigCommerce/src/index.js",
"sideEffects": false
}
200 changes: 200 additions & 0 deletions packages/snap-platforms/bigCommerce/src/addToCart.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import 'whatwg-fetch';
import { addToCart } from './addToCart';
import { Product } from '@searchspring/snap-store-mobx';
import { MockClient } from '@searchspring/snap-shared';
import { SearchStore } from '@searchspring/snap-store-mobx';
import { UrlManager, QueryStringTranslator, reactLinker } from '@searchspring/snap-url-manager';
import { EventManager } from '@searchspring/snap-event-manager';
import { Profiler } from '@searchspring/snap-profiler';
import { Logger } from '@searchspring/snap-logger';
import { Tracker } from '@searchspring/snap-tracker';
import { SearchController } from '@searchspring/snap-controller';

const wait = (time = 1) => {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
};

const urlManager = new UrlManager(new QueryStringTranslator(), reactLinker);
const services = {
urlManager: urlManager,
};
let searchConfig = {
id: 'search',
};

const globals = { siteId: '8uyt2m' };
const searchConfigDefault = {
id: 'search',
globals: {
filters: [],
},
settings: {},
};
let results: any;
let controller: any;
let errMock: any;

// @ts-ignore
const fetchMock = jest.spyOn(global, 'fetch').mockImplementation(() => Promise.resolve({ json: () => Promise.resolve([]), ok: true, status: 200 }));
const root = 'http://localhost/remote/v1/cart/add';

describe('addToCart', () => {
beforeAll(async () => {
searchConfig = { ...searchConfigDefault };
controller = new SearchController(searchConfig, {
client: new MockClient(globals, {}),
store: new SearchStore(searchConfig, services),
urlManager,
eventManager: new EventManager(),
profiler: new Profiler(),
logger: new Logger(),
tracker: new Tracker(globals),
});

await controller.search();

results = controller.store.results;

errMock = jest.spyOn(console, 'error').mockImplementation(() => {});
});

it('requires data to exist on the dom', () => {
// @ts-ignore
addToCart();

expect(fetchMock).not.toHaveBeenCalled();
});

it('adds data passed', () => {
const item = results[0] as Product;
addToCart([item]);

const obj = {
product_id: item.id,
quantity: item.quantity,
action: 'add',
};
const params = {
body: JSON.stringify(obj),
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
method: 'POST',
};

expect(fetchMock).toHaveBeenCalledWith(root, params);

fetchMock.mockClear();
});

it('can add multiple quantities', () => {
const item = results[0] as Product;

item.quantity = 4;

addToCart([item]);

const obj = {
product_id: item.id,
quantity: 4,
action: 'add',
};

const params = {
body: JSON.stringify(obj),
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
method: 'POST',
};

expect(fetchMock).toHaveBeenCalledWith(root, params);

fetchMock.mockClear();

item.quantity = 1;
});

it('can use alternate id column', () => {
const config = {
idFieldName: 'mappings.core.url',
};

const item = results[0] as Product;

addToCart([item], config);

const obj = {
product_id: item.mappings.core?.url,
quantity: item.quantity,
action: 'add',
};

const params = {
body: JSON.stringify(obj),
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
method: 'POST',
};

expect(fetchMock).toHaveBeenCalledWith(root, params);

fetchMock.mockClear();
});

it('can pass a callback', async () => {
const cb = jest.fn();
const config = {
callback: cb,
};

const item = results[0] as Product;

addToCart([item], config);

const obj = {
product_id: item.id,
quantity: item.quantity,
action: 'add',
};
const params = {
body: JSON.stringify(obj),
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
method: 'POST',
};

expect(fetchMock).toHaveBeenCalledWith(root, params);

await wait(10);

expect(cb).toHaveBeenCalled();

fetchMock.mockClear();
});

it('can add multiple items', async () => {
const items = results.slice(0, 3) as Product[];
addToCart(items);

for (let i = 0; i < items.length; i++) {
const obj = {
product_id: items[i].id,
quantity: items[i].quantity,
action: 'add',
};
const params = {
body: JSON.stringify(obj),
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
method: 'POST',
};

await wait(10);

expect(fetchMock).toHaveBeenCalledWith(root, params);
}

fetchMock.mockClear();
});
});
110 changes: 110 additions & 0 deletions packages/snap-platforms/bigCommerce/src/addToCart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import type { Product } from '@searchspring/snap-store-mobx';

interface config {
callback?: () => void;
idFieldName?: string; //display.mappings.core.id
}

type formData = {
line_items: {
product_id: number;
quantity: number;
}[];
};

export const addToCart = async (data: Product[], config?: config) => {
const formData: formData = {
line_items: [],
};

if (!data) {
console.error('Error: no products to add');
return false;
}

data.map((item) => {
let id: any;
if (config?.idFieldName) {
let level: any = item;
config.idFieldName.split('.').map((field) => {
if (level[field]) {
level = level[field];
} else {
console.error('Error: couldnt find column in item data. please check your idFieldName is correct in the config.');
return false;
}
});
if (level && level !== item) {
id = level;
} else {
id = item.display.mappings.core?.uid;
}
} else {
id = item.display.mappings.core?.uid;
}
if (id && item.quantity) {
const obj = {
product_id: id,
quantity: item.quantity,
};

formData.line_items.push(obj);
}
});

//first check how many products we are adding
if (formData.line_items.length) {
for (let i = 0; i < formData.line_items.length; i++) {
await addSingleProductv1(formData.line_items[i]);
}
}

if (config?.callback) {
config.callback();
} else {
console.log('redirecting');
setTimeout(() => (window.location.href = '/cart.php'));
}
};

const addSingleProductv1 = async (item: { product_id: number; quantity: number }) => {
const endpoint = {
route: `/remote/v1/cart/add`,
method: 'POST',
accept: 'application/json',
content: 'application/json',
success: 200,
};

const resource = `${window.location.origin}${endpoint.route}`;

const init: any = {
method: endpoint.method,
credentials: 'same-origin',
headers: {
// note: no authorization
Accept: endpoint.accept,
},
};

if (item) {
init.headers['Content-Type'] = endpoint.content;
//clone item..
init.body = { ...item };
init.body['action'] = 'add';
init.body = JSON.stringify(init.body);
}

try {
const response = await fetch(resource, init);

if (response.status === endpoint.success) {
const jsonResponse = response.json();
return jsonResponse;
} else {
return new Error(`Error: Snap-platform-bigcommerce addToCart responded with ${response.status}, ${response}`);
}
} catch (err) {
console.error(err);
}
};
1 change: 1 addition & 0 deletions packages/snap-platforms/bigCommerce/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './addToCart';
7 changes: 7 additions & 0 deletions packages/snap-platforms/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* eslint-disable */
const rootConfig = require('../../jest.base.config.json');
module.exports = {
...rootConfig,
displayName: 'snap-toolbox',
roots: ['<rootDir>/bigCommerce/src', '<rootDir>/magento2/src', '<rootDir>/shopify/src'],
};
Loading
Loading