mirror of
https://gitlab.com/Thoscellen/Wallset.git
synced 2025-05-31 19:04:51 +02:00
Init project
This commit is contained in:
commit
b2f76f3a0d
BIN
public/Gaming-Themeset-for-WinDynamicDesktop-icon.jpg
Normal file
BIN
public/Gaming-Themeset-for-WinDynamicDesktop-icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
0
src/build_job/themeset_builder.js
Normal file
0
src/build_job/themeset_builder.js
Normal file
91
src/test_images_job/test_wpp.py
Normal file
91
src/test_images_job/test_wpp.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import glob
|
||||||
|
from PIL import Image, ImageStat
|
||||||
|
# from _pytest.outcomes import skip
|
||||||
|
from iteration_utilities import duplicates
|
||||||
|
from pathlib import Path
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
def validate_brightness_image(working_path, theme_config, high_light, image_list, brightness_way):
|
||||||
|
# get a dict<filename:string, mean:int> of all images to scan them
|
||||||
|
image_pattern = theme_config.get("imageFilename")
|
||||||
|
|
||||||
|
# if image_filenames is None:
|
||||||
|
image_filenames = {}.fromkeys(glob.glob(str(Path(working_path, image_pattern))))
|
||||||
|
|
||||||
|
# generate an image statistics for each images
|
||||||
|
for an_imagefile in image_filenames:
|
||||||
|
this_image = Image.open(an_imagefile).convert("L")
|
||||||
|
this_image_stats = ImageStat.Stat(this_image)
|
||||||
|
image_filenames[an_imagefile] = this_image_stats.mean[0]
|
||||||
|
|
||||||
|
# get the brightest observed image from the list
|
||||||
|
if high_light == "dayHighlight":
|
||||||
|
actual_est_image = max(image_filenames, key=lambda key: image_filenames[key])
|
||||||
|
else:
|
||||||
|
actual_est_image = min(image_filenames, key=lambda key: image_filenames[key])
|
||||||
|
|
||||||
|
# get the brightest referenced image OR in the daylist to compare to
|
||||||
|
if theme_config.get(high_light):
|
||||||
|
an_image = image_pattern.replace("*", str(theme_config.get(high_light)))
|
||||||
|
ref_est_file = str(Path(working_path, an_image))
|
||||||
|
assert actual_est_image == ref_est_file, f"✖ {brightness_way} image is {actual_est_image}, but the {high_light} image is {ref_est_file}."
|
||||||
|
|
||||||
|
else:
|
||||||
|
# if not highlight is given in theme.json, we suppose that brightest images are in the daylist
|
||||||
|
ref_est_files = []
|
||||||
|
for an_id in theme_config.get(image_list):
|
||||||
|
an_image = image_pattern.replace('*', str(an_id))
|
||||||
|
ref_est_files.append(str(Path(working_path, an_image)))
|
||||||
|
assert actual_est_image in ref_est_files, f"✖ {brightness_way} image {actual_est_image} was not found in the '{image_list}' attribute."
|
||||||
|
# print(f"✔ {brightness_way} image is {actual_est_image}, as expected.")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def working_path():
|
||||||
|
# get the global variables containing gitlab-given project slug.
|
||||||
|
project_slug = os.environ["WPP_SLUG"]
|
||||||
|
root_folder = os.environ["WPP_ROOT"]
|
||||||
|
working_path = Path(root_folder, project_slug)
|
||||||
|
if not working_path.is_dir():
|
||||||
|
raise FileNotFoundError(f"No project found for the given {working_path}.")
|
||||||
|
return working_path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def manifest(working_path):
|
||||||
|
with open(Path(working_path, "theme.json"), 'r') as fileobj:
|
||||||
|
return json.load(fileobj)
|
||||||
|
|
||||||
|
|
||||||
|
def test_brightest_image(working_path, manifest):
|
||||||
|
validate_brightness_image(working_path, manifest, "dayHighlight", "dayImageList", "Brightest")
|
||||||
|
|
||||||
|
|
||||||
|
def test_darkest_image(working_path, manifest):
|
||||||
|
validate_brightness_image(working_path, manifest, "nightHighlight", "nightImageList", "Darkest")
|
||||||
|
|
||||||
|
|
||||||
|
def test_image_size(working_path, manifest):
|
||||||
|
image_filename = manifest["imageFilename"].replace("*", str(manifest["dayImageList"][0]))
|
||||||
|
img = Image.open(Path(working_path, image_filename))
|
||||||
|
w, h = img.size
|
||||||
|
assert w >= 1920 and h >= 1080, f"✖ Image size is too small (must be at least 1920×1080, is {w}×{h})"
|
||||||
|
assert w >= h, "✖ Image orientation is portrait (must be landscape or square)"
|
||||||
|
# print(f"✔ Images are big enough ({w}×{h}) and landscape.")
|
||||||
|
|
||||||
|
|
||||||
|
def test_overlapping_images(manifest):
|
||||||
|
jointed_lists = manifest.get("dayImageList")
|
||||||
|
jointed_lists.extend(manifest.get("nightImageList"))
|
||||||
|
jointed_lists.extend(manifest.get("sunriseImageList", []))
|
||||||
|
jointed_lists.extend(manifest.get("sunsetImageList", []))
|
||||||
|
|
||||||
|
dup_refs = list(duplicates(jointed_lists))
|
||||||
|
str_dup_refs = [manifest["imageFilename"].replace("*", str(int)) for int in dup_refs]
|
||||||
|
separator = ", "
|
||||||
|
|
||||||
|
assert not dup_refs, f"✖ Some images are referenced twice or more times: {separator.join(str_dup_refs)}."
|
||||||
|
# print("✔ There is no overlapping references of images in the theme.json.")
|
56
src/test_manifest_job/json_theme_schema.jsonc
Normal file
56
src/test_manifest_job/json_theme_schema.jsonc
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"type": "object",
|
||||||
|
"required": ["imageFilename","imageCredits","displayName","dayImageList","nightImageList"],
|
||||||
|
"properties": {
|
||||||
|
"imageFilename": {"type": "string"},
|
||||||
|
"imageCredits": {"type": "string"},
|
||||||
|
"displayName": {"type": "string"},
|
||||||
|
"dayHighlight": {"type": "integer", "minimum": 0},
|
||||||
|
"nightHighlight": {"type": "integer", "minimum": 0},
|
||||||
|
"sunriseImageList": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems" : 0,
|
||||||
|
"uniqueItems" : true,
|
||||||
|
"items": {"type": "integer", "minimum": 0}
|
||||||
|
},
|
||||||
|
"dayImageList": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems" : 0,
|
||||||
|
"uniqueItems" : true,
|
||||||
|
"items": {"type": "integer", "minimum": 0}
|
||||||
|
},
|
||||||
|
"sunsetImageList": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems" : 0,
|
||||||
|
"uniqueItems" : true,
|
||||||
|
"items": {"type": "integer", "minimum": 0}
|
||||||
|
},
|
||||||
|
"nightImageList": {
|
||||||
|
"type": "array",
|
||||||
|
"minItems" : 0,
|
||||||
|
"uniqueItems" : true,
|
||||||
|
"items": {"type": "integer", "minimum": 0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"errorMessage": {
|
||||||
|
"required": {
|
||||||
|
"imageFilename":"The ‘imageFilename’ property is missing. Consider adding it.",
|
||||||
|
"imageCredits":"The ‘imageCredits’ property is missing. Consider adding it.",
|
||||||
|
"displayName":"The ‘displayName’ property is missing. Consider adding it.",
|
||||||
|
"dayImageList":"The ‘dayImageList’ property is missing. Consider adding it.",
|
||||||
|
"nightImageList":"The ‘nightImageList’ property is missing. Consider adding it."
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"imageFilename": "The ‘imageFilename’ property must be of type ‘string’ and reflect a glob of an image, i.e.: ‘myWallpaper_*.jpg’.",
|
||||||
|
"imageCredits": "The ‘imageCredits’ property must be of type ‘string’.",
|
||||||
|
"displayName": "The ‘displayName’ property must be of type ‘string’.",
|
||||||
|
"dayHighlight": "The ‘dayHighlight’ property must be a counting number referencing an image, i.e.: ‘5’ in ‘myWallpaper_5.jpg’.",
|
||||||
|
"nightHighlight": "The ‘nightHighlight’ property must be a counting number referencing an image, i.e.: ‘13’ in ‘myWallpaper_13.jpg’.",
|
||||||
|
"sunriseImageList": "The ‘sunriseImageList’ property must be a list of counting numbers referencing images, i.e.: ‘[1, 2, 3, 4].’",
|
||||||
|
"dayImageList": "The ‘dayImageList’ property must be a list of counting numbers referencing images, i.e.: ‘[1, 2, 3, 4]’.",
|
||||||
|
"sunsetImageList": "The ‘sunsetImageList’ property must be a list of counting numbers referencing images, i.e.: ‘[1, 2, 3, 4]’.",
|
||||||
|
"nightImageList": "The ‘nightImageList’ property must be a list of counting numbers referencing images, i.e.: ‘[1, 2, 3, 4]’."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1853
src/test_manifest_job/package-lock.json
generated
Normal file
1853
src/test_manifest_job/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
src/test_manifest_job/package.json
Normal file
18
src/test_manifest_job/package.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "wppchecker",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "wppChecker.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha wppChecker.js --require mocha-step --colors"
|
||||||
|
},
|
||||||
|
"author": "PtiSimon",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": "^8.5.0",
|
||||||
|
"ajv-errors": "^3.0.0",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"mocha": "^8.4.0",
|
||||||
|
"mocha-steps": "^1.3.0"
|
||||||
|
}
|
||||||
|
}
|
76
src/test_manifest_job/wppChecker.js
Normal file
76
src/test_manifest_job/wppChecker.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
const { env, exit } = require("process");
|
||||||
|
const expect = require("chai").expect;
|
||||||
|
const Ajv = require("ajv").default;
|
||||||
|
const ajv = new Ajv({allErrors: true});
|
||||||
|
require("ajv-errors")(ajv);
|
||||||
|
|
||||||
|
//let root, slug;
|
||||||
|
//let workingDirectory = path.join(root, slug);
|
||||||
|
//console.log(`👷♂️ Working with ‘${slug}’ slug.`);
|
||||||
|
|
||||||
|
const themeSchemaFile = ".gitlab/node_job/json_theme_schema.jsonc";
|
||||||
|
let wppManifest;
|
||||||
|
let validator;
|
||||||
|
let files;
|
||||||
|
|
||||||
|
function leftOuterJoin(leftArray, rightArray) {
|
||||||
|
return leftArray.filter(function(el) {
|
||||||
|
return this.indexOf(el) < 0;
|
||||||
|
}, rightArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
function flatReferences(wppManifest) {
|
||||||
|
allImageIds = [
|
||||||
|
wppManifest.dayHighlight,
|
||||||
|
wppManifest.nightHighlight,
|
||||||
|
...wppManifest.dayImageList,
|
||||||
|
...wppManifest.nightImageList,
|
||||||
|
...(wppManifest.sunsetImageList || []),
|
||||||
|
...(wppManifest.sunriseImageList || [])
|
||||||
|
];
|
||||||
|
return allImageIds.filter(el => el !== undefined).map(el => {
|
||||||
|
return wppManifest.imageFilename.replace("*", el);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Mandatory Checks', function() {
|
||||||
|
before(function() {
|
||||||
|
slug = env.WPP_SLUG;
|
||||||
|
expect(slug).to.be.a("string").that.is.not.empty;
|
||||||
|
root = env.WPP_ROOT;
|
||||||
|
expect(root).to.be.a("string").that.is.not.empty;
|
||||||
|
workingDirectory = path.join(root, slug);
|
||||||
|
files = fs.readdirSync(workingDirectory);
|
||||||
|
expect(files).to.be.an('array').that.is.not.empty;
|
||||||
|
validator = ajv.compile(JSON.parse(fs.readFileSync(themeSchemaFile, 'utf8')));
|
||||||
|
});
|
||||||
|
|
||||||
|
step('Manifest is an existing json file', function() {
|
||||||
|
wppManifest = JSON.parse(fs.readFileSync(path.join(workingDirectory, "theme.json"), "utf8"));
|
||||||
|
});
|
||||||
|
|
||||||
|
step('Manifest passes the schema', function() {
|
||||||
|
const isValid = validator(wppManifest);
|
||||||
|
if(!isValid) expect.fail(`\n\t• ${validator.errors.map(el => {return el.message;}).join('\n\t• ')}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
step('There are no missing files', function() {
|
||||||
|
let references = flatReferences(wppManifest);
|
||||||
|
references.push("theme.json");
|
||||||
|
missings = leftOuterJoin(references, files);
|
||||||
|
expect(missings,
|
||||||
|
`The following reference${(missings.length > 1)? "s": ""} from theme.json ${(missings.length > 1)? "are": "is"} missing in the pack. Consider adding ${(missings.length > 1)? "them": " it"} to the pack or removing the reference${(missings.length > 1)? "s": ""} from the theme.json:\n\t• ${missings.join('\n\t• ')}\n`
|
||||||
|
).to.be.lengthOf(0, );
|
||||||
|
});
|
||||||
|
|
||||||
|
step('There are no orphan files', function() {
|
||||||
|
let references = flatReferences(wppManifest);
|
||||||
|
orphans = leftOuterJoin(files.filter(x => x !== "theme.json"), references);
|
||||||
|
expect(orphans,
|
||||||
|
`The following orphan file${(orphans.length > 1)? "s are": " is"} not referenced in this theme.json. Consider removing the file${(orphans.length > 1)? "s": ""} or referencing ${(orphans.length > 1)? "them": "it"} in the theme.json:\n\t• ${orphans.join('\n\t• ')}\n`
|
||||||
|
).to.be.lengthOf(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
BIN
test/valid_set/bl2_eridum_badlands_1.jpg
Normal file
BIN
test/valid_set/bl2_eridum_badlands_1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 263 KiB |
BIN
test/valid_set/bl2_eridum_badlands_2.jpg
Normal file
BIN
test/valid_set/bl2_eridum_badlands_2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 253 KiB |
BIN
test/valid_set/bl2_eridum_badlands_3.jpg
Normal file
BIN
test/valid_set/bl2_eridum_badlands_3.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 236 KiB |
BIN
test/valid_set/bl2_eridum_badlands_4.jpg
Normal file
BIN
test/valid_set/bl2_eridum_badlands_4.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 239 KiB |
Loading…
x
Reference in New Issue
Block a user