forked from trent_larson/crowd-funder-for-time-pwa
fix image server references for tests (2 tests failing: missing function & looking for registration prompt for unregistered user)
This commit is contained in:
@@ -6,6 +6,7 @@ VITE_APP_SERVER=http://localhost:3000
|
||||
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
|
||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
||||
VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000
|
||||
VITE_DEFAULT_IMAGE_API_SERVER=http://localhost:3000
|
||||
# Using shared server by default to ease setup, which works for shared test users.
|
||||
VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app
|
||||
VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000
|
||||
VITE_PASSKEYS_ENABLED=true
|
||||
VITE_PASSKEYS_ENABLED=true
|
||||
|
||||
@@ -6,5 +6,6 @@ VITE_APP_SERVER=https://timesafari.app
|
||||
# This is the claim ID for actions in the BVC project.
|
||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01GXYPFF7FA03NXKPYY142PY4H
|
||||
VITE_DEFAULT_ENDORSER_API_SERVER=https://api.endorser.ch
|
||||
|
||||
VITE_DEFAULT_IMAGE_API_SERVER=https://image-api.timesafari.app
|
||||
VITE_DEFAULT_PARTNER_API_SERVER=https://partner-api.endorser.ch
|
||||
|
||||
@@ -6,6 +6,7 @@ VITE_APP_SERVER=https://test.timesafari.app
|
||||
# This is the claim ID for actions in the BVC project, with the JWT ID on this environment (not production).
|
||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
||||
VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch
|
||||
|
||||
VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app
|
||||
VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch
|
||||
VITE_PASSKEYS_ENABLED=true
|
||||
|
||||
27
BUILDING.md
27
BUILDING.md
@@ -246,32 +246,7 @@ npm run lint-fix
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
### Development
|
||||
Create a `.env.development` file:
|
||||
```bash
|
||||
TIME_SAFARI_APP_TITLE="TimeSafari_Dev"
|
||||
VITE_APP_SERVER=http://localhost:3000
|
||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
||||
VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000
|
||||
VITE_DEFAULT_IMAGE_API_SERVER=http://localhost:3000
|
||||
VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000
|
||||
VITE_PASSKEYS_ENABLED=true
|
||||
```
|
||||
|
||||
### Test/Staging
|
||||
Create a `.env.staging` file:
|
||||
```bash
|
||||
TIME_SAFARI_APP_TITLE="TimeSafari_Test"
|
||||
VITE_APP_SERVER=https://test.timesafari.app
|
||||
VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F
|
||||
VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch
|
||||
VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app
|
||||
VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch
|
||||
VITE_PASSKEYS_ENABLED=true
|
||||
```
|
||||
|
||||
### Production
|
||||
The `.env.production` file will be used automatically for production builds.
|
||||
See `.env.*` files for configuration.
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ export default defineConfig({
|
||||
*/
|
||||
webServer: {
|
||||
command:
|
||||
"VITE_APP_SERVER=http://localhost:8081 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_PASSKEYS_ENABLED=true npm run dev -- --port=8081",
|
||||
"VITE_APP_SERVER=http://localhost:8081 VITE_DEFAULT_ENDORSER_API_SERVER=http://localhost:3000 VITE_DEFAULT_PARTNER_API_SERVER=http://localhost:3000 VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_PASSKEYS_ENABLED=true npm run dev -- --port=8081",
|
||||
url: "http://localhost:8081",
|
||||
reuseExistingServer: !process.env.CI,
|
||||
},
|
||||
|
||||
68
src/App.vue
68
src/App.vue
@@ -333,12 +333,40 @@ export default class App extends Vue {
|
||||
|
||||
stopAsking = false;
|
||||
|
||||
created() {
|
||||
console.log(
|
||||
"Component created: Reactivity set up.",
|
||||
window.location.pathname,
|
||||
);
|
||||
}
|
||||
// created() {
|
||||
// console.log(
|
||||
// "Component created: Reactivity set up.",
|
||||
// window.location.pathname,
|
||||
// );
|
||||
// }
|
||||
|
||||
// beforeCreate() {
|
||||
// console.log("Component beforeCreate: Instance initialized.");
|
||||
// }
|
||||
|
||||
// beforeMount() {
|
||||
// console.log("Component beforeMount: Template is about to be rendered.");
|
||||
// }
|
||||
|
||||
// mounted() {
|
||||
// console.log("Component mounted: Template is now rendered.");
|
||||
// }
|
||||
|
||||
// beforeUpdate() {
|
||||
// console.log("Component beforeUpdate: DOM is about to be updated.");
|
||||
// }
|
||||
|
||||
// updated() {
|
||||
// console.log("Component updated: DOM has been updated.");
|
||||
// }
|
||||
|
||||
// beforeUnmount() {
|
||||
// console.log("Component beforeUnmount: Cleaning up before removal.");
|
||||
// }
|
||||
|
||||
// unmounted() {
|
||||
// console.log("Component unmounted: Component removed from the DOM.");
|
||||
// }
|
||||
|
||||
truncateLongWords(sentence: string) {
|
||||
return sentence
|
||||
@@ -347,34 +375,6 @@ export default class App extends Vue {
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
beforeCreate() {
|
||||
console.log("Component beforeCreate: Instance initialized.");
|
||||
}
|
||||
|
||||
beforeMount() {
|
||||
console.log("Component beforeMount: Template is about to be rendered.");
|
||||
}
|
||||
|
||||
mounted() {
|
||||
console.log("Component mounted: Template is now rendered.");
|
||||
}
|
||||
|
||||
beforeUpdate() {
|
||||
console.log("Component beforeUpdate: DOM is about to be updated.");
|
||||
}
|
||||
|
||||
updated() {
|
||||
console.log("Component updated: DOM has been updated.");
|
||||
}
|
||||
|
||||
beforeUnmount() {
|
||||
console.log("Component beforeUnmount: Cleaning up before removal.");
|
||||
}
|
||||
|
||||
unmounted() {
|
||||
console.log("Component unmounted: Component removed from the DOM.");
|
||||
}
|
||||
|
||||
async turnOffNotifications(
|
||||
notification: NotificationIface,
|
||||
): Promise<boolean> {
|
||||
|
||||
@@ -369,6 +369,14 @@ export default class PhotoDialog extends Vue {
|
||||
formData.append("image", this.blob, this.fileName || "snapshot.png");
|
||||
formData.append("claimType", this.claimType);
|
||||
try {
|
||||
if (
|
||||
window.location.hostname === "localhost" &&
|
||||
!DEFAULT_IMAGE_API_SERVER.includes("localhost")
|
||||
) {
|
||||
console.log(
|
||||
"Using shared image API server, so only users on that server can play with images.",
|
||||
);
|
||||
}
|
||||
const response = await axios.post(
|
||||
DEFAULT_IMAGE_API_SERVER + "/image",
|
||||
formData,
|
||||
|
||||
@@ -197,7 +197,7 @@ function setupGlobalErrorHandler(app: VueApp) {
|
||||
);
|
||||
};
|
||||
}
|
||||
console.log("Bootstrapping Vue app...");
|
||||
// console.log("Bootstrapping Vue app...");
|
||||
const app = createApp(App)
|
||||
.component("fa", FontAwesomeIcon)
|
||||
.component("camera", Camera)
|
||||
@@ -209,4 +209,4 @@ const app = createApp(App)
|
||||
setupGlobalErrorHandler(app);
|
||||
|
||||
app.mount("#app");
|
||||
console.log("Vue app mounted.");
|
||||
// console.log("Vue app mounted.");
|
||||
|
||||
@@ -23,8 +23,6 @@ const enterOrStart = async (
|
||||
const accountsDB = await accountsDBPromise;
|
||||
const num_accounts = await accountsDB.accounts.count();
|
||||
|
||||
console.log("Number of accounts: ", num_accounts);
|
||||
|
||||
if (num_accounts > 0) {
|
||||
next();
|
||||
} else {
|
||||
@@ -299,8 +297,6 @@ const router = createRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
console.log("Initial URL:", initialPath);
|
||||
|
||||
// Replace initial URL to start at `/` if necessary
|
||||
router.replace(initialPath || "/");
|
||||
|
||||
@@ -319,12 +315,10 @@ const errorHandler = (
|
||||
|
||||
router.onError(errorHandler); // Assign the error handler to the router instance
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log("Navigating to view:", to.name);
|
||||
console.log("From view:", from.name);
|
||||
next();
|
||||
});
|
||||
|
||||
console.log("Initial URL:", window.location.pathname);
|
||||
// router.beforeEach((to, from, next) => {
|
||||
// console.log("Navigating to view:", to.name);
|
||||
// console.log("From view:", from.name);
|
||||
// next();
|
||||
// });
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -365,35 +365,41 @@
|
||||
<div v-if="loadingLimits" class="text-center">
|
||||
Checking… <fa icon="spinner" class="fa-spin"></fa>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-4 text-center">
|
||||
{{ limitsMessage }}
|
||||
</div>
|
||||
<div v-if="!!endorserLimits?.nextWeekBeginDateTime">
|
||||
<div>
|
||||
<p class="text-sm">
|
||||
You have done
|
||||
<b>{{ endorserLimits.doneClaimsThisWeek }} claims</b> out of
|
||||
<b>{{ endorserLimits.maxClaimsPerWeek }}</b> for this week. Your
|
||||
claims counter resets at
|
||||
<b>{{ endorserLimits?.doneClaimsThisWeek || "?" }} claims</b> out of
|
||||
<b>{{ endorserLimits?.maxClaimsPerWeek || "?" }}</b> for this week.
|
||||
Your claims counter resets at
|
||||
<b class="whitespace-nowrap">{{
|
||||
readableDate(endorserLimits.nextWeekBeginDateTime)
|
||||
readableDate(endorserLimits?.nextWeekBeginDateTime)
|
||||
}}</b>
|
||||
</p>
|
||||
<p class="mt-3 text-sm">
|
||||
You have done
|
||||
<b>{{ endorserLimits.doneRegistrationsThisMonth }} registrations</b>
|
||||
out of <b>{{ endorserLimits.maxRegistrationsPerMonth }}</b> for this
|
||||
month.
|
||||
<i>(You cannot register anyone else on your first day.)</i>
|
||||
<b
|
||||
>{{
|
||||
endorserLimits?.doneRegistrationsThisMonth || "?"
|
||||
}}
|
||||
registrations</b
|
||||
>
|
||||
out of
|
||||
<b>{{ endorserLimits?.maxRegistrationsPerMonth || "?" }}</b> for this
|
||||
this month.
|
||||
<i>(You cannot register anyone on your first day.)</i>
|
||||
Your registration counter resets at
|
||||
<b class="whitespace-nowrap">
|
||||
{{ readableDate(endorserLimits.nextMonthBeginDateTime) }}
|
||||
{{ readableDate(endorserLimits?.nextMonthBeginDateTime) }}
|
||||
</b>
|
||||
</p>
|
||||
<p class="mt-3 text-sm" v-if="!!imageLimits">
|
||||
<p class="mt-3 text-sm">
|
||||
You have uploaded
|
||||
<b>{{ imageLimits?.doneImagesThisWeek }} images</b> out of
|
||||
<b>{{ imageLimits?.maxImagesPerWeek }}</b> for this week. Your image
|
||||
counter resets at
|
||||
<b>{{ imageLimits?.doneImagesThisWeek || "?" }} images</b> out of
|
||||
<b>{{ imageLimits?.maxImagesPerWeek || "?" }}</b> for this week. Your
|
||||
image counter resets at
|
||||
<b class="whitespace-nowrap">{{
|
||||
readableDate(imageLimits?.nextWeekBeginDateTime)
|
||||
}}</b>
|
||||
@@ -1215,7 +1221,7 @@ export default class AccountViewView extends Vue {
|
||||
}
|
||||
|
||||
readableDate(timeStr: string) {
|
||||
return timeStr.substring(0, timeStr.indexOf("T"));
|
||||
return timeStr ? timeStr.substring(0, timeStr.indexOf("T")) : "?";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1230,11 +1236,11 @@ export default class AccountViewView extends Vue {
|
||||
this.publicHex = identity.keys[0].publicKeyHex;
|
||||
this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64");
|
||||
this.derivationPath = identity.keys[0].meta?.derivationPath as string;
|
||||
await this.checkLimitsFor(this.activeDid);
|
||||
await this.checkLimits();
|
||||
} else if (account?.publicKeyHex) {
|
||||
this.publicHex = account.publicKeyHex as string;
|
||||
this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64");
|
||||
await this.checkLimitsFor(this.activeDid);
|
||||
await this.checkLimits();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1598,11 +1604,13 @@ export default class AccountViewView extends Vue {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use "checkLimits" instead.
|
||||
*
|
||||
* Asynchronously checks rate limits for the given identity.
|
||||
*
|
||||
* Updates component state variables `limits`, `limitsMessage`, and `loadingLimits`.
|
||||
*/
|
||||
public async checkLimitsFor(did: string) {
|
||||
private async checkLimitsFor(did: string) {
|
||||
this.loadingLimits = true;
|
||||
this.limitsMessage = "";
|
||||
|
||||
@@ -1632,9 +1640,15 @@ export default class AccountViewView extends Vue {
|
||||
);
|
||||
}
|
||||
}
|
||||
const imageResp = await fetchImageRateLimits(this.axios, did);
|
||||
if (imageResp.status === 200) {
|
||||
this.imageLimits = imageResp.data;
|
||||
try {
|
||||
const imageResp = await fetchImageRateLimits(this.axios, did);
|
||||
if (imageResp.status === 200) {
|
||||
this.imageLimits = imageResp.data;
|
||||
} else {
|
||||
this.limitsMessage = "You don't have access to upload images.";
|
||||
}
|
||||
} catch {
|
||||
this.limitsMessage = "You cannot upload images.";
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -1739,6 +1753,14 @@ export default class AccountViewView extends Vue {
|
||||
try {
|
||||
const headers = await getHeaders(this.activeDid);
|
||||
this.passkeyExpirationDescription = tokenExpiryTimeDescription();
|
||||
if (
|
||||
window.location.hostname === "localhost" &&
|
||||
!DEFAULT_IMAGE_API_SERVER.includes("localhost")
|
||||
) {
|
||||
console.log(
|
||||
"Using shared image API server, so only users on that server can play with images.",
|
||||
);
|
||||
}
|
||||
const response = await this.axios.delete(
|
||||
DEFAULT_IMAGE_API_SERVER +
|
||||
"/image/" +
|
||||
|
||||
@@ -302,7 +302,10 @@ import InfiniteScroll from "../components/InfiniteScroll.vue";
|
||||
import ProjectIcon from "../components/ProjectIcon.vue";
|
||||
import OnboardingDialog from "../components/OnboardingDialog.vue";
|
||||
import TopMessage from "../components/TopMessage.vue";
|
||||
import { NotificationIface, DEFAULT_PARTNER_API_SERVER } from "../constants/app";
|
||||
import {
|
||||
NotificationIface,
|
||||
DEFAULT_PARTNER_API_SERVER,
|
||||
} from "../constants/app";
|
||||
import {
|
||||
db,
|
||||
logConsoleAndDb,
|
||||
|
||||
@@ -547,6 +547,14 @@ export default class GiftedDetails extends Vue {
|
||||
}
|
||||
try {
|
||||
const headers = await getHeaders(this.activeDid);
|
||||
if (
|
||||
window.location.hostname === "localhost" &&
|
||||
!DEFAULT_IMAGE_API_SERVER.includes("localhost")
|
||||
) {
|
||||
console.log(
|
||||
"Using shared image API server, so only users on that server can play with images.",
|
||||
);
|
||||
}
|
||||
const response = await this.axios.delete(
|
||||
DEFAULT_IMAGE_API_SERVER +
|
||||
"/image/" +
|
||||
|
||||
@@ -357,6 +357,14 @@ export default class NewEditProjectView extends Vue {
|
||||
}
|
||||
try {
|
||||
const headers = (await getHeaders(this.activeDid)) as AxiosRequestHeaders;
|
||||
if (
|
||||
window.location.hostname === "localhost" &&
|
||||
!DEFAULT_IMAGE_API_SERVER.includes("localhost")
|
||||
) {
|
||||
console.log(
|
||||
"Using shared image API server, so only users on that server can play with images.",
|
||||
);
|
||||
}
|
||||
const response = await this.axios.delete(
|
||||
DEFAULT_IMAGE_API_SERVER +
|
||||
"/image/" +
|
||||
|
||||
@@ -183,6 +183,14 @@ export default class SharedPhotoView extends Vue {
|
||||
);
|
||||
formData.append("claimType", imageType);
|
||||
|
||||
if (
|
||||
window.location.hostname === "localhost" &&
|
||||
!DEFAULT_IMAGE_API_SERVER.includes("localhost")
|
||||
) {
|
||||
console.log(
|
||||
"Using shared image API server, so only users on that server can play with images.",
|
||||
);
|
||||
}
|
||||
const response = await axios.post(
|
||||
DEFAULT_IMAGE_API_SERVER + "/image",
|
||||
formData,
|
||||
|
||||
@@ -50,6 +50,14 @@ import path from 'path';
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { importUser } from './testUtils';
|
||||
|
||||
/**
|
||||
* Note: by default, this test uses the test image API server.
|
||||
*
|
||||
* If you want to use your own image API server, you can set the
|
||||
* VITE_DEFAULT_IMAGE_API_SERVER environment variable to your server's URL
|
||||
* in the playwright.config-local.ts file.
|
||||
*
|
||||
*/
|
||||
test('Record item given from image-share', async ({ page }) => {
|
||||
|
||||
let randomString = Math.random().toString(36).substring(2, 8);
|
||||
|
||||
@@ -300,7 +300,7 @@ test('Copy contact to clipboard, then import ', async ({ page, context }, testIn
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Running test that copies contact details to clipboard.");
|
||||
// console.log("Running test that copies contact details to clipboard.");
|
||||
await page.getByTestId('copySelectedContactsButtonTop').click();
|
||||
const clipboardText = await page.evaluate(async () => {
|
||||
return navigator.clipboard.readText();
|
||||
|
||||
@@ -33,12 +33,6 @@ export default defineConfig(({ mode }) => {
|
||||
fs: {
|
||||
strict: false
|
||||
},
|
||||
proxy: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ? {
|
||||
'/api': {
|
||||
target: process.env.VITE_DEFAULT_ENDORSER_API_SERVER || 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
},
|
||||
} : undefined,
|
||||
},
|
||||
build: {
|
||||
outDir: isElectron ? "dist-electron" : "dist",
|
||||
|
||||
Reference in New Issue
Block a user