## Differencify specific methods |Method|Arguments|description| |------|---------|-----------| |`launchBrowser`/`launch`|`Object` [puppeteer.launch options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)|Launches a browser instance| |`connectBrowser`/`connect`|`Object` [puppeteer.connect options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerconnectoptions)|Attaches to an existing browser instance| |`init`|[TestOptions](https://github.com/NimaSoroush/differencify#testoptions)|Configure and prepare differencify to operate based on `TestOptions`| |`cleanup`|no argument|Closes browser instance if it is not closed already| ## Additional methods on top of Puppeteer's Page class |Method|Arguments|description| |------|---------|-----------| |`toMatchSnapshot`|`image` or
`image, callback` or
` callback` | Pass an image object to compare it to the snapshot. Optionally, pass a callback to receive [details from the comparison](#detailed-result-information). Alternatively, just pass a callback to receive details of the snapshot currently in the chain. | |`result`|`Object`|A function that returns response object of previous step when on chained mode| |`launch`|`Object` [puppeteer.launch options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)|launches new browser and returns browser object| |`connect`|`Object` [puppeteer.connect options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerconnectoptions)|Attaches to an existing browser instance and returns browser object| |`freezeImage`|`string`|Selector name of a `` tag containing animated image to be freezed before taking screenshot| |`mockRequests`|`Object`|Runs chrome headless browser in isolation using [Mockeer](https://github.com/NimaSoroush/Mockeer)| ## Puppeteer methods Differencify matches [Puppeteer](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md)'s API completely. Here are some examples of how to use it. ## Simple ```js (async () => { await differencify.launchBrowser(); await differencify .init() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://github.com/NimaSoroush/differencify') .waitFor(1000) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); await differencify.cleanup(); })(); ``` In this example, differencify will launch a browser instance and continues on others steps ## Simple unchained ```js (async () => { await differencify.launchBrowser(); const target = differencify.init({ testName: 'Differencify simple unchained', chain: false }); const page = await target.newPage(); await page.goto('https://github.com/NimaSoroush/differencify'); await page.setViewport({ width: 1600, height: 1200 }); await page.waitFor(1000); const image = await page.screenshot(); const result = await target.toMatchSnapshot(image); await page.close(); console.log(result) // True or False await differencify.cleanup(); })(); ``` In this example, differencify will launch a browser instance and unchain steps. `differencify.init().newPage()` will return a `puppeteer` page instance which with all supported methods on that [page](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page) ## Launch new browser per test ```js (async () => { await differencify .init() .launch() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://github.com/NimaSoroush/differencify') .waitFor(1000) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); })(); ``` In this example, differencify will launch a browser instance and continues on others steps and on `close()` it will close both page and browser ## Launch new browser per test when unchained ```js (async () => { const target = differencify.init({ testName: 'Differencify simple unchained', chain: false }); await target.launch(); const page = await target.newPage(); await page.goto('https://github.com/NimaSoroush/differencify'); await page.setViewport({ width: 1600, height: 1200 }); await page.waitFor(1000); const image = await page.screenshot(); const result = await target.toMatchSnapshot(image); await page.close(); await target.close(); console.log(result) // True or False })(); ``` In this example, differencify will launch a browser instance and unchain steps. `differencify.init().newPage()` will return a `puppeteer` page instance which with all supported methods on that [page](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page) ## Share browser ```js (async () => { await differencify.launchBrowser(); await differencify .init({ testName: 'test1' }) .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://github.com/NimaSoroush/differencify') .wait(3000) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); await differencify .init({ testName: 'test2' }) .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://github.com/NimaSoroush/differencify') .wait(3000) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); await differencify.cleanup(); })(); ``` In this example, differencify will launch a browser instance and share same browser instance with all following tests and on `cleanup()` it will close the browser ## Using result function ```js (async () => { await differencify .init() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://github.com/NimaSoroush/differencify') .title() .result((title) => { console.log(title) }) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); })(); ``` In this example, after calling `result` function it will return the previous step result as an object. ## Detailed Result Information For programmatic use cases where more information is required than simply whether or not a test passed, a callback function may be passed to `toMatchSnapshot` which will be invoked after the test and passed additional details. ```js (async () => { await differencify .init() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://github.com/NimaSoroush/differencify') .screenshot() .toMatchSnapshot((resultDetail) => { console.log(resultDetail); /* Example output: { testConfig: { chain: false, testNameProvided: true, testName: 'TestName', 'testId': 2, 'isUpdate': false, 'isJest': false, 'newWindow': true }, testResult: { diffPath: '/parent/__image_snapshots__/__differencified_output__/test.differencified.png', matched: false, diffPercent: 0.02, distance: 0, snapshotPath: '/parent/__image_snapshots__/test.snap.png', } } */ }) .close() .end(); })(); ``` Similarly, the callback may be passed as a second argument when unchained: ```js (async () => { const target = differencify.init({ chain: false }); await target.launch(); const page = await target.newPage(); await page.goto('https://github.com/NimaSoroush/differencify'); await page.setViewport({ width: 1600, height: 1200 }); await page.waitFor(1000); const image = await page.screenshot(); await target.toMatchSnapshot(image, (resultDetail) => { console.log(resultDetail); /* Example output: { testConfig: { chain: false, testNameProvided: true, testName: 'TestName', 'testId': 2, 'isUpdate': false, 'isJest': false, 'newWindow': true }, testResult: { diffPath: '/parent/__image_snapshots__/__differencified_output__/test.differencified.png', matched: false, diffPercent: 0.02, distance: 0, snapshotPath: '/parent/__image_snapshots__/test.snap.png', } } */ }); await page.close(); await target.close(); })(); ``` ## Context switching when chained ```js (async () => { await differencify .init() .newPage() .tracing .start({ path: 'trace.json' }) .page .setViewport({ width: 1600, height: 1200 }) .goto('https://nimasoroush.github.io/differencify/') .waitFor(1000) .keyboard .press('Space') .tracing .stop() .page .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); })(); ``` In this example, differencify will launch a browser instance and opens a new tab and starts tracing, goto url, mouse click, stop tracing and finally closes the tab. All steps are running on `page` context unless you switch to one of the following context: ``` 'page', 'keyboard', 'mouse', 'touchscreen', 'tracing', ``` If you do so, you need to come back to `page` context by calling it. ## Calling Puppeteer's specific functions when chained ```js (async () => { await differencify .init() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://nimasoroush.github.io/differencify/') .on('console', msg => { for (let i = 0; i < msg.args.length; ++i) { console.log(`${i}: ${msg.args[i]}`); // JSHandle:hello } }); .evaluate(() => console.log('hello', 5, { foo: 'bar' })) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); })(); ``` In this example, differencify will call `on()` method of Puppeteer asynchronously. same logic should apply for other specific methods of Puppeteer like: ```js on('dialog', async dialog => { console.log(dialog.message()) }; evaluate(() => console.log('hello', 5, {foo: 'bar'})); $$eval('div', divs => divs.length); evaluateHandle(() => document.body); ... ``` Another example ```js (async () => { await differencify .init() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://nimasoroush.github.io/differencify/') .on('dialog', async (dialog) => { console.log(dialog.message()); // 1 await dialog.dismiss(); }) .evaluate(() => alert('1')) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result) // True or False }) .close() .end(); })(); ``` ## Continue on chained object ```js (async () => { await differencify .init() .newPage() .goto('https://github.com/NimaSoroush/differencify') .mainFrame() .then .url() .result((url) => { console.log(url); // https://github.com/NimaSoroush/differencify }) .screenshot() .toMatchSnapshot() .result((result) => { console.log(result); // True or False }) .close() .end(); })(); ``` In this example, differencify will get the `mainFrame` of page and continues by `then` to get `childFrame` of that frame and finally prints the `url` of the childFrame. ## Multiple toMatchSnapshot on chained object ```js (async () => { await differencify .init() .newPage() .goto('https://nimasoroush.github.io/differencify/') .screenshot() .toMatchSnapshot() .result((result) => { console.log(result); // True or False }) .goto('https://nimasoroush.github.io/differencify/') .screenshot() .toMatchSnapshot() .result((result) => { console.log(result); // True or False }) .close() .end(); })(); ``` In this example, differencify will got to different pages and compare screenshots with reference screenshots. ## Multiple toMatchSnapshot when unchained ```js (async () => { const target = differencify.init({ chain: false }); const page = await target.newPage(); await page.goto('https://nimasoroush.github.io/differencify/'); await page.setViewport({ width: 1600, height: 1200 }); await page.waitFor(1000); const image = await page.screenshot(); const result = await target.toMatchSnapshot(image); await page.goto('https://github.com/NimaSoroush/differencify#about'); await page.setViewport({ width: 1600, height: 1200 }); await page.waitFor(1000); const image2 = await page.screenshot(); const result2 = await target.toMatchSnapshot(image2); await page.close(); console.log(result); // True or False console.log(result2); // True or False })(); ``` In this example, differencify will got to different pages and compare screenshots with reference screenshots. ## Custom test path ```js (async () => { const differencify = new Differencify({ imageSnapshotPath: './custom_test_path' }); const target = differencify.init({ chain: false }); await target.launch(); const page = await target.newPage(); await page.setViewport({ width: 1600, height: 1200 }); await page.goto('http://example.com/'); await page.waitFor(1000); const image = await page.screenshot(); const result = await target.toMatchSnapshot(image); await page.close(); console.log(result); // True or False console.log(result2); // True or False })(); ``` In this example, you can specify the custom path for storing images. ## Freezing an image ```js (async () => { await differencify .init() .newPage() .setViewport({ width: 1600, height: 1200 }) .goto('https://i.giphy.com/media/xTiTnoUnHxVaaVNWhO/giphy.webp') .waitFor('body > img') .freezeImage('body > img') .screenshot() .toMatchSnapshot() .close() .end(); })(); ``` In this example, you can freeze an image by specifying the selector path. ## Page interactions ```js (async () => { await differencify .init() .newPage() .goto('https://nimasoroush.github.io/differencify/') .waitFor(2000) .click('[id=js-repo-pjax-container] div nav a') .waitFor(2000) .url() .result((url) => { expect(url).toContain('pulls'); }) .screenshot() .toMatchSnapshot() .close() .end(); })(); ``` In this example an element is clicked on that performs navigation, and the url checked to see it has been successful.