1 /* GTK - The GIMP Toolkit
2 * autotestfilechooser.c: Automated unit tests for the GtkFileChooser widget
3 * Copyright (C) 2005, Novell, Inc.
6 * Federico Mena-Quintero <federico@novell.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 #define GTK_FILE_SYSTEM_ENABLE_UNSUPPORTED
27 #include <glib/gprintf.h>
29 #include "gtk/gtkfilechooserprivate.h"
30 #include "gtk/gtkfilechooserdefault.h"
31 #include "gtk/gtkfilechooserentry.h"
34 log_test (gboolean passed, const char *test_name, ...)
39 va_start (args, test_name);
40 str = g_strdup_vprintf (test_name, args);
43 g_printf ("%s: %s\n", passed ? "PASSED" : "FAILED", str);
47 static const GtkFileChooserAction open_actions[] = {
48 GTK_FILE_CHOOSER_ACTION_OPEN,
49 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
52 static const GtkFileChooserAction save_actions[] = {
53 GTK_FILE_CHOOSER_ACTION_SAVE,
54 GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
59 has_action (const GtkFileChooserAction *actions,
61 GtkFileChooserAction sought_action)
65 for (i = 0; i < n_actions; i++)
66 if (actions[i] == sought_action)
73 get_action_name (GtkFileChooserAction action)
75 GEnumClass *enum_class;
76 GEnumValue *enum_value;
78 enum_class = g_type_class_peek (GTK_TYPE_FILE_CHOOSER_ACTION);
80 g_error ("BUG: get_action_name(): no GEnumClass for GTK_TYPE_FILE_CHOOSER_ACTION");
82 enum_value = g_enum_get_value (enum_class, (int) action);
84 g_error ("BUG: get_action_name(): no GEnumValue for GtkFileChooserAction %d", (int) action);
86 return enum_value->value_name;
89 static GtkFileChooserDefault *
90 get_impl_from_dialog (GtkWidget *dialog)
92 GtkFileChooserDialog *d;
93 GtkFileChooserDialogPrivate *dialog_priv;
94 GtkFileChooserWidget *chooser_widget;
95 GtkFileChooserWidgetPrivate *widget_priv;
96 GtkFileChooserDefault *impl;
98 d = GTK_FILE_CHOOSER_DIALOG (dialog);
99 dialog_priv = d->priv;
100 chooser_widget = GTK_FILE_CHOOSER_WIDGET (dialog_priv->widget);
102 g_error ("BUG: dialog_priv->widget is not a GtkFileChooserWidget");
104 widget_priv = chooser_widget->priv;
105 impl = (GtkFileChooserDefault *) (widget_priv->impl);
107 g_error ("BUG: widget_priv->impl is not a GtkFileChooserDefault");
113 test_widgets_for_current_action (GtkFileChooserDialog *dialog,
114 GtkFileChooserAction expected_action)
116 GtkFileChooserDefault *impl;
119 if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog)) != expected_action)
122 impl = get_impl_from_dialog (GTK_WIDGET (dialog));
124 g_assert (impl->action == expected_action);
128 /* OPEN implies that the "new folder" button is hidden; otherwise it is shown */
129 if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
130 passed = passed && !GTK_WIDGET_VISIBLE (impl->browse_new_folder_button);
132 passed = passed && GTK_WIDGET_VISIBLE (impl->browse_new_folder_button);
134 /* Check that the widgets are present/visible or not */
135 if (has_action (open_actions, G_N_ELEMENTS (open_actions), impl->action))
137 passed = passed && (impl->save_widgets == NULL
138 && impl->save_file_name_entry == NULL
139 && impl->save_folder_label == NULL
140 && impl->save_folder_combo == NULL
141 && impl->save_expander == NULL
142 && GTK_IS_CONTAINER (impl->browse_widgets) && GTK_WIDGET_DRAWABLE (impl->browse_widgets));
144 else if (has_action (save_actions, G_N_ELEMENTS (save_actions), impl->action))
146 /* FIXME: we can't use GTK_IS_FILE_CHOOSER_ENTRY() because it uses
147 * _gtk_file_chooser_entry_get_type(), which is a non-exported symbol.
148 * So, we just test impl->save_file_name_entry for being non-NULL
150 passed = passed && (GTK_IS_CONTAINER (impl->save_widgets) && GTK_WIDGET_DRAWABLE (impl->save_widgets)
151 && impl->save_file_name_entry != NULL && GTK_WIDGET_DRAWABLE (impl->save_file_name_entry)
152 && GTK_IS_LABEL (impl->save_folder_label) && GTK_WIDGET_DRAWABLE (impl->save_folder_label)
153 && GTK_IS_COMBO_BOX (impl->save_folder_combo) && GTK_WIDGET_DRAWABLE (impl->save_folder_combo)
154 && GTK_IS_EXPANDER (impl->save_expander) && GTK_WIDGET_DRAWABLE (impl->save_expander)
155 && GTK_IS_CONTAINER (impl->browse_widgets));
157 /* FIXME: we are in a SAVE mode; test the visibility and sensitivity of
158 * the children that change depending on the state of the expander.
163 g_error ("BAD TEST: test_widgets_for_current_action() doesn't know about %s", get_action_name (impl->action));
170 typedef gboolean (* ForeachActionCallback) (GtkFileChooserDialog *dialog,
171 GtkFileChooserAction action,
175 foreach_action (GtkFileChooserDialog *dialog,
176 ForeachActionCallback callback,
179 GEnumClass *enum_class;
182 enum_class = g_type_class_peek (GTK_TYPE_FILE_CHOOSER_ACTION);
184 g_error ("BUG: get_action_name(): no GEnumClass for GTK_TYPE_FILE_CHOOSER_ACTION");
186 for (i = 0; i < enum_class->n_values; i++)
188 GEnumValue *enum_value;
189 GtkFileChooserAction action;
192 enum_value = enum_class->values + i;
193 action = enum_value->value;
195 passed = (* callback) (dialog, action, user_data);
203 struct action_closure {
204 GtkFileChooserAction from_action;
208 switch_from_to_action_cb (GtkFileChooserDialog *dialog,
209 GtkFileChooserAction action,
212 struct action_closure *closure;
217 gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), closure->from_action);
219 passed = test_widgets_for_current_action (dialog, closure->from_action);
220 log_test (passed, "switch_from_to_action_cb(): reset to action %s", get_action_name (closure->from_action));
224 gtk_file_chooser_set_action (GTK_FILE_CHOOSER (dialog), action);
226 passed = test_widgets_for_current_action (dialog, action);
227 log_test (passed, "switch_from_to_action_cb(): transition from %s to %s",
228 get_action_name (closure->from_action),
229 get_action_name (action));
234 switch_from_action_cb (GtkFileChooserDialog *dialog,
235 GtkFileChooserAction action,
238 struct action_closure closure;
240 closure.from_action = action;
242 return foreach_action (dialog, switch_from_to_action_cb, &closure);
246 test_action_widgets (void)
249 GtkFileChooserAction action;
252 dialog = gtk_file_chooser_dialog_new ("Test file chooser",
254 GTK_FILE_CHOOSER_ACTION_OPEN,
260 gtk_widget_show_now (dialog);
262 action = gtk_file_chooser_get_action (GTK_FILE_CHOOSER (dialog));
264 passed = test_widgets_for_current_action (GTK_FILE_CHOOSER_DIALOG (dialog), action);
265 log_test (passed, "test_action_widgets(): widgets for initial action %s", get_action_name (action));
269 passed = foreach_action (GTK_FILE_CHOOSER_DIALOG (dialog), switch_from_action_cb, NULL);
270 log_test (passed, "test_action_widgets(): all transitions through property change");
272 gtk_widget_destroy (dialog);
278 test_reload_sequence (gboolean set_folder_before_map)
281 GtkFileChooserDefault *impl;
286 dialog = gtk_file_chooser_dialog_new ("Test file chooser",
288 GTK_FILE_CHOOSER_ACTION_OPEN,
294 impl = get_impl_from_dialog (dialog);
296 if (set_folder_before_map)
298 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ());
300 passed = (impl->current_folder != NULL
301 && impl->browse_files_model != NULL
302 && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
303 && impl->reload_state == RELOAD_HAS_FOLDER
304 && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
305 && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
306 ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
311 /* Initially, no folder is not loaded or pending */
312 passed = passed && (impl->current_folder == NULL
313 && impl->sort_model == NULL
314 && impl->browse_files_model == NULL
315 && impl->load_state == LOAD_EMPTY
316 && impl->reload_state == RELOAD_EMPTY
317 && impl->load_timeout_id == 0);
323 /* After mapping, it is loading some folder, either the one that was explicitly set or the default one */
325 gtk_widget_show_now (dialog);
327 passed = (impl->current_folder != NULL
328 && impl->browse_files_model != NULL
329 && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
330 && impl->reload_state == RELOAD_HAS_FOLDER
331 && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
332 && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
333 ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
338 /* Unmap it; we should still have a folder */
340 gtk_widget_hide (dialog);
342 passed = (impl->current_folder != NULL
343 && impl->browse_files_model != NULL
344 && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
345 && impl->reload_state == RELOAD_WAS_UNMAPPED
346 && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
347 && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
348 ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
355 gtk_widget_show_now (dialog);
357 passed = (impl->current_folder != NULL
358 && impl->browse_files_model != NULL
359 && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
360 && impl->reload_state == RELOAD_HAS_FOLDER
361 && (impl->load_state == LOAD_PRELOAD ? (impl->load_timeout_id != 0) : TRUE)
362 && ((impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED)
363 ? (impl->load_timeout_id == 0 && impl->sort_model != NULL)
368 gtk_widget_destroy (dialog);
378 passed = test_reload_sequence (FALSE);
379 log_test (passed, "test_reload(): create and use the default folder");
383 passed = test_reload_sequence (TRUE);
384 log_test (passed, "test_reload(): set a folder explicitly before mapping");
390 main (int argc, char **argv)
392 gtk_init (&argc, &argv);
394 test_action_widgets ();