Skip to content

Commit

Permalink
Tests for batch insert
Browse files Browse the repository at this point in the history
  • Loading branch information
nygrenh committed Aug 26, 2024
1 parent 725885d commit d0c0e2f
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,12 @@ CREATE TABLE code_giveaway_codes (
code_giveaway_id UUID NOT NULL REFERENCES code_giveaways(id),
code_given_to_user_id UUID REFERENCES users(id),
added_by_user_id UUID NOT NULL REFERENCES users(id),
code VARCHAR(2048) NOT NULL,
-- A user can only receive one code from a giveaway.
UNIQUE NULLS NOT DISTINCT (
code_giveaway_id,
code_given_to_user_id,
deleted_at
)
code VARCHAR(2048) NOT NULL
);
-- A user can only receive one code from a giveaway. We use unique index here because if we used a unique constraint we would like to have NULLS NOT disctinct on the delted_at column but NULLS DISTINCT on the code_given_to_user_id column. This did not seem possible so we use a unique index instead.
CREATE UNIQUE INDEX giveaway_codes_one_code_per_user ON code_giveaway_codes (code_giveaway_id, code_given_to_user_id)
WHERE deleted_at IS NULL;

CREATE TRIGGER set_timestamp BEFORE
UPDATE ON code_giveaway_codes FOR EACH ROW EXECUTE PROCEDURE trigger_set_timestamp();
COMMENT ON TABLE code_giveaway_codes IS 'A code that is available in a code giveaway. A user can only receive one code from a giveaway.';
Expand Down
54 changes: 40 additions & 14 deletions services/headless-lms/models/src/code_giveaway_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub async fn insert_many(
input: &[String],
added_by_user_id: Uuid,
) -> ModelResult<Vec<CodeGiveawayCode>> {
if input.is_empty() {
return Ok(vec![]);
}
let mut query_builder = QueryBuilder::new(
"INSERT INTO code_giveaway_codes (code_giveaway_id, code, added_by_user_id) ",
);
Expand Down Expand Up @@ -133,27 +136,50 @@ mod tests {

#[tokio::test]
async fn test_insert_many_empty() {
insert_data!(:tx, :user, :org, :course, instance: _instance, :course_module);
insert_data!(:tx, :user, :org, :course);

let insert_result = insert_many(tx.as_mut(), &[]).await.unwrap();
let code_giveaway = crate::code_giveaways::insert(tx.as_mut(), course)
.await
.unwrap();

let inserted_data = get_inserted_data(tx.as_mut()).await.unwrap();
let insert_result = insert_many(tx.as_mut(), code_giveaway.id, &[], user)
.await
.unwrap();

assert!(insert_result.is_empty());
assert!(inserted_data.is_empty());
}

#[tokio::test]
async fn test_insert_many_with_data() {
insert_data!(:tx, :user, :org, :course, instance: _instance, :course_module, chapter: _chapter, page: _page, exercise: exercise_id);

let data_to_insert = vec![/* your data here */];

let insert_result = insert_many(tx.as_mut(), &data_to_insert).await.unwrap();

let inserted_data = get_inserted_data(tx.as_mut()).await.unwrap();

assert_eq!(insert_result.len(), data_to_insert.len());
assert_eq!(inserted_data.len(), data_to_insert.len());
insert_data!(:tx, :user, :org, :course);

let code_giveaway = crate::code_giveaways::insert(tx.as_mut(), course)
.await
.unwrap();

let codes = vec![
"code1".to_string(),
"code2".to_string(),
"code3".to_string(),
];

let insert_result = insert_many(tx.as_mut(), code_giveaway.id, &codes, user)
.await
.unwrap();

assert_eq!(insert_result.len(), codes.len());
for code in &codes {
let found = insert_result.iter().find(|c| c.code == *code);
assert!(found.is_some());
}
// Double checking
let all_codes = get_all_by_code_giveaway_id(tx.as_mut(), code_giveaway.id)
.await
.unwrap();
assert_eq!(all_codes.len(), codes.len());
for code in &codes {
let found = all_codes.iter().find(|c| c.code == *code);
assert!(found.is_some());
}
}
}
8 changes: 4 additions & 4 deletions services/headless-lms/models/src/code_giveaways.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub struct CodeGiveaway {
pub enabled: bool,
}

async fn insert(conn: &mut PgConnection, course_id: Uuid) -> ModelResult<CodeGiveaway> {
pub async fn insert(conn: &mut PgConnection, course_id: Uuid) -> ModelResult<CodeGiveaway> {
let res = sqlx::query_as!(
CodeGiveaway,
r#"
Expand All @@ -28,7 +28,7 @@ RETURNING *
Ok(res)
}

async fn get_all_for_course(
pub async fn get_all_for_course(
conn: &mut PgConnection,
course_id: Uuid,
) -> ModelResult<Vec<CodeGiveaway>> {
Expand All @@ -48,7 +48,7 @@ WHERE course_id = $1
Ok(res)
}

async fn get_by_id(conn: &mut PgConnection, id: Uuid) -> ModelResult<Option<CodeGiveaway>> {
pub async fn get_by_id(conn: &mut PgConnection, id: Uuid) -> ModelResult<Option<CodeGiveaway>> {
let res = sqlx::query_as!(
CodeGiveaway,
r#"
Expand All @@ -64,7 +64,7 @@ WHERE id = $1
Ok(res)
}

async fn set_enabled(
pub async fn set_enabled(
conn: &mut PgConnection,
id: Uuid,
enabled: bool,
Expand Down
2 changes: 1 addition & 1 deletion services/headless-lms/models/src/library/progressing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ mod tests {

#[tokio::test]
async fn tags_suspected_cheater() {
insert_data!(:tx, user:user, :org, course:course, instance:instance, course_module:course_module, :chapter, :page, :exercise, :slide, :task);
insert_data!(:tx, user:user, :org, course:course, instance:instance, course_module:course_module, :chapter, :page, :exercise, :slide);

crate::library::course_instances::enroll(tx.as_mut(), user, instance.id, &[])
.await
Expand Down

0 comments on commit d0c0e2f

Please sign in to comment.