ReviewOS

also looking at this

stacks/lastsoulultra

LSU's own coaching surface, and what auditing the site turned up

#12
Merged glennmichael123 wants to merge claude/last-soul-ultra-web-6e0718 into main
86 files +3943 -1190

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

resources/views/lottery.stxmodified+1-4
Changes to resources/views/lottery.stx
@@ -14,9 +14,7 @@ const canonicalPath = "/lottery"
1414</section>
1515<section id="form" class="entry lsu-scope-lottery">
1616<div class="entry-shell lsu-scope-lottery">
17<div class="form lsu-scope-lottery portal" data-lottery-portal data-lang="en" aria-live="polite">
18<div class="lsu-scope-lottery portal-message">Loading account access…</div>
19</div>
17<RacePortal />
2018</div>
2119</section>
2220<section class="lsu-scope-lottery open-now section">
@@ -106,5 +104,4 @@ const canonicalPath = "/lottery"
106104<br class="lsu-scope-lottery">Selection is by LSU team and a random draw. </p>
107105</div>
108106</section>
109<section class="section"><div class="shell"><RacePortal /></div></section>
110107@endsection
tests/entry.test.tsadded+48-0
Changes to tests/entry.test.ts
@@ -0,0 +1,48 @@
1import { describe, expect, it } from 'bun:test'
2import { resolve } from 'node:path'
3import { processDirectives } from '@stacksjs/stx'
4
5/**
6 * The entry page's job is one form. It shipped with two: a placeholder that
7 * read "Loading account access…" in the section the page calls #form, which
8 * nothing ever replaced, and the working portal more than a thousand pixels
9 * below it. Nothing errored, and the page looked like it was still loading.
10 */
11
12async function render(view: string): Promise<string> {
13 const path = resolve(`resources/views/${view}.stx`)
14 return processDirectives(await Bun.file(path).text(), {}, path, {
15 enabled: true,
16 cache: false,
17 componentsDir: resolve('resources/components'),
18 layoutsDir: resolve('resources/layouts'),
19 partialsDir: resolve('resources/partials'),
20 }, new Set())
21}
22
23describe('the entry page', () => {
24 it('puts the form in the section it calls the form', async () => {
25 const html = await render('lottery')
26 const form = html.slice(html.indexOf('id="form"'))
27
28 expect(form.indexOf('race-portal')).toBeGreaterThan(-1)
29 // Before the next section begins.
30 expect(form.indexOf('race-portal')).toBeLessThan(form.indexOf('open-now'))
31 })
32
33 it('has one portal, not a working one and a decorative one', async () => {
34 const html = await render('lottery')
35 expect([...html.matchAll(/class="race-portal"/g)]).toHaveLength(1)
36 })
37
38 it('shows no loading state that nothing ever clears', async () => {
39 const html = await render('lottery')
40
41 expect(html).not.toContain('Loading account access')
42 expect(html).not.toContain('data-lottery-portal')
43 })
44
45 it('offers the same account on the profile page', async () => {
46 expect(await render('profile')).toContain('race-portal')
47 })
48})