Shallow jest-enzyme unit test generates coverage for entire application tree - reactjs

I have (for demonstration purposes) an extremely simple React component:
import React, { Component } from 'react';
import { fetchUser, fetchNews } from '../../infrastructure/actions';
class Layout extends Component {
render() {
return (
<div />
);
}
}
export default Layout;
and a simple Jest snapshot test:
import React from 'react';
import { shallow } from 'enzyme';
import Layout from '../Layout';
describe('rendering', () => {
it('should render valid snapshot when loading', () => {
const jsx = (<Layout />);
const element = shallow(jsx);
expect(element).toMatchSnapshot();
});
});
The relevant line here is the
import { fetchUser, fetchNews } from '../../infrastructure/actions';
infrastructure/actions/index.js is a barrel file full of Redux actions, thus:
export { fetchNews, FETCH_NEWS } from './news/fetchNews';
export { fetchUser, FETCH_USER} from './user/fetchUser';
// ...etc
My issue is that even though nothing in the import statement is being used in the shallow-rendered component, Jest's code coverage report is treating EVERY module in the infrastructure/actions/index.js file as having been both imported and executed, leaving me with a useless code coverage report that looks like this.
--------------------------------------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------------------------------------------|----------|----------|----------|----------|-------------------|
All files | 56.08 | 38.46 | 5.17 | 56.08 | |
display/containers | 100 | 100 | 100 | 100 | |
Layout.js | 100 | 100 | 100 | 100 | |
infrastructure/actions | 100 | 100 | 100 | 100 | |
index.js | 100 | 100 | 100 | 100 | |
infrastructure/actions/characters | 50 | 0 | 0 | 50 | |
fetchCharacters.js | 50 | 100 | 0 | 50 | 3 |
fetchedCharactersFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedCharactersSuccess.js | 50 | 100 | 0 | 50 | 3 |
untrackCharacter.js | 50 | 100 | 0 | 50 | 5 |
untrackCharacterFailure.js | 50 | 100 | 0 | 50 | 3 |
untrackCharacterSuccess.js | 50 | 100 | 0 | 50 | 3 |
upsertCharacter.js | 50 | 0 | 0 | 50 | 5 |
upsertCharacterFailure.js | 50 | 100 | 0 | 50 | 3 |
upsertCharacterSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/help | 50 | 100 | 0 | 50 | |
submitContactForm.js | 50 | 100 | 0 | 50 | 5 |
submitContactFormFailure.js | 50 | 100 | 0 | 50 | 3 |
submitContactFormSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/news | 50 | 100 | 0 | 50 | |
fetchNews.js | 50 | 100 | 0 | 50 | 3 |
fetchedNewsSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/public | 50 | 0 | 0 | 50 | |
fetchPublicThreads.js | 50 | 100 | 0 | 50 | 3 |
fetchPublicViews.js | 50 | 100 | 0 | 50 | 3 |
fetchedPublicThreadsFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedPublicThreadsSuccess.js | 50 | 100 | 0 | 50 | 3 |
fetchedPublicViewsFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedPublicViewsSuccess.js | 50 | 100 | 0 | 50 | 3 |
untrackPublicView.js | 50 | 100 | 0 | 50 | 5 |
untrackPublicViewFailure.js | 50 | 100 | 0 | 50 | 3 |
untrackPublicViewSuccess.js | 50 | 100 | 0 | 50 | 3 |
upsertPublicView.js | 50 | 0 | 0 | 50 | 5 |
upsertPublicViewFailure.js | 50 | 100 | 0 | 50 | 3 |
upsertPublicViewSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/tags | 50 | 100 | 0 | 50 | |
fetchTags.js | 50 | 100 | 0 | 50 | 3 |
fetchedTagsSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/threads | 50 | 0 | 0 | 50 | |
bulkUntrackThreads.js | 50 | 100 | 0 | 50 | 5 |
bulkUntrackThreadsFailure.js | 50 | 100 | 0 | 50 | 3 |
bulkUntrackThreadsSuccess.js | 50 | 100 | 0 | 50 | 3 |
bulkUpdateThreads.js | 50 | 100 | 0 | 50 | 5 |
bulkUpdateThreadsFailure.js | 50 | 100 | 0 | 50 | 3 |
bulkUpdateThreadsSuccess.js | 50 | 100 | 0 | 50 | 3 |
exportThreads.js | 50 | 100 | 0 | 50 | 5 |
exportThreadsFailure.js | 50 | 100 | 0 | 50 | 3 |
exportThreadsSuccess.js | 50 | 100 | 0 | 50 | 3 |
fetchActiveThreads.js | 50 | 100 | 0 | 50 | 3 |
fetchActiveThreadsStatus.js | 50 | 100 | 0 | 50 | 3 |
fetchArchivedThreads.js | 50 | 100 | 0 | 50 | 3 |
fetchedActiveThreadsFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedActiveThreadsStatusChunkFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedActiveThreadsStatusChunkSuccess.js | 50 | 100 | 0 | 50 | 3 |
fetchedActiveThreadsStatusFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedActiveThreadsStatusSuccess.js | 50 | 100 | 0 | 50 | 3 |
fetchedActiveThreadsSuccess.js | 50 | 100 | 0 | 50 | 3 |
fetchedArchivedThreadsFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedArchivedThreadsSuccess.js | 50 | 100 | 0 | 50 | 3 |
generateRandomThread.js | 50 | 100 | 0 | 50 | 5 |
generatedRandomThreadSuccess.js | 50 | 100 | 0 | 50 | 3 |
setFilteredTag.js | 50 | 100 | 0 | 50 | 3 |
untrackThread.js | 50 | 100 | 0 | 50 | 5 |
untrackThreadFailure.js | 50 | 100 | 0 | 50 | 3 |
untrackThreadSuccess.js | 50 | 100 | 0 | 50 | 3 |
upsertThread.js | 50 | 0 | 0 | 50 | 5 |
upsertThreadFailure.js | 50 | 100 | 0 | 50 | 3 |
upsertThreadSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/ui | 50 | 0 | 0 | 50 | |
closeBulkUntrackThreadsModal.js | 50 | 100 | 0 | 50 | 3 |
closeUntrackCharacterModal.js | 50 | 100 | 0 | 50 | 3 |
closeUntrackPublicViewModal.js | 50 | 100 | 0 | 50 | 3 |
closeUntrackThreadModal.js | 50 | 100 | 0 | 50 | 3 |
closeUpsertCharacterModal.js | 50 | 100 | 0 | 50 | 3 |
closeUpsertPublicViewModal.js | 50 | 100 | 0 | 50 | 3 |
closeUpsertThreadModal.js | 50 | 100 | 0 | 50 | 3 |
openBulkUntrackThreadsModal.js | 50 | 100 | 0 | 50 | 3 |
openUntrackCharacterModal.js | 50 | 100 | 0 | 50 | 3 |
openUntrackPublicViewModal.js | 50 | 100 | 0 | 50 | 3 |
openUntrackThreadModal.js | 50 | 100 | 0 | 50 | 3 |
openUpsertCharacterModal.js | 50 | 0 | 0 | 50 | 5 |
openUpsertPublicViewModal.js | 50 | 0 | 0 | 50 | 5 |
openUpsertThreadModal.js | 50 | 0 | 0 | 50 | 5 |
setActiveHelpTab.js | 50 | 100 | 0 | 50 | 5 |
setActiveSettingsTab.js | 50 | 100 | 0 | 50 | 5 |
setActiveToolsTab.js | 50 | 100 | 0 | 50 | 5 |
setMaintenanceModeOn.js | 50 | 100 | 0 | 50 | 3 |
toggleHeaderDropdown.js | 50 | 100 | 0 | 50 | 5 |
toggleMobileSidebar.js | 50 | 100 | 0 | 50 | 5 |
toggleNewsAside.js | 50 | 100 | 0 | 50 | 5 |
toggleSidebar.js | 50 | 100 | 0 | 50 | 5 |
infrastructure/actions/user | 50 | 100 | 0 | 50 | |
fetchUser.js | 50 | 100 | 0 | 50 | 3 |
fetchedUserFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedUserSuccess.js | 50 | 100 | 0 | 50 | 3 |
submitUserAccountInfo.js | 50 | 100 | 0 | 50 | 5 |
submitUserChangePassword.js | 50 | 100 | 0 | 50 | 5 |
submitUserForgotPassword.js | 50 | 100 | 0 | 50 | 5 |
submitUserLogin.js | 50 | 100 | 0 | 50 | 5 |
submitUserLogout.js | 50 | 100 | 0 | 50 | 5 |
submitUserRegistration.js | 50 | 100 | 0 | 50 | 5 |
submitUserResetPassword.js | 50 | 100 | 0 | 50 | 5 |
userAccountInfoFailure.js | 50 | 100 | 0 | 50 | 3 |
userAccountInfoSuccess.js | 50 | 100 | 0 | 50 | 3 |
userChangePasswordFailure.js | 50 | 100 | 0 | 50 | 3 |
userChangePasswordSuccess.js | 50 | 100 | 0 | 50 | 3 |
userForgotPasswordFailure.js | 50 | 100 | 0 | 50 | 3 |
userForgotPasswordSuccess.js | 50 | 100 | 0 | 50 | 3 |
userLoginFailure.js | 50 | 100 | 0 | 50 | 3 |
userLoginSuccess.js | 50 | 100 | 0 | 50 | 3 |
userRegistrationFailure.js | 50 | 100 | 0 | 50 | 3 |
userRegistrationSuccess.js | 50 | 100 | 0 | 50 | 3 |
userResetPasswordFailure.js | 50 | 100 | 0 | 50 | 3 |
userResetPasswordSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/actions/userSettings | 50 | 100 | 0 | 50 | |
fetchUserSettings.js | 50 | 100 | 0 | 50 | 3 |
fetchedUserSettingsFailure.js | 50 | 100 | 0 | 50 | 3 |
fetchedUserSettingsSuccess.js | 50 | 100 | 0 | 50 | 3 |
setShowDashboardThreadDistribution.js | 50 | 100 | 0 | 50 | 5 |
updateUserSettings.js | 50 | 100 | 0 | 50 | 5 |
updatedUserSettingsFailure.js | 50 | 100 | 0 | 50 | 3 |
updatedUserSettingsSuccess.js | 50 | 100 | 0 | 50 | 3 |
infrastructure/constants | 100 | 100 | 100 | 100 | |
analytics.js | 100 | 100 | 100 | 100 | |
utility | 62.5 | 100 | 50 | 62.5 | |
testHelpers.js | 62.5 | 100 | 50 | 62.5 | 12,13,16 |
--------------------------------------------------|----------|----------|----------|----------|-------------------|
Needless to say, this negates the purpose of the code coverage report, since none of these files except for two of them are even related to the component under test -- and even for the ones that are, their code shouldn't be executed by this test.
Also of note -- down at the bottom the code coverage report, it references analytics.js which is actually imported by one of the child files of infrastructure/actions/index.js, not by the barrel file itself, meaning that the coverage is somehow traveling even further down the dependency tree.
As soon as I remove the line importing the actions, the coverage file immediately behaves itself again and reflects only the component being tested.
This also happens if I import a component which would (presumably) be used somewhere in the layout; I immediately start seeing coverage indications for that component and its children all the way down, even though I am only doing a shallow rendering in my component under test.
I've tried to use jest.mock() to mock these imports prior to running the shallow() method, but it doesn't seem to make any difference to the coverage output.
All of this leads me to believe I've done something wrong in setting my test environment up; I'd appreciate any guidance on what might cause this effect.

For those curious, I did some more digging and realized that this is actually expected behavior -- an imported file by default executes when it is imported, so while none of the functions inside the imported files were executed, the lines on which they were initialized were still being hit by virtue of their being imported.
The solution for this is to use Jest mocking to mock all the imports used by the system under test as part of your test initialization. I added this line to the bottom of the test file (Jest hoists it to the top of the tests during execution):
jest.mock('../../../infrastructure/actions', () => ({}));
(i.e. when an import calls for actions/index.js, then import a function that returns an empty object instead). And everything went back to normal.

Related

is there any way to make vnode sync faster in TDengine database?

I created a database with two replicas, when I tried to write some data into the database, the vnode status is always syncing, how to make it sync faster?
taos> show vgroups;
vgId | tables | status | onlines | v1_dnode | v1_status | v2_dnode | v2_status | compacting |
=================================================================================================================
2 | 1000 | ready | 2 | 3 | master | 2 | slave | 0 |
3 | 1000 | ready | 2 | 2 | master | 1 | slave | 0 |
4 | 1000 | ready | 2 | 1 | master | 3 | slave | 0 |
5 | 1000 | ready | 2 | 3 | master | 2 | slave | 0 |
6 | 1000 | ready | 2 | 2 | master | 1 | slave | 0 |
7 | 1000 | ready | 2 | 1 | master | 3 | slave | 0 |
8 | 1000 | ready | 2 | 3 | master | 2 | slave | 0 |
9 | 1000 | ready | 2 | 2 | master | 1 | slave | 0 |
10 | 1000 | ready | 2 | 1 | master | 3 | syncing | 0 |
11 | 1000 | ready | 2 | 3 | master | 2 | slave | 0 |
Query OK, 10 row(s) in set (0.004323s)

