Skip to content

Commit

Permalink
fixup into audio recorder
Browse files Browse the repository at this point in the history
  • Loading branch information
bdemann committed Jun 29, 2024
1 parent 16fb9cc commit 2b37061
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 143 deletions.
2 changes: 1 addition & 1 deletion examples/audio_recorder/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 3 additions & 8 deletions examples/audio_recorder/src/index.did
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,13 @@ type Recording = record {
userId: principal;
};

type AudioRecorderError = variant {
RecordingDoesNotExist: principal;
UserDoesNotExist: principal;
};

service: () -> {
createUser: (text) -> (User);
readUsers: () -> (vec User) query;
readUserById: (principal) -> (opt User) query;
deleteUser: (principal) -> (variant { Ok: User; Err: AudioRecorderError });
createRecording: (vec nat8, text, principal) -> (variant { Ok: Recording; Err: AudioRecorderError });
deleteUser: (principal) -> (User);
createRecording: (vec nat8, text, principal) -> (Recording);
readRecordings: () -> (vec Recording) query;
readRecordingById: (principal) -> (opt Recording) query;
deleteRecording: (principal) -> (variant { Ok: Recording; Err: AudioRecorderError });
deleteRecording: (principal) -> (Recording);
}
79 changes: 30 additions & 49 deletions examples/audio_recorder/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import {
blob,
Canister,
Err,
ic,
nat64,
Ok,
Opt,
Principal,
query,
Record,
Result,
StableBTreeMap,
text,
update,
Variant,
Vec
} from 'azle/experimental';

Expand All @@ -34,12 +30,6 @@ const Recording = Record({
});
type Recording = typeof Recording.tsType;

const AudioRecorderError = Variant({
RecordingDoesNotExist: Principal,
UserDoesNotExist: Principal
});
type AudioRecorderError = typeof AudioRecorderError.tsType;

let users = StableBTreeMap<Principal, User>(0);
let recordings = StableBTreeMap<Principal, Recording>(1);

