mirror of
https://github.com/google/pebble.git
synced 2025-03-21 11:21:21 +00:00
228 lines
7.6 KiB
C
228 lines
7.6 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "applib/ui/option_menu_window.h"
|
|
#include "resource/resource.h"
|
|
#include "resource/resource_ids.auto.h"
|
|
#include "services/normal/timeline/timeline_resources.h"
|
|
|
|
#include "clar.h"
|
|
|
|
// Fakes
|
|
/////////////////////
|
|
|
|
#include "fake_app_state.h"
|
|
#include "fake_content_indicator.h"
|
|
#include "fake_graphics_context.h"
|
|
#include "fixtures/load_test_resources.h"
|
|
|
|
// Stubs
|
|
/////////////////////
|
|
|
|
#include "stubs_analytics.h"
|
|
#include "stubs_animation_timing.h"
|
|
#include "stubs_app_install_manager.h"
|
|
#include "stubs_app_state.h"
|
|
#include "stubs_app_timer.h"
|
|
#include "stubs_bootbits.h"
|
|
#include "stubs_buffer.h"
|
|
#include "stubs_click.h"
|
|
#include "stubs_compiled_with_legacy2_sdk.h"
|
|
#include "stubs_event_service_client.h"
|
|
#include "stubs_heap.h"
|
|
#include "stubs_logging.h"
|
|
#include "stubs_memory_layout.h"
|
|
#include "stubs_mutex.h"
|
|
#include "stubs_passert.h"
|
|
#include "stubs_pbl_malloc.h"
|
|
#include "stubs_pebble_tasks.h"
|
|
#include "stubs_print.h"
|
|
#include "stubs_process_manager.h"
|
|
#include "stubs_prompt.h"
|
|
#include "stubs_serial.h"
|
|
#include "stubs_shell_prefs.h"
|
|
#include "stubs_sleep.h"
|
|
#include "stubs_syscalls.h"
|
|
#include "stubs_task_watchdog.h"
|
|
#include "stubs_unobstructed_area.h"
|
|
#include "stubs_window_manager.h"
|
|
#include "stubs_window_stack.h"
|
|
|
|
// Setup and Teardown
|
|
////////////////////////////////////
|
|
|
|
typedef struct OptionMenuTestData {
|
|
OptionMenu option_menu;
|
|
} OptionMenuTestData;
|
|
|
|
OptionMenuTestData s_data;
|
|
|
|
void test_option_menu_window__initialize(void) {
|
|
fake_app_state_init();
|
|
load_system_resources_fixture();
|
|
|
|
s_data = (OptionMenuTestData) {};
|
|
rtc_set_time(3 * SECONDS_PER_DAY);
|
|
}
|
|
|
|
void test_option_menu_window__cleanup(void) {
|
|
}
|
|
|
|
// Helpers
|
|
//////////////////////
|
|
|
|
typedef struct MenuItemConfig {
|
|
const char *title;
|
|
const char *subtitle;
|
|
} MenuItemConfig;
|
|
|
|
typedef struct MenuConfig {
|
|
OptionMenuCallbacks callbacks;
|
|
const char *title;
|
|
size_t num_items;
|
|
MenuItemConfig *items;
|
|
OptionMenuContentType content_type;
|
|
bool icons_enabled;
|
|
} MenuConfig;
|
|
|
|
static uint16_t prv_menu_get_num_rows(OptionMenu *option_menu, void *context) {
|
|
return ((MenuConfig *)context)->num_items;
|
|
}
|
|
|
|
static void prv_menu_draw_row(OptionMenu *option_menu, GContext *ctx, const Layer *cell_layer,
|
|
const GRect *cell_frame, uint32_t row, bool selected, void *context) {
|
|
MenuConfig *data = context;
|
|
option_menu_system_draw_row(option_menu, ctx, cell_layer, cell_frame, data->items[row].title,
|
|
selected, context);
|
|
}
|
|
|
|
static void prv_create_menu_and_render(MenuConfig *config) {
|
|
option_menu_init(&s_data.option_menu);
|
|
|
|
const OptionMenuConfig option_menu_config = {
|
|
.title = config->title ?: "Option Menu",
|
|
.content_type = config->content_type,
|
|
.status_colors = { GColorWhite, GColorBlack },
|
|
.highlight_colors = { PBL_IF_COLOR_ELSE(GColorCobaltBlue, GColorBlack), GColorWhite },
|
|
.icons_enabled = config->icons_enabled,
|
|
};
|
|
option_menu_configure(&s_data.option_menu, &option_menu_config);
|
|
|
|
const OptionMenuCallbacks callbacks = {
|
|
.draw_row = config->callbacks.draw_row ?: prv_menu_draw_row,
|
|
.get_num_rows = config->callbacks.get_num_rows ?: prv_menu_get_num_rows,
|
|
.get_cell_height = config->callbacks.get_cell_height ?: NULL,
|
|
};
|
|
option_menu_set_callbacks(&s_data.option_menu, &callbacks, config);
|
|
|
|
window_set_on_screen(&s_data.option_menu.window, true, true);
|
|
window_render(&s_data.option_menu.window, fake_graphics_context_get_context());
|
|
}
|
|
|
|
// Tests
|
|
//////////////////////
|
|
|
|
// These tests test all permutations on all platforms even if the combination on the particular
|
|
// platform was not designed and thus does not appear pleasant. Make sure you are looking at the
|
|
// combination relevant to your use case when examining the unit test output of Option Menu.
|
|
|
|
void prv_create_menu_and_render_long_title(bool icons_enabled, const char *title,
|
|
bool special_height) {
|
|
prv_create_menu_and_render(&(MenuConfig) {
|
|
.title = title,
|
|
.content_type = special_height ? OptionMenuContentType_DoubleLine :
|
|
OptionMenuContentType_Default,
|
|
.num_items = 3,
|
|
.items = (MenuItemConfig[]) {
|
|
{
|
|
.title = "Allow All Notifications",
|
|
}, {
|
|
.title = "Allow Phone Calls Only",
|
|
}, {
|
|
.title = "Mute All Notifications",
|
|
}
|
|
},
|
|
.icons_enabled = icons_enabled,
|
|
});
|
|
}
|
|
|
|
void test_option_menu_window__long_title_default_height(void) {
|
|
prv_create_menu_and_render_long_title(false /* icons_enabled */, "Default Height",
|
|
false /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void test_option_menu_window__long_title_default_height_icons(void) {
|
|
prv_create_menu_and_render_long_title(true /* icons_enabled */, "Default Height",
|
|
false /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void test_option_menu_window__long_title_special_height(void) {
|
|
prv_create_menu_and_render_long_title(false /* icons_enabled */, "Special Height",
|
|
true /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void test_option_menu_window__long_title_special_height_icons(void) {
|
|
prv_create_menu_and_render_long_title(true /* icons_enabled */, "Special Height",
|
|
true /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void prv_create_menu_and_render_short_title(bool icons_enabled, const char *title,
|
|
bool special_height) {
|
|
prv_create_menu_and_render(&(MenuConfig) {
|
|
.title = title,
|
|
.content_type = special_height ? OptionMenuContentType_SingleLine :
|
|
OptionMenuContentType_Default,
|
|
.num_items = 3,
|
|
.items = (MenuItemConfig[]) {
|
|
{
|
|
.title = "Smaller",
|
|
}, {
|
|
.title = "Default",
|
|
}, {
|
|
.title = "Larger",
|
|
}
|
|
},
|
|
.icons_enabled = icons_enabled,
|
|
});
|
|
}
|
|
|
|
void test_option_menu_window__short_title_default_height(void) {
|
|
prv_create_menu_and_render_short_title(false /* icons_enabled */, "Default Height",
|
|
false /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void test_option_menu_window__short_title_default_height_icons(void) {
|
|
prv_create_menu_and_render_short_title(true /* icons_enabled */, "Default Height",
|
|
false /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void test_option_menu_window__short_title_special_height(void) {
|
|
prv_create_menu_and_render_short_title(false /* icons_enabled */, "Special Height",
|
|
true /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|
|
|
|
void test_option_menu_window__short_title_special_height_icons(void) {
|
|
prv_create_menu_and_render_short_title(true /* icons_enabled */, "Special Height",
|
|
true /* special_height */);
|
|
FAKE_GRAPHICS_CONTEXT_CHECK_DEST_BITMAP_FILE();
|
|
}
|