| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- //! E2E bootstrap fixture tests (todo 31).
- //!
- //! All passwords and TOTP secrets below are synthetic test values in temp
- //! dirs — never the real `config/` tree, never real credentials.
- use std::fs;
- use provision::e2e::{
- CHANGE_CONFIRM_FIELD, CHANGE_NEW_PASSWORD_FIELD, CONSENT_APPROVE_VALUE, CONSENT_DECISION_FIELD,
- CONSENT_REQUEST_ID_FIELD, CSRF_FIELD, E2eError, LOGIN_CODE_FIELD, LOGIN_EMAIL_FIELD,
- LOGIN_PASSWORD_FIELD, MISSING_FIXTURE_HINT, WriteOutcome, load, write_initial,
- };
- #[cfg(unix)]
- fn assert_0600(path: &std::path::Path) {
- use std::os::unix::fs::PermissionsExt as _;
- let mode = fs::metadata(path)
- .expect("fixture metadata")
- .permissions()
- .mode()
- & 0o777;
- assert_eq!(mode, 0o600, "fixture at `{}` is not 0600", path.display());
- }
- #[test]
- fn writes_email_and_password_0600_only_when_absent() {
- let dir = tempfile::tempdir().expect("tempdir");
- let out = dir.path().join("e2e.json");
- let outcome = write_initial(&out, "demo@example.com", "test-password-01").expect("first write");
- assert_eq!(outcome, WriteOutcome::Created);
- let raw = fs::read_to_string(&out).expect("fixture readable");
- let value: serde_json::Value = serde_json::from_str(&raw).expect("fixture is JSON");
- assert_eq!(
- value.get("email").and_then(|email| email.as_str()),
- Some("demo@example.com")
- );
- assert_eq!(
- value.get("password").and_then(|password| password.as_str()),
- Some("test-password-01")
- );
- assert!(
- value.get("totp_secret").is_none(),
- "provision must not write the spec-owned totp_secret field"
- );
- #[cfg(unix)]
- assert_0600(&out);
- }
- #[test]
- fn leaves_an_existing_file_byte_for_byte_untouched() {
- let dir = tempfile::tempdir().expect("tempdir");
- let out = dir.path().join("e2e.json");
- // A spec-owned file: rotated password plus a captured TOTP secret.
- let spec_owned =
- r#"{"email":"demo@example.com","password":"rotated-by-spec","totp_secret":"JBSWY3DPEHPK3PXP"}"#;
- fs::write(&out, spec_owned).expect("pre-existing fixture");
- let outcome = write_initial(&out, "demo@example.com", "initial-password").expect("second write");
- assert_eq!(outcome, WriteOutcome::Kept);
- let raw = fs::read_to_string(&out).expect("fixture readable");
- assert_eq!(raw, spec_owned, "existing fixture must be untouched");
- }
- #[test]
- fn written_fixture_round_trips_through_load() {
- let dir = tempfile::tempdir().expect("tempdir");
- let out = dir.path().join("nested/e2e.json");
- write_initial(&out, "demo@example.com", "test-password-01").expect("write");
- let fixture = load(&out).expect("load");
- assert_eq!(fixture.email, "demo@example.com");
- assert_eq!(fixture.password, "test-password-01");
- assert_eq!(fixture.totp_secret, None);
- }
- #[test]
- fn missing_fixture_load_fails_with_run_provision_first_hint() {
- let dir = tempfile::tempdir().expect("tempdir");
- let out = dir.path().join("e2e.json");
- let result = load(&out);
- assert!(
- matches!(result, Err(E2eError::Missing { .. })),
- "expected Missing, got {result:?}"
- );
- let message = result.expect_err("missing fixture").to_string();
- assert!(
- message.contains("provision"),
- "hint must name provision: {message}"
- );
- assert!(
- message.contains(MISSING_FIXTURE_HINT),
- "hint must match the documented contract: {message}"
- );
- }
- #[test]
- fn malformed_fixture_is_a_typed_parse_error() {
- let dir = tempfile::tempdir().expect("tempdir");
- let out = dir.path().join("e2e.json");
- fs::write(&out, "{not json").expect("malformed fixture");
- let result = load(&out);
- assert!(matches!(result, Err(E2eError::Parse { .. })));
- }
- #[test]
- fn debug_redacts_password_and_totp_secret() {
- let dir = tempfile::tempdir().expect("tempdir");
- let out = dir.path().join("e2e.json");
- write_initial(&out, "demo@example.com", "S3CRET-PW").expect("write");
- let mut fixture = load(&out).expect("load");
- fixture.totp_secret = Some("S3CRET-TOTP".to_owned());
- let rendered = format!("{fixture:?}");
- assert!(
- !rendered.contains("S3CRET-PW"),
- "password leaked: {rendered}"
- );
- assert!(
- !rendered.contains("S3CRET-TOTP"),
- "totp secret leaked: {rendered}"
- );
- assert!(rendered.contains("demo@example.com"));
- }
- #[test]
- fn documented_selectors_match_the_d_oauth_templates() {
- // Login form (`src/ui/login.rs` `LoginTemplate`).
- assert_eq!(LOGIN_EMAIL_FIELD, "email");
- assert_eq!(LOGIN_PASSWORD_FIELD, "password");
- assert_eq!(LOGIN_CODE_FIELD, "code");
- // Hidden form token on every d-OAuth form.
- assert_eq!(CSRF_FIELD, "csrf");
- // Password-change form (`PasswordTemplate`).
- assert_eq!(CHANGE_NEW_PASSWORD_FIELD, "new_password");
- assert_eq!(CHANGE_CONFIRM_FIELD, "confirm");
- // Consent form (`src/ui/consent.rs` `ConsentTemplate`/`ConsentForm`).
- assert_eq!(CONSENT_REQUEST_ID_FIELD, "request_id");
- assert_eq!(CONSENT_DECISION_FIELD, "decision");
- assert_eq!(CONSENT_APPROVE_VALUE, "approve");
- }
|