Skip to content

Commit

Permalink
feat(arcgis): support arcgis content (#335)
Browse files Browse the repository at this point in the history
  • Loading branch information
mspivak-actionengine authored Jan 16, 2024
1 parent dd8a771 commit e531f73
Show file tree
Hide file tree
Showing 28 changed files with 1,288 additions and 289 deletions.
28 changes: 28 additions & 0 deletions __mocks__/@esri/arcgis-rest-portal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const mockContent = {
items: [
{
id: "new-york",
name: "NewYork.slpk",
url: "https://123.com",
created: 123456,
type: "Scene Service",
typeKeywords: "This is a Hosted Service",
title: "New York",
token: "token-https://123.com",
},
{
id: "turanga-library",
name: "TurangaLibrary.slpk",
url: "https://456.com",
created: 123457,
type: "Scene Service",
typeKeywords: "This is a Hosted Service",
title: "Turanga Library",
token: "token-https://456.com",
},
],
};

export const getUserContent = async (authentication) => {
return mockContent;
};
27 changes: 16 additions & 11 deletions __mocks__/@esri/arcgis-rest-request.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
const mockEmailExpected = "[email protected]";
const mockSessionExpected = '{"usermail": "usermail"}';
const mockTokenExpectedPrefix = "token-";

const session = {
usermail: mockEmailExpected,
serialize: () => {
return mockSessionExpected;
},
getUser: async () => {
return { email: mockEmailExpected };
},
getToken: async (url: string) => {
return mockTokenExpectedPrefix + url;
},
};

export class ArcGISIdentityManager {
static beginOAuth2 = async () => {
const session = {
usermail: mockEmailExpected,
serialize: () => {
return mockSessionExpected;
},
getUser: async () => {
return { email: mockEmailExpected };
},
};
return session;
};
static completeOAuth2 = async () => {
Expand All @@ -20,7 +25,7 @@ export class ArcGISIdentityManager {
static destroy = async () => {
return;
};
static deserialize = (session) => {
return { usermail: "usermail" };
static deserialize = () => {
return session;
};
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"dependencies": {
"@esri/arcgis-rest-auth": "^3.7.0",
"@esri/arcgis-rest-request": "^4.2.0",
"@esri/arcgis-rest-portal": "^4.4.0",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/react-fontawesome": "^0.1.17",
Expand Down
4 changes: 3 additions & 1 deletion src/components/common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ export const PanelContent = styled.div`
export const PanelHorizontalLine = styled.div<{
top?: number;
bottom?: number;
left?: number;
right?: number;
}>`
margin: ${({ top = 24, bottom = 16 }) => `${top}px 16px ${bottom}px 16px`};
margin: ${({ top = 24, bottom = 16, left = 16, right = 16 }) => `${top}px ${right}px ${bottom}px ${left}px`};
border: 1px solid ${({ theme }) => theme.colors.mainHiglightColorInverted};
border-radius: 1px;
background: ${({ theme }) => theme.colors.mainHiglightColorInverted};
Expand Down
21 changes: 20 additions & 1 deletion src/components/expand-icon/expand-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ const IconButton = styled.div<{
}
`;

const IconButtonContainer = styled.div<{
width: number;
height: number;
}>`
display: flex;
justify-content: center;
align-items: center;
width: ${({ width }) => `${width}px`}}
height: ${({ height }) => `${height}px`}}
`;

type ExpandIconProps = {
/** expanded/collapsed */
expandState: ExpandState;
Expand All @@ -56,6 +67,10 @@ type ExpandIconProps = {
fillExpanded?: string;
/** icon color for collapsed state */
fillCollapsed?: string;
/** Width of the icon */
width?: number;
/** Height of the icon */
height?: number;
/** click event handler */
onClick: (e: SyntheticEvent) => void;
};
Expand All @@ -65,6 +80,8 @@ export const ExpandIcon = ({
fillExpanded,
fillCollapsed,
collapseDirection = CollapseDirection.top,
width = 8,
height = 12,
}: ExpandIconProps) => {
return (
<IconButton
Expand All @@ -74,7 +91,9 @@ export const ExpandIcon = ({
fillCollapsed={fillCollapsed}
onClick={onClick}
>
<ChevronIcon />
<IconButtonContainer width={width} height={height}>
<ChevronIcon />
</IconButtonContainer>
</IconButton>
);
};
150 changes: 150 additions & 0 deletions src/components/layers-panel/arcgis-control-panel.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { renderWithThemeProviders } from "../../utils/testing-utils/render-with-theme";
import { screen, within } from "@testing-library/react";
import { setupStore } from "../../redux/store";
import { ArcGisControlPanel } from "./arcgis-control-panel";
import userEvent from "@testing-library/user-event";
import {
arcGisLogin,
arcGisLogout,
} from "../../redux/slices/arcgis-auth-slice";
import {
getAuthenticatedUser,
arcGisRequestLogin,
arcGisCompleteLogin,
arcGisRequestLogout,
} from "../../utils/arcgis";

jest.mock("../../utils/arcgis");

const getAuthenticatedUserMock =
getAuthenticatedUser as unknown as jest.Mocked<any>;
const arcGisRequestLoginMock =
arcGisRequestLogin as unknown as jest.Mocked<any>;
const arcGisCompleteLoginMock =
arcGisCompleteLogin as unknown as jest.Mocked<any>;
const arcGisRequestLogoutMock =
arcGisRequestLogout as unknown as jest.Mocked<any>;

const EMAIL_EXPECTED = "[email protected]";
let storageUserinfo = "";

const onArcGisImportMock = jest.fn();

const callRender = (renderFunc, props = {}, store = setupStore()) => {
return renderFunc(
<ArcGisControlPanel onArcGisImportClick={onArcGisImportMock} {...props} />,
store
);
};

describe("Layers Control Panel - ArcGIS auth", () => {
beforeAll(() => {
arcGisRequestLoginMock.mockImplementation(async () => {
storageUserinfo = EMAIL_EXPECTED;
return storageUserinfo;
});
arcGisCompleteLoginMock.mockImplementation(async () => {
return storageUserinfo;
});
arcGisRequestLogoutMock.mockImplementation(async () => {
storageUserinfo = "";
return storageUserinfo;
});
getAuthenticatedUserMock.mockImplementation(() => {
return storageUserinfo;
});
});

it("Should render ArcGIS Login button", async () => {
const store = setupStore();
// Let's Log out...
await store.dispatch(arcGisLogout());
const { container } = callRender(
renderWithThemeProviders,
undefined,
store
);
expect(container).toBeInTheDocument();
expect(arcGisRequestLogoutMock).toHaveBeenCalledTimes(1);

// We are in the "Logged out" state, so the "Log in" button should be there.
const loginButton = await screen.findByText("Login to ArcGIS");
expect(loginButton).toBeInTheDocument();
loginButton && userEvent.click(loginButton);
expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1);

const importButton = screen.queryByText("Import from ArcGIS");
expect(importButton).not.toBeInTheDocument();
});

it("Should render ArcGIS Import and Logout buttons", async () => {
const store = setupStore();
// Let's Log in...
await store.dispatch(arcGisLogin());
const { container } = callRender(
renderWithThemeProviders,
undefined,
store
);
expect(container).toBeInTheDocument();
expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1);

// We are in the "Logged in" state, so the "Log in" button should NOT be there.
const importButton = await screen.findByText("Import from ArcGIS");
expect(importButton).toBeInTheDocument();

const logoutUserInfo = await screen.findByText(EMAIL_EXPECTED);
expect(logoutUserInfo).toBeInTheDocument();

const loginButton = screen.queryByText("Login to ArcGIS");
expect(loginButton).not.toBeInTheDocument();
});

it("Should respond to action on the ArcGIS Login button", async () => {
const store = setupStore();
// Let's Log out...
await store.dispatch(arcGisLogout());
const { container } = callRender(
renderWithThemeProviders,
undefined,
store
);
expect(container).toBeInTheDocument();

const loginButton = screen.getByText("Login to ArcGIS");
loginButton && userEvent.click(loginButton);
expect(arcGisRequestLoginMock).toHaveBeenCalledTimes(1);

const importButton = await screen.findByText("Import from ArcGIS");
expect(importButton).toBeInTheDocument();

const loginButtonHidden = screen.queryByText("Login to ArcGIS");
expect(loginButtonHidden).not.toBeInTheDocument();
});

it("Should respond to action on ArcGIS Logout button", async () => {
const store = setupStore();
// Let's Log in...
await store.dispatch(arcGisLogin());
callRender(
renderWithThemeProviders,
undefined,
store
);

const logoutButton = await screen.findByTestId("userinfo-button");
logoutButton && userEvent.click(logoutButton);

const modalDialog = await screen.findByTestId("modal-dialog-content");
expect(modalDialog).toContainHTML("Are you sure you want to log out?");

const cancelButton = within(modalDialog).getByText("Log out");
cancelButton && userEvent.click(cancelButton);

const modalDialogHidden = screen.queryByTestId("modal-dialog-content");
expect(modalDialogHidden).not.toBeInTheDocument();

const loginButton = await screen.findByText("Login to ArcGIS");
expect(loginButton).toBeInTheDocument();
});
});
Loading

0 comments on commit e531f73

Please sign in to comment.