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]
25 pub fn install(pocket_ic: PocketIc, spec: InstallSpec) -> Self {
26 Self::try_install(pocket_ic, spec)
27 .unwrap_or_else(|err| panic!("failed to install standalone canister fixture: {err}"))
28 }
29
30 pub fn try_install(
35 pocket_ic: PocketIc,
36 spec: InstallSpec,
37 ) -> Result<Self, StandaloneCanisterInstallError> {
38 let canister_id = match pocket_ic.try_create_and_install(spec) {
39 Ok(canister_id) => canister_id,
40 Err(error) => return Err(StandaloneCanisterInstallError::new(pocket_ic, error)),
41 };
42
43 Ok(Self {
44 pocket_ic,
45 canister_id,
46 })
47 }
48
49 #[must_use]
51 pub const fn pocket_ic(&self) -> &PocketIc {
52 &self.pocket_ic
53 }
54
55 #[must_use]
57 pub const fn canister_id(&self) -> Principal {
58 self.canister_id
59 }
60
61 #[must_use]
63 pub fn into_parts(self) -> (PocketIc, Principal) {
64 (self.pocket_ic, self.canister_id)
65 }
66
67 pub fn update_candid<T, A>(&self, method: &str, args: A) -> Result<T, CandidCallError>
69 where
70 T: CandidType + DeserializeOwned,
71 A: ArgumentEncoder,
72 {
73 self.pocket_ic.update_candid(self.canister_id, method, args)
74 }
75
76 #[track_caller]
82 pub fn update_candid_or_panic<T, A>(&self, method: &str, args: A) -> T
83 where
84 T: CandidType + DeserializeOwned,
85 A: ArgumentEncoder,
86 {
87 self.pocket_ic
88 .update_candid_or_panic(self.canister_id, method, args)
89 }
90
91 pub fn update_candid_as<T, A>(
93 &self,
94 caller: Principal,
95 method: &str,
96 args: A,
97 ) -> Result<T, CandidCallError>
98 where
99 T: CandidType + DeserializeOwned,
100 A: ArgumentEncoder,
101 {
102 self.pocket_ic
103 .update_candid_as(self.canister_id, caller, method, args)
104 }
105
106 #[track_caller]
112 pub fn update_candid_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
113 where
114 T: CandidType + DeserializeOwned,
115 A: ArgumentEncoder,
116 {
117 self.pocket_ic
118 .update_candid_as_or_panic(self.canister_id, caller, method, args)
119 }
120
121 pub fn query_candid<T, A>(&self, method: &str, args: A) -> Result<T, CandidCallError>
123 where
124 T: CandidType + DeserializeOwned,
125 A: ArgumentEncoder,
126 {
127 self.pocket_ic.query_candid(self.canister_id, method, args)
128 }
129
130 #[track_caller]
136 pub fn query_candid_or_panic<T, A>(&self, method: &str, args: A) -> T
137 where
138 T: CandidType + DeserializeOwned,
139 A: ArgumentEncoder,
140 {
141 self.pocket_ic
142 .query_candid_or_panic(self.canister_id, method, args)
143 }
144
145 pub fn query_candid_as<T, A>(
147 &self,
148 caller: Principal,
149 method: &str,
150 args: A,
151 ) -> Result<T, CandidCallError>
152 where
153 T: CandidType + DeserializeOwned,
154 A: ArgumentEncoder,
155 {
156 self.pocket_ic
157 .query_candid_as(self.canister_id, caller, method, args)
158 }
159
160 #[track_caller]
166 pub fn query_candid_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
167 where
168 T: CandidType + DeserializeOwned,
169 A: ArgumentEncoder,
170 {
171 self.pocket_ic
172 .query_candid_as_or_panic(self.canister_id, caller, method, args)
173 }
174}