Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add opinionated authentication, questing, rewards, notifications, and gamification domains #7

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 55 additions & 3 deletions apps/govquests-api/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,57 @@
prepare-dev:
docker-compose up -d
# Define the subdirectories where tests should be run
SUBDIRS := govquests/authentication govquests/questing govquests/gamification govquests/notifications govquests/rewarding govquests/action_tracking infra rails_app

.PHONY: test $(SUBDIRS)

# Default target
all: test

# Run tests in all subdirectories
test: $(SUBDIRS)

$(SUBDIRS):
@echo "Running tests in $@"
@$(MAKE) -C $@ test

# Install dependencies in all subdirectories
install:
bundle install
@for dir in $(SUBDIRS); do \
echo "Installing dependencies in $$dir"; \
$(MAKE) -C $$dir install; \
done

# Run linter (assuming it's only applicable to rails_app)
lint:
@$(MAKE) -C rails_app lint

# Run Sorbet type checking (assuming it's only applicable to rails_app)
sorbet:
@$(MAKE) -C rails_app sorbet

# Run mutation testing (where applicable)
mutate:
@for dir in govquests/authentication govquests/questing infra; do \
echo "Running mutation tests in $$dir"; \
$(MAKE) -C $$dir mutate; \
done

# Prepare development environment
prepare-dev:
@$(MAKE) -C . prepare-dev

# Clean up (you can define cleanup tasks here if needed)
clean:
@echo "Cleaning up..."
# Add cleanup commands here

# Help target
help:
@echo "Available targets:"
@echo " test - Run all tests in subdirectories"
@echo " install - Install dependencies in all subdirectories"
@echo " lint - Run linter on rails_app"
@echo " sorbet - Run Sorbet type checking on rails_app"
@echo " mutate - Run mutation tests where applicable"
@echo " prepare-dev - Prepare development environment"
@echo " clean - Clean up (if defined)"
@echo " help - Show this help message"
11 changes: 11 additions & 0 deletions apps/govquests-api/govquests/action_tracking/.mutant.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
requires:
- ./test/test_helper
integration: minitest
usage: opensource
coverage_criteria:
process_abort: true
matcher:
subjects:
- ActionTracking*
ignore:
- ActionTracking::Configuration#call
4 changes: 4 additions & 0 deletions apps/govquests-api/govquests/action_tracking/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source "https://rubygems.org"

eval_gemfile "../../infra/Gemfile.test"
gem "infra", path: "../../infra"
110 changes: 110 additions & 0 deletions apps/govquests-api/govquests/action_tracking/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
PATH
remote: ../../infra
specs:
infra (1.0.0)
aggregate_root (~> 2.15)
arkency-command_bus
dry-struct
dry-types
rake
ruby_event_store (~> 2.15)
ruby_event_store-transformations

GEM
remote: https://oss:7AXfeZdAfCqL1PvHm2nvDJO6Zd9UW8IK@gem.mutant.dev/
specs:
mutant-license (0.1.1.2.1627430819213747598431630701693729869473.6)

GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.2)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
aggregate_root (2.15.0)
ruby_event_store (= 2.15.0)
arkency-command_bus (0.4.1)
concurrent-ruby
ast (2.4.2)
base64 (0.2.0)
bigdecimal (3.1.4)
concurrent-ruby (1.2.2)
connection_pool (2.4.1)
diff-lcs (1.5.1)
drb (2.2.0)
ruby2_keywords
dry-core (1.0.1)
concurrent-ruby (~> 1.0)
zeitwerk (~> 2.6)
dry-inflector (1.0.0)
dry-logic (1.5.0)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0, < 2)
zeitwerk (~> 2.6)
dry-struct (1.6.0)
dry-core (~> 1.0, < 2)
dry-types (>= 1.7, < 2)
ice_nine (~> 0.11)
zeitwerk (~> 2.6)
dry-types (1.7.1)
concurrent-ruby (~> 1.0)
dry-core (~> 1.0)
dry-inflector (~> 1.0)
dry-logic (~> 1.4)
zeitwerk (~> 2.6)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
minitest (5.25.0)
mutant (0.12.4)
diff-lcs (~> 1.3)
parser (~> 3.3.0)
regexp_parser (~> 2.9.0)
sorbet-runtime (~> 0.5.0)
unparser (~> 0.6.14)
mutant-minitest (0.12.4)
minitest (~> 5.11)
mutant (= 0.12.4)
mutex_m (0.2.0)
parser (3.3.4.2)
ast (~> 2.4.1)
racc
racc (1.8.1)
rake (13.1.0)
regexp_parser (2.9.2)
ruby2_keywords (0.0.5)
ruby_event_store (2.15.0)
concurrent-ruby (~> 1.0, >= 1.1.6)
ruby_event_store-transformations (0.1.0)
activesupport (>= 5.0)
ruby_event_store (>= 2.0.0, < 3.0.0)
sorbet-runtime (0.5.11525)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unparser (0.6.15)
diff-lcs (~> 1.3)
parser (>= 3.3.0)
zeitwerk (2.6.12)

PLATFORMS
arm64-darwin-20
arm64-darwin-21
ruby
x86_64-darwin-20
x86_64-linux

DEPENDENCIES
infra!
minitest (= 5.25.0)!
mutant-license!
mutant-minitest (= 0.12.4)!

BUNDLED WITH
2.5.9
10 changes: 10 additions & 0 deletions apps/govquests-api/govquests/action_tracking/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
install:
@bundle install

test:
@bundle exec ruby -e "require \"rake/rake_test_loader\"" test/*_test.rb

mutate:
@RAILS_ENV=test bundle exec mutant run

.PHONY: install test mutate
7 changes: 7 additions & 0 deletions apps/govquests-api/govquests/action_tracking/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# ActionTracking

#### Up and running

```
make install test mutate
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require "infra"
require_relative "action_tracking/commands"
require_relative "action_tracking/events"
require_relative "action_tracking/on_action_commands"
require_relative "action_tracking/action"

module ActionTracking
class Configuration
def call(event_store, command_bus)
command_handler = OnActionCommands.new(event_store)
command_bus.register(CreateAction, command_handler)
command_bus.register(CompleteAction, command_handler)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module ActionTracking
class Action
include AggregateRoot

def initialize(id)
@id = id
@content = nil
@action_type = nil
@completion_criteria = {}
@completed = false
end

def create(content, action_type, completion_criteria)
apply ActionCreated.new(data: {
action_id: @id,
content: content,
action_type: action_type,
completion_criteria: completion_criteria
})
end

def complete(user_id, completion_data)
raise "Action already completed" if @completed

apply ActionExecuted.new(data: {
action_id: @id,
user_id: user_id,
completion_data: completion_data
})
end

private

on ActionCreated do |event|
@content = event.data[:content]
@action_type = event.data[:action_type]
@completion_criteria = event.data[:completion_criteria]
end

on ActionExecuted do |event|
@completed = true
# Additional logic for completion can be added here
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# govquests/action_tracking/lib/action_tracking/commands.rb
module ActionTracking
class CreateAction < Infra::Command
attribute :action_id, Infra::Types::UUID
attribute :content, Infra::Types::String
attribute :action_type, Infra::Types::String
attribute :completion_criteria, Infra::Types::Hash

alias_method :aggregate_id, :action_id
end

class CompleteAction < Infra::Command
attribute :action_id, Infra::Types::UUID
attribute :user_id, Infra::Types::UUID
attribute :completion_data, Infra::Types::Hash

alias_method :aggregate_id, :action_id
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module ActionTracking
class ActionCreated < Infra::Event
attribute :action_id, Infra::Types::UUID
attribute :content, Infra::Types::String
attribute :action_type, Infra::Types::String
attribute :completion_criteria, Infra::Types::Hash
end

class ActionExecuted < Infra::Event
attribute :action_id, Infra::Types::UUID
attribute :user_id, Infra::Types::UUID
attribute :completion_data, Infra::Types::Hash
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module ActionTracking
class OnActionCommands
def initialize(event_store)
@repository = Infra::AggregateRootRepository.new(event_store)
end

def call(command)
@repository.with_aggregate(Action, command.aggregate_id) do |action|
case command
when CreateAction
action.create(command.content, command.action_type, command.completion_criteria)
when CompleteAction
action.complete(command.user_id, command.completion_data)
else
raise "Unknown command: #{command.class}"
end
end
end
end
end
46 changes: 46 additions & 0 deletions apps/govquests-api/govquests/action_tracking/test/action_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
require_relative "test_helper"

module ActionTracking
class ActionTest < Test
cover "ActionTracking::Action"

def setup
super
@action_id = SecureRandom.uuid
@action = Action.new(@action_id)
end

def test_create_a_new_action
content = "Complete survey"
action_type = "ReadDocument"
completion_criteria = {document_url: "https://example.com/survey"}

@action.create(content, action_type, completion_criteria)

events = @action.unpublished_events.to_a
assert_equal 1, events.size
event = events.first
assert_instance_of ActionCreated, event
assert_equal @action_id, event.data[:action_id]
assert_equal content, event.data[:content]
assert_equal action_type, event.data[:action_type]
assert_equal completion_criteria, event.data[:completion_criteria]
end

def test_complete_an_action
@action.create("Complete survey", "ReadDocument", {document_url: "https://example.com/survey"})
user_id = SecureRandom.uuid
completion_data = {result: "success"}

@action.complete(user_id, completion_data)

events = @action.unpublished_events.to_a
assert_equal 2, events.size
event = events.last
assert_instance_of ActionExecuted, event
assert_equal @action_id, event.data[:action_id]
assert_equal user_id, event.data[:user_id]
assert_equal completion_data, event.data[:completion_data]
end
end
end
19 changes: 19 additions & 0 deletions apps/govquests-api/govquests/action_tracking/test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require "minitest/autorun"
require "mutant/minitest/coverage"

require_relative "../lib/action_tracking"

module ActionTracking
class Test < Infra::InMemoryTest
def before_setup
super
Configuration.new.call(event_store, command_bus)
end

private

def fake_login
"fake_login"
end
end
end
Loading
Loading