fix test
This commit is contained in:
parent
54048b29c4
commit
abadcd4eaa
|
@ -68,7 +68,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
||||||
private static String event;
|
private static String event;
|
||||||
|
|
||||||
Profile profile;
|
Profile profile;
|
||||||
ProfileStore profileStore;
|
public ProfileStore profileStore;
|
||||||
String units = Constants.MGDL;
|
String units = Constants.MGDL;
|
||||||
|
|
||||||
TextView eventTypeText;
|
TextView eventTypeText;
|
||||||
|
@ -680,7 +680,7 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void createNSTreatment(JSONObject data) {
|
public void createNSTreatment(JSONObject data) {
|
||||||
if (options.executeProfileSwitch) {
|
if (options.executeProfileSwitch) {
|
||||||
if (data.has("profile")) {
|
if (data.has("profile")) {
|
||||||
doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
|
doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package info.nightscout.androidaps.plugins.ProfileLocal;
|
package info.nightscout.androidaps.plugins.ProfileLocal;
|
||||||
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
@ -70,18 +68,15 @@ public class LocalProfilePlugin extends PluginBase implements ProfileInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void storeSettings() {
|
public synchronized void storeSettings() {
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(MainApp.instance().getApplicationContext());
|
SP.putBoolean(LOCAL_PROFILE + "mmol", mmol);
|
||||||
SharedPreferences.Editor editor = settings.edit();
|
SP.putBoolean(LOCAL_PROFILE + "mgdl", mgdl);
|
||||||
editor.putBoolean(LOCAL_PROFILE + "mmol", mmol);
|
SP.putString(LOCAL_PROFILE + "dia", dia.toString());
|
||||||
editor.putBoolean(LOCAL_PROFILE + "mgdl", mgdl);
|
SP.putString(LOCAL_PROFILE + "ic", ic.toString());
|
||||||
editor.putString(LOCAL_PROFILE + "dia", dia.toString());
|
SP.putString(LOCAL_PROFILE + "isf", isf.toString());
|
||||||
editor.putString(LOCAL_PROFILE + "ic", ic.toString());
|
SP.putString(LOCAL_PROFILE + "basal", basal.toString());
|
||||||
editor.putString(LOCAL_PROFILE + "isf", isf.toString());
|
SP.putString(LOCAL_PROFILE + "targetlow", targetLow.toString());
|
||||||
editor.putString(LOCAL_PROFILE + "basal", basal.toString());
|
SP.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString());
|
||||||
editor.putString(LOCAL_PROFILE + "targetlow", targetLow.toString());
|
|
||||||
editor.putString(LOCAL_PROFILE + "targethigh", targetHigh.toString());
|
|
||||||
|
|
||||||
editor.apply();
|
|
||||||
createAndStoreConvertedProfile();
|
createAndStoreConvertedProfile();
|
||||||
edited = false;
|
edited = false;
|
||||||
if (Config.logPrefsChange)
|
if (Config.logPrefsChange)
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class SP {
|
||||||
return sharedPreferences.getString(key, defaultValue);
|
return sharedPreferences.getString(key, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public boolean getBoolean(int resourceID, boolean defaultValue) {
|
static public boolean getBoolean(int resourceID, Boolean defaultValue) {
|
||||||
try {
|
try {
|
||||||
return sharedPreferences.getBoolean(MainApp.sResources.getString(resourceID), defaultValue);
|
return sharedPreferences.getBoolean(MainApp.sResources.getString(resourceID), defaultValue);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -32,7 +32,7 @@ public class SP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static public boolean getBoolean(String key, boolean defaultValue) {
|
static public boolean getBoolean(String key, Boolean defaultValue) {
|
||||||
try {
|
try {
|
||||||
return sharedPreferences.getBoolean(key, defaultValue);
|
return sharedPreferences.getBoolean(key, defaultValue);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -2,16 +2,12 @@ package info;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import com.squareup.otto.Bus;
|
import com.squareup.otto.Bus;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.mockito.ArgumentMatchers;
|
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -21,8 +17,10 @@ import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.ConstraintChecker;
|
import info.nightscout.androidaps.data.ConstraintChecker;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
|
import info.nightscout.androidaps.data.ProfileStore;
|
||||||
import info.nightscout.androidaps.db.DatabaseHelper;
|
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||||
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentService;
|
||||||
import info.nightscout.androidaps.queue.CommandQueue;
|
import info.nightscout.androidaps.queue.CommandQueue;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
|
@ -39,6 +37,8 @@ import static org.mockito.Mockito.when;
|
||||||
public class AAPSMocker {
|
public class AAPSMocker {
|
||||||
private static String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
private static String validProfile = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"},{\"time\":\"2:00\",\"value\":\"110\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}";
|
||||||
private static Profile profile;
|
private static Profile profile;
|
||||||
|
private static ProfileStore profileStore;
|
||||||
|
public static final String TESTPROFILENAME = "someProfile";
|
||||||
|
|
||||||
public static Intent intentSent = null;
|
public static Intent intentSent = null;
|
||||||
|
|
||||||
|
@ -125,28 +125,6 @@ public class AAPSMocker {
|
||||||
public static void mockApplicationContext() {
|
public static void mockApplicationContext() {
|
||||||
Context context = mock(Context.class);
|
Context context = mock(Context.class);
|
||||||
when(MainApp.instance().getApplicationContext()).thenReturn(context);
|
when(MainApp.instance().getApplicationContext()).thenReturn(context);
|
||||||
try {
|
|
||||||
PowerMockito.when(context, "sendBroadcast", ArgumentMatchers.any()).then(invocation -> {
|
|
||||||
Intent i = invocation.getArgument(0);
|
|
||||||
intentSent = i;
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
Assert.fail("Unable to mock the construction of the Context object: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void mockBundle() {
|
|
||||||
try {
|
|
||||||
PowerMockito.whenNew(Bundle.class).withNoArguments().thenAnswer(new Answer<Bundle>() {
|
|
||||||
@Override
|
|
||||||
public Bundle answer(InvocationOnMock invocation) throws Throwable {
|
|
||||||
return BundleMock.mock();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (Exception e) {
|
|
||||||
Assert.fail("Unable to mock the construction of the Bundle object: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void mockDatabaseHelper() {
|
public static void mockDatabaseHelper() {
|
||||||
|
@ -159,6 +137,11 @@ public class AAPSMocker {
|
||||||
when(ConfigBuilderPlugin.getCommandQueue()).thenReturn(queue);
|
when(ConfigBuilderPlugin.getCommandQueue()).thenReturn(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void mockTreatmentService() throws Exception {
|
||||||
|
TreatmentService treatmentService = PowerMockito.mock(TreatmentService.class);
|
||||||
|
PowerMockito.whenNew(TreatmentService.class).withNoArguments().thenReturn(treatmentService);
|
||||||
|
}
|
||||||
|
|
||||||
public static Profile getValidProfile() {
|
public static Profile getValidProfile() {
|
||||||
try {
|
try {
|
||||||
if (profile == null)
|
if (profile == null)
|
||||||
|
@ -168,6 +151,24 @@ public class AAPSMocker {
|
||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ProfileStore getValidProfileStore() {
|
||||||
|
try {
|
||||||
|
if (profileStore == null) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
JSONObject store = new JSONObject();
|
||||||
|
JSONObject profile = new JSONObject(validProfile);
|
||||||
|
|
||||||
|
json.put("defaultProfile", TESTPROFILENAME);
|
||||||
|
json.put("store", store);
|
||||||
|
store.put(TESTPROFILENAME, profile);
|
||||||
|
profileStore = new ProfileStore(json);
|
||||||
|
}
|
||||||
|
} catch (JSONException ignored) {
|
||||||
|
Assert.fail("getValidProfileStore() failed");
|
||||||
|
}
|
||||||
|
return profileStore;
|
||||||
|
}
|
||||||
|
|
||||||
private static MockedBus bus = new MockedBus();
|
private static MockedBus bus = new MockedBus();
|
||||||
|
|
||||||
public static void prepareMockedBus() {
|
public static void prepareMockedBus() {
|
||||||
|
|
|
@ -2,17 +2,12 @@ package info;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
import org.powermock.api.mockito.PowerMockito;
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
import static org.powermock.api.mockito.PowerMockito.when;
|
|
||||||
|
|
||||||
public class SPMocker {
|
public class SPMocker {
|
||||||
|
|
||||||
static HashMap<String, Object> data = new HashMap<>();
|
static HashMap<String, Object> data = new HashMap<>();
|
||||||
|
@ -24,19 +19,48 @@ public class SPMocker {
|
||||||
PowerMockito.when(SP.class, "putString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> {
|
PowerMockito.when(SP.class, "putString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> {
|
||||||
String key = invocation.getArgument(0);
|
String key = invocation.getArgument(0);
|
||||||
String value = invocation.getArgument(1);
|
String value = invocation.getArgument(1);
|
||||||
data.put(key,value);
|
data.put(key, value);
|
||||||
|
System.out.print("putString " + key + " " + value + "\n");
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
PowerMockito.when(SP.class, "getString", ArgumentMatchers.anyString(), ArgumentMatchers.anyString()).then(invocation -> {
|
PowerMockito.when(SP.class, "getString", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> {
|
||||||
String key = invocation.getArgument(0);
|
String key = invocation.getArgument(0);
|
||||||
String def = invocation.getArgument(1);
|
String def = invocation.getArgument(1);
|
||||||
String value = (String) data.get(key);
|
String value = (String) data.get(key);
|
||||||
if (value == null) value = def;
|
if (value == null) value = def;
|
||||||
|
System.out.print("getString " + key + " " + value + "\n");
|
||||||
return value;
|
return value;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PowerMockito.when(SP.class, "putBoolean", ArgumentMatchers.anyString(), ArgumentMatchers.anyBoolean()).then(invocation -> {
|
||||||
|
String key = invocation.getArgument(0);
|
||||||
|
Boolean value = invocation.getArgument(1);
|
||||||
|
data.put(key, value);
|
||||||
|
System.out.print("putBoolean " + key + " " + value + "\n");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
PowerMockito.when(SP.class, "getBoolean", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> {
|
||||||
|
String key = invocation.getArgument(0);
|
||||||
|
Boolean def = invocation.getArgument(1);
|
||||||
|
Boolean value = (Boolean) data.get(key);
|
||||||
|
if (value == null) value = def;
|
||||||
|
System.out.print("getBoolean " + key + " " + value + "\n");
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
PowerMockito.when(SP.class, "getDouble", ArgumentMatchers.anyString(), ArgumentMatchers.any()).then(invocation -> {
|
||||||
|
String key = invocation.getArgument(0);
|
||||||
|
Double def = invocation.getArgument(1);
|
||||||
|
Double value = (Double) data.get(key);
|
||||||
|
if (value == null) value = def;
|
||||||
|
System.out.print("getDouble " + key + " " + value + "\n");
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Assert.fail("Unable to mock the construction of the SP object");
|
Assert.fail("Unable to mock the construction of the SP object: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,62 @@
|
||||||
package info.nightscout.androidaps.plugins.Careportal.Dialogs;
|
package info.nightscout.androidaps.plugins.Careportal.Dialogs;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentMatchers;
|
||||||
|
import org.powermock.api.mockito.PowerMockito;
|
||||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||||
import org.powermock.modules.junit4.PowerMockRunner;
|
import org.powermock.modules.junit4.PowerMockRunner;
|
||||||
|
|
||||||
import info.AAPSMocker;
|
import info.AAPSMocker;
|
||||||
import info.BundleMock;
|
import info.SPMocker;
|
||||||
import info.nightscout.androidaps.MainApp;
|
import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.plugins.Careportal.CareportalFragment;
|
import info.nightscout.androidaps.db.DatabaseHelper;
|
||||||
|
import info.nightscout.androidaps.db.ProfileSwitch;
|
||||||
|
import info.nightscout.androidaps.plugins.Careportal.Dialogs.NewNSTreatmentDialog;
|
||||||
|
import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.ProfileNS.NSProfilePlugin;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentService;
|
||||||
|
import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin;
|
||||||
|
import info.nightscout.utils.NSUpload;
|
||||||
import info.nightscout.utils.SP;
|
import info.nightscout.utils.SP;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static info.nightscout.androidaps.plugins.Careportal.CareportalFragment.PROFILESWITCH;
|
||||||
|
import static org.powermock.api.mockito.PowerMockito.doAnswer;
|
||||||
|
import static org.powermock.api.mockito.PowerMockito.when;
|
||||||
|
|
||||||
@RunWith(PowerMockRunner.class)
|
@RunWith(PowerMockRunner.class)
|
||||||
@PrepareForTest({MainApp.class, SP.class, Context.class})
|
@PrepareForTest({SP.class, MainApp.class, ConfigBuilderPlugin.class, Context.class, NSUpload.class, TreatmentsPlugin.class, TreatmentService.class, DatabaseHelper.class})
|
||||||
public class NewNSTreatmentDialogTest {
|
public class NewNSTreatmentDialogTest {
|
||||||
|
|
||||||
NewNSTreatmentDialog dialog;
|
NewNSTreatmentDialog dialog;
|
||||||
|
ProfileSwitch profileSwitchUpload = null;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void createNSTreatmentTest() throws JSONException {
|
public void createNSTreatmentTest() throws Exception {
|
||||||
// Test profile creation
|
// Test profile creation
|
||||||
dialog.setOptions(CareportalFragment.PROFILESWITCH, R.string.careportal_profileswitch);
|
doAnswer(invocation -> {
|
||||||
|
ProfileSwitch ps = invocation.getArgument(0);
|
||||||
|
profileSwitchUpload = ps;
|
||||||
|
return null;
|
||||||
|
}).when(NSUpload.class, "uploadProfileSwitch", ArgumentMatchers.any());
|
||||||
|
PROFILESWITCH.executeProfileSwitch = true;
|
||||||
|
dialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch);
|
||||||
|
dialog.profileStore = AAPSMocker.getValidProfileStore();
|
||||||
JSONObject data = new JSONObject();
|
JSONObject data = new JSONObject();
|
||||||
data.put("profile", AAPSMocker.getValidProfile().getData());
|
data.put("profile", AAPSMocker.TESTPROFILENAME);
|
||||||
data.put("duration", 0);
|
data.put("duration", 0);
|
||||||
data.put("percentage", 110);
|
data.put("percentage", 110);
|
||||||
data.put("timeshift", 0);
|
data.put("timeshift", 0);
|
||||||
dialog.createNSTreatment(data);
|
dialog.createNSTreatment(data);
|
||||||
|
|
||||||
Bundle bundles = AAPSMocker.intentSent.getExtras();
|
// Profile should be sent to NS
|
||||||
Assert.assertTrue(bundles.getString("profile").contains("00:00"));
|
Assert.assertEquals(AAPSMocker.TESTPROFILENAME, profileSwitchUpload.profileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -51,12 +68,21 @@ public class NewNSTreatmentDialogTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void prepareMock() {
|
public void prepareMock() throws Exception {
|
||||||
AAPSMocker.mockMainApp();
|
AAPSMocker.mockMainApp();
|
||||||
|
SPMocker.prepareMock();
|
||||||
|
SP.putString("profile", AAPSMocker.getValidProfileStore().getData().toString());
|
||||||
|
AAPSMocker.mockConfigBuilder();
|
||||||
AAPSMocker.mockApplicationContext();
|
AAPSMocker.mockApplicationContext();
|
||||||
AAPSMocker.mockSP();
|
|
||||||
AAPSMocker.mockStrings();
|
AAPSMocker.mockStrings();
|
||||||
AAPSMocker.mockBundle();
|
PowerMockito.mockStatic(NSUpload.class);
|
||||||
|
AAPSMocker.mockTreatmentService();
|
||||||
|
AAPSMocker.mockBus();
|
||||||
|
AAPSMocker.mockDatabaseHelper();
|
||||||
|
|
||||||
|
NSProfilePlugin profilePlugin = NSProfilePlugin.getPlugin();
|
||||||
|
when(MainApp.getConfigBuilder().getActiveProfileInterface())
|
||||||
|
.thenReturn(profilePlugin);
|
||||||
|
|
||||||
dialog = new NewNSTreatmentDialog();
|
dialog = new NewNSTreatmentDialog();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue