@bongos/core 1.21.90 → 1.21.92
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bongos-core.json +67 -52
- package/clients/bongos-client/README.md +1 -1
- package/clients/bongos-client/bongos-client.global.js +4 -0
- package/clients/bongos-client/index.cjs +4 -0
- package/clients/bongos-client/index.d.ts +4 -0
- package/clients/bongos-client/index.mjs +4 -0
- package/docs/api/openapi.json +36 -1
- package/docs/api-reference.md +7 -1
- package/docs/copy-inventory.md +364 -374
- package/docs/copy-registry.json +566 -648
- package/docs/module-api-changelog.md +4 -0
- package/docs/page-inventory.json +15 -18
- package/docs/page-readings.json +1500 -1191
- package/modules/hall-ui/public/craft-mode.js +60 -0
- package/modules/hall-ui/public/style.css +32 -0
- package/modules/hall-ui/records/craft-mode.md +1 -1
- package/modules/lifecycle/module.json +2 -1
- package/modules/lifecycle/moving.js +55 -0
- package/modules/lifecycle/routes/moving.js +30 -0
- package/modules/public-landing/public/projects-hall-live.states.json +6 -35
- package/modules/public-landing/public/projects.html +1019 -983
- package/modules/public-landing/public/projects.probes.json +15 -18
- package/modules/public-landing/public/projects.states.json +22 -25
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +12 -0
- package/src/module-api.js +1 -1
- package/tests/craft_mode_tallies.mjs +149 -0
- package/tests/onboard.mjs +8 -8
- package/tests/project_invite_ui.mjs +6 -5
- package/tests/projects_hub.mjs +77 -98
- package/tests/projects_hub_app_status.mjs +3 -3
- package/tests/projects_hub_app_step.mjs +8 -8
- package/tests/projects_hub_cloud_hop.mjs +29 -53
- package/tests/projects_hub_look.mjs +29 -39
- package/tests/projects_hub_module_picker.mjs +32 -39
- package/tests/projects_hub_pre_uat.mjs +11 -14
- package/tests/wizard_demo.mjs +30 -25
- package/tests/wizard_draft_resume.mjs +24 -32
- package/tests/wizard_front_door.mjs +91 -243
- package/tests/wizard_intent_resume.mjs +28 -48
- package/tests/wizard_one_page.mjs +201 -0
- package/tests/wizard_physics.mjs +46 -41
- package/tests/wizard_physics_more.mjs +71 -106
- package/tests/wizard_ship_mode.mjs +1 -1
- package/tests/wizard_six_screens.mjs +0 -129
|
@@ -158,24 +158,21 @@
|
|
|
158
158
|
{ "name": "manage flows: disconnect entirely asks for the name typed back, queues the true delete, and the page re-reads the project as being disconnected (task 1003249)", "auth": true, "width": 1440, "url": "/projects?view=manage&id=104",
|
|
159
159
|
"steps": [["wait",900],["click","[data-disc-ask]"],["wait",200],["fill","#mDiscName","old-lantern"],["wait",100],["click","[data-disc-yes]"],["wait",900]],
|
|
160
160
|
"expect": {"text":[["#mDisc .addr","This project is being disconnected."],["#mName","old-lantern"]],"hidden":["#mDiscName","[data-disc-ask]"]} },
|
|
161
|
-
{ "name": "the
|
|
162
|
-
"steps": [["wait",600],["click","#
|
|
163
|
-
"expect": {"visible":["#
|
|
164
|
-
{ "name": "the quick checks (task
|
|
165
|
-
"steps": [["wait",600],["
|
|
166
|
-
"expect": {"visible":["#
|
|
167
|
-
{ "name": "
|
|
168
|
-
"steps": [["wait",600],["
|
|
169
|
-
"expect": {"visible":["#
|
|
170
|
-
{ "name": "the wizard driver (
|
|
171
|
-
"steps": [["wait",600],["
|
|
172
|
-
"expect": {"visible":["#panel-done","#hop","#hopCanvas","#hopStatus","#hopJump"],"hidden":["#
|
|
173
|
-
{ "name": "the
|
|
174
|
-
"steps": [["wait",600],["click","#termsAck"],["wait",100]],
|
|
175
|
-
"expect": {"visible":["#panel-
|
|
176
|
-
{ "name": "the wizard driver at 390: the review rows stack and the walk still reaches Create", "auth": true, "width": 390, "url": "/projects?view=new",
|
|
177
|
-
"steps": [["wait",600],["click","#termsAck"],["wait",100],["click","#wizStart"],["wait",400],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["click","#panel-what button[type=submit]"],["wait",400],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["click","#physNext"],["wait",700],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#reviewGo"],["wait",500]],
|
|
178
|
-
"expect": {"visible":["#panel-look","#wizLook","#doCreate"],"hidden":["#panel-review"],"text":[["#look-h","Give it a look."]]} },
|
|
161
|
+
{ "name": "the one page (task 1004648): Create waits for a name and the terms tick and says why in place; the demo link opens the demo at the top of part 01 and \"Make a real project instead\" closes it again", "auth": true, "width": 1440, "url": "/projects?view=new",
|
|
162
|
+
"steps": [["wait",600],["click","#wizDemo"],["wait",300],["click","#demoCancel"],["wait",300],["fill","#newName","Mercury"],["wait",100]],
|
|
163
|
+
"expect": {"visible":["#part-project","#part-run","#doCreate"],"hidden":["#demoSetup","#demoTag"],"attr":[["#wizDemo","aria-expanded","false"],["#doCreate","disabled",""]],"text":[["#createWhy","Tick the terms to create your project."]]} },
|
|
164
|
+
{ "name": "the quick checks (task 1004648): a country with states asks for one, a yes to under-18s shows the age tiers, and an existing entity opens the full list — in place, in part 01", "auth": true, "width": 1440, "url": "/projects?view=new",
|
|
165
|
+
"steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["select","#physRegion","US-CA"],["click","[data-phys=\"builder_geography\"][data-val=\"us-eu\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"true\"]"],["wait",200],["click","#physHaveEntity"],["wait",100],["click","[data-phys=\"entity\"][data-val=\"for-profit\"]"],["wait",300]],
|
|
166
|
+
"expect": {"visible":["#physRegionField","#physAges","#physForms","#part-run"],"hidden":["#physIntent","#checksStop"]} },
|
|
167
|
+
{ "name": "part 02 (task 1004648): Change opens a row in place and reads Done, opening another closes it, and nothing needs confirming", "auth": true, "width": 1440, "url": "/projects?view=new",
|
|
168
|
+
"steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"team\"] [data-row-chg]"],["wait",200],["click","[data-phys-solo=\"many\"]"],["wait",600],["click","#reviewRows .setRow[data-row=\"run\"] [data-row-chg]"],["wait",300]],
|
|
169
|
+
"expect": {"visible":["#reviewRows .setRow[data-row=\"rewards\"]","#reviewRows .setRow.open[data-row=\"run\"] .opts"],"hidden":["#reviewRows .setRow[data-row=\"team\"] .opts"],"text":[["#reviewRows .setRow[data-row=\"run\"] [data-row-chg]","Done"],["#reviewRows .setRow[data-row=\"team\"] [data-row-chg]","Change"]]} },
|
|
170
|
+
{ "name": "the wizard driver (task 1004648): part 01, the checks, the address row (the dotless stub host takes a domain the founder owns), the tick, then Create — part 03 goes live with the checklist, the cloud hop and its status line", "auth": true, "width": 1440, "url": "/projects?view=new",
|
|
171
|
+
"steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],
|
|
172
|
+
"expect": {"visible":["#panel-done","#humanSteps","#hop","#hopCanvas","#hopStatus","#hopJump"],"hidden":["#wizParts","#liveProgress"],"text":[["#done-h","Setting up Mercury"],["#hopStatus","Raising the server, database, and address — nothing needed from you."]]} },
|
|
173
|
+
{ "name": "the wizard driver at 320 (narrower than a 375 phone): the page stacks, nothing scrolls sideways, and the walk still reaches part 03", "auth": true, "width": 320, "url": "/projects?view=new",
|
|
174
|
+
"steps": [["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],
|
|
175
|
+
"expect": {"noOverflow":true,"visible":["#panel-done","#humanSteps"],"hidden":["#wizParts"]} },
|
|
179
176
|
{ "name": "invite a guild (task 1002303, R27): a /g/ address gives one pending line per member on its public page, each a link to the hall", "auth": true, "width": 1440, "url": "/projects?view=manage&id=101",
|
|
180
177
|
"steps": [["wait",900],["fill","#mInviteGuild","/g/forge-crew"],["click","#mInvite [data-invite-guild]"],["wait",400]],
|
|
181
178
|
"expect": { "count": [["#mInviteList li", 4]], "value": [["#mInviteGuild", ""]],
|
|
@@ -37,31 +37,28 @@
|
|
|
37
37
|
"in-manage-gone": { "auth": true, "url": "/projects?view=manage&id=104", "expect": { "visible": ["#mMain", "#mActs"], "hidden": ["#mErr", "#mAddress"], "text": [["#mName", "old-lantern"]] } },
|
|
38
38
|
"in-manage-missing": { "auth": true, "url": "/projects?view=manage&id=999", "expect": { "visible": ["#mMissing"], "hidden": ["#mMain", "#mGate"] } },
|
|
39
39
|
"out-manage": { "auth": false, "url": "/projects?view=manage&id=101", "expect": { "visible": ["#mGate"], "hidden": ["#mMain", "#mMissing"] } },
|
|
40
|
-
"in-new": {"auth":true,"url":"/projects?view=new","expect":{"visible":["#panel-
|
|
41
|
-
"in-new-
|
|
42
|
-
"in-new-
|
|
43
|
-
"in-new-
|
|
44
|
-
"in-new-demo
|
|
45
|
-
"in-new-demo-
|
|
46
|
-
"in-new-
|
|
47
|
-
"in-new-
|
|
48
|
-
"in-new-
|
|
49
|
-
"in-new-
|
|
50
|
-
"in-new-
|
|
51
|
-
"in-new-
|
|
52
|
-
"in-new-
|
|
53
|
-
"in-new-
|
|
54
|
-
"in-new-
|
|
55
|
-
"in-new-
|
|
56
|
-
"in-new-
|
|
57
|
-
"in-new-
|
|
58
|
-
"in-new-
|
|
59
|
-
"in-new-
|
|
60
|
-
"in-new-
|
|
61
|
-
"
|
|
62
|
-
"in-new-resume-offer": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["click","#termsAck"],["wait",100],["click","#wizStart"],["wait",400],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#panel-what button[type=submit]"],["wait",400],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["click","#physNext"],["wait",700],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#reviewGo"],["wait",500],["click","#doCreate"],["wait",1500],["click","#projTrig"],["wait",350],["click","#menuProjects [data-nav=\"new\"]"],["wait",500]],"expect":{"visible":["#panel-fork","#wizResume","#wizResumeGo"],"hidden":["#panel-done"],"text":[["#wizResumeName","Mercury"]]}},
|
|
63
|
-
"in-new-look-custom": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["click","#termsAck"],["wait",100],["click","#wizStart"],["wait",400],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#panel-what button[type=submit]"],["wait",400],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["click","#physNext"],["wait",700],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#reviewGo"],["wait",500],["click","#wizLook-custom"],["wait",200]],"expect":{"visible":["#panel-look","#wizAccent","#wizAccentNote"],"hidden":["#panel-review"]}},
|
|
64
|
-
"out-new": {"auth":false,"url":"/projects?view=new","expect":{"visible":["#panel-gate","#wizSignin"],"hidden":["#qWrap","#panel-fork"]}},
|
|
40
|
+
"in-new": {"auth":true,"url":"/projects?view=new","expect":{"visible":["#panel-page","#part-project","#part-run","#termsAck","#doCreate","#panel-done",".wizRoom .rmWindow"],"hidden":["#qWrap","#doneBody","#demoSetup","#checksStop","#panel-gate"],"attr":[["#doCreate","disabled",""],["#wizRoom","data-screen","page"],["#panel-done","class","part waiting"]],"text":[["#createWhy","Give it a name first."],["#ghState","opens once your project exists"]]}},
|
|
41
|
+
"in-new-named": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["wait",200]],"expect":{"visible":["#doCreate","#wizRecap"],"attr":[["#doCreate","disabled",""]],"text":[["#createWhy","Tick the terms to create your project."],["#wizRecap","Mercury · new repo · no address yet"]]}},
|
|
42
|
+
"in-new-ready": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#termsAck"],["wait",200]],"expect":{"visible":["#doCreate","#wizRecap"],"attr":[["#wizRoom","data-fill","3"]],"text":[["#wizRecap","Mercury · Game · new repo · no address yet"]]}},
|
|
43
|
+
"in-new-name-prefilled": {"auth":true,"url":"/projects?view=new&name=Mercury","actions":[["wait",600]],"expect":{"visible":["#panel-page","#newName"]}},
|
|
44
|
+
"in-new-demo": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["click","#wizDemo"],["wait",300]],"expect":{"visible":["#panel-page","#demoSetup","#demoFitVerdict","#demoInvites","#demoStart","#demoCancel"],"attr":[["#wizDemo","aria-expanded","true"]]}},
|
|
45
|
+
"in-new-demo-used": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["click","#wizDemo"],["wait",300],["fill","#demoIdea","A voting app for movie night"],["click","#demoStart"],["wait",400]],"expect":{"visible":["#demoTag","#newName","#part-run"],"hidden":["#demoSetup","#checksMain"],"text":[["#wizEyebrow","New demo"]]}},
|
|
46
|
+
"in-new-checks-filled": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["select","#physRegion","US-CA"],["click","[data-phys=\"builder_geography\"][data-val=\"us-eu\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"true\"]"],["wait",300]],"expect":{"visible":["#physRegionField","#physAges"],"hidden":["#checksStop"]}},
|
|
47
|
+
"in-new-checks-entity": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#physHaveEntity"],["wait",200],["click","[data-phys=\"entity\"][data-val=\"for-profit\"]"],["wait",100]],"expect":{"visible":["#physForms","#physNoEntity"],"hidden":["#physIntent"]}},
|
|
48
|
+
"in-new-row-code": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"code\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"code\"] .opts","#c-green","#c-adopt"]}},
|
|
49
|
+
"in-new-row-address": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"address\"] .opts","#f-slug","#addrConfirm","#f-noaddr"]}},
|
|
50
|
+
"in-new-row-team": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"team\"] [data-row-chg]"],["wait",400],["click","[data-phys-solo=\"many\"]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"team\"] .opts","[data-phys-solo=\"many\"]"]}},
|
|
51
|
+
"in-new-row-extras": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"extras\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"extras\"] .opts","#modCards"]}},
|
|
52
|
+
"in-new-row-rewards": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"team\"] [data-row-chg]"],["wait",200],["click","[data-phys-solo=\"many\"]"],["wait",600],["click","#reviewRows .setRow[data-row=\"rewards\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"rewards\"] .opts","[data-phys=\"reward_intents\"][data-val=\"cash\"]"]}},
|
|
53
|
+
"in-new-row-app": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"app\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"app\"] .opts","#appOpts"]}},
|
|
54
|
+
"in-new-row-run": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"run\"] [data-row-chg]"],["wait",400],["click","[data-phys=\"framing\"][data-val=\"hybrid\"]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"run\"] .opts","#physSuite"]}},
|
|
55
|
+
"in-new-row-ship": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"ship\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"ship\"] .opts","#shipOpts"]}},
|
|
56
|
+
"in-new-look": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"look\"] [data-row-chg]"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"look\"] .opts","#wizLook"]}},
|
|
57
|
+
"in-new-look-custom": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"look\"] [data-row-chg]"],["wait",400],["click","#wizLook-custom"],["wait",200]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"look\"] .opts","#wizLook","#wizAccent","#wizAccentNote"]}},
|
|
58
|
+
"in-new-create-blocked": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",400]],"expect":{"visible":["#reviewRows .setRow.open[data-row=\"address\"] .opts","#h-domain"],"hidden":["#doneBody"],"text":[["#createWhy","Fix the row that’s open, then create."]]}},
|
|
59
|
+
"in-new-done": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500]],"expect":{"visible":["#panel-done","#doneBody","#humanSteps","#hop","#hopCanvas","#hopStatus","#hopJump","#wizRecap"],"hidden":["#wizParts","#qWrap","#wizInvite","#liveProgress","#wizInviteLater"],"attr":[["#doCreate","disabled",""],["#wizRoom","data-screen","done"]],"text":[["#done-h","Setting up Mercury"],["#doCreate","Created"]]}},
|
|
60
|
+
"in-new-resume-offer": {"auth":true,"url":"/projects?view=new","actions":[["wait",600],["fill","#newName","Mercury"],["click","#typeCards .tpill[data-type=\"game\"]"],["fill","#f-desc","A co-op farming game where the seasons never repeat."],["select","#physCountry","US"],["wait",100],["click","[data-phys=\"builder_geography\"][data-val=\"global\"]"],["click","[data-phys=\"minors_on_board\"][data-val=\"false\"]"],["click","[data-phys=\"entity\"][data-val=\"intent-solo\"]"],["wait",300],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["fill","#f-slug","mercury"],["wait",900],["fill","#f-domain","mercury.example.com"],["wait",200],["click","#reviewRows .setRow[data-row=\"address\"] [data-row-chg]"],["wait",200],["click","#termsAck"],["wait",100],["click","#doCreate"],["wait",1500],["click","#projTrig"],["wait",350],["click","#menuProjects [data-nav=\"new\"]"],["wait",500]],"expect":{"visible":["#panel-page","#wizResume","#wizResumeGo","#wizParts"],"hidden":["#doneBody"],"text":[["#wizResumeName","Mercury"]]}},
|
|
61
|
+
"out-new": {"auth":false,"url":"/projects?view=new","expect":{"visible":["#panel-gate","#wizSignin"],"hidden":["#qWrap","#panel-page"]}},
|
|
65
62
|
"out-map-projects": { "auth": false, "actions": [["click", "#projTrig"], ["wait", 350]], "expect": { "expanded": true, "hidden": ["#menuProjects [data-nav=\"mine\"]"] } },
|
|
66
63
|
"card": { "auth": true, "actions": [["dispatchClick", "#orbField a.worldOrb[data-origin=\"https://example.com\"]"], ["wait", 900]], "expect": { "dialog": true, "hasClass": [["#projCard", "has-art"]], "visible": ["#cardArt", "#cardFaces", "#cardBuildersFig", "#cardShippedFig", "#cardOpen", "#cardHall"], "text": [["#cardBuilders", "11"], ["#cardShipped", "0"], ["#cardRel", "you build here"], ["#cardRuns", "example.com"], ["#cardFaces .facesMore", "+6"]], "count": [["#cardFaces img", 5]], "href": [["#cardHall", "https://builders.example.com/"]] } },
|
|
67
64
|
"card-noart": { "auth": true, "actions": [["dispatchClick", "#orbField a.worldOrb[data-origin=\"https://emersonian-circles.cloudbongos.com\"]"], ["wait", 600]], "expect": { "dialog": true, "hasClass": [["#projCard", "has-art", false]], "hidden": ["#cardArt", "#cardFaces", "#cardHall"], "visible": ["#cardBuildersFig", "#cardShippedFig", "#cardOpen"], "text": [["#cardShipped", "30+"], ["#cardRel", "you build here"]] } },
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.92",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.21.
|
|
9
|
+
"version": "1.21.92",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.92",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
package/release-notes.json
CHANGED
|
@@ -9370,5 +9370,17 @@
|
|
|
9370
9370
|
"id": "1004655",
|
|
9371
9371
|
"text": "Three government actions now have tests that check them the way the site really answers: choosing a form of government, taking back your own proposal before anyone votes, and seeing who each founding stage is still waiting on."
|
|
9372
9372
|
}
|
|
9373
|
+
],
|
|
9374
|
+
"1.21.91": [
|
|
9375
|
+
{
|
|
9376
|
+
"id": "1004563",
|
|
9377
|
+
"text": "In Governing mode the top bar now shows two live numbers: how many things are waiting on the owner (\"needs you\") and how many tasks are being built or waiting to go live (\"moving\"). If a number can't be read it is simply left"
|
|
9378
|
+
}
|
|
9379
|
+
],
|
|
9380
|
+
"1.21.92": [
|
|
9381
|
+
{
|
|
9382
|
+
"id": "1004648",
|
|
9383
|
+
"text": "Starting a project is now one page instead of six screens. After signing in, a founder sees \"Make something.\" with three parts: their project (name, kind, a sentence and four quick checks), a short summary of how it will be ru"
|
|
9384
|
+
}
|
|
9373
9385
|
]
|
|
9374
9386
|
}
|
package/src/module-api.js
CHANGED
|
@@ -75,7 +75,7 @@ const { responsibilityFor, ROLE_RESPONSIBILITIES } = require('./role-responsibil
|
|
|
75
75
|
// MAJOR (see allowBoxScope below): passes the request through untouched.
|
|
76
76
|
function deprecatedNoopMiddleware(_req, _res, next) { next(); }
|
|
77
77
|
|
|
78
|
-
const CORE_VERSION = '1.21.
|
|
78
|
+
const CORE_VERSION = '1.21.92'; // CI auto-patch carrier (ADR 0161); changelog: docs/module-api-changelog.md
|
|
79
79
|
|
|
80
80
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
81
81
|
// Usage: const log = api.logger('discord'); log.info('mounted');
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// tests/craft_mode_tallies.mjs — Governing mode's header tallies (task 1004563, goal
|
|
2
|
+
// 1000095 WA6): "needs you N · moving M" beside the eyebrow.
|
|
3
|
+
//
|
|
4
|
+
// Runs the REAL craft-mode.js over a small DOM with a stubbed fetch, and the REAL
|
|
5
|
+
// server count (modules/lifecycle/moving.js) over a fake pool, so the two halves are
|
|
6
|
+
// pinned where they actually decide: which statuses "moving" counts (owner decision
|
|
7
|
+
// 2026-10-08: active + confirmed), and that a figure the page could not read is left
|
|
8
|
+
// out rather than drawn as a zero that says nothing waits on you.
|
|
9
|
+
import assert from 'node:assert/strict';
|
|
10
|
+
import { test } from 'node:test';
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import vm from 'node:vm';
|
|
14
|
+
import { createRequire } from 'node:module';
|
|
15
|
+
import { fileURLToPath } from 'node:url';
|
|
16
|
+
|
|
17
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
18
|
+
const CRAFT = fs.readFileSync(path.join(ROOT, 'modules/hall-ui/public/craft-mode.js'), 'utf8');
|
|
19
|
+
const require = createRequire(import.meta.url);
|
|
20
|
+
process.env.NODE_ENV = 'test';
|
|
21
|
+
const { countMoving, movingHandler, MOVING_STATUSES } = require('../modules/lifecycle/moving.js');
|
|
22
|
+
|
|
23
|
+
function node(tag, id, cls) {
|
|
24
|
+
const attrs = {};
|
|
25
|
+
return {
|
|
26
|
+
tagName: tag, id: id || '', className: cls || '', dataset: {}, children: [], parentNode: null,
|
|
27
|
+
textContent: '', innerHTML: '',
|
|
28
|
+
setAttribute(k, v) { attrs[k] = String(v); }, getAttribute(k) { return k in attrs ? attrs[k] : null; },
|
|
29
|
+
removeAttribute(k) { delete attrs[k]; },
|
|
30
|
+
get nextSibling() { const sib = this.parentNode && this.parentNode.children; return sib ? sib[sib.indexOf(this) + 1] || null : null; },
|
|
31
|
+
appendChild(c) { c.parentNode = this; this.children.push(c); return c; },
|
|
32
|
+
insertBefore(c, ref) {
|
|
33
|
+
c.parentNode = this;
|
|
34
|
+
const at = ref ? this.children.indexOf(ref) : -1;
|
|
35
|
+
if (at === -1) this.children.push(c); else this.children.splice(at, 0, c);
|
|
36
|
+
return c;
|
|
37
|
+
},
|
|
38
|
+
removeChild(c) { this.children.splice(this.children.indexOf(c), 1); c.parentNode = null; return c; },
|
|
39
|
+
querySelector(sel) { return all(this).find((n) => sel === '.' + n.className) || null; },
|
|
40
|
+
querySelectorAll() { return []; },
|
|
41
|
+
addEventListener() {}, classList: { toggle() {} },
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function all(root) { return root.children.flatMap((c) => [c, ...all(c)]); }
|
|
45
|
+
|
|
46
|
+
// answers: path → JSON body, or a number (an HTTP failure status), or 'throw'.
|
|
47
|
+
function boot(mode, answers) {
|
|
48
|
+
const sidebar = node('NAV', 'app-sidebar');
|
|
49
|
+
sidebar.appendChild(node('DIV', '', 'app-sidebar__brand'));
|
|
50
|
+
const topbar = node('DIV', 'app-topbar');
|
|
51
|
+
topbar.appendChild(node('H2', 'topbar-title'));
|
|
52
|
+
const root = node('HTML');
|
|
53
|
+
const asked = [];
|
|
54
|
+
const document = {
|
|
55
|
+
documentElement: root, body: node('BODY'), activeElement: null,
|
|
56
|
+
getElementById: (id) => [sidebar, topbar, ...all(sidebar), ...all(topbar)].find((n) => n.id === id) || null,
|
|
57
|
+
querySelectorAll: () => [],
|
|
58
|
+
createElement: (t) => node(t.toUpperCase()),
|
|
59
|
+
addEventListener() {}, removeEventListener() {}, dispatchEvent() { return true; },
|
|
60
|
+
};
|
|
61
|
+
const mk = (obj) => ({ getItem: (k) => (k in obj ? obj[k] : null), setItem: (k, v) => { obj[k] = String(v); }, removeItem: (k) => { delete obj[k]; } });
|
|
62
|
+
const window = { localStorage: mk({}), sessionStorage: mk(mode ? { 'hall-craft': mode } : {}), matchMedia: () => ({ matches: false }) };
|
|
63
|
+
const fetch = (url) => {
|
|
64
|
+
asked.push(url);
|
|
65
|
+
const key = Object.keys(answers || {}).find((k) => url.endsWith(k));
|
|
66
|
+
const a = key ? answers[key] : 404;
|
|
67
|
+
if (a === 'throw') return Promise.reject(new Error('offline'));
|
|
68
|
+
if (typeof a === 'number') return Promise.resolve({ ok: false, status: a, json: () => Promise.resolve({}) });
|
|
69
|
+
return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve(a) });
|
|
70
|
+
};
|
|
71
|
+
const sandbox = { window, document, fetch, CustomEvent: class { constructor(t, i) { this.type = t; Object.assign(this, i); } } };
|
|
72
|
+
vm.createContext(sandbox);
|
|
73
|
+
vm.runInContext(CRAFT, sandbox, { filename: 'craft-mode.js' });
|
|
74
|
+
const craft = window.OTBCraftMode;
|
|
75
|
+
craft.mount();
|
|
76
|
+
const box = () => all(topbar).find((n) => n.id === 'craft-tallies') || null;
|
|
77
|
+
return { craft, topbar, asked, box };
|
|
78
|
+
}
|
|
79
|
+
const settle = () => new Promise((r) => setImmediate(r));
|
|
80
|
+
const text = (html) => html.replace(/<[^>]+>/g, '').replace(/\s+/g, ' ').trim();
|
|
81
|
+
|
|
82
|
+
const BOTH = { '/blockers?limit=1': { blockers: [{ id: 1 }], page: { limit: 1, offset: 0, total: 3 } }, '/moving': { moving: 12, active: 9, confirmed: 3 } };
|
|
83
|
+
|
|
84
|
+
test('Governing reads both counts and draws "needs you 3 · moving 12" right after the eyebrow', async () => {
|
|
85
|
+
const { topbar, box, asked } = boot('governing', BOTH);
|
|
86
|
+
await settle();
|
|
87
|
+
const b = box();
|
|
88
|
+
assert.ok(b, 'the tallies are drawn');
|
|
89
|
+
const eyebrow = all(topbar).find((n) => n.id === 'craft-eyebrow');
|
|
90
|
+
assert.equal(eyebrow.nextSibling, b, 'they sit directly after the mode words');
|
|
91
|
+
assert.equal(b.getAttribute('hidden'), null);
|
|
92
|
+
assert.equal(text(b.innerHTML), 'needs you 3 · moving 12');
|
|
93
|
+
assert.match(b.innerHTML, /craft-tally craft-tally--due/, 'something waits, so needs-you carries the warm dot');
|
|
94
|
+
assert.deepEqual(asked.map((u) => u.replace('/api/bongos', '')).sort(), ['/blockers?limit=1', '/moving'], 'one page of one blocker for the total, one count — never a task list');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('nothing waiting draws "needs you 0" without the dot', async () => {
|
|
98
|
+
const { box } = boot('governing', { ...BOTH, '/blockers?limit=1': { blockers: [], page: { limit: 1, offset: 0, total: 0 } } });
|
|
99
|
+
await settle();
|
|
100
|
+
assert.equal(text(box().innerHTML), 'needs you 0 · moving 12');
|
|
101
|
+
assert.doesNotMatch(box().innerHTML, /craft-tally--due/);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('a count that cannot be read is LEFT OUT, never drawn as zero', async () => {
|
|
105
|
+
const noMoving = boot('governing', { ...BOTH, '/moving': 401 });
|
|
106
|
+
await settle();
|
|
107
|
+
assert.equal(text(noMoving.box().innerHTML), 'needs you 3', 'a signed-out or failed /moving drops only its own figure');
|
|
108
|
+
|
|
109
|
+
const offline = boot('governing', { '/blockers?limit=1': 'throw', '/moving': { moving: 'lots' } });
|
|
110
|
+
await settle();
|
|
111
|
+
assert.equal(offline.box().getAttribute('hidden'), '', 'nothing readable: the slot stays hidden, no zeros');
|
|
112
|
+
assert.equal(offline.box().innerHTML, '');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('only Governing wears the tallies, and leaving it removes them', async () => {
|
|
116
|
+
for (const mode of ['building', 'artistry', 'ideating', null]) {
|
|
117
|
+
const { box, asked } = boot(mode, BOTH);
|
|
118
|
+
await settle();
|
|
119
|
+
assert.equal(box(), null, `${mode || 'no mode'} draws no tallies`);
|
|
120
|
+
assert.deepEqual(asked, [], `${mode || 'no mode'} asks the server for nothing`);
|
|
121
|
+
}
|
|
122
|
+
const { craft, box } = boot('governing', BOTH);
|
|
123
|
+
await settle();
|
|
124
|
+
assert.ok(box());
|
|
125
|
+
craft.choose('building');
|
|
126
|
+
assert.equal(box(), null, 'switching away takes them down');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('the server counts active + confirmed only, and sums them', async () => {
|
|
130
|
+
assert.deepEqual([...MOVING_STATUSES], ['active', 'confirmed']);
|
|
131
|
+
let seen;
|
|
132
|
+
const pool = { query: async (sql, params) => { seen = { sql, params }; return { rows: [{ status: 'active', n: 9 }, { status: 'confirmed', n: '3' }] }; } };
|
|
133
|
+
assert.deepEqual(await countMoving({ pool }), { moving: 12, active: 9, confirmed: 3 });
|
|
134
|
+
assert.deepEqual(seen.params, [['active', 'confirmed']]);
|
|
135
|
+
assert.match(seen.sql, /count\(\*\)/, 'a count in SQL, never rows to count in JS');
|
|
136
|
+
const empty = { query: async () => ({ rows: [] }) };
|
|
137
|
+
assert.deepEqual(await countMoving({ pool: empty }), { moving: 0, active: 0, confirmed: 0 }, 'a quiet board is a real zero');
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test('GET /moving answers the count, and a failed read is a 500, not a zero', async () => {
|
|
141
|
+
const res = () => { const r = { headers: {} }; r.set = (k, v) => { r.headers[k] = v; }; r.json = (b) => { r.body = b; }; r.fail = (code, o) => { r.failed = { code, status: o.status }; }; return r; };
|
|
142
|
+
const ok = res();
|
|
143
|
+
await movingHandler({ count: async () => ({ moving: 4, active: 1, confirmed: 3 }) })({}, ok);
|
|
144
|
+
assert.deepEqual(ok.body, { moving: 4, active: 1, confirmed: 3 });
|
|
145
|
+
const bad = res();
|
|
146
|
+
await movingHandler({ count: async () => { throw new Error('db down'); }, log: { error() {} } })({}, bad);
|
|
147
|
+
assert.deepEqual(bad.failed, { code: 'moving_failed', status: 500 });
|
|
148
|
+
assert.equal(bad.body, undefined);
|
|
149
|
+
});
|
package/tests/onboard.mjs
CHANGED
|
@@ -81,15 +81,15 @@ test('every form OFFERS the optional step and names what skipping costs — skil
|
|
|
81
81
|
assert.match(cli, /Press Enter to skip/, 'the terminal form offers the skip in the prompt itself');
|
|
82
82
|
assert.match(cli, /off the public map/, 'and says what a missing description means');
|
|
83
83
|
|
|
84
|
-
// the web form — since task
|
|
85
|
-
//
|
|
86
|
-
//
|
|
84
|
+
// the web form — since task 1004648 the optional step is a field of part 01 of the one
|
|
85
|
+
// page, "Your project", whose label names what the sentence is for (the public map), and
|
|
86
|
+
// the team shape is part 02's Team row
|
|
87
87
|
const hub = read('modules/public-landing/public/projects.html').replace(/\r\n/g, '\n');
|
|
88
|
-
const what = (hub.match(/<
|
|
89
|
-
assert.ok(what, 'the wizard ships the
|
|
90
|
-
assert.match(what, /<label class="wizField"><span>In a sentence <small>\(optional
|
|
91
|
-
'the sentence is offered as optional, and its label says what
|
|
92
|
-
assert.match(hub, /<div class="setRow" data-row="team">[\s\S]*?id="teamCards"/, 'the team shape rides
|
|
88
|
+
const what = (hub.match(/<div class="part" id="part-project"[\s\S]*?\n {14}<\/div>\n/) || [''])[0];
|
|
89
|
+
assert.ok(what, 'the wizard ships the part that carries the sentence');
|
|
90
|
+
assert.match(what, /<label class="wizField"><span>In a sentence <small>\(optional, it goes on the public map\)<\/small><\/span>\s*<input type="text" id="f-desc"/,
|
|
91
|
+
'the sentence is offered as optional, and its label says what it is for');
|
|
92
|
+
assert.match(hub, /<div class="setRow" data-row="team">[\s\S]*?id="teamCards"/, 'the team shape rides part 02\'s Team row');
|
|
93
93
|
assert.doesNotMatch(hub, /id="panel-detail"|id="skipDetail"/, 'the old About panel and its skip control are gone');
|
|
94
94
|
|
|
95
95
|
// the route that receives it
|
|
@@ -452,7 +452,7 @@ test('a skip moves focus on rather than stranding it inside the box it just hid'
|
|
|
452
452
|
|
|
453
453
|
await ui.skip();
|
|
454
454
|
|
|
455
|
-
assert.deepEqual(ui.focused, ['
|
|
455
|
+
assert.deepEqual(ui.focused, ['wizInviteLater'], 'the line saying where inviting lives afterwards (task 1004648)');
|
|
456
456
|
});
|
|
457
457
|
|
|
458
458
|
test('a NEW project starts the step clean — the last one’s pending lines do not follow it', async () => {
|
|
@@ -569,16 +569,17 @@ test('the project page opens the step from its own manage read, which the API al
|
|
|
569
569
|
|
|
570
570
|
// ── the markup + the sheet ───────────────────────────────────────────────────
|
|
571
571
|
|
|
572
|
-
test('the wizard’s invite step ships as real markup
|
|
573
|
-
const panel = (HUB.match(/<
|
|
572
|
+
test('the wizard’s invite step ships as real markup in part 03, with the alive moment after the checklist', () => {
|
|
573
|
+
const panel = (HUB.match(/<div class="part waiting" id="panel-done"[\s\S]*?<\/section>/) || [''])[0];
|
|
574
574
|
assert.ok(panel, '#panel-done ships as real markup');
|
|
575
575
|
assert.match(panel, /<div class="inviteBox" id="wizInvite" hidden>/, 'the step is a real element the script only shows');
|
|
576
576
|
assert.match(panel, /id="wizInviteWho"/, 'the one field');
|
|
577
577
|
assert.match(panel, /data-invite-send="wizInvite"/, 'the sender');
|
|
578
578
|
assert.match(panel, /data-invite-skip="wizInvite"/, 'and the skip is a CONTROL, not "leave it and move on"');
|
|
579
579
|
assert.match(panel, /Optional/, 'the panel says so before it asks');
|
|
580
|
-
assert.ok(panel.indexOf('id="
|
|
581
|
-
'
|
|
580
|
+
assert.ok(panel.indexOf('id="humanSteps"') < panel.indexOf('id="done-h"') && panel.indexOf('id="done-h"') < panel.indexOf('id="wizInvite"'),
|
|
581
|
+
'the mockup\'s order: the checklist, then "is alive", then the invite (task 1004648)');
|
|
582
|
+
assert.match(panel, /Invite your first builders\. They become founding builders\./, 'in the mockup\'s words');
|
|
582
583
|
assert.match(panel, /<p class="samePath" id="wizInviteLater"><\/p>/, 'and the way back afterwards is a slot beside the modules one');
|
|
583
584
|
assert.match(SCRIPT, /\$\('wizInviteLater'\)\.innerHTML = 'You can invite builders any time from ' \+ projectPageLink\('the project’s own page'\) \+ '\.';/,
|
|
584
585
|
'filled with one sentence naming THIS project, the doneModules idiom');
|