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()
})
})