-
![](https://placehold.it/750x450)
+
John Smith
Job Title
@@ -125,7 +125,7 @@
-
![](https://placehold.it/750x450)
+
John Smith
Job Title
@@ -151,22 +151,22 @@
-
![](https://placehold.it/500x300)
+
-
![](https://placehold.it/500x300)
+
-
![](https://placehold.it/500x300)
+
-
![](https://placehold.it/500x300)
+
-
![](https://placehold.it/500x300)
+
-
![](https://placehold.it/500x300)
+
diff --git a/app/sprinkles/core/templates/pages/index.html.twig b/app/sprinkles/core/templates/pages/index.html.twig
index 3162aa79b..703fdd557 100755
--- a/app/sprinkles/core/templates/pages/index.html.twig
+++ b/app/sprinkles/core/templates/pages/index.html.twig
@@ -20,21 +20,21 @@
-
![First slide](https://placehold.it/1900x1080&text=Slide One)
+
First Slide
-
![Second slide](https://placehold.it/1900x1080&text=Slide Two)
+
Second Slide
-
![Third slide](https://placehold.it/1900x1080&text=Slide Three)
+
Third Slide
@@ -104,32 +104,32 @@
@@ -153,7 +153,7 @@
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Corporis, omnis doloremque non cum id reprehenderit, quisquam totam aspernatur tempora minima unde aliquid ea culpa sunt. Reiciendis quia dolorum ducimus unde.
-
![](https://placehold.it/700x450)
+
diff --git a/app/sprinkles/core/tests/Integration/Database/DatabaseTests.php b/app/sprinkles/core/tests/Integration/Database/DatabaseTests.php
index ec3753366..ea98fa0e1 100644
--- a/app/sprinkles/core/tests/Integration/Database/DatabaseTests.php
+++ b/app/sprinkles/core/tests/Integration/Database/DatabaseTests.php
@@ -648,8 +648,11 @@ public function testBelongsToManyThrough()
// Test counting related models (withCount)
$users = EloquentTestUser::withCount('permissions')->get();
- $this->assertEquals(3, $users[0]->permissions_count);
- $this->assertEquals(3, $users[1]->permissions_count);
+
+ // N.B.: Changed behavior in UF 4.6 due to change in Laravel API. Duplicated permission now count as two, instead of 1.
+ // See : https://github.com/laravel/framework/issues/30575#issuecomment-554096259
+ $this->assertEquals(4, $users[0]->permissions_count); // Used to be 3
+ $this->assertEquals(4, $users[1]->permissions_count);
$this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[0]);
$this->assertInstanceOf(EloquentTestPermission::class, $users[0]->permissions[1]);
diff --git a/app/sprinkles/core/tests/Integration/Filesystem/FilesystemTest.php b/app/sprinkles/core/tests/Integration/Filesystem/FilesystemTest.php
index 481d49a21..bf2c97356 100644
--- a/app/sprinkles/core/tests/Integration/Filesystem/FilesystemTest.php
+++ b/app/sprinkles/core/tests/Integration/Filesystem/FilesystemTest.php
@@ -89,7 +89,7 @@ public function testAdapter(FilesystemAdapter $files)
// We'll delete the test file now
$this->assertTrue($files->delete('file.txt'));
- $this->assertFileNotExists($this->testDir . '/file.txt');
+ $this->assertFileDoesNotExist($this->testDir . '/file.txt');
}
/**
@@ -117,7 +117,7 @@ public function testUrl(FilesystemAdapter $files)
$url = $files->url('file.txt');
$this->assertEquals('files/testing/file.txt', $url);
$this->assertTrue($files->delete('file.txt'));
- $this->assertFileNotExists($this->testDir . '/file.txt');
+ $this->assertFileDoesNotExist($this->testDir . '/file.txt');
}
/**
diff --git a/app/sprinkles/core/tests/Unit/Database/Relations/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/Database/Relations/BelongsToManyThroughTest.php
index 8508ed415..38d6fe11c 100644
--- a/app/sprinkles/core/tests/Unit/Database/Relations/BelongsToManyThroughTest.php
+++ b/app/sprinkles/core/tests/Unit/Database/Relations/BelongsToManyThroughTest.php
@@ -69,10 +69,11 @@ protected function getRelation()
{
// We simulate a BelongsToManyThrough relationship that gets all related users for a specified permission(s).
$builder = m::mock(EloquentBuilder::class);
- $related = m::mock('Illuminate\Database\Eloquent\Model');
+ $related = m::mock('Illuminate\Database\Eloquent\Model')->makePartial();
$related->shouldReceive('getKey')->andReturn(1);
$related->shouldReceive('getTable')->andReturn('users');
$related->shouldReceive('getKeyName')->andReturn('id');
+
// Tie the mocked builder to the mocked related model
$builder->shouldReceive('getModel')->andReturn($related);
diff --git a/app/sprinkles/core/tests/Unit/Util/VersionValidatorTest.php b/app/sprinkles/core/tests/Unit/Util/VersionValidatorTest.php
index 684faa211..a560c71b1 100644
--- a/app/sprinkles/core/tests/Unit/Util/VersionValidatorTest.php
+++ b/app/sprinkles/core/tests/Unit/Util/VersionValidatorTest.php
@@ -161,12 +161,13 @@ public function testNpm(string $version, string $sanitized, bool $valid): void
public function phpVersionProvider(): array
{
return [
- ['7.1.4', '7.1.4', false, true],
- ['7.2.1', '7.2.1', true, true],
- ['7.2', '7.2', true, true],
+ ['7.2.3', '7.2.3', false, true],
['7.3.14', '7.3.14', true, true],
- ['7.4.13', '7.4.13', true, false],
- ['7.2.34-18+ubuntu20.04.1+deb.sury.org+1', '7.2.34', true, true],
+ ['7.3', '7.3', true, true],
+ ['7.4', '7.4', true, true],
+ ['7.4.13', '7.4.13', true, true],
+ ['8.0.3', '8.0.3', true, false],
+ ['7.4.34-18+ubuntu20.04.1+deb.sury.org+1', '7.4.34', true, true],
];
}
diff --git a/build/gulpfile.esm.js b/build/gulpfile.mjs
similarity index 98%
rename from build/gulpfile.esm.js
rename to build/gulpfile.mjs
index 74188d09d..7034c36bd 100644
--- a/build/gulpfile.esm.js
+++ b/build/gulpfile.mjs
@@ -1,4 +1,3 @@
-// @ts-check
import { exec as _exec } from "child_process";
import { config as envConfig } from "dotenv";
import { writeFileSync } from "fs";
diff --git a/build/missing-types.d.ts b/build/missing-types.d.ts
new file mode 100644
index 000000000..27a95d139
--- /dev/null
+++ b/build/missing-types.d.ts
@@ -0,0 +1,52 @@
+// TODO Remove pending merging of https://github.com/gulpjs/gulplog/pull/12
+declare module "gulplog" {
+ /**
+ * Highest log level. Typically used for debugging purposes.
+ *
+ * If the first argument is a string, all arguments are passed to node's util.format() before being emitted.
+ * @param msg Message to log
+ * @param args Arguments to format message with via util.format()
+ */
+ export function debug(msg: string, ...args: any[]): void;
+ export function debug(msg: any): void;
+ /**
+ * Standard log level. Typically used for user information.
+ *
+ * If the first argument is a string, all arguments are passed to node's util.format() before being emitted.
+ * @param msg Message to log
+ * @param args Arguments to format message with via util.format()
+ */
+ export function info(msg: string, ...args: any[]): void;
+ export function info(msg: any): void;
+ /**
+ * Warning log level. Typically used for warnings.
+ *
+ * If the first argument is a string, all arguments are passed to node's util.format() before being emitted.
+ * @param msg Message to log
+ * @param args Arguments to format message with via util.format()
+ */
+ export function warn(msg: string, ...args: any[]): void;
+ export function warn(msg: any): void;
+ /**
+ * Error log level. Typically used when things went horribly wrong.
+ *
+ * If the first argument is a string, all arguments are passed to node's util.format() before being emitted.
+ * @param msg Message to log
+ * @param args Arguments to format message with via util.format()
+ */
+ export function error(msg: string, ...args: any[]): void;
+ export function error(msg: any): void;
+
+ const _default = {
+ debug,
+ info,
+ warn,
+ error,
+ };
+
+ export default _default;
+}
+
+declare module "gulp-concat-css" {
+ export = (...args?: unknown[]) => unknown;
+}
diff --git a/build/package.json b/build/package.json
index 4bdfec1d6..99f10c9de 100755
--- a/build/package.json
+++ b/build/package.json
@@ -1,26 +1,27 @@
{
"private": true,
+ "type": "module",
"dependencies": {
- "@userfrosting/browserify-dependencies": "^3.1.0",
- "@userfrosting/gulp-bundle-assets": "^4.0.1",
- "@userfrosting/merge-package-dependencies": "^2.1.0",
- "@userfrosting/vinyl-fs-vpath": "^2.0.0",
+ "@userfrosting/browserify-dependencies": "^4.0.0",
+ "@userfrosting/gulp-bundle-assets": "^5.0.2",
+ "@userfrosting/merge-package-dependencies": "^3.0.1",
+ "@userfrosting/ts-log-adapter-gulplog": "^1.0.0",
+ "@userfrosting/vinyl-fs-vpath": "^3.0.2",
"@yarnpkg/shell": "^2.4.1",
"bower": "^1.8.12",
"del": "^6.0.0",
- "dotenv": "^8.2.0",
- "esm": "^3.2.25",
- "gulp": "^4.0.2",
+ "dotenv": "^10.0.0",
"gulp-clean-css": "^4.3.0",
- "gulp-concat": "^2.6.1",
"gulp-concat-css": "^3.1.0",
+ "gulp-concat": "^2.6.1",
"gulp-if": "^3.0.0",
- "gulp-prune": "^0.2.0",
+ "gulp-prune": "^2.0.0",
"gulp-rev": "^9.0.0",
"gulp-sourcemaps": "^3.0.0",
"gulp-terser": "^2.0.1",
+ "gulp": "^4.0.2",
"gulplog": "^1.0.0",
- "strip-ansi": "^6.0.0"
+ "strip-ansi": "^7.0.0"
},
"scripts": {
"uf-bundle": "shell './node_modules/.bin/gulp build'",
@@ -32,5 +33,17 @@
"node": "^12.17.0 || >=14.0.0",
"npm": ">=6.14.4"
},
- "engineStrict": true
+ "engineStrict": true,
+ "devDependencies": {
+ "@types/gulp": "^4.0.9",
+ "@types/gulp-clean-css": "^4.3.0",
+ "@types/gulp-concat": "^0.0.33",
+ "@types/gulp-if": "^0.0.34",
+ "@types/gulp-rev": "^5.0.32",
+ "@types/gulp-sourcemaps": "0.0.35",
+ "@types/gulp-terser": "^1.2.1",
+ "@types/node": "^16.3.1",
+ "@types/vinyl": "^2.0.5",
+ "typescript": "^4.3.5"
+ }
}
diff --git a/build/tasks/assets-install.js b/build/tasks/assets-install.js
index 85843a529..fc19dc7c6 100644
--- a/build/tasks/assets-install.js
+++ b/build/tasks/assets-install.js
@@ -1,32 +1,35 @@
-// @ts-check
-import { Logger, legacyVendorAssetsGlob, sprinkles, sprinklesDir, vendorAssetsDir } from "./util.js";
+import { legacyVendorAssetsGlob, sprinkles, sprinklesDir, vendorAssetsDir } from "./util.js";
import { bower as mergeBowerDeps, npm as mergeNpmDeps } from "@userfrosting/merge-package-dependencies";
-import browserifyDependencies from "@userfrosting/browserify-dependencies";
+import { browserifyDependencies } from "@userfrosting/browserify-dependencies";
import { sync as deleteSync } from "del";
import childProcess, { exec as _exec } from "child_process";
import { existsSync } from "fs";
import { promisify } from "util";
+import { GulpLogLogger } from "@userfrosting/ts-log-adapter-gulplog";
// Promisify exec
const exec = promisify(_exec);
/**
* Runs the provided command and captures output.
+ * @todo Add support for realtime logging
* @param {string} source Used to annotate logs.
* @param {string} cmd Command to execute.
* @param {childProcess.ExecOptions} options Options to pass to `exec`.
*/
async function runCommand(source, cmd, options) {
- const log = new Logger(`${source}> ${cmd}`)
+ const log = new GulpLogLogger(`${source}> ${cmd}`)
log.info("Running command");
try {
const result = await exec(cmd, options);
- if (result.stdout) log.info(result.stdout);
- if (result.stderr) log.error(result.stderr);
+ if (result.stdout) result.stdout.split("\n").forEach(msg => log.info(msg));
+ if (result.stderr) result.stderr.split("\n").forEach(msg => log.error(msg));
} catch (e) {
- if (e.stdout) log.info(e.stdout);
- if (e.stderr) log.error(e.stderr);
+ /** @type {{ stdout: string, stderr: string }} */
+ const err = e;
+ if (e.stdout) err.stdout.split("\n").forEach(msg => log.info(msg));
+ if (e.stderr) err.stderr.split("\n").forEach(msg => log.error(msg));
log.error("Command has completed with an error");
throw e;
}
@@ -38,7 +41,7 @@ async function runCommand(source, cmd, options) {
* Installs vendor assets. Mapped to npm script "uf-assets-install".
*/
export async function assetsInstall() {
- const log = new Logger(assetsInstall.name);
+ const log = new GulpLogLogger(assetsInstall.name);
// Clean up any legacy assets
if (deleteSync(legacyVendorAssetsGlob, { force: true }))
@@ -66,6 +69,7 @@ export async function assetsInstall() {
private: true
};
log.info("Collating dependencies...");
+ /** @type {{ private: boolean, dependencies?: { [x: string]: string } }} */
const pkg = mergeNpmDeps(npmTemplate, npmPaths, vendorAssetsDir, true);
log.info("Dependency collation complete.");
@@ -85,14 +89,14 @@ export async function assetsInstall() {
await runCommand(assetsInstall.name, "npm audit", { cwd: vendorAssetsDir });
}
catch {
- log.warn("There appear to be some vulerabilities within your dependencies. Updating is recommended.");
+ log.warn("There appear to be some vulnerabilities within your dependencies. Updating is recommended.");
}
// Browserify dependencies
log.info("Compiling compatible node modules into UMD bundles with browserify");
deleteSync(vendorAssetsDir + "browser_modules/", { force: true });
await browserifyDependencies({
- dependencies: Object.keys(pkg.dependencies),
+ dependencies: Object.keys(pkg.dependencies || []),
inputDir: vendorAssetsDir + "node_modules/",
outputDir: vendorAssetsDir + "browser_modules/",
silentFailures: true,
@@ -114,8 +118,7 @@ export async function assetsInstall() {
for (const sprinkle of sprinkles) {
const path = sprinklesDir + sprinkle + "/bower.json";
if (existsSync(path)) {
- // TODO: We should really have a link to docs in the message
- log.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`);
+ log.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead. https://learn.userfrosting.com/upgrading/41-to-42#bower-deprecation-new-npm-support`);
bowerPaths.push(path);
}
}
diff --git a/build/tasks/build.js b/build/tasks/build.js
index fb0d8fe25..9019cc023 100644
--- a/build/tasks/build.js
+++ b/build/tasks/build.js
@@ -1,24 +1,24 @@
-// @ts-check
import gulp from "gulp";
import minifyCss from "gulp-clean-css";
import concatJs from "gulp-concat";
import concatCss from "gulp-concat-css";
-import prune from "gulp-prune";
+import { prune } from "gulp-prune";
import rev from "gulp-rev";
import minifyJs from "gulp-terser";
import { relative as relativePath } from "path";
import Bundler, { MergeRawConfigs, ValidateRawConfig } from "@userfrosting/gulp-bundle-assets";
import { readFileSync, writeFileSync } from "fs";
import { src } from "@userfrosting/vinyl-fs-vpath";
-import { Logger, vendorAssetsDir, sprinklesDir, sprinkles, sprinkleBundleFile, publicAssetsDir } from "./util.js";
+import { vendorAssetsDir, sprinklesDir, sprinkles, sprinkleBundleFile, publicAssetsDir } from "./util.js";
import gulpIf from "gulp-if";
+import { GulpLogLogger } from "@userfrosting/ts-log-adapter-gulplog";
import gulpSourcemaps from "gulp-sourcemaps";
/**
* Compiles frontend assets. Mapped to npm script "uf-bundle".
*/
export function build() {
- const log = new Logger(build.name);
+ const log = new GulpLogLogger(build.name);
// Build sources list
const sources = [];
@@ -35,6 +35,7 @@ export function build() {
sources.push("!**.php");
// Create bundle stream factories object
+ /** @type {import("@userfrosting/gulp-bundle-assets").Bundlers} */
const bundleBuilder = {
Scripts: (src, name) => {
return src
@@ -131,7 +132,7 @@ export function build() {
log.info("Finished writing results file.")
};
- rawConfig.Logger = new Logger(`${build.name} - @userfrosting/gulp-bundle-assets`);
+ rawConfig.Logger = new GulpLogLogger(`${build.name} - @userfrosting/gulp-bundle-assets`);
rawConfig.cwd = publicAssetsDir;
// Open stream
@@ -149,7 +150,7 @@ export function build() {
/**
* Used to filter to just styles and scripts.
- * @param {import("vinyl").NullFile} fs
+ * @param {import("vinyl")} fs
*/
function stylesAndScriptsFilter(fs) {
return scriptsFilter(fs) || stylesFilter(fs);
@@ -157,7 +158,7 @@ function stylesAndScriptsFilter(fs) {
/**
* Used to filter to just styles.
- * @param {import("vinyl").NullFile} fs
+ * @param {import("vinyl")} fs
*/
function stylesFilter(fs) {
return fs.extname === ".css";
@@ -165,7 +166,7 @@ function stylesFilter(fs) {
/**
* Used to filter to just scripts.
- * @param {import("vinyl").NullFile} fs
+ * @param {import("vinyl")} fs
*/
function scriptsFilter(fs) {
return fs.extname === ".js";
diff --git a/build/tasks/clean.js b/build/tasks/clean.js
index d7c6d3e25..628316cb8 100644
--- a/build/tasks/clean.js
+++ b/build/tasks/clean.js
@@ -1,13 +1,13 @@
-// @ts-check
import { sync as deleteSync } from "del";
-import { vendorAssetsDir, publicAssetsDir, Logger } from "./util.js";
+import { vendorAssetsDir, publicAssetsDir } from "./util.js";
+import { GulpLogLogger } from "@userfrosting/ts-log-adapter-gulplog";
/**
* Clean vendor and public asset folders.
- * @param {(err?) => {}} done Used to mark task completion.
+ * @param {(err?: unknown) => {}} done Used to mark task completion.
*/
export function clean(done) {
- const log = new Logger(clean.name);
+ const log = new GulpLogLogger(clean.name);
try {
log.info("Cleaning vendor assets...");
@@ -16,11 +16,12 @@ export function clean(done) {
log.info("Cleaning public assets...");
deleteSync(publicAssetsDir, { force: true })
- log.info("Finsihed cleaning public assets.");
+ log.info("Finished cleaning public assets.");
done();
}
catch (error) {
+ log.error("Completed with error");
done(error);
}
};
diff --git a/build/tasks/util.js b/build/tasks/util.js
index e43fc37e9..2bf0182b7 100644
--- a/build/tasks/util.js
+++ b/build/tasks/util.js
@@ -1,4 +1,3 @@
-// @ts-check
import gulplog from "gulplog";
import { readFileSync } from "fs";
@@ -13,93 +12,14 @@ export const vendorAssetsDir = `${rootDir}/app/assets/`;
export const logFile = `${rootDir}/app/logs/build.log`;
// Load sprinkles
+/** @type {string[]} */
let sprinkles;
try {
sprinkles = JSON.parse(readFileSync(sprinklesSchemaPath).toString()).base;
}
catch (error) {
- gulplog.info(sprinklesSchemaPath + " could not be loaded, does it exist?");
+ gulplog.error(sprinklesSchemaPath + " could not be loaded, does it exist?");
throw error;
}
export { sprinkles };
-
-/**
- * Log adapter for "ts-log" to "gulplog".
- */
-export class Logger {
- /**
- * @param {string} source
- */
- constructor(source) {
- this.source = source;
- }
-
- /**
- * Composes complete message to log.
- * @private
- * @param {(x: string) => void} logFunc Logging function.
- * @param {string} message Message to log.
- * @param {any[]} optionalParams Values to log, encoded with `JSON.stringify`.
- */
- log(logFunc, message, optionalParams) {
- const messageLines = message.split("\n");
-
- if (optionalParams.length > 0) {
- if (messageLines.length > 1) {
- messageLines.push(JSON.stringify(optionalParams));
- } else {
- messageLines[0] = `${messageLines[0]} ${JSON.stringify(optionalParams)}`;
- }
- }
-
- for (const messageLine of messageLines) {
- logFunc(`${this.source}: ${messageLine}`)
- }
- }
-
- /**
- * Debug log level.
- * @param {string} message Message to log.
- * @param {...any} optionalParams Values to log, encoded with `JSON.stringify`.
- */
- debug(message, ...optionalParams) {
- this.log(gulplog.debug, message, optionalParams);
- }
-
- /**
- * Trace log level.
- * @param {string} message Message to log.
- * @param {...any} optionalParams Values to log, encoded with `JSON.stringify`.
- */
- trace(message, ...optionalParams) {
- this.log(gulplog.debug, message, optionalParams);
- }
-
- /**
- * "Standard" log level.
- * @param {string} message Message to log.
- * @param {...any} optionalParams Values to log, encoded with `JSON.stringify`.
- */
- info(message, ...optionalParams) {
- this.log(gulplog.info, message, optionalParams);
- }
-
- /**
- * Warning log level.
- * @param {string} message Message to log.
- * @param {...any} optionalParams Values to log, encoded with `JSON.stringify`.
- */
- warn(message, ...optionalParams) {
- this.log(gulplog.warn, message, optionalParams);
- }
-
- /**
- * Error log level.
- * @param {string} message Message to log.
- * @param {...any} optionalParams Values to log, encoded with `JSON.stringify`.
- */
- error(message, ...optionalParams) {
- this.log(gulplog.error, message, optionalParams);
- }
-}
diff --git a/build/tsconfig.json b/build/tsconfig.json
new file mode 100644
index 000000000..590f675f4
--- /dev/null
+++ b/build/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "$schema": "http://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "module": "es2020",
+ "moduleResolution": "node",
+ "target": "es2020",
+ "noEmit": true,
+ "allowSyntheticDefaultImports": true
+ }
+}
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 34b3c18e8..0b4a6edb3 100755
--- a/composer.json
+++ b/composer.json
@@ -24,16 +24,16 @@
"vendor-dir": "app/vendor"
},
"require": {
- "php": ">=7.2",
+ "php": "^7.3 | ^8.0",
"ext-gd": "*",
"composer/installers": "^1.4.0",
- "userfrosting/uniformresourcelocator": "~4.5.0",
- "symfony/console": "^4.3",
+ "userfrosting/framework": "^4.6",
+ "symfony/console": "^5.1",
"wikimedia/composer-merge-plugin": "^2.1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.13",
- "phpunit/phpunit": "^7.5 | ^8.5",
+ "phpunit/phpunit": "^9.5",
"mockery/mockery": "^1.2",
"league/factory-muffin": "^3.0",
"league/factory-muffin-faker": "^2.0"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index 161175b00..0b1d42483 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,30 +1,21 @@
-
-
-
- app/tests/Unit
- app/sprinkles/*/tests/Unit
-
-
- app/sprinkles/*/tests/Integration
-
-
-
-
-
-
-
- app/sprinkles/*/src/
- app/system/
-
-
+
+
+
+ app/sprinkles/*/src/
+ app/system/
+
+
+
+
+ app/tests/Unit
+ app/sprinkles/*/tests/Unit
+
+
+ app/sprinkles/*/tests/Integration
+
+
+
+
+
diff --git a/public/index.php b/public/index.php
index a26563f20..e5dfb4537 100755
--- a/public/index.php
+++ b/public/index.php
@@ -17,6 +17,12 @@
// First off, we'll grab the Composer dependencies
require_once __DIR__ . '/../app/vendor/autoload.php';
+// Workaround to get php built-in server to access assets
+// @see : https://github.com/slimphp/Slim/issues/359#issuecomment-363076423
+if (PHP_SAPI == 'cli-server') {
+ $_SERVER['SCRIPT_NAME'] = '/index.php';
+}
+
use UserFrosting\System\UserFrosting;
$uf = new UserFrosting();
diff --git a/vagrant/after.sh b/vagrant/after.sh
index 1c741166c..2145f4750 100644
--- a/vagrant/after.sh
+++ b/vagrant/after.sh
@@ -14,14 +14,9 @@ npm cache clean -f
npm install -g n
n -q lts
-# Ensuite PHP 7.4 is used (UF doesn't support PHP 8 yet...)
-echo "\n\n >> Forcing PHP 7.4 in CLI\n"
-sudo update-alternatives --set php /usr/bin/php7.4
-
# Ensure composer deps are installed
echo "\n\n >> Installating Composer\n"
cd ${BASE_PATH}
-composer self-update --1
composer install
# Setup .env