Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:magento/pwa-studio into PB-220
Browse files Browse the repository at this point in the history
  • Loading branch information
omiroshnichenko committed Nov 13, 2019
2 parents e87808f + d0164ba commit 448f296
Show file tree
Hide file tree
Showing 74 changed files with 2,190 additions and 407 deletions.
18 changes: 18 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# create-pwa
# /packages/create-pwa/lib/ @zetlen

# peregrine
# /packages/peregrine/lib/ @jimbo

# pwa-buildpack
# /packages/pwa-buildpack/lib/ @zetlen

# venia-ui
# /packages/venia-ui/lib/ @jimbo
/packages/venia-ui/lib/components/RichContent/PageBuilder/ @davemacaulay

# upward-js
# /packages/upward-js/lib/ @zetlen

# upward-spec
# /packages/upward-spec/suite/ @zetlen
52 changes: 52 additions & 0 deletions packages/peregrine/lib/talons/Breadcrumbs/useBreadcrumbs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useMemo } from 'react';
import { useQuery } from '@apollo/react-hooks';

// Just incase the data is unsorted, lets sort it.
const sortCrumbs = (a, b) => a.category_level > b.category_level;

// Generates the path for the category.
const getPath = (path, suffix) => {
if (path) {
return `/${category_url_path}${suffix}`;
}

// If there is no path this is just a dead link.
return '#';
};

/**
* Returns props necessary to render a Breadcrumbs component.
*
* @param {object} props
* @param {object} props.query - the breadcrumb query
* @param {string} props.categoryId - the id of the category for which to generate breadcrumbs
* @return {{ currentCategory: string, isLoading: boolean, normalizedData: array }}
*/
export const useBreadcrumbs = props => {
const { categoryId, query } = props;

const { data, loading } = useQuery(query, {
variables: { category_id: categoryId }
});

// When we have breadcrumb data sort and normalize it for easy rendering.
const normalizedData = useMemo(() => {
if (!loading && data) {
const breadcrumbData = data.category.breadcrumbs;
const categoryUrlSuffix = data.storeConfig.category_url_suffix;
return (
breadcrumbData &&
breadcrumbData.sort(sortCrumbs).map(category => ({
text: category.category_name,
path: getPath(category.category_url_path, categoryUrlSuffix)
}))
);
}
}, [data, loading]);

return {
currentCategory: (data && data.category.name) || '',
isLoading: loading,
normalizedData: normalizedData || []
};
};
44 changes: 12 additions & 32 deletions packages/peregrine/lib/talons/Image/__tests__/useImage.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { createTestInstance } from '@magento/peregrine';

import { useImage } from '../useImage';

const SMALL_RESOURCE_SIZE = 50;
const props = {
onError: jest.fn(),
onLoad: jest.fn(),
resourceSizes: new Map([['small', SMALL_RESOURCE_SIZE]]),
resourceWidth: 100
widths: new Map().set('default', 50)
};

const log = jest.fn();
Expand Down Expand Up @@ -37,23 +35,11 @@ test('it returns the proper shape', () => {
});

describe('resourceWidth', () => {
test('uses the prop, if present', () => {
// Act.
createTestInstance(<Component {...props} />);

// Assert.
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
resourceWidth: props.resourceWidth
})
);
});

test('falls back to the first entry in resourceSizes if prop is not present', () => {
test('uses width if present', () => {
// Arrange.
const myProps = {
...props,
resourceWidth: undefined
width: 75
};

// Act.
Expand All @@ -62,36 +48,30 @@ describe('resourceWidth', () => {
// Assert.
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
resourceWidth: SMALL_RESOURCE_SIZE
resourceWidth: myProps.width
})
);
});

test('returns null if prop and resourceSizes are not present', () => {
// Arrange.
const myProps = {
...props,
resourceSizes: undefined,
resourceWidth: undefined
};

test('falls back to the default entry in widths', () => {
// Act.
createTestInstance(<Component {...myProps} />);
createTestInstance(<Component {...props} />);

// Assert.
const defaultWidthEntry = props.widths.get('default');
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
resourceWidth: null
resourceWidth: defaultWidthEntry
})
);
});

