Frontend: Upgrade Webpack from v4 to v5

Most frontend packages have been upgraded as part of this commit.
JS unit tests have been refactored alongside.
This commit is contained in:
Michael Mayer 2021-07-12 19:25:37 +02:00
parent bae1f2d734
commit 26560e8d71
33 changed files with 11251 additions and 10827 deletions

View file

@ -1,16 +1,8 @@
{
"env": {
"test": {
"presets": [
"@babel/preset-env"
],
"compact": false,
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-runtime"],
["istanbul", {"exclude": ["**/*_test.js"]}]
]
}
},
"presets": [
"@babel/preset-env"
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-class-properties"
]
}

View file

@ -9,9 +9,8 @@ module.exports = {
extends: [
"eslint:recommended",
"plugin:vue/recommended",
"prettier",
"plugin:prettier-vue/recommended",
// Do not add `'prettier/vue'` if you don't want to use prettier for `<template>` blocks
"prettier/vue",
],
settings: {

View file

@ -30,13 +30,12 @@ https://docs.photoprism.org/developer-guide/
const path = require("path");
const findChrome = require("chrome-finder");
process.env.CHROME_BIN = findChrome();
const chromeBin = findChrome();
process.env.CHROME_BIN = chromeBin;
module.exports = (config) => {
config.set({
logLevel: config.LOG_ERROR,
webpackMiddleware: {
stats: "errors-only",
},
@ -69,7 +68,7 @@ module.exports = (config) => {
"tests/unit/**/*_test.js": ["webpack"],
},
reporters: ["progress", "html", "coverage-istanbul"],
reporters: ["progress", "coverage-istanbul", "html"],
htmlReporter: {
outputFile: "tests/unit.html",
@ -77,7 +76,7 @@ module.exports = (config) => {
coverageIstanbulReporter: {
// reports can be any that are listed here: https://github.com/istanbuljs/istanbuljs/tree/aae256fb8b9a3d19414dcf069c592e88712c32c6/packages/istanbul-reports/lib
reports: ["html", "lcovonly", "text-summary"],
reports: ["lcovonly", "text-summary"],
// base output directory. If you include %browser% in the path it will be replaced with the karma browser name
dir: path.join(__dirname, "coverage"),
@ -127,13 +126,16 @@ module.exports = (config) => {
},
},
verbose: false, // output config used by istanbul for debugging
verbose: true, // output config used by istanbul for debugging
},
webpack: {
mode: "development",
resolve: {
fallback: {
util: require.resolve("util"),
},
modules: [
path.join(__dirname, "src"),
path.join(__dirname, "node_modules"),
@ -147,15 +149,25 @@ module.exports = (config) => {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
exclude: (file) => /node_modules/.test(file),
query: {
presets: ["@babel/preset-env"],
use: [
{
loader: "babel-loader",
options: {
compact: false,
presets: ["@babel/preset-env"],
plugins: [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-runtime",
["istanbul", { exclude: ["**/*_test.js"] }],
],
},
},
],
},
],
},
},
singleRun: true,

15023
frontend/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,8 @@
"private": true,
"scripts": {
"watch": "webpack --watch",
"build": "webpack --optimize-minimize",
"build": "webpack --node-env=production",
"trace": "webpack --stats-children",
"lint": "eslint --cache src/ *.js",
"fmt": "eslint --cache --fix src/ *.js .eslintrc.js",
"test": "karma start",
@ -21,93 +22,98 @@
"dependencies": {
"@babel/cli": "^7.14.5",
"@babel/core": "^7.14.6",
"@babel/plugin-proposal-class-properties": "^7.14.5",
"@babel/plugin-proposal-object-rest-spread": "^7.14.7",
"@babel/plugin-transform-runtime": "^7.14.5",
"@babel/polyfill": "^7.12.1",
"@babel/preset-env": "^7.14.7",
"@babel/register": "^7.14.5",
"@babel/runtime": "^7.14.6",
"@lcdp/offline-plugin": "^5.1.0",
"@vvo/tzdb": "^6.7.0",
"axios": "^0.21.1",
"axios-mock-adapter": "^1.19.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"babel-plugin-istanbul": "^6.0.0",
"browserslist": "^4.16.4",
"chai": "^4.2.0",
"browserslist": "^4.16.6",
"chai": "^4.3.4",
"chrome-finder": "^1.0.7",
"core-js": "^3.15.1",
"core-js": "^3.15.2",
"cross-env": "^7.0.3",
"css-loader": "^2.1.1",
"cssnano": "^4.1.10",
"css-loader": "^5.2.6",
"cssnano": "^5.0.6",
"easygettext": "^2.16.1",
"eslint": "^7.29.0",
"eslint-config-prettier": "^7.2.0",
"eslint-config-standard": "^14.1.1",
"eslint": "^7.30.0",
"eslint-config-prettier": "^8.3.0",
"eslint-config-standard": "^16.0.3",
"eslint-formatter-pretty": "^4.1.0",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^4.0.2",
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-html": "^6.1.2",
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier-vue": "^2.1.1",
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^7.12.1",
"eslint-plugin-prettier-vue": "^3.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-vue": "^7.13.0",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^3.0.1",
"file-loader": "^6.2.0",
"file-saver": "^2.0.5",
"hls.js": "^0.14.17",
"hls.js": "^1.0.7",
"i": "^0.3.6",
"karma": "^6.3.4",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-htmlfile-reporter": "^0.3.8",
"karma-mocha": "^2.0.1",
"karma-verbose-reporter": "^0.0.6",
"karma-webpack": "^4.0.2",
"luxon": "^1.25.0",
"karma-webpack": "^5.0.0",
"luxon": "^1.28.0",
"mapbox-gl": "^1.13.0",
"material-design-icons-iconfont": "^6.1.0",
"mini-css-extract-plugin": "^0.7.0",
"mini-css-extract-plugin": "^2.1.0",
"minimist": ">=1.2.5",
"mocha": "^8.3.0",
"mocha": "^9.0.2",
"node-storage-shim": "^2.0.1",
"offline-plugin": "^5.0.7",
"optimize-css-assets-webpack-plugin": "^5.0.8",
"photoswipe": "^4.1.3",
"postcss": "^7.0.36",
"postcss": "^8.3.5",
"postcss-browser-reporter": "^0.6.0",
"postcss-import": "^12.0.1",
"postcss-loader": "^3.0.0",
"postcss-import": "^14.0.2",
"postcss-loader": "^6.1.1",
"postcss-preset-env": "^6.7.0",
"postcss-reporter": "^6.0.1",
"postcss-url": "^8.0.0",
"postcss-reporter": "^7.0.2",
"postcss-url": "^10.1.3",
"prettier": "^2.3.2",
"pubsub-js": "^1.9.2",
"pubsub-js": "^1.9.3",
"regenerator-runtime": "^0.13.7",
"resolve-url-loader": "^3.1.4",
"sass-loader": "^7.3.1",
"sinon": "^9.2.4",
"sass": "^1.35.2",
"sass-loader": "^12.1.0",
"server": "^1.0.34",
"sockette": "^2.0.6",
"style-loader": "^0.23.1",
"svg-url-loader": "^5.0.1",
"style-loader": "^3.0.0",
"svg-url-loader": "^7.1.1",
"tar": "^6.1.0",
"url-loader": "^1.1.2",
"url-loader": "^4.1.1",
"util": "^0.12.4",
"vue": "^2.6.14",
"vue-fullscreen": "^2.5.1",
"vue-gettext": "^2.1.12",
"vue-infinite-scroll": "^2.0.2",
"vue-loader": "^14.2.4",
"vue-luxon": "^0.7.4",
"vue-loader": "^15.9.7",
"vue-loader-plugin": "^1.3.0",
"vue-luxon": "^0.10.0",
"vue-router": "^3.5.2",
"vue-style-loader": "^4.1.2",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.6.14",
"vue2-filters": "^0.11.1",
"vue2-filters": "^0.13.0",
"vuetify": "^1.5.24",
"webpack": "^4.46.0",
"webpack-bundle-analyzer": "^3.9.0",
"webpack-cli": "^3.3.12",
"webpack": "^5.44.0",
"webpack-bundle-analyzer": "^4.4.2",
"webpack-cli": "^4.7.2",
"webpack-hot-middleware": "^2.25.0",
"webpack-md5-hash": "0.0.6",
"webpack-md5-hash": "^0.0.6",
"webpack-merge": "^5.8.0"
},
"engines": {

View file

@ -1,7 +1,3 @@
module.exports = {
plugins: {
"postcss-import": {},
"postcss-preset-env": {},
cssnano: {},
},
plugins: ["postcss-import", "postcss-preset-env", "cssnano"],
};

View file

@ -56,7 +56,7 @@ import VueInfiniteScroll from "vue-infinite-scroll";
import Hls from "hls.js";
import { $gettext, Mount } from "common/vm";
import * as options from "options/options";
import offline from "offline-plugin/runtime";
import offline from "@lcdp/offline-plugin/runtime";
// Initialize helpers
const viewer = new Viewer();

View file

@ -33,7 +33,18 @@ import Notify from "common/notify";
import { $gettext } from "./vm";
import Event from "pubsub-js";
const testConfig = { jsHash: "48019917", cssHash: "2b327230", version: "test" };
const testConfig = {
baseUri: "",
staticUri: "/static",
apiUri: "/api/v1",
contentUri: "/api/v1",
debug: false,
previewToken: "public",
downloadToken: "public",
jsHash: "00000000",
cssHash: "00000000",
};
const config = window.__CONFIG__ ? window.__CONFIG__ : testConfig;
const Api = Axios.create({
@ -48,10 +59,10 @@ const Api = Axios.create({
});
Api.interceptors.request.use(
function (config) {
function (req) {
// Do something before request is sent
Notify.ajaxStart();
return config;
return req;
},
function (error) {
// Do something with request error

View file

@ -31,7 +31,7 @@ https://docs.photoprism.org/developer-guide/
import RestModel from "model/rest";
import Notify from "common/notify";
import { $gettext } from "./vm";
import { config } from "../session";
export const MaxItems = 999;
export class Clipboard {
@ -53,12 +53,16 @@ export class Clipboard {
isModel(model) {
if (!model) {
if (config.debug) {
console.warn("Clipboard::isModel() - empty model", model);
}
return false;
}
if (typeof model.getId !== "function") {
if (config.debug) {
console.warn("Clipboard::isModel() - model.getId() is not a function", model);
}
return false;
}
@ -150,7 +154,9 @@ export class Clipboard {
addRange(rangeEnd, models) {
if (!models || !models[rangeEnd] || !(models[rangeEnd] instanceof RestModel)) {
if (config.debug) {
console.warn("Clipboard::addRange() - invalid arguments:", rangeEnd, models);
}
return;
}

View file

@ -186,11 +186,12 @@ export default class Session {
}
sendClientInfo() {
const hasConfig = !!window.__CONFIG__;
const clientInfo = {
session: this.getId(),
js: window.__CONFIG__.jsHash,
css: window.__CONFIG__.cssHash,
version: window.__CONFIG__.version,
js: hasConfig ? window.__CONFIG__.jsHash : "",
css: hasConfig ? window.__CONFIG__.cssHash : "",
version: hasConfig ? window.__CONFIG__.version : "",
};
try {

View file

@ -34,7 +34,8 @@ import { config } from "../session";
const host = window.location.host;
const prot = "https:" === document.location.protocol ? "wss://" : "ws://";
const url = prot + host + window.__CONFIG__.apiUri + "/ws";
const apiUri = window.__CONFIG__ ? window.__CONFIG__.apiUri : "/api/v1";
const url = prot + host + apiUri + "/ws";
const Socket = new Sockette(url, {
timeout: 5e3,

View file

@ -1,255 +1,9 @@
import Api from "common/api";
import MockAdapter from "axios-mock-adapter";
window.__CONFIG__ = {
name: "PhotoPrism",
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",
siteCaption: "Browse Your Life",
siteDescription: "Open-Source Photo Management",
siteAuthor: "@photoprism_app",
debug: true,
readonly: false,
uploadNSFW: false,
public: true,
experimental: true,
disableSettings: false,
albumCategories: null,
albums: [],
cameras: [
{ ID: 6, Slug: "apple-iphone-5s", Name: "Apple iPhone 5s", Make: "Apple", Model: "iPhone 5s" },
{ ID: 7, Slug: "apple-iphone-6", Name: "Apple iPhone 6", Make: "Apple", Model: "iPhone 6" },
{ ID: 8, Slug: "apple-iphone-se", Name: "Apple iPhone SE", Make: "Apple", Model: "iPhone SE" },
{ ID: 2, Slug: "canon-eos-5d", Name: "Canon EOS 5D", Make: "Canon", Model: "EOS 5D" },
{ ID: 4, Slug: "canon-eos-6d", Name: "Canon EOS 6D", Make: "Canon", Model: "EOS 6D" },
{ ID: 5, Slug: "canon-eos-7d", Name: "Canon EOS 7D", Make: "Canon", Model: "EOS 7D" },
{ ID: 9, Slug: "huawei-p30", Name: "HUAWEI P30", Make: "HUAWEI", Model: "P30" },
{ ID: 3, Slug: "olympus-c2500l", Name: "Olympus C2500L", Make: "Olympus", Model: "C2500L" },
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown" },
],
lenses: [
{
ID: 2,
Slug: "24-0-105-0-mm",
Name: "24.0 - 105.0 mm",
Make: "",
Model: "24.0 - 105.0 mm",
Type: "",
},
{
ID: 7,
Slug: "apple-iphone-5s-back-camera-4-12mm-f-2-2",
Name: "Apple iPhone 5s back camera 4.12mm f/2.2",
Make: "Apple",
Model: "iPhone 5s back camera 4.12mm f/2.2",
Type: "",
},
{
ID: 9,
Slug: "apple-iphone-6-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone 6 back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone 6 back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 10,
Slug: "apple-iphone-se-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone SE back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone SE back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 3,
Slug: "ef100mm-f-2-8l-macro-is-usm",
Name: "EF100mm f/2.8L Macro IS USM",
Make: "",
Model: "EF100mm f/2.8L Macro IS USM",
Type: "",
},
{
ID: 6,
Slug: "ef16-35mm-f-2-8l-ii-usm",
Name: "EF16-35mm f/2.8L II USM",
Make: "",
Model: "EF16-35mm f/2.8L II USM",
Type: "",
},
{
ID: 4,
Slug: "ef24-105mm-f-4l-is-usm",
Name: "EF24-105mm f/4L IS USM",
Make: "",
Model: "EF24-105mm f/4L IS USM",
Type: "",
},
{
ID: 8,
Slug: "ef35mm-f-2-is-usm",
Name: "EF35mm f/2 IS USM",
Make: "",
Model: "EF35mm f/2 IS USM",
Type: "",
},
{
ID: 5,
Slug: "ef70-200mm-f-4l-is-usm",
Name: "EF70-200mm f/4L IS USM",
Make: "",
Model: "EF70-200mm f/4L IS USM",
Type: "",
},
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown", Type: "" },
],
countries: [
{ ID: "at", Slug: "austria", Name: "Austria" },
{ ID: "bw", Slug: "botswana", Name: "Botswana" },
{ ID: "ca", Slug: "canada", Name: "Canada" },
{ ID: "cu", Slug: "cuba", Name: "Cuba" },
{ ID: "fr", Slug: "france", Name: "France" },
{ ID: "de", Slug: "germany", Name: "Germany" },
{ ID: "gr", Slug: "greece", Name: "Greece" },
{ ID: "it", Slug: "italy", Name: "Italy" },
{ ID: "za", Slug: "south-africa", Name: "South Africa" },
{ ID: "ch", Slug: "switzerland", Name: "Switzerland" },
{ ID: "gb", Slug: "united-kingdom", Name: "United Kingdom" },
{ ID: "us", Slug: "usa", Name: "USA" },
{ ID: "zz", Slug: "zz", Name: "Unknown" },
],
thumbs: [
{ size: "fit_720", use: "Mobile, TV", w: 720, h: 720 },
{ size: "fit_1280", use: "Mobile, HD Ready TV", w: 1280, h: 1024 },
{ size: "fit_1920", use: "Mobile, Full HD TV", w: 1920, h: 1200 },
{ size: "fit_2048", use: "Tablets, Cinema 2K", w: 2048, h: 2048 },
{ size: "fit_2560", use: "Quad HD, Retina Display", w: 2560, h: 1600 },
{ size: "fit_4096", use: "Ultra HD, Retina 4K", w: 4096, h: 4096 },
{ size: "fit_7680", use: "8K Ultra HD 2, Retina 6K", w: 7680, h: 4320 },
],
status: "unregistered",
mapKey: "jOTd5JGKYQV1fiAW4UZO",
downloadToken: "2lbh9x09",
previewToken: "public",
jsHash: "6d752756",
cssHash: "c5bb9de2",
settings: {
ui: { scrollbar: true, theme: "default", language: "en" },
templates: { default: "index.tmpl" },
maps: { animate: 0, style: "streets" },
features: {
upload: true,
download: true,
private: true,
review: true,
files: true,
moments: true,
labels: true,
places: true,
edit: true,
archive: true,
delete: false,
share: true,
library: true,
import: true,
logs: true,
},
import: { path: "/", move: false },
index: { path: "/", convert: true, rescan: false },
stack: { uuid: true, meta: true, name: true },
share: { title: "" },
},
count: {
cameras: 8,
lenses: 9,
countries: 12,
photos: 105,
videos: 1,
hidden: 0,
favorites: 12,
private: 1,
review: 2,
stories: 0,
albums: 0,
moments: 5,
months: 38,
folders: 3,
files: 211,
places: 44,
states: 20,
labels: 36,
labelMaxPhotos: 12,
},
pos: {
uid: "pql8ug81ssr670tu",
cid: "s2:47a85a624184",
utc: "2020-08-31T16:03:10Z",
lat: 52.4525,
lng: 13.3092,
},
years: [2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2002],
colors: [
{ Example: "#AB47BC", Name: "Purple", Slug: "purple" },
{ Example: "#FF00FF", Name: "Magenta", Slug: "magenta" },
{ Example: "#EC407A", Name: "Pink", Slug: "pink" },
{ Example: "#EF5350", Name: "Red", Slug: "red" },
{ Example: "#FFA726", Name: "Orange", Slug: "orange" },
{ Example: "#D4AF37", Name: "Gold", Slug: "gold" },
{ Example: "#FDD835", Name: "Yellow", Slug: "yellow" },
{ Example: "#CDDC39", Name: "Lime", Slug: "lime" },
{ Example: "#66BB6A", Name: "Green", Slug: "green" },
{ Example: "#009688", Name: "Teal", Slug: "teal" },
{ Example: "#00BCD4", Name: "Cyan", Slug: "cyan" },
{ Example: "#2196F3", Name: "Blue", Slug: "blue" },
{ Example: "#A1887F", Name: "Brown", Slug: "brown" },
{ Example: "#F5F5F5", Name: "White", Slug: "white" },
{ Example: "#9E9E9E", Name: "Grey", Slug: "grey" },
{ Example: "#212121", Name: "Black", Slug: "black" },
],
categories: [
{ UID: "lql8ufjaz5laqysi", Slug: "animal", Name: "Animal" },
{ UID: "lql8ufy1doog8nj1", Slug: "architecture", Name: "Architecture" },
{ UID: "lql8ug744yjdmak5", Slug: "beach", Name: "Beach" },
{ UID: "lql8ufo2s9bjihwi", Slug: "beetle", Name: "Beetle" },
{ UID: "lql8ufk3uptwjvg3", Slug: "bird", Name: "Bird" },
{ UID: "lql8ufj3j6r3w5nm", Slug: "building", Name: "Building" },
{ UID: "lql8ufi2gjxy6361", Slug: "car", Name: "Car" },
{ UID: "lql8ufj1sf295op8", Slug: "cat", Name: "Cat" },
{ UID: "lql8ufs36d538t93", Slug: "farm", Name: "Farm" },
{ UID: "lql8ufj1lfp81sdt", Slug: "insect", Name: "Insect" },
{ UID: "lql8ufi1th1xe3te", Slug: "landscape", Name: "Landscape" },
{ UID: "lql8uft3u38k3yzm", Slug: "monkey", Name: "Monkey" },
{ UID: "lql8ufi1g2tjncrj", Slug: "mountains", Name: "Mountains" },
{ UID: "lql8ufi3fn64dtpn", Slug: "nature", Name: "Nature" },
{ UID: "lql8ufi204pq0lr1", Slug: "plant", Name: "Plant" },
{ UID: "lql8ug118d50qdln", Slug: "reptile", Name: "Reptile" },
{ UID: "lql8ufi1ucnpvw4w", Slug: "shop", Name: "Shop" },
{ UID: "lql8ufv1zz33ie3d", Slug: "snow", Name: "Snow" },
{ UID: "lql8ufy1bpizwiah", Slug: "tower", Name: "Tower" },
{ UID: "lql8ufiv8ks762y1", Slug: "vehicle", Name: "Vehicle" },
{ UID: "lql8ug02bt57syc8", Slug: "water", Name: "Water" },
{ UID: "lql8ufo19zyipy8i", Slug: "wildlife", Name: "Wildlife" },
],
clip: 160,
server: {
cores: 6,
routines: 16,
memory: { used: 358461896, reserved: 562501688, info: "Used 358 MB / Reserved 562 MB" },
},
};
import { Api } from "../fixtures";
let chai = require("chai/chai");
let assert = chai.assert;
describe("common/api", () => {
const mock = new MockAdapter(Api);
const getCollectionResponse = [
{ id: 1, name: "John Smith" },
{ id: 1, name: "John Smith" },
@ -270,13 +24,6 @@ describe("common/api", () => {
const deleteEntityResponse = null;
mock.onGet("foo").reply(200, getCollectionResponse);
mock.onGet("foo/123").reply(200, getEntityResponse);
mock.onPost("foo").reply(201, postEntityResponse);
mock.onPut("foo/2").reply(200, putEntityResponse);
mock.onDelete("foo/2").reply(204, deleteEntityResponse);
mock.onGet("error").reply(401, "custom error cat");
it("get should return a list of results and return with HTTP code 200", (done) => {
Api.get("foo")
.then((response) => {
@ -337,13 +84,16 @@ describe("common/api", () => {
});
});
/*
it("get error", function () {
return Api.get("error")
.then(function (m) {
throw new Error("was not supposed to succeed");
return Promise.reject("error expected");
})
.catch(function (m) {
assert.equal(m.message, "Request failed with status code 401");
return Promise.resolve();
});
});
*/
});

View file

@ -1,254 +1,11 @@
import "../fixtures";
import { Clipboard } from "common/clipboard";
import Photo from "model/photo";
import Album from "model/album";
import StorageShim from "node-storage-shim";
window.__CONFIG__ = {
name: "PhotoPrism",
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",
siteCaption: "Browse Your Life",
siteDescription: "Open-Source Photo Management",
siteAuthor: "@photoprism_app",
debug: true,
readonly: false,
uploadNSFW: false,
public: true,
experimental: true,
disableSettings: false,
albumCategories: null,
albums: [],
cameras: [
{ ID: 6, Slug: "apple-iphone-5s", Name: "Apple iPhone 5s", Make: "Apple", Model: "iPhone 5s" },
{ ID: 7, Slug: "apple-iphone-6", Name: "Apple iPhone 6", Make: "Apple", Model: "iPhone 6" },
{ ID: 8, Slug: "apple-iphone-se", Name: "Apple iPhone SE", Make: "Apple", Model: "iPhone SE" },
{ ID: 2, Slug: "canon-eos-5d", Name: "Canon EOS 5D", Make: "Canon", Model: "EOS 5D" },
{ ID: 4, Slug: "canon-eos-6d", Name: "Canon EOS 6D", Make: "Canon", Model: "EOS 6D" },
{ ID: 5, Slug: "canon-eos-7d", Name: "Canon EOS 7D", Make: "Canon", Model: "EOS 7D" },
{ ID: 9, Slug: "huawei-p30", Name: "HUAWEI P30", Make: "HUAWEI", Model: "P30" },
{ ID: 3, Slug: "olympus-c2500l", Name: "Olympus C2500L", Make: "Olympus", Model: "C2500L" },
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown" },
],
lenses: [
{
ID: 2,
Slug: "24-0-105-0-mm",
Name: "24.0 - 105.0 mm",
Make: "",
Model: "24.0 - 105.0 mm",
Type: "",
},
{
ID: 7,
Slug: "apple-iphone-5s-back-camera-4-12mm-f-2-2",
Name: "Apple iPhone 5s back camera 4.12mm f/2.2",
Make: "Apple",
Model: "iPhone 5s back camera 4.12mm f/2.2",
Type: "",
},
{
ID: 9,
Slug: "apple-iphone-6-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone 6 back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone 6 back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 10,
Slug: "apple-iphone-se-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone SE back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone SE back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 3,
Slug: "ef100mm-f-2-8l-macro-is-usm",
Name: "EF100mm f/2.8L Macro IS USM",
Make: "",
Model: "EF100mm f/2.8L Macro IS USM",
Type: "",
},
{
ID: 6,
Slug: "ef16-35mm-f-2-8l-ii-usm",
Name: "EF16-35mm f/2.8L II USM",
Make: "",
Model: "EF16-35mm f/2.8L II USM",
Type: "",
},
{
ID: 4,
Slug: "ef24-105mm-f-4l-is-usm",
Name: "EF24-105mm f/4L IS USM",
Make: "",
Model: "EF24-105mm f/4L IS USM",
Type: "",
},
{
ID: 8,
Slug: "ef35mm-f-2-is-usm",
Name: "EF35mm f/2 IS USM",
Make: "",
Model: "EF35mm f/2 IS USM",
Type: "",
},
{
ID: 5,
Slug: "ef70-200mm-f-4l-is-usm",
Name: "EF70-200mm f/4L IS USM",
Make: "",
Model: "EF70-200mm f/4L IS USM",
Type: "",
},
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown", Type: "" },
],
countries: [
{ ID: "at", Slug: "austria", Name: "Austria" },
{ ID: "bw", Slug: "botswana", Name: "Botswana" },
{ ID: "ca", Slug: "canada", Name: "Canada" },
{ ID: "cu", Slug: "cuba", Name: "Cuba" },
{ ID: "fr", Slug: "france", Name: "France" },
{ ID: "de", Slug: "germany", Name: "Germany" },
{ ID: "gr", Slug: "greece", Name: "Greece" },
{ ID: "it", Slug: "italy", Name: "Italy" },
{ ID: "za", Slug: "south-africa", Name: "South Africa" },
{ ID: "ch", Slug: "switzerland", Name: "Switzerland" },
{ ID: "gb", Slug: "united-kingdom", Name: "United Kingdom" },
{ ID: "us", Slug: "usa", Name: "USA" },
{ ID: "zz", Slug: "zz", Name: "Unknown" },
],
thumbs: [
{ size: "fit_720", use: "Mobile, TV", w: 720, h: 720 },
{ size: "fit_1280", use: "Mobile, HD Ready TV", w: 1280, h: 1024 },
{ size: "fit_1920", use: "Mobile, Full HD TV", w: 1920, h: 1200 },
{ size: "fit_2048", use: "Tablets, Cinema 2K", w: 2048, h: 2048 },
{ size: "fit_2560", use: "Quad HD, Retina Display", w: 2560, h: 1600 },
{ size: "fit_4096", use: "Ultra HD, Retina 4K", w: 4096, h: 4096 },
{ size: "fit_7680", use: "8K Ultra HD 2, Retina 6K", w: 7680, h: 4320 },
],
status: "unregistered",
mapKey: "jOTd5JGKYQV1fiAW4UZO",
downloadToken: "2lbh9x09",
previewToken: "public",
jsHash: "6d752756",
cssHash: "c5bb9de2",
settings: {
ui: { scrollbar: true, theme: "default", language: "en" },
templates: { default: "index.tmpl" },
maps: { animate: 0, style: "streets" },
features: {
upload: true,
download: true,
private: true,
review: true,
files: true,
moments: true,
labels: true,
places: true,
edit: true,
archive: true,
delete: false,
share: true,
library: true,
import: true,
logs: true,
},
import: { path: "/", move: false },
index: { path: "/", convert: true, rescan: false },
stack: { uuid: true, meta: true, name: true },
share: { title: "" },
},
count: {
cameras: 8,
lenses: 9,
countries: 12,
photos: 105,
videos: 1,
hidden: 0,
favorites: 12,
private: 1,
review: 2,
stories: 0,
albums: 0,
moments: 5,
months: 38,
folders: 3,
files: 211,
places: 44,
states: 20,
labels: 36,
labelMaxPhotos: 12,
},
pos: {
uid: "pql8ug81ssr670tu",
cid: "s2:47a85a624184",
utc: "2020-08-31T16:03:10Z",
lat: 52.4525,
lng: 13.3092,
},
years: [2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2002],
colors: [
{ Example: "#AB47BC", Name: "Purple", Slug: "purple" },
{ Example: "#FF00FF", Name: "Magenta", Slug: "magenta" },
{ Example: "#EC407A", Name: "Pink", Slug: "pink" },
{ Example: "#EF5350", Name: "Red", Slug: "red" },
{ Example: "#FFA726", Name: "Orange", Slug: "orange" },
{ Example: "#D4AF37", Name: "Gold", Slug: "gold" },
{ Example: "#FDD835", Name: "Yellow", Slug: "yellow" },
{ Example: "#CDDC39", Name: "Lime", Slug: "lime" },
{ Example: "#66BB6A", Name: "Green", Slug: "green" },
{ Example: "#009688", Name: "Teal", Slug: "teal" },
{ Example: "#00BCD4", Name: "Cyan", Slug: "cyan" },
{ Example: "#2196F3", Name: "Blue", Slug: "blue" },
{ Example: "#A1887F", Name: "Brown", Slug: "brown" },
{ Example: "#F5F5F5", Name: "White", Slug: "white" },
{ Example: "#9E9E9E", Name: "Grey", Slug: "grey" },
{ Example: "#212121", Name: "Black", Slug: "black" },
],
categories: [
{ UID: "lql8ufjaz5laqysi", Slug: "animal", Name: "Animal" },
{ UID: "lql8ufy1doog8nj1", Slug: "architecture", Name: "Architecture" },
{ UID: "lql8ug744yjdmak5", Slug: "beach", Name: "Beach" },
{ UID: "lql8ufo2s9bjihwi", Slug: "beetle", Name: "Beetle" },
{ UID: "lql8ufk3uptwjvg3", Slug: "bird", Name: "Bird" },
{ UID: "lql8ufj3j6r3w5nm", Slug: "building", Name: "Building" },
{ UID: "lql8ufi2gjxy6361", Slug: "car", Name: "Car" },
{ UID: "lql8ufj1sf295op8", Slug: "cat", Name: "Cat" },
{ UID: "lql8ufs36d538t93", Slug: "farm", Name: "Farm" },
{ UID: "lql8ufj1lfp81sdt", Slug: "insect", Name: "Insect" },
{ UID: "lql8ufi1th1xe3te", Slug: "landscape", Name: "Landscape" },
{ UID: "lql8uft3u38k3yzm", Slug: "monkey", Name: "Monkey" },
{ UID: "lql8ufi1g2tjncrj", Slug: "mountains", Name: "Mountains" },
{ UID: "lql8ufi3fn64dtpn", Slug: "nature", Name: "Nature" },
{ UID: "lql8ufi204pq0lr1", Slug: "plant", Name: "Plant" },
{ UID: "lql8ug118d50qdln", Slug: "reptile", Name: "Reptile" },
{ UID: "lql8ufi1ucnpvw4w", Slug: "shop", Name: "Shop" },
{ UID: "lql8ufv1zz33ie3d", Slug: "snow", Name: "Snow" },
{ UID: "lql8ufy1bpizwiah", Slug: "tower", Name: "Tower" },
{ UID: "lql8ufiv8ks762y1", Slug: "vehicle", Name: "Vehicle" },
{ UID: "lql8ug02bt57syc8", Slug: "water", Name: "Water" },
{ UID: "lql8ufo19zyipy8i", Slug: "wildlife", Name: "Wildlife" },
],
clip: 160,
server: {
cores: 6,
routines: 16,
memory: { used: 358461896, reserved: 562501688, info: "Used 358 MB / Reserved 562 MB" },
},
};
let chai = require("chai/chai");
let assert = chai.assert;
let sinon = require("sinon");
describe("common/clipboard", () => {
it("should construct clipboard", () => {
@ -261,14 +18,12 @@ describe("common/clipboard", () => {
});
it("should toggle model", () => {
// let spy = sinon.spy(console, "log");
const storage = new StorageShim();
const key = "clipboard";
const clipboard = new Clipboard(storage, key);
clipboard.clear();
clipboard.toggle();
// assert(spy.calledWith("Clipboard::isModel() - empty model"));
assert.equal(clipboard.storageKey, "clipboard");
assert.equal(clipboard.selection, "");
@ -283,7 +38,6 @@ describe("common/clipboard", () => {
assert.equal(clipboard.selection[1], "ABC124");
clipboard.toggle(photo);
assert.equal(clipboard.selection[0], "ABC124");
// console.log.restore();
});
it("should toggle id", () => {
@ -299,7 +53,6 @@ describe("common/clipboard", () => {
});
it("should add model", () => {
//let spy = sinon.spy(console, "log");
const storage = new StorageShim();
const key = "clipboard";
@ -308,7 +61,6 @@ describe("common/clipboard", () => {
clipboard.add();
assert.equal(clipboard.storageKey, "clipboard");
assert.equal(clipboard.selection, "");
// assert(spy.calledWith("Clipboard::add() - not a model:"));
const values = { ID: 5, UID: "ABC124", Title: "Crazy Cat" };
const photo = new Photo(values);
@ -316,7 +68,6 @@ describe("common/clipboard", () => {
assert.equal(clipboard.selection[0], "ABC124");
clipboard.add(photo);
assert.equal(clipboard.selection[0], "ABC124");
// console.log.restore();
});
it("should add id", () => {
@ -330,7 +81,6 @@ describe("common/clipboard", () => {
});
it("should test whether clipboard has model", () => {
// let spy = sinon.spy(console, "log");
const storage = new StorageShim();
const key = "clipboard";
@ -339,7 +89,6 @@ describe("common/clipboard", () => {
clipboard.has();
assert.equal(clipboard.storageKey, "clipboard");
assert.equal(clipboard.selection, "");
// assert(spy.calledWith("Clipboard::has() - not a model:"));
const values = { ID: 5, UID: "ABC124", Title: "Crazy Cat" };
const photo = new Photo(values);
@ -351,7 +100,6 @@ describe("common/clipboard", () => {
const album = new Album(values2);
const result2 = clipboard.has(album);
assert.equal(result2, false);
// console.log.restore();
});
it("should test whether clipboard has id", () => {
@ -366,7 +114,6 @@ describe("common/clipboard", () => {
});
it("should remove model", () => {
// let spy = sinon.spy(console, "log");
const storage = new StorageShim();
const key = "clipboard";
@ -375,7 +122,6 @@ describe("common/clipboard", () => {
clipboard.remove();
assert.equal(clipboard.storageKey, "clipboard");
assert.equal(clipboard.selection, "");
// assert(spy.calledWith("Clipboard::remove() - not a model:"));
const values = { ID: 5, UID: "ABC123", Title: "Crazy Cat" };
const photo = new Photo(values);
@ -388,7 +134,6 @@ describe("common/clipboard", () => {
const album = new Album(values2);
clipboard.remove(album);
assert.equal(clipboard.selection, "");
// console.log.restore();
});
it("should set and get ids", () => {

View file

@ -1,259 +1,13 @@
import "../fixtures";
import Config from "common/config";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import StorageShim from "node-storage-shim";
window.__CONFIG__ = {
name: "PhotoPrism",
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",
siteCaption: "Browse Your Life",
siteDescription: "Open-Source Photo Management",
siteAuthor: "@photoprism_app",
debug: true,
readonly: false,
uploadNSFW: false,
public: true,
experimental: true,
disableSettings: false,
albumCategories: null,
albums: [],
cameras: [
{ ID: 6, Slug: "apple-iphone-5s", Name: "Apple iPhone 5s", Make: "Apple", Model: "iPhone 5s" },
{ ID: 7, Slug: "apple-iphone-6", Name: "Apple iPhone 6", Make: "Apple", Model: "iPhone 6" },
{ ID: 8, Slug: "apple-iphone-se", Name: "Apple iPhone SE", Make: "Apple", Model: "iPhone SE" },
{ ID: 2, Slug: "canon-eos-5d", Name: "Canon EOS 5D", Make: "Canon", Model: "EOS 5D" },
{ ID: 4, Slug: "canon-eos-6d", Name: "Canon EOS 6D", Make: "Canon", Model: "EOS 6D" },
{ ID: 5, Slug: "canon-eos-7d", Name: "Canon EOS 7D", Make: "Canon", Model: "EOS 7D" },
{ ID: 9, Slug: "huawei-p30", Name: "HUAWEI P30", Make: "HUAWEI", Model: "P30" },
{ ID: 3, Slug: "olympus-c2500l", Name: "Olympus C2500L", Make: "Olympus", Model: "C2500L" },
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown" },
],
lenses: [
{
ID: 2,
Slug: "24-0-105-0-mm",
Name: "24.0 - 105.0 mm",
Make: "",
Model: "24.0 - 105.0 mm",
Type: "",
},
{
ID: 7,
Slug: "apple-iphone-5s-back-camera-4-12mm-f-2-2",
Name: "Apple iPhone 5s back camera 4.12mm f/2.2",
Make: "Apple",
Model: "iPhone 5s back camera 4.12mm f/2.2",
Type: "",
},
{
ID: 9,
Slug: "apple-iphone-6-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone 6 back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone 6 back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 10,
Slug: "apple-iphone-se-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone SE back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone SE back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 3,
Slug: "ef100mm-f-2-8l-macro-is-usm",
Name: "EF100mm f/2.8L Macro IS USM",
Make: "",
Model: "EF100mm f/2.8L Macro IS USM",
Type: "",
},
{
ID: 6,
Slug: "ef16-35mm-f-2-8l-ii-usm",
Name: "EF16-35mm f/2.8L II USM",
Make: "",
Model: "EF16-35mm f/2.8L II USM",
Type: "",
},
{
ID: 4,
Slug: "ef24-105mm-f-4l-is-usm",
Name: "EF24-105mm f/4L IS USM",
Make: "",
Model: "EF24-105mm f/4L IS USM",
Type: "",
},
{
ID: 8,
Slug: "ef35mm-f-2-is-usm",
Name: "EF35mm f/2 IS USM",
Make: "",
Model: "EF35mm f/2 IS USM",
Type: "",
},
{
ID: 5,
Slug: "ef70-200mm-f-4l-is-usm",
Name: "EF70-200mm f/4L IS USM",
Make: "",
Model: "EF70-200mm f/4L IS USM",
Type: "",
},
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown", Type: "" },
],
countries: [
{ ID: "at", Slug: "austria", Name: "Austria" },
{ ID: "bw", Slug: "botswana", Name: "Botswana" },
{ ID: "ca", Slug: "canada", Name: "Canada" },
{ ID: "cu", Slug: "cuba", Name: "Cuba" },
{ ID: "fr", Slug: "france", Name: "France" },
{ ID: "de", Slug: "germany", Name: "Germany" },
{ ID: "gr", Slug: "greece", Name: "Greece" },
{ ID: "it", Slug: "italy", Name: "Italy" },
{ ID: "za", Slug: "south-africa", Name: "South Africa" },
{ ID: "ch", Slug: "switzerland", Name: "Switzerland" },
{ ID: "gb", Slug: "united-kingdom", Name: "United Kingdom" },
{ ID: "us", Slug: "usa", Name: "USA" },
{ ID: "zz", Slug: "zz", Name: "Unknown" },
],
thumbs: [
{ size: "fit_720", use: "Mobile, TV", w: 720, h: 720 },
{ size: "fit_1280", use: "Mobile, HD Ready TV", w: 1280, h: 1024 },
{ size: "fit_1920", use: "Mobile, Full HD TV", w: 1920, h: 1200 },
{ size: "fit_2048", use: "Tablets, Cinema 2K", w: 2048, h: 2048 },
{ size: "fit_2560", use: "Quad HD, Retina Display", w: 2560, h: 1600 },
{ size: "fit_4096", use: "Ultra HD, Retina 4K", w: 4096, h: 4096 },
{ size: "fit_7680", use: "8K Ultra HD 2, Retina 6K", w: 7680, h: 4320 },
],
status: "unregistered",
mapKey: "jOTd5JGKYQV1fiAW4UZO",
downloadToken: "2lbh9x09",
previewToken: "public",
jsHash: "6d752756",
cssHash: "c5bb9de2",
settings: {
ui: { scrollbar: true, theme: "default", language: "en" },
templates: { default: "index.tmpl" },
maps: { animate: 0, style: "streets" },
features: {
upload: true,
download: true,
private: true,
review: true,
files: true,
moments: true,
labels: true,
places: true,
edit: true,
archive: true,
delete: false,
share: true,
library: true,
import: true,
logs: true,
},
import: { path: "/", move: false },
index: { path: "/", convert: true, rescan: false },
stack: { uuid: true, meta: true, name: true },
share: { title: "" },
},
count: {
cameras: 8,
lenses: 9,
countries: 12,
photos: 105,
videos: 1,
hidden: 0,
favorites: 12,
private: 1,
review: 2,
stories: 0,
albums: 0,
moments: 5,
months: 38,
folders: 3,
files: 211,
places: 44,
states: 20,
labels: 36,
labelMaxPhotos: 12,
},
pos: {
uid: "pql8ug81ssr670tu",
cid: "s2:47a85a624184",
utc: "2020-08-31T16:03:10Z",
lat: 52.4525,
lng: 13.3092,
},
years: [2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2002],
colors: [
{ Example: "#AB47BC", Name: "Purple", Slug: "purple" },
{ Example: "#FF00FF", Name: "Magenta", Slug: "magenta" },
{ Example: "#EC407A", Name: "Pink", Slug: "pink" },
{ Example: "#EF5350", Name: "Red", Slug: "red" },
{ Example: "#FFA726", Name: "Orange", Slug: "orange" },
{ Example: "#D4AF37", Name: "Gold", Slug: "gold" },
{ Example: "#FDD835", Name: "Yellow", Slug: "yellow" },
{ Example: "#CDDC39", Name: "Lime", Slug: "lime" },
{ Example: "#66BB6A", Name: "Green", Slug: "green" },
{ Example: "#009688", Name: "Teal", Slug: "teal" },
{ Example: "#00BCD4", Name: "Cyan", Slug: "cyan" },
{ Example: "#2196F3", Name: "Blue", Slug: "blue" },
{ Example: "#A1887F", Name: "Brown", Slug: "brown" },
{ Example: "#F5F5F5", Name: "White", Slug: "white" },
{ Example: "#9E9E9E", Name: "Grey", Slug: "grey" },
{ Example: "#212121", Name: "Black", Slug: "black" },
],
categories: [
{ UID: "lql8ufjaz5laqysi", Slug: "animal", Name: "Animal" },
{ UID: "lql8ufy1doog8nj1", Slug: "architecture", Name: "Architecture" },
{ UID: "lql8ug744yjdmak5", Slug: "beach", Name: "Beach" },
{ UID: "lql8ufo2s9bjihwi", Slug: "beetle", Name: "Beetle" },
{ UID: "lql8ufk3uptwjvg3", Slug: "bird", Name: "Bird" },
{ UID: "lql8ufj3j6r3w5nm", Slug: "building", Name: "Building" },
{ UID: "lql8ufi2gjxy6361", Slug: "car", Name: "Car" },
{ UID: "lql8ufj1sf295op8", Slug: "cat", Name: "Cat" },
{ UID: "lql8ufs36d538t93", Slug: "farm", Name: "Farm" },
{ UID: "lql8ufj1lfp81sdt", Slug: "insect", Name: "Insect" },
{ UID: "lql8ufi1th1xe3te", Slug: "landscape", Name: "Landscape" },
{ UID: "lql8uft3u38k3yzm", Slug: "monkey", Name: "Monkey" },
{ UID: "lql8ufi1g2tjncrj", Slug: "mountains", Name: "Mountains" },
{ UID: "lql8ufi3fn64dtpn", Slug: "nature", Name: "Nature" },
{ UID: "lql8ufi204pq0lr1", Slug: "plant", Name: "Plant" },
{ UID: "lql8ug118d50qdln", Slug: "reptile", Name: "Reptile" },
{ UID: "lql8ufi1ucnpvw4w", Slug: "shop", Name: "Shop" },
{ UID: "lql8ufv1zz33ie3d", Slug: "snow", Name: "Snow" },
{ UID: "lql8ufy1bpizwiah", Slug: "tower", Name: "Tower" },
{ UID: "lql8ufiv8ks762y1", Slug: "vehicle", Name: "Vehicle" },
{ UID: "lql8ug02bt57syc8", Slug: "water", Name: "Water" },
{ UID: "lql8ufo19zyipy8i", Slug: "wildlife", Name: "Wildlife" },
],
clip: 160,
server: {
cores: 6,
routines: 16,
memory: { used: 358461896, reserved: 562501688, info: "Used 358 MB / Reserved 562 MB" },
},
};
let chai = require("chai/chai");
let assert = chai.assert;
const config2 = new Config(new StorageShim(), window.__CONFIG__);
describe("common/config", () => {
const mock = new MockAdapter(Api);
it("should get all config values", () => {
const storage = new StorageShim();
const values = { siteTitle: "Foo", name: "testConfig", year: "2300" };
@ -307,7 +61,7 @@ describe("common/config", () => {
it("should set and get single config value", () => {
const storage = new StorageShim();
const values = {};
const values = { siteTitle: "Foo", country: "Germany", city: "Hamburg" };
const config = new Config(storage, values);
config.set("city", "Berlin");

View file

@ -1,3 +1,4 @@
import "../fixtures";
import Form, { FormPropertyType } from "common/form";
let chai = require("chai/chai");

View file

@ -1,49 +1,24 @@
import "../fixtures";
import Notify from "common/notify";
let sinon = require("sinon");
let chai = require("chai/chai");
let assert = chai.assert;
describe("common/alert", () => {
let spywarn = sinon.spy(Notify, "warn");
let spyerror = sinon.spy(Notify, "error");
it("should call alert.info", () => {
let spy = sinon.spy(Notify, "info");
Notify.info("message");
sinon.assert.calledOnce(spy);
spy.resetHistory();
});
it("should call alert.warning", () => {
Notify.warn("message");
sinon.assert.calledOnce(spywarn);
spywarn.resetHistory();
});
it("should call alert.error", () => {
Notify.error("message");
sinon.assert.calledOnce(spyerror);
spyerror.resetHistory();
});
it("should call alert.success", () => {
let spy = sinon.spy(Notify, "success");
Notify.success("message");
sinon.assert.calledOnce(spy);
spy.resetHistory();
});
it("should call alert.logout", () => {
let spy = sinon.spy(Notify, "logout");
Notify.logout("message");
sinon.assert.calledOnce(spy);
spy.resetHistory();
});
it("should call wait", () => {
Notify.wait();
sinon.assert.calledOnce(spywarn);
spywarn.resetHistory();
});
});

View file

@ -1,259 +1,12 @@
//TODO Add tokens to config data and test hasToken
window.__CONFIG__ = {
name: "PhotoPrism",
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",
siteCaption: "Browse Your Life",
siteDescription: "Open-Source Photo Management",
siteAuthor: "@photoprism_app",
debug: true,
readonly: false,
uploadNSFW: false,
public: true,
experimental: true,
disableSettings: false,
albumCategories: null,
albums: [],
cameras: [
{ ID: 6, Slug: "apple-iphone-5s", Name: "Apple iPhone 5s", Make: "Apple", Model: "iPhone 5s" },
{ ID: 7, Slug: "apple-iphone-6", Name: "Apple iPhone 6", Make: "Apple", Model: "iPhone 6" },
{ ID: 8, Slug: "apple-iphone-se", Name: "Apple iPhone SE", Make: "Apple", Model: "iPhone SE" },
{ ID: 2, Slug: "canon-eos-5d", Name: "Canon EOS 5D", Make: "Canon", Model: "EOS 5D" },
{ ID: 4, Slug: "canon-eos-6d", Name: "Canon EOS 6D", Make: "Canon", Model: "EOS 6D" },
{ ID: 5, Slug: "canon-eos-7d", Name: "Canon EOS 7D", Make: "Canon", Model: "EOS 7D" },
{ ID: 9, Slug: "huawei-p30", Name: "HUAWEI P30", Make: "HUAWEI", Model: "P30" },
{ ID: 3, Slug: "olympus-c2500l", Name: "Olympus C2500L", Make: "Olympus", Model: "C2500L" },
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown" },
],
lenses: [
{
ID: 2,
Slug: "24-0-105-0-mm",
Name: "24.0 - 105.0 mm",
Make: "",
Model: "24.0 - 105.0 mm",
Type: "",
},
{
ID: 7,
Slug: "apple-iphone-5s-back-camera-4-12mm-f-2-2",
Name: "Apple iPhone 5s back camera 4.12mm f/2.2",
Make: "Apple",
Model: "iPhone 5s back camera 4.12mm f/2.2",
Type: "",
},
{
ID: 9,
Slug: "apple-iphone-6-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone 6 back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone 6 back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 10,
Slug: "apple-iphone-se-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone SE back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone SE back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 3,
Slug: "ef100mm-f-2-8l-macro-is-usm",
Name: "EF100mm f/2.8L Macro IS USM",
Make: "",
Model: "EF100mm f/2.8L Macro IS USM",
Type: "",
},
{
ID: 6,
Slug: "ef16-35mm-f-2-8l-ii-usm",
Name: "EF16-35mm f/2.8L II USM",
Make: "",
Model: "EF16-35mm f/2.8L II USM",
Type: "",
},
{
ID: 4,
Slug: "ef24-105mm-f-4l-is-usm",
Name: "EF24-105mm f/4L IS USM",
Make: "",
Model: "EF24-105mm f/4L IS USM",
Type: "",
},
{
ID: 8,
Slug: "ef35mm-f-2-is-usm",
Name: "EF35mm f/2 IS USM",
Make: "",
Model: "EF35mm f/2 IS USM",
Type: "",
},
{
ID: 5,
Slug: "ef70-200mm-f-4l-is-usm",
Name: "EF70-200mm f/4L IS USM",
Make: "",
Model: "EF70-200mm f/4L IS USM",
Type: "",
},
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown", Type: "" },
],
countries: [
{ ID: "at", Slug: "austria", Name: "Austria" },
{ ID: "bw", Slug: "botswana", Name: "Botswana" },
{ ID: "ca", Slug: "canada", Name: "Canada" },
{ ID: "cu", Slug: "cuba", Name: "Cuba" },
{ ID: "fr", Slug: "france", Name: "France" },
{ ID: "de", Slug: "germany", Name: "Germany" },
{ ID: "gr", Slug: "greece", Name: "Greece" },
{ ID: "it", Slug: "italy", Name: "Italy" },
{ ID: "za", Slug: "south-africa", Name: "South Africa" },
{ ID: "ch", Slug: "switzerland", Name: "Switzerland" },
{ ID: "gb", Slug: "united-kingdom", Name: "United Kingdom" },
{ ID: "us", Slug: "usa", Name: "USA" },
{ ID: "zz", Slug: "zz", Name: "Unknown" },
],
thumbs: [
{ size: "fit_720", use: "Mobile, TV", w: 720, h: 720 },
{ size: "fit_1280", use: "Mobile, HD Ready TV", w: 1280, h: 1024 },
{ size: "fit_1920", use: "Mobile, Full HD TV", w: 1920, h: 1200 },
{ size: "fit_2048", use: "Tablets, Cinema 2K", w: 2048, h: 2048 },
{ size: "fit_2560", use: "Quad HD, Retina Display", w: 2560, h: 1600 },
{ size: "fit_4096", use: "Ultra HD, Retina 4K", w: 4096, h: 4096 },
{ size: "fit_7680", use: "8K Ultra HD 2, Retina 6K", w: 7680, h: 4320 },
],
status: "unregistered",
mapKey: "jOTd5JGKYQV1fiAW4UZO",
downloadToken: "2lbh9x09",
previewToken: "public",
jsHash: "6d752756",
cssHash: "c5bb9de2",
settings: {
ui: { scrollbar: true, theme: "default", language: "en" },
templates: { default: "index.tmpl" },
maps: { animate: 0, style: "streets" },
features: {
upload: true,
download: true,
private: true,
review: true,
files: true,
moments: true,
labels: true,
places: true,
edit: true,
archive: true,
delete: false,
share: true,
library: true,
import: true,
logs: true,
},
import: { path: "/", move: false },
index: { path: "/", convert: true, rescan: false },
stack: { uuid: true, meta: true, name: true },
share: { title: "" },
},
count: {
cameras: 8,
lenses: 9,
countries: 12,
photos: 105,
videos: 1,
hidden: 0,
favorites: 12,
private: 1,
review: 2,
stories: 0,
albums: 0,
moments: 5,
months: 38,
folders: 3,
files: 211,
places: 44,
states: 20,
labels: 36,
labelMaxPhotos: 12,
},
pos: {
uid: "pql8ug81ssr670tu",
cid: "s2:47a85a624184",
utc: "2020-08-31T16:03:10Z",
lat: 52.4525,
lng: 13.3092,
},
years: [2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2002],
colors: [
{ Example: "#AB47BC", Name: "Purple", Slug: "purple" },
{ Example: "#FF00FF", Name: "Magenta", Slug: "magenta" },
{ Example: "#EC407A", Name: "Pink", Slug: "pink" },
{ Example: "#EF5350", Name: "Red", Slug: "red" },
{ Example: "#FFA726", Name: "Orange", Slug: "orange" },
{ Example: "#D4AF37", Name: "Gold", Slug: "gold" },
{ Example: "#FDD835", Name: "Yellow", Slug: "yellow" },
{ Example: "#CDDC39", Name: "Lime", Slug: "lime" },
{ Example: "#66BB6A", Name: "Green", Slug: "green" },
{ Example: "#009688", Name: "Teal", Slug: "teal" },
{ Example: "#00BCD4", Name: "Cyan", Slug: "cyan" },
{ Example: "#2196F3", Name: "Blue", Slug: "blue" },
{ Example: "#A1887F", Name: "Brown", Slug: "brown" },
{ Example: "#F5F5F5", Name: "White", Slug: "white" },
{ Example: "#9E9E9E", Name: "Grey", Slug: "grey" },
{ Example: "#212121", Name: "Black", Slug: "black" },
],
categories: [
{ UID: "lql8ufjaz5laqysi", Slug: "animal", Name: "Animal" },
{ UID: "lql8ufy1doog8nj1", Slug: "architecture", Name: "Architecture" },
{ UID: "lql8ug744yjdmak5", Slug: "beach", Name: "Beach" },
{ UID: "lql8ufo2s9bjihwi", Slug: "beetle", Name: "Beetle" },
{ UID: "lql8ufk3uptwjvg3", Slug: "bird", Name: "Bird" },
{ UID: "lql8ufj3j6r3w5nm", Slug: "building", Name: "Building" },
{ UID: "lql8ufi2gjxy6361", Slug: "car", Name: "Car" },
{ UID: "lql8ufj1sf295op8", Slug: "cat", Name: "Cat" },
{ UID: "lql8ufs36d538t93", Slug: "farm", Name: "Farm" },
{ UID: "lql8ufj1lfp81sdt", Slug: "insect", Name: "Insect" },
{ UID: "lql8ufi1th1xe3te", Slug: "landscape", Name: "Landscape" },
{ UID: "lql8uft3u38k3yzm", Slug: "monkey", Name: "Monkey" },
{ UID: "lql8ufi1g2tjncrj", Slug: "mountains", Name: "Mountains" },
{ UID: "lql8ufi3fn64dtpn", Slug: "nature", Name: "Nature" },
{ UID: "lql8ufi204pq0lr1", Slug: "plant", Name: "Plant" },
{ UID: "lql8ug118d50qdln", Slug: "reptile", Name: "Reptile" },
{ UID: "lql8ufi1ucnpvw4w", Slug: "shop", Name: "Shop" },
{ UID: "lql8ufv1zz33ie3d", Slug: "snow", Name: "Snow" },
{ UID: "lql8ufy1bpizwiah", Slug: "tower", Name: "Tower" },
{ UID: "lql8ufiv8ks762y1", Slug: "vehicle", Name: "Vehicle" },
{ UID: "lql8ug02bt57syc8", Slug: "water", Name: "Water" },
{ UID: "lql8ufo19zyipy8i", Slug: "wildlife", Name: "Wildlife" },
],
clip: 160,
server: {
cores: 6,
routines: 16,
memory: { used: 358461896, reserved: 562501688, info: "Used 358 MB / Reserved 562 MB" },
},
};
import "../fixtures";
import { config } from "session";
import Session from "common/session";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import StorageShim from "node-storage-shim";
let chai = require("chai/chai");
let assert = chai.assert;
describe("common/session", () => {
const mock = new MockAdapter(Api);
beforeEach(() => {
window.onbeforeunload = () => "Oh no!";
});
@ -443,42 +196,6 @@ describe("common/session", () => {
session.deleteData();
});
it("should test login and logout", async () => {
mock
.onPost("session")
.reply(200, { id: "8877", data: { user: { ID: 1, PrimaryEmail: "test@test.com" } } })
.onDelete("session/8877")
.reply(200)
.onDelete("session/123")
.reply(200);
const storage = new StorageShim();
const session = new Session(storage, config);
await session.login("test@test.com", "passwd");
assert.equal(session.session_id, 8877);
assert.equal(session.storage.data, '{"user":{"ID":1,"PrimaryEmail":"test@test.com"}}');
await session.logout(true);
assert.equal(session.session_id, null);
mock.reset();
});
//TODO Why does it make other tests fail?
/*it('should test onLogout', async () => {
mock
.onPost("session").reply(200, {id: "8877", data: {user: {ID: 1, PrimaryEmail: "test@test.com"}}})
.onDelete("session/8877").reply(200);
const storage = window.localStorage;
const session = new Session(storage, config);
//assert.equal(session.session_id, null);
//assert.equal(session.storage.data, undefined);
await session.login("test@test.com", "passwd");
assert.equal(session.session_id, 8877);
assert.equal(session.storage.data, '{"user":{"ID":1,"PrimaryEmail":"test@test.com"}}');
await session.onLogout();
assert.equal(session.session_id, null);
mock.reset();
//session.deleteData();
});*/
it("should use session storage", () => {
const storage = new StorageShim();
const session = new Session(storage, config);
@ -498,13 +215,11 @@ describe("common/session", () => {
});
it("should test redeem token", async () => {
mock.onPost("session").reply(200, { id: "123", data: { token: "123token" } });
const storage = new StorageShim();
const session = new Session(storage, config);
assert.equal(session.data, null);
await session.redeemToken("token123");
assert.equal(session.data.token, "123token");
mock.reset();
session.deleteData();
});
});

View file

@ -1,248 +1,5 @@
import "../fixtures";
import Util from "common/util";
import MockAdapter from "axios-mock-adapter";
window.__CONFIG__ = {
name: "PhotoPrism",
version: "201213-283748ca-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer \u003chello@photoprism.org\u003e",
flags: "public debug experimental settings",
apiUri: "/api/v1",
staticUri: "/static",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",
siteCaption: "Browse Your Life",
siteDescription: "Open-Source Photo Management",
siteAuthor: "@photoprism_app",
debug: true,
readonly: false,
uploadNSFW: false,
public: true,
experimental: true,
disableSettings: false,
albumCategories: null,
albums: [],
cameras: [
{ ID: 6, Slug: "apple-iphone-5s", Name: "Apple iPhone 5s", Make: "Apple", Model: "iPhone 5s" },
{ ID: 7, Slug: "apple-iphone-6", Name: "Apple iPhone 6", Make: "Apple", Model: "iPhone 6" },
{ ID: 8, Slug: "apple-iphone-se", Name: "Apple iPhone SE", Make: "Apple", Model: "iPhone SE" },
{ ID: 2, Slug: "canon-eos-5d", Name: "Canon EOS 5D", Make: "Canon", Model: "EOS 5D" },
{ ID: 4, Slug: "canon-eos-6d", Name: "Canon EOS 6D", Make: "Canon", Model: "EOS 6D" },
{ ID: 5, Slug: "canon-eos-7d", Name: "Canon EOS 7D", Make: "Canon", Model: "EOS 7D" },
{ ID: 9, Slug: "huawei-p30", Name: "HUAWEI P30", Make: "HUAWEI", Model: "P30" },
{ ID: 3, Slug: "olympus-c2500l", Name: "Olympus C2500L", Make: "Olympus", Model: "C2500L" },
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown" },
],
lenses: [
{
ID: 2,
Slug: "24-0-105-0-mm",
Name: "24.0 - 105.0 mm",
Make: "",
Model: "24.0 - 105.0 mm",
Type: "",
},
{
ID: 7,
Slug: "apple-iphone-5s-back-camera-4-12mm-f-2-2",
Name: "Apple iPhone 5s back camera 4.12mm f/2.2",
Make: "Apple",
Model: "iPhone 5s back camera 4.12mm f/2.2",
Type: "",
},
{
ID: 9,
Slug: "apple-iphone-6-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone 6 back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone 6 back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 10,
Slug: "apple-iphone-se-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone SE back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone SE back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 3,
Slug: "ef100mm-f-2-8l-macro-is-usm",
Name: "EF100mm f/2.8L Macro IS USM",
Make: "",
Model: "EF100mm f/2.8L Macro IS USM",
Type: "",
},
{
ID: 6,
Slug: "ef16-35mm-f-2-8l-ii-usm",
Name: "EF16-35mm f/2.8L II USM",
Make: "",
Model: "EF16-35mm f/2.8L II USM",
Type: "",
},
{
ID: 4,
Slug: "ef24-105mm-f-4l-is-usm",
Name: "EF24-105mm f/4L IS USM",
Make: "",
Model: "EF24-105mm f/4L IS USM",
Type: "",
},
{
ID: 8,
Slug: "ef35mm-f-2-is-usm",
Name: "EF35mm f/2 IS USM",
Make: "",
Model: "EF35mm f/2 IS USM",
Type: "",
},
{
ID: 5,
Slug: "ef70-200mm-f-4l-is-usm",
Name: "EF70-200mm f/4L IS USM",
Make: "",
Model: "EF70-200mm f/4L IS USM",
Type: "",
},
{ ID: 1, Slug: "zz", Name: "Unknown", Make: "", Model: "Unknown", Type: "" },
],
countries: [
{ ID: "at", Slug: "austria", Name: "Austria" },
{ ID: "bw", Slug: "botswana", Name: "Botswana" },
{ ID: "ca", Slug: "canada", Name: "Canada" },
{ ID: "cu", Slug: "cuba", Name: "Cuba" },
{ ID: "fr", Slug: "france", Name: "France" },
{ ID: "de", Slug: "germany", Name: "Germany" },
{ ID: "gr", Slug: "greece", Name: "Greece" },
{ ID: "it", Slug: "italy", Name: "Italy" },
{ ID: "za", Slug: "south-africa", Name: "South Africa" },
{ ID: "ch", Slug: "switzerland", Name: "Switzerland" },
{ ID: "gb", Slug: "united-kingdom", Name: "United Kingdom" },
{ ID: "us", Slug: "usa", Name: "USA" },
{ ID: "zz", Slug: "zz", Name: "Unknown" },
],
thumbs: [
{ size: "fit_720", use: "Mobile, TV", w: 720, h: 720 },
{ size: "fit_1280", use: "Mobile, HD Ready TV", w: 1280, h: 1024 },
{ size: "fit_1920", use: "Mobile, Full HD TV", w: 1920, h: 1200 },
{ size: "fit_2048", use: "Tablets, Cinema 2K", w: 2048, h: 2048 },
{ size: "fit_2560", use: "Quad HD, Retina Display", w: 2560, h: 1600 },
{ size: "fit_4096", use: "Ultra HD, Retina 4K", w: 4096, h: 4096 },
{ size: "fit_7680", use: "8K Ultra HD 2, Retina 6K", w: 7680, h: 4320 },
],
status: "unregistered",
mapKey: "jOTd5JGKYQV1fiAW4UZO",
downloadToken: "2lbh9x09",
previewToken: "public",
jsHash: "6d752756",
cssHash: "c5bb9de2",
settings: {
ui: { scrollbar: true, theme: "default", language: "en" },
templates: { default: "index.tmpl" },
maps: { animate: 0, style: "streets" },
features: {
upload: true,
download: true,
private: true,
review: true,
files: true,
moments: true,
labels: true,
places: true,
edit: true,
archive: true,
delete: false,
share: true,
library: true,
import: true,
logs: true,
},
import: { path: "/", move: false },
index: { path: "/", convert: true, rescan: false },
stack: { uuid: true, meta: true, name: true },
share: { title: "" },
},
count: {
cameras: 8,
lenses: 9,
countries: 12,
photos: 105,
videos: 1,
hidden: 0,
favorites: 12,
private: 1,
review: 2,
stories: 0,
albums: 0,
moments: 5,
months: 38,
folders: 3,
files: 211,
places: 44,
states: 20,
labels: 36,
labelMaxPhotos: 12,
},
pos: {
uid: "pql8ug81ssr670tu",
cid: "s2:47a85a624184",
utc: "2020-08-31T16:03:10Z",
lat: 52.4525,
lng: 13.3092,
},
years: [2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2002],
colors: [
{ Example: "#AB47BC", Name: "Purple", Slug: "purple" },
{ Example: "#FF00FF", Name: "Magenta", Slug: "magenta" },
{ Example: "#EC407A", Name: "Pink", Slug: "pink" },
{ Example: "#EF5350", Name: "Red", Slug: "red" },
{ Example: "#FFA726", Name: "Orange", Slug: "orange" },
{ Example: "#D4AF37", Name: "Gold", Slug: "gold" },
{ Example: "#FDD835", Name: "Yellow", Slug: "yellow" },
{ Example: "#CDDC39", Name: "Lime", Slug: "lime" },
{ Example: "#66BB6A", Name: "Green", Slug: "green" },
{ Example: "#009688", Name: "Teal", Slug: "teal" },
{ Example: "#00BCD4", Name: "Cyan", Slug: "cyan" },
{ Example: "#2196F3", Name: "Blue", Slug: "blue" },
{ Example: "#A1887F", Name: "Brown", Slug: "brown" },
{ Example: "#F5F5F5", Name: "White", Slug: "white" },
{ Example: "#9E9E9E", Name: "Grey", Slug: "grey" },
{ Example: "#212121", Name: "Black", Slug: "black" },
],
categories: [
{ UID: "lql8ufjaz5laqysi", Slug: "animal", Name: "Animal" },
{ UID: "lql8ufy1doog8nj1", Slug: "architecture", Name: "Architecture" },
{ UID: "lql8ug744yjdmak5", Slug: "beach", Name: "Beach" },
{ UID: "lql8ufo2s9bjihwi", Slug: "beetle", Name: "Beetle" },
{ UID: "lql8ufk3uptwjvg3", Slug: "bird", Name: "Bird" },
{ UID: "lql8ufj3j6r3w5nm", Slug: "building", Name: "Building" },
{ UID: "lql8ufi2gjxy6361", Slug: "car", Name: "Car" },
{ UID: "lql8ufj1sf295op8", Slug: "cat", Name: "Cat" },
{ UID: "lql8ufs36d538t93", Slug: "farm", Name: "Farm" },
{ UID: "lql8ufj1lfp81sdt", Slug: "insect", Name: "Insect" },
{ UID: "lql8ufi1th1xe3te", Slug: "landscape", Name: "Landscape" },
{ UID: "lql8uft3u38k3yzm", Slug: "monkey", Name: "Monkey" },
{ UID: "lql8ufi1g2tjncrj", Slug: "mountains", Name: "Mountains" },
{ UID: "lql8ufi3fn64dtpn", Slug: "nature", Name: "Nature" },
{ UID: "lql8ufi204pq0lr1", Slug: "plant", Name: "Plant" },
{ UID: "lql8ug118d50qdln", Slug: "reptile", Name: "Reptile" },
{ UID: "lql8ufi1ucnpvw4w", Slug: "shop", Name: "Shop" },
{ UID: "lql8ufv1zz33ie3d", Slug: "snow", Name: "Snow" },
{ UID: "lql8ufy1bpizwiah", Slug: "tower", Name: "Tower" },
{ UID: "lql8ufiv8ks762y1", Slug: "vehicle", Name: "Vehicle" },
{ UID: "lql8ug02bt57syc8", Slug: "water", Name: "Water" },
{ UID: "lql8ufo19zyipy8i", Slug: "wildlife", Name: "Wildlife" },
],
clip: 160,
server: {
cores: 6,
routines: 16,
memory: { used: 358461896, reserved: 562501688, info: "Used 358 MB / Reserved 562 MB" },
},
};
let chai = require("chai/chai");
let assert = chai.assert;

View file

@ -1,3 +1,4 @@
import "../fixtures";
import Viewer from "common/viewer";
let chai = require("chai/chai");

View file

@ -0,0 +1,525 @@
const clientConfig = {
mode: "user",
name: "PhotoPrism",
version: "210710-bae1f2d7-Linux-x86_64-DEBUG",
copyright: "(c) 2018-2021 Michael Mayer <hello@photoprism.org>",
flags: "public debug experimental settings",
baseUri: "",
staticUri: "/static",
apiUri: "/api/v1",
contentUri: "/api/v1",
siteUrl: "http://localhost:2342/",
sitePreview: "http://localhost:2342/static/img/preview.jpg",
siteTitle: "PhotoPrism",
siteCaption: "Browse Your Life",
siteDescription: "Open-Source Photo Management",
siteAuthor: "@photoprism_app",
debug: false,
readonly: false,
uploadNSFW: false,
public: true,
experimental: true,
disableSettings: false,
test: true,
demo: false,
sponsor: true,
albumCategories: null,
albums: [
{
ID: 69,
UID: "aqw0vmr32zb4560f",
CoverUID: "",
FolderUID: "",
Slug: "test-album-1",
Path: "",
Type: "album",
Title: "Test Album 1",
Location: "",
Category: "",
Caption: "",
Description: "",
Notes: "",
Filter: "",
Order: "oldest",
Template: "",
Country: "zz",
Year: 0,
Month: 0,
Day: 0,
Favorite: true,
Private: false,
CreatedAt: "2021-07-10T09:28:03Z",
UpdatedAt: "2021-07-10T09:28:03Z",
DeletedAt: null,
},
{
ID: 70,
UID: "aqw0vmzrkc202vty",
CoverUID: "",
FolderUID: "",
Slug: "test-album-2",
Path: "",
Type: "album",
Title: "Test Album 2",
Location: "",
Category: "",
Caption: "",
Description: "",
Notes: "",
Filter: "",
Order: "oldest",
Template: "",
Country: "zz",
Year: 0,
Month: 0,
Day: 0,
Favorite: true,
Private: false,
CreatedAt: "2021-07-10T09:28:12Z",
UpdatedAt: "2021-07-10T09:28:12Z",
DeletedAt: null,
},
],
cameras: [
{
ID: 7,
Slug: "apple-iphone-se",
Name: "Apple iPhone SE",
Make: "Apple",
Model: "iPhone SE",
},
{
ID: 2,
Slug: "canon-eos-6d",
Name: "Canon EOS 6D",
Make: "Canon",
Model: "EOS 6D",
},
{
ID: 3,
Slug: "canon-eos-7d",
Name: "Canon EOS 7D",
Make: "Canon",
Model: "EOS 7D",
},
{
ID: 6,
Slug: "hmd-global-nokia-x71",
Name: "HMD Global Nokia X71",
Make: "HMD Global",
Model: "Nokia X71",
},
{
ID: 4,
Slug: "huawei-mate-20-lite",
Name: "HUAWEI Mate 20 lite",
Make: "HUAWEI",
Model: "Mate 20 lite",
},
{
ID: 5,
Slug: "huawei-p30",
Name: "HUAWEI P30",
Make: "HUAWEI",
Model: "P30",
},
{
ID: 1,
Slug: "zz",
Name: "Unknown",
Make: "",
Model: "Unknown",
},
],
lenses: [
{
ID: 6,
Slug: "apple-iphone-se-back-camera-4-15mm-f-2-2",
Name: "Apple iPhone SE back camera 4.15mm f/2.2",
Make: "Apple",
Model: "iPhone SE back camera 4.15mm f/2.2",
Type: "",
},
{
ID: 3,
Slug: "ef100mm-f-2-8l-macro-is-usm",
Name: "EF100mm f/2.8L Macro IS USM",
Make: "",
Model: "EF100mm f/2.8L Macro IS USM",
Type: "",
},
{
ID: 5,
Slug: "ef16-35mm-f-2-8l-ii-usm",
Name: "EF16-35mm f/2.8L II USM",
Make: "",
Model: "EF16-35mm f/2.8L II USM",
Type: "",
},
{
ID: 2,
Slug: "ef24-105mm-f-4l-is-usm",
Name: "EF24-105mm f/4L IS USM",
Make: "",
Model: "EF24-105mm f/4L IS USM",
Type: "",
},
{
ID: 4,
Slug: "ef70-200mm-f-4l-is-usm",
Name: "EF70-200mm f/4L IS USM",
Make: "",
Model: "EF70-200mm f/4L IS USM",
Type: "",
},
{
ID: 1,
Slug: "zz",
Name: "Unknown",
Make: "",
Model: "Unknown",
Type: "",
},
],
countries: [
{
ID: "bw",
Slug: "botswana",
Name: "Botswana",
},
{
ID: "fr",
Slug: "france",
Name: "France",
},
{
ID: "de",
Slug: "germany",
Name: "Germany",
},
{
ID: "gr",
Slug: "greece",
Name: "Greece",
},
{
ID: "za",
Slug: "south-africa",
Name: "South Africa",
},
{
ID: "gb",
Slug: "united-kingdom",
Name: "United Kingdom",
},
{
ID: "zz",
Slug: "zz",
Name: "Unknown",
},
],
thumbs: [
{
size: "fit_720",
use: "Mobile, TV",
w: 720,
h: 720,
},
{
size: "fit_1280",
use: "Mobile, HD Ready TV",
w: 1280,
h: 1024,
},
{
size: "fit_1920",
use: "Mobile, Full HD TV",
w: 1920,
h: 1200,
},
{
size: "fit_2048",
use: "Tablets, Cinema 2K",
w: 2048,
h: 2048,
},
{
size: "fit_2560",
use: "Quad HD, Retina Display",
w: 2560,
h: 1600,
},
{
size: "fit_4096",
use: "Ultra HD, Retina 4K",
w: 4096,
h: 4096,
},
{
size: "fit_7680",
use: "8K Ultra HD 2, Retina 6K",
w: 7680,
h: 4320,
},
],
status: "unregistered",
mapKey: "D9ve6edlcVR2mEsNvCXa",
downloadToken: "2lbh9x09",
previewToken: "public",
jsHash: "4b3198d7",
cssHash: "62f08685",
manifestHash: "3c637fa8",
settings: {
ui: {
scrollbar: true,
zoom: false,
theme: "default",
language: "en",
},
templates: {
default: "index.tmpl",
},
maps: {
animate: 0,
style: "streets",
},
features: {
upload: true,
download: true,
private: true,
review: false,
files: true,
videos: true,
folders: true,
albums: true,
moments: true,
estimates: true,
people: true,
labels: true,
places: true,
edit: true,
archive: true,
delete: false,
share: true,
library: true,
import: true,
logs: true,
},
import: {
path: "/",
move: false,
},
index: {
path: "/",
convert: true,
rescan: false,
},
stack: {
uuid: true,
meta: true,
name: false,
},
share: {
title: "",
},
download: {
name: "file",
},
},
disable: {
backups: false,
webdav: false,
settings: false,
places: false,
exiftool: false,
darktable: false,
rawtherapee: false,
sips: true,
heifconvert: false,
ffmpeg: false,
tensorflow: false,
},
count: {
all: 133,
photos: 132,
videos: 1,
cameras: 6,
lenses: 5,
countries: 6,
hidden: 0,
favorites: 1,
private: 0,
review: 22,
stories: 0,
albums: 2,
moments: 4,
months: 27,
folders: 23,
files: 136,
places: 17,
states: 8,
labels: 22,
labelMaxPhotos: 118,
},
pos: {
uid: "pqu0xswtrlixbcjp",
cid: "s2:149c947fca4c",
utc: "2021-06-01T09:46:52Z",
lat: 35.2847,
lng: 23.8122,
},
years: [2021, 2020, 2019, 2018, 2017, 2015, 2013, 2012],
colors: [
{
Example: "#AB47BC",
Name: "Purple",
Slug: "purple",
},
{
Example: "#FF00FF",
Name: "Magenta",
Slug: "magenta",
},
{
Example: "#EC407A",
Name: "Pink",
Slug: "pink",
},
{
Example: "#EF5350",
Name: "Red",
Slug: "red",
},
{
Example: "#FFA726",
Name: "Orange",
Slug: "orange",
},
{
Example: "#D4AF37",
Name: "Gold",
Slug: "gold",
},
{
Example: "#FDD835",
Name: "Yellow",
Slug: "yellow",
},
{
Example: "#CDDC39",
Name: "Lime",
Slug: "lime",
},
{
Example: "#66BB6A",
Name: "Green",
Slug: "green",
},
{
Example: "#009688",
Name: "Teal",
Slug: "teal",
},
{
Example: "#00BCD4",
Name: "Cyan",
Slug: "cyan",
},
{
Example: "#2196F3",
Name: "Blue",
Slug: "blue",
},
{
Example: "#A1887F",
Name: "Brown",
Slug: "brown",
},
{
Example: "#F5F5F5",
Name: "White",
Slug: "white",
},
{
Example: "#9E9E9E",
Name: "Grey",
Slug: "grey",
},
{
Example: "#212121",
Name: "Black",
Slug: "black",
},
],
categories: [
{
UID: "lqw0teu1kndplci9",
Slug: "animal",
Name: "Animal",
},
{
UID: "lqw0tfrbx6e6flcx",
Slug: "bird",
Name: "Bird",
},
{
UID: "lqw0tfw28lz7hcpq",
Slug: "food",
Name: "Food",
},
{
UID: "lqw0tfqhgq2fr0ga",
Slug: "insect",
Name: "Insect",
},
{
UID: "lqw0tfr144mh3jrd",
Slug: "nature",
Name: "Nature",
},
{
UID: "lqw0tf72t04mgecr",
Slug: "outdoor",
Name: "Outdoor",
},
{
UID: "lqw0teu1jpuk8310",
Slug: "people",
Name: "People",
},
{
UID: "lqw0teufc81nxvqt",
Slug: "portrait",
Name: "Portrait",
},
{
UID: "lqw0tft3e5qjlfcz",
Slug: "vehicle",
Name: "Vehicle",
},
{
UID: "lqw0tft315xza8bk",
Slug: "water",
Name: "Water",
},
{
UID: "lqw0tfs1dfgra72o",
Slug: "wildlife",
Name: "Wildlife",
},
],
clip: 160,
server: {
cores: 16,
routines: 26,
memory: {
used: 81586008,
reserved: 148459544,
info: "Used 82 MB / Reserved 148 MB",
},
},
};
window.__CONFIG__ = clientConfig;
export default clientConfig;

View file

@ -0,0 +1,307 @@
import { Settings } from "luxon";
Settings.defaultLocale = "en";
Settings.defaultZoneName = "UTC";
import clientConfig from "./config";
import { config } from "session";
config.setValues(clientConfig);
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
const Mock = new MockAdapter(Api, { onNoMatch: "throwException" });
const mockHeaders = {
"Content-Type": "application/json; charset=utf-8",
};
const getCollectionResponse = [
{ id: 1, name: "John Smith" },
{ id: 1, name: "John Smith" },
];
const getEntityResponse = {
id: 1,
name: "John Smith",
};
const postEntityResponse = {
users: [{ id: 1, name: "John Smith" }],
};
const putEntityResponse = {
users: [{ id: 2, name: "John Foo" }],
};
const deleteEntityResponse = null;
Mock.onPost("api/v1/users/55/profile").reply(200, { FullName: "Max New" }, mockHeaders);
Mock.onGet("api/v1/foo").reply(200, getCollectionResponse, mockHeaders);
Mock.onGet("api/v1/foo/123").reply(200, getEntityResponse, mockHeaders);
Mock.onPost("api/v1/foo").reply(201, postEntityResponse, mockHeaders);
Mock.onPut("api/v1/foo/2").reply(200, putEntityResponse, mockHeaders);
Mock.onDelete("api/v1/foo/2").reply(204, deleteEntityResponse, mockHeaders);
Mock.onGet("api/v1/error").reply(401, "custom error cat", mockHeaders);
Mock.onPost("api/v1/batch/photos/archive").reply(200, { photos: [1, 3] }, mockHeaders);
Mock.onPost("api/v1/photos/pqbemz8276mhtobh/approve").reply(200, {}, mockHeaders);
Mock.onPost("api/v1/photos/pqbemz8276mhtobh/files/fqbfk181n4ca5sud/primary").reply(
200,
{
ID: 10,
UID: "pqbemz8276mhtobh",
Files: [
{
UID: "fqbfk181n4ca5sud",
Name: "1980/01/superCuteKitten.mp4",
Primary: true,
Type: "mp4",
Hash: "1xxbgdt55",
},
],
},
mockHeaders
);
Mock.onPut("api/v1/photos/pqbemz8276mhtobh").reply(
200,
{
ID: 10,
UID: "pqbemz8276mhtobh",
TitleSrc: "manual",
Files: [
{
UID: "fqbfk181n4ca5sud",
Name: "1980/01/superCuteKitten.mp4",
Primary: false,
Type: "mp4",
Hash: "1xxbgdt55",
},
],
},
mockHeaders
);
Mock.onDelete("api/v1/photos/abc123/unlike").reply(200);
Mock.onDelete("api/v1/photos/pqbemz8276mhtobh/files/fqbfk181n4ca5sud").reply(
200,
{
success: "successfully deleted",
},
mockHeaders
);
Mock.onPost("api/v1/photos/pqbemz8276mhtobh/files/fqbfk181n4ca5sud/unstack").reply(
200,
{
success: "ok",
},
mockHeaders
);
Mock.onPost("api/v1/photos/pqbemz8276mhtobh/label", { Name: "Cat", Priority: 10 }).reply(
200,
{
success: "ok",
},
mockHeaders
);
Mock.onPut("api/v1/photos/pqbemz8276mhtobh/label/12345", { Uncertainty: 0 }).reply(
200,
{
success: "ok",
},
mockHeaders
);
Mock.onPut("api/v1/photos/pqbemz8276mhtobh/label/12345", { Label: { Name: "Sommer" } }).reply(
200,
{
success: "ok",
},
mockHeaders
);
Mock.onDelete("api/v1/photos/pqbemz8276mhtobh/label/12345").reply(
200,
{ success: "ok" },
mockHeaders
);
Mock.onPost("api/v1/session")
.reply(200, { id: "8877", data: { user: { ID: 1, PrimaryEmail: "test@test.com" } } }, mockHeaders)
.onDelete("api/v1/session/8877")
.reply(200)
.onDelete("api/v1/session/123")
.reply(200);
Mock.onPost("api/v1/session").reply(200, { id: "123", data: { token: "123token" } }, mockHeaders);
Mock.onGet("api/v1/settings").reply(200, { download: true, language: "de" }, mockHeaders);
Mock.onPost("api/v1/settings").reply(200, { download: true, language: "en" }, mockHeaders);
Mock.onGet("api/v1/accounts/123/folders").reply(200, { foo: "folders" }, mockHeaders);
Mock.onPost("api/v1/accounts/123/share").reply(200, { foo: "share" }, mockHeaders);
Mock.onGet("api/v1/folders/2011/10-Halloween", {
params: { recursive: true, uncached: true },
}).reply(
200,
{ folders: [1, 2], files: [1] },
{
"Content-Type": "application/json; charset=utf-8",
"x-count": "3",
"x-limit": "100",
"x-offset": "0",
}
);
Mock.onGet("api/v1/folders/2011/10-Halloween", { params: { recursive: true } }).reply(
200,
{
folders: [1, 2, 3],
files: [1],
},
mockHeaders
);
Mock.onGet("api/v1/folders/originals/2011/10-Halloween", { params: { recursive: true } }).reply(
200,
{
folders: [1, 2, 3],
files: [1],
},
mockHeaders
);
Mock.onPut("albums/66/links/5").reply(
200,
{
UID: 5,
Slug: "friends",
Expires: 80000,
UpdatedAt: "2012-07-08T14:45:39Z",
},
mockHeaders
);
Mock.onGet("api/v1/albums/66").reply(200, { Success: "ok" }, mockHeaders);
Mock.onPost("api/v1/albums/66/links").reply(
200,
{
Password: "passwd",
Expires: 8000,
Slug: "christmas-2019",
CanEdit: false,
CanComment: false,
},
mockHeaders
);
Mock.onDelete("api/v1/albums/66/links/5").reply(200, { Success: "ok" }, mockHeaders);
Mock.onGet("api/v1/albums/66/links").reply(
200,
[
{ UID: "sqcwh80ifesw74ht", Share: "aqcwh7weohhk49q2", Slug: "july-2020" },
{ UID: "sqcwhxh1h58rf3c2", Share: "aqcwh7weohhk49q2" },
],
mockHeaders
);
Mock.onPut("/api/v1/albums/66").reply(
200,
{
Description: "Test description",
},
mockHeaders
);
Mock.onGet("api/v1/albums").reply(
200,
{
ID: 51,
CreatedAt: "2019-07-03T18:48:07Z",
UpdatedAt: "2019-07-25T01:04:44Z",
DeletedAt: "0001-01-01T00:00:00Z",
Slug: "tabby-cat",
Name: "tabby cat",
Priority: 5,
LabelCount: 9,
Favorite: false,
Description: "",
Notes: "",
},
{
"Content-Type": "application/json; charset=utf-8",
"x-count": "3",
"x-limit": "100",
"x-offset": "0",
}
);
Mock.onOptions("api/v1/albums").reply(
200,
{
foo: "bar",
},
mockHeaders
);
Mock.onOptions("api/v1/albums/abc").reply(
200,
{
foo: "edit",
},
mockHeaders
);
Mock.onDelete("api/v1/albums/abc").reply(
200,
{
status: "ok",
},
mockHeaders
);
Mock.onPut("api/v1/albums/abc").reply(
200,
{
Description: "Test description",
},
mockHeaders
);
//Mock.onPost("api/v1/users/55/profile").reply(200, { FullName: "Max New" }, mockHeaders);
//Mock.onPost("users/55/profile").reply(200, { FullName: "Max New" }, mockHeaders);
//Mock.onPost("api/v1/users/55/profile").reply(200, { FullName: "Max New" }, mockHeaders);
Mock.onAny("api/v1/users/52/register").reply(200, { foo: "register" }, mockHeaders);
Mock.onAny("api/v1/users/53/profile").reply(200, { foo: "profile" }, mockHeaders);
Mock.onPut("api/v1/users/54/password").reply(
200,
{ password: "old", new_password: "new" },
mockHeaders
);
Mock.onGet("api/v1/link/5").reply(200, "get success", mockHeaders);
Mock.onPut("api/v1/link/5").reply(200, "put success", mockHeaders);
Mock.onDelete("api/v1/link/5").reply(200, "delete success", mockHeaders);
Mock.onPost("api/v1/photos/55/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onDelete("api/v1/photos/55/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onGet("api/v1/albums/5").reply(200, { UID: "5" }, mockHeaders);
Mock.onPut("api/v1/photos/5").reply(200, { UID: "5" }, mockHeaders);
Mock.onDelete("api/v1/photos/abc123/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onPost("api/v1/photos/5/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onPost("api/v1/labels/ABC123/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onDelete("api/v1/labels/ABC123/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onPost("api/v1/folders/dqbevau2zlhxrxww/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onDelete("api/v1/folders/dqbevau2zlhxrxww/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onPost("api/v1/photos/undefined/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onDelete("api/v1/photos/undefined/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onPost("api/v1/albums/undefined/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onDelete("api/v1/albums/undefined/like").reply(200, { status: "ok" }, mockHeaders);
Mock.onGet("api/v1/config").reply(200, clientConfig, mockHeaders);
//Mock.onPost().reply(200);
//Mock.onDelete().reply(200);
/*
Mock.onPost().reply(200).onDelete().reply(200);
Mock.onDelete().reply(200);
Mock.onAny().reply(200, "editForm");
Mock.onPut().reply(200, { Description: "Test description" });
Mock.onPut().reply(200, { Description: "Test description" });
Mock.onPost().reply(200, { Description: "Test description" });
*/
export { Api, Mock };

View file

@ -1,20 +1,12 @@
import "../fixtures";
import Account from "model/account";
import Photo from "model/photo";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
let chai = require("chai/chai");
let assert = chai.assert;
const mock = new MockAdapter(Api);
mock
.onGet("api/v1/accounts/123/folders").reply(200, "folders success")
.onPost("api/v1/accounts/123/share").reply(200, "share success");
describe("model/account", () => {
it("should get account defaults", () => {
const values = { ID: 5 };
const account = new Account(values);
@ -41,16 +33,15 @@ describe("model/account", () => {
it("should get folders", (done) => {
const values = { ID: 123, AccName: "Test Name" };
const account = new Account(values);
account.Folders().then(
(response) => {
assert.equal(response, "folders success");
account
.Folders()
.then((response) => {
assert.equal(response.foo, "folders");
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
it("should get share photos", (done) => {
@ -61,16 +52,15 @@ describe("model/account", () => {
const values2 = { ID: 6, Title: "Crazy Cat 2", UID: 783 };
const photo2 = new Photo(values2);
const Photos = [photo, photo2];
account.Share(Photos, "destination").then(
(response) => {
assert.equal(response, "share success");
account
.Share(Photos, "destination")
.then((response) => {
assert.equal(response.foo, "share");
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
it("should get collection resource", () => {
@ -82,5 +72,4 @@ describe("model/account", () => {
const result = Account.getModelName();
assert.equal(result, "Account");
});
});

View file

@ -1,20 +1,9 @@
import "../fixtures";
import Album from "model/album";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import {Settings} from "luxon";
Settings.defaultLocale = "en"
Settings.defaultZoneName = "UTC"
let chai = require("chai/chai");
let assert = chai.assert;
const mock = new MockAdapter(Api);
mock
.onPost().reply(200)
.onDelete().reply(200);
describe("model/album", () => {
it("should get route view", () => {
const values = { id: 5, Title: "Christmas 2019", Slug: "christmas-2019" };
@ -25,7 +14,14 @@ describe("model/album", () => {
});
it("should return classes", () => {
const values = {UID: 5, Title: "Christmas 2019", Slug: "christmas-2019", Type: "moment", Favorite: true, Private: true};
const values = {
UID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
Type: "moment",
Favorite: true,
Private: true,
};
const album = new Album(values);
const result = album.classes(true);
assert.include(result, "is-album");
@ -65,42 +61,87 @@ describe("model/album", () => {
});
it("should get created date string", () => {
const values = {ID: 5, Title: "Christmas 2019", Slug: "christmas-2019", CreatedAt: "2012-07-08T14:45:39Z"};
const values = {
ID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
CreatedAt: "2012-07-08T14:45:39Z",
};
const album = new Album(values);
const result = album.getCreatedString();
assert.equal(result, "Jul 8, 2012, 2:45 PM");
});
it("should get album date string with invalid day", () => {
const values = {ID: 5, Title: "Christmas 2019", Slug: "christmas-2019", CreatedAt: "2012-07-08T14:45:39Z", Day: -1, Month: 5, Year: 2019};
const values = {
ID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
CreatedAt: "2012-07-08T14:45:39Z",
Day: -1,
Month: 5,
Year: 2019,
};
const album = new Album(values);
const result = album.getDateString();
assert.equal(result, "May 2019");
});
it("should get album date string with invalid year", () => {
const values = {ID: 5, Title: "Christmas 2019", Slug: "christmas-2019", CreatedAt: "2012-07-08T14:45:39Z", Day: 1, Month: 5, Year: 800};
const values = {
ID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
CreatedAt: "2012-07-08T14:45:39Z",
Day: 1,
Month: 5,
Year: 800,
};
const album = new Album(values);
const result = album.getDateString();
assert.equal(result, "Unknown");
});
it("should get day string", () => {
const values = {ID: 5, Title: "Christmas 2019", Slug: "christmas-2019", CreatedAt: "2012-07-08T14:45:39Z", Day: 8, Month: 5, Year: 2019};
const values = {
ID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
CreatedAt: "2012-07-08T14:45:39Z",
Day: 8,
Month: 5,
Year: 2019,
};
const album = new Album(values);
const result = album.dayString();
assert.equal(result, "08");
});
it("should get month string", () => {
const values = {ID: 5, Title: "Christmas 2019", Slug: "christmas-2019", CreatedAt: "2012-07-08T14:45:39Z", Day: 8, Month: -5, Year: 2019};
const values = {
ID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
CreatedAt: "2012-07-08T14:45:39Z",
Day: 8,
Month: -5,
Year: 2019,
};
const album = new Album(values);
const result = album.monthString();
assert.equal(result, "01");
});
it("should get year string", () => {
const values = {ID: 5, Title: "Christmas 2019", Slug: "christmas-2019", CreatedAt: "2012-07-08T14:45:39Z", Day: 8, Month: -5, Year: 800};
const values = {
ID: 5,
Title: "Christmas 2019",
Slug: "christmas-2019",
CreatedAt: "2012-07-08T14:45:39Z",
Day: 8,
Month: -5,
Year: 800,
};
const album = new Album(values);
const result = album.yearString();
assert.equal(result, new Date().getFullYear().toString().padStart(4, "0"));

View file

@ -1,15 +1,10 @@
import "../fixtures";
import File from "model/file";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import {Settings} from "luxon";
Settings.defaultLocale = "en"
Settings.defaultZoneName = "UTC"
let chai = require("chai/chai");
let assert = chai.assert;
describe("model/file", () => {
it("should return classes", () => {
const values = {
InstanceID: 5,
@ -17,7 +12,8 @@ describe("model/file", () => {
Name: "1/2/IMG123.jpg",
Primary: true,
Sidecar: true,
Video: true};
Video: true,
};
const file = new File(values);
const result = file.classes(true);
assert.include(result, "is-file");
@ -31,7 +27,8 @@ describe("model/file", () => {
it("should get file defaults", () => {
const values = {
InstanceID: 5,
UID: "ABC123"};
UID: "ABC123",
};
const file = new File(values);
const result = file.getDefaults();
assert.equal(result.UID, "");
@ -42,7 +39,8 @@ describe("model/file", () => {
const values = {
InstanceID: 5,
UID: "ABC123",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
const result = file.baseName();
assert.equal(result, "IMG123.jpg");
@ -54,7 +52,8 @@ describe("model/file", () => {
const values = {
InstanceID: 5,
UID: "ABC123",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(file.isFile(), true);
});
@ -64,7 +63,8 @@ describe("model/file", () => {
InstanceID: 5,
UID: "ABC123",
Root: "",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(file.getEntityName(), "/1/2/IMG123.jpg");
});
@ -75,21 +75,24 @@ describe("model/file", () => {
UID: "ABC123",
Hash: "54ghtfd",
Type: "jpg",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(file.thumbnailUrl("tile_224"), "/api/v1/t/54ghtfd/public/tile_224");
const values2 = {
InstanceID: 5,
UID: "ABC123",
Name: "1/2/IMG123.jpg",
Error: true};
Error: true,
};
const file2 = new File(values2);
assert.equal(file2.thumbnailUrl("tile_224"), "/api/v1/svg/broken");
const values3 = {
InstanceID: 5,
UID: "ABC123",
Name: "1/2/IMG123.jpg",
Type: "raw"};
Type: "raw",
};
const file3 = new File(values3);
assert.equal(file3.thumbnailUrl("tile_224"), "/api/v1/svg/raw");
});
@ -100,7 +103,8 @@ describe("model/file", () => {
UID: "ABC123",
Hash: "54ghtfd",
Type: "jpg",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(file.getDownloadUrl("abc"), "/api/v1/dl/54ghtfd?t=2lbh9x09");
});
@ -113,7 +117,8 @@ describe("model/file", () => {
Type: "jpg",
Width: 500,
Height: 700,
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(file.calculateSize(600, 800).width, 500);
assert.equal(file.calculateSize(600, 800).height, 700);
@ -124,7 +129,8 @@ describe("model/file", () => {
Type: "jpg",
Width: 900,
Height: 850,
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file2 = new File(values2);
assert.equal(file2.calculateSize(600, 800).width, 600);
assert.equal(file2.calculateSize(600, 800).height, 567);
@ -135,7 +141,8 @@ describe("model/file", () => {
Type: "jpg",
Width: 750,
Height: 850,
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file3 = new File(values3);
assert.equal(file3.calculateSize(900, 450).width, 397);
assert.equal(file3.calculateSize(900, 450).height, 450);
@ -334,5 +341,4 @@ describe("model/file", () => {
const result = File.getModelName();
assert.equal(result, "File");
});
});

View file

@ -1,23 +1,10 @@
import "../fixtures";
import Folder from "model/folder";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import {Settings} from "luxon";
Settings.defaultLocale = "en"
Settings.defaultZoneName = "UTC"
let chai = require("chai/chai");
let assert = chai.assert;
const mock = new MockAdapter(Api);
mock
.onGet("folders/2011/10-Halloween", {"params": {"recursive": true, "uncached": true}}).reply(200, {folders: [1, 2], files: [1]}, {"x-count": "3", "x-limit": "100", "x-offset": "0"})
.onGet("folders/2011/10-Halloween", {"params": {"recursive": true}}).reply(200, {folders: [1, 2, 3], files: [1]})
.onGet("folders/originals/2011/10-Halloween", {"params": {"recursive": true}}).reply(200, {folders: [1, 2, 3], files: [1]});
describe("model/folder", () => {
it("should return classes", () => {
const values = {
Folder: true,
@ -129,7 +116,10 @@ describe("model/folder", () => {
Title: "Halloween Party",
};
const folder = new Folder(values);
assert.equal(folder.thumbnailUrl("tile_224"), "/api/v1/folders/t/dqbevau2zlhxrxww/public/tile_224");
assert.equal(
folder.thumbnailUrl("tile_224"),
"/api/v1/folders/t/dqbevau2zlhxrxww/public/tile_224"
);
});
it("should get date string", () => {
@ -207,65 +197,54 @@ describe("model/folder", () => {
});
it("should test find all", (done) => {
Folder.findAll("2011/10-Halloween").then(
(response) => {
Folder.findAll("2011/10-Halloween")
.then((response) => {
assert.equal(response.status, 200);
assert.equal(response.count, 4);
assert.equal(response.folders, 3);
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
it("should test find all uncached", (done) => {
Folder.findAllUncached("2011/10-Halloween").then(
(response) => {
Folder.findAllUncached("2011/10-Halloween")
.then((response) => {
assert.equal(response.status, 200);
assert.equal(response.count, 3);
assert.equal(response.folders, 2);
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
it("should test find in originals", (done) => {
Folder.originals("2011/10-Halloween", {recursive: true}).then(
(response) => {
Folder.originals("2011/10-Halloween", { recursive: true })
.then((response) => {
assert.equal(response.status, 200);
assert.equal(response.count, 4);
assert.equal(response.folders, 3);
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
it("should test search", (done) => {
Folder.search("2011/10-Halloween",{recursive: true, uncached: true}).then(
(response) => {
Folder.search("2011/10-Halloween", { recursive: true, uncached: true })
.then((response) => {
assert.equal(response.status, 200);
assert.equal(response.count, 3);
assert.equal(response.folders, 2);
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
});

File diff suppressed because one or more lines are too long

View file

@ -1,19 +1,10 @@
import "../fixtures";
import Link from "model/link";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
let chai = require("chai/chai");
let assert = chai.assert;
const mock = new MockAdapter(Api);
mock
.onGet("api/v1/link/5").reply(200, "get success")
.onPut("api/v1/link/5").reply(200, "put success")
.onDelete("api/v1/link/5").reply(200, "delete success");
describe("model/link", () => {
it("should get link defaults", () => {
const values = { UID: 5 };
const link = new Link(values);
@ -82,7 +73,14 @@ describe("model/link", () => {
});
it("should test expire", () => {
const values = {UID: 5, Token: "AcfgbTTh", Slug: "friends", Share: "family", Expires: 80000, UpdatedAt: "2012-07-08T14:45:39Z"};
const values = {
UID: 5,
Token: "AcfgbTTh",
Slug: "friends",
Share: "family",
Expires: 80000,
UpdatedAt: "2012-07-08T14:45:39Z",
};
const link = new Link(values);
const result = link.expires();
assert.equal(result, "7/9/2012");
@ -97,5 +95,4 @@ describe("model/link", () => {
const result = Link.getModelName();
assert.equal(result, "Link");
});
});

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,13 @@
import "../fixtures";
import Rest from "model/rest";
import Album from "model/album";
import Label from "model/label";
import Link from "model/link";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
let chai = require("chai/chai");
let assert = chai.assert;
describe("model/abstract", () => {
const mock = new MockAdapter(Api);
it("should set values", () => {
const values = { id: 5, Name: "Black Cat", Slug: "black-cat" };
const label = new Label(values);
@ -52,85 +50,49 @@ describe("model/abstract", () => {
});
it("should update album", async () => {
mock.onPut().reply(200, {Description: "Test description"});
const values = { id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66 };
const album = new Album(values);
assert.equal(album.Description, undefined);
await album.update();
assert.equal(album.Description, "Test description");
mock.reset();
});
it("should save album", async () => {
mock.onPut().reply(200, {Description: "Test description"});
const values = {id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66};
const values = { UID: "abc", Name: "Christmas 2019", Slug: "christmas-2019" };
const album = new Album(values);
assert.equal(album.Description, undefined);
await album.save();
assert.equal(album.Description, "Test description");
mock.reset();
});
it("should save album", async() => {
mock.onPost().reply(200, {Description: "Test description"});
const values = {id: 5, Name: "Christmas 2019", Slug: "christmas-2019"};
const album = new Album(values);
assert.equal(album.Description, undefined);
await album.save();
assert.equal(album.Description, "Test description");
mock.reset();
});
it("should remove album", async () => {
mock.onDelete().reply(200);
const values = {id: 5, Name: "Christmas 2019", Slug: "christmas-2019"};
const values = { UID: "abc", Name: "Christmas 2019", Slug: "christmas-2019" };
const album = new Album(values);
assert.equal(album.Name, "Christmas 2019");
await album.remove();
mock.reset();
});
it("should get edit form", async () => {
mock.onAny().reply(200, "editForm");
const values = {id: 5, Name: "Christmas 2019", Slug: "christmas-2019"};
const values = { UID: "abc", Name: "Christmas 2019", Slug: "christmas-2019" };
const album = new Album(values);
const result = await album.getEditForm();
assert.equal(result.definition, "editForm");
mock.reset();
assert.equal(result.definition.foo, "edit");
});
it("should get create form", async () => {
mock.onAny().reply(200, "createForm");
const result = await Album.getCreateForm();
assert.equal(result.definition, "createForm");
mock.reset();
assert.equal(result.definition.foo, "bar");
});
it("should get search form", async () => {
mock.onAny().reply(200, "searchForm");
const result = await Album.getSearchForm();
assert.equal(result.definition, "searchForm");
mock.reset();
assert.equal(result.definition.foo, "bar");
});
it("should search label", async () => {
mock.onAny().reply(200, {
"ID":51,
"CreatedAt":"2019-07-03T18:48:07Z",
"UpdatedAt":"2019-07-25T01:04:44Z",
"DeletedAt":"0001-01-01T00:00:00Z",
"Slug":"tabby-cat",
"Name":"tabby cat",
"Priority":5,
"LabelCount":9,
"Favorite":false,
"Description":"",
"Notes":""},
{"x-count": "3", "x-limit": "100", "x-offset": "0"});
const result = await Album.search();
assert.equal(result.data.ID, 51);
assert.equal(result.data.Name, "tabby cat");
mock.reset();
});
it("should get collection resource", () => {
@ -154,20 +116,17 @@ describe("model/abstract", () => {
});
it("should find album", async () => {
mock.onGet("api/v1/albums/66", {params: {}}).reply(200, {Success: "ok"});
const values = {id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66};
const values = { Name: "Christmas 2019", Slug: "christmas-2019", UID: 66 };
const album = new Album(values);
album.find(5).then(
(response) => {
assert.equal(response.Success, "ok");
done();
}
).catch(
(error) => {
done(error);
}
);
mock.reset();
return album
.find(5)
.then((response) => {
assert.equal(response.UID, "5");
return Promise.resolve();
})
.catch((error) => {
return Promise.reject(error);
});
});
it("should get entity name", () => {
@ -193,86 +152,75 @@ describe("model/abstract", () => {
});
it("should create link", async () => {
mock.onPost("api/v1/albums/66/links", {
"Password": "passwd",
"Expires": 8000,
"Slug": "christmas-2019",
"CanEdit": false,
"CanComment": false,
}).reply(200, {Success: "ok"});
const values = { id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66 };
const album = new Album(values);
album.createLink("passwd", 8000).then(
(response) => {
assert.equal(response.Success, "ok");
done();
}
).catch(
(error) => {
done(error);
}
);
mock.reset();
album
.createLink("passwd", 8000)
.then((response) => {
assert.equal(response.Slug, "christmas-2019");
return Promise.resolve();
})
.catch((error) => {
return Promise.reject(error);
});
});
it("should update link", async () => {
mock.onPut("api/v1/albums/66/links/5", {
"Password": "passwd123",
"Expires": 9000,
"Slug": "christmas-2018",
"CanEdit": false,
"CanComment": false,
}).reply(200, {Success: "ok"});
const values = {UID: 5, Password: "passwd", Slug: "friends", Expires: 80000, UpdatedAt: "2012-07-08T14:45:39Z"};
const values = {
UID: 5,
Password: "passwd",
Slug: "friends",
Expires: 80000,
UpdatedAt: "2012-07-08T14:45:39Z",
};
const link = new Link(values);
const values2 = { id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66 };
const album = new Album(values2);
album.updateLink(link).then(
(response) => {
assert.equal(response.Success, "ok");
done();
}
).catch(
(error) => {
done(error);
}
);
mock.reset();
return album
.updateLink(link)
.then((response) => {
assert.equal(response.Slug, "friends");
return Promise.resolve();
})
.catch((error) => {
return Promise.reject(error);
});
});
it("should remove link", async () => {
mock.onDelete("api/v1/albums/66/links/5").reply(200, {Success: "ok"});
const values = {UID: 5, Password: "passwd", Slug: "friends", Expires: 80000, UpdatedAt: "2012-07-08T14:45:39Z"};
const values = {
UID: 5,
Password: "passwd",
Slug: "friends",
Expires: 80000,
UpdatedAt: "2012-07-08T14:45:39Z",
};
const link = new Link(values);
const values2 = { id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66 };
const album = new Album(values2);
album.removeLink(link).then(
(response) => {
return album
.removeLink(link)
.then((response) => {
assert.equal(response.Success, "ok");
done();
}
).catch(
(error) => {
done(error);
}
);
mock.reset();
return Promise.resolve();
})
.catch((error) => {
return Promise.reject(error);
});
});
it("should return links", async () => {
mock.onGet("api/v1/albums/66/links").reply(200, [{"UID":"sqcwh80ifesw74ht","Share":"aqcwh7weohhk49q2","Slug":"july-2020"},{"UID":"sqcwhxh1h58rf3c2","Share":"aqcwh7weohhk49q2"}]);
const values2 = { id: 5, Name: "Christmas 2019", Slug: "christmas-2019", UID: 66 };
const album = new Album(values2);
album.links().then(
(response) => {
assert.equal(response.length, 2);
done();
}
).catch(
(error) => {
done(error);
}
);
mock.reset();
return album
.links()
.then((response) => {
assert.equal(response.count, 2);
assert.equal(response.models.length, 2);
return Promise.resolve();
})
.catch((error) => {
return Promise.reject(error);
});
});
});

View file

@ -1,52 +1,41 @@
import "../fixtures";
import Settings from "model/settings";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
let chai = require("chai/chai");
let assert = chai.assert;
const mock = new MockAdapter(Api);
mock
.onGet("api/v1/settings").reply(200, {"download": true, "language": "de"})
.onPost("api/v1/settings").reply(200, {"download": true, "language": "en"});
describe("model/settings", () => {
it("should return if key was changed", () => {
const model = new Settings({"ui": {"language": "de", "scrollbar": false}});
const model = new Settings({ ui: { language: "de", scrollbar: false } });
assert.equal(model.changed("ui", "scrollbar"), false);
assert.equal(model.changed("ui", "language"), false);
});
it("should load settings", (done) => {
const model = new Settings({"ui": {"language": "de", "scrollbar": false}});
model.load().then(
(response) => {
const model = new Settings({ ui: { language: "de", scrollbar: false } });
model
.load()
.then((response) => {
assert.equal(response["ui"]["scrollbar"], false);
assert.equal(response["ui"]["language"], "de");
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
it("should save settings", (done) => {
const model = new Settings({"ui": {"language": "de", "scrollbar": false}});
model.save().then(
(response) => {
const model = new Settings({ ui: { language: "de", scrollbar: false } });
model
.save()
.then((response) => {
assert.equal(response["ui"]["scrollbar"], false);
assert.equal(response["ui"]["language"], "de");
done();
}
).catch(
(error) => {
})
.catch((error) => {
done(error);
}
);
});
});
});

View file

@ -1,21 +1,12 @@
import "../fixtures";
import Thumb from "model/thumb";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
import Photo from "model/photo";
import File from "model/file";
let chai = require("chai/chai");
let assert = chai.assert;
const mock = new MockAdapter(Api);
mock
.onGet("api/v1/settings").reply(200, {"download": true, "language": "de"})
.onPost("api/v1/settings").reply(200, {"download": true, "language": "en"});
describe("model/thumb", () => {
it("should get thumb defaults", () => {
const values = {
uid: "55",
@ -57,7 +48,6 @@ describe("model/thumb", () => {
const result = Thumb.thumbNotFound();
assert.equal(result.uid, "");
assert.equal(result.favorite, false);
});
it("should test from file", () => {
@ -67,7 +57,8 @@ describe("model/thumb", () => {
Name: "1/2/IMG123.jpg",
Hash: "abc123",
Width: 500,
Height: 900};
Height: 900,
};
const file = new File(values);
const values2 = {
@ -115,14 +106,18 @@ describe("model/thumb", () => {
UID: "ABC123",
Description: "Nice description 2",
Hash: "abc345",
Files: [{
Files: [
{
UID: "123fgb",
Name: "1980/01/superCuteKitten.jpg",
Primary: true,
Type: "jpg",
Width: 500,
Height: 600,
Hash: "1xxbgdt53"}]};
Hash: "1xxbgdt53",
},
],
};
const photo3 = new Photo(values4);
const Photos2 = [photo, photo2, photo3];
const result2 = Thumb.fromFiles(Photos2);
@ -130,7 +125,6 @@ describe("model/thumb", () => {
assert.equal(result2[0].description, "Nice description 2");
assert.equal(result2[0].original_w, 500);
assert.equal(result2.length, 1);
});
it("should test from files", () => {
@ -145,14 +139,18 @@ describe("model/thumb", () => {
UID: "ABC123",
Description: "Nice description 3",
Hash: "345ggh",
Files: [{
Files: [
{
UID: "123fgb",
Name: "1980/01/superCuteKitten.jpg",
Primary: true,
Type: "jpg",
Width: 500,
Height: 600,
Hash: "1xxbgdt53"}]};
Hash: "1xxbgdt53",
},
],
};
const photo = new Photo(values);
const result = Thumb.fromPhoto(photo);
assert.equal(result.uid, "ABC123");
@ -175,7 +173,6 @@ describe("model/thumb", () => {
Description: "Nice description",
Favorite: true,
Hash: "xdf45m",
};
const photo2 = new Photo(values2);
const result3 = Thumb.fromPhoto(photo2);
@ -190,14 +187,18 @@ describe("model/thumb", () => {
UID: "ABC123",
Description: "Nice description 3",
Hash: "345ggh",
Files: [{
Files: [
{
UID: "123fgb",
Name: "1980/01/superCuteKitten.jpg",
Primary: true,
Type: "jpg",
Width: 500,
Height: 600,
Hash: "1xxbgdt53"}]};
Hash: "1xxbgdt53",
},
],
};
const photo = new Photo(values);
const Photos = [photo];
const result = Thumb.fromPhotos(Photos);
@ -212,14 +213,16 @@ describe("model/thumb", () => {
UID: "ABC123",
Hash: "54ghtfd",
Type: "jpg",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(Thumb.downloadUrl(file), "/api/v1/dl/54ghtfd?t=2lbh9x09");
const values2 = {
InstanceID: 5,
UID: "ABC123",
Type: "jpg",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file2 = new File(values2);
assert.equal(Thumb.downloadUrl(file2), "");
});
@ -230,13 +233,15 @@ describe("model/thumb", () => {
UID: "ABC123",
Hash: "54ghtfd",
Type: "jpg",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
assert.equal(Thumb.thumbnailUrl(file, "abc"), "/api/v1/t/54ghtfd/public/abc");
const values2 = {
InstanceID: 5,
UID: "ABC123",
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file2 = new File(values2);
assert.equal(Thumb.thumbnailUrl(file2, "bcd"), "/api/v1/svg/photo");
});
@ -249,7 +254,8 @@ describe("model/thumb", () => {
Type: "jpg",
Width: 900,
Height: 850,
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file = new File(values);
const result = Thumb.calculateSize(file, 600, 800); //max 0,75
assert.equal(result.width, 600);
@ -261,7 +267,8 @@ describe("model/thumb", () => {
Type: "jpg",
Width: 750,
Height: 850,
Name: "1/2/IMG123.jpg"};
Name: "1/2/IMG123.jpg",
};
const file3 = new File(values3);
const result2 = Thumb.calculateSize(file3, 900, 450);
assert.equal(result2.width, 397);
@ -270,5 +277,4 @@ describe("model/thumb", () => {
assert.equal(result4.width, 750);
assert.equal(result4.height, 850);
});
});

View file

@ -1,13 +1,10 @@
import "../fixtures";
import User from "model/user";
import MockAdapter from "axios-mock-adapter";
import Api from "common/api";
let chai = require("chai/chai");
let assert = chai.assert;
describe("model/user", () => {
const mock = new MockAdapter(Api);
it("should get entity name", () => {
const values = { ID: 5, FullName: "Max Last", PrimaryEmail: "test@test.com", RoleAdmin: true };
const user = new User(values);
@ -33,25 +30,20 @@ describe("model/user", () => {
});
it("should get register form", async () => {
mock.onAny("users/52/register").reply(200, "registerForm");
const values = { ID: 52, FullName: "Max Last" };
const user = new User(values);
const result = await user.getRegisterForm();
assert.equal(result.definition, "registerForm");
mock.reset();
assert.equal(result.definition.foo, "register");
});
it("should get profile form", async () => {
mock.onAny("users/53/profile").reply(200, "profileForm");
const values = { ID: 53, FullName: "Max Last" };
const user = new User(values);
const result = await user.getProfileForm();
assert.equal(result.definition, "profileForm");
mock.reset();
assert.equal(result.definition.foo, "profile");
});
it("should get change password", async () => {
mock.onPut("users/54/password").reply(200, {password: "old", new_password: "new"});
const values = { ID: 54, FullName: "Max Last", PrimaryEmail: "test@test.com", RoleAdmin: true };
const user = new User(values);
const result = await user.changePassword("old", "new");
@ -59,7 +51,6 @@ describe("model/user", () => {
});
it("should save profile", async () => {
mock.onPost("users/55/profile").reply(200, {FullName: "Max New",});
const values = { ID: 55, FullName: "Max Last", PrimaryEmail: "test@test.com", RoleAdmin: true };
const user = new User(values);
assert.equal(user.FullName, "Max Last");

View file

@ -30,9 +30,10 @@ https://docs.photoprism.org/developer-guide/
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OfflinePlugin = require("offline-plugin");
const OfflinePlugin = require("@lcdp/offline-plugin");
const webpack = require("webpack");
const isDev = process.env.NODE_ENV !== "production";
const { VueLoaderPlugin } = require("vue-loader");
if (isDev) {
console.log("Building frontend in DEVELOPMENT mode. Please wait.");
@ -51,6 +52,9 @@ const PATHS = {
const config = {
mode: isDev ? "development" : "production",
devtool: isDev ? "inline-source-map" : false,
optimization: {
minimize: !isDev,
},
entry: {
app: PATHS.app,
share: PATHS.share,
@ -68,12 +72,12 @@ const config = {
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
experimentalUseImportModule: false,
}),
new webpack.ProgressPlugin(),
new VueLoaderPlugin(),
new OfflinePlugin(),
],
node: {
fs: "empty",
},
performance: {
hints: isDev ? false : "error",
maxEntrypointSize: 4000000,
@ -86,15 +90,21 @@ const config = {
include: PATHS.app,
exclude: /node_modules/,
enforce: "pre",
use: [
{
loader: "eslint-loader",
options: {
formatter: require("eslint-formatter-pretty"),
},
},
],
},
{
test: /\.vue$/,
loader: "vue-loader",
include: PATHS.js,
use: [
{
loader: "vue-loader",
options: {
loaders: {
js: "babel-loader",
@ -102,16 +112,27 @@ const config = {
},
},
},
],
},
{
test: /\.js$/,
loader: "babel-loader",
include: PATHS.js,
exclude: (file) => /node_modules/.test(file),
query: {
presets: ["@babel/preset-env"],
use: [
{
loader: "babel-loader",
options: {
sourceMap: isDev,
compact: false,
presets: ["@babel/preset-env"],
plugins: [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-class-properties",
],
},
},
],
},
{
test: /\.css$/,
include: PATHS.css,
@ -120,75 +141,83 @@ const config = {
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: false,
fallback: "vue-style-loader",
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 1,
sourceMap: isDev,
},
},
{
loader: "postcss-loader",
options: {
sourceMap: isDev,
config: {
path: path.resolve(__dirname, "./postcss.config.js"),
},
},
},
"resolve-url-loader",
],
publicPath: PATHS.build,
},
},
"css-loader",
{
loader: "css-loader",
options: {
sourceMap: true,
importLoaders: 1,
},
},
"resolve-url-loader",
{
loader: "postcss-loader",
options: {
sourceMap: true,
postcssOptions: {
config: path.resolve(__dirname, "./postcss.config.js"),
},
},
},
],
},
{
test: /\.css$/,
include: /node_modules/,
loaders: [
"vue-style-loader",
"style-loader",
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: PATHS.build,
},
},
{
loader: "css-loader",
options: { importLoaders: 1, sourceMap: isDev },
},
{
loader: "postcss-loader",
options: {
sourceMap: isDev,
config: {
path: path.resolve(__dirname, "./postcss.config.js"),
},
sourceMap: true,
importLoaders: 1,
},
},
"resolve-url-loader",
{
loader: "postcss-loader",
options: {
sourceMap: true,
postcssOptions: {
config: path.resolve(__dirname, "./postcss.config.js"),
},
},
},
],
},
{
test: /\.s[c|a]ss$/,
use: [
"vue-style-loader",
"style-loader",
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: PATHS.build,
},
},
{
loader: "css-loader",
options: { importLoaders: 2, sourceMap: isDev },
},
{
loader: "postcss-loader",
options: {
sourceMap: isDev,
config: {
path: path.resolve(__dirname, "./postcss.config.js"),
},
sourceMap: true,
importLoaders: 1,
},
},
"resolve-url-loader",
{
loader: "postcss-loader",
options: {
sourceMap: true,
postcssOptions: {
config: path.resolve(__dirname, "./postcss.config.js"),
},
},
},
"sass-loader",
],
},
@ -197,7 +226,7 @@ const config = {
loader: "file-loader",
options: {
name: "[hash].[ext]",
publicPath: "./static/build/img",
publicPath: "./img",
outputPath: "img",
},
},