PS pension module: optional federal PSSA engine + UI (PSPC-accurate, EN/FR)
This commit is contained in:
1 parent
2ab52c2f5e
commit
249be69a57
14 files changed
+1991
-27
No files matched your search
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"http_code": "200",
|
||||
"pspension_code": "200",
|
||||
"html_has_pspension_script": true,
|
||||
"html_has_ps_card": true,
|
||||
"pspension_has_formula": true,
|
||||
"pspension_has_it_asof": true,
|
||||
"i18n_ps_en": true,
|
||||
"i18n_ps_fr": true,
|
||||
"pspension_js_size": 11233,
|
||||
"checked_at": "2026-10-09T15:42:59Z",
|
||||
"vantage": "trouble@100.96.20.61 (Midhurst, off-LAN)",
|
||||
"all_ok": true
|
||||
}
|
||||
@@ -0,0 +1,818 @@
|
||||
[
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "iphone14",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 358,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "pixel",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 328,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "se",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 288,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "en",
|
||||
"device": "desktop",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 1028,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "iphone14",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 358,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "pixel",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 328,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": true,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "se",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 288,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "ps-toggle",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "ps-join",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "ps-service",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "ps-salary",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "ps-occ",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "ps-it",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "extra-note",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"device": "desktop",
|
||||
"shot": "results-pscard",
|
||||
"geo": {
|
||||
"docOverflowX": 0,
|
||||
"stepBodyScroll": false,
|
||||
"btnNextInView": true,
|
||||
"psCard": {
|
||||
"visible": true,
|
||||
"width": 1028,
|
||||
"fits": true,
|
||||
"links": 6
|
||||
}
|
||||
},
|
||||
"ok": true,
|
||||
"bad": []
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
"""PS pension module UI audit — https://retire.krisforbes.ca in EN + FR at 320/360/390 + 1280.
|
||||
Drives localStorage state (PS answers), captures screenshots + geometry at the PS quiz steps
|
||||
and the results card. Checks:
|
||||
- no horizontal document overflow (scrollWidth <= innerWidth + 1)
|
||||
- #step-body is the scroller; #btn-next + #panel bottom cluster fully in viewport
|
||||
- #ps-card table fits the viewport; sources links present
|
||||
Writes audit/ps-pension/geo.json + *.png, prints PS-AUDIT-OK/FAIL.
|
||||
"""
|
||||
import json, os, sys
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
OUT = 'audit/ps-pension'
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
CHROME = '/usr/bin/google-chrome'
|
||||
BASE = 'https://retire.krisforbes.ca/'
|
||||
LS = 'retire-planner-v1'
|
||||
|
||||
ANS = {
|
||||
"province": "ON", "age": 60, "retireAge": 60, "household": "single",
|
||||
"partner": {"age": 60, "income": 0, "rrsp": 0, "tfsa": 0, "nonreg": 0, "monthlyContribution": 0},
|
||||
"income": 0, "rrsp": 100000, "tfsa": 30000, "nonreg": 20000,
|
||||
"monthlyContribution": 0, "employerMatchMonthly": 0,
|
||||
"spendingAnnual": 50000, "cppStartAge": 65, "oasStartAge": 65,
|
||||
"pensionAnnual": 0, "rentalAnnual": 0, "otherAnnual": 0,
|
||||
"psPension": True, "psJoinYear": 2000, "psServiceYears": 30, "psAvgSalary": 100000,
|
||||
"psOccupation": "it", "psItLevel": "IT-02", "psItStep": 1,
|
||||
"realReturnPre": 3.5, "realReturnPost": 2.5, "inflation": 2.0, "lifeExp": 95,
|
||||
"interests": ["dock", "travel"],
|
||||
}
|
||||
STEPS = { # visible step index (single household, module ON): 20 steps
|
||||
'ps-toggle': 11, 'ps-join': 12, 'ps-service': 13, 'ps-salary': 14,
|
||||
'ps-occ': 15, 'ps-it': 16, 'extra-note': 17,
|
||||
}
|
||||
DEVICES = [
|
||||
('iphone14', 390, 844, 3.0),
|
||||
('pixel', 360, 800, 2.75),
|
||||
('se', 320, 700, 2.0),
|
||||
('desktop', 1280, 900, 1.0),
|
||||
]
|
||||
|
||||
GEO_JS = """() => {
|
||||
const de = document.documentElement;
|
||||
const out = {
|
||||
docOverflowX: de.scrollWidth - window.innerWidth,
|
||||
stepBodyScroll: (() => { const s = document.getElementById('step-body'); return s ? (s.scrollHeight > s.clientHeight) : null; })(),
|
||||
btnNextInView: (() => { const b = document.getElementById('btn-next'); if (!b) return null; const r = b.getBoundingClientRect(); return r.bottom <= window.innerHeight + 1 && r.top >= -1; })(),
|
||||
};
|
||||
const card = document.getElementById('ps-card');
|
||||
if (card && !card.hidden) {
|
||||
const r = card.getBoundingClientRect();
|
||||
const t = card.querySelector('table');
|
||||
out.psCard = { visible: getComputedStyle(card).display !== 'none', width: Math.round(r.width),
|
||||
fits: (t ? t.scrollWidth : 0) <= window.innerWidth + 1,
|
||||
links: card.querySelectorAll('a').length };
|
||||
}
|
||||
return out;
|
||||
}"""
|
||||
|
||||
def main():
|
||||
results, fails = [], 0
|
||||
with sync_playwright() as pw:
|
||||
browser = pw.chromium.launch(executable_path=CHROME)
|
||||
for lang in ('en', 'fr'):
|
||||
for name, w, h, dpr in DEVICES:
|
||||
ctx = browser.new_context(viewport={'width': w, 'height': h}, device_scale_factor=dpr,
|
||||
is_mobile=(w < 800), has_touch=(w < 800))
|
||||
page = ctx.new_page()
|
||||
page.goto(BASE, wait_until='domcontentloaded')
|
||||
page.evaluate("([ls, st]) => localStorage.setItem(ls, JSON.stringify(st))",
|
||||
[LS, {"a": ANS, "step": 0, "screen": "quiz", "lang": lang}])
|
||||
for shot, idx in STEPS.items():
|
||||
page.evaluate("([ls, st]) => localStorage.setItem(ls, JSON.stringify(st))",
|
||||
[LS, {"a": ANS, "step": idx, "screen": "quiz", "lang": lang}])
|
||||
page.reload(wait_until='domcontentloaded')
|
||||
page.wait_for_timeout(350)
|
||||
geo = page.evaluate(GEO_JS)
|
||||
png = f"{OUT}/{lang}-{name}-{shot}.png"
|
||||
page.screenshot(path=png)
|
||||
bad = [k for k in ('docOverflowX',) if geo[k] > 1]
|
||||
if geo.get('btnNextInView') is False: bad.append('btnNext')
|
||||
rec = {"lang": lang, "device": name, "shot": shot, "geo": geo, "ok": not bad, "bad": bad}
|
||||
results.append(rec); fails += 1 if bad else 0
|
||||
if not bad: print(f" ok {lang} {name:9s} {shot}")
|
||||
else: print(f" FAIL {lang} {name:9s} {shot} {bad} {geo}")
|
||||
# results screen with PS card
|
||||
page.evaluate("([ls, st]) => localStorage.setItem(ls, JSON.stringify(st))",
|
||||
[LS, {"a": ANS, "step": 0, "screen": "results", "lang": lang}])
|
||||
page.reload(wait_until='domcontentloaded')
|
||||
page.wait_for_timeout(900)
|
||||
geo = page.evaluate(GEO_JS)
|
||||
page.evaluate("() => { const c = document.getElementById('ps-card'); if (c) c.scrollIntoView(); }")
|
||||
page.wait_for_timeout(200)
|
||||
page.screenshot(path=f"{OUT}/{lang}-{name}-results-pscard.png")
|
||||
bad = []
|
||||
if geo.get('docOverflowX', 0) > 1: bad.append('overflowX')
|
||||
pc = geo.get('psCard')
|
||||
if not pc or not pc.get('visible'): bad.append('psCardHidden')
|
||||
elif not pc.get('fits'): bad.append('psCardWide')
|
||||
elif pc.get('links', 0) < 5: bad.append('links<5')
|
||||
rec = {"lang": lang, "device": name, "shot": "results-pscard", "geo": geo, "ok": not bad, "bad": bad}
|
||||
results.append(rec); fails += 1 if bad else 0
|
||||
if not bad: print(f" ok {lang} {name:9s} results-pscard")
|
||||
else: print(f" FAIL {lang} {name:9s} results-pscard {bad} {geo}")
|
||||
ctx.close()
|
||||
browser.close()
|
||||
with open(f'{OUT}/geo.json', 'w') as f:
|
||||
json.dump(results, f, indent=1)
|
||||
print(f"{len(results)} shots, {fails} failures")
|
||||
print("PS-AUDIT-OK" if fails == 0 else "PS-AUDIT-FAIL")
|
||||
sys.exit(1 if fails else 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Off-LAN reachability + PS-module content check for https://retire.krisforbes.ca/
|
||||
via the Midhurst troublebox (outside the LAN). Verifies 200 on index + pspension.js
|
||||
and PS markers (EN card strings + FR strings) in the served bundles.
|
||||
Writes audit/ps-geo-check.json, prints OFFLAN-OK."""
|
||||
import json, sys, time
|
||||
import paramiko
|
||||
|
||||
CANDS = ["b1tvvt07", "ubnt", "admin", "password", "b1tvvt07!", "1234", "root", "glinet"]
|
||||
URL = "https://retire.krisforbes.ca/"
|
||||
|
||||
def main():
|
||||
conn = None
|
||||
for pw in CANDS:
|
||||
c = paramiko.SSHClient()
|
||||
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
try:
|
||||
c.connect("100.96.20.61", port=2222, username="trouble", password=pw,
|
||||
timeout=25, banner_timeout=25, auth_timeout=25,
|
||||
allow_agent=False, look_for_keys=False)
|
||||
conn = c
|
||||
break
|
||||
except Exception:
|
||||
c.close()
|
||||
if conn is None:
|
||||
print("OFFLAN-FAIL: no auth to troublebox")
|
||||
sys.exit(1)
|
||||
|
||||
def run(cmd):
|
||||
_, out, _ = conn.exec_command(cmd, timeout=60)
|
||||
return out.read().decode("utf-8", "replace").strip()
|
||||
|
||||
code = run(f"curl -s -o /dev/null -w '%{{http_code}}' {URL} --max-time 30")
|
||||
psp_code = run(f"curl -s -o /dev/null -w '%{{http_code}}' {URL}engine/pspension.js --max-time 30")
|
||||
html = run(f"curl -s {URL} --max-time 30 | head -c 300000")
|
||||
psp = run(f"curl -s {URL}engine/pspension.js --max-time 30 | head -c 300000")
|
||||
i18n = run(f"curl -s {URL}i18n.js --max-time 30 | head -c 400000")
|
||||
conn.close()
|
||||
|
||||
checks = {
|
||||
"http_code": code,
|
||||
"pspension_code": psp_code,
|
||||
"html_has_pspension_script": "engine/pspension.js" in html,
|
||||
"html_has_ps_card": 'id="ps-card"' in html,
|
||||
"pspension_has_formula": "0.01375" in psp and "0.00625" in psp,
|
||||
"pspension_has_it_asof": "2024-12-22" in psp,
|
||||
"i18n_ps_en": "federal public service pension" in i18n,
|
||||
"i18n_ps_fr": "prestation de raccordement" in i18n or "fonction publique f" in i18n,
|
||||
"pspension_js_size": len(psp),
|
||||
"checked_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
||||
"vantage": "trouble@100.96.20.61 (Midhurst, off-LAN)",
|
||||
}
|
||||
checks["all_ok"] = (code == "200" and psp_code == "200"
|
||||
and checks["html_has_pspension_script"] and checks["html_has_ps_card"]
|
||||
and checks["pspension_has_formula"] and checks["pspension_has_it_asof"]
|
||||
and checks["i18n_ps_en"] and checks["i18n_ps_fr"])
|
||||
with open("audit/ps-geo-check.json", "w") as f:
|
||||
json.dump(checks, f, indent=2, ensure_ascii=False)
|
||||
print(json.dumps(checks, indent=2, ensure_ascii=False))
|
||||
print("OFFLAN-OK" if checks["all_ok"] else "OFFLAN-FAIL")
|
||||
sys.exit(0 if checks["all_ok"] else 1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user