@@ -2531,3 +2531,248 @@ def test_reference_to_single_select_field_is_removed_after_trashing(
25312531 json_response = response .json ()
25322532
25332533 assert len (json_response ) == 0
2534+
2535+
2536+ @pytest .mark .django_db
2537+ @override_settings (DEBUG = True )
2538+ def test_list_rows_applies_view_sortings_per_stack (api_client , premium_data_fixture ):
2539+ user , token = premium_data_fixture .create_user_and_token (
2540+ has_active_premium_license = True
2541+ )
2542+ table = premium_data_fixture .create_database_table (user = user )
2543+ text_field = premium_data_fixture .create_text_field (table = table , primary = True )
2544+ single_select_field = premium_data_fixture .create_single_select_field (table = table )
2545+ option_a = premium_data_fixture .create_select_option (
2546+ field = single_select_field , value = "A" , color = "blue"
2547+ )
2548+ kanban = premium_data_fixture .create_kanban_view (
2549+ table = table , single_select_field = single_select_field
2550+ )
2551+ premium_data_fixture .create_view_sort (view = kanban , field = text_field , order = "ASC" )
2552+
2553+ model = table .get_model ()
2554+ # Insert rows in unsorted order; the view sort should reorder them.
2555+ row_a_c = model .objects .create (
2556+ ** {
2557+ f"field_{ text_field .id } " : "C" ,
2558+ f"field_{ single_select_field .id } _id" : option_a .id ,
2559+ }
2560+ )
2561+ row_a_a = model .objects .create (
2562+ ** {
2563+ f"field_{ text_field .id } " : "A" ,
2564+ f"field_{ single_select_field .id } _id" : option_a .id ,
2565+ }
2566+ )
2567+ row_a_b = model .objects .create (
2568+ ** {
2569+ f"field_{ text_field .id } " : "B" ,
2570+ f"field_{ single_select_field .id } _id" : option_a .id ,
2571+ }
2572+ )
2573+ row_null_b = model .objects .create (
2574+ ** {
2575+ f"field_{ text_field .id } " : "B" ,
2576+ f"field_{ single_select_field .id } _id" : None ,
2577+ }
2578+ )
2579+ row_null_a = model .objects .create (
2580+ ** {
2581+ f"field_{ text_field .id } " : "A" ,
2582+ f"field_{ single_select_field .id } _id" : None ,
2583+ }
2584+ )
2585+
2586+ url = reverse ("api:database:views:kanban:list" , kwargs = {"view_id" : kanban .id })
2587+ response = api_client .get (url , ** {"HTTP_AUTHORIZATION" : f"JWT { token } " })
2588+ response_json = response .json ()
2589+ assert response .status_code == HTTP_200_OK
2590+
2591+ null_results = response_json ["rows" ]["null" ]["results" ]
2592+ assert [r ["id" ] for r in null_results ] == [row_null_a .id , row_null_b .id ]
2593+
2594+ a_results = response_json ["rows" ][str (option_a .id )]["results" ]
2595+ assert [r ["id" ] for r in a_results ] == [row_a_a .id , row_a_b .id , row_a_c .id ]
2596+
2597+
2598+ @pytest .mark .django_db
2599+ @override_settings (DEBUG = True )
2600+ def test_list_public_rows_applies_view_sortings_per_stack (
2601+ api_client , premium_data_fixture
2602+ ):
2603+ user , _ = premium_data_fixture .create_user_and_token ()
2604+ table = premium_data_fixture .create_database_table (user = user )
2605+ text_field = premium_data_fixture .create_text_field (table = table , primary = True )
2606+ single_select_field = premium_data_fixture .create_single_select_field (table = table )
2607+ option_a = premium_data_fixture .create_select_option (
2608+ field = single_select_field , value = "A" , color = "blue"
2609+ )
2610+ kanban_view = premium_data_fixture .create_kanban_view (
2611+ table = table ,
2612+ user = user ,
2613+ public = True ,
2614+ single_select_field = single_select_field ,
2615+ )
2616+ premium_data_fixture .create_kanban_view_field_option (
2617+ kanban_view , text_field , hidden = False
2618+ )
2619+ premium_data_fixture .create_view_sort (
2620+ view = kanban_view , field = text_field , order = "DESC"
2621+ )
2622+
2623+ model = table .get_model ()
2624+ row_a_a = model .objects .create (
2625+ ** {
2626+ f"field_{ text_field .id } " : "A" ,
2627+ f"field_{ single_select_field .id } _id" : option_a .id ,
2628+ }
2629+ )
2630+ row_a_c = model .objects .create (
2631+ ** {
2632+ f"field_{ text_field .id } " : "C" ,
2633+ f"field_{ single_select_field .id } _id" : option_a .id ,
2634+ }
2635+ )
2636+ row_a_b = model .objects .create (
2637+ ** {
2638+ f"field_{ text_field .id } " : "B" ,
2639+ f"field_{ single_select_field .id } _id" : option_a .id ,
2640+ }
2641+ )
2642+
2643+ response = api_client .get (
2644+ reverse (
2645+ "api:database:views:kanban:public_rows" ,
2646+ kwargs = {"slug" : kanban_view .slug },
2647+ )
2648+ )
2649+ response_json = response .json ()
2650+ assert response .status_code == HTTP_200_OK
2651+
2652+ a_results = response_json ["rows" ][str (option_a .id )]["results" ]
2653+ assert [r ["id" ] for r in a_results ] == [row_a_c .id , row_a_b .id , row_a_a .id ]
2654+
2655+
2656+ @pytest .mark .django_db
2657+ @override_settings (DEBUG = True )
2658+ def test_list_public_rows_adhoc_order_by_overrides_view_sortings (
2659+ api_client , premium_data_fixture
2660+ ):
2661+ user , _ = premium_data_fixture .create_user_and_token ()
2662+ table = premium_data_fixture .create_database_table (user = user )
2663+ text_field = premium_data_fixture .create_text_field (table = table , primary = True )
2664+ single_select_field = premium_data_fixture .create_single_select_field (table = table )
2665+ option_a = premium_data_fixture .create_select_option (
2666+ field = single_select_field , value = "A" , color = "blue"
2667+ )
2668+ kanban_view = premium_data_fixture .create_kanban_view (
2669+ table = table ,
2670+ user = user ,
2671+ public = True ,
2672+ single_select_field = single_select_field ,
2673+ )
2674+ premium_data_fixture .create_kanban_view_field_option (
2675+ kanban_view , text_field , hidden = False
2676+ )
2677+ # The view's own sort is DESC; the adhoc `order_by` query parameter should
2678+ # override this and sort ASC instead.
2679+ premium_data_fixture .create_view_sort (
2680+ view = kanban_view , field = text_field , order = "DESC"
2681+ )
2682+
2683+ model = table .get_model ()
2684+ row_a_b = model .objects .create (
2685+ ** {
2686+ f"field_{ text_field .id } " : "B" ,
2687+ f"field_{ single_select_field .id } _id" : option_a .id ,
2688+ }
2689+ )
2690+ row_a_a = model .objects .create (
2691+ ** {
2692+ f"field_{ text_field .id } " : "A" ,
2693+ f"field_{ single_select_field .id } _id" : option_a .id ,
2694+ }
2695+ )
2696+ row_a_c = model .objects .create (
2697+ ** {
2698+ f"field_{ text_field .id } " : "C" ,
2699+ f"field_{ single_select_field .id } _id" : option_a .id ,
2700+ }
2701+ )
2702+
2703+ response = api_client .get (
2704+ reverse (
2705+ "api:database:views:kanban:public_rows" ,
2706+ kwargs = {"slug" : kanban_view .slug },
2707+ )
2708+ + f"?order_by=field_{ text_field .id } "
2709+ )
2710+ response_json = response .json ()
2711+ assert response .status_code == HTTP_200_OK
2712+
2713+ a_results = response_json ["rows" ][str (option_a .id )]["results" ]
2714+ assert [r ["id" ] for r in a_results ] == [row_a_a .id , row_a_b .id , row_a_c .id ]
2715+
2716+
2717+ @pytest .mark .django_db
2718+ @override_settings (DEBUG = True )
2719+ def test_list_public_rows_adhoc_order_by_invalid_field (
2720+ api_client , premium_data_fixture
2721+ ):
2722+ user , _ = premium_data_fixture .create_user_and_token ()
2723+ table = premium_data_fixture .create_database_table (user = user )
2724+ single_select_field = premium_data_fixture .create_single_select_field (table = table )
2725+ kanban_view = premium_data_fixture .create_kanban_view (
2726+ table = table ,
2727+ user = user ,
2728+ public = True ,
2729+ single_select_field = single_select_field ,
2730+ )
2731+
2732+ response = api_client .get (
2733+ reverse (
2734+ "api:database:views:kanban:public_rows" ,
2735+ kwargs = {"slug" : kanban_view .slug },
2736+ )
2737+ + "?order_by=field_999999"
2738+ )
2739+ response_json = response .json ()
2740+ assert response .status_code == HTTP_400_BAD_REQUEST
2741+ assert response_json ["error" ] == "ERROR_ORDER_BY_FIELD_NOT_FOUND"
2742+
2743+
2744+ @pytest .mark .django_db
2745+ @override_settings (DEBUG = True )
2746+ def test_list_public_rows_adhoc_order_by_hidden_field_not_found (
2747+ api_client , premium_data_fixture
2748+ ):
2749+ user , _ = premium_data_fixture .create_user_and_token ()
2750+ table = premium_data_fixture .create_database_table (user = user )
2751+ text_field = premium_data_fixture .create_text_field (table = table , primary = True )
2752+ hidden_text_field = premium_data_fixture .create_text_field (table = table )
2753+ single_select_field = premium_data_fixture .create_single_select_field (table = table )
2754+ kanban_view = premium_data_fixture .create_kanban_view (
2755+ table = table ,
2756+ user = user ,
2757+ public = True ,
2758+ single_select_field = single_select_field ,
2759+ )
2760+ # Hide the secondary text field; sorting on it from the public endpoint
2761+ # should be rejected the same way as sorting on a non-existing field.
2762+ premium_data_fixture .create_kanban_view_field_option (
2763+ kanban_view , text_field , hidden = False
2764+ )
2765+ premium_data_fixture .create_kanban_view_field_option (
2766+ kanban_view , hidden_text_field , hidden = True
2767+ )
2768+
2769+ response = api_client .get (
2770+ reverse (
2771+ "api:database:views:kanban:public_rows" ,
2772+ kwargs = {"slug" : kanban_view .slug },
2773+ )
2774+ + f"?order_by=field_{ hidden_text_field .id } "
2775+ )
2776+ response_json = response .json ()
2777+ assert response .status_code == HTTP_400_BAD_REQUEST
2778+ assert response_json ["error" ] == "ERROR_ORDER_BY_FIELD_NOT_FOUND"
0 commit comments