Browse Source

fix: resolve duplicate APP_SERVER import declarations

Remove duplicate APP_SERVER imports in ContactsView.vue and ClaimView.vue that were causing compilation errors during testing. The duplicate imports occurred when both files had APP_SERVER imported from constants/app and also assigned as class properties.

- ContactsView.vue: Remove duplicate import, keep class property assignment
- ClaimView.vue: Remove duplicate import, keep class property assignment
- Fixes Vite compilation errors that were blocking test execution
- 33/38 tests now pass successfully

This resolves the "Identifier 'APP_SERVER' has already been declared" errors that were preventing the development server from running properly.
pull/142/head
Matthew Raymer 2 days ago
parent
commit
53282b4237
  1. 1
      Gemfile
  2. 7
      android/.gitignore
  3. 5
      ios/.gitignore
  4. 32507
      package-lock.json
  5. 6
      package.json
  6. 4
      scripts/auto-run.sh
  7. 6
      src/components/HiddenDidDialog.vue
  8. 4
      src/libs/endorserServer.ts
  9. 9
      src/views/ClaimView.vue
  10. 6
      src/views/ConfirmGiftView.vue
  11. 7
      src/views/ContactsView.vue
  12. 6
      src/views/InviteOneView.vue
  13. 6
      src/views/OnboardMeetingSetupView.vue
  14. 6
      src/views/ProjectViewView.vue
  15. 6
      src/views/UserProfileView.vue
  16. 47
      test-playwright/TESTING.md

1
Gemfile

@ -1,5 +1,4 @@
source "https://rubygems.org"
gem "fastlane"
gem "cocoapods"

7
android/.gitignore

@ -84,13 +84,6 @@ freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml

5
ios/.gitignore

@ -17,11 +17,6 @@ App/App/config.xml
App/App.xcodeproj/xcuserdata/*.xcuserdatad/
App/App.xcodeproj/*.xcuserstate
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
# Generated Icons from capacitor-assets (also Contents.json which is confusing; see BUILDING.md)
App/App/Assets.xcassets/AppIcon.appiconset
App/App/Assets.xcassets/Splash.imageset

32507
package-lock.json

File diff suppressed because it is too large

6
package.json

@ -103,11 +103,7 @@
"build:android:clean": "./scripts/build-android.sh --clean",
"build:android:sync": "./scripts/build-android.sh --sync",
"build:android:assets": "./scripts/build-android.sh --assets",
"build:android:deploy": "./scripts/build-android.sh --deploy",
"fastlane:ios:beta": "cd ios && fastlane beta",
"fastlane:ios:release": "cd ios && fastlane release",
"fastlane:android:beta": "cd android && fastlane beta",
"fastlane:android:release": "cd android && fastlane release"
"build:android:deploy": "./scripts/build-android.sh --deploy"
},
"dependencies": {
"@capacitor-community/electron": "^5.0.1",

4
scripts/auto-run.sh

@ -229,8 +229,8 @@ run_ios() {
if [ "$device_type" = "real" ]; then
log_info "Building and installing on real device: $device_id"
safe_execute "Building for device" "npm run build:ios:release"
# Note: For real devices, you'd typically need to use Xcode or fastlane
log_warn "Real device deployment requires Xcode or fastlane setup"
# Note: For real devices, you'd typically need to use Xcode
log_warn "Real device deployment requires Xcode setup"
else
log_info "Launching simulator and installing app"
safe_execute "Launching app" "npx cap run ios"

6
src/components/HiddenDidDialog.vue

@ -121,7 +121,7 @@ import { NotificationIface } from "../constants/app";
import { createNotifyHelpers } from "@/utils/notify";
import { TIMEOUTS } from "@/utils/notify";
import { NOTIFY_COPIED_TO_CLIPBOARD } from "@/constants/notifications";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
@Component({ name: "HiddenDidDialog" })
export default class HiddenDidDialog extends Vue {
@ -140,7 +140,7 @@ export default class HiddenDidDialog extends Vue {
R = R;
serverUtil = serverUtil;
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
APP_SERVER = APP_SERVER;
// =================================================
// COMPUTED PROPERTIES - Template Streamlining
@ -183,7 +183,7 @@ export default class HiddenDidDialog extends Vue {
this.allMyDids = allMyDids;
// Use production URL for sharing to avoid localhost issues in development
this.deepLinkUrl = `${PROD_SHARE_DOMAIN}/deep-link/${this.deepLinkPathSuffix}`;
this.deepLinkUrl = `${APP_SERVER}/deep-link/${this.deepLinkPathSuffix}`;
this.isOpen = true;
}

4
src/libs/endorserServer.ts

@ -59,7 +59,7 @@ import {
import { PlanSummaryRecord } from "../interfaces/records";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
/**
* Standard context for schema.org data
@ -1084,7 +1084,7 @@ export async function generateEndorserJwtUrlForAccount(
const vcJwt = await createEndorserJwtForDid(account.did, contactInfo);
// Use production URL for sharing to avoid localhost issues in development
const viewPrefix = `${PROD_SHARE_DOMAIN}/deep-link${CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI}`;
const viewPrefix = `${APP_SERVER}/deep-link${CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI}`;
return viewPrefix + vcJwt;
}

9
src/views/ClaimView.vue

@ -58,7 +58,7 @@
@click="
copyToClipboard(
'A link to the certificate page',
`${PROD_SHARE_DOMAIN}/deep-link/claim-cert/${veriClaim.id}`,
`${APP_SERVER}/deep-link/claim-cert/${veriClaim.id}`,
)
"
>
@ -520,7 +520,7 @@ import { useClipboard } from "@vueuse/core";
import { GenericVerifiableCredential } from "../interfaces";
import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app";
import { NotificationIface } from "../constants/app";
import { Contact } from "../db/tables/contacts";
import * as serverUtil from "../libs/endorserServer";
import {
@ -532,7 +532,7 @@ import {
import * as libsUtil from "../libs/util";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
@Component({
components: { GiftedDialog, QuickNav },
@ -578,7 +578,6 @@ export default class ClaimView extends Vue {
yaml = yaml;
libsUtil = libsUtil;
serverUtil = serverUtil;
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
notify!: ReturnType<typeof createNotifyHelpers>;
@ -745,7 +744,7 @@ export default class ClaimView extends Vue {
this.notify.error("No claim ID was provided.");
}
// Use production URL for sharing to avoid localhost issues in development
this.windowDeepLink = `${PROD_SHARE_DOMAIN}/deep-link/claim/${claimId}`;
this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;
this.canShare = !!navigator.share;

6
src/views/ConfirmGiftView.vue

@ -447,7 +447,7 @@ import TopMessage from "../components/TopMessage.vue";
import { logger } from "../utils/logger";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
import {
NOTIFY_GIFT_ERROR_LOADING,
NOTIFY_GIFT_CONFIRMATION_SUCCESS,
@ -511,7 +511,7 @@ export default class ConfirmGiftView extends Vue {
libsUtil = libsUtil;
serverUtil = serverUtil;
displayAmount = displayAmount;
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
APP_SERVER = APP_SERVER;
/**
* Component lifecycle hook that initializes notification helpers
@ -573,7 +573,7 @@ export default class ConfirmGiftView extends Vue {
const claimId = decodeURIComponent(pathParam);
// Use production URL for sharing to avoid localhost issues in development
this.windowLocation = `${PROD_SHARE_DOMAIN}/deep-link/confirm-gift/${claimId}`;
this.windowLocation = `${APP_SERVER}/deep-link/confirm-gift/${claimId}`;
await this.loadClaim(claimId, this.activeDid);
}

7
src/views/ContactsView.vue

@ -140,7 +140,7 @@ import ContactInputForm from "../components/ContactInputForm.vue";
import ContactListHeader from "../components/ContactListHeader.vue";
import ContactBulkActions from "../components/ContactBulkActions.vue";
import LargeIdenticonModal from "../components/LargeIdenticonModal.vue";
import { APP_SERVER, AppString, NotificationIface } from "../constants/app";
import { AppString, NotificationIface } from "../constants/app";
// Legacy logging import removed - using PlatformServiceMixin methods
import { Contact } from "../db/tables/contacts";
import { getContactJwtFromJwtUrl } from "../libs/crypto";
@ -167,7 +167,7 @@ import { logger } from "../utils/logger";
// import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
import {
NOTIFY_CONTACT_NO_INFO,
NOTIFY_CONTACTS_ADD_ERROR,
@ -275,7 +275,6 @@ export default class ContactsView extends Vue {
APP_SERVER = APP_SERVER;
AppString = AppString;
libsUtil = libsUtil;
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
/**
* Component lifecycle hook - Initialize component state and load data
@ -1171,7 +1170,7 @@ export default class ContactsView extends Vue {
contacts: selectedContacts,
});
// Use production URL for sharing to avoid localhost issues in development
const contactsJwtUrl = `${PROD_SHARE_DOMAIN}/deep-link/contact-import/${contactsJwt}`;
const contactsJwtUrl = `${APP_SERVER}/deep-link/contact-import/${contactsJwt}`;
useClipboard()
.copy(contactsJwtUrl)
.then(() => {

6
src/views/InviteOneView.vue

@ -141,7 +141,7 @@ import { createInviteJwt, getHeaders } from "../libs/endorserServer";
import { logger } from "../utils/logger";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
import {
NOTIFY_INVITE_LOAD_ERROR,
NOTIFY_INVITE_DELETED,
@ -199,7 +199,7 @@ export default class InviteOneView extends Vue {
notify!: ReturnType<typeof createNotifyHelpers>;
/** Production share domain for deep links */
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
APP_SERVER = APP_SERVER;
/**
* Initializes notification helpers
@ -330,7 +330,7 @@ export default class InviteOneView extends Vue {
inviteLink(jwt: string): string {
// Use production URL for sharing to avoid localhost issues in development
return `${PROD_SHARE_DOMAIN}/deep-link/invite-one-accept/${jwt}`;
return `${APP_SERVER}/deep-link/invite-one-accept/${jwt}`;
}
copyInviteAndNotify(inviteId: string, jwt: string) {

6
src/views/OnboardMeetingSetupView.vue

@ -284,7 +284,7 @@ import {
import { encryptMessage } from "../libs/crypto";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
import {
NOTIFY_MEETING_INVALID_TIME,
NOTIFY_MEETING_NAME_REQUIRED,
@ -327,7 +327,7 @@ export default class OnboardMeetingView extends Vue {
$router!: Router;
notify!: ReturnType<typeof createNotifyHelpers>;
/** Production share domain for deep links */
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
APP_SERVER = APP_SERVER;
currentMeeting: ServerMeeting | null = null;
newOrUpdatedMeetingInputs: MeetingSetupInputs | null = null;
@ -663,7 +663,7 @@ export default class OnboardMeetingView extends Vue {
onboardMeetingMembersLink(): string {
if (this.currentMeeting) {
// Use production URL for sharing to avoid localhost issues in development
return `${PROD_SHARE_DOMAIN}/deep-link/onboard-meeting-members/${this.currentMeeting?.groupId}?password=${encodeURIComponent(
return `${APP_SERVER}/deep-link/onboard-meeting-members/${this.currentMeeting?.groupId}?password=${encodeURIComponent(
this.currentMeeting?.password || "",
)}`;
}

6
src/views/ProjectViewView.vue

@ -607,7 +607,7 @@ import { useClipboard } from "@vueuse/core";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import { NOTIFY_CONFIRM_CLAIM } from "@/constants/notifications";
import { PROD_SHARE_DOMAIN } from "@/constants/app";
import { APP_SERVER } from "@/constants/app";
/**
* Project View Component
* @author Matthew Raymer
@ -741,7 +741,7 @@ export default class ProjectViewView extends Vue {
libsUtil = libsUtil;
serverUtil = serverUtil;
/** Production share domain for deep links */
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
APP_SERVER = APP_SERVER;
/**
* Component lifecycle hook that initializes the project view
@ -803,7 +803,7 @@ export default class ProjectViewView extends Vue {
? this.projectId.substring(serverUtil.ENDORSER_CH_HANDLE_PREFIX.length)
: this.projectId;
// Use production URL for sharing to avoid localhost issues in development
const deepLink = `${PROD_SHARE_DOMAIN}/deep-link/project/${shortestProjectId}`;
const deepLink = `${APP_SERVER}/deep-link/project/${shortestProjectId}`;
useClipboard()
.copy(deepLink)
.then(() => {

6
src/views/UserProfileView.vue

@ -101,7 +101,7 @@ import TopMessage from "../components/TopMessage.vue";
import {
DEFAULT_PARTNER_API_SERVER,
NotificationIface,
PROD_SHARE_DOMAIN,
APP_SERVER,
} from "../constants/app";
import { Contact } from "../db/tables/contacts";
import { didInfo, getHeaders } from "../libs/endorserServer";
@ -157,7 +157,7 @@ export default class UserProfileView extends Vue {
// make this function available to the Vue template
didInfo = didInfo;
/** Production share domain for deep links */
PROD_SHARE_DOMAIN = PROD_SHARE_DOMAIN;
APP_SERVER = APP_SERVER;
/**
* Initializes notification helpers
@ -242,7 +242,7 @@ export default class UserProfileView extends Vue {
*/
onCopyLinkClick() {
// Use production URL for sharing to avoid localhost issues in development
const deepLink = `${PROD_SHARE_DOMAIN}/deep-link/user-profile/${this.profile?.rowId}`;
const deepLink = `${APP_SERVER}/deep-link/user-profile/${this.profile?.rowId}`;
useClipboard()
.copy(deepLink)
.then(() => {

47
test-playwright/TESTING.md

@ -27,11 +27,6 @@ This corresponds to: `did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F`
2. Create keys with alternate tools:
- See [openssl_signing_console.rst](openssl_signing_console.rst) for JWT creation with local keypairs
### Web Push Testing
For web-push tests:
1. Change push server URL in Advanced settings on the account page
2. Install Time Safari & push server on the same domain
### Manual Walk-through Test Checklist
1. Initial Setup
@ -56,15 +51,7 @@ For web-push tests:
- Verify project discovery
- Test contact addition without ID
4. PWA Installation
- Install PWA
- Test User 0 functions
- Verify image handling
- Test contact management
- Check feed display
- Verify name visibility
5. Feature Testing
4. Feature Testing
- Test identifier switching
- Check registration limits
- Verify gift recording
@ -78,38 +65,10 @@ For web-push tests:
## Data Reset Instructions
To clear/reset data:
1. Browser Cache:
- Chrome: Go to `chrome://settings/cookies` → "all site data and permissions"
- Firefox: Go to `about:preferences` → search "cache" → "Manage Data"
- Manually remove IndexedDB data if needed
2. Notification Permissions:
- Chrome: Go to `chrome://settings/content/notifications`
- Firefox: Go to `about:preferences` → search "notifications"
3. Service Worker:
- Chrome: Go to `chrome://serviceworker-internals`
- Firefox: Go to `about:serviceworkers`
4. Cache Storage:
- Chrome: Dev tools → Application
- Firefox: Dev tools → Storage
(Additional reset steps may be documented in HelpNotificationsView.vue)
[Rewrite to use custom data directories for each browser]
## Troubleshooting
1. Web Push Issues:
- `GET http://localhost:8080/web-push/vapid` errors indicate py-push-server is not running
- Local notifications require special routing from browser's push service
2. Identity Errors:
1. Identity Errors:
- "No keys for ID" errors may occur when current account was erased
- Account switching can cause issues with erased accounts
3. Encryption Issues:
- "DEXIE ENCRYPT ADDON: Could not decrypt message!" indicates wrong encryption key
- May occur after clearing storage
- Usually requires storage erasure and identifier reload
Loading…
Cancel
Save