Skip to content

Commit 3cdd419

Browse files
committed
Update event key to use meetup uid to ensure that there are no duplicated events (e.g. if the event title changes). Add tests to check this
1 parent 859667d commit 3cdd419

5 files changed

Lines changed: 116 additions & 207 deletions

File tree

_data/events.yml

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,9 +1953,9 @@
19531953
path: https://www.meetup.com/women-coding-community/events/313256761/
19541954
title: View meetup event
19551955
target: _target
1956-
19571956
- title: |
19581957
Java bootcamp - Session 5
1958+
uid: "event_313256771@meetup.com"
19591959
description: |
19601960
Do you want to build strong Java skills but don't know where to start? Do you feel overwhelmed juggling tutorials, documentation, and scattered resources while trying to learn Java on your own? Our Java Bootcamp is designed to give you a clear, structured path to build practical Java skills through hands-on coding, not endless theory.
19611961
category_style: tech-talk
@@ -1974,45 +1974,48 @@
19741974
target: _target
19751975

19761976
- title: |
1977-
Java bootcamp - Session 6
1977+
Java Bootcamp: Vibe Coding with AI Agents & MCP
1978+
uid: "event_313257077@meetup.com"
19781979
description: |
1979-
Do you want to build strong Java skills but don't know where to start? Do you feel overwhelmed juggling tutorials, documentation, and scattered resources while trying to learn Java on your own? Our Java Bootcamp is designed to give you a clear, structured path to build practical Java skills through hands-on coding, not endless theory.
1980+
Ready to build a Java project even if you've never written a line of Java before? This special edition of our Java Bootcamp series brings together everything we've been building with you, and takes it one step further.
19801981
category_style: tech-talk
19811982
category_name: Tech Talk
19821983
date: THU, MAR 12, 2026
19831984
expiration: "20260312"
1984-
host: "Zaynah Ahmed"
1985-
speaker: "Adriana Zencke Zimmermann, Sonali Goel"
1986-
time: 07:00 PM GMT
1985+
host: ""
1986+
speaker: ""
1987+
time: 06:30 PM GMT
19871988
image:
1988-
path: "https://secure.meetupstatic.com/photos/event/2/4/4/9/600_532629289.jpeg"
1989+
path: "https://secure.meetupstatic.com/photos/event/5/4/a/2/600_532941666.jpeg"
19891990
alt: WCC Meetup event image
19901991
link:
19911992
path: https://www.meetup.com/women-coding-community/events/313257077/
19921993
title: View meetup event
19931994
target: _target
19941995

19951996
- title: |
1996-
March Book Club: TBD
1997+
Java Bootcamp: The Grand Finale Hack Hour
1998+
uid: "event_313574241@meetup.com"
19971999
description: |
1998-
Women Coding Community Book Club! March 2026 Book: TBD If you would like to have a say in our next book club read, do join our channel progbookclub.
1999-
category_style: book-club
2000-
category_name: Book Club
2001-
date: MON, MAR 30, 2026
2002-
expiration: "20260330"
2003-
host: "Silke Nodwell and Prabha Venkatesh"
2000+
The Women Coding Community (WCC) is wrapping up our Java Fullstack Bootcamp with a high-energy, hands-on Hack Hour session.
2001+
category_style: tech-talk
2002+
category_name: Tech Talk
2003+
date: FRI, MAR 13, 2026
2004+
expiration: "20260313"
2005+
host: ""
20042006
speaker: ""
2005-
time: 07:00 PM BST
2007+
time: 06:00 PM GMT
20062008
image:
2007-
path: "https://secure.meetupstatic.com/photos/event/a/6/e/d/600_521202733.jpeg"
2009+
path: "https://secure.meetupstatic.com/photos/event/9/4/0/7/600_532957895.jpeg"
20082010
alt: WCC Meetup event image
20092011
link:
2010-
path: https://www.meetup.com/women-coding-community/events/313316083/
2012+
path: https://www.meetup.com/women-coding-community/events/313574241/
20112013
title: View meetup event
20122014
target: _target
20132015

20142016
- title: |
20152017
Own your voice: Assertive Communication for Women in Tech
2018+
uid: "event_313463081@meetup.com"
20162019
description: "We\u2019re thrilled to re-launch the Women Coding Community Career Club! We are kicking off with a powerful session led by Yasuko Ohtake, a leading technologist who will share candid insights from her career and practical strategies for visibility and influence in tech.\n"
20172020
category_style: tech-talk
20182021
category_name: Tech Talk
@@ -2029,27 +2032,9 @@
20292032
title: View meetup event
20302033
target: _target
20312034

2032-
- title: |
2033-
March Book Club: AI Engineering pt.2 and Showcase
2034-
description: |
2035-
Women Coding Community Book Club! March 2026 Book: AI Engineering by Chip Huyen (continued) With a small showcase of AI engineering projects by WCC members If you would like to have a say in our next book club read, do join our channel progbookclub.
2036-
category_style: book-club
2037-
category_name: Book Club
2038-
date: MON, MAR 30, 2026
2039-
expiration: "20260330"
2040-
host: "Silke Nodwell, Prabha Venkatesh"
2041-
speaker: ""
2042-
time: 07:00 PM BST
2043-
image:
2044-
path: "https://secure.meetupstatic.com/photos/event/7/0/d/7/600_532888887.jpeg"
2045-
alt: WCC Meetup event image
2046-
link:
2047-
path: https://www.meetup.com/women-coding-community/events/313316083/
2048-
title: View meetup event
2049-
target: _target
2050-
20512035
- title: |
20522036
2026 International Women's Day Celebration - Feast, Talks & Tech Community
2037+
uid: "event_313538360@meetup.com"
20532038
description: |
20542039
In partnership with Nando's Women in Engineering Celebrate IWD with the best women in tech and incredible food! This International Women's Day, a number of London's most powerful women-in-tech communities are coming together for an unforgettable evening of inspiring talks, a delicious feast, a candid panel discussion, and genuine connection.
20552040
category_style: tech-talk
@@ -2068,39 +2053,41 @@
20682053
target: _target
20692054

20702055
- title: |
2071-
Java Bootcamp: Vibe Coding with AI Agents & MCP
2056+
March Book Club: AI Engineering pt.2 and Showcase
2057+
uid: "event_313316083@meetup.com"
20722058
description: |
2073-
Ready to build a Java project even if you've never written a line of Java before? This special edition of our Java Bootcamp series brings together everything we've been building with you, and takes it one step further.
2074-
category_style: tech-talk
2075-
category_name: Tech Talk
2076-
date: THU, MAR 12, 2026
2077-
expiration: "20260312"
2078-
host: ""
2059+
Women Coding Community Book Club! March 2026 Book: AI Engineering by Chip Huyen (continued) With a small showcase of AI engineering projects by WCC members If you would like to have a say in our next book club read, do join our channel progbookclub.
2060+
category_style: book-club
2061+
category_name: Book Club
2062+
date: MON, MAR 30, 2026
2063+
expiration: "20260330"
2064+
host: "Silke Nodwell, Prabha Venkatesh"
20792065
speaker: ""
2080-
time: 06:30 PM GMT
2066+
time: 07:00 PM BST
20812067
image:
2082-
path: "https://secure.meetupstatic.com/photos/event/5/4/a/2/600_532941666.jpeg"
2068+
path: "https://secure.meetupstatic.com/photos/event/7/0/d/7/600_532888887.jpeg"
20832069
alt: WCC Meetup event image
20842070
link:
2085-
path: https://www.meetup.com/women-coding-community/events/313257077/
2071+
path: https://www.meetup.com/women-coding-community/events/313316083/
20862072
title: View meetup event
20872073
target: _target
20882074

20892075
- title: |
2090-
Java Bootcamp: The Grand Finale Hack Hour
2076+
From Idea to Impact: Building Products That Actually Matter
2077+
uid: "event_313608754@meetup.com"
20912078
description: |
2092-
The Women Coding Community (WCC) is wrapping up our Java Fullstack Bootcamp with a high-energy, hands-on Hack Hour session.
2079+
From Idea to Impact: Building Products That Actually Matter How to define real user problems, prioritize effectively, and lead cross-functional teams to deliver meaningful results.
20932080
category_style: tech-talk
20942081
category_name: Tech Talk
2095-
date: FRI, MAR 13, 2026
2096-
expiration: "20260313"
2082+
date: WED, APR 01, 2026
2083+
expiration: "20260401"
20972084
host: ""
20982085
speaker: ""
2099-
time: 06:00 PM GMT
2086+
time: 07:00 PM BST
21002087
image:
2101-
path: "https://secure.meetupstatic.com/photos/event/9/4/0/7/600_532957895.jpeg"
2088+
path: "https://secure.meetupstatic.com/photos/event/7/4/3/1/600_533009745.jpeg"
21022089
alt: WCC Meetup event image
21032090
link:
2104-
path: https://www.meetup.com/women-coding-community/events/313574241/
2091+
path: https://www.meetup.com/women-coding-community/events/313608754/
21052092
title: View meetup event
21062093
target: _target

tools/llm_meetup_summary/llm_event_summary.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,14 @@ def _load_events(events_file):
3535
except yaml.YAMLError as e:
3636
raise ValueError(f"Invalid YAML in events file: {e}")
3737

38-
def get_date_of_event_iso(event):
39-
event_date = event.get('expiration') # should be in the format 'YYYYMMDD'
40-
assert len(event_date)==8
41-
event_date_formatted = event_date[:4] + event_date[4:6] + event_date[6:8]
42-
return event_date_formatted
43-
4438
def _filter_future_events(events):
4539
today = date.today().isoformat().replace('-', '')
46-
return [event for event in events if get_date_of_event_iso(event) >= today]
40+
assert len(today) == 8
41+
return [event for event in events if event.get('expiration', '') >= today]
4742

4843
def _validate_event(event):
4944
missing_fields = [field for field in REQUIRED_EVENT_FIELDS if field not in event]
45+
assert len(event['expiration'])==8, f"Event expiration date must be in YYYYMMDD format: {event['expiration']}"
5046
if missing_fields:
5147
raise ValueError(f"Event missing fields: {missing_fields}")
5248

tools/llm_meetup_summary/tests/tests.py

Lines changed: 19 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -19,131 +19,22 @@
1919
get_date_of_event_iso,
2020
)
2121

22-
class TestGetLlmSummary:
23-
"""Tests for _get_llm_summary function"""
24-
25-
@patch("tools.llm_meetup_summary.summarise_events_with_llms.openai.chat.completions.create")
26-
@patch("builtins.open", new_callable=mock_open)
27-
@patch("pathlib.Path.read_text")
28-
def test_get_llm_summary_success(self, mock_read_text, mock_file, mock_openai):
29-
"""Test successful LLM summary generation"""
30-
mock_read_text.return_value = "Example content"
31-
32-
mock_response = MagicMock()
33-
mock_response.choices[0].message.content = "Here's a summary of upcoming events"
34-
mock_openai.return_value = mock_response
35-
36-
result = _get_llm_summary("## Event 1\nTitle: Test Event")
37-
38-
assert result == "Here's a summary of upcoming events"
39-
assert mock_openai.called
40-
41-
@patch("tools.llm_meetup_summary.summarise_events_with_llms.openai.chat.completions.create")
42-
@patch("pathlib.Path.read_text")
43-
def test_get_llm_summary_error_response(self, mock_read_text, mock_openai):
44-
"""Test when LLM returns error message"""
45-
mock_read_text.return_value = "Example content"
46-
47-
mock_response = MagicMock()
48-
mock_response.choices[0].message.content = "#ERROR: Invalid event format"
49-
mock_openai.return_value = mock_response
50-
51-
with pytest.raises(ValueError, match="LLM Error"):
52-
_get_llm_summary("## Event 1")
53-
54-
@patch("tools.llm_meetup_summary.summarise_events_with_llms.openai.chat.completions.create")
55-
@patch("pathlib.Path.read_text")
56-
def test_get_llm_summary_creates_prompt_file(self, mock_read_text, mock_openai):
57-
"""Test that prompt is saved to current_prompt.md"""
58-
mock_read_text.return_value = "Example content"
59-
60-
mock_response = MagicMock()
61-
mock_response.choices[0].message.content = "Summary content"
62-
mock_openai.return_value = mock_response
63-
64-
with patch("builtins.open", mock_open()) as mock_file:
65-
_get_llm_summary("## Event 1")
66-
mock_file.assert_called()
67-
68-
69-
class TestFormatForSlack:
70-
"""Tests for _format_for_slack function"""
71-
72-
def test_format_for_slack_converts_bold(self):
73-
"""Test markdown bold conversion to Slack format"""
74-
result = _format_for_slack("This is **bold** text")
75-
assert result == "This is *bold* text"
76-
77-
def test_format_for_slack_converts_links(self):
78-
"""Test markdown link conversion to Slack format"""
79-
result = _format_for_slack("[Click here](https://example.com)")
80-
assert result == "<https://example.com|Click here>"
81-
82-
def test_format_for_slack_multiple_conversions(self):
83-
"""Test multiple markdown conversions"""
84-
result = _format_for_slack("**Bold** and [link](https://example.com)")
85-
assert "*Bold*" in result
86-
assert "<https://example.com|link>" in result
87-
88-
def test_format_for_slack_none_input(self):
89-
"""Test that None input raises ValueError"""
90-
with pytest.raises(ValueError, match="No text provided"):
91-
_format_for_slack(None)
92-
93-
94-
class TestValidateEvent:
95-
"""Tests for _validate_event function"""
96-
97-
def test_validate_event_valid(self):
98-
"""Test validation passes for complete event"""
99-
event = {
100-
'title': 'Test',
101-
'description': 'Desc',
102-
'date': '2024-01-01',
103-
'time': '18:00',
104-
'link': {'path': 'https://example.com'}
105-
}
106-
_validate_event(event) # Should not raise
107-
108-
def test_validate_event_missing_field(self):
109-
"""Test validation fails for missing field"""
110-
event = {
111-
'title': 'Test',
112-
'description': 'Desc',
113-
'date': '2024-01-01'
114-
}
115-
with pytest.raises(ValueError, match="missing fields"):
116-
_validate_event(event)
117-
118-
119-
class TestLoadEvents:
120-
"""Tests for _load_events function"""
121-
122-
@patch("builtins.open", new_callable=mock_open, read_data="- title: Event1\n description: Desc")
123-
@patch("yaml.safe_load")
124-
def test_load_events_success(self, mock_yaml, mock_file):
125-
"""Test successful event loading"""
126-
mock_yaml.return_value = [{'title': 'Event1'}]
127-
result = _load_events("test.yml")
128-
assert result == [{'title': 'Event1'}]
129-
130-
def test_load_events_file_not_found(self):
131-
"""Test FileNotFoundError for missing file"""
132-
with pytest.raises(FileNotFoundError):
133-
_load_events("/nonexistent/path.yml")
134-
135-
136-
class TestGetDateOfEventIso:
137-
"""Tests for get_date_of_event_iso function"""
138-
139-
def test_get_date_of_event_iso_valid(self):
140-
"""Test date formatting from YYYYMMDD"""
141-
event = {'expiration': '20240115'}
142-
result = get_date_of_event_iso(event)
143-
assert result == '20240115'
144-
145-
def test_get_date_of_event_iso_invalid_length(self):
146-
"""Test assertion error for invalid date length"""
147-
event = {'expiration': '2024011'}
148-
with pytest.raises(AssertionError):
149-
get_date_of_event_iso(event)
22+
test_get_date_of_event_iso():
23+
event = {
24+
'expiration': "20250101",
25+
}
26+
iso_date = get_date_of_event_iso(event)
27+
assert iso_date == '20250101'
28+
29+
def test_event_dates_are_sorted():
30+
event1 = {
31+
'expiration': "20260330",
32+
}
33+
event2 = {
34+
'expiration': "20250101",
35+
}
36+
event3 = {
37+
'expiration': "20251215",
38+
}
39+
iso_date = get_date_of_event_iso(event)
40+
assert iso_date == '2025-01-01T10:00:00'

0 commit comments

Comments
 (0)