test(12.2-05): SPA unit tests for the phase and the check-phase12.2 gate

- sessionKey, dateFormat, FileuploadField (protected thumbnails and
  keyboard reorder backstops), RelationChildModal, RelationPivotModal,
  RelationManager row actions and create-screen deferral, date and time
  list cells; typed deferred relation-schema and file-list fixtures
- scripts/check-phase12.2.sh: go, security (named tests, refuses missing
  or skipped), spa, openapi, dist, docs, hygiene and app stages, a
  detector self-test, one PASS or FAIL line per stage under --all
This commit is contained in:
Jakub Zych
2026-10-02 20:51:36 +02:00
parent 5b06b20ac3
commit d5494faa81
11 changed files with 1856 additions and 4 deletions

View File

@@ -0,0 +1,38 @@
{
"data": [
{
"id": 41,
"file_name": "front.png",
"file_size": 120400,
"content_type": "image/png",
"title": "Front",
"description": "",
"sort_order": 41,
"pending": false,
"created_at": "2026-10-02T10:00:00Z"
},
{
"id": 42,
"file_name": "back.png",
"file_size": 98000,
"content_type": "image/png",
"title": "",
"description": "",
"sort_order": 42,
"pending": true,
"created_at": "2026-10-02T10:05:00Z"
},
{
"id": 43,
"file_name": "manual.pdf",
"file_size": 2400000,
"content_type": "application/pdf",
"title": "",
"description": "",
"sort_order": 43,
"pending": false,
"created_at": "2026-10-02T10:10:00Z"
}
],
"meta": {}
}

View File

@@ -0,0 +1,287 @@
{
"parts": {
"data": {
"name": "parts",
"label": "Parts",
"kind": "hasMany",
"deferrable": true,
"view": {
"list": {
"columns": [
{
"key": "label",
"label": "Label",
"searchable": true,
"sortable": true
}
]
},
"toolbarButtons": [
"create",
"update",
"delete",
"link",
"unlink"
],
"showSearch": false
},
"manage": {
"list": {
"columns": [
{
"key": "label",
"label": "Label",
"searchable": true,
"sortable": true
}
]
},
"toolbarButtons": [],
"showSearch": false
},
"messages": {
"link": {
"other": "Add member"
},
"linkHint": {
"other": "Pick people who are not members yet. The owner is not listed."
},
"candidateSearch": {
"other": "Search by name or email…"
},
"linked": {
"one": "Added :count member",
"other": "Added :count members"
},
"unlinkSelected": {
"other": "Remove selected"
},
"unlinkConfirm": {
"one": "Remove :count member?",
"other": "Remove :count members?"
},
"unlinked": {
"one": "Removed :count member",
"other": "Removed :count members"
},
"empty": {
"other": "This widget has no members."
},
"create": {
"other": "New record"
},
"createTitle": {
"other": "New record"
},
"updateTitle": {
"other": "Edit record"
},
"previewTitle": {
"other": "Record preview"
},
"created": {
"other": "Record created"
},
"updated": {
"other": "Record saved"
},
"deleteSelected": {
"other": "Delete selected"
},
"deleteConfirm": {
"other": "Delete the selected (:count)? This cannot be undone."
},
"deleteOneConfirm": {
"other": "Delete this record? This cannot be undone."
},
"deleted": {
"one": "Deleted :count record",
"other": "Deleted :count records"
},
"pivotTitle": {
"other": "Link details"
},
"pivotSaved": {
"other": "Link details saved"
},
"editPivot": {
"other": "Edit link details: :name"
},
"createSubmit": {
"other": "Create record"
},
"updateSubmit": {
"other": "Save record"
},
"pivotSubmit": {
"other": "Save link details"
},
"linkSubmit": {
"other": "Add link"
}
},
"manageForm": [
{
"name": "label",
"label": "Label",
"type": "text",
"required": true
},
{
"name": "notes",
"label": "Notes",
"type": "textarea",
"tab": "Details"
}
],
"viewForm": [
{
"name": "label",
"label": "Label",
"type": "text"
}
]
},
"meta": {
"locale": "en"
}
},
"members": {
"data": {
"name": "members",
"label": "Members",
"kind": "belongsToMany",
"deferrable": true,
"view": {
"list": {
"columns": [
{
"key": "email",
"label": "E-mail",
"searchable": true,
"sortable": true
}
]
},
"toolbarButtons": [
"link",
"unlink"
],
"showSearch": false
},
"manage": {
"list": {
"columns": [
{
"key": "email",
"label": "E-mail",
"searchable": true,
"sortable": true
}
]
},
"toolbarButtons": [],
"showSearch": false
},
"messages": {
"link": {
"other": "Add member"
},
"linkHint": {
"other": "Pick people who are not members yet. The owner is not listed."
},
"candidateSearch": {
"other": "Search by name or email…"
},
"linked": {
"one": "Added :count member",
"other": "Added :count members"
},
"unlinkSelected": {
"other": "Remove selected"
},
"unlinkConfirm": {
"one": "Remove :count member?",
"other": "Remove :count members?"
},
"unlinked": {
"one": "Removed :count member",
"other": "Removed :count members"
},
"empty": {
"other": "This widget has no members."
},
"create": {
"other": "New record"
},
"createTitle": {
"other": "New record"
},
"updateTitle": {
"other": "Edit record"
},
"previewTitle": {
"other": "Record preview"
},
"created": {
"other": "Record created"
},
"updated": {
"other": "Record saved"
},
"deleteSelected": {
"other": "Delete selected"
},
"deleteConfirm": {
"other": "Delete the selected (:count)? This cannot be undone."
},
"deleteOneConfirm": {
"other": "Delete this record? This cannot be undone."
},
"deleted": {
"one": "Deleted :count record",
"other": "Deleted :count records"
},
"pivotTitle": {
"other": "Link details"
},
"pivotSaved": {
"other": "Link details saved"
},
"editPivot": {
"other": "Edit link details: :name"
},
"createSubmit": {
"other": "Create record"
},
"updateSubmit": {
"other": "Save record"
},
"pivotSubmit": {
"other": "Save link details"
},
"linkSubmit": {
"other": "Add link"
}
},
"viewForm": [
{
"name": "email",
"label": "E-mail",
"type": "text"
}
],
"pivotForm": [
{
"name": "note",
"label": "Note",
"type": "text",
"required": true
}
]
},
"meta": {
"locale": "en"
}
}
}

