diff --git a/.github/workflows/visual-diff.yml b/.github/workflows/visual-diff.yml index 40733ef3d..192ba0ff1 100644 --- a/.github/workflows/visual-diff.yml +++ b/.github/workflows/visual-diff.yml @@ -29,6 +29,9 @@ jobs: visual-diff: # The type of runner that the job will run on runs-on: windows-latest + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -51,20 +54,20 @@ jobs: run: npx playwright install # Take images - - name: Take screenshots for comparison [push|main] + - name: Take screenshots for baseline [push|main] if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} id: 'visual_diff_all' run: npm run screenshots:all - # On pushes to main, upload images for comparison against pull_request runs - - name: Upload comparison screenshots [push|main] + # On pushes to main, upload images for baseline against pull_request runs + - name: Upload baseline screenshots [push|main] if: ${{ github.event_name == 'push' && github.ref_name == 'main' }} uses: actions/upload-artifact@v4 with: - name: visual_diff_comparison_shapshots + name: visual_diff_baseline_shapshots path: ./integration/visual-diff/screenshots/updated - # On pull requests into main, download images for comparison + # On pull requests into main, download images for baseline - name: Take screenshots [pull_request] if: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' }} id: 'visual_diff_light' @@ -78,9 +81,50 @@ jobs: name: visual_diff_pull_request_shapshots-${{ github.sha }} path: ./integration/visual-diff/screenshots/updated - - name: Download comparison screenshots [pull_request] + - name: Download baseline screenshots [pull_request] if: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' }} uses: actions/upload-artifact@v4 with: - name: visual_diff_comparison_shapshots - path: ./integration/visual-diff/screenshots/comparison + name: visual_diff_baseline_shapshots + path: ./integration/visual-diff/screenshots/baseline + + - name: Download baseline screenshots [pull_request] + if: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' }} + uses: actions/upload-artifact@v4 + with: + name: visual_diff_baseline_shapshots + path: ./integration/visual-diff/screenshots/baseline + + # populate ./integration/visual-diff/screenshots/ with the contents of the diff site + - name: Compare Screenshots and Generate Site + run: npm run compare -w @microsoft/atlas-integration + + # Ready for Parcel to build the thing + - name: Build diff report site + run: npm run build-report -w @microsoft/atlas-integration + + # Temporarily upload screenshots for pull requests, just to verify they are as we'd expect + - name: Upload report folder [pull_request] + if: ${{ github.event_name == 'pull_request' && github.base_ref == 'main' }} + uses: actions/upload-artifact@v4 + with: + name: visual-diff-screenshots-${{ github.event.number }} + path: ./integration/dist + + - name: Run GH Action Script + run: npm run action -w @microsoft/atlas-integration + + # # Pages setup and upload + # - name: Setup Pages + # uses: actions/configure-pages@v5 + + # - name: Upload artifact + # uses: actions/upload-pages-artifact@v3 + # with: + # name: github-pages + # # Upload entire repository + # path: './integration/visual-diff/screenshots/' + + # - name: Deploy to GitHub Pages + # id: deployment + # uses: actions/deploy-pages@v4 diff --git a/css/src/components/button.scss b/css/src/components/button.scss index 2b1f6e0f5..d26b6b5d9 100644 --- a/css/src/components/button.scss +++ b/css/src/components/button.scss @@ -27,6 +27,8 @@ $button-icon-spacing: 0.375em !default; $button-font-weight: $weight-semibold !default; .button { + font-size: 50px; + @include control; @include unselectable; diff --git a/integration/package.json b/integration/package.json index 38b4afc2f..a3b1b0d7d 100644 --- a/integration/package.json +++ b/integration/package.json @@ -4,9 +4,10 @@ "private": true, "description": "", "scripts": { + "action": "wireit", "codegen": "playwright codegen localhost:1111", - "compare": "node \"./tasks/dist/compare.js\" ", - "compile-tasks": "tsc -p \"./tasks/tsconfig.json\"", + "compare": "wireit", + "compile-tasks": "wireit", "test": "playwright test --config=integration-tests.config.ts", "test:debug": "playwright test --debug --config=integration-tests.config.ts", "screenshots:all": "cross-env FULL_DIFF=true playwright test --config=visual-diff.config.ts", @@ -18,21 +19,41 @@ "serve-report": "parcel \"./visual-diff/screenshots/*.html\" --port 7777 --open Chrome --no-cache", "build-report": "parcel build \"./visual-diff/screenshots/*.html\"" }, + "wireit": { + "compare": { + "command": "node \"./tasks/dist/compare.js\" ", + "dependencies": [ + "compile-tasks" + ] + }, + "compile-tasks": { + "command": "tsc -p \"./tasks/tsconfig.json\"" + }, + "action": { + "command": "node \"./tasks/dist/action.js\" ", + "dependencies": [ + "compile-tasks" + ] + } + }, "author": "Microsoft Corporation", "license": "ISC", "devDependencies": { + "@actions/core": "1.11.1", "@axe-core/playwright": "^4.7.3", "@playwright/test": "^1.35.1", "@types/normalize-path": "^3.0.0", "@types/pixelmatch": "^5.2.4", + "@types/fs-extra": "^11.0.4", "@types/pngjs": "6.0.1", "cross-env": "^7.0.3", "execa": "^7.1.1", "fs-extra": "^11.1.1", - "glob": "^10.3.1", + "glob": "^11.0.0", "normalize-path": "^3.0.0", "parcel": "^2.12.0", "pixelmatch": "^5.3.0", - "pngjs": "^7.0.0" + "pngjs": "^7.0.0", + "wireit": "0.14.9" } } diff --git a/integration/tasks/action.ts b/integration/tasks/action.ts new file mode 100644 index 000000000..3eea6434d --- /dev/null +++ b/integration/tasks/action.ts @@ -0,0 +1,6 @@ +// https://github.com/actions/toolkit/tree/main +//https://github.com/actions/toolkit/tree/main/packages/artifact +// https://www.npmjs.com/package/@actions/github +import * as core from '@actions/core'; + +core.notice('Something happened that you might want to know about.', {}); diff --git a/integration/tasks/compare.ts b/integration/tasks/compare.ts index fb6eaa57c..87394a06a 100644 --- a/integration/tasks/compare.ts +++ b/integration/tasks/compare.ts @@ -1,10 +1,9 @@ // @ts-check -import { emptyDir, ensureDir, readFile, writeFile, writeJSON } from 'fs-extra'; +import { emptyDir, ensureDir, PathLike, readFile, writeFile, writeJSON } from 'fs-extra'; import { basename, dirname, join, resolve, sep } from 'path'; import * as pixelmatch from 'pixelmatch'; import { PNG } from 'pngjs'; -import { promisify } from 'util'; import { baselineDirectory, diffDirectory, @@ -12,7 +11,7 @@ import { screenshotsRoot } from './locations'; import { generateHtmlReport } from './report'; -export const glob = promisify(require('glob')); +import { glob } from 'glob'; export const diffExt = '.diff.png'; /** @@ -84,12 +83,13 @@ async function compare( emptyDir(outDir) ]); - const sourceMap = sourceKeys.reduce( - (m: { set: (arg0: any, arg1: string) => any }, f: any) => m.set(f, join(sourceDir, f)), + const sourceMap: Map = sourceKeys.reduce( + (m: Map, f: any) => m.set(f, join(sourceDir, f)), new Map() ); - const targetMap = targetKeys.reduce( - (m: { set: (arg0: any, arg1: string) => any }, f: any) => m.set(f, join(targetDir, f)), + + const targetMap: Map = targetKeys.reduce( + (m: Map, f: any) => m.set(f, join(targetDir, f)), new Map() ); const manifest: VisualDiffReportManifest = []; @@ -100,12 +100,12 @@ async function compare( continue; } - const targetFilename = targetMap.get(key); + const targetFilename = targetMap.get(key) || ''; const [source, target] = await Promise.all([ readFile(sourceFilename), - readFile(targetFilename) + readFile(targetFilename as PathLike) ]); - const diff = await compareBuffers(source, target); + const diff = await compareBuffers(source, target as Buffer); if (diff.pixelCount === 0) { continue; diff --git a/integration/tasks/tsconfig.json b/integration/tasks/tsconfig.json index 465979647..e068943dc 100644 --- a/integration/tasks/tsconfig.json +++ b/integration/tasks/tsconfig.json @@ -2,6 +2,7 @@ "$schema": "https://json.schemastore.org/tsconfig", "compilerOptions": { /*NOTE: This file is used only for linting. */ + "skipLibCheck": true, /* Basic Options */ "target": "es2021", "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, diff --git a/package-lock.json b/package-lock.json index 5d2145184..e7eda0641 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ }, "css": { "name": "@microsoft/atlas-css", - "version": "3.57.1", + "version": "3.58.0", "license": "MIT", "devDependencies": { "@microsoft/stylelint-config-atlas": "4.1.0", @@ -410,19 +410,31 @@ "version": "1.8.0", "license": "ISC", "devDependencies": { + "@actions/core": "1.11.1", "@axe-core/playwright": "^4.7.3", "@playwright/test": "^1.35.1", + "@types/fs-extra": "^11.0.4", "@types/normalize-path": "^3.0.0", "@types/pixelmatch": "^5.2.4", "@types/pngjs": "6.0.1", "cross-env": "^7.0.3", "execa": "^7.1.1", "fs-extra": "^11.1.1", - "glob": "^10.3.1", + "glob": "^11.0.0", "normalize-path": "^3.0.0", "parcel": "^2.12.0", "pixelmatch": "^5.3.0", - "pngjs": "^7.0.0" + "pngjs": "^7.0.0", + "wireit": "0.14.9" + } + }, + "integration/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" } }, "integration/node_modules/execa": { @@ -471,6 +483,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "integration/node_modules/glob": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "integration/node_modules/human-signals": { "version": "4.3.1", "dev": true, @@ -490,6 +525,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "integration/node_modules/jackspeak": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "integration/node_modules/lru-cache": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", + "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "dev": true, + "engines": { + "node": "20 || >=22" + } + }, "integration/node_modules/mimic-fn": { "version": "4.0.0", "dev": true, @@ -501,6 +560,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "integration/node_modules/minimatch": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "integration/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "integration/node_modules/npm-run-path": { "version": "5.1.0", "dev": true, @@ -540,6 +623,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "integration/node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dev": true, + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "integration/node_modules/pngjs": { "version": "7.0.0", "dev": true, @@ -561,7 +660,7 @@ }, "js": { "name": "@microsoft/atlas-js", - "version": "1.13.1", + "version": "1.14.0", "license": "MIT", "devDependencies": { "eslint": "^8.43.0", @@ -591,6 +690,41 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dev": true, + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dev": true, + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dev": true, + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "dev": true + }, "node_modules/@axe-core/playwright": { "version": "4.7.3", "dev": true, @@ -1091,6 +1225,15 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@glideapps/ts-necessities": { "version": "2.1.3", "dev": true, @@ -3071,6 +3214,16 @@ "node": ">=10.13.0" } }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/glob": { "version": "8.1.0", "dev": true, @@ -3098,6 +3251,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/minimatch": { "version": "5.1.2", "dev": true, @@ -7900,6 +8062,12 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/pako": { "version": "1.0.11", "dev": true, @@ -10418,6 +10586,18 @@ "dev": true, "license": "MIT" }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "dev": true, + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/unicode-properties": { "version": "1.4.1", "dev": true, @@ -11320,13 +11500,13 @@ }, "site": { "name": "@microsoft/atlas-site", - "version": "0.59.0", + "version": "0.59.1", "license": "MIT", "dependencies": { "@microsoft/atlas-js": "^1.12.0" }, "devDependencies": { - "@microsoft/atlas-css": "^3.57.0", + "@microsoft/atlas-css": "^3.58.0", "@microsoft/parcel-transformer-markdown-html": "^2.7.0", "@parcel/transformer-sass": "^2.12.0", "@typescript-eslint/eslint-plugin": "^5.60.1",