Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
77 changes: 77 additions & 0 deletions .github/workflows/frontend-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Frontend Tests

on:
push:
branches: [ main ]
paths:
- "src/static/**"
- "package.json"
- "vitest.config.js"
- "playwright.config.js"
- ".github/workflows/frontend-tests.yaml"
pull_request:
branches: [ main ]
paths:
- "src/static/**"
- "package.json"
- "vitest.config.js"
- "playwright.config.js"
- ".github/workflows/frontend-tests.yaml"

jobs:
unit-tests:
name: Unit Tests (Vitest)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: src/static/package-lock.json

- run: npm ci
working-directory: src/static

- run: npm run test:unit
working-directory: src/static

visual-tests:
name: Visual Tests (Playwright)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: src/static/package-lock.json

- run: npm ci
working-directory: src/static

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium
working-directory: src/static

- name: Run visual tests
run: npm run test:visual
working-directory: src/static

- name: Upload screenshots on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: playwright-screenshots
path: src/static/tests/visual/test-results/
retention-days: 7

- name: Upload snapshot updates
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-snapshots
path: src/static/tests/visual/snapshots/
retention-days: 30
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ RUN pip3 install -r /tmp/requirements.txt

COPY patches/01_add_api_urls.patch /opt/venv/lib/python3.12/site-packages/
COPY patches/03_add_active_needs_renewal_status.patch /opt/venv/lib/python3.12/site-packages/
COPY patches/04_add_usage_chart.patch /opt/venv/lib/python3.12/site-packages/

RUN cd /opt/venv/lib/python3.12/site-packages && \
patch -p1 < 01_add_api_urls.patch && \
patch -p1 < 03_add_active_needs_renewal_status.patch
patch -p1 < 03_add_active_needs_renewal_status.patch && \
patch -p1 < 04_add_usage_chart.patch

# Final Image
FROM python:3.12-slim-bullseye
Expand All @@ -45,6 +47,11 @@ COPY src/bin/run_coldfront.sh /opt/venv/bin
# Update NERC's email templates
COPY src/email/ /opt/venv/lib/python3.12/site-packages/coldfront/templates/email/

# Add NERC usage chart static files
COPY src/static/chartjs/ /opt/venv/lib/python3.12/site-packages/coldfront/static/chartjs/
COPY src/static/css/ /opt/venv/lib/python3.12/site-packages/coldfront/static/css/
COPY src/static/js/ /opt/venv/lib/python3.12/site-packages/coldfront/static/js/

ENV PATH="/opt/venv/bin:$PATH"
ENV DJANGO_SETTINGS_MODULE="local_settings"

Expand Down
83 changes: 83 additions & 0 deletions patches/04_add_usage_chart.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
diff --git a/coldfront/core/allocation/templates/allocation/allocation_detail.html b/coldfront/core/allocation/templates/allocation/allocation_detail.html
index 369cf81..cfea375 100644
--- a/coldfront/core/allocation/templates/allocation/allocation_detail.html
+++ b/coldfront/core/allocation/templates/allocation/allocation_detail.html
@@ -173,6 +173,61 @@ Allocation Detail
</div>
</div>

+<!-- NERC Usage Chart -->
+<div class="card mb-3">

Copilot AI Mar 3, 2026

Copy link

Choose a reason for hiding this comment

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

The production template markup added in this patch does not give the SU costs card an id, but the JS (allocation_detail.js) expects an element with id="su-costs-card" (used for hide/show logic and tests). As-is, the card will not be hidden in the real page when there is no data, and the production DOM will diverge from the test fixture.

Suggestion: add id="su-costs-card" to the outer card element (or update the JS to target the actual element you render).

Suggested change
+<div class="card mb-3">
+<div id="su-costs-card" class="card mb-3">

Copilot uses AI. Check for mistakes.
+ <div class="card-header">
+ <h3 class="d-inline"><i class="fas fa-chart-bar" aria-hidden="true"></i> SU Costs</h3>
+ </div>
+ <div class="card-body">
+ <!-- Chart info header section -->
+ <div class="d-flex justify-content-between align-items-start mb-3 chart-info-header">
+ <div>
+ <h5 class="mb-1 font-weight-bold chart-title" id="chart-title">SU Cost - Cumulative</h5>
+ <p class="mb-0 text-muted small" id="chart-subtitle">Showing the cumulative cost for the last month</p>
+ </div>
+ </div>
+ <!-- Toolbar section -->
+ <div class="mb-3 d-flex justify-content-between align-items-center pb-3 chart-toolbar">
+ <div class="d-flex align-items-center">
+ <div class="btn-group toggle-btn-group-view" role="group" aria-label="Toggle view">
+ <button type="button" class="btn toggle-btn active" id="show-graph-btn">
+ <i class="fas fa-chart-line mr-1"></i> Graph
+ </button>
+ <button type="button" class="btn toggle-btn" id="show-table-btn">
+ <i class="fas fa-table mr-1"></i> Table
+ </button>
+ </div>
+ </div>
+ <div class="d-flex align-items-center">
+ <div class="btn-group toggle-btn-group-mode mr-3" role="group" aria-label="Data mode">
+ <button type="button" class="btn toggle-btn active" id="show-cumulative-btn">
+ Cumulative
+ </button>
+ <button type="button" class="btn toggle-btn" id="show-daily-btn">
+ Daily
+ </button>
+ </div>
+ <button type="button" class="btn export-csv-btn" id="export-csv-btn">
+ <i class="fas fa-download mr-1"></i> Export CSV
+ </button>
+ </div>
+ </div>
+ <div id="chart-view" style="position: relative; height: 500px; width: 100%;">
+ <canvas id="allocationUsageChart"></canvas>
+ </div>
+ <div id="table-view" class="table-responsive" style="display: none;">
+ <table id="allocationUsageTable" class="table table-bordered table-sm">
+ <thead>
+ <!-- Populated by JS -->
+ </thead>
+ <tbody>
+ <!-- Populated by JS -->
+ </tbody>
+ </table>
+ </div>
+ </div>
+</div>
+
{% if eulas %}
<div class="card mb-3">
<div class="card-header">
@@ -470,4 +525,13 @@ Allocation Detail
}
})
</script>
-{% endblock %}
\ No newline at end of file
+
+<!-- Load Chart.js for NERC usage visualization -->
+<script src="{% static 'chartjs/chart.min.js' %}"></script>
+
+<link rel="stylesheet" href="{% static 'css/chart_tooltip.css' %}">
+<link rel="stylesheet" href="{% static 'css/chart_controls.css' %}">
+<script src="{% static 'js/chart_utils.js' %}"></script>
+<script src="{% static 'js/chart_config.js' %}"></script>
+<script src="{% static 'js/chart_tooltip.js' %}"></script>
+<script src="{% static 'js/allocation_detail.js' %}"></script>
+{% endblock %}
61 changes: 61 additions & 0 deletions src/static/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Frontend Tests

How to run the chart and UI tests.

## Setup

From `src/static/`:

```bash
npm install
```

For visual tests (Playwright), install the browser once:

```bash
npx playwright install chromium
```

## Running Tests

All commands run from `src/static/`:

**Unit tests** (Vitest, tests chart logic like missing data, daily calculations, responsive tick intervals):

```bash
npm run test:unit
```

**Unit tests in watch mode** (re-runs on file changes):

```bash
npx vitest
```

**Visual tests** (Playwright, loads the chart in a browser and checks rendering at different breakpoints):

```bash
npm run test:visual
```

**Both unit and visual tests:**

```bash
npm test
```

## Visual Test Notes

The first time you run visual tests, Playwright creates baseline screenshots in `tests/visual/snapshots/`. Commit those to git so CI and future runs have something to compare against.

If you intentionally change how the chart looks and need to refresh the baselines:

```bash
npx playwright test tests/visual --update-snapshots
```

To see the browser while tests run (useful for debugging):

```bash
npx playwright test tests/visual --headed
```
14 changes: 14 additions & 0 deletions src/static/chartjs/chart.min.js

Large diffs are not rendered by default.

Loading
Loading