Skip to content

Commit

Permalink
artifact choice
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisinajar committed Feb 25, 2025
1 parent 41329b6 commit 96afdcf
Show file tree
Hide file tree
Showing 18 changed files with 3,893 additions and 109 deletions.
10 changes: 10 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
['@babel/preset-react', { runtime: 'automatic' }],
'@babel/preset-typescript',
],
plugins: [
['@babel/plugin-transform-runtime', { regenerator: true }]
]
};
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/** @type {import('jest').Config} */
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
moduleNameMapper: {
'^src/(.*)$': '<rootDir>/src/$1',
},
transform: {
'^.+\\.(ts|tsx)$': 'babel-jest',
},
};
18 changes: 17 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
"start": "next start",
"lint": "next lint",
"generate": "graphql-codegen --config codegen.yml -r dotenv/config",
"ts": "tsc --noEmit --incremental"
"ts": "tsc --noEmit --incremental",
"test": "jest"
},
"dependencies": {
"@apollo/client": "^3.5.9",
"@babel/runtime": "^7.26.9",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@mui/base": "~5.0.0-beta.40",
Expand Down Expand Up @@ -39,15 +41,29 @@
"worker-timers": "^7.0.45"
},
"devDependencies": {
"@babel/core": "^7.26.9",
"@babel/plugin-transform-runtime": "^7.26.9",
"@babel/preset-env": "^7.26.9",
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.26.0",
"@graphql-codegen/cli": "2.6.2",
"@graphql-codegen/introspection": "2.1.1",
"@graphql-codegen/typescript": "2.4.5",
"@graphql-codegen/typescript-operations": "2.3.2",
"@graphql-codegen/typescript-react-apollo": "3.2.8",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "14",
"@testing-library/user-event": "^14.6.1",
"@types/jest": "^29.5.14",
"@types/node": "17.0.18",
"@types/react": "~18.2.59",
"babel-jest": "^29.7.0",
"eslint": "8.9.0",
"eslint-config-next": "12.0.10",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"ts-jest": "^29.2.6",
"tslint": "^6.1.3",
"typescript": "4.5.5"
}
Expand Down
36 changes: 36 additions & 0 deletions src/admin/generate-artifact.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
mutation GenerateArtifact($id: ID!, $level: Float!) {
generateArtifact(id: $id, level: $level) {
id
hero {
id
pendingArtifact {
id
owner
name
level
attributes {
namePrefix {
type
magnitude
}
namePostfix {
type
magnitude
}
titlePrefix {
type
magnitude
}
titlePostfix {
type
magnitude
}
bonusAffixes {
type
magnitude
}
}
}
}
}
}
62 changes: 62 additions & 0 deletions src/admin/generate-artifact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React, { useState } from "react";

import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import { useSnackbar } from "notistack";

import { useGenerateArtifactMutation, AdminAccountQuery } from "src/generated/graphql";

type GenerateArtifactProps = {
account: AdminAccountQuery["account"];
};

export function GenerateArtifact({ account }: GenerateArtifactProps): JSX.Element {
const [level, setLevel] = useState("1");
const { enqueueSnackbar } = useSnackbar();
const [generateArtifact] = useGenerateArtifactMutation();

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
await generateArtifact({
variables: {
id: account.id,
level: parseFloat(level),
},
});
enqueueSnackbar("Artifact generated successfully", { variant: "success" });
} catch (error) {
enqueueSnackbar(error instanceof Error ? error.message : "Failed to generate artifact", { variant: "error" });
}
};

return (
<Box component="form" onSubmit={handleSubmit} sx={{ maxWidth: 400, mb: 4 }}>
<Typography variant="h6" gutterBottom>Generate Test Artifact</Typography>

<TextField
fullWidth
label="Artifact Level"
type="number"
value={level}
onChange={(e) => setLevel(e.target.value)}
margin="normal"
required
inputProps={{ min: "1", step: "1" }}
helperText="The level of the artifact to generate"
/>

<Button
type="submit"
variant="contained"
color="primary"
fullWidth
sx={{ mt: 2 }}
>
Generate Artifact
</Button>
</Box>
);
}
2 changes: 2 additions & 0 deletions src/admin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { SetSkill } from "./set-skill";
import { AddLevels } from "./add-levels";
import { BanToggle } from "./ban-toggle";
import { DeleteAccount } from "./delete-account";
import { GenerateArtifact } from "./generate-artifact";

export default function AdminPage(): JSX.Element {
const [showData, setShowData] = useState<boolean>(false);
Expand Down Expand Up @@ -80,6 +81,7 @@ export default function AdminPage(): JSX.Element {
<br />
<br />
<br />
{account && <GenerateArtifact account={account} />}
{account && <CreateItem account={account} />}
{account && <GiveGold account={account} />}
{account?.hero && <SetSkill hero={account.hero} />}
Expand Down
50 changes: 50 additions & 0 deletions src/components/artifact-selection-box.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from "react";

import Typography from "@mui/material/Typography";
import Paper from "@mui/material/Paper";

import { ArtifactItem } from "src/generated/graphql";
import { ArtifactModifiers } from "./artifact-modifiers";

type ArtifactSelectionBoxProps = {
artifact: ArtifactItem | null;
isSelected: boolean;
title: string;
onSelect: () => void;
};

export function ArtifactSelectionBox({
artifact,
isSelected,
title,
onSelect
}: ArtifactSelectionBoxProps): JSX.Element {
return (
<Paper
sx={{
flex: 1,
p: 2,
cursor: 'pointer',
transition: 'all 0.2s',
border: '2px solid',
borderColor: isSelected ? 'primary.main' : 'divider',
bgcolor: isSelected ? 'action.selected' : 'background.paper',
'&:hover': {
bgcolor: 'action.hover',
},
}}
elevation={isSelected ? 8 : 1}
onClick={onSelect}
>
<Typography variant="h6" gutterBottom>{title}</Typography>
{artifact ? (
<React.Fragment>
<Typography variant="subtitle1">{artifact.name}</Typography>
<ArtifactModifiers artifact={artifact} title={`${title} Stats`} />
</React.Fragment>
) : (
<Typography color="text.secondary">No artifact equipped</Typography>
)}
</Paper>
);
}
92 changes: 92 additions & 0 deletions src/components/chat/artifact-modal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from "react";
import { render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";
import { MockedProvider } from "@apollo/client/testing";
import { ArtifactModal } from "./artifact-modal";
import { MeDocument, ArtifactAttributeType } from "src/generated/graphql";

const mockArtifact = {
__typename: "ArtifactItem" as const,
id: "test-id",
owner: "test-owner",
name: "Test Artifact",
level: 1,
attributes: {
__typename: "ArtifactAttributes" as const,
namePrefix: { __typename: "ArtifactAttribute" as const, type: ArtifactAttributeType.BonusPhysicalDamage, magnitude: 1 },
namePostfix: { __typename: "ArtifactAttribute" as const, type: ArtifactAttributeType.BonusHealth, magnitude: 1 },
bonusAffixes: [],
titlePrefix: null,
titlePostfix: null,
},
};

const mocks = [
{
request: {
query: MeDocument,
},
result: {
data: {
me: {
account: {
hero: {
equipment: {
artifact: {
...mockArtifact,
id: "current-id",
name: "Current Artifact",
},
},
},
},
},
},
},
},
];

describe("ArtifactModal", () => {
it("renders both artifacts and allows selection", async () => {
const user = userEvent.setup();
const { getByText } = render(
<MockedProvider mocks={mocks}>
<ArtifactModal artifact={mockArtifact} />
</MockedProvider>
);

// Check that both artifacts are rendered
expect(getByText("Current Artifact")).toBeInTheDocument();
expect(getByText("Test Artifact")).toBeInTheDocument();

// Continue button should be disabled initially
const continueButton = getByText("Continue with Selected");
expect(continueButton).toBeDisabled();

// Select new artifact
await user.click(getByText("Test Artifact"));
expect(continueButton).toBeEnabled();

// Open confirmation dialog
await user.click(continueButton);
expect(getByText("Confirm Your Choice")).toBeInTheDocument();
expect(getByText(/Are you sure you want to keep the new artifact/)).toBeInTheDocument();
});

it("shows warning message in confirmation dialog", async () => {
const user = userEvent.setup();
const { getByText } = render(
<MockedProvider mocks={mocks}>
<ArtifactModal artifact={mockArtifact} />
</MockedProvider>
);

// Select new artifact and open confirmation
await user.click(getByText("Test Artifact"));
await user.click(getByText("Continue with Selected"));

// Check warning message
expect(getByText("This action cannot be undone.")).toBeInTheDocument();
});
});
Loading

0 comments on commit 96afdcf

Please sign in to comment.