this repo has no description
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add checks to make sure too many items is checked with parsing

up until now, that was just used for how many fields to display, you could still submit too many.

+92 -6
+47 -6
formz/src/formz.gleam
··· 410 410 pub fn simple_limit_check(min: Int, max: Int, extra: Int) -> LimitCheck { 411 411 fn(num_nonempty) { 412 412 case max - num_nonempty { 413 - x if x < 0 -> Error(x) 413 + x if x < 0 -> Error(-x) 414 414 _ -> { 415 415 int.max(1 - num_nonempty, int.min(extra, max - num_nonempty)) 416 416 list.fold([1, extra, min], 0, int.max) ··· 507 507 let assert [ListField(field, states, limit_check, widget), ..next_items] = 508 508 items 509 509 510 - // go through all decode all input values. these can have empty rows 510 + // go through and parse all input values. these can have empty rows 511 511 // that were offered to the consumer, but they didn't fill out. we need 512 - // to keep track of those so they can be used when generating the form 513 - // again on error 512 + // to keep track of those so they can be displayed when generating the form 513 + // again on error. 514 514 let item_results = 515 - list.map(states, parse_list_state(_, definition.parse, definition.stub)) 515 + states 516 + |> list.map(parse_list_state(_, definition.parse, definition.stub)) 517 + // then we need to check if too many values were submitted, and if so 518 + // mark the extra ones as having errors 519 + |> mark_above_max_values_as_invalid(limit_check) 516 520 517 521 // but we don't want them for considering the output of this list field, 518 522 // so remove the empty optional fields and just grab the outputs ··· 587 591 stub: a, 588 592 ) -> ListParsingResult(a) { 589 593 case state.value, state.requirement { 590 - "", Required -> parse(state.value) 591 594 "", Optional -> Ok(stub) 592 595 _, _ -> parse(state.value) 593 596 } 594 597 |> ListParsingResult(state.value, state.requirement, _) 598 + } 599 + 600 + fn mark_above_max_values_as_invalid( 601 + list: List(ListParsingResult(output)), 602 + limit_check: LimitCheck, 603 + ) -> List(ListParsingResult(output)) { 604 + let count = 605 + list.fold(list, 0, fn(acc, r) { 606 + case r.value, r.requirement { 607 + "", Optional -> acc 608 + _, _ -> acc + 1 609 + } 610 + }) 611 + 612 + case limit_check(count) { 613 + Ok(_) -> list 614 + Error(num_too_many) -> { 615 + let max_index = count - num_too_many 616 + 617 + let #(mapped_results, _) = 618 + list.fold(list, #([], 0), fn(acc, r) { 619 + let #(results, i) = acc 620 + case r.value, r.requirement, i >= max_index { 621 + "", Optional, _ -> #([r, ..results], i) 622 + _, _, False -> #([r, ..results], i + 1) 623 + v, r, True -> #( 624 + [ 625 + ListParsingResult(v, r, Error("exceeds maximum allowed items")), 626 + ..results 627 + ], 628 + i + 1, 629 + ) 630 + } 631 + }) 632 + 633 + mapped_results |> list.reverse 634 + } 635 + } 595 636 } 596 637 597 638 /// Add a list field to a form, but with no limits on the number of values that
+45
formz/test/formz_test.gleam
··· 690 690 Valid("2", Optional), 691 691 ]) 692 692 } 693 + 694 + pub fn limited_list_too_many_test() { 695 + let f = { 696 + use a <- formz.limited_list( 697 + formz.limit_between(2, 3), 698 + field("a"), 699 + integer_field(), 700 + ) 701 + 702 + formz.create_form(a) 703 + } 704 + 705 + // straight up too many 706 + f 707 + |> formz.data([ 708 + #("a", "1"), 709 + #("a", "2"), 710 + #("a", "3"), 711 + #("a", "4"), 712 + #("a", "5"), 713 + ]) 714 + |> formz.decode 715 + |> get_form_from_error_result 716 + |> formz.get_states 717 + |> should.equal([ 718 + Valid("1", Required), 719 + Valid("2", Required), 720 + Valid("3", Optional), 721 + Invalid("4", Optional, "exceeds maximum allowed items"), 722 + Invalid("5", Optional, "exceeds maximum allowed items"), 723 + ]) 724 + 725 + // too many but with an empty value that should be skipped 726 + f 727 + |> formz.data([#("a", "1"), #("a", ""), #("a", "3"), #("a", "4"), #("a", "5")]) 728 + |> formz.decode 729 + |> get_form_from_error_result 730 + |> formz.get_states 731 + |> should.equal([ 732 + Valid("1", Required), 733 + Valid("3", Required), 734 + Valid("4", Optional), 735 + Invalid("5", Optional, "exceeds maximum allowed items"), 736 + ]) 737 + }