How do I configure the global threshold to match the "All Files" value using Jest?

When I run my test with the --coverage flag set I get a message that my global coverage threshold isn't met. But when I look at the "All Files" section in the report it seems to match my set thresholds.
At first I thought it was the low coverage I have on the React components, but when I excluded all the components the global percentage only went up with 1 or 2 percent.
So my question is, how do I align the global threshold to the "All Files" results?
This is the report I get when I run my tests
----------------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------------------|----------|----------|----------|----------|-------------------|
All files | 86.39 | 80.53 | 90.12 | 87.16 | |
src | 100 | 100 | 100 | 100 | |
settings.js | 100 | 100 | 100 | 100 | |
src/actions | 100 | 72.22 | 100 | 100 | |
deploysActions.js | 100 | 50 | 100 | 100 | 30 |
environmentsActions.js | 100 | 75 | 100 | 100 | 31 |
errorsActions.js | 100 | 100 | 100 | 100 | |
systemsActions.js | 100 | 50 | 100 | 100 | 24 |
tagsActions.js | 100 | 75 | 100 | 100 | 31 |
testResultsActions.js | 100 | 50 | 100 | 100 | 35 |
timeRangeActions.js | 100 | 100 | 100 | 100 | |
src/constants | 100 | 100 | 100 | 100 | |
actions.js | 100 | 100 | 100 | 100 | |
responseColumns.js | 100 | 100 | 100 | 100 | |
src/middleware | 0 | 0 | 0 | 0 | |
localStorageMiddleware.js | 0 | 0 | 0 | 0 | 4,5,6,7,8,11 |
loggerMiddleware.js | 0 | 100 | 0 | 0 | 1,2,3,4,5,6,7 |
src/reducers | 88.55 | 80.17 | 97.37 | 88.05 | |
authReducer.js | 0 | 0 | 0 | 0 |... 44,49,55,56,60 |
deploysReducer.js | 100 | 86.67 | 100 | 100 | 77 |
environmentsReducer.js | 100 | 100 | 100 | 100 | |
errorsReducer.js | 100 | 100 | 100 | 100 | |
rootReducer.js | 0 | 100 | 100 | 0 | 11 |
systemsReducer.js | 100 | 100 | 100 | 100 | |
tagsReducer.js | 100 | 100 | 100 | 100 | |
testResultsReducer.js | 100 | 97.37 | 100 | 100 | 122 |
timeRangeReducer.js | 100 | 100 | 100 | 100 | |
src/store | 0 | 0 | 0 | 0 | |
configureStore.js | 0 | 0 | 0 | 0 |... 11,13,15,16,18 |
src/utils | 94.55 | 94 | 100 | 94.55 | |
api.js | 100 | 100 | 100 | 100 | |
dateTimeFormatting.js | 100 | 100 | 100 | 100 | |
environments.js | 100 | 100 | 100 | 100 | |
errors.js | 100 | 100 | 100 | 100 | |
localStorage.js | 75 | 25 | 100 | 75 | 18,19,21 |
----------------------------|----------|----------|----------|----------|-------------------|
Jest: "global" coverage threshold for statements (50%) not met: 4%
Jest: "global" coverage threshold for branches (50%) not met: 0%
Jest: "global" coverage threshold for lines (50%) not met: 4.76%
Jest: "global" coverage threshold for functions (40%) not met: 0%
And this is my jest configuration (Note, the components directory is excluded)
"jest": {
"collectCoverageFrom": [
"src/**/*.js",
"!**/node_modules/**",
"!**/coverage/**",
"!src/components/**",
"!src/index.js",
"!src/serviceWorker.js"
],
"coverageReporters": ["html", "cobertura", "json", "lcov", "text", "clover"],
"coverageThreshold": {
"global": {
"branches": 50,
"functions": 40,
"lines": 50,
"statements": 50
}
}
}
I've ran into this same issue and haven't been able to find a solution.
A work around i use is setting up coverage for each folder. Using jest.config.js.
coverageThreshold: {
'./src/actions': {
branches: 80,
functions: 80,
lines: 80,
statements: 80
},
'./src/reducers': {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
}
Let me know if you've found an actual fix to this issue.
Another thing you can do, instead of global is.
coverageThreshold: {
'*/**': {
branches: 80,
functions: 80,
lines: 80,
statements: 80
},
Although this checks every file for 80% coverage. Not the actual average of All files that we are looking for

Multi-dimensional data structure management in R

I have a concern about data organisation and the best approach to simplify some multi-layered data. Simply, I have a 10 replicates of small wood beams (BeamID, ~10) subjected to a 10 different treatment (TreatID, ~10), and each beam is load tested which produces a series data of a Load with consequent Displacement (ranging from 10 to 50 rows per test; I have code that corrects for disparities in row length). Each wood beam is tested multiple times (Rep, ~10).
My plan was to lump all this data into a 5-D array:
Array[Load, Deflection, BeamID, TreatID, Rep]
This way, I should be able to plot the load~deflection curves for a given BeamID, TreatID, for all Reps by using Array[ , ,1,1, ], right? So the hypothetical output for Array[ , ,1,1,1], would be:
+------------+--------+-----+
| Deflection | Load | Rep |
+------------+--------+-----+
| 0 | 0 | 1 |
| 6.35 | 10.5 | 1 |
| 12.7 | 20.8 | 1 |
| 19.05 | 45.3 | 1 |
| 25.4 | 75.2 | 1 |
+------------+--------+-----+
And Array[ , ,1,1,2] would be:
+------------+--------+-----+
| Deflection | Load | Rep |
+------------+--------+-----+
| 0 | 0 | 2 |
| 7.3025 | 12.075 | 2 |
| 14.605 | 23.92 | 2 |
| 21.9075 | 52.095 | 2 |
| 29.21 | 86.48 | 2 |
+------------+--------+-----+
Or I think I could keep it as a simpler, 'melted' dataframe, which would have columns for Load and Deflection, and BeamID, TreatID, and Rep would be repeated for each row of the test output.
+------------+--------+-----+--------+---------+
| Deflection | Load | Rep | BeamID | TreatID |
+------------+--------+-----+--------+---------+
| 0 | 0 | 1 | 1 | 1 |
| 6.35 | 10.5 | 1 | 1 | 1 |
| 12.7 | 20.8 | 1 | 1 | 1 |
| 19.05 | 45.3 | 1 | 1 | 1 |
| 25.4 | 75.2 | 1 | 1 | 1 |
| 0 | 0 | 2 | 1 | 1 |
| 7.3025 | 12.075 | 2 | 1 | 1 |
| 14.605 | 23.92 | 2 | 1 | 1 |
| 21.9075 | 52.095 | 2 | 1 | 1 |
| 29.21 | 86.48 | 2 | 1 | 1 |
+------------+--------+-----+--------+---------+
However, with the latter, I'm not sure how I could easily and discretely pull out all the Rep test values for a specific BeamID and TreatID, especially since I use a linear model to fit a 3rd order polynomial for an specific test to extract the slope of the curves. Having it as a continuous dataframe means I'd have to specify starting and stopping points to start the linear model, correct?
Thoughts, suggestions? Am I headed in the right direction in using a 5-D array? R is a new programming language for me, so please pardon my misunderstandings.

Multiple outcomes/scenarios

I got a problem that I have already created a solution for, but I'm wondering if there's a better way of solving the problem. Basically I have to create a flag for certain scenarios under a partition of ID and date. My solution involved mapping for all the possible scenarios, then creating "case when" statements for all these scenarios with the specific outcome. Basically, I was the one that created the outcomes. I am wondering if there's another way, something around letting SQL create the outcomes instead of myself.
Thanks a lot!
Background:
+----+-----------+--------+-------+------+-----------------+-----------------------------------------------------------------------------------+
| ID | Month | Status | Value | Flag | Scenario Number | Scenario Description |
+----+-----------+--------+-------+------+-----------------+-----------------------------------------------------------------------------------+
| 1 | 1/01/2016 | First | 123 | No | 1 | First, second and blank exists. Do not flag |
| 1 | 1/01/2016 | Second | 456 | No | 1 | First, second and blank exists. Do not flag |
| 1 | 1/01/2016 | | 789 | No | 1 | First, second and blank exists. Do not flag |
| 1 | 1/02/2016 | Second | 123 | Yes | 2 | First does not exist, two second but have different values. Flag these as Yes |
| 1 | 1/02/2016 | Second | 456 | Yes | 2 | First does not exist, two second but have different values. Flag these as Yes |
| 1 | 1/02/2016 | Second | 123 | No | 3 | First does not exist, two second have same values. Do not flag |
| 1 | 1/02/2016 | Second | 123 | No | 3 | First does not exist, two second have same values. Do not flag |
| 1 | 1/03/2016 | Second | 123 | No | 4 | Only one entry of Second exist. Do no flag |
| 1 | 1/04/2016 | | 123 | Yes | 5 | Two blanks for the partition. Flag these as Yes |
| 1 | 1/04/2016 | | 123 | Yes | 5 | Two blanks for the partition. Flag these as Yes |
| 1 | 1/05/2016 | | | No | 6 | Only one entry of blank exist. Do not flag these |
| 1 | 1/06/2016 | First | 123 | Yes | 7 | First exist for the partition. Do not flag |
| 1 | 1/06/2016 | | 456 | Yes | 7 | First exist for the partition. Do not flag |
| 1 | 1/07/2016 | Second | 123 | Yes | 8 | First does not exist and second and blank do not have the same value. Flag these. |
| 1 | 1/07/2016 | | 456 | Yes | 8 | First does not exist and second and blank do not have the same value. Flag these. |
| 1 | 1/07/2016 | Second | 123 | Yes | 8 | First does not exist and second and blank have the same value. Flag these. |
| 1 | 1/07/2016 | | 123 | Yes | 8 | First does not exist and second and blank have the same value. Flag these. |
+----+-----------+--------+-------+------+-----------------+-----------------------------------------------------------------------------------+
Data:
+----+-----------+-------+----------+---------------+
| ID | Month | Value | Priority | Expected_Flag |
+----+-----------+-------+----------+---------------+
| 1 | 1/01/2016 | 96.01 | | Yes |
| 1 | 1/01/2016 | 96.01 | | Yes |
| 1 | 1/02/2016 | 65.2 | First | No |
| 1 | 1/02/2016 | 3.47 | Second | No |
| 1 | 1/02/2016 | 45.99 | | No |
| 11 | 1/01/2016 | 25 | | No |
| 11 | 1/02/2016 | 74.25 | Second | No |
| 11 | 1/02/2016 | 74.25 | Second | No |
| 11 | 1/02/2016 | 23.25 | | No |
| 24 | 1/01/2016 | 1.25 | First | No |
| 24 | 1/01/2016 | 1.365 | | No |
| 24 | 1/04/2016 | 1.365 | First | No |
| 24 | 1/04/2016 | 1.365 | | No |
| 24 | 1/05/2016 | 1.365 | First | No |
| 24 | 1/05/2016 | 1.365 | First | No |
| 24 | 1/06/2016 | 1.365 | Second | No |
| 24 | 1/06/2016 | 1.365 | Second | No |
| 24 | 1/07/2016 | 1.365 | Second | Yes |
| 24 | 1/07/2016 | 1.365 | | Yes |
| 24 | 1/08/2016 | 1.365 | First | No |
| 24 | 1/08/2016 | 1.365 | | No |
| 24 | 1/09/2016 | 1.365 | Second | No |
| 24 | 1/09/2016 | 1.365 | | No |
| 27 | 1/01/2016 | 0 | Second | Yes |
| 27 | 1/01/2016 | 0 | Second | Yes |
| 27 | 1/02/2016 | 45.25 | Second | No |
| 3 | 1/01/2016 | 96.01 | First | No |
| 3 | 1/01/2016 | 96.01 | First | No |
| 3 | 1/03/2016 | 96.01 | First | No |
| 3 | 1/03/2016 | 96.01 | First | No |
| 35 | 1/01/2016 | | | Yes |
| 35 | 1/01/2016 | | | Yes |
| 35 | 1/02/2016 | | First | No |
| 35 | 1/02/2016 | | Second | No |
| 35 | 1/02/2016 | | | No |
| 35 | 1/02/2016 | | | No |
| 35 | 1/03/2016 | | Second | Yes |
| 35 | 1/03/2016 | | Second | Yes |
| 35 | 1/04/2016 | | Second | No |
| 35 | 1/04/2016 | | Second | No |
+----+-----------+-------+----------+---------------+

How to make a SQL "IF-THEN-ELSE" statement

I've seen other questions about SQL If-then-else stuff, but I'm not seeing how to relate it to what I'm trying to do. I've been using SQL for about a year now but only basic stuff and never this.
If I have a SQL table that looks like this
| Name | Version | Category | Value | Number |
|:-----:|:-------:|:--------:|:-----:|:------:|
| File1 | 1.0 | Time | 123 | 1 |
| File1 | 1.0 | Size | 456 | 1 |
| File1 | 1.0 | Final | 789 | 1 |
| File2 | 1.0 | Time | 312 | 1 |
| File2 | 1.0 | Size | 645 | 1 |
| File2 | 1.0 | Final | 978 | 1 |
| File3 | 1.0 | Time | 741 | 1 |
| File3 | 1.0 | Size | 852 | 1 |
| File3 | 1.0 | Final | 963 | 1 |
| File1 | 1.1 | Time | 369 | 2 |
| File1 | 1.1 | Size | 258 | 2 |
| File1 | 1.1 | Final | 147 | 2 |
| File2 | 1.1 | Time | 741 | 2 |
| File2 | 1.1 | Size | 734 | 2 |
| File2 | 1.1 | Final | 942 | 2 |
| File3 | 1.1 | Time | 997 | 2 |
| File3 | 1.1 | Size | 997 | 2 |
| File3 | 1.1 | Final | 985 | 2 |
How can I write a SQL IF, ELSE statement that creates a new column called "Replication" that follows this rule:
A = B + 1 when x = 1
else
A = B
where A = the number we will use for the next Number
B = Max(Number)
x = Replication count (this is the number of times that a loop is executed. x=i)
The results table will look like this:
| Name | Version | Category | Value | Number | Replication |
|:-----:|:-------:|:--------:|:-----:|:------:|:-----------:|
| File1 | 1.0 | Time | 123 | 1 | 1 |
| File1 | 1.0 | Size | 456 | 1 | 1 |
| File1 | 1.0 | Final | 789 | 1 | 1 |
| File2 | 1.0 | Time | 312 | 1 | 1 |
| File2 | 1.0 | Size | 645 | 1 | 1 |
| File2 | 1.0 | Final | 978 | 1 | 1 |
| File1 | 1.0 | Time | 369 | 1 | 2 |
| File1 | 1.0 | Size | 258 | 1 | 2 |
| File1 | 1.0 | Final | 147 | 1 | 2 |
| File2 | 1.0 | Time | 741 | 1 | 2 |
| File2 | 1.0 | Size | 734 | 1 | 2 |
| File2 | 1.0 | Final | 942 | 1 | 2 |
| File1 | 1.1 | Time | 997 | 2 | 1 |
| File1 | 1.1 | Size | 997 | 2 | 1 |
| File1 | 1.1 | Final | 985 | 2 | 1 |
| File2 | 1.1 | Time | 438 | 2 | 1 |
| File2 | 1.1 | Size | 735 | 2 | 1 |
| File2 | 1.1 | Final | 768 | 2 | 1 |
| File1 | 1.1 | Time | 786 | 2 | 2 |
| File1 | 1.1 | Size | 486 | 2 | 2 |
| File1 | 1.1 | Final | 135 | 2 | 2 |
| File2 | 1.1 | Time | 379 | 2 | 2 |
| File2 | 1.1 | Size | 943 | 2 | 2 |
| File2 | 1.1 | Final | 735 | 2 | 2 |
EDIT: Based on the answer by Sean Lange, this is my 2nd attempt at a solution:
SELECT COALESCE(MAX)(Number) + CASE WHEN Replication = 1 then 1 else 0, 1) FROM Table
The COALESCE is in there for when there is no value yet in the Number column.
The IF/Else construct is used to control flow of statements in t-sql. You want a case expression, which is used to conditionally return values in a column.
https://msdn.microsoft.com/en-us/library/ms181765.aspx
Yours would be something like:
case when x = 1 then A else B end as A
As SeanLange pointed out in this case it would be better to use an CASE/WHEN but to illustrate how to use If\ELSE the way to do it in sql is like this:
if x = 1
BEGIN
---Do something
END
ELSE
BEGIN
--Do something else
END
I would say the best way to know the difference and when to use which is if you are writing a query and want a different field to appear based on a certain condition, use case/when. If a certain condition will cause a series of steps to happen then use if/else

Resources