test('returns null if prop is not present and resourceSizes does not have a "small" entry', () => {
test('returns undefined if width and widths are not present', () => {
// Arrange.
const myProps = {
...props,
resourceSizes: new Map([['large', 400]]),
resourceWidth: undefined
width: undefined,
widths: undefined
};

// Act.
Expand All @@ -100,7 +80,7 @@ describe('resourceWidth', () => {
// Assert.
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
resourceWidth: null
resourceWidth: undefined
})
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import { useResourceImage } from '../useResourceImage';
const SMALL_RESOURCE_SIZE = 100;
const props = {
generateSrcset: jest.fn(() => 'mock_srcset'),
height: 125,
resource: 'unit_test_resource.jpg',
resourceHeight: 125,
resourceSizeBreakpoints: new Map(),
resourceSizes: new Map([['small', SMALL_RESOURCE_SIZE]]),
resourceUrl: jest.fn(() => 'mock_resource_url'),
resourceWidth: SMALL_RESOURCE_SIZE,
type: 'image-product'
type: 'image-product',
widths: new Map().set('default', SMALL_RESOURCE_SIZE)
};

const log = jest.fn();
Expand Down Expand Up @@ -48,57 +46,77 @@ test('it calls generateSrcset and resourceUrl', () => {
});

describe('sizes', () => {
test('works when given no breakpoints', () => {
test('works when given a width but no widths', () => {
// Arrange.
const myProps = {
...props,
width: 100,
widths: undefined
};

// Act.
createTestInstance(<Component {...props} />);
createTestInstance(<Component {...myProps} />);

// Assert.
const expected = `${SMALL_RESOURCE_SIZE}px`;
const expected = '100px';
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
sizes: expected
})
);
});

test('works when given a small breakpoint only', () => {
test('returns an empty string when given no width or widths', () => {
// Arrange.
const myProps = {
...props,
resourceSizeBreakpoints: new Map([['small', 75]]),
resourceSizes: new Map([['small', 50], ['medium', 100]])
width: undefined,
widths: undefined
};

// Act.
createTestInstance(<Component {...myProps} />);

// Assert.
const expected = '(max-width: 75px) 50px, 100px';
const expected = '';
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
sizes: expected
})
);
});

test('works when given a single "default" breakpoint', () => {
// Act.
createTestInstance(<Component {...props} />);

// Assert.
const expected = '100px';
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
sizes: expected
})
);
});

test('works when given a small and medium breakpoint', () => {
test('works when given a multiple breakpoints', () => {
// Arrange.
const myProps = {
...props,
resourceSizeBreakpoints: new Map([['small', 75], ['medium', 125]]),
resourceSizes: new Map([
['small', 50],
['medium', 100],
['large', 150]
])
widths: new Map()
.set(100, 50)
.set(200, 150)
.set(300, 250)
.set(400, 350)
.set('default', 450)
};

// Act.
createTestInstance(<Component {...myProps} />);

// Assert.
const expected =
'(max-width: 75px) 50px, (max-width: 125px) 100px, 150px';
'(max-width: 100px) 50px, (max-width: 200px) 150px, (max-width: 300px) 250px, (max-width: 400px) 350px, 450px';
expect(log).toHaveBeenCalledWith(
expect.objectContaining({
sizes: expected
Expand Down
29 changes: 14 additions & 15 deletions packages/peregrine/lib/talons/Image/useImage.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { useCallback, useMemo, useState } from 'react';

export const UNCONSTRAINED_SIZE_KEY = 'default';

/**
* Returns props to render an Image component.
*
* @param {function} props.onError callback for error of loading image
* @param {function} props.onLoad callback for load of image
* @param {Map} props.resourceSizes image sizes used by the browser to select the image source. Supported keys are 'small', 'medium', and 'large'.
* @param {number} props.resourceWidth the intrinsic width of the image & the width to request for the fallback image for browsers that don't support srcset / sizes.
* @param {number} props.width the intrinsic width of the image & the width to request for the fallback image for browsers that don't support srcset / sizes.
* @param {Map} props.widths a map of breakpoints to possible widths used to create the img's sizes attribute.
*/
export const useImage = props => {
const {
onError,
onLoad,
resourceSizes,
resourceWidth: propResourceWidth
} = props;
const { onError, onLoad, width, widths } = props;
const [isLoaded, setIsLoaded] = useState(false);
const [hasError, setHasError] = useState(false);

Expand All @@ -34,18 +31,20 @@ export const useImage = props => {
}
}, [onError]);

// If we don't have a resourceWidth, use the smallest resource size.
// Use the unconstrained / default entry in widths.
const resourceWidth = useMemo(() => {
if (propResourceWidth) {
return propResourceWidth;
if (width) {
return width;
}

if (!resourceSizes) {
return null;
// We don't have an explicit width.
// Attempt to use the unconstrained entry in widths.
if (!widths) {
return undefined;
}

return resourceSizes.get('small') || null;
}, [propResourceWidth, resourceSizes]);
return widths.get(UNCONSTRAINED_SIZE_KEY);
}, [width, widths]);

return {
handleError,
Expand Down
8 changes: 8 additions & 0 deletions packages/peregrine/lib/talons/Image/usePlaceholderImage.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
/**
* The talon for working with PlaceholderImages.
* Determines whether the visual placeholder should be rendered or not.
*
* @param {bool} props.displayPlaceholder whether or not to display a visual placeholder.
* @param {string} props.imageHasError there was an error loading the actual image.
* @param {string} props.imageIsLoaded the actual image is loaded.
*/
export const usePlaceholderImage = props => {
const { displayPlaceholder, imageHasError, imageIsLoaded } = props;

Expand Down
Loading

0 comments on commit 448f296

Please sign in to comment.