1use candid::{CandidType, Principal, utils::ArgumentEncoder};
2use pocket_ic::PocketIc;
3use serde::de::DeserializeOwned;
4
5use super::{
6 CandidCallError, CandidCallExt, CanisterInstallExt, InstallSpec, StandaloneCanisterInstallError,
7};
8
9pub struct StandaloneCanisterFixture {
14 pocket_ic: PocketIc,
15 canister_id: Principal,
16}
17
18impl StandaloneCanisterFixture {
19 #[must_use]
21 pub fn install(pocket_ic: PocketIc, spec: InstallSpec) -> Self {
22 Self::try_install(pocket_ic, spec)
23 .unwrap_or_else(|err| panic!("failed to install standalone canister fixture: {err}"))
24 }
25
26 pub fn try_install(
31 pocket_ic: PocketIc,
32 spec: InstallSpec,
33 ) -> Result<Self, StandaloneCanisterInstallError> {
34 let canister_id = match pocket_ic.try_create_and_install(spec) {
35 Ok(canister_id) => canister_id,
36 Err(error) => return Err(StandaloneCanisterInstallError::new(pocket_ic, error)),
37 };
38
39 Ok(Self {
40 pocket_ic,
41 canister_id,
42 })
43 }
44
45 #[must_use]
47 pub const fn pocket_ic(&self) -> &PocketIc {
48 &self.pocket_ic
49 }
50
51 #[must_use]
53 pub const fn canister_id(&self) -> Principal {
54 self.canister_id
55 }
56
57 #[must_use]
59 pub fn into_parts(self) -> (PocketIc, Principal) {
60 (self.pocket_ic, self.canister_id)
61 }
62
63 pub fn update_candid<T, A>(&self, method: &str, args: A) -> Result<T, CandidCallError>
65 where
66 T: CandidType + DeserializeOwned,
67 A: ArgumentEncoder,
68 {
69 self.pocket_ic.update_candid(self.canister_id, method, args)
70 }
71
72 #[track_caller]
78 pub fn update_candid_or_panic<T, A>(&self, method: &str, args: A) -> T
79 where
80 T: CandidType + DeserializeOwned,
81 A: ArgumentEncoder,
82 {
83 self.pocket_ic
84 .update_candid_or_panic(self.canister_id, method, args)
85 }
86
87 pub fn update_candid_as<T, A>(
89 &self,
90 caller: Principal,
91 method: &str,
92 args: A,
93 ) -> Result<T, CandidCallError>
94 where
95 T: CandidType + DeserializeOwned,
96 A: ArgumentEncoder,
97 {
98 self.pocket_ic
99 .update_candid_as(self.canister_id, caller, method, args)
100 }
101
102 #[track_caller]
108 pub fn update_candid_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
109 where
110 T: CandidType + DeserializeOwned,
111 A: ArgumentEncoder,
112 {
113 self.pocket_ic
114 .update_candid_as_or_panic(self.canister_id, caller, method, args)
115 }
116
117 pub fn query_candid<T, A>(&self, method: &str, args: A) -> Result<T, CandidCallError>
119 where
120 T: CandidType + DeserializeOwned,
121 A: ArgumentEncoder,
122 {
123 self.pocket_ic.query_candid(self.canister_id, method, args)
124 }
125
126 #[track_caller]
132 pub fn query_candid_or_panic<T, A>(&self, method: &str, args: A) -> T
133 where
134 T: CandidType + DeserializeOwned,
135 A: ArgumentEncoder,
136 {
137 self.pocket_ic
138 .query_candid_or_panic(self.canister_id, method, args)
139 }
140
141 pub fn query_candid_as<T, A>(
143 &self,
144 caller: Principal,
145 method: &str,
146 args: A,
147 ) -> Result<T, CandidCallError>
148 where
149 T: CandidType + DeserializeOwned,
150 A: ArgumentEncoder,
151 {
152 self.pocket_ic
153 .query_candid_as(self.canister_id, caller, method, args)
154 }
155
156 #[track_caller]
162 pub fn query_candid_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
163 where
164 T: CandidType + DeserializeOwned,
165 A: ArgumentEncoder,
166 {
167 self.pocket_ic
168 .query_candid_as_or_panic(self.canister_id, caller, method, args)
169 }
170}