switch from cypress to testcafe
This commit is contained in:
		
							parent
							
								
									819f975948
								
							
						
					
					
						commit
						391455bee4
					
				
					 22 changed files with 180 additions and 1085 deletions
				
			
		
							
								
								
									
										11
									
								
								.travis.yml
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								.travis.yml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
sudo: false
 | 
			
		||||
language: node_js
 | 
			
		||||
node_js:
 | 
			
		||||
  - "stable"
 | 
			
		||||
env:
 | 
			
		||||
  global:
 | 
			
		||||
    - BUILD_TIMEOUT=10000
 | 
			
		||||
install:
 | 
			
		||||
  - npm install
 | 
			
		||||
  - npm install cypress
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,9 +24,9 @@ In separate terminals:
 | 
			
		|||
 | 
			
		||||
    npm run dev
 | 
			
		||||
 | 
			
		||||
3\. Run a Cypress dev environment:
 | 
			
		||||
3\. Run a debuggable TestCafé instance:
 | 
			
		||||
 | 
			
		||||
    npm run cy:open 
 | 
			
		||||
    npx testcafe --hostname localhost --skip-js-errors --debug-mode chrome tests/spec
 | 
			
		||||
 | 
			
		||||
If you want to export the current data in the Mastodon instance as canned data, so that it can be loaded later:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,6 @@ Lint:
 | 
			
		|||
 | 
			
		||||
    npm run lint
 | 
			
		||||
 | 
			
		||||
Run Cypress tests:
 | 
			
		||||
Run integration tests:
 | 
			
		||||
 | 
			
		||||
    npm test
 | 
			
		||||
							
								
								
									
										18
									
								
								appveyor.yml
									
										
									
									
									
								
							
							
						
						
									
										18
									
								
								appveyor.yml
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
version: "{build}"
 | 
			
		||||
 | 
			
		||||
shallow_clone: true
 | 
			
		||||
 | 
			
		||||
init:
 | 
			
		||||
  - git config --global core.autocrlf false
 | 
			
		||||
 | 
			
		||||
build: off
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  matrix:
 | 
			
		||||
    # node.js
 | 
			
		||||
    - nodejs_version: stable
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - ps: Install-Product node $env:nodejs_version
 | 
			
		||||
  - npm install cypress
 | 
			
		||||
  - npm install
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "baseUrl": "http://localhost:4002",
 | 
			
		||||
  "videoRecording": false,
 | 
			
		||||
  "chromeWebSecurity": false
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "Using fixtures to represent data",
 | 
			
		||||
  "email": "hello@cypress.io",
 | 
			
		||||
  "body": "Fixtures are a great way to mock data for responses to routes"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,31 +0,0 @@
 | 
			
		|||