View File

@@ -10,7 +10,9 @@ import settingsJson from './settings.json'
import extensionFormSchemaJson from './extension.form-schema.json'
import extensionListSchemaJson from './extension.list-schema.json'
import extensionPartialJson from './extension.partial.json'
import deferredFilesJson from './deferred.files.json'
import deferredFormSchemaJson from './deferred.form-schema.json'
import deferredRelationSchemaJson from './deferred.relation-schema.json'
import formSchemaJson from './widgets.form-schema.json'
import listJson from './widgets.list.json'
import listSchemaJson from './widgets.list-schema.json'
@@ -33,6 +35,13 @@ export const settingsFixture: {
export const formSchemaFixture: S['cabana.Envelope-cabana_FormView'] = formSchemaJson
/** A gadget form with deferred-binding fields: fileupload (Phase 12.2). */
export const deferredFormSchemaFixture: S['cabana.Envelope-cabana_FormView'] = deferredFormSchemaJson
/** Relation schemas with child, view and pivot forms: a hasMany and a belongsToMany (Phase 12.2). */
export const deferredRelationSchemaFixture: {
parts: S['cabana.Envelope-cabana_RelationSchema']
members: S['cabana.Envelope-cabana_RelationSchema']
} = deferredRelationSchemaJson
/** A protected file list: a captioned image, a pending image and a PDF (Phase 12.2). */
export const deferredFilesFixture: S['cabana.Envelope-array_cabana_FileItem'] = deferredFilesJson
/** A form with a plugin widget and its controller script (Phase 10.1). */
export const extensionFormSchemaFixture: S['cabana.Envelope-cabana_FormView'] = extensionFormSchemaJson
/** A list with a header partial and a controller stylesheet (Phase 10.1). */