Expand All @@ -63,13 +53,11 @@ export default Canister({
readUserById: query([Principal], Opt(User), (id) => {
return users.get(id);
}),
deleteUser: update([Principal], Result(User, AudioRecorderError), (id) => {
deleteUser: update([Principal], User, (id) => {
const userOpt = users.get(id);

if ('None' in userOpt) {
return Err({
UserDoesNotExist: id
});
throw new Error(`User does not exist: ${id.toText()}`);
}

const user = userOpt.Some;
Expand All @@ -80,18 +68,16 @@ export default Canister({

users.remove(user.id);

return Ok(user);
return user;
}),
createRecording: update(
[blob, text, Principal],
Result(Recording, AudioRecorderError),
Recording,
(audio, name, userId) => {
const userOpt = users.get(userId);

if ('None' in userOpt) {
return Err({
UserDoesNotExist: userId
});
throw new Error(`User does not exist: ${userId.toText()}`);
}

const user = userOpt.Some;
Expand All @@ -114,7 +100,7 @@ export default Canister({

users.insert(updatedUser.id, updatedUser);

return Ok(recording);
return recording;
}
),
readRecordings: query([], Vec(Recording), () => {
Expand All @@ -123,43 +109,38 @@ export default Canister({
readRecordingById: query([Principal], Opt(Recording), (id) => {
return recordings.get(id);
}),
deleteRecording: update(
[Principal],
Result(Recording, AudioRecorderError),
(id) => {
const recordingOpt = recordings.get(id);

if ('None' in recordingOpt) {
return Err({ RecordingDoesNotExist: id });
}
deleteRecording: update([Principal], Recording, (id) => {
const recordingOpt = recordings.get(id);

const recording = recordingOpt.Some;
if ('None' in recordingOpt) {
throw new Error(`Recording does not exist: ${id.toText()}`);
}

const userOpt = users.get(recording.userId);
const recording = recordingOpt.Some;

if ('None' in userOpt) {
return Err({
UserDoesNotExist: recording.userId
});
}
const userOpt = users.get(recording.userId);

const user = userOpt.Some;
if ('None' in userOpt) {
throw new Error(
`User does not exist: ${recording.userId.toText()}`
);
}

const updatedUser: User = {
...user,
recordingIds: user.recordingIds.filter(
(recordingId) =>
recordingId.toText() !== recording.id.toText()
)
};
const user = userOpt.Some;

users.insert(updatedUser.id, updatedUser);
const updatedUser: User = {
...user,
recordingIds: user.recordingIds.filter(
(recordingId) => recordingId.toText() !== recording.id.toText()
)
};

recordings.remove(id);
users.insert(updatedUser.id, updatedUser);

return Ok(recording);
}
)
recordings.remove(id);

return recording;
})
});

function generateId(): Principal {
Expand Down
138 changes: 66 additions & 72 deletions examples/audio_recorder/test/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,140 +6,134 @@ import { _SERVICE } from './dfx_generated/audio_recorder/audio_recorder.did';

// TODO to be more thorough we could test all of the error cases as well

let global_user: any;
let global_recording: any;
let globalUser: any;
let globalRecording: any;

export function getTests(
audio_recorder_canister: ActorSubclass<_SERVICE>
): Test {
export function getTests(audioRecorderCanister: ActorSubclass<_SERVICE>): Test {
return () => {
it('creates a user in stable memory', async () => {
const user = await audio_recorder_canister.createUser('lastmjs');
const user = await audioRecorderCanister.createUser('lastmjs');

const expectedUsername = 'lastmjs';
const expectedRecordingCount = 0;

global_user = user;
globalUser = user;

expect(user.username).toBe(expectedUsername);
expect(user.recordingIds).toHaveLength(expectedRecordingCount);
});

it('creates a recording in stable memory', async () => {
const result = await audio_recorder_canister.createRecording(
const recording = await audioRecorderCanister.createRecording(
Uint8Array.from([0, 1, 2, 3, 4]),
'First recording',
global_user.id
globalUser.id
);

if ('Err' in result) {
throw new Error(JSON.stringify(result.Err, null, 2));
}

const recording = result.Ok;
global_recording = recording;
global_user.recordingIds = [recording.id];
globalRecording = recording;
globalUser.recordingIds = [recording.id];

expect(recording.audio).toHaveLength(5);
expect(recording.name).toBe('First recording');
expect(recording.userId).toStrictEqual(global_user.id);
expect(recording.userId).toStrictEqual(globalUser.id);
});

it('reads users from stable memory', async () => {
const result = await audio_recorder_canister.readUsers();
const result = await audioRecorderCanister.readUsers();

expect(result).toStrictEqual([global_user]);
expect(result).toStrictEqual([globalUser]);
});

it('reads recordings from stable memory', async () => {
const result = await audio_recorder_canister.readRecordings();
const result = await audioRecorderCanister.readRecordings();

expect(result).toHaveLength(1);
expect(result[0].id).toStrictEqual(global_recording.id);
expect(result[0].createdAt).toBe(global_recording.createdAt);
expect(result[0].name).toBe(global_recording.name);
expect(result[0].userId).toStrictEqual(global_recording.userId);
expect(result[0].id).toStrictEqual(globalRecording.id);
expect(result[0].createdAt).toBe(globalRecording.createdAt);
expect(result[0].name).toBe(globalRecording.name);
expect(result[0].userId).toStrictEqual(globalRecording.userId);
});

it('reads user by id from stable memory', async () => {
const result = await audio_recorder_canister.readUserById(
global_user.id
const result = await audioRecorderCanister.readUserById(
globalUser.id
);

expect(result).toStrictEqual([global_user]);
expect(result).toStrictEqual([globalUser]);
});

it('reads recording by id from stable memory', async () => {
const result = await audio_recorder_canister.readRecordingById(
global_recording.id
const result = await audioRecorderCanister.readRecordingById(
globalRecording.id
);

expect(result).toStrictEqual([global_recording]);
expect(result).toStrictEqual([globalRecording]);
});

it('deletes recording from stable memory', async () => {
const delete_recording_result =
await audio_recorder_canister.deleteRecording(
global_recording.id
);
const deleteRecordingResult =
await audioRecorderCanister.deleteRecording(globalRecording.id);

if ('Err' in delete_recording_result) {
if ('Err' in deleteRecordingResult) {
throw new Error(
JSON.stringify(delete_recording_result.Err, null, 2)
JSON.stringify(deleteRecordingResult.Err, null, 2)
);
}

const read_recordings_result =
await audio_recorder_canister.readRecordings();
const read_users_result = await audio_recorder_canister.readUsers();
const readRecordingsResult =
await audioRecorderCanister.readRecordings();
const readUsersResult = await audioRecorderCanister.readUsers();

expect(read_recordings_result).toHaveLength(0);
expect(read_users_result).toHaveLength(1);
expect(read_users_result[0].recordingIds).toHaveLength(0);
expect(readRecordingsResult).toHaveLength(0);
expect(readUsersResult).toHaveLength(1);
expect(readUsersResult[0].recordingIds).toHaveLength(0);
});

it('deletes user from stable memory', async () => {
const create_recording_result =
await audio_recorder_canister.createRecording(
const createRecordingResult =
await audioRecorderCanister.createRecording(
Uint8Array.from([]),
'second recording',
global_user.id
globalUser.id
);

if ('Err' in create_recording_result) {
throw new Error(
JSON.stringify(create_recording_result.Err, null, 2)
);
}
expect(createRecordingResult).toEqual(
expect.objectContaining({
userId: globalUser.id,
audio: Uint8Array.from([]),
name: 'second recording'
})
);

const read_users_before_result =
await audio_recorder_canister.readUsers();
const read_recordings_before_result =
await audio_recorder_canister.readRecordings();
const readUsersBeforeResult =
await audioRecorderCanister.readUsers();
const readRecordingsBeforeResult =
await audioRecorderCanister.readRecordings();

const delete_user_result = await audio_recorder_canister.deleteUser(
global_user.id
const deleteUserResult = await audioRecorderCanister.deleteUser(
globalUser.id
);

if ('Err' in delete_user_result) {
throw new Error(
JSON.stringify(delete_user_result.Err, null, 2)
);
}
expect(deleteUserResult).toEqual(
expect.objectContaining({
id: globalUser.id,
username: globalUser.username
})
);

const read_users_after_result =
await audio_recorder_canister.readUsers();
const read_recordings_after_result =
await audio_recorder_canister.readRecordings();
const readUsersAfterResult =
await audioRecorderCanister.readUsers();
const readRecordingsAfterResult =
await audioRecorderCanister.readRecordings();

expect(read_users_before_result).toHaveLength(1);
expect(read_users_before_result[0].recordingIds.length).toBe(1);
expect(read_recordings_before_result).toHaveLength(1);
expect(read_recordings_before_result[0].userId).toStrictEqual(
global_user.id
expect(readUsersBeforeResult).toHaveLength(1);
expect(readUsersBeforeResult[0].recordingIds.length).toBe(1);
expect(readRecordingsBeforeResult).toHaveLength(1);
expect(readRecordingsBeforeResult[0].userId).toStrictEqual(
globalUser.id
);
expect(read_users_after_result).toHaveLength(0);
expect(read_recordings_after_result).toHaveLength(0);
expect(readUsersAfterResult).toHaveLength(0);
expect(readRecordingsAfterResult).toHaveLength(0);
});
};
}
Loading

0 comments on commit 2b37061

Please sign in to comment.