describe('01-basic-spec.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.visit('/')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('has the correct <h1>', () => {
 | 
			
		||||
    cy.contains('h1', 'Pinafore')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('navigates to about', () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Settings]').click()
 | 
			
		||||
    cy.url().should('contain', '/settings')
 | 
			
		||||
    cy.get('a').contains('About').click()
 | 
			
		||||
    cy.url().should('contain', '/settings/about')
 | 
			
		||||
    cy.contains('h1', 'About Pinafore')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('navigates to /settings/instances/add', () => {
 | 
			
		||||
    cy.contains('log in to an instance').click()
 | 
			
		||||
    cy.url().should('contain', '/settings/instances/add')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('navigates to settings/instances', () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Settings]').click()
 | 
			
		||||
    cy.url().should('contain', '/settings')
 | 
			
		||||
    cy.get('a').contains('Instances').click()
 | 
			
		||||
    cy.url().should('contain', '/settings/instances')
 | 
			
		||||
    cy.contains("You're not logged in to any instances")
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
describe('02-login-spec.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.visit('/')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Cannot log in to a fake instance', () => {
 | 
			
		||||
    cy.get('a').contains('log in to an instance').click()
 | 
			
		||||
 | 
			
		||||
    cy.get('#instanceInput').clear().type('fake.nolanlawson.com')
 | 
			
		||||
    cy.get('.add-new-instance').submit()
 | 
			
		||||
    cy.get('.form-error', {timeout: 20000}).contains('Is this a valid Mastodon instance?')
 | 
			
		||||
    cy.get('#instanceInput').type('.biz')
 | 
			
		||||
    cy.get('.form-error').should('not.exist')
 | 
			
		||||
    cy.get('#instanceInput').clear().type('fake.nolanlawson.com')
 | 
			
		||||
    cy.get('.form-error').should('exist')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Logs in to localhost:3000', () => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
 | 
			
		||||
    cy.url().should('equal', 'http://localhost:4002/')
 | 
			
		||||
    cy.get('article.status-article').should('exist')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Logs out', () => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('nav a[aria-label=Settings]').click()
 | 
			
		||||
    cy.get('a').contains('Instances').click()
 | 
			
		||||
    cy.get('a').contains('localhost:3000').click()
 | 
			
		||||
    cy.url().should('contain', '/settings/instances/localhost:3000')
 | 
			
		||||
    cy.get('button').contains('Log out').click()
 | 
			
		||||
    cy.get('#modal-dialog button').contains('OK').click()
 | 
			
		||||
    cy.url().should('contain', '/settings/instances')
 | 
			
		||||
    cy.contains("You're not logged in to any instances")
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,101 +0,0 @@
 | 
			
		|||
const times = require('lodash/times')
 | 
			
		||||
 | 
			
		||||
describe('03-basic-timeline-spec.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const homeTimeline = [
 | 
			
		||||
    {content: 'pinned toot 1'},
 | 
			
		||||
    {content: 'notification of unlisted message'},
 | 
			
		||||
    {content: 'notification of followers-only message'},
 | 
			
		||||
    {content: 'notification of direct message'},
 | 
			
		||||
    {content: 'this is unlisted'},
 | 
			
		||||
    {content: 'this is followers-only'},
 | 
			
		||||
    {content: 'direct'},
 | 
			
		||||
    {spoiler: 'kitten CW'},
 | 
			
		||||
    {content: 'secret video'},
 | 
			
		||||
    {content: "here's a video"},
 | 
			
		||||
    {spoiler: 'CW'},
 | 
			
		||||
    {content: "here's a secret animated kitten gif"},
 | 
			
		||||
    {content: "here's an animated kitten gif"},
 | 
			
		||||
    {content: "here's 2 kitten photos"},
 | 
			
		||||
    {content: "here's a secret kitten"},
 | 
			
		||||
    {content: "here's a kitten"},
 | 
			
		||||
    {content: 'hello admin'},
 | 
			
		||||
    {content: 'hello foobar'},
 | 
			
		||||
    {content: 'hello world'}
 | 
			
		||||
  ].concat(times(30, i => ({content: (30 - i).toString()})))
 | 
			
		||||
 | 
			
		||||
  const localTimeline = [
 | 
			
		||||
    {spoiler: 'kitten CW'},
 | 
			
		||||
    {content: 'secret video'},
 | 
			
		||||
    {content: "here's a video"},
 | 
			
		||||
    {spoiler: 'CW'},
 | 
			
		||||
    {content: "here's a secret animated kitten gif"},
 | 
			
		||||
    {content: "here's an animated kitten gif"},
 | 
			
		||||
    {content: "here's 2 kitten photos"},
 | 
			
		||||
    {content: "here's a secret kitten"},
 | 
			
		||||
    {content: "here's a kitten"},
 | 
			
		||||
    {content: 'hello world'}
 | 
			
		||||
  ].concat(times(30, i => ({content: (30 - i).toString()})))
 | 
			
		||||
 | 
			
		||||
  const notifications = [
 | 
			
		||||
    {favoritedBy: 'admin'},
 | 
			
		||||
    {rebloggedBy: 'admin'},
 | 
			
		||||
    {content: 'notification of unlisted message'},
 | 
			
		||||
    {content: 'notification of followers-only message'},
 | 
			
		||||
    {content: 'notification of direct message'},
 | 
			
		||||
    {followedBy: 'quux'},
 | 
			
		||||
    {content: 'hello foobar'},
 | 
			
		||||
    {followedBy: 'admin'}
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  const favorites = [
 | 
			
		||||
    {content: 'notification of direct message'},
 | 
			
		||||
    {content: 'notification of followers-only message'},
 | 
			
		||||
    {content: 'notification of unlisted message'},
 | 
			
		||||
    {content: 'pinned toot 1'}
 | 
			
		||||
  ]
 | 
			
		||||
 | 
			
		||||
  it('Shows the home timeline', () => {
 | 
			
		||||
    cy.get('.virtual-list-item[aria-hidden=false] .status-article:first').should('have.attr', 'aria-setsize')
 | 
			
		||||
    cy.get('.virtual-list-item[aria-hidden=false] .status-article:first').should('have.attr', 'aria-posinset', '0')
 | 
			
		||||
 | 
			
		||||
    cy.validateTimeline(homeTimeline)
 | 
			
		||||
 | 
			
		||||
    cy.get('.virtual-list-item[aria-hidden=false] .status-article:first').should('have.attr', 'aria-setsize', '49')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Shows notifications', () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Notifications]').click()
 | 
			
		||||
    cy.url().should('contain', '/notifications')
 | 
			
		||||
 | 
			
		||||
    cy.validateTimeline(notifications)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Shows the local timeline', () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Local]').click()
 | 
			
		||||
    cy.url().should('contain', '/local')
 | 
			
		||||
 | 
			
		||||
    cy.validateTimeline(localTimeline)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Shows the federated timeline', () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Community]').click()
 | 
			
		||||
    cy.url().should('contain', '/community')
 | 
			
		||||
    cy.get('a').contains('Federated').click()
 | 
			
		||||
    cy.url().should('contain', '/federated')
 | 
			
		||||
 | 
			
		||||
    cy.validateTimeline(localTimeline) // local is same as federated in this case
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('Shows favorites', () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Community]').click()
 | 
			
		||||
    cy.url().should('contain', '/community')
 | 
			
		||||
    cy.get('a').contains('Favorites').click()
 | 
			
		||||
    cy.url().should('contain', '/favorites')
 | 
			
		||||
    cy.validateTimeline(favorites)
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,36 +0,0 @@
 | 
			
		|||
describe('04-pinned-statuses.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it("shows a user's pinned statuses", () => {
 | 
			
		||||
    cy.get('nav a[aria-label=Community]').click()
 | 
			
		||||
    cy.url().should('contain', '/community')
 | 
			
		||||
    cy.get('a').contains('Pinned').click()
 | 
			
		||||
    cy.url().should('contain', '/pinned')
 | 
			
		||||
 | 
			
		||||
    cy.get('.status-article').should('have.attr', 'aria-posinset', '0')
 | 
			
		||||
    cy.get('.status-article').should('have.attr', 'aria-setsize', '1')
 | 
			
		||||
    cy.get('.status-article .status-content').should('contain', 'this is unlisted')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it("shows pinned statuses on a user's account page", () => {
 | 
			
		||||
    cy.visit('/accounts/2')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('.pinned-statuses .status-article').should('have.attr', 'aria-posinset', '0')
 | 
			
		||||
    cy.get('.pinned-statuses .status-article').should('have.attr', 'aria-setsize', '1')
 | 
			
		||||
    cy.get('.pinned-statuses .status-article').should('contain', 'this is unlisted')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it("shows pinned statuses on a user's account page 2", () => {
 | 
			
		||||
    cy.visit('/accounts/3')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('.pinned-statuses .status-article').should('have.attr', 'aria-posinset', '0')
 | 
			
		||||
    cy.get('.pinned-statuses .status-article').should('have.attr', 'aria-setsize', '2')
 | 
			
		||||
    cy.get('.pinned-statuses .status-article').should('contain', 'pinned toot 1')
 | 
			
		||||
 | 
			
		||||
    cy.get('.pinned-statuses .status-article[aria-posinset=1]').should('have.attr', 'aria-setsize', '2')
 | 
			
		||||
    cy.get('.pinned-statuses .status-article[aria-posinset=1]').should('contain', 'pinned toot 2')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,49 +0,0 @@
 | 
			
		|||
describe('05-status-types.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows direct vs followers-only vs regular', () => {
 | 
			
		||||
    cy.getNthVirtualArticle(1).should('have.attr', 'aria-label', 'Status by admin')
 | 
			
		||||
    cy.getNthVirtualArticle(1).find('.status-content').should('contain', 'notification of unlisted message')
 | 
			
		||||
    cy.getNthVirtualArticle(1).find('.status-toolbar button:nth-child(2)')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Boost')
 | 
			
		||||
      .and('not.have.attr', 'disabled')
 | 
			
		||||
 | 
			
		||||
    cy.getNthVirtualArticle(2).should('have.attr', 'aria-label', 'Status by admin')
 | 
			
		||||
    cy.getNthVirtualArticle(2).find('.status-content').should('contain', 'notification of followers-only message')
 | 
			
		||||
    cy.getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Cannot be boosted because this is followers-only')
 | 
			
		||||
      .and('have.attr', 'disabled')
 | 
			
		||||
 | 
			
		||||
    cy.getNthVirtualArticle(3).should('have.attr', 'aria-label', 'Direct message by admin')
 | 
			
		||||
    cy.getNthVirtualArticle(3).find('.status-content').should('contain', 'notification of direct message')
 | 
			
		||||
    cy.getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Cannot be boosted because this is a direct message')
 | 
			
		||||
      .and('have.attr', 'disabled')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows direct vs followers-only vs regular in notifications', () => {
 | 
			
		||||
    cy.visit('/notifications')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
 | 
			
		||||
    cy.getNthVirtualArticle(2).should('have.attr', 'aria-label', 'Status by admin')
 | 
			
		||||
    cy.getNthVirtualArticle(2).find('.status-content').should('contain', 'notification of unlisted message')
 | 
			
		||||
    cy.getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Boost')
 | 
			
		||||
      .and('not.have.attr', 'disabled')
 | 
			
		||||
 | 
			
		||||
    cy.getNthVirtualArticle(3).should('have.attr', 'aria-label', 'Status by admin')
 | 
			
		||||
    cy.getNthVirtualArticle(3).find('.status-content').should('contain', 'notification of followers-only message')
 | 
			
		||||
    cy.getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Cannot be boosted because this is followers-only')
 | 
			
		||||
      .and('have.attr', 'disabled')
 | 
			
		||||
 | 
			
		||||
    cy.getNthVirtualArticle(4).should('have.attr', 'aria-label', 'Direct message by admin')
 | 
			
		||||
    cy.getNthVirtualArticle(4).find('.status-content').should('contain', 'notification of direct message')
 | 
			
		||||
    cy.getNthVirtualArticle(4).find('.status-toolbar button:nth-child(2)')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Cannot be boosted because this is a direct message')
 | 
			
		||||
      .and('have.attr', 'disabled')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,45 +0,0 @@
 | 
			
		|||
describe('06-tabindex.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows correct tabindex in home timeline', () => {
 | 
			
		||||
    cy.getNthVirtualArticle(0).should('have.attr', 'tabindex', '0')
 | 
			
		||||
    cy.getNthVirtualArticle(2).should('have.attr', 'tabindex', '0')
 | 
			
		||||
    cy.getNthVirtualArticle(3).should('have.attr', 'tabindex', '0')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows correct tabindex in notifications', () => {
 | 
			
		||||
    cy.visit('/notifications')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.getNthVirtualArticle(0).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.class', 'status-article')
 | 
			
		||||
    cy.getNthVirtualArticle(1).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.class', 'status-article')
 | 
			
		||||
    cy.getNthVirtualArticle(2).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.class', 'status-article')
 | 
			
		||||
    cy.getNthVirtualArticle(3).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.class', 'status-article')
 | 
			
		||||
    cy.getNthVirtualArticle(4).should('have.attr', 'tabindex', '0')
 | 
			
		||||
    cy.getNthVirtualArticle(4).scrollIntoView()
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.getNthVirtualArticle(5).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.class', 'notification-article')
 | 
			
		||||
    cy.getNthVirtualArticle(6).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.class', 'status-article')
 | 
			
		||||
    cy.getNthVirtualArticle(6).scrollIntoView()
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.getNthVirtualArticle(7).should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.attr', 'aria-setsize', '8')
 | 
			
		||||
      .and('have.class', 'notification-article')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows correct tabindex in pinned statuses', () => {
 | 
			
		||||
    cy.visit('/pinned')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('.status-article').should('have.attr', 'tabindex', '0')
 | 
			
		||||
      .and('have.attr', 'aria-posinset', '0')
 | 
			
		||||
      .and('have.attr', 'aria-setsize', '1')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,41 +0,0 @@
 | 
			
		|||
describe('07-account-profile.js', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    cy.login('foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows account profile', () => {
 | 
			
		||||
    cy.get('.status-author-name').contains('quux').click()
 | 
			
		||||
    cy.url().should('contain', '/accounts/3')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('.account-profile .account-profile-name').should('contain', 'quux')
 | 
			
		||||
    cy.get('.account-profile .account-profile-username').should('contain', '@quux')
 | 
			
		||||
    cy.get('.account-profile .account-profile-followed-by').should('contain', 'Follows you')
 | 
			
		||||
    cy.get('.account-profile .account-profile-follow button')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Follow')
 | 
			
		||||
      .and('have.attr', 'aria-pressed', 'false')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows account profile 2', () => {
 | 
			
		||||
    cy.get('.status-author-name').contains('admin').click()
 | 
			
		||||
    cy.url().should('contain', '/accounts/1')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('.account-profile .account-profile-name').should('contain', 'admin')
 | 
			
		||||
    cy.get('.account-profile .account-profile-username').should('contain', '@admin')
 | 
			
		||||
    cy.get('.account-profile .account-profile-followed-by').should('contain', 'Follows you')
 | 
			
		||||
    cy.get('.account-profile .account-profile-follow button')
 | 
			
		||||
      .should('have.attr', 'aria-label', 'Unfollow')
 | 
			
		||||
      .and('have.attr', 'aria-pressed', 'true')
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('shows account profile 3', () => {
 | 
			
		||||
    cy.get('.mention').contains('foobar').click()
 | 
			
		||||
    cy.url().should('contain', '/accounts/2')
 | 
			
		||||
    cy.wait(500)
 | 
			
		||||
    cy.get('.account-profile .account-profile-name').should('contain', 'foobar')
 | 
			
		||||
    cy.get('.account-profile .account-profile-username').should('contain', '@foobar')
 | 
			
		||||
    // can't follow or be followed by your own account
 | 
			
		||||
    cy.get('.account-profile .account-profile-followed-by').should('be.empty')
 | 
			
		||||
    cy.get('.account-profile .account-profile-follow').should('be.empty')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,17 +0,0 @@
 | 
			
		|||
// ***********************************************************
 | 
			
		||||
// This example plugins/index.js can be used to load plugins
 | 
			
		||||
//
 | 
			
		||||
// You can change the location of this file or turn off loading
 | 
			
		||||
// the plugins file with the 'pluginsFile' configuration option.
 | 
			
		||||
//
 | 
			
		||||
// You can read more here:
 | 
			
		||||
// https://on.cypress.io/plugins-guide
 | 
			
		||||
// ***********************************************************
 | 
			
		||||
 | 
			
		||||
// This function is called when a project is opened or re-opened (e.g. due to
 | 
			
		||||
// the project's config changing)
 | 
			
		||||
 | 
			
		||||
module.exports = (on, config) => {
 | 
			
		||||
  // `on` is used to hook into various events Cypress emits
 | 
			
		||||
  // `config` is the resolved Cypress config
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,80 +0,0 @@
 | 
			
		|||
// ***********************************************
 | 
			
		||||
// This example commands.js shows you how to
 | 
			
		||||
// create various custom commands and overwrite
 | 
			
		||||
// existing commands.
 | 
			
		||||
//
 | 
			
		||||
// For more comprehensive examples of custom
 | 
			
		||||
// commands please read more here:
 | 
			
		||||
// https://on.cypress.io/custom-commands
 | 
			
		||||
// ***********************************************
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// -- This is a parent command --
 | 
			
		||||
// Cypress.Commands.add("login", (email, password) => { ... })
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// -- This is a child command --
 | 
			
		||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// -- This is a dual command --
 | 
			
		||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// -- This is will overwrite an existing command --
 | 
			
		||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
 | 
			
		||||
 | 
			
		||||
Cypress.Commands.add('login', (email, password) => {
 | 
			
		||||
  // mastodon throws some uncaught TypeErrors
 | 
			
		||||
  cy.on('uncaught:exception', (err) => {
 | 
			
		||||
    expect(err.name).to.include('TypeError')
 | 
			
		||||
    expect(err.message).to.include('Illegal invocation')
 | 
			
		||||
    return false
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  cy.visit('/settings/instances/add')
 | 
			
		||||
  cy.wait(500)
 | 
			
		||||
  cy.get('#instanceInput').clear().type('localhost:3000')
 | 
			
		||||
  cy.get('.add-new-instance').submit()
 | 
			
		||||
  cy.wait(500)
 | 
			
		||||
  cy.url().should('equal', 'http://localhost:3000/auth/sign_in')
 | 
			
		||||
  cy.get('input#user_email').should('exist')
 | 
			
		||||
  cy.get('input#user_password').should('exist')
 | 
			
		||||
  cy.get('input#user_email').type(email)
 | 
			
		||||
  cy.get('input#user_password').type(password)
 | 
			
		||||
  cy.get('form#new_user').submit()
 | 
			
		||||
  cy.url().should('contain', '/oauth/authorize')
 | 
			
		||||
 | 
			
		||||
  cy.get('button').contains('Authorize').click()
 | 
			
		||||
  cy.url().should('equal', 'http://localhost:4002/')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
Cypress.Commands.add('getNthVirtualArticle', (n) => {
 | 
			
		||||
  return cy.get(`.virtual-list-item[aria-hidden=false] article[aria-posinset=${n}]`)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
Cypress.Commands.add('validateTimeline', (timeline) => {
 | 
			
		||||
  timeline.forEach((status, i) => {
 | 
			
		||||
    if (status.content) {
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-content p').should('contain', status.content)
 | 
			
		||||
    }
 | 
			
		||||
    if (status.spoiler) {
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-spoiler p').should('contain', status.spoiler)
 | 
			
		||||
    }
 | 
			
		||||
    if (status.followedBy) {
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-header span').should('contain', status.followedBy)
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-header span').should('contain', 'followed you')
 | 
			
		||||
    }
 | 
			
		||||
    if (status.rebloggedBy) {
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-header span').should('contain', status.rebloggedBy)
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-header span').should('contain', 'boosted')
 | 
			
		||||
    }
 | 
			
		||||
    if (status.favoritedBy) {
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-header span').should('contain', status.favoritedBy)
 | 
			
		||||
      cy.getNthVirtualArticle(i).find('.status-header span').should('contain', 'favorited')
 | 
			
		||||
    }
 | 
			
		||||
    cy.wait(50)
 | 
			
		||||
    cy.getNthVirtualArticle(i).scrollIntoView()
 | 
			
		||||
    cy.get('.loading-footer').should('not.exist')
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -1,20 +0,0 @@
 | 
			
		|||
// ***********************************************************
 | 
			
		||||
// This example support/index.js is processed and
 | 
			
		||||
// loaded automatically before your test files.
 | 
			
		||||
//
 | 
			
		||||
// This is a great place to put global configuration and
 | 
			
		||||
// behavior that modifies Cypress.
 | 
			
		||||
//
 | 
			
		||||
// You can change the location of this file or turn off
 | 
			
		||||
// automatically serving support files with the
 | 
			
		||||
// 'supportFile' configuration option.
 | 
			
		||||
//
 | 
			
		||||
// You can read more here:
 | 
			
		||||
// https://on.cypress.io/configuration
 | 
			
		||||
// ***********************************************************
 | 
			
		||||
 | 
			
		||||
// Import commands.js using ES2015 syntax:
 | 
			
		||||
import './commands'
 | 
			
		||||
 | 
			
		||||
// Alternatively you can use CommonJS syntax:
 | 
			
		||||
// require('./commands')
 | 
			
		||||
							
								
								
									
										569
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										569
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -4,54 +4,11 @@
 | 
			
		|||
  "lockfileVersion": 1,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@cypress/listr-verbose-renderer": {
 | 
			
		||||
      "version": "0.4.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
 | 
			
		||||
      "integrity": "sha1-p3SS9LEdzHxEajSz4ochr9M8ZCo=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "1.1.3",
 | 
			
		||||
        "cli-cursor": "1.0.2",
 | 
			
		||||
        "date-fns": "1.29.0",
 | 
			
		||||
        "figures": "1.7.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@cypress/xvfb": {
 | 
			
		||||
      "version": "1.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.1.3.tgz",
 | 
			
		||||
      "integrity": "sha512-EfRzw+wgI0Zdb4ZlhSvjh3q7I+oenqEYPXvr7oH/2RnzQqGDrPr7IU1Pi2yzGwoXmkNUQbo6qvntnItvQj0F4Q==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "lodash.once": "4.1.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@gamestdio/websocket": {
 | 
			
		||||
      "version": "0.2.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@gamestdio/websocket/-/websocket-0.2.2.tgz",
 | 
			
		||||
      "integrity": "sha512-ptWTKBq6IliC7lNhfAI/YI5WBjhPClflZV61V7In/qxGbgrWrlny6/Df4NtrUs7QUeNccv8yqQwjjw+f0veGjQ=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/blob-util": {
 | 
			
		||||
      "version": "1.3.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/blob-util/-/blob-util-1.3.3.tgz",
 | 
			
		||||
      "integrity": "sha512-4ahcL/QDnpjWA2Qs16ZMQif7HjGP2cw3AGjHabybjw7Vm1EKu+cfQN1D78BaZbS1WJNa1opSMF5HNMztx7lR0w=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/bluebird": {
 | 
			
		||||
      "version": "3.5.18",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.18.tgz",
 | 
			
		||||
      "integrity": "sha512-OTPWHmsyW18BhrnG5x8F7PzeZ2nFxmHGb42bZn79P9hl+GI5cMzyPgQTwNjbem0lJhoru/8vtjAFCUOu3+gE2w=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/chai": {
 | 
			
		||||
      "version": "4.0.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.0.8.tgz",
 | 
			
		||||
      "integrity": "sha512-m812CONwdZn/dMzkIJEY0yAs4apyTkTORgfB2UsMOxgkUbC205AHnm4T8I0I5gPg9MHrFc1dJ35iS75c0CJkjg=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/chai-jquery": {
 | 
			
		||||
      "version": "1.1.35",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/chai-jquery/-/chai-jquery-1.1.35.tgz",
 | 
			
		||||
      "integrity": "sha512-7aIt9QMRdxuagLLI48dPz96YJdhu64p6FCa6n4qkGN5DQLHnrIjZpD9bXCvV2G0NwgZ1FAmfP214dxc5zNCfgQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@types/chai": "4.0.8",
 | 
			
		||||
        "@types/jquery": "2.0.48"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@types/chalk": {
 | 
			
		||||
      "version": "0.4.31",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -72,35 +29,11 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.87.tgz",
 | 
			
		||||
      "integrity": "sha512-AqRC+aEF4N0LuNHtcjKtvF9OTfqZI0iaBoe3dA6m/W+/YZJBZjBmW/QIZ8fBeXC6cnytSY9tBoFBqZ9uSCeVsw=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/minimatch": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-rUO/jz10KRSyA9SHoCWQ8WX9BICyj5jZYu1/ucKEJKb4KzLZCKMURdYbadP157Q6Zl1x0vHsrU+Z/O0XlhYQDw=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/mocha": {
 | 
			
		||||
      "version": "2.2.44",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.44.tgz",
 | 
			
		||||
      "integrity": "sha512-k2tWTQU8G4+iSMvqKi0Q9IIsWAp/n8xzdZS4Q4YVIltApoMA00wFBFdlJnmoaK1/z7B0Cy0yPe6GgXteSmdUNw=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/node": {
 | 
			
		||||
      "version": "9.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/node/-/node-9.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-zkYho6/4wZyX6o9UQ8rd0ReEaiEYNNCqYFIAACe2Tf9DrYlgzWW27OigYHnnztnnZQwVRpwWmZKegFmDpinIsA=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/sinon": {
 | 
			
		||||
      "version": "4.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-4.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-cuK4xM8Lg2wd8cxshcQa8RG4IK/xfyB6TNE6tNVvkrShR4xdrYgsV04q6Dp6v1Lp6biEFdzD8k8zg/ujQeiw+A=="
 | 
			
		||||
    },
 | 
			
		||||
    "@types/sinon-chai": {
 | 
			
		||||
      "version": "2.7.29",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-2.7.29.tgz",
 | 
			
		||||
      "integrity": "sha512-EkI/ZvJT4hglWo7Ipf9SX+J+R9htNOMjW8xiOhce7+0csqvgoF5IXqY5Ae1GqRgNtWCuaywR5HjVa1snkTqpOw==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@types/chai": "4.0.8",
 | 
			
		||||
        "@types/sinon": "4.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "a11y-dialog": {
 | 
			
		||||
      "version": "4.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/a11y-dialog/-/a11y-dialog-4.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -1410,11 +1343,6 @@
 | 
			
		|||
        "isarray": "1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "buffer-crc32": {
 | 
			
		||||
      "version": "0.2.13",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
 | 
			
		||||
      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI="
 | 
			
		||||
    },
 | 
			
		||||
    "buffer-xor": {
 | 
			
		||||
      "version": "1.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -1595,11 +1523,6 @@
 | 
			
		|||
        "supports-color": "2.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "check-more-types": {
 | 
			
		||||
      "version": "2.24.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
 | 
			
		||||
      "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA="
 | 
			
		||||
    },
 | 
			
		||||
    "cheerio": {
 | 
			
		||||
      "version": "1.0.0-rc.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -1805,32 +1728,6 @@
 | 
			
		|||
        "restore-cursor": "1.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "cli-spinners": {
 | 
			
		||||
      "version": "0.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz",
 | 
			
		||||
      "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw="
 | 
			
		||||
    },
 | 
			
		||||
    "cli-truncate": {
 | 
			
		||||
      "version": "0.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
 | 
			
		||||
      "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "slice-ansi": "0.0.4",
 | 
			
		||||
        "string-width": "1.0.2"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "string-width": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "code-point-at": "1.1.0",
 | 
			
		||||
            "is-fullwidth-code-point": "1.0.0",
 | 
			
		||||
            "strip-ansi": "3.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "cli-width": {
 | 
			
		||||
      "version": "2.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -1937,14 +1834,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz",
 | 
			
		||||
      "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA=="
 | 
			
		||||
    },
 | 
			
		||||
    "common-tags": {
 | 
			
		||||
      "version": "1.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.4.0.tgz",
 | 
			
		||||
      "integrity": "sha1-EYe+Tz1M8MBCfUP3Tu8fc1AWFMA=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "babel-runtime": "6.26.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "commondir": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2345,195 +2234,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
 | 
			
		||||
      "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA="
 | 
			
		||||
    },
 | 
			
		||||
    "cypress": {
 | 
			
		||||
      "version": "2.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/cypress/-/cypress-2.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-ciIOchZSnvlkwB6cxjeK9TycKVHAA3eE/PJYq7CSnLWkmepkwxASRqD5RPcXgefKVJB5rS92RkKIq2CBOZGcdQ==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@cypress/listr-verbose-renderer": "0.4.1",
 | 
			
		||||
        "@cypress/xvfb": "1.1.3",
 | 
			
		||||
        "@types/blob-util": "1.3.3",
 | 
			
		||||
        "@types/bluebird": "3.5.18",
 | 
			
		||||
        "@types/chai": "4.0.8",
 | 
			
		||||
        "@types/chai-jquery": "1.1.35",
 | 
			
		||||
        "@types/jquery": "3.2.16",
 | 
			
		||||
        "@types/lodash": "4.14.87",
 | 
			
		||||
        "@types/minimatch": "3.0.1",
 | 
			
		||||
        "@types/mocha": "2.2.44",
 | 
			
		||||
        "@types/sinon": "4.0.0",
 | 
			
		||||
        "@types/sinon-chai": "2.7.29",
 | 
			
		||||
        "bluebird": "3.5.0",
 | 
			
		||||
        "chalk": "2.1.0",
 | 
			
		||||
        "check-more-types": "2.24.0",
 | 
			
		||||
        "commander": "2.11.0",
 | 
			
		||||
        "common-tags": "1.4.0",
 | 
			
		||||
        "debug": "3.1.0",
 | 
			
		||||
        "extract-zip": "1.6.6",
 | 
			
		||||
        "fs-extra": "4.0.1",
 | 
			
		||||
        "getos": "2.8.4",
 | 
			
		||||
        "glob": "7.1.2",
 | 
			
		||||
        "is-ci": "1.0.10",
 | 
			
		||||
        "is-installed-globally": "0.1.0",
 | 
			
		||||
        "lazy-ass": "1.6.0",
 | 
			
		||||
        "listr": "0.12.0",
 | 
			
		||||
        "lodash": "4.17.4",
 | 
			
		||||
        "minimist": "1.2.0",
 | 
			
		||||
        "progress": "1.1.8",
 | 
			
		||||
        "ramda": "0.24.1",
 | 
			
		||||
        "request": "2.81.0",
 | 
			
		||||
        "request-progress": "0.3.1",
 | 
			
		||||
        "supports-color": "5.1.0",
 | 
			
		||||
        "tmp": "0.0.31",
 | 
			
		||||
        "url": "0.11.0",
 | 
			
		||||
        "yauzl": "2.8.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@types/jquery": {
 | 
			
		||||
          "version": "3.2.16",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.2.16.tgz",
 | 
			
		||||
          "integrity": "sha512-q2WC02YxQoX2nY1HRKlYGHpGP1saPmD7GN0pwCDlTz35a4eOtJG+aHRlXyjCuXokUukSrR2aXyBhSW3j+jPc0A=="
 | 
			
		||||
        },
 | 
			
		||||
        "ajv": {
 | 
			
		||||
          "version": "4.11.8",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
 | 
			
		||||
          "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "co": "4.6.0",
 | 
			
		||||
            "json-stable-stringify": "1.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "ansi-styles": {
 | 
			
		||||
          "version": "3.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
 | 
			
		||||
          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-convert": "1.9.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "bluebird": {
 | 
			
		||||
          "version": "3.5.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz",
 | 
			
		||||
          "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw="
 | 
			
		||||
        },
 | 
			
		||||
        "caseless": {
 | 
			
		||||
          "version": "0.12.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
 | 
			
		||||
          "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
 | 
			
		||||
        },
 | 
			
		||||
        "chalk": {
 | 
			
		||||
          "version": "2.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
 | 
			
		||||
          "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-styles": "3.2.0",
 | 
			
		||||
            "escape-string-regexp": "1.0.5",
 | 
			
		||||
            "supports-color": "4.5.0"
 | 
			
		||||
          },
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "supports-color": {
 | 
			
		||||
              "version": "4.5.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
 | 
			
		||||
              "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
 | 
			
		||||
              "requires": {
 | 
			
		||||
                "has-flag": "2.0.0"
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "commander": {
 | 
			
		||||
          "version": "2.11.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
 | 
			
		||||
          "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
 | 
			
		||||
        },
 | 
			
		||||
        "debug": {
 | 
			
		||||
          "version": "3.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
 | 
			
		||||
          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ms": "2.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "extend": {
 | 
			
		||||
          "version": "3.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
 | 
			
		||||
        },
 | 
			
		||||
        "har-validator": {
 | 
			
		||||
          "version": "4.2.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
 | 
			
		||||
          "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ajv": "4.11.8",
 | 
			
		||||
            "har-schema": "1.0.5"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "has-flag": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
 | 
			
		||||
        },
 | 
			
		||||
        "minimist": {
 | 
			
		||||
          "version": "1.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
 | 
			
		||||
        },
 | 
			
		||||
        "performance-now": {
 | 
			
		||||
          "version": "0.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU="
 | 
			
		||||
        },
 | 
			
		||||
        "qs": {
 | 
			
		||||
          "version": "6.4.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
 | 
			
		||||
          "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
 | 
			
		||||
        },
 | 
			
		||||
        "request": {
 | 
			
		||||
          "version": "2.81.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
 | 
			
		||||
          "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "aws-sign2": "0.6.0",
 | 
			
		||||
            "aws4": "1.6.0",
 | 
			
		||||
            "caseless": "0.12.0",
 | 
			
		||||
            "combined-stream": "1.0.5",
 | 
			
		||||
            "extend": "3.0.1",
 | 
			
		||||
            "forever-agent": "0.6.1",
 | 
			
		||||
            "form-data": "2.1.4",
 | 
			
		||||
            "har-validator": "4.2.1",
 | 
			
		||||
            "hawk": "3.1.3",
 | 
			
		||||
            "http-signature": "1.1.1",
 | 
			
		||||
            "is-typedarray": "1.0.0",
 | 
			
		||||
            "isstream": "0.1.2",
 | 
			
		||||
            "json-stringify-safe": "5.0.1",
 | 
			
		||||
            "mime-types": "2.1.17",
 | 
			
		||||
            "oauth-sign": "0.8.2",
 | 
			
		||||
            "performance-now": "0.2.0",
 | 
			
		||||
            "qs": "6.4.0",
 | 
			
		||||
            "safe-buffer": "5.1.1",
 | 
			
		||||
            "stringstream": "0.0.5",
 | 
			
		||||
            "tough-cookie": "2.3.3",
 | 
			
		||||
            "tunnel-agent": "0.6.0",
 | 
			
		||||
            "uuid": "3.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "supports-color": {
 | 
			
		||||
          "version": "5.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "has-flag": "2.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "tunnel-agent": {
 | 
			
		||||
          "version": "0.6.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 | 
			
		||||
          "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "safe-buffer": "5.1.1"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "d": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -2557,11 +2257,6 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "date-fns": {
 | 
			
		||||
      "version": "1.29.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
 | 
			
		||||
      "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw=="
 | 
			
		||||
    },
 | 
			
		||||
    "date-now": {
 | 
			
		||||
      "version": "0.1.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3506,35 +3201,6 @@
 | 
			
		|||
        "webpack-sources": "1.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "extract-zip": {
 | 
			
		||||
      "version": "1.6.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz",
 | 
			
		||||
      "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "concat-stream": "1.6.0",
 | 
			
		||||
        "debug": "2.6.9",
 | 
			
		||||
        "mkdirp": "0.5.0",
 | 
			
		||||
        "yauzl": "2.4.1"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "mkdirp": {
 | 
			
		||||
          "version": "0.5.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
 | 
			
		||||
          "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "minimist": "0.0.8"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "yauzl": {
 | 
			
		||||
          "version": "2.4.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
 | 
			
		||||
          "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "fd-slicer": "1.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "extsprintf": {
 | 
			
		||||
      "version": "1.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3560,14 +3226,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz",
 | 
			
		||||
      "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg="
 | 
			
		||||
    },
 | 
			
		||||
    "fd-slicer": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "pend": "1.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "fg-loadcss": {
 | 
			
		||||
      "version": "2.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fg-loadcss/-/fg-loadcss-2.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -3835,16 +3493,6 @@
 | 
			
		|||
        "readable-stream": "2.3.3"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "fs-extra": {
 | 
			
		||||
      "version": "4.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-f8DGyJV/mD9X8waiTlud3Y0N2IA=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "graceful-fs": "4.1.11",
 | 
			
		||||
        "jsonfile": "3.0.1",
 | 
			
		||||
        "universalify": "0.1.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "fs-write-stream-atomic": {
 | 
			
		||||
      "version": "1.0.10",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -4734,24 +4382,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
 | 
			
		||||
      "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
 | 
			
		||||
    },
 | 
			
		||||
    "getos": {
 | 
			
		||||
      "version": "2.8.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/getos/-/getos-2.8.4.tgz",
 | 
			
		||||
      "integrity": "sha1-e4YD02GcKOOMsP56T2PDrLgNUWM=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "async": "2.1.4"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "async": {
 | 
			
		||||
          "version": "2.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/async/-/async-2.1.4.tgz",
 | 
			
		||||
          "integrity": "sha1-LSFgx3iAMuTdbL4lAvH5osj2zeQ=",
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "lodash": "4.17.4"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "getpass": {
 | 
			
		||||
      "version": "0.1.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -4831,14 +4461,6 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "global-dirs": {
 | 
			
		||||
      "version": "0.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
 | 
			
		||||
      "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "ini": "1.3.5"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "globals": {
 | 
			
		||||
      "version": "9.18.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -4887,11 +4509,6 @@
 | 
			
		|||
        "duplexer": "0.1.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "har-schema": {
 | 
			
		||||
      "version": "1.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
 | 
			
		||||
      "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4="
 | 
			
		||||
    },
 | 
			
		||||
    "har-validator": {
 | 
			
		||||
      "version": "2.0.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5236,11 +4853,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
 | 
			
		||||
      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
 | 
			
		||||
    },
 | 
			
		||||
    "ini": {
 | 
			
		||||
      "version": "1.3.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
 | 
			
		||||
      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
 | 
			
		||||
    },
 | 
			
		||||
    "inquirer": {
 | 
			
		||||
      "version": "0.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5454,15 +5066,6 @@
 | 
			
		|||
        "is-extglob": "2.1.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "is-installed-globally": {
 | 
			
		||||
      "version": "0.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "global-dirs": "0.1.1",
 | 
			
		||||
        "is-path-inside": "1.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "is-my-json-valid": {
 | 
			
		||||
      "version": "2.17.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5541,11 +5144,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
 | 
			
		||||
    },
 | 
			
		||||
    "is-promise": {
 | 
			
		||||
      "version": "2.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
 | 
			
		||||
    },
 | 
			
		||||
    "is-property": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5688,14 +5286,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
 | 
			
		||||
      "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
 | 
			
		||||
    },
 | 
			
		||||
    "jsonfile": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "graceful-fs": "4.1.11"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "jsonify": {
 | 
			
		||||
      "version": "0.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5737,11 +5327,6 @@
 | 
			
		|||
        "is-buffer": "1.1.6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "lazy-ass": {
 | 
			
		||||
      "version": "1.6.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
 | 
			
		||||
      "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM="
 | 
			
		||||
    },
 | 
			
		||||
    "lazy-cache": {
 | 
			
		||||
      "version": "1.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5772,67 +5357,6 @@
 | 
			
		|||
        "os-family": "1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "listr": {
 | 
			
		||||
      "version": "0.12.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/listr/-/listr-0.12.0.tgz",
 | 
			
		||||
      "integrity": "sha1-a84sD1YD+klYDqF81qAMwOX6RRo=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "1.1.3",
 | 
			
		||||
        "cli-truncate": "0.2.1",
 | 
			
		||||
        "figures": "1.7.0",
 | 
			
		||||
        "indent-string": "2.1.0",
 | 
			
		||||
        "is-promise": "2.1.0",
 | 
			
		||||
        "is-stream": "1.1.0",
 | 
			
		||||
        "listr-silent-renderer": "1.1.1",
 | 
			
		||||
        "listr-update-renderer": "0.2.0",
 | 
			
		||||
        "listr-verbose-renderer": "0.4.1",
 | 
			
		||||
        "log-symbols": "1.0.2",
 | 
			
		||||
        "log-update": "1.0.2",
 | 
			
		||||
        "ora": "0.2.3",
 | 
			
		||||
        "p-map": "1.2.0",
 | 
			
		||||
        "rxjs": "5.5.6",
 | 
			
		||||
        "stream-to-observable": "0.1.0",
 | 
			
		||||
        "strip-ansi": "3.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "listr-silent-renderer": {
 | 
			
		||||
      "version": "1.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz",
 | 
			
		||||
      "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4="
 | 
			
		||||
    },
 | 
			
		||||
    "listr-update-renderer": {
 | 
			
		||||
      "version": "0.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz",
 | 
			
		||||
      "integrity": "sha1-yoDhd5tOcCZoB+ju0a1qvjmFUPk=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "1.1.3",
 | 
			
		||||
        "cli-truncate": "0.2.1",
 | 
			
		||||
        "elegant-spinner": "1.0.1",
 | 
			
		||||
        "figures": "1.7.0",
 | 
			
		||||
        "indent-string": "3.2.0",
 | 
			
		||||
        "log-symbols": "1.0.2",
 | 
			
		||||
        "log-update": "1.0.2",
 | 
			
		||||
        "strip-ansi": "3.0.1"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "indent-string": {
 | 
			
		||||
          "version": "3.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok="
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "listr-verbose-renderer": {
 | 
			
		||||
      "version": "0.4.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz",
 | 
			
		||||
      "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "1.1.3",
 | 
			
		||||
        "cli-cursor": "1.0.2",
 | 
			
		||||
        "date-fns": "1.29.0",
 | 
			
		||||
        "figures": "1.7.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "load-json-file": {
 | 
			
		||||
      "version": "4.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -5994,11 +5518,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz",
 | 
			
		||||
      "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU="
 | 
			
		||||
    },
 | 
			
		||||
    "lodash.once": {
 | 
			
		||||
      "version": "4.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
 | 
			
		||||
      "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
 | 
			
		||||
    },
 | 
			
		||||
    "lodash.pairs": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -6012,23 +5531,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
 | 
			
		||||
      "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
 | 
			
		||||
    },
 | 
			
		||||
    "log-symbols": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "1.1.3"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "log-update": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "ansi-escapes": "1.4.0",
 | 
			
		||||
        "cli-cursor": "1.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "log-update-async-hook": {
 | 
			
		||||
      "version": "2.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/log-update-async-hook/-/log-update-async-hook-2.0.2.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -6941,17 +6443,6 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ora": {
 | 
			
		||||
      "version": "0.2.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz",
 | 
			
		||||
      "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "1.1.3",
 | 
			
		||||
        "cli-cursor": "1.0.2",
 | 
			
		||||
        "cli-spinners": "0.1.2",
 | 
			
		||||
        "object-assign": "4.1.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "os-browserify": {
 | 
			
		||||
      "version": "0.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -7020,11 +6511,6 @@
 | 
			
		|||
        "p-limit": "1.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "p-map": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA=="
 | 
			
		||||
    },
 | 
			
		||||
    "p-some": {
 | 
			
		||||
      "version": "2.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/p-some/-/p-some-2.0.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -7186,11 +6672,6 @@
 | 
			
		|||
        "sha.js": "2.4.9"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "pend": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
 | 
			
		||||
    },
 | 
			
		||||
    "performance-now": {
 | 
			
		||||
      "version": "2.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -8037,11 +7518,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g="
 | 
			
		||||
    },
 | 
			
		||||
    "ramda": {
 | 
			
		||||
      "version": "0.24.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.24.1.tgz",
 | 
			
		||||
      "integrity": "sha1-w7d1UZfzW43DUCIoJixMkd22uFc="
 | 
			
		||||
    },
 | 
			
		||||
    "randomatic": {
 | 
			
		||||
      "version": "1.1.7",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -8369,14 +7845,6 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "request-progress": {
 | 
			
		||||
      "version": "0.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-0.3.1.tgz",
 | 
			
		||||
      "integrity": "sha1-ByHBBdipasayzossia4tXs/Pazo=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "throttleit": "0.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "requestidlecallback": {
 | 
			
		||||
      "version": "0.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/requestidlecallback/-/requestidlecallback-0.3.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -8499,14 +7967,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz",
 | 
			
		||||
      "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI="
 | 
			
		||||
    },
 | 
			
		||||
    "rxjs": {
 | 
			
		||||
      "version": "5.5.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.6.tgz",
 | 
			
		||||
      "integrity": "sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "symbol-observable": "1.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "safe-buffer": {
 | 
			
		||||
      "version": "5.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -9420,11 +8880,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI="
 | 
			
		||||
    },
 | 
			
		||||
    "stream-to-observable": {
 | 
			
		||||
      "version": "0.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/stream-to-observable/-/stream-to-observable-0.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-Rb8dny19wJvtgfHDB8Qw5ouEz/4="
 | 
			
		||||
    },
 | 
			
		||||
    "strict-uri-encode": {
 | 
			
		||||
      "version": "1.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -9611,11 +9066,6 @@
 | 
			
		|||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "symbol-observable": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ="
 | 
			
		||||
    },
 | 
			
		||||
    "table": {
 | 
			
		||||
      "version": "3.8.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -10044,11 +9494,6 @@
 | 
			
		|||
      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
 | 
			
		||||
      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
 | 
			
		||||
    },
 | 
			
		||||
    "throttleit": {
 | 
			
		||||
      "version": "0.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz",
 | 
			
		||||
      "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8="
 | 
			
		||||
    },
 | 
			
		||||
    "through": {
 | 
			
		||||
      "version": "2.3.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -10438,11 +9883,6 @@
 | 
			
		|||
        "imurmurhash": "0.1.4"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "universalify": {
 | 
			
		||||
      "version": "0.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
 | 
			
		||||
      "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc="
 | 
			
		||||
    },
 | 
			
		||||
    "unpipe": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
 | 
			
		||||
| 
						 | 
				
			
			@ -11216,15 +10656,6 @@
 | 
			
		|||
          "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "yauzl": {
 | 
			
		||||
      "version": "2.8.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz",
 | 
			
		||||
      "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "buffer-crc32": "0.2.13",
 | 
			
		||||
        "fd-slicer": "1.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										17
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -13,10 +13,9 @@
 | 
			
		|||
    "build-sass": "node ./bin/build-sass.js",
 | 
			
		||||
    "build-sass-watch": "node ./bin/build-sass.js --watch",
 | 
			
		||||
    "run-mastodon": "node ./bin/run-mastodon",
 | 
			
		||||
    "cy:run": "cypress run",
 | 
			
		||||
    "cy:open": "cypress open",
 | 
			
		||||
    "run-testcafe": "testcafe --hostname localhost --skip-js-errors chrome:headless tests/spec",
 | 
			
		||||
    "test": "run-p --race run-mastodon dev test-mastodon",
 | 
			
		||||
    "test-mastodon": "run-s wait-for-mastodon-to-start cy:run",
 | 
			
		||||
    "test-mastodon": "run-s wait-for-mastodon-to-start run-testcafe",
 | 
			
		||||
    "wait-for-mastodon-to-start": "node bin/wait-for-mastodon-to-start.js",
 | 
			
		||||
    "globalize-css": "node ./bin/globalize-css.js",
 | 
			
		||||
    "deglobalize-css": "node ./bin/globalize-css.js --reverse",
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +30,6 @@
 | 
			
		|||
    "compression": "^1.7.1",
 | 
			
		||||
    "cross-env": "^5.1.3",
 | 
			
		||||
    "css-loader": "^0.28.7",
 | 
			
		||||
    "cypress": "^2.0.2",
 | 
			
		||||
    "express": "^4.16.2",
 | 
			
		||||
    "extract-text-webpack-plugin": "^3.0.2",
 | 
			
		||||
    "fg-loadcss": "^2.0.1",
 | 
			
		||||
| 
						 | 
				
			
			@ -94,15 +92,8 @@
 | 
			
		|||
      "__routes__",
 | 
			
		||||
      "__shell__",
 | 
			
		||||
      "__assets__",
 | 
			
		||||
      "cy",
 | 
			
		||||
      "Cypress",
 | 
			
		||||
      "expect",
 | 
			
		||||
      "before",
 | 
			
		||||
      "beforeEach",
 | 
			
		||||
      "after",
 | 
			
		||||
      "afterEach",
 | 
			
		||||
      "describe",
 | 
			
		||||
      "it"
 | 
			
		||||
      "test",
 | 
			
		||||
      "fixture"
 | 
			
		||||
    ],
 | 
			
		||||
    "ignore": [
 | 
			
		||||
      "dist",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,25 @@
 | 
			
		|||
import { Selector as $ } from 'testcafe'
 | 
			
		||||
import { addInstanceButton, getUrl, instanceInput, login, settingsButton } from '../utils'
 | 
			
		||||
import { foobarRole } from '../roles'
 | 
			
		||||
 | 
			
		||||
fixture `02-login-spec.js`
 | 
			
		||||
  .page `http://localhost:4002`
 | 
			
		||||
 | 
			
		||||
const formError = $('.form-error')
 | 
			
		||||
 | 
			
		||||
function manualLogin(t, username, password) {
 | 
			
		||||
  return t.click($('a').withText('log in to an instance'))
 | 
			
		||||
    .expect(getUrl()).contains('/settings/instances/add')
 | 
			
		||||
    .typeText(instanceInput, 'localhost:3000')
 | 
			
		||||
    .click(addInstanceButton)
 | 
			
		||||
    .expect(getUrl()).eql('http://localhost:3000/auth/sign_in')
 | 
			
		||||
    .typeText($('input#user_email'), username)
 | 
			
		||||
    .typeText($('input#user_password'), password)
 | 
			
		||||
    .click($('button[type=submit]'))
 | 
			
		||||
    .expect(getUrl()).contains('/oauth/authorize')
 | 
			
		||||
    .click($('button[type=submit]:not(.negative)'))
 | 
			
		||||
    .expect(getUrl()).eql('http://localhost:4002/')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test('Cannot log in to a fake instance', async t => {
 | 
			
		||||
  await t.click($('a').withText('log in to an instance'))
 | 
			
		||||
    .expect(getUrl()).contains('/settings/instances/add')
 | 
			
		||||
| 
						 | 
				
			
			@ -22,12 +35,12 @@ test('Cannot log in to a fake instance', async t => {
 | 
			
		|||
})
 | 
			
		||||
 | 
			
		||||
test('Logs in to localhost:3000', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
  await manualLogin(t, 'foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    .expect($('article.status-article').exists).ok()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('Logs out', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
  await manualLogin(t, 'foobar@localhost:3000', 'foobarfoobar')
 | 
			
		||||
    .click(settingsButton)
 | 
			
		||||
    .click($('a').withText('Instances'))
 | 
			
		||||
    .click($('a').withText('localhost:3000'))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										35
									
								
								tests/spec/04-pinned-statuses.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								tests/spec/04-pinned-statuses.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
import { Selector as $ } from 'testcafe'
 | 
			
		||||
import { getUrl, login } from '../utils'
 | 
			
		||||
import { foobarRole } from '../roles'
 | 
			
		||||
 | 
			
		||||
fixture `04-pinned-statuses.js`
 | 
			
		||||
  .page `http://localhost:4002`
 | 
			
		||||
 | 
			
		||||
test("shows a user's pinned statuses", async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .click($('nav a[aria-label=Community]'))
 | 
			
		||||
    .expect(getUrl()).contains('/community')
 | 
			
		||||
    .click($('a').withText(('Pinned')))
 | 
			
		||||
    .expect(getUrl()).contains('/pinned')
 | 
			
		||||
    .expect($('.status-article').getAttribute('aria-posinset')).eql('0')
 | 
			
		||||
    .expect($('.status-article').getAttribute('aria-setsize')).eql('1')
 | 
			
		||||
    .expect($('.status-article .status-content').innerText).contains('this is unlisted')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("shows pinned statuses on a user's account page", async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .navigateTo('/accounts/2')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article').getAttribute('aria-posinset')).eql('0')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article').getAttribute('aria-setsize')).eql('1')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article').innerText).contains('this is unlisted')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("shows pinned statuses on a user's account page 2", async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .navigateTo('/accounts/3')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article').getAttribute('aria-posinset')).eql('0')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article').getAttribute('aria-setsize')).eql('2')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article').innerText).contains('pinned toot 1')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article[aria-posinset="1"]').getAttribute('aria-setsize')).eql('2')
 | 
			
		||||
    .expect($('.pinned-statuses .status-article[aria-posinset="1"]').innerText).contains('pinned toot 2')
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										44
									
								
								tests/spec/05-status-types.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								tests/spec/05-status-types.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,44 @@
 | 
			
		|||
import { getNthVirtualArticle } from '../utils'
 | 
			
		||||
import { foobarRole } from '../roles'
 | 
			
		||||
 | 
			
		||||
fixture `05-status-types.js`
 | 
			
		||||
  .page `http://localhost:4002`
 | 
			
		||||
 | 
			
		||||
test('shows direct vs followers-only vs regular', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .expect(getNthVirtualArticle(1).getAttribute('aria-label')).eql('Status by admin')
 | 
			
		||||
    .expect(getNthVirtualArticle(1).find('.status-content').innerText).contains('notification of unlisted message')
 | 
			
		||||
    .expect(getNthVirtualArticle(1).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
 | 
			
		||||
      .eql('Boost')
 | 
			
		||||
    .expect(getNthVirtualArticle(1).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).notOk()
 | 
			
		||||
    .expect(getNthVirtualArticle(2).getAttribute('aria-label')).eql('Status by admin')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).find('.status-content').innerText).contains('notification of followers-only message')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
 | 
			
		||||
      .eql('Cannot be boosted because this is followers-only')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
 | 
			
		||||
    .expect(getNthVirtualArticle(3).getAttribute('aria-label')).eql('Direct message by admin')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).find('.status-content').innerText).contains('notification of direct message')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
 | 
			
		||||
      .eql('Cannot be boosted because this is a direct message')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('shows direct vs followers-only vs regular in notifications', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .navigateTo('/notifications')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).getAttribute('aria-label')).eql('Status by admin')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).find('.status-content').innerText).contains('notification of unlisted message')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
 | 
			
		||||
    .eql('Boost')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).notOk()
 | 
			
		||||
    .expect(getNthVirtualArticle(3).getAttribute('aria-label')).eql('Status by admin')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).find('.status-content').innerText).contains('notification of followers-only message')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
 | 
			
		||||
    .eql('Cannot be boosted because this is followers-only')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
 | 
			
		||||
    .expect(getNthVirtualArticle(4).getAttribute('aria-label')).eql('Direct message by admin')
 | 
			
		||||
    .expect(getNthVirtualArticle(4).find('.status-content').innerText).contains('notification of direct message')
 | 
			
		||||
    .expect(getNthVirtualArticle(4).find('.status-toolbar button:nth-child(2)').getAttribute('aria-label'))
 | 
			
		||||
    .eql('Cannot be boosted because this is a direct message')
 | 
			
		||||
    .expect(getNthVirtualArticle(4).find('.status-toolbar button:nth-child(2)').hasAttribute('disabled')).ok()
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										39
									
								
								tests/spec/06-tabindex.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tests/spec/06-tabindex.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
import { Selector as $ } from 'testcafe'
 | 
			
		||||
import { getNthVirtualArticle } from '../utils'
 | 
			
		||||
import { foobarRole } from '../roles'
 | 
			
		||||
 | 
			
		||||
fixture `06-tabindex.js`
 | 
			
		||||
  .page `http://localhost:4002`
 | 
			
		||||
 | 
			
		||||
test('shows correct tabindex in home timeline', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .expect(getNthVirtualArticle(0).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(1).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(3).getAttribute('tabindex')).eql('0')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('shows correct tabindex in notifications', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .navigateTo('/notifications')
 | 
			
		||||
    .expect(getNthVirtualArticle(0).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(1).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(2).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .hover(getNthVirtualArticle(2))
 | 
			
		||||
    .expect(getNthVirtualArticle(3).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(4).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .hover(getNthVirtualArticle(4))
 | 
			
		||||
    .expect(getNthVirtualArticle(5).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(6).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .hover(getNthVirtualArticle(6))
 | 
			
		||||
    .expect(getNthVirtualArticle(7).getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect(getNthVirtualArticle(7).getAttribute('aria-setsize')).eql('8')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('shows correct tabindex in pinned statuses', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .navigateTo('/pinned')
 | 
			
		||||
    .expect($('.status-article').getAttribute('tabindex')).eql('0')
 | 
			
		||||
    .expect($('.status-article').getAttribute('aria-posinset')).eql('0')
 | 
			
		||||
    .expect($('.status-article').getAttribute('aria-setsize')).eql('1')
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										39
									
								
								tests/spec/07-account-profile.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tests/spec/07-account-profile.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
import { Selector as $ } from 'testcafe'
 | 
			
		||||
import { getUrl } from '../utils'
 | 
			
		||||
import { foobarRole } from '../roles'
 | 
			
		||||
 | 
			
		||||
fixture `07-account-profile.js`
 | 
			
		||||
  .page `http://localhost:4002`
 | 
			
		||||
 | 
			
		||||
test('shows account profile', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .click($('.status-author-name').withText(('quux')))
 | 
			
		||||
    .expect(getUrl()).contains('/accounts/3')
 | 
			
		||||
    .expect($('.account-profile .account-profile-name').innerText).contains('quux')
 | 
			
		||||
    .expect($('.account-profile .account-profile-username').innerText).contains('@quux')
 | 
			
		||||
    .expect($('.account-profile .account-profile-followed-by').innerText).match(/follows you/i)
 | 
			
		||||
    .expect($('.account-profile .account-profile-follow button').getAttribute('aria-label')).eql('Follow')
 | 
			
		||||
    .expect($('.account-profile .account-profile-follow button').getAttribute('aria-pressed')).eql('false')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('shows account profile 2', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .click($('.status-author-name').withText(('admin')))
 | 
			
		||||
    .expect(getUrl()).contains('/accounts/1')
 | 
			
		||||
    .expect($('.account-profile .account-profile-name').innerText).contains('admin')
 | 
			
		||||
    .expect($('.account-profile .account-profile-username').innerText).contains('@admin')
 | 
			
		||||
    .expect($('.account-profile .account-profile-followed-by').innerText).match(/follows you/i)
 | 
			
		||||
    .expect($('.account-profile .account-profile-follow button').getAttribute('aria-label')).eql('Unfollow')
 | 
			
		||||
    .expect($('.account-profile .account-profile-follow button').getAttribute('aria-pressed')).eql('true')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test('shows account profile 3', async t => {
 | 
			
		||||
  await t.useRole(foobarRole)
 | 
			
		||||
    .click($('.mention').withText(('foobar')))
 | 
			
		||||
    .expect(getUrl()).contains('/accounts/2')
 | 
			
		||||
    .expect($('.account-profile .account-profile-name').innerText).contains('foobar')
 | 
			
		||||
    .expect($('.account-profile .account-profile-username').innerText).contains('@foobar')
 | 
			
		||||
    // can't follow or be followed by your own account
 | 
			
		||||
    .expect($('.account-profile .account-profile-followed-by').innerText).eql('')
 | 
			
		||||
    .expect($('.account-profile .account-profile-follow').innerText).eql('')
 | 
			
		||||
})
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue