initial commit
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
Some checks failed
ci / go (push) Has been cancelled
ci / admin-ui (push) Has been cancelled
ci / runtime-sdk (push) Has been cancelled
ci / helm (push) Has been cancelled
ci / openapi (push) Has been cancelled
ci / container (push) Has been cancelled
ci / release-config (push) Has been cancelled
ci / shared styling (push) Has been cancelled
ci / security (push) Has been cancelled
ci / all green (push) Has been cancelled
This commit is contained in:
commit
951dd8d26b
175 changed files with 50041 additions and 0 deletions
124
hack/pilot-go-loose.js
Normal file
124
hack/pilot-go-loose.js
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/**
|
||||
* The pilot check's reporter.
|
||||
*
|
||||
* It is injected into a *copy* of go-loose's page; go-loose's own source is untouched.
|
||||
*
|
||||
* The question it answers is narrow and specific: does the component shipped by
|
||||
* go-bananas change the attributes that go-loose's own hand-written stylesheet already
|
||||
* keys on? If it does, go-loose is themed by the shared contract without a single edit
|
||||
* to its CSS, which is the entire claim of ADR 0005.
|
||||
*/
|
||||
import { getContractState } from '/rt/v1/components.js'
|
||||
|
||||
const results = []
|
||||
/** @param {string} name @param {boolean} pass @param {string} [detail] */
|
||||
const check = (name, pass, detail = '') => results.push({ name, pass: !!pass, detail: String(detail) })
|
||||
|
||||
const root = document.documentElement
|
||||
const state = getContractState()
|
||||
|
||||
/** The computed background of go-loose's own page surface. */
|
||||
function pageBackground() {
|
||||
return getComputedStyle(document.body).backgroundColor
|
||||
}
|
||||
|
||||
/**
|
||||
* The value go-loose's page sees for a contract custom property.
|
||||
*
|
||||
* This is the claim worth testing: go-loose's stylesheet never mentions --bn-* or
|
||||
* --surface being defined anywhere, yet reading the property off its own body proves
|
||||
* the contract reached the page through the one stylesheet link.
|
||||
*/
|
||||
function contractValueOnHost(name) {
|
||||
return getComputedStyle(document.body).getPropertyValue(name).trim()
|
||||
}
|
||||
|
||||
/** The text colour go-loose's own CSS takes from --text. */
|
||||
function pageText() {
|
||||
return getComputedStyle(document.body).color
|
||||
}
|
||||
|
||||
async function run() {
|
||||
// The selector fetches its palette list from the service. The wait has to cover a
|
||||
// real cross-origin round trip, not the instant rejection that used to happen when
|
||||
// the service sent no CORS headers: that failure was fast enough to hide behind a
|
||||
// short settle time, and the wait was tuned to it.
|
||||
await new Promise((r) => setTimeout(r, 4000))
|
||||
|
||||
const selector = document.querySelector('bananas-theme-selector')
|
||||
const toggle = document.querySelector('bananas-appearance-toggle')
|
||||
const shadow = (el) => /** @type {ShadowRoot} */ (el.shadowRoot)
|
||||
|
||||
check('the selector element upgraded', !!shadow(selector), selector ? selector.tagName : 'absent')
|
||||
check('the toggle element upgraded', !!shadow(toggle), toggle ? toggle.tagName : 'absent')
|
||||
|
||||
const buttons = [...shadow(selector).querySelectorAll('button')]
|
||||
const labels = buttons.map((b) => b.textContent.trim())
|
||||
check('palettes are listed from the service', buttons.length > 1, labels.join(', '))
|
||||
|
||||
// go-loose's four palettes must all be offered, because those are the slugs its own
|
||||
// CSS has blocks for.
|
||||
for (const slug of ['Tokyo Night', 'Catppuccin', 'Tomorrow', 'Kanagawa']) {
|
||||
check(`go-loose's "${slug}" is offered`, labels.includes(slug))
|
||||
}
|
||||
|
||||
// The contract stylesheet loaded and reached go-loose's page.
|
||||
const bgTokyo = pageBackground()
|
||||
check('go-loose\'s page is themed through the contract', bgTokyo !== 'rgba(0, 0, 0, 0)' && bgTokyo !== '', bgTokyo)
|
||||
|
||||
// The decisive test: change the palette with the component, and confirm go-loose's
|
||||
// OWN stylesheet responded. Nothing in style.css was edited.
|
||||
const startBg = bgTokyo
|
||||
const startText = pageText()
|
||||
const kanagawa = buttons.find((b) => b.textContent.trim() === 'Kanagawa')
|
||||
if (!kanagawa) {
|
||||
check('the Kanagawa button was found', false, labels.join(', '))
|
||||
} else {
|
||||
kanagawa.click()
|
||||
await new Promise((r) => setTimeout(r, 60))
|
||||
check('selecting a palette writes data-theme', root.getAttribute('data-theme') === 'kanagawa', root.getAttribute('data-theme'))
|
||||
check('selecting a palette writes the legacy attribute', root.getAttribute('data-bananas-theme') === 'kanagawa', root.getAttribute('data-bananas-theme'))
|
||||
check("go-loose's own CSS followed the palette", pageBackground() !== startBg, startBg + ' -> ' + pageBackground())
|
||||
// The alias layer reached a page that never referenced it.
|
||||
check('go-loose\'s page reads --surface from the contract', contractValueOnHost('--surface') !== '', contractValueOnHost('--surface'))
|
||||
check('go-loose\'s page reads --bn-surface from the contract', contractValueOnHost('--bn-surface') !== '', contractValueOnHost('--bn-surface'))
|
||||
check('the alias and the contract agree', contractValueOnHost('--surface') === contractValueOnHost('--bn-surface'),
|
||||
contractValueOnHost('--surface') + ' vs ' + contractValueOnHost('--bn-surface'))
|
||||
}
|
||||
|
||||
// And the appearance axis, which go-loose has never had.
|
||||
const toggleButtons = [...shadow(toggle).querySelectorAll('button')]
|
||||
check('the appearance toggle has three states', toggleButtons.length === 3, toggleButtons.map((b) => b.getAttribute('aria-label')).join(', '))
|
||||
const light = toggleButtons.find((b) => b.getAttribute('aria-label') === 'Light')
|
||||
if (light) {
|
||||
light.click()
|
||||
await new Promise((r) => setTimeout(r, 60))
|
||||
check('light writes data-mode', root.getAttribute('data-mode') === 'light', root.getAttribute('data-mode'))
|
||||
check("go-loose's own CSS followed the appearance", pageBackground() !== 'rgb(0, 0, 0)', pageBackground())
|
||||
}
|
||||
|
||||
// Isolation: go-loose has a broad `.card button { all: unset }`-style surface, and a
|
||||
// control that leaked would be reset by it.
|
||||
const first = shadow(selector).querySelector('button')
|
||||
const style = first ? getComputedStyle(first) : null
|
||||
check('the control is not reset by the host page', !!style && style.padding !== '0px', style ? style.padding : 'no button')
|
||||
check('the control is not inheriting the page font', !!style && !style.fontFamily.includes('DM Sans'), style ? style.fontFamily : '')
|
||||
|
||||
// The store is reachable, so go-loose can read or set the selection itself.
|
||||
check('the contract store is reachable from the module', state && typeof state.selectTheme === 'function')
|
||||
|
||||
const failed = results.filter((r) => !r.pass)
|
||||
const out = document.getElementById('pilot') || document.createElement('pre')
|
||||
out.id = 'pilot'
|
||||
out.textContent = failed.length
|
||||
? 'PILOT FAIL ' + failed.length + '/' + results.length + ' :: ' + failed.map((f) => f.name + ' [' + f.detail + ']').join(' | ')
|
||||
: 'PILOT PASS ' + results.length + ' :: ' + results.map((f) => f.name).join(' | ')
|
||||
document.body.append(out)
|
||||
}
|
||||
|
||||
run().catch((error) => {
|
||||
const out = document.createElement('pre')
|
||||
out.id = 'pilot'
|
||||
out.textContent = 'PILOT FAIL the check threw: ' + (error instanceof Error ? error.message : String(error))
|
||||
document.body.append(out)
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue