Skip to content

Commit

Permalink
Merge branch 'gsoc/visual-testing' into vt-ghaction
Browse files Browse the repository at this point in the history
  • Loading branch information
KshitijThareja authored Aug 6, 2024
2 parents 19654cf + 9e45f45 commit 0821b88
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 121 deletions.
3 changes: 0 additions & 3 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ esLintConfig.globals = {
context: true,
puppeteerConfig: true,
jestPuppeteer: true,
describe: "readonly",
describeUnit: "readonly",
describeVisual: "readonly"
};

module.exports = esLintConfig;
1 change: 1 addition & 0 deletions jest.conf/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const moduleNameMapper = {
module.exports = {
rootDir: path.resolve(__dirname, '..'),
moduleFileExtensions: ['js', 'json', 'vue'],
testNamePattern: '^(?!.*\\[Visual\\])',
moduleNameMapper,
testEnvironment: 'jsdom',
testEnvironmentOptions: {
Expand Down
13 changes: 9 additions & 4 deletions jest.conf/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import VueRouter from 'vue-router';
import VueIntl from 'vue-intl';
import VueCompositionAPI from '@vue/composition-api';
import KThemePlugin from '../lib/KThemePlugin';
import { describeUnit, describeVisual } from './testUtils';

global.beforeEach(() => {
return new Promise(resolve => {
Expand All @@ -29,6 +28,15 @@ global.afterEach(() => {
});
});

// Configure special test blocks for visual tests
global.describe.visual = (name, fn) => {
global.describe(`[Visual] ${name}`, fn);
};

global.it.visual = (name, fn) => {
global.it(`[Visual] ${name}`, fn);
};

// Register Vue plugins and components
Vue.use(VueRouter);
Vue.use(VueCompositionAPI);
Expand Down Expand Up @@ -56,6 +64,3 @@ global.flushPromises = function flushPromises() {
setImmediate(resolve);
});
};

global.describeUnit = describeUnit;
global.describeVisual = describeVisual;
50 changes: 0 additions & 50 deletions jest.conf/testUtils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { setMedia } from 'mock-match-media';

const percySnapshot = require('@percy/puppeteer');

export const resizeWindow = (width, height = 768) => {
window.innerWidth = width;
window.innerHeight = height;
Expand All @@ -20,51 +18,3 @@ export const testAfterResize = testFunction => {
};
animationFrameId = requestAnimationFrame(assertAfterResize);
};

export async function renderComponent(page, component, props) {
await page.evaluate(
({ component, props }) => {
window.postMessage(
{
type: 'RENDER_COMPONENT',
component: component,
props: props,
},
'*'
);
},
{ component, props }
);
await page.waitForSelector('#testing-playground');

const isComponentRendered = await page.evaluate(() => {
const testing_playground = document.querySelector('#testing-playground');
return testing_playground && testing_playground.children.length > 0;
});

if (!isComponentRendered) {
// eslint-disable-next-line no-console
console.error('Component did not render in the testing playground');
}
}

export async function takeSnapshot(page, name) {
if (process.env.TEST_TYPE == 'visual') {
await percySnapshot(page, name);
} else {
// eslint-disable-next-line no-console
console.log(`Skipping Percy snapshot: ${name}`);
}
}

export function describeUnit(name, fn) {
if (process.env.TEST_TYPE != 'visual') {
describe(name, fn);
}
}

export function describeVisual(name, fn) {
if (process.env.TEST_TYPE == 'visual') {
describe(name, fn);
}
}
1 change: 1 addition & 0 deletions jest.conf/visual.index.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ module.exports = async () => {
preset: 'jest-puppeteer',
testTimeout: 50000,
moduleFileExtensions: ['js', 'json', 'vue'],
testNamePattern: '\\[Visual\\]',
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|css)$': path.resolve(
__dirname,
Expand Down
5 changes: 5 additions & 0 deletions jest.conf/visual.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ import { percySnapshot } from '@percy/puppeteer';
// Set the test type to visual
process.env.TEST_TYPE = 'visual';

const TESTING_PLAYGROUND_URL = 'http://localhost:4000/testing-playground';
global.percySnapshot = percySnapshot;

global.beforeAll(async () => {
await page.goto(TESTING_PLAYGROUND_URL, { waitUntil: 'networkidle2' });
});
47 changes: 47 additions & 0 deletions jest.conf/visual.testUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import percySnapshot from '@percy/puppeteer';

export async function renderComponent(component, props) {
const beforeRenderState = await page.evaluate(() => {
const testing_playground = document.querySelector('#testing-playground');
return testing_playground ? testing_playground.innerHTML : '';
});

await page.evaluate(
({ component, props }) => {
window.postMessage(
{
type: 'RENDER_COMPONENT',
component: component,
props: props,
},
'*'
);
},
{ component, props }
);
await page.waitForSelector('#testing-playground');

// Wait until the innerHTML of the testing playground changes, indicating that the component has been rendered.
await page.waitForFunction(
initialState => {
const testing_playground = document.querySelector('#testing-playground');
return testing_playground && testing_playground.innerHTML !== initialState;
},
{},
beforeRenderState
);

// Check if the component has been rendered by comparing the initial state with the current state.
const isComponentRendered = await page.evaluate(initialState => {
const testing_playground = document.querySelector('#testing-playground');
return testing_playground && testing_playground.innerHTML !== initialState;
}, beforeRenderState);

global.expect(isComponentRendered).toBe(true);
}

export async function takeSnapshot(name) {
if (process.env.TEST_TYPE == 'visual') {
await percySnapshot(page, name);
}
}
18 changes: 7 additions & 11 deletions lib/buttons-and-links/__tests__/KButton.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { shallowMount } from '@vue/test-utils';
import KButton from '../KButton.vue';
import { renderComponent, takeSnapshot } from '../../../jest.conf/testUtils';
import { renderComponent, takeSnapshot } from '../../../jest.conf/visual.testUtils';

describe('KButton', () => {
describeUnit('icon related props', () => {
describe('icon related props', () => {
it('should render an icon before the text with the icon string passed to the `icon` prop', () => {
const wrapper = shallowMount(KButton, {
propsData: {
Expand All @@ -30,7 +30,7 @@ describe('KButton', () => {
});
});

describeUnit('text prop and slots', () => {
describe('text prop and slots', () => {
it('should render the text prop if nothing is in the default slot', () => {
const wrapper = shallowMount(KButton, {
propsData: {
Expand All @@ -54,7 +54,7 @@ describe('KButton', () => {
});
});

describeUnit('event handling', () => {
describe('event handling', () => {
it('should emit a click event when clicked', () => {
const wrapper = shallowMount(KButton, {
propsData: {
Expand All @@ -66,14 +66,10 @@ describe('KButton', () => {
});
});

describeVisual('KButton Visual Tests', () => {
beforeAll(async () => {
await page.goto('http://localhost:4000/testing-playground', { waitUntil: 'networkidle2' });
});

describe.visual('KButton Visual Tests', () => {
it('renders correctly with default props', async () => {
await renderComponent(page, 'KButton', { text: 'Test Button' });
await takeSnapshot(page, 'KButton - Default');
await renderComponent('KButton', { text: 'Test Button' });
await takeSnapshot('KButton - Default');
});
});
});
55 changes: 2 additions & 53 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5778,7 +5778,7 @@ dotenv@^9.0.2:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-9.0.2.tgz#dacc20160935a37dea6364aa1bef819fb9b6ab05"
integrity sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==

duplexer@^0.1.2, duplexer@~0.1.1:
duplexer@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
Expand Down Expand Up @@ -6338,19 +6338,6 @@ etag@^1.8.1, etag@~1.8.1:
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==

event-stream@=3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==
dependencies:
duplexer "~0.1.1"
from "~0"
map-stream "~0.1.0"
pause-stream "0.0.11"
split "0.3"
stream-combiner "~0.0.4"
through "~2.3.1"

eventemitter3@^4.0.0:
version "4.0.7"
resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz"
Expand Down Expand Up @@ -6890,11 +6877,6 @@ from2@^2.1.0:
inherits "^2.0.1"
readable-stream "^2.0.0"

from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==

fs-exists-sync@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
Expand Down Expand Up @@ -9604,11 +9586,6 @@ map-obj@^4.0.0:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==

map-stream@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==

map-values@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz"
Expand Down Expand Up @@ -10881,13 +10858,6 @@ path-type@^4.0.0:
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==

[email protected]:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
dependencies:
through "~2.3"

pbkdf2@^3.0.3, pbkdf2@^3.1.2:
version "3.1.2"
resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz"
Expand Down Expand Up @@ -12083,13 +12053,6 @@ prr@~1.0.1:
resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=

ps-tree@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
dependencies:
event-stream "=3.3.4"

pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz"
Expand Down Expand Up @@ -13508,13 +13471,6 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"

[email protected]:
version "0.3.3"
resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==
dependencies:
through "2"

sprintf-js@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
Expand Down Expand Up @@ -13620,13 +13576,6 @@ stream-browserify@^2.0.1:
inherits "~2.0.1"
readable-stream "^2.0.2"

stream-combiner@~0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==
dependencies:
duplexer "~0.1.1"

stream-each@^1.1.0:
version "1.2.3"
resolved "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz"
Expand Down Expand Up @@ -14254,7 +14203,7 @@ through2@^2.0.0:
readable-stream "~2.3.6"
xtend "~4.0.1"

through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1:
through@^2.3.6, through@^2.3.8:
version "2.3.8"
resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
Expand Down

0 comments on commit 0821b88

Please sign in to comment.