diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ae50f79..efb97fb 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -6,11 +6,24 @@ on: types: [opened, reopened, synchronize] jobs: - build-and-test: + build: runs-on: ubuntu-latest - env: - FOSSA_API_KEY: ${{ secrets.FOSSA_API_KEY }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v3.1.1 + + - name: Install dependencies + run: npm install + + - name: Build + run: npm run build + + test: + runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -24,12 +37,30 @@ jobs: - name: Test run: npm run test + continue-on-error: true + + - name: Archive test artifacst + uses: actions/upload-artifact@v3 + with: + name: test images + path: | + test/e2e/**/*.png - - name: Build - run: npm run build + + license: + runs-on: ubuntu-latest + + env: + FOSSA_API_KEY: ${{ secrets.FOSSA_API_KEY }} + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 - name: Run Fossa and upload data if: env.FOSSA_API_KEY != '' uses: fossa-contrib/fossa-action@v1 with: fossa-api-key: ${{ env.FOSSA_API_KEY }} + diff --git a/site/jest-function-plot.html b/site/jest-function-plot.html index bba77d0..898dc3f 100644 --- a/site/jest-function-plot.html +++ b/site/jest-function-plot.html @@ -4,6 +4,13 @@ Function Plot +
diff --git a/src/chart.ts b/src/chart.ts index 46c97d5..e542279 100644 --- a/src/chart.ts +++ b/src/chart.ts @@ -534,7 +534,9 @@ export class Chart extends EventEmitter.EventEmitter { const graphs = content .merge(contentEnter) .selectAll(':scope > g.graph') - .data((d: FunctionPlotOptions) => d.data.map(datumDefaults)) + .data((d: FunctionPlotOptions) => { + return d.data.map(datumDefaults) + }) // enter const graphsEnter = graphs.enter().append('g').attr('class', 'graph') @@ -548,6 +550,9 @@ export class Chart extends EventEmitter.EventEmitter { selection.call(globals.graphTypes[d.graphType](self)) selection.call(helpers(self)) }) + + // exit + graphs.exit().remove() } buildZoomHelper() { diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-evaluate-with-multiple-samples-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-evaluate-with-multiple-samples-1-snap.png new file mode 100644 index 0000000..16306ec Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-evaluate-with-multiple-samples-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-a-grid-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-a-grid-1-snap.png new file mode 100644 index 0000000..260cd41 Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-a-grid-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-an-x-2-graph-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-an-x-2-graph-1-snap.png index 34e83aa..4a7508a 100644 Binary files a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-an-x-2-graph-1-snap.png and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-an-x-2-graph-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-annotations-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-annotations-1-snap.png new file mode 100644 index 0000000..6f5c2a1 Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-annotations-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-closed-paths-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-closed-paths-1-snap.png new file mode 100644 index 0000000..7f9784c Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-closed-paths-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-different-graph-types-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-different-graph-types-1-snap.png new file mode 100644 index 0000000..0fadcce Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-different-graph-types-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-distinct-domains-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-distinct-domains-1-snap.png new file mode 100644 index 0000000..203477a Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-distinct-domains-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-logarithmic-scales-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-logarithmic-scales-1-snap.png new file mode 100644 index 0000000..56f5768 Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-logarithmic-scales-1-snap.png differ diff --git a/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-with-additional-options-1-snap.png b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-with-additional-options-1-snap.png new file mode 100644 index 0000000..3355f76 Binary files /dev/null and b/test/e2e/__image_snapshots__/graphs-test-js-function-plot-should-render-with-additional-options-1-snap.png differ diff --git a/test/e2e/graphs.test.js b/test/e2e/graphs.test.js index d0ff1a7..71c785f 100644 --- a/test/e2e/graphs.test.js +++ b/test/e2e/graphs.test.js @@ -10,10 +10,15 @@ describe('Function Plot', () => { beforeAll(async () => { browser = await puppeteer.launch({ headless: 'new' }) page = await browser.newPage() + await page.setViewport({ + width: 1000, + height: 1000, + deviceScaleFactor: 2 + }) + await page.goto('http://localhost:4444/jest-function-plot.html') }) it('should render an x^2 graph', async () => { - await page.goto('http://localhost:4444/jest-function-plot.html') await page.evaluate(` functionPlot({ target: '#playground', @@ -23,9 +28,163 @@ functionPlot({ }) `) const image = await page.screenshot() - expect(image).toMatchImageSnapshot({ - failureThreshold: 0.01, - failureThresholdType: 'percent' - }) + expect(image).toMatchImageSnapshot() + }) + + it('should render with additional options', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + title: 'quadratic with options', + width: 580, + height: 400, + disableZoom: true, + xAxis: { + label: 'x - axis', + domain: [-6, 6] + }, + yAxis: { + label: 'y - axis' + }, + data: [{ + fn: 'x^2' + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should render a grid', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + xAxis: { + label: 'real' + }, + yAxis: { + label: 'imaginary' + }, + grid: true, + data: [ + { fn: 'sqrt(1 - x * x)' }, + { fn: '-sqrt(1 - x * x)' } + ] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should render distinct domains', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + yAxis: {domain: [-1, 1]}, + xAxis: {domain: [8, 24]}, + data: [{ + fn: 'sin(x)' + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should evaluate with multiple samples', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + data: [{ + fn: 'sin(x)', + nSamples: 1000 + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should render annotations', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + yAxis: {domain: [-1, 9]}, + data: [{ + fn: 'x^2' + }], + annotations: [{ + x: -1 + }, { + x: 1, + text: 'x = 1' + }, { + y: 2, + text: 'y = 2' + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should render closed paths', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + xAxis: {domain: [-2, 12]}, + data: [{ + fn: '3 + sin(x)', + range: [2, 8], + closed: true + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should render logarithmic scales', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + xAxis: { + type: 'log', + domain: [0.01, 1] + }, + yAxis: { + domain: [-100, 100] + }, + grid: true, + data: [{ + fn: '1/x * cos(1/x)', + // to make it look like a definite integral + closed: true + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() + }) + + it('should render different graph types', async () => { + await page.evaluate(` +functionPlot({ + target: '#playground', + data: [{ + fn: '-sqrt(-x)', + nSamples: 100, + graphType: 'scatter' + }, { + fn: 'sqrt(x)', + graphType: 'polyline' + }, { + fn: 'x^2', + graphType: 'interval' + }] +}) + `) + const image = await page.screenshot() + expect(image).toMatchImageSnapshot() }) })