import { Role } from 'testcafe';
const admin = Role('http://localhost:3000' ,async t => { // port: 5000 when yarn build
await t
.typeText('#login', 'admin')
.typeText('#password', '923878')
.click('#submit-button')
}
, { preserveUrl: true }
);
fixture `Test for profile`;
test('Test for user name', async t => {
await t
.useRole(admin)
.click('#avatar')
.expect('#user-name').eql('admin');
});
If i use 'yarn start', this test:
Open page.
Authorized.
Refresh page.
Walks in steps.
If i use 'yarn build', this test:
Open page.
Authorized.
Refresh page.
The main page is displayed.
The user is not logged in.
Related
I am doing an e2e test that is attempting to login a user and I get the error: Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.6.8), when clicking the login button.
I am very confused as to why this is happening and have tried mocking the data differently, and creating different stubs using cy.intercept(). Not sure what I have to do to get this test to sign up a user at this point.
I would even appreciate an answer to why this is happening in the first place.
Here is Cypress login in test:
describe('visit and interact with home page', () => {
const serverUrl = `${Cypress.env('serverUrl')}`
const ethProvider = `${Cypress.env('ethProvider')}`
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
// note: uncaught errors are shown in Cypress GUI
return false
})
beforeEach(() => {
cy.intercept('GET', `${serverUrl}/api/post?*`, {
body: {
posts: 'string',
},
}).as('getApiContent')
cy.intercept('GET', `${serverUrl}/api/config`, {
body: {
unirepAddress: '0x0165878A594ca255338adfa4d48449f69242Eb8F',
unirepSocialAddress:
'0xa513E6E4b8f2a923D98304ec87F64353C4D5C853',
},
}).as('getApiConfig')
cy.intercept('POST', `${ethProvider}*`, {
fixture: 'ethProvider.json',
}).as('ethProvider')
cy.intercept('POST', `${serverUrl}/api/genInvitationCode/*`, {
fixture: 'genInvitationCode.json',
}).as('genInvitationCode')
})
it('navigate to the login page and login a user', () => {
cy.visit('/')
cy.wait('#getApiConfig').then((res: any) => {
cy.log(JSON.stringify(res.response))
})
// quickly tests if signup page loads
cy.findByText('Sign in').click()
cy.findByRole('textbox').type('test')
cy.get('*[class^="login-page"]').should('be.visible')
cy.get('#close-icon').click()
cy.findByText('Sign in').click()
cy.findByRole('textbox').type('testprivatekey')
cy.get('*[class^="loading-btn"]').click()
// (uncaught exception)Error: could not detect network (event="noNetwork", code=NETWORK_ERROR, version=providers/5.6.8)
})
})
The test throws the uncaught exception at the very end when I click the sign in button.
I have a React-native app, from which I want share my website's URL in a Facebook post.
My current code is :
import Share from "react-native-share";
const shareToFacebook = async () => {
const shareOptions = {
social: Share.Social.FACEBOOK,
message: "Test message",
url: "https://example.com/",
};
try {
const ShareResponse = await Share.shareSingle(shareOptions);
console.log(ShareResponse);
} catch (error) {
console.log("Error =>", error);
}
};
but this solution ,opens Facebook in the browser. Is there any way to open the actual Facebook app ?
Facebook offers an SDK for sharing posts, you can use that SDK with react-native-fbsdk-next library. It shows an in-app modal. I think showing an in-app modal is better than the open the Facebook app or open a browser because some people do not have Facebook on their phones.
You can test the share function before installing the library, follow below steps:
# clone the react-native-fbsdk-next
git clone https://github.com/thebergamo/react-native-fbsdk-next.git
# go to the test project
cd RNFBSDKExample
# install dependencies
npm install
# run the project
npm run android
Example code (from README page):
// ...
import { ShareDialog } from 'react-native-fbsdk-next';
// ...
// Build up a shareable link.
const shareLinkContent = {
contentType: 'link',
contentUrl: "https://facebook.com",
contentDescription: 'Wow, check out this great site!',
};
// ...
// Share the link using the share dialog.
shareLinkWithShareDialog() {
var tmp = this;
ShareDialog.canShow(this.state.shareLinkContent).then(
function(canShow) {
if (canShow) {
return ShareDialog.show(tmp.state.shareLinkContent);
}
}
).then(
function(result) {
if (result.isCancelled) {
console.log('Share cancelled');
} else {
console.log('Share success with postId: '
+ result.postId);
}
},
function(error) {
console.log('Share fail with error: ' + error);
}
);
}
Read more about Facebook Sharing Feature.
I run detox in version 17.13.2 with jest-circus as the test runner. My main problem is the app is not reset either after or before I run the tests which leads to an inconsistent state of the app.
My test file:
import { by, device, element, expect, waitFor } from "detox"
describe("Login", () => {
beforeEach(async () => {
await device.reloadReactNative()
})
it("should login with correct data", async () => {
await element(by.id("login_email_input")).typeText("ch.tietz#gmail.com")
await element(by.id("login_password_input")).typeText("12345678")
await element(by.id("login_submit_button")).tap()
await waitFor(element(by.id("workout_screen"))).toBeVisible()
// additional test steps
})
})
Now if the login actually works but the test fails at one of the subsequent steps, the state of the app user will still be "logged in".
From what I understand, it's not possible to actually alter the app state, e.g. by clearing the AsyncStorage or interacting directly with the state mgmt tool. Instead, it's recommended to just reinstall the app - but this is exactly where I am struggling.
I have tried numerous approaches and none of them worked. What makes it really hard to understand configuration is that detox completely changed how the configuration works and switched to jest-circus as the main test runner.
My setup is basically the one created by jest init -r jest. From what I understand, this already includes some defaults for detox.init() and detox.cleanup():
{
"detox": {
"behavior": {
"init": {
"reinstallApp": true,
"launchApp": true,
"exposeGlobals": true
},
"cleanup": {
"shutdownDevice": false
}
}
}
}
However, this does not seem to be sufficient to actually wipe the app state after running the tests.
I tried working with an init script as setupFilesAfterEnv, which would call cleanup() after the test suite is run. Actually that works in an older project which still uses jasmine 2 as test runner.
import { cleanup, init } from 'detox';
const adapter = require('detox/runners/jest/adapter');
const specReporter = require('detox/runners/jest/specReporter');
const config = require('../package.json').detox;
// Set the default timeout
jest.setTimeout(120000);
jasmine.getEnv().addReporter(adapter);
// This takes care of generating status logs on a per-spec basis. By default, jest only reports at file-level.
// This is strictly optional.
jasmine.getEnv().addReporter(specReporter);
beforeAll(async () => {
await init(config, { launchApp: false });
}, 300000);
beforeEach(async () => {
await adapter.beforeEach();
});
afterAll(async () => {
await adapter.afterAll();
await cleanup();
});
First off, it complains that jasmine is not defined. I guess that's because actually the adapter in this case should be a DetoxAdapterCircus which it is not, even though in my config file I specify:
{
"preset": "react-native",
"testEnvironment": "./environment.ts",
"testRunner": "jest-circus/runner",
"testTimeout": 120000,
"testRegex": "\\.e2e\\.ts$",
"reporters": ["detox/runners/jest/streamlineReporter"],
"verbose": true
}
"testRunner": "jest-circus/runner"
Another idea would be to alter the CustomDetoxEnvironment but I do not understand how I can get access to the detox lifecycle hooks.
const {
DetoxCircusEnvironment,
SpecReporter,
WorkerAssignReporter,
} = require("detox/runners/jest-circus")
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
constructor(config) {
super(config)
// should I access the hooks here now?
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners({
SpecReporter,
WorkerAssignReporter,
})
}
}
module.exports = CustomDetoxEnvironment
Tl;dr: I don't know where to put my reusable lifecycle hooks in the latest version of Detox. Also, I wonder if these custom configurations are even needed to reinstall the app and wipe the app data before each test suite.
You can still use setupFilesAfterEnv, but you're not supposed to call the same hooks/cleanup as before (see https://github.com/wix/Detox/issues/2410#issuecomment-744387707).
here's an example of our init script:
// init.ts
// with "setupFilesAfterEnv": ["./init.ts"] in the conf
beforeAll(async () => {
// to reset the state
await device.clearKeychain();
// we are launching the app manually
await device.launchApp({
permissions: { notifications: 'YES', location: 'inuse' },
});
await device.setURLBlacklist([
// ...
]);
});
Could somebody help with finding the most adequate way to run the same fixture with different preconditions using testcafe (fixture beforeEach)?
Given I have following fixture:
fixture('[Test] My Page')
.meta({ env: 'aat', mobile: 'true', author: 'me' })
.beforeEach(async t => {
await t.navigateTo(myPage.url)
await waitForReact(10000)
})
test('Page should load all data successfully', async t => {
const { Query: queries } = await t.ctx.graphQLTools.mockManagementClient.getCalls()
for (const q of Object.keys(queries)) {
for (const { args, context } of Object.keys(queries[q])) {
await t.expect(queries[q][args]).typeOf('undefined')
await t.expect(queries[q][context]).typeOf('undefined')
}
}
})
In the code example above I need to run this test for several times:
I'm an anonymous user
I'm the admin user
I'm a default user
I've tried the following code, but it looks cumbersome and will create complexity when I have more than 1 test in the fixture that needs to be checked(taken from https://testcafe-discuss.devexpress.com/t/multiple-execution-of-one-test-with-different-data/219):
const a = ['anonymous', 'logged In']
for (const user of a) {
test.meta({ wip: 'true' })(`Page should load all data successfully for ${user} user`, async t => {
if (R.equals('logged In', user)) {
await helpers.setCookie({ key: 'access_token', value: '123123123' })
await helpers.reloadPage()
}
const { Query: queries } = await t.ctx.graphQLTools.mockManagementClient.getCalls()
await t.expect(helpers.isEqlToEmptyQuery(queries.basket)).eql(true)
await t.expect(helpers.isEqlToEmptyQuery(queries.categories)).eql(true)
if (R.equals('logged In', user)) {
await t.expect(helpers.isEqlToEmptyQuery(queries.customer)).eql(true)
}
})
}
Is there a way I can run the whole fixture for 2-3 times with different beforeEach fixture hooks?
One simple solution could be to add three npm scripts in package.json:
"test": "testcafe chrome <all testcafe options>"
"test-anonymous": "npm test -- --user=anonymous"
"test-admin": "npm test -- --user=admin"
"test-default": "npm test -- --user=default"
Then read this custom command-line option in the beforeEach as I explained in Testcafe - Test command line argument outside test case
I'm trying to build a functional testing system to verify our web site is behaving correctly for our users. I have cobbled together a bunch of Node.js modules and helpers in an attempt to get a framework that provides simple, concise tests without a heap of nested function callbacks and I believe promises can provide that, so my package.json file looks like this:
"dependencies": {
"chai-as-promised": "^4.3.0",
"grunt": "^0.4.5",
"grunt-webdriver": "^0.4.8"
}
My Gruntfile.js looks like this:
module.exports = function(grunt) {
grunt.initConfig({
webdriver: { // for use with webdriver.io
options: {
desiredCapabilities: {
browserName: 'phantomjs' // No Xvfb required
}
},
chrome: {
tests: ['chrome/*.js'],
options: {
desiredCapabilities: {
browserName: 'chrome'
}
}
},
},
});
grunt.loadNpmTasks('grunt-webdriver');
grunt.registerTask('default', ['webdriver']);
};
And finally my test case in chrome/login.js looks like this:
'use strict';
var chai = require('chai'),
chaiAsPromised = require('chai-as-promised'),
assert;
chaiAsPromised.transferPromiseness = browser.transferPromiseness;
chai.use(chaiAsPromised);
assert = chai.assert;
describe('login test', function () {
it('verifies user can log in', function(done) {
browser
.url('https://localhost/')
.setValue('#userauth_username','foo')
.setValue('#userauth_password',"password")
.submitForm('#form_users_login')
.then(function(){
browser.getText('#auth-user-id', function(err, value){
console.log(value);
});
assert.becomes(browser.getText('#auth-user-id'), 'foo');
})//.call(done);
});
});
When I run grunt webdriver:chrome on the command line, I see it start up Chrome and log into the website. The 'auth-user-id' span is correctly displaying the user's id after logging in but for some reason browser.getText() is not returning it and the test is therefore failing. I have tried adding a .pause(100) after the .submitForm() to give me time to interact with the page in Chrome so I know it is a problem in the test case.
What am I doing wrong?
This seems to be the best and most succinct way of doing what I want. I'm not sure I need chai-as-promised yet but maybe I'll move the login function to an included file and use chai-as-promised to assert that the promised login has occurred before entering the tests.
'use strict';
var chai = require('chai'),
chaiAsPromised = require('chai-as-promised'),
assert,
expect;
chaiAsPromised.transferPromiseness = browser.transferPromiseness;
chai.use(chaiAsPromised);
assert = chai.assert;
expect = chai.expect;
describe('login test', function () {
it('verifies user can log in', function(done) {
browser
.url('https://localhost/')
.setValue('#userauth_username','foo')
.setValue('#userauth_password',"password")
.submitForm('#form_users_login')
.waitForExist('#auth-user-id')
.getText('#auth-user-id')
.then(function(text){
//console.log('Username: ' + text);
assert.equal(text, 'foo');
})
.saveScreenshot('out.png')
.call(done)
});
it('should not display logincontrols after login', function(done){
browser
.isVisible('#logincontrols')
.then(function(bool){
expect(bool).to.be.false;
})
.call(done)
});
it('should display loggedin section after login', function(done){
browser
.isVisible('#loggedin')
.then(function(bool){
expect(bool).to.be.true;
})
.call(done)
});
});
and for completeness, this is what I see on the output:
# grunt webdriver:chrome
Running "webdriver:chrome" (webdriver) task
login test
✓ verifies user can log in (7691ms)
✓ should not display logincontrols after login (70ms)
✓ should display loggedin section after login (58ms)
3 passing (8s)
Done, without errors.