hire_david_parker/
lib.rs

1use std::fs;
2use std::path::Path;
3use std::error::Error;
4
5pub mod tui;
6
7/// Returns a greeting message
8pub fn greeting() -> String {
9    String::from("Hello Warp, I am David Parker.")
10}
11
12/// Load content from markdown files
13pub fn load_content(filename: &str) -> String {
14    let path = Path::new(env!("CARGO_MANIFEST_DIR"))
15        .join("src")
16        .join("static")
17        .join("content")
18        .join(filename);
19
20    match fs::read_to_string(&path) {
21        Ok(content) => content,
22        Err(_) => format!("Error: Failed to load content from '{}'", filename),
23    }
24}
25
26/// Returns the about content
27pub fn about() -> String {
28    load_content("about.md")
29}
30
31/// Returns the skills content
32pub fn skills() -> String {
33    load_content("skills.md")
34}
35
36/// Returns the projects content
37pub fn projects() -> String {
38    load_content("projects.md")
39}
40
41
42/// Returns the welcome content
43pub fn welcome() -> String {
44    load_content("welcome.md")
45}
46
47/// Returns the timeline content
48pub fn timeline() -> String {
49    load_content("timeline.md")
50}
51
52/// Returns the contact content
53pub fn contact() -> String {
54    load_content("contact.md")
55}
56
57/// Loads timeline data from JSON file
58pub fn load_timeline_data() -> Result<Vec<TimelineEvent>, Box<dyn Error>> {
59    let path = Path::new(env!("CARGO_MANIFEST_DIR"))
60        .join("src")
61        .join("static")
62        .join("content")
63        .join("timeline.json");
64    
65    let content = fs::read_to_string(&path)?;
66    let timeline_events: Vec<TimelineEvent> = serde_json::from_str(&content)?;
67    Ok(timeline_events)
68}
69
70/// Project link structure
71#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
72pub struct ProjectLink {
73    pub text: String,
74    pub url: String,
75}
76
77/// Project links data structure
78#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
79pub struct ProjectLinks {
80    pub links: Vec<ProjectLink>,
81}
82
83/// Loads project links data from JSON file
84pub fn load_project_links() -> Result<ProjectLinks, Box<dyn Error>> {
85    let path = Path::new(env!("CARGO_MANIFEST_DIR"))
86        .join("src")
87        .join("static")
88        .join("content")
89        .join("projects.json");
90    
91    let content = fs::read_to_string(&path)?;
92    let project_links: ProjectLinks = serde_json::from_str(&content)?;
93    Ok(project_links)
94}
95
96/// Represents a timeline event
97#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
98pub struct TimelineEvent {
99    pub year: u32,
100    pub title: String,
101    pub organization: String,
102    pub description: String,
103    pub highlights: Vec<String>,
104    pub technologies: Vec<String>,
105}
106
107/// Runs the interactive TUI application
108#[cfg(not(test))]
109pub fn run_tui() -> Result<(), Box<dyn Error>> {
110    tui::run()?;
111    Ok(())
112}
113
114/// Test version of run_tui that doesn't actually launch the TUI
115#[cfg(test)]
116pub fn run_tui() -> Result<(), Box<dyn Error>> {
117    Ok(())
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[test]
125    fn test_greeting() {
126        assert_eq!(greeting(), "Hello Warp, I am David Parker.");
127    }
128
129    #[test]
130    fn test_about_content() {
131        let about_content = about();
132        assert!(about_content.contains("About David Parker"));
133        assert!(about_content.contains("Warp team"));
134    }
135
136    #[test]
137    fn test_skills_content() {
138        let skills_content = skills();
139        assert!(!skills_content.is_empty());
140        assert!(!skills_content.contains("Error: Failed to load content from 'skills.md'"));
141    }
142
143    #[test]
144    fn test_projects_content() {
145        let projects_content = projects();
146        assert!(!projects_content.is_empty());
147        assert!(!projects_content.contains("Error: Failed to load content from 'projects.md'"));
148    }
149
150
151    #[test]
152    fn test_welcome_content() {
153        let welcome_content = welcome();
154        assert!(!welcome_content.is_empty());
155        assert!(!welcome_content.contains("Error: Failed to load content from 'welcome.md'"));
156    }
157
158    #[test]
159    fn test_timeline_content() {
160        let timeline_content = timeline();
161        assert!(!timeline_content.is_empty());
162        assert!(!timeline_content.contains("Error: Failed to load content from 'timeline.md'"));
163    }
164    
165    #[test]
166    fn test_contact_content() {
167        let contact_content = contact();
168        assert!(!contact_content.is_empty());
169        assert!(!contact_content.contains("Error: Failed to load content from 'contact.md'"));
170    }
171
172    #[test]
173    fn test_load_timeline_data() {
174        let result = load_timeline_data();
175        assert!(result.is_ok());
176        
177        let timeline_events = result.unwrap();
178        assert!(!timeline_events.is_empty());
179        
180        let first_event = &timeline_events[0];
181        assert!(first_event.year > 0);
182        assert!(!first_event.title.is_empty());
183        assert!(!first_event.organization.is_empty());
184        assert!(!first_event.description.is_empty());
185    }
186
187    #[test]
188    fn test_load_content_error_handling() {
189        let content = load_content("nonexistent_file.md");
190        assert!(content.contains("Error: Failed to load content from 'nonexistent_file.md'"));
191    }
192    
193    #[test]
194    fn test_run_tui() {
195        let result = run_tui();
196        assert!(result.is_ok());
197    }
198}