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

Implementing V2 tree page #1788

Open
wants to merge 6 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 29 additions & 0 deletions cypress/fixtures/186734captures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"captures": [
{
"id": 186734,
"lat": -4.881696978000001,
"lon": 38.37997515399998,
"time_created": "2019-03-15T06:46:40.000Z",
"image_url":
"https://treetracker-dev-images.s3.eu-central-1.amazonaws.com/2020.10.19.09.50.52_-5.508076904796398_38.98152805626448_28181c3e-e5b9-442b-8bb4-00de35de3de2_IMG_20201019_094643_486288846930987329.jpg"
},
{
"id": 186734,
"lat": -4.881696978000001,
"lon": 38.37997515399998,
"time_created": "2020-10-29T06:46:40.000Z",
"image_url":
"https://treetracker-production-images.s3.eu-central-1.amazonaws.com/2023.02.17.11.59.47_38.364922414000006_-122.51189396800001_a906ab31-5169-421c-8df3-be43f24d4d9c_IMG_20230217_111351_7976264471450881710.jpg"
},

{
"id": 186734,
"lat": -4.881696978000001,
"lon": 38.37997515399998,
"time_created": "2022-06-03T06:46:40.000Z",
"image_url":
"https://treetracker-production-images.s3.eu-central-1.amazonaws.com/2021.07.05.14.00.45_-3.2064076340000005_36.640772894_7b988c04-668e-48f5-b2e5-906f7d8374eb_IMG_20210705_132121_643781854.jpg"
}
]
}
15 changes: 15 additions & 0 deletions cypress/tests/integration/nockRoutes.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import grower100 from '../../../doc/examples/growers/100.json';
import organization1 from '../../../doc/examples/organizations/1.json';
import planter940 from '../../../doc/examples/planters/940.json';
import captures186734 from '../../../doc/examples/trees/186734captures.json';
import { defaultConfig } from '../../../src/context/configContext';
import capture1 from '../../fixtures/capture.json';
import leader from '../../fixtures/countries/leader.json';
Expand All @@ -13,13 +14,15 @@ export function getNockRoutes(
grower: {},
planter: {},
capture: {},
treeCaputres: {},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please correct this spelling mistake ("captures") throughout the file?

},
) {
const organization = { ...organization1, ...props.organization };
const grower = { ...grower100, ...props.grower };
const planter = { ...planter940, ...props.planter };
const tree = { ...tree186734, ...props.tree };
const capture = { ...capture1, ...props.capture };
const treeCaputres = { ...captures186734, ...props.treeCaputres };

return [
{
Expand Down Expand Up @@ -70,6 +73,12 @@ export function getNockRoutes(
statusCode: 200,
body: tree,
},
{
method: 'GET',
path: `/trees/${tree.id}/captures`,
statusCode: 200,
body: treeCaputres,
},
{
method: 'GET',
path: `/growers/${planter.id}`,
Expand Down Expand Up @@ -118,6 +127,12 @@ export function getNockRoutes(
captures: [capture],
},
},
{
method: 'GET',
path: `/stakeholder/${organization.id}`,
statusCode: 200,
body: organization,
},
];
}

Expand Down
120 changes: 120 additions & 0 deletions cypress/tests/integration/v2/trees/[treeid].cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import grower from '../../../../../doc/examples/growers/100.json';
import treecaptures from '../../../../../doc/examples/trees/186734captures.json';
import tree from '../../../../fixtures/tree186734.json';
import { prepareNocks, clearNocks } from '../../nockRoutes';

const getStubbedImageUrl = (image) => {
const blob = Cypress.Blob.base64StringToBlob(image, 'image/png');
return Cypress.Blob.createObjectURL(blob);
};

beforeEach(() => {
clearNocks();

const stubs = {};
cy.fixture('images/trees/10.jpg').then((image) => {
stubs.tree = { ...tree, image_url: getStubbedImageUrl(image) };
});
cy.fixture('images/grower.png').then((image) => {
stubs.grower = { ...grower, image_url: getStubbedImageUrl(image) };
});
cy.fixture('images/trees/1.jpg').then((image) => {
stubs.tree1 = getStubbedImageUrl(image);
});
cy.fixture('images/trees/2.jpg').then((image) => {
stubs.tree2 = getStubbedImageUrl(image);
});
cy.fixture('images/trees/3.jpg').then((image) => {
stubs.tree3 = getStubbedImageUrl(image);
});
// Load mock JSON data
const updatedCaptures = treecaptures.captures.map((capture, index) => ({
...capture,
image_url: stubs[`tree${index + 1}`],
}));
stubs.treeCaptures = updatedCaptures;

cy.wrap(null).then(() => {
prepareNocks(stubs);
});

cy.visit(`/trees/${tree.id}`, {
failOnStatusCode: false,
});
});

describe('V2 Tree Page', () => {
it('renders with tree data', () => {
cy.url().should('include', `/trees/${tree.id}`);

// check if the tree caputrues data correct

// Wait for the tree captures data to be available
cy.get('#tree-captures-data', { timeout: 10000 }).should('exist');

// Check if the tree captures data is correct

if (treecaptures.captures.length > 0) {
cy.get('#tree-captures-data').should(
'contain.text',
`Captures of growth: ${treecaptures.captures.length}`,
);
} else {
cy.get('#tree-captures-data').should('contain.text', 'No captures yet');
}

cy.get('#tree-title > .MuiTypography-root').should(
'include.text',
`${tree.id}`,
);

if (tree.species) {
cy.get('#tree-species-data').should('include.text', `${tree.species}`);
} else {
cy.get('#tree-species-data').should('include.text', 'Unknown Species');
}

cy.screenshot();
});

it('timeline component render with correct date', () => {
// Check the first capture's date
cy.get(
':nth-child(1) > .MuiTypography-body1 > .MuiTypography-root > time',
).should(
'have.text',
new Date(treecaptures.captures[0].time_created).toLocaleDateString(),
);

// Check the second capture's date
cy.get(
':nth-child(2) > .MuiTypography-body1 > .MuiTypography-root > time',
).should(
'have.text',
new Date(treecaptures.captures[1].time_created).toLocaleDateString(),
);

// Check the third capture's date
cy.get(
':nth-child(3) > .MuiTypography-body1 > .MuiTypography-root > time',
).should(
'have.text',
new Date(treecaptures.captures[2].time_created).toLocaleDateString(),
);
});
});

describe('Tree Page - Mobile Version', () => {
beforeEach(() => {
// Set viewport to a mobile screen size
cy.viewport('iphone-6');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that including testing for mobile layouts is a great idea, and something we should consider requiring in all of the project's integration tests, going forward.

The web-map-client mobile layout was designed with iPhone 12 Pro dimensions (390px × 844px). Could you change this .viewport() to use these dimensions instead?

});

it('should display mobile version elements and not display desktop version elements', () => {
// Assert that the mobile version element exists
cy.get('#mobile-tree-info').should('exist');

// Assert that the desktop version element does not exist
cy.get('#desktop-tree-info').should('not.exist');
});
});
29 changes: 29 additions & 0 deletions doc/examples/trees/186734captures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"captures": [
{
"id": 186734,
"lat": -4.881696978000001,
"lon": 38.37997515399998,
"time_created": "2019-03-15T06:46:40.000Z",
"image_url":
"https://treetracker-dev-images.s3.eu-central-1.amazonaws.com/2020.10.19.09.50.52_-5.508076904796398_38.98152805626448_28181c3e-e5b9-442b-8bb4-00de35de3de2_IMG_20201019_094643_486288846930987329.jpg"
},
{
"id": 186734,
"lat": -4.881696978000001,
"lon": 38.37997515399998,
"time_created": "2020-10-29T06:46:40.000Z",
"image_url":
"https://treetracker-production-images.s3.eu-central-1.amazonaws.com/2023.02.17.11.59.47_38.364922414000006_-122.51189396800001_a906ab31-5169-421c-8df3-be43f24d4d9c_IMG_20230217_111351_7976264471450881710.jpg"
},

{
"id": 186734,
"lat": -4.881696978000001,
"lon": 38.37997515399998,
"time_created": "2022-06-03T06:46:40.000Z",
"image_url":
"https://treetracker-production-images.s3.eu-central-1.amazonaws.com/2021.07.05.14.00.45_-3.2064076340000005_36.640772894_7b988c04-668e-48f5-b2e5-906f7d8374eb_IMG_20210705_132121_643781854.jpg"
}
]
}
75 changes: 75 additions & 0 deletions src/components/TreeCapturesTimeline/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
Timeline,
TimelineItem,
TimelineSeparator,
TimelineConnector,
TimelineContent,
TimelineDot,
timelineItemClasses,
} from '@mui/lab';
import { Box, Typography, useTheme, useMediaQuery } from '@mui/material';

function TreeCapturesTimeline({
captures = [],
imgWidth = '160px',
imgMaxHeight = '240px',
}) {
const theme = useTheme();
const smallerScreen = useMediaQuery(theme.breakpoints.down('md'));
return (
<Box>
<Timeline
position={smallerScreen ? 'right' : 'alternate'}
sx={{
[`& .${timelineItemClasses.root}:before`]: {
flex: smallerScreen ? 0 : undefined,
padding: smallerScreen ? 0 : undefined,
},
}}
>
{captures.map((capture, index) => (
<TimelineItem key={capture.id}>
<>
<TimelineSeparator>
<TimelineDot color="primary" />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent color="text.secondary">
<Typography
variant="h6"
sx={[
{
fontSize: [18, 20],
lineHeight: (t) => [t.spacing(7.25), t.spacing(8.5)],
},
]}
>
<time dateTime={capture.time_created}>
{new Date(capture.time_created).toLocaleDateString()}
</time>
</Typography>
<Box
sx={{
mt: 2,
}}
>
<img
src={capture.image_url}
alt={`Capture ${capture.id}`}
style={{
width: imgWidth,
maxHeight: imgMaxHeight,
objectFit: 'contain',
}}
/>
</Box>
</TimelineContent>
</>
</TimelineItem>
))}
</Timeline>
</Box>
);
}

export default TreeCapturesTimeline;
38 changes: 38 additions & 0 deletions src/components/TreeCapturesTimeline/test.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { mountWithTheme as mount } from 'models/test-utils';
import TreeCapturesTimeline from '.';

describe('Featured Planters Slider', () => {
it('it shows tree captures', () => {
// fake data
const mockData = {
captures: [
{
id: 186734,
lat: -4.881696978000001,
lon: 38.37997515399998,
time_created: '2019-03-15T06:46:40.000Z',
image_url:
'https://treetracker-dev-images.s3.eu-central-1.amazonaws.com/2020.10.19.09.50.52_-5.508076904796398_38.98152805626448_28181c3e-e5b9-442b-8bb4-00de35de3de2_IMG_20201019_094643_486288846930987329.jpg',
},
{
id: 186734,
lat: -4.881696978000001,
lon: 38.37997515399998,
time_created: '2020-10-29T06:46:40.000Z',
image_url:
'https://treetracker-production-images.s3.eu-central-1.amazonaws.com/2023.02.17.11.59.47_38.364922414000006_-122.51189396800001_a906ab31-5169-421c-8df3-be43f24d4d9c_IMG_20230217_111351_7976264471450881710.jpg',
},

{
id: 186734,
lat: -4.881696978000001,
lon: 38.37997515399998,
time_created: '2022-06-03T06:46:40.000Z',
image_url:
'https://treetracker-production-images.s3.eu-central-1.amazonaws.com/2021.07.05.14.00.45_-3.2064076340000005_36.640772894_7b988c04-668e-48f5-b2e5-906f7d8374eb_IMG_20210705_132121_643781854.jpg',
},
],
};
mount(<TreeCapturesTimeline captures={mockData.captures} />);
});
});
21 changes: 21 additions & 0 deletions src/mocks/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import leader from '../../doc/examples/countries/leader.json';
import grower from '../../doc/examples/growers/100.json';
import organization from '../../doc/examples/organizations/1.json';
import species from '../../doc/examples/species/1.json';
import treeCaptures from '../../doc/examples/trees/186734captures.json';

const trees = { trees: [mockTree, mockTree, mockTree] };
const host = process.env.NEXT_PUBLIC_API || '';
Expand All @@ -17,10 +18,30 @@ const handlers = [
res(ctx.status(200, 'success'), ctx.json(mockTree)),
),

rest.get(`${host}/trees/:id/captures`, (req, res, ctx) =>
res(ctx.status(200, 'success'), ctx.json(treeCaptures)),
),

rest.get(`${host}/trees*`, (req, res, ctx) =>
res(ctx.status(200, 'success'), ctx.json(trees)),
),

rest.get(`${host}/v2/trees/featured`, (req, res, ctx) =>
res(ctx.status(200, 'success'), ctx.json(trees)),
),

rest.get(`${host}/v2/trees/:id`, (req, res, ctx) =>
res(ctx.status(200, 'success'), ctx.json(mockTree)),
),

rest.get(`${host}/v2/trees/:id/captures`, (req, res, ctx) =>
res(ctx.status(200, 'success'), ctx.json(treeCaptures)),
),

rest.get(`${host}/v2/trees*`, (req, res, ctx) =>
res(ctx.status(200, 'success'), ctx.json(trees)),
),

rest.get(`${host}/growers/featured`, (req, res, ctx) =>
res(
ctx.status(200, 'success'),
Expand Down
Loading
Loading