-
Notifications
You must be signed in to change notification settings - Fork 1
merge walker #13
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
Open
JohnDaWalka
wants to merge
14
commits into
sourcery-ai:sourcery-ai/issue-1
Choose a base branch
from
JohnDaWalka:main
base: sourcery-ai/issue-1
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+752
−4
Open
merge walker #13
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
3f875c2
Merge pull request #7 from sourcery-ai/sourcery-ai/issue-1
brendanator 73525f3
feat: Implement Advent of Code CLI
sourcery-ai[bot] 7581399
Address review by @brendanator
sourcery-ai[bot] a5f742b
Merge pull request #8 from sourcery-ai/sourcery-ai/issue-2
brendanator 6835738
CI: Auto-merge Sourcery AI bot PRs (#9)
sourcery-ai[bot] 38a3a88
CI: Add workflow to create Advent of Code puzzle issues (#10)
sourcery-ai[bot] 7f682d7
Add workflow to submit Advent of Code solutions (#12)
sourcery-ai[bot] ce26e94
Integrate code into GitHub project
JohnDaWalka daf4bb2
Merge pull request #1 from JohnDaWalka/integrate-code
JohnDaWalka 83d2870
Update README.md
JohnDaWalka 6849db6
e496043
Add `actions/checkout@v4` step and update `GH_TOKEN` in GitHub workflows
JohnDaWalka 2a720cb
Add steps to merge `develop` into `main` branch in GitHub Actions wor…
JohnDaWalka 6c8fe55
Add Poker Coach UI implementation and tests
JohnDaWalka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
name: Create Puzzle Issue | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
year: | ||
required: true | ||
type: number | ||
description: "The year of the puzzle" | ||
day: | ||
required: true | ||
type: number | ||
description: "The day of the puzzle" | ||
part: | ||
required: true | ||
type: number | ||
description: "The part of the puzzle (1 or 2)" | ||
|
||
permissions: | ||
issues: write | ||
|
||
jobs: | ||
create-issue: | ||
runs-on: ubuntu-latest | ||
env: | ||
GH_TOKEN: ${{ secrets.GH_TOKEN }} | ||
steps: | ||
- name: Check out repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Create puzzle issue | ||
id: create-issue | ||
run: | | ||
ISSUE_URL=$(gh issue create \ | ||
--title "Advent of code - ${{ inputs.year }} day ${{ inputs.day }} part ${{ inputs.part }}" \ | ||
--body "Write solution in \`puzzles/year_${{ inputs.year }}/day_${{ inputs.day }}/solution.py\`, and write tests in \`puzzles/year_${{ inputs.year }}/day_${{ inputs.day }}/test_solution.py\` using relative imports") | ||
echo "issue_url=${ISSUE_URL}" >> $GITHUB_OUTPUT | ||
|
||
- name: Add sourcery comment | ||
run: | | ||
gh issue comment "${ISSUE_URL}" --body "@sourcery-ai develop - you can read the puzzle statement with \`uv run advent_of_code.py read ${{ inputs.year }} ${{ inputs.day }} ${{ inputs.part }}\`. Run the solution on \`puzzles/year_${{ inputs.year }}/day_${{ inputs.day }}/input.txt\` and write answer to \`puzzles/year_${{ inputs.year }}/day_${{ inputs.day }}/answer_part${{ inputs.part }}.txt\`" | ||
env: | ||
ISSUE_URL: ${{ steps.create-issue.outputs.issue_url }} | ||
|
||
- name: Merge develop into main | ||
run: | | ||
git fetch origin | ||
git checkout main | ||
git merge develop | ||
gh pr merge --squash --auto --delete-branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: Merge Repos | ||
|
||
on: | ||
repository_dispatch: | ||
types: [merge-repos] | ||
|
||
permissions: | ||
contents: write | ||
|
||
jobs: | ||
merge-repos: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check out target repository | ||
uses: actions/checkout@v4 | ||
with: | ||
repository: ${{ github.event.client_payload.target_repo }} | ||
token: ${{ secrets.GH_TOKEN }} | ||
|
||
- name: Merge source repository | ||
run: | | ||
git remote add source https://github.com/${{ github.event.client_payload.source_repo }}.git | ||
git fetch source | ||
git merge source/main --allow-unrelated-histories | ||
|
||
- name: Push changes to target repository | ||
run: | | ||
git push origin main |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: Auto-merge Sourcery AI Bot PRs | ||
|
||
on: | ||
pull_request: | ||
types: [opened, synchronize, reopened] | ||
|
||
permissions: | ||
contents: write | ||
|
||
env: | ||
GH_TOKEN: ${{ secrets.GH_TOKEN }} | ||
|
||
jobs: | ||
merge-sourcery-pr: | ||
runs-on: ubuntu-latest | ||
if: github.event.pull_request.user.login == 'sourcery-ai[bot]' | ||
steps: | ||
- name: Check out repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Merge Pull Request | ||
run: | | ||
gh pr merge "${{ github.event.pull_request.number }}" \ | ||
--squash \ | ||
--auto \ | ||
--delete-branch \ | ||
--repo "${{ github.repository }}" | ||
|
||
- name: Merge develop into main | ||
run: | | ||
git fetch origin | ||
git checkout main | ||
git merge develop | ||
gh pr merge --squash --auto --delete-branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
name: Submit Advent of Code Solution | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
paths: | ||
- 'puzzles/year_*/day_*/answer_part*.txt' | ||
workflow_dispatch: | ||
|
||
permissions: | ||
contents: write | ||
issues: write | ||
repository-dispatch: write | ||
|
||
env: | ||
AOC_SESSION: ${{ secrets.AOC_SESSION }} | ||
GH_TOKEN: ${{ secrets.GH_TOKEN }} | ||
|
||
jobs: | ||
submit: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Set up uv | ||
uses: astral-sh/setup-uv@v4 | ||
|
||
- name: Install dependencies | ||
run: uv sync | ||
|
||
- name: Get changed files | ||
id: changed-files | ||
uses: tj-actions/changed-files@v42 | ||
with: | ||
files: puzzles/year_*/day_*/answer_part*.txt | ||
|
||
- name: Extract year, day and part from filename | ||
id: extract-info | ||
run: | | ||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | ||
echo "No file changes to process" | ||
exit 0 | ||
fi | ||
|
||
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do | ||
if [[ $file =~ puzzles/year_([0-9]+)/day_([0-9]+)/answer_part([12]).txt ]]; then | ||
echo "year=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT | ||
echo "day=${BASH_REMATCH[2]}" >> $GITHUB_OUTPUT | ||
echo "part=${BASH_REMATCH[3]}" >> $GITHUB_OUTPUT | ||
fi | ||
done | ||
|
||
- name: Submit solution | ||
id: submit | ||
if: steps.extract-info.outputs.year != '' | ||
continue-on-error: true | ||
run: | | ||
output=$(uv run advent_of_code.py submit ${{ steps.extract-info.outputs.year }} ${{ steps.extract-info.outputs.day }} ${{ steps.extract-info.outputs.part }}) | ||
echo "submission_result=$output" >> $GITHUB_OUTPUT | ||
|
||
- name: Update results in README | ||
if: steps.extract-info.outputs.year != '' | ||
run: uv run advent_of_code.py update-results ${{ steps.extract-info.outputs.year }} | ||
|
||
- name: Download part 2 if part 1 was correct | ||
id: download-part2 | ||
if: steps.extract-info.outputs.part == '1' && steps.submit.outcome == 'success' | ||
run: | | ||
file_path=$(uv run advent_of_code.py download ${{ steps.extract-info.outputs.year }} ${{ steps.extract-info.outputs.day }}) | ||
echo "file_path=$file_path" >> $GITHUB_OUTPUT | ||
|
||
- name: Configure Git | ||
run: | | ||
git config --global user.name 'github-actions[bot]' | ||
git config --global user.email 'github-actions[bot]@users.noreply.github.com' | ||
|
||
- name: Commit and push changes | ||
run: | | ||
git add puzzles/year_${{ steps.extract-info.outputs.year }}/day_${{ steps.extract-info.outputs.day }} | ||
git add README.md | ||
git commit -m "Update puzzle files for year ${{ steps.extract-info.outputs.year }} day ${{ steps.extract-info.outputs.day }}" | ||
git push | ||
|
||
- name: Trigger create-puzzle-issue workflow | ||
if: steps.download-part2.outputs.file_path != '' | ||
uses: peter-evans/repository-dispatch@v2 | ||
with: | ||
token: ${{ env.GH_TOKEN }} | ||
event-type: create-puzzle-issue | ||
client-payload: '{"year": "${{ steps.extract-info.outputs.year }}", "day": "${{ steps.extract-info.outputs.day }}", "part": "2"}' | ||
|
||
- name: Merge develop into main | ||
run: | | ||
git fetch origin | ||
git checkout main | ||
git merge develop | ||
gh pr merge --squash --auto --delete-branch |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
import codecs | ||
import os | ||
import re | ||
from pathlib import Path | ||
from typing import Annotated, Optional | ||
|
||
import httpx | ||
import typer | ||
from bs4 import BeautifulSoup | ||
from markdownify import markdownify as md | ||
|
||
app = typer.Typer() | ||
|
||
|
||
def get_session() -> str: | ||
"""Get AOC session from environment variable.""" | ||
session = os.getenv("AOC_SESSION") | ||
if not session: | ||
raise typer.BadParameter("AOC_SESSION environment variable not set") | ||
return session | ||
|
||
|
||
def get_headers(session: str) -> dict[str, str]: | ||
"""Get request headers with session cookie.""" | ||
return { | ||
"Cookie": f"session={session}", | ||
"User-Agent": "github.com/sourcery-ai/autonomous-advent-of-code", | ||
} | ||
|
||
|
||
def rot13_encode(text: str) -> str: | ||
"""ROT13 encode text.""" | ||
return codecs.encode(text, "rot13") | ||
|
||
|
||
def rot13_decode(text: str) -> str: | ||
"""ROT13 decode text.""" | ||
return codecs.decode(text, "rot13") | ||
|
||
|
||
def ensure_puzzle_dir(year: int, day: int) -> Path: | ||
"""Ensure puzzle directory exists and return path.""" | ||
puzzle_dir = Path(f"puzzles/year_{year}/day_{day:02d}") | ||
puzzle_dir.mkdir(parents=True, exist_ok=True) | ||
return puzzle_dir | ||
|
||
|
||
def extract_parts(html: str) -> tuple[str, Optional[str]]: | ||
"""Extract puzzle parts from HTML content.""" | ||
soup = BeautifulSoup(html, "html.parser") | ||
article = soup.find("article") | ||
if not article: | ||
raise typer.BadParameter("Could not find puzzle content") | ||
|
||
# Convert to markdown and split on "--- Part Two ---" | ||
markdown = md(str(article)) | ||
parts = markdown.split("--- Part Two ---") | ||
|
||
part1 = parts[0].strip() | ||
part2 = parts[1].strip() if len(parts) > 1 else None | ||
|
||
return part1, part2 | ||
|
||
|
||
@app.command() | ||
def download( | ||
year: Annotated[int, typer.Argument(help="Year of puzzle")], | ||
day: Annotated[int, typer.Argument(help="Day of puzzle")], | ||
) -> None: | ||
"""Download puzzle content and input.""" | ||
session = get_session() | ||
headers = get_headers(session) | ||
|
||
# Fetch puzzle content | ||
url = f"https://adventofcode.com/{year}/day/{day}" | ||
response = httpx.get(url, headers=headers, follow_redirects=True) | ||
response.raise_for_status() | ||
|
||
# Extract parts | ||
part1, part2 = extract_parts(response.text) | ||
|
||
# Create puzzle directory | ||
puzzle_dir = ensure_puzzle_dir(year, day) | ||
|
||
# Save part 1 | ||
part1_path = puzzle_dir / "question_part1_rot13.md" | ||
part1_path.write_text(rot13_encode(part1)) | ||
|
||
# Save part 2 if it exists | ||
if part2: | ||
part2_path = puzzle_dir / "question_part2_rot13.md" | ||
combined = f"{part1}\n\n--- Part Two ---\n\n{part2}" | ||
part2_path.write_text(rot13_encode(combined)) | ||
|
||
# Fetch and save input | ||
input_url = f"{url}/input" | ||
input_response = httpx.get(input_url, headers=headers, follow_redirects=True) | ||
input_response.raise_for_status() | ||
|
||
input_path = puzzle_dir / "input.txt" | ||
input_path.write_text(input_response.text) | ||
|
||
print(2 if part2 else 1) | ||
|
||
|
||
@app.command() | ||
def read( | ||
year: Annotated[int, typer.Argument(help="Year of puzzle")], | ||
day: Annotated[int, typer.Argument(help="Day of puzzle")], | ||
part: Annotated[int, typer.Argument(help="Part number (1 or 2)")], | ||
) -> None: | ||
"""Read puzzle content.""" | ||
puzzle_dir = ensure_puzzle_dir(year, day) | ||
question_path = puzzle_dir / f"question_part{part}_rot13.md" | ||
|
||
if not question_path.exists(): | ||
raise typer.BadParameter(f"Question file not found: {question_path}") | ||
|
||
encoded_content = question_path.read_text() | ||
decoded_content = rot13_decode(encoded_content) | ||
print(decoded_content) | ||
|
||
|
||
@app.command() | ||
def submit( | ||
year: Annotated[int, typer.Argument(help="Year of puzzle")], | ||
day: Annotated[int, typer.Argument(help="Day of puzzle")], | ||
part: Annotated[int, typer.Argument(help="Part number (1 or 2)")], | ||
) -> int: | ||
"""Submit answer for puzzle.""" | ||
puzzle_dir = ensure_puzzle_dir(year, day) | ||
answer_path = puzzle_dir / f"answer_part{part}.txt" | ||
|
||
if not answer_path.exists(): | ||
raise typer.BadParameter(f"Answer file not found: {answer_path}") | ||
|
||
session = get_session() | ||
headers = get_headers(session) | ||
|
||
answer = answer_path.read_text().strip() | ||
|
||
# Submit answer | ||
url = f"https://adventofcode.com/{year}/day/{day}/answer" | ||
data = {"level": str(part), "answer": answer} | ||
response = httpx.post(url, headers=headers, data=data, follow_redirects=True) | ||
response.raise_for_status() | ||
|
||
# Extract response content | ||
soup = BeautifulSoup(response.text, "html.parser") | ||
article = soup.find("article") | ||
if not article: | ||
raise typer.BadParameter("Could not find response content") | ||
|
||
result_markdown = md(str(article)) | ||
|
||
# Save response | ||
result_path = puzzle_dir / f"result_part{part}.md" | ||
result_path.write_text(result_markdown) | ||
|
||
# Print response | ||
print(result_markdown) | ||
|
||
return 0 if "That's the right answer" in result_markdown else 1 | ||
|
||
|
||
@app.command() | ||
def update_results( | ||
year: Annotated[int, typer.Argument(help="Year of puzzle")], | ||
) -> None: | ||
"""Update results table in README.""" | ||
results: dict[int, dict[int, str]] = {} | ||
puzzles_dir = Path(f"puzzles/year_{year}") | ||
|
||
if not puzzles_dir.exists(): | ||
raise typer.BadParameter(f"No puzzles found for year {year}") | ||
|
||
# Collect results for each day | ||
for day_dir in sorted(puzzles_dir.glob("day_*")): | ||
day = int(day_dir.name.replace("day_", "")) | ||
results[day] = {1: "NOT_SUBMITTED", 2: "NOT_SUBMITTED"} | ||
|
||
for part in [1, 2]: | ||
answer_file = day_dir / f"answer_part{part}.txt" | ||
result_file = day_dir / f"result_part{part}.md" | ||
|
||
if answer_file.exists() and result_file.exists(): | ||
result_content = result_file.read_text() | ||
if "That's the right answer" in result_content: | ||
results[day][part] = "CORRECT" | ||
else: | ||
results[day][part] = "INCORRECT" | ||
|
||
# Generate results table | ||
table_lines = [ | ||
"| Day | Part 1 | Part 2 |", | ||
"|-----|--------|--------|", | ||
] | ||
|
||
max_day = max(results.keys()) | ||
for day in range(1, max_day + 1): | ||
day_results = results.get(day, {1: "NOT_SUBMITTED", 2: "NOT_SUBMITTED"}) | ||
symbols = { | ||
"NOT_SUBMITTED": "", | ||
"INCORRECT": "❌", | ||
"CORRECT": "✅", | ||
} | ||
table_lines.append( | ||
f"| {day:2d} | {symbols[day_results[1]]:8} | {symbols[day_results[2]]:8} |" | ||
) | ||
|
||
table = "\n".join(table_lines) | ||
|
||
# Update README.md | ||
readme_path = Path("README.md") | ||
if not readme_path.exists(): | ||
readme_path.write_text("") | ||
|
||
content = readme_path.read_text() | ||
pattern = f"<!-- begin-results: {year} -->.*?<!-- end-results: {year} -->" | ||
replacement = f"<!-- begin-results: {year} -->\n{table}\n<!-- end-results: {year} -->" | ||
|
||
if re.search(pattern, content, re.DOTALL): | ||
new_content = re.sub(pattern, replacement, content, flags=re.DOTALL) | ||
else: | ||
new_content = f"{content}\n\n{replacement}\n" | ||
|
||
readme_path.write_text(new_content) | ||
|
||
|
||
if __name__ == "__main__": | ||
app() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import tkinter as tk | ||
from tkinter import messagebox | ||
|
||
class PokerCoachUI: | ||
def __init__(self, root): | ||
self.root = root | ||
self.root.title("Poker Coach") | ||
|
||
self.create_widgets() | ||
|
||
def create_widgets(self): | ||
self.hand_label = tk.Label(self.root, text="Enter your hand:") | ||
self.hand_label.pack() | ||
|
||
self.hand_entry = tk.Entry(self.root) | ||
self.hand_entry.pack() | ||
|
||
self.analyze_button = tk.Button(self.root, text="Analyze Hand", command=self.analyze_hand) | ||
self.analyze_button.pack() | ||
|
||
self.result_label = tk.Label(self.root, text="") | ||
self.result_label.pack() | ||
|
||
def analyze_hand(self): | ||
hand = self.hand_entry.get() | ||
if not hand: | ||
messagebox.showerror("Error", "Please enter a hand.") | ||
return | ||
|
||
# Placeholder for hand analysis logic | ||
result = f"Analysis result for hand: {hand}" | ||
|
||
self.result_label.config(text=result) | ||
|
||
if __name__ == "__main__": | ||
root = tk.Tk() | ||
app = PokerCoachUI(root) | ||
root.mainloop() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import os | ||
from pathlib import Path | ||
from typing import Generator | ||
|
||
import pytest | ||
from typer.testing import CliRunner | ||
|
||
from advent_of_code import app, extract_parts, rot13_decode, rot13_encode | ||
|
||
runner = CliRunner() | ||
|
||
|
||
@pytest.fixture | ||
def temp_puzzle_dir(tmp_path: Path) -> Generator[Path, None, None]: | ||
"""Create temporary puzzle directory.""" | ||
original_cwd = os.getcwd() | ||
os.chdir(tmp_path) | ||
yield tmp_path | ||
os.chdir(original_cwd) | ||
|
||
|
||
def test_rot13_encode_decode() -> None: | ||
"""Test ROT13 encoding and decoding.""" | ||
text = "Hello, World!" | ||
encoded = rot13_encode(text) | ||
assert encoded != text | ||
decoded = rot13_decode(encoded) | ||
assert decoded == text | ||
|
||
|
||
def test_extract_parts_part1_only() -> None: | ||
"""Test extracting only part 1 from HTML.""" | ||
html = """ | ||
<article> | ||
<h2>--- Day 1: Test ---</h2> | ||
<p>Part 1 content</p> | ||
</article> | ||
""" | ||
part1, part2 = extract_parts(html) | ||
assert "Part 1 content" in part1 | ||
assert part2 is None | ||
|
||
|
||
def test_extract_parts_both_parts() -> None: | ||
"""Test extracting both parts from HTML.""" | ||
html = """ | ||
<article> | ||
<h2>--- Day 1: Test ---</h2> | ||
<p>Part 1 content</p> | ||
<h2>--- Part Two ---</h2> | ||
<p>Part 2 content</p> | ||
</article> | ||
""" | ||
part1, part2 = extract_parts(html) | ||
assert "Part 1 content" in part1 | ||
assert "Part 2 content" in part2 | ||
|
||
|
||
def test_download_command_no_session(temp_puzzle_dir: Path) -> None: | ||
"""Test download command fails without session.""" | ||
result = runner.invoke(app, ["download", "2023", "1"]) | ||
assert result.exit_code == 2 | ||
assert "AOC_SESSION environment variable not set" in result.stdout | ||
|
||
|
||
def test_read_command_missing_file(temp_puzzle_dir: Path) -> None: | ||
"""Test read command fails with missing file.""" | ||
result = runner.invoke(app, ["read", "2023", "1", "1"]) | ||
assert result.exit_code != 0 | ||
assert "Question file not found" in result.stdout | ||
|
||
|
||
def test_submit_command_missing_answer(temp_puzzle_dir: Path) -> None: | ||
"""Test submit command fails with missing answer file.""" | ||
result = runner.invoke(app, ["submit", "2023", "1", "1"]) | ||
assert result.exit_code != 0 | ||
assert "Answer file not found" in result.stdout | ||
|
||
|
||
def test_update_results_command_no_puzzles(temp_puzzle_dir: Path) -> None: | ||
"""Test update-results command fails with no puzzles.""" | ||
result = runner.invoke(app, ["update-results", "2023"]) | ||
assert result.exit_code != 0 | ||
assert "No puzzles found for year 2023" in result.stdout | ||
|
||
|
||
def test_update_results_command_creates_table(temp_puzzle_dir: Path) -> None: | ||
"""Test update-results command creates results table.""" | ||
# Create puzzle directory with some results | ||
puzzle_dir = temp_puzzle_dir / "puzzles" / "year_2023" / "day_01" | ||
puzzle_dir.mkdir(parents=True) | ||
|
||
# Create answer and result files | ||
(puzzle_dir / "answer_part1.txt").write_text("42") | ||
(puzzle_dir / "result_part1.md").write_text("That's the right answer!") | ||
|
||
result = runner.invoke(app, ["update-results", "2023"]) | ||
assert result.exit_code == 0 | ||
|
||
# Check README.md was created with table | ||
readme = Path("README.md").read_text() | ||
assert "| Day | Part 1 | Part 2 |" in readme | ||
assert "| 1 | ✅" in readme |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import pytest | ||
import tkinter as tk | ||
from poker_coach.ui import PokerCoachUI | ||
|
||
@pytest.fixture | ||
def app(): | ||
root = tk.Tk() | ||
app = PokerCoachUI(root) | ||
yield app | ||
root.destroy() | ||
|
||
def test_initial_state(app): | ||
assert app.hand_entry.get() == "" | ||
assert app.result_label.cget("text") == "" | ||
|
||
def test_analyze_hand_empty(app): | ||
app.hand_entry.delete(0, tk.END) | ||
app.analyze_hand() | ||
assert app.result_label.cget("text") == "" | ||
|
||
def test_analyze_hand_valid(app): | ||
app.hand_entry.insert(0, "AS KS QS JS TS") | ||
app.analyze_hand() | ||
assert "Analysis result for hand: AS KS QS JS TS" in app.result_label.cget("text